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',
|
||||
features: callback(features)
|
||||
}));
|
||||
ajax({ url, type: 'GET' })
|
||||
.then(() => fire(document, 'ds:page:update'))
|
||||
.catch(() => null);
|
||||
ajax({ url, type: 'GET' }).catch(() => null);
|
||||
},
|
||||
[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
|
||||
} from '../controllers/react_controller';
|
||||
import { TurboEventController } from '../controllers/turbo_event_controller';
|
||||
import { GeoAreaController } from '../controllers/geo_area_controller';
|
||||
|
||||
import '../new_design/dropdown';
|
||||
import '../new_design/form-validation';
|
||||
|
@ -95,6 +96,7 @@ Turbo.session.drive = false;
|
|||
const Stimulus = Application.start();
|
||||
Stimulus.register('react', ReactController);
|
||||
Stimulus.register('turbo-event', TurboEventController);
|
||||
Stimulus.register('geo-area', GeoAreaController);
|
||||
|
||||
// Expose globals
|
||||
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
|
||||
= link_to '#', data: { geo_area: geo_area.id } do
|
||||
= link_to '#', data: { action: 'geo-area#onClick' } do
|
||||
= 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
|
||||
= link_to '#', data: { geo_area: geo_area.id } do
|
||||
= link_to '#', data: { action: 'geo-area#onClick' } do
|
||||
= geo_area_label(geo_area)
|
||||
- if geo_area.description.present?
|
||||
%span
|
||||
|
|
Loading…
Reference in a new issue