dyomedea/src/components/wpt/Wpt.tsx

173 lines
4.4 KiB
TypeScript

import { Component, createEffect, createSignal, onCleanup } from 'solid-js';
import dispatch, { cancelDispatch } from '../../workers/dispatcher-main';
import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON';
import { useI18n } from '@solid-primitives/i18n';
import { cloneDeep } from 'lodash';
import Dialog from '../dialog';
import { Box, Button, Stack, TextField } from '@suid/material';
interface Props {
wptId: string;
vectorSource: VectorSource;
}
enum Mode {
CLOSED,
EDIT,
}
export const Wpt: Component<Props> = ({ vectorSource, wptId: wptId }) => {
const [t, { add, locale, dict }] = useI18n();
const [wpt, setWpt] = createSignal<Wpt>();
const [editedWpt, setEditedWpt] = createSignal<Wpt>();
const [dispatchId, setDispatchId] = createSignal<number>(-1);
const getTitle = () => {
if (wpt()?.name) {
return `${wpt()?.name} (${t('wpt')})`;
}
return t('wpt');
};
const wptCallBack = (error: any, result: any, id?: number) => {
if (error) {
console.error({ caller: 'wptCallBack', error });
} else {
console.log({ caller: 'wptCallBack', result });
setWpt(result);
}
if (id) {
setDispatchId(id);
}
};
dispatch(
{
action: 'getAndWatch',
params: {
id: wptId,
method: 'getWpt',
},
},
wptCallBack,
true
);
onCleanup(() => {
dispatch({
action: 'cancelWatch',
params: {
id: wptId,
method: 'getWpt',
},
});
cancelDispatch(dispatchId());
});
const [mode, setMode] = createSignal<Mode>(Mode.CLOSED);
const edit = () => {
setMode(Mode.EDIT);
setEditedWpt(cloneDeep(wpt()));
};
createEffect(() => {
console.log({ caller: 'Wpt', vectorSource, wptId, wpt: cloneDeep(wpt()) });
if (wpt()) {
const existingFeature = vectorSource.getFeatureById(wptId);
if (existingFeature) {
vectorSource.removeFeature(existingFeature);
}
let geo: any = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [wpt()?.$.lon, wpt()?.$.lat],
},
properties: { type: 'wpt', ...wpt(), id: wptId, getTitle, edit },
id: wptId,
},
],
};
const features = new GeoJSON().readFeatures(geo);
console.log({ caller: 'Wpt', features });
const feature = vectorSource.getFeatureById(wptId);
if (feature) {
vectorSource.removeFeature(feature);
}
vectorSource.addFeatures(features);
}
});
const closeHandler = () => {
setMode(Mode.CLOSED);
};
const saveHandler = () => {
console.log({
caller: 'Wpt / saveHandler',
wptId,
editedWpt: editedWpt(),
});
dispatch({ action: 'putWpt', params: { id: wptId, wpt: editedWpt() } });
setMode(Mode.CLOSED);
};
return (
<Dialog
open={mode() === Mode.EDIT}
title={getTitle()}
closeHandler={closeHandler}
>
<Box sx={{ flexGrow: 1, padding: '10px' }}>
<div>
<TextField
required
label={t('name')}
defaultValue={wpt()?.name}
onChange={(event: any, value: string) => {
setEditedWpt({ ...editedWpt(), name: value });
}}
/>
<TextField
label={t('sym')}
defaultValue={wpt()?.sym}
onChange={(event: any, value: string) => {
setEditedWpt({ ...editedWpt(), sym: value });
}}
/>
<TextField
label={t('minZoom')}
defaultValue={wpt()?.extensions?.['dyo:minZoom']?.toString()}
onChange={(event: any, value: string) => {
const extensions = {
...editedWpt()?.extensions,
'dyo:minZoom': parseFloat(value),
};
setEditedWpt({ ...editedWpt(), extensions });
}}
/>
<Stack spacing={2} direction='row' sx={{ marginTop: '20px' }}>
<Button variant='outlined' color='secondary' onClick={closeHandler}>
{t('cancel')}
</Button>
<Button variant='contained' color='success' onClick={saveHandler}>
{t('save')}
</Button>
</Stack>
</div>
</Box>
</Dialog>
);
};
export default Wpt;