Wpt editor: we can add waypoints (at last !)

This commit is contained in:
Eric van der Vlist 2023-02-02 16:10:20 +01:00
parent 6451b110b9
commit 55830251e0
4 changed files with 125 additions and 21 deletions

View File

@ -12,6 +12,7 @@ import Dialog from '../dialog';
import { getMap, getState } from '../map'; import { getMap, getState } from '../map';
import { Overlay } from 'ol'; import { Overlay } from 'ol';
import { fromLonLat } from 'ol/proj'; import { fromLonLat } from 'ol/proj';
import WptEditDialog from '../wpt/WptEditDialog';
interface Props {} interface Props {}
@ -22,6 +23,7 @@ const Finder: Component<Props> = (props) => {
const navigate = useNavigate(); const navigate = useNavigate();
const [t, { add, locale, dict }] = useI18n(); const [t, { add, locale, dict }] = useI18n();
const [popup, setPopup] = createSignal<Overlay>(); const [popup, setPopup] = createSignal<Overlay>();
const [coordinate, setCoordinate] = createSignal<Coordinate>();
const searchStringChangeHandler = (event: any) => { const searchStringChangeHandler = (event: any) => {
setSearchString(event.target.value); setSearchString(event.target.value);
}; };
@ -33,38 +35,37 @@ const Finder: Component<Props> = (props) => {
let popupElement: HTMLElement; let popupElement: HTMLElement;
const submitHandler = () => { const submitHandler = () => {
let coordinates: Coordinate | undefined = undefined;
const latLonRegExp = /(-?[0-9]+.[0-9]+)\s*,\s*(-?[0-9]+.[0-9]+)/; const latLonRegExp = /(-?[0-9]+.[0-9]+)\s*,\s*(-?[0-9]+.[0-9]+)/;
const latLonMatch = searchString().match(latLonRegExp); const latLonMatch = searchString().match(latLonRegExp);
if (!!latLonMatch) { if (!!latLonMatch) {
coordinates = [+latLonMatch[2], +latLonMatch[1]]; setCoordinate([+latLonMatch[2], +latLonMatch[1]]);
setPopupContent(<>{latLonMatch[0]}</>); setPopupContent(<>{latLonMatch[0]}</>);
console.log({ console.log({
caller: 'Finder / submitHandler', caller: 'Finder / submitHandler',
searchString: searchString(), searchString: searchString(),
latLonMatch, latLonMatch,
coordinates, coordinate: coordinate(),
}); });
} else { } else {
const utmRegExp = /([0-6]?[0-9])\s*([C-X])\s*([0-9]+)\s*([0-9]+)/; const utmRegExp = /([0-6]?[0-9])\s*([C-X])\s*([0-9]+)\s*([0-9]+)/;
const utmMatch = searchString().match(utmRegExp); const utmMatch = searchString().match(utmRegExp);
if (!!utmMatch) { if (!!utmMatch) {
const utm = `+proj=utm +zone=${utmMatch[1]}`; const utm = `+proj=utm +zone=${utmMatch[1]}`;
coordinates = proj4(utm, 'EPSG:4326', [+utmMatch[3], +utmMatch[4]]); setCoordinate(proj4(utm, 'EPSG:4326', [+utmMatch[3], +utmMatch[4]]));
setPopupContent( setPopupContent(
<>{`${coordinates[0]}, ${coordinates[1]} (UTM ${utmMatch[0]})`}</> <>{`${coordinate()[0]}, ${coordinate()[1]} (UTM ${utmMatch[0]})`}</>
); );
} }
console.log({ console.log({
caller: 'Finder / submitHandler', caller: 'Finder / submitHandler',
searchString: searchString(), searchString: searchString(),
utmMatch, utmMatch,
coordinates, coordinate: coordinate(),
}); });
} }
if (!!coordinates) { if (!!coordinate()) {
setOpen(false); setOpen(false);
if (popup() === undefined) { if (popup() === undefined) {
setPopup( setPopup(
@ -77,22 +78,29 @@ const Finder: Component<Props> = (props) => {
console.log({ console.log({
caller: 'Finder / submitHandler / popup', caller: 'Finder / submitHandler / popup',
searchString: searchString(), searchString: searchString(),
coordinates, coordinate: coordinate(),
popup: popup(), popup: popup(),
popupElement, popupElement,
}); });
popup().setMap(getMap()); popup().setMap(getMap());
popup().setPosition(fromLonLat(coordinates)); popup().setPosition(fromLonLat(coordinate()));
getMap()?.addOverlay(popup()); getMap()?.addOverlay(popup());
navigate( navigate(
`/map/${getState().provider}/${coordinates[0]}/${coordinates[1]}/16/${ `/map/${getState().provider}/${coordinate()[0]}/${coordinate()[1]}/16/${
getState().rotation getState().rotation
}` }`
); );
} }
}; };
const [openCreateWptDialog, setOpenCreateWptDialog] = createSignal(false);
const createWptCloseHandler = () => {
setOpenCreateWptDialog(false);
popupCloseHandler();
};
return ( return (
<> <>
<div class={style.control}> <div class={style.control}>
@ -135,8 +143,19 @@ const Finder: Component<Props> = (props) => {
<div> <div>
<div>{popupContent()}</div> <div>{popupContent()}</div>
<div> <div>
<Button>New waypoint</Button> <Button
onClick={() => {
setOpenCreateWptDialog(true);
}}
>
New waypoint
</Button>
</div> </div>
<WptEditDialog
open={openCreateWptDialog}
closeHandler={createWptCloseHandler}
coordinate={coordinate}
/>
</div> </div>
</div> </div>
</> </>

View File

@ -1,31 +1,65 @@
import { Box, Button, Stack, TextField } from '@suid/material'; import { Box, Button, Stack, TextField } from '@suid/material';
import { Component, createEffect, createSignal } from 'solid-js'; import { Component, createEffect, createSignal, Show } from 'solid-js';
import { useI18n } from '@solid-primitives/i18n'; import { useI18n } from '@solid-primitives/i18n';
import Dialog from '../dialog'; import Dialog from '../dialog';
import { peekCachedSignal } from '../../workers/cached-signals'; import {
cachedSignalValue,
peekCachedSignal,
} from '../../workers/cached-signals';
import dispatch from '../../workers/dispatcher-main'; import dispatch from '../../workers/dispatcher-main';
import { emptyWpt } from '../../db/wpt';
import GpxChooser from '../gpx-chooser';
import { currentGpxId } from '../gpx-dialog';
import { emptyGpx } from '../../db/gpx';
import getUri from '../../lib/ids';
import { Coordinate } from 'ol/coordinate';
interface Props { interface Props {
wptId: string; wptId?: string;
coordinate?: () => Coordinate | undefined;
open: () => boolean; open: () => boolean;
closeHandler?: () => vpod; closeHandler?: () => vpod;
} }
const WptEditDialog: Component<Props> = (props) => { const WptEditDialog: Component<Props> = (props) => {
const { wptId, closeHandler, open } = props; const { wptId, closeHandler, open, coordinate } = props;
const [t, { add, locale, dict }] = useI18n(); const [t, { add, locale, dict }] = useI18n();
const wpt = peekCachedSignal({ id: wptId, method: 'getWpt' }); const wpt = !!wptId
? peekCachedSignal({ id: wptId, method: 'getWpt' })
: () => emptyWpt;
const [gpxId, setGpxId] = !wptId
? createSignal<string>(currentGpxId())
: [() => '', () => {}];
createEffect(() => {
setGpxId(currentGpxId());
});
const [editedWpt, setEditedWpt] = createSignal<Wpt>(); const [editedWpt, setEditedWpt] = createSignal<Wpt>();
createEffect(() => { createEffect(() => {
console.log({ console.log({
caller: 'WptEditDialog / createEffect', caller: 'WptEditDialog / createEffect',
wptId, wptId,
gpxId: gpxId(),
wpt: wpt(), wpt: wpt(),
}); });
setEditedWpt(wpt()); const newWpt = editedWpt() || wpt();
if (!!coordinate && !!coordinate()) {
newWpt.$.lon = coordinate()[0];
newWpt.$.lat = coordinate()[1];
}
console.log({
caller: 'WptEditDialog / createEffect',
wptId,
gpxId: gpxId(),
wpt: wpt(),
newWpt,
});
setEditedWpt(newWpt);
}); });
const _closeHandler = () => { const _closeHandler = () => {
@ -34,13 +68,46 @@ const WptEditDialog: Component<Props> = (props) => {
} }
}; };
const saveHandler = () => { const saveHandler = async () => {
console.log({ console.log({
caller: 'WptEditDialog / saveHandler', caller: 'WptEditDialog / saveHandler',
wptId, wptId,
editedWpt: editedWpt(), editedWpt: editedWpt(),
}); });
dispatch({ action: 'putWpt', params: { id: wptId, wpt: editedWpt() } }); let newWptId = wptId;
if (!newWptId) {
if (gpxId() === 'new') {
const id = (await dispatch({
action: 'putGpx',
params: {
id: 'new',
gpx: emptyGpx,
},
})) as string;
setGpxId(id);
}
const gpx = await cachedSignalValue({ method: 'getGpx', id: gpxId() });
const gpxIdObj = getUri('gpx', gpxId());
const lastWptId = gpx.wpt?.at(-1);
const lastWptIdObj = !!lastWptId
? getUri('wpt', lastWptId)
: {
gpx: gpxIdObj.gpx,
wpt: -1,
};
newWptId = getUri('wpt', { ...lastWptIdObj, wpt: lastWptIdObj.wpt + 1 });
}
console.log({
caller: 'WptEditDialog / saveHandler',
wptId,
editedWpt: editedWpt(),
newWptId,
});
dispatch({
action: 'putWpt',
params: { id: newWptId, wpt: editedWpt() },
});
_closeHandler(); _closeHandler();
}; };
@ -57,6 +124,10 @@ const WptEditDialog: Component<Props> = (props) => {
title={getTitle()} title={getTitle()}
closeHandler={_closeHandler} closeHandler={_closeHandler}
> >
<Show when={!wptId}>
<GpxChooser gpxId={gpxId} setGpxId={setGpxId} />
</Show>
<Box <Box
component='form' component='form'
sx={{ sx={{

View File

@ -427,11 +427,12 @@ export const putGpx = async (params: any) => {
let { id, gpx } = params; let { id, gpx } = params;
if (id === 'new') { if (id === 'new') {
const date = !!gpx.metadata.time ? new Date(gpx.metadata.time) : new Date();
id = getUri('gpx', { id = getUri('gpx', {
gpx: intToGpxId(new Date(gpx.metadata.time).valueOf()), gpx: intToGpxId(date.valueOf()),
}); });
} }
console.log({ caller: 'putGpx', params, id, gpx });
const extensions = gpx?.extensions; const extensions = gpx?.extensions;
gpx.extensions = undefined; gpx.extensions = undefined;

View File

@ -49,6 +49,19 @@ export const peekCachedSignal = (params: any) => {
return signal; return signal;
}; };
export const cachedSignalValue = async (params: any) => {
const cachedSignal = cache.get({ cacheId: 'signals', key: params.id });
console.log({ caller: 'cachedSignalValue', params, cachedSignal });
if (cachedSignal !== null) {
const value = cachedSignal();
if (value != undefined) {
return value;
}
}
const value = await dispatch({ action: params.method, params });
return value;
};
export const destroyCachedSignal = (params: any) => { export const destroyCachedSignal = (params: any) => {
dispatch({ dispatch({
action: 'cancelWatch', action: 'cancelWatch',