diff --git a/src/components/map-tile-provider/MapTileProvider.module.css b/src/components/map-tile-provider/MapTileProvider.module.css index 41b200c..6ad2e36 100644 --- a/src/components/map-tile-provider/MapTileProvider.module.css +++ b/src/components/map-tile-provider/MapTileProvider.module.css @@ -5,22 +5,3 @@ margin-left: calc(100% - 70px) !important; z-index: 1; } - -.title { - background-color: rgba(14, 116, 144, 0.7); - color: white; - clear: both; -} - -.title-text { - float: left; -} - -.close { - float: right; -} - -.body { - padding: 20px; - background-color: rgba(255, 255, 255, 0.7); -} diff --git a/src/components/map-tile-provider/MapTileProvider.tsx b/src/components/map-tile-provider/MapTileProvider.tsx index a2d9bc2..5c4f6f0 100644 --- a/src/components/map-tile-provider/MapTileProvider.tsx +++ b/src/components/map-tile-provider/MapTileProvider.tsx @@ -1,6 +1,6 @@ import OSM from 'ol/source/OSM'; import XYZ from 'ol/source/XYZ'; -import { Component, createSignal, For } from 'solid-js'; +import { Component, createEffect, createSignal, For, Show } from 'solid-js'; import { I18nContext, createI18nContext, @@ -11,14 +11,19 @@ import style from './MapTileProvider.module.css'; import LayersIcon from '@suid/icons-material/Layers'; import CloseIcon from '@suid/icons-material/Close'; import { - Dialog, - DialogTitle, FormControlLabel, IconButton, Radio, RadioGroup, } from '@suid/material'; import { useNavigate, useParams } from '@solidjs/router'; +import Dialog from '../dialog'; +import Tree from '../tree'; +import { createCachedSignal } from '../../workers/cached-signals'; +import dispatch from '../../workers/dispatcher-main'; +import getUri from '../../lib/ids'; + +const id = getUri('overlays', undefined); interface TileProvider { name: string; @@ -93,6 +98,91 @@ export const mapTileProviders: TileProviders = { }, }; +type FeatureSubTypes = Array | '*'; +type FeatureTypes = Record; +type Overlay = { + selected: boolean; + highlighted: FeatureTypes; + hidden: FeatureTypes; +}; +type Overlays = Record; + +const defaultOverlays: Overlays = { + none: { selected: true, highlighted: { none: [] }, hidden: {} }, + hiking: { + selected: false, + highlighted: { + none: [], + }, + hidden: { none: [] }, + }, +}; + +type OverlayDefinition = Record; +type OverlayDefinitions = Record; + +export const overlayDefinitions: OverlayDefinitions = { + none: {}, + hiking: { + none: {}, + sleeping: { + tourism: '*', + }, + drinking: { + amenity: ['bar', 'cafe', 'pub', 'drinking_water', 'water_point'], + }, + eating: { + amenity: ['fast_food', 'pub', 'restaurant'], + shop: [ + 'bakery', + 'butcher', + 'cheese', + 'chocolate', + 'convenience', + 'dairy', + 'farm', + 'greengrocer', + 'health_food', + 'pastry', + 'seafood', + 'department_store', + 'supermarket', + ], + }, + health: { + amenity: ['doctors', 'hospital', 'pharmacy'], + }, + security: { + amenity: ['police', 'fire_station'], + }, + dayToDay: { + amenity: ['waste_basket', 'waste_disposal'], + shop: ['laundry'], + }, + }, +}; + +const getOverlays = createCachedSignal({ + id, + method: 'getOverlays', + defaultOverlays, +}) as () => Overlays; + +const currentOverlayKey = () => + getOverlays() + ? Object.keys(getOverlays()).filter((key) => getOverlays()[key].selected)[0] + : 'none'; + +const currentOverlay = () => + getOverlays() ? getOverlays()[currentOverlayKey()] : {}; + +const currentOverlayDefinition = () => overlayDefinitions[currentOverlayKey()]; + +const currentOverlayHighlightedKey = () => + currentOverlay() && currentOverlay().highlighted + ? Object.keys(currentOverlay().highlighted)[0] + : 'none'; + const MapTilesProvider: Component<{}> = (props) => { const [open, setOpen] = createSignal(false); @@ -116,6 +206,50 @@ const MapTilesProvider: Component<{}> = (props) => { setOpen(false); }; + createEffect(() => { + console.log({ + caller: 'MapTilesProvider', + overlays: getOverlays(), + currentOverlayKey: currentOverlayKey(), + currentOverlay: currentOverlay(), + currentOverlayDefinition: currentOverlayDefinition(), + currentOverlayHighlightedKey: currentOverlayHighlightedKey(), + }); + }); + + const handleOverlayChange = (ev: any) => { + const value = ev.target.value; + console.log({ + caller: 'MapTilesProvider / handleOverlayChange', + ev, + value, + }); + const newOverlays = getOverlays(); + Object.keys(newOverlays).forEach((key) => { + newOverlays[key].selected = key === value; + }); + dispatch({ + action: 'putOverlays', + params: { id, overlays: newOverlays }, + }); + }; + + const handleOverlayHighlightChange = (ev: any) => { + const value = ev.target.value; + console.log({ + caller: 'MapTilesProvider / handleOverlayHighlightChange', + ev, + value, + }); + const newOverlays = getOverlays(); + newOverlays[currentOverlayKey()].highlighted = {}; + newOverlays[currentOverlayKey()].highlighted[value] = []; + dispatch({ + action: 'putOverlays', + params: { id, overlays: newOverlays }, + }); + }; + return ( <>
@@ -123,28 +257,66 @@ const MapTilesProvider: Component<{}> = (props) => {
- - -
{t('chooseYourMap')}
- - - -
- - - {(p: string) => ( - } - label={mapTileProviders[p].name} - /> - )} - - + + + + + {(p: string) => ( + } label={p} /> + )} + + + 0}> + {' '} +
---
+
Highlight
+ + + {(p: string) => ( + } + label={p} + /> + )} + + +
+ + } + subTree={undefined} + >
+ + + + {(p: string) => ( + } + label={mapTileProviders[p].name} + /> + )} + + + } + subTree={undefined} + >
); diff --git a/src/db/change-handler.ts b/src/db/change-handler.ts index 75018de..af0c834 100644 --- a/src/db/change-handler.ts +++ b/src/db/change-handler.ts @@ -3,6 +3,7 @@ import { getWpt } from '../db/wpt'; import { returnAgain } from '../workers/dispatcher-worker'; import { getAllGpxes, getGpx } from './gpx'; import { put } from './lib'; +import { getOverlays } from './overlays'; import { getRte } from './rte'; import { getTrk } from './trk'; import { getTrkseg } from './trkseg'; @@ -18,6 +19,7 @@ const methods = { getTrkseg, getWpt, getRte, + getOverlays, }; const sendUpdate = async (params: any) => { @@ -79,7 +81,9 @@ const changeHandler = async (change: any) => { } const parentParams = globalThis.watches.get(parentId); - debouncedSendUpdates[parentParams.method](parentParams); + if (parentParams) { + debouncedSendUpdates[parentParams.method](parentParams); + } }; export default changeHandler; diff --git a/src/db/index.ts b/src/db/index.ts index e713ea3..b656d86 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -136,6 +136,16 @@ export const initDb = async (params: any) => { console.log({ caller: 'changes / complete', error }); }); + const localDbChanges = localDb + .changes({ since: 'now', live: true, include_docs: false }) + .on('change', changeHandler) + .on('complete', (info: any) => { + console.log({ caller: 'localDb changes / complete', info }); + }) + .on('error', (error: any) => { + console.log({ caller: 'localDb changes / complete', error }); + }); + // console.log({ caller: 'initDb / back from db.changes', changes }); // changes.cancel(); diff --git a/src/db/overlays.ts b/src/db/overlays.ts new file mode 100644 index 0000000..d6ce104 --- /dev/null +++ b/src/db/overlays.ts @@ -0,0 +1,18 @@ +import { get, put } from './lib'; + +export const getOverlays = async (params: any) => { + const { id, defaultOverlays } = params; + try { + const overlays = await get(id, true); + return overlays.doc; + } catch (error: any) { + console.error({ caller: 'getOverlays', error }); + return defaultOverlays; + } +}; + +export const putOverlays = async (params: any) => { + const { id, overlays } = params; + await put(id, 'overlays', (doc) => overlays, {}, true); + return overlays; +}; diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 7ae5fca..d866bc2 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -2,6 +2,9 @@ const dict = { close: 'close', chooseYourMap: 'Choose your map', + baseLayer: 'Base layer', + overlay: 'Overlay', + hiking: 'Hiking', nearby: 'Nearby', diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts index 7fce833..0a46935 100644 --- a/src/i18n/fr.ts +++ b/src/i18n/fr.ts @@ -4,6 +4,9 @@ const dict = { close: 'quitter', chooseYourMap: 'Choisissez votre carte', + baseLayer: 'Fond de carte', + overlay: 'Sur couche', + hiking: 'Randonnée', nearby: 'À proximité', diff --git a/src/lib/ids.ts b/src/lib/ids.ts index c32ce27..311ef8f 100644 --- a/src/lib/ids.ts +++ b/src/lib/ids.ts @@ -27,6 +27,7 @@ const coding = { const routes = { dbdef: route('dbdef', coding), state: route('state', coding), + overlays: route('overlays', coding), account: route('account/:account', coding), settings: route('settings', coding), gpx: route('gpx/:gpx', coding), diff --git a/src/workers/dispatcher-worker.ts b/src/workers/dispatcher-worker.ts index 2ebc0bf..73b1104 100644 --- a/src/workers/dispatcher-worker.ts +++ b/src/workers/dispatcher-worker.ts @@ -12,6 +12,7 @@ import { getAllGpxes, getAllGpxesWithSummary, } from '../db/gpx'; +import { putOverlays } from '../db/overlays'; import { putRte } from '../db/rte'; import { putRtept } from '../db/rtept'; import { getSettings, putSettings } from '../db/settings'; @@ -59,6 +60,8 @@ onmessage = async function (e) { getState, setState, + putOverlays, + getAndWatch, cancelWatch,