From 55830251e02ef64dcc8bd8d8b738a736fe86644b Mon Sep 17 00:00:00 2001 From: evlist Date: Thu, 2 Feb 2023 16:10:20 +0100 Subject: [PATCH] Wpt editor: we can add waypoints (at last !) --- src/components/finder/Finder.tsx | 41 +++++++++---- src/components/wpt/WptEditDialog.tsx | 87 +++++++++++++++++++++++++--- src/db/gpx.ts | 5 +- src/workers/cached-signals.ts | 13 +++++ 4 files changed, 125 insertions(+), 21 deletions(-) diff --git a/src/components/finder/Finder.tsx b/src/components/finder/Finder.tsx index b858d7c..affe0d5 100644 --- a/src/components/finder/Finder.tsx +++ b/src/components/finder/Finder.tsx @@ -12,6 +12,7 @@ import Dialog from '../dialog'; import { getMap, getState } from '../map'; import { Overlay } from 'ol'; import { fromLonLat } from 'ol/proj'; +import WptEditDialog from '../wpt/WptEditDialog'; interface Props {} @@ -22,6 +23,7 @@ const Finder: Component = (props) => { const navigate = useNavigate(); const [t, { add, locale, dict }] = useI18n(); const [popup, setPopup] = createSignal(); + const [coordinate, setCoordinate] = createSignal(); const searchStringChangeHandler = (event: any) => { setSearchString(event.target.value); }; @@ -33,38 +35,37 @@ const Finder: Component = (props) => { let popupElement: HTMLElement; const submitHandler = () => { - let coordinates: Coordinate | undefined = undefined; const latLonRegExp = /(-?[0-9]+.[0-9]+)\s*,\s*(-?[0-9]+.[0-9]+)/; const latLonMatch = searchString().match(latLonRegExp); if (!!latLonMatch) { - coordinates = [+latLonMatch[2], +latLonMatch[1]]; + setCoordinate([+latLonMatch[2], +latLonMatch[1]]); setPopupContent(<>{latLonMatch[0]}); console.log({ caller: 'Finder / submitHandler', searchString: searchString(), latLonMatch, - coordinates, + coordinate: coordinate(), }); } else { const utmRegExp = /([0-6]?[0-9])\s*([C-X])\s*([0-9]+)\s*([0-9]+)/; const utmMatch = searchString().match(utmRegExp); if (!!utmMatch) { 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( - <>{`${coordinates[0]}, ${coordinates[1]} (UTM ${utmMatch[0]})`} + <>{`${coordinate()[0]}, ${coordinate()[1]} (UTM ${utmMatch[0]})`} ); } console.log({ caller: 'Finder / submitHandler', searchString: searchString(), utmMatch, - coordinates, + coordinate: coordinate(), }); } - if (!!coordinates) { + if (!!coordinate()) { setOpen(false); if (popup() === undefined) { setPopup( @@ -77,22 +78,29 @@ const Finder: Component = (props) => { console.log({ caller: 'Finder / submitHandler / popup', searchString: searchString(), - coordinates, + coordinate: coordinate(), popup: popup(), popupElement, }); popup().setMap(getMap()); - popup().setPosition(fromLonLat(coordinates)); + popup().setPosition(fromLonLat(coordinate())); getMap()?.addOverlay(popup()); navigate( - `/map/${getState().provider}/${coordinates[0]}/${coordinates[1]}/16/${ + `/map/${getState().provider}/${coordinate()[0]}/${coordinate()[1]}/16/${ getState().rotation }` ); } }; + const [openCreateWptDialog, setOpenCreateWptDialog] = createSignal(false); + + const createWptCloseHandler = () => { + setOpenCreateWptDialog(false); + popupCloseHandler(); + }; + return ( <>
@@ -135,8 +143,19 @@ const Finder: Component = (props) => {
{popupContent()}
- +
+
diff --git a/src/components/wpt/WptEditDialog.tsx b/src/components/wpt/WptEditDialog.tsx index 6472781..c3291aa 100644 --- a/src/components/wpt/WptEditDialog.tsx +++ b/src/components/wpt/WptEditDialog.tsx @@ -1,31 +1,65 @@ 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 Dialog from '../dialog'; -import { peekCachedSignal } from '../../workers/cached-signals'; +import { + cachedSignalValue, + peekCachedSignal, +} from '../../workers/cached-signals'; 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 { - wptId: string; + wptId?: string; + coordinate?: () => Coordinate | undefined; open: () => boolean; closeHandler?: () => vpod; } const WptEditDialog: Component = (props) => { - const { wptId, closeHandler, open } = props; + const { wptId, closeHandler, open, coordinate } = props; 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(currentGpxId()) + : [() => '', () => {}]; + + createEffect(() => { + setGpxId(currentGpxId()); + }); + const [editedWpt, setEditedWpt] = createSignal(); createEffect(() => { console.log({ caller: 'WptEditDialog / createEffect', wptId, + gpxId: gpxId(), 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 = () => { @@ -34,13 +68,46 @@ const WptEditDialog: Component = (props) => { } }; - const saveHandler = () => { + const saveHandler = async () => { console.log({ caller: 'WptEditDialog / saveHandler', wptId, 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(); }; @@ -57,6 +124,10 @@ const WptEditDialog: Component = (props) => { title={getTitle()} closeHandler={_closeHandler} > + + + + { let { id, gpx } = params; if (id === 'new') { + const date = !!gpx.metadata.time ? new Date(gpx.metadata.time) : new Date(); 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; gpx.extensions = undefined; diff --git a/src/workers/cached-signals.ts b/src/workers/cached-signals.ts index 636e6e1..bae6f16 100644 --- a/src/workers/cached-signals.ts +++ b/src/workers/cached-signals.ts @@ -49,6 +49,19 @@ export const peekCachedSignal = (params: any) => { 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) => { dispatch({ action: 'cancelWatch',