refactor(js): add geo-area stimulus controller
This commit is contained in:
parent
22aefbaa4a
commit
b585808924
4 changed files with 60 additions and 7 deletions
|
@ -37,9 +37,7 @@ export function useFeatureCollection(
|
||||||
type: 'FeatureCollection',
|
type: 'FeatureCollection',
|
||||||
features: callback(features)
|
features: callback(features)
|
||||||
}));
|
}));
|
||||||
ajax({ url, type: 'GET' })
|
ajax({ url, type: 'GET' }).catch(() => null);
|
||||||
.then(() => fire(document, 'ds:page:update'))
|
|
||||||
.catch(() => null);
|
|
||||||
},
|
},
|
||||||
[url, setFeatureCollection]
|
[url, setFeatureCollection]
|
||||||
);
|
);
|
||||||
|
|
53
app/javascript/controllers/geo_area_controller.tsx
Normal file
53
app/javascript/controllers/geo_area_controller.tsx
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
import { debounce } from '@utils';
|
||||||
|
|
||||||
|
type Detail = Record<string, unknown>;
|
||||||
|
|
||||||
|
export class GeoAreaController extends Controller {
|
||||||
|
static values = {
|
||||||
|
id: String,
|
||||||
|
description: String
|
||||||
|
};
|
||||||
|
static targets = ['description'];
|
||||||
|
|
||||||
|
declare readonly idValue: string;
|
||||||
|
declare readonly descriptionTarget: HTMLInputElement;
|
||||||
|
|
||||||
|
onFocus() {
|
||||||
|
this.globalDispatch('map:feature:focus', { id: this.idValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick(event: MouseEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.globalDispatch('map:feature:focus', { id: this.idValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
onInput() {
|
||||||
|
this.debounce(this.updateDescription, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateDescription(): void {
|
||||||
|
this.globalDispatch('map:feature:update', {
|
||||||
|
id: this.idValue,
|
||||||
|
properties: { description: this.descriptionTarget.value.trim() }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#debounced = new Map<() => void, () => void>();
|
||||||
|
private debounce(fn: () => void, interval: number): void {
|
||||||
|
let debounced = this.#debounced.get(fn);
|
||||||
|
if (!debounced) {
|
||||||
|
debounced = debounce(fn.bind(this), interval);
|
||||||
|
this.#debounced.set(fn, debounced);
|
||||||
|
}
|
||||||
|
debounced();
|
||||||
|
}
|
||||||
|
|
||||||
|
private globalDispatch(type: string, detail: Detail): void {
|
||||||
|
this.dispatch(type, {
|
||||||
|
detail,
|
||||||
|
prefix: '',
|
||||||
|
target: document.documentElement
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import {
|
||||||
registerComponents
|
registerComponents
|
||||||
} from '../controllers/react_controller';
|
} from '../controllers/react_controller';
|
||||||
import { TurboEventController } from '../controllers/turbo_event_controller';
|
import { TurboEventController } from '../controllers/turbo_event_controller';
|
||||||
|
import { GeoAreaController } from '../controllers/geo_area_controller';
|
||||||
|
|
||||||
import '../new_design/dropdown';
|
import '../new_design/dropdown';
|
||||||
import '../new_design/form-validation';
|
import '../new_design/form-validation';
|
||||||
|
@ -95,6 +96,7 @@ Turbo.session.drive = false;
|
||||||
const Stimulus = Application.start();
|
const Stimulus = Application.start();
|
||||||
Stimulus.register('react', ReactController);
|
Stimulus.register('react', ReactController);
|
||||||
Stimulus.register('turbo-event', TurboEventController);
|
Stimulus.register('turbo-event', TurboEventController);
|
||||||
|
Stimulus.register('geo-area', GeoAreaController);
|
||||||
|
|
||||||
// Expose globals
|
// Expose globals
|
||||||
window.DS = window.DS || DS;
|
window.DS = window.DS || DS;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
%li{ class: editing ? 'mb-1' : 'flex column mb-2' }
|
%li{ class: editing ? 'mb-1' : 'flex column mb-2', data: { controller: 'geo-area', geo_area_id_value: geo_area.id } }
|
||||||
- if editing
|
- if editing
|
||||||
= link_to '#', data: { geo_area: geo_area.id } do
|
= link_to '#', data: { action: 'geo-area#onClick' } do
|
||||||
= geo_area_label(geo_area)
|
= geo_area_label(geo_area)
|
||||||
= text_field_tag :description, geo_area.description, data: { geo_area: geo_area.id }, placeholder: 'Description', class: 'no-margin'
|
= text_field_tag :description, geo_area.description, data: { action: 'focus->geo-area#onFocus input->geo-area#onInput', geo_area_target: 'description' }, placeholder: 'Description', class: 'no-margin'
|
||||||
- else
|
- else
|
||||||
= link_to '#', data: { geo_area: geo_area.id } do
|
= link_to '#', data: { action: 'geo-area#onClick' } do
|
||||||
= geo_area_label(geo_area)
|
= geo_area_label(geo_area)
|
||||||
- if geo_area.description.present?
|
- if geo_area.description.present?
|
||||||
%span
|
%span
|
||||||
|
|
Loading…
Reference in a new issue