Adding a basic mechanism to choose overlays (not operational yet)

This commit is contained in:
Eric van der Vlist 2023-01-21 17:13:25 +01:00
parent 82e38308a4
commit 8ddbe1bdee
9 changed files with 240 additions and 45 deletions

View File

@ -5,22 +5,3 @@
margin-left: calc(100% - 70px) !important; margin-left: calc(100% - 70px) !important;
z-index: 1; 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);
}

View File

@ -1,6 +1,6 @@
import OSM from 'ol/source/OSM'; import OSM from 'ol/source/OSM';
import XYZ from 'ol/source/XYZ'; import XYZ from 'ol/source/XYZ';
import { Component, createSignal, For } from 'solid-js'; import { Component, createEffect, createSignal, For, Show } from 'solid-js';
import { import {
I18nContext, I18nContext,
createI18nContext, createI18nContext,
@ -11,14 +11,19 @@ import style from './MapTileProvider.module.css';
import LayersIcon from '@suid/icons-material/Layers'; import LayersIcon from '@suid/icons-material/Layers';
import CloseIcon from '@suid/icons-material/Close'; import CloseIcon from '@suid/icons-material/Close';
import { import {
Dialog,
DialogTitle,
FormControlLabel, FormControlLabel,
IconButton, IconButton,
Radio, Radio,
RadioGroup, RadioGroup,
} from '@suid/material'; } from '@suid/material';
import { useNavigate, useParams } from '@solidjs/router'; 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 { interface TileProvider {
name: string; name: string;
@ -93,6 +98,91 @@ export const mapTileProviders: TileProviders = {
}, },
}; };
type FeatureSubTypes = Array<string> | '*';
type FeatureTypes = Record<string, FeatureSubTypes>;
type Overlay = {
selected: boolean;
highlighted: FeatureTypes;
hidden: FeatureTypes;
};
type Overlays = Record<string, Overlay>;
const defaultOverlays: Overlays = {
none: { selected: true, highlighted: { none: [] }, hidden: {} },
hiking: {
selected: false,
highlighted: {
none: [],
},
hidden: { none: [] },
},
};
type OverlayDefinition = Record<string, FeatureTypes>;
type OverlayDefinitions = Record<string, OverlayDefinition>;
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 MapTilesProvider: Component<{}> = (props) => {
const [open, setOpen] = createSignal(false); const [open, setOpen] = createSignal(false);
@ -116,6 +206,50 @@ const MapTilesProvider: Component<{}> = (props) => {
setOpen(false); 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 ( return (
<> <>
<div class={style.control}> <div class={style.control}>
@ -123,28 +257,66 @@ const MapTilesProvider: Component<{}> = (props) => {
<LayersIcon /> <LayersIcon />
</IconButton> </IconButton>
</div> </div>
<Dialog onClose={handleClose} open={open()} class={style.dialog}> <Dialog
<DialogTitle class={style.title}> closeHandler={handleClose}
<div class={style['title-text']}>{t('chooseYourMap')}</div> open={open()}
<IconButton onClick={handleClose} class={style.close}> title={t('chooseYourMap')}
<CloseIcon /> >
</IconButton> <Tree
</DialogTitle> title={t('overlay')}
<RadioGroup content={
defaultValue={params.provider} <>
class={style.body} <RadioGroup
onChange={handleChange} defaultValue={currentOverlayKey()}
> onChange={handleOverlayChange}
<For each={Object.keys(mapTileProviders)}> >
{(p: string) => ( <For each={Object.keys(overlayDefinitions)}>
<FormControlLabel {(p: string) => (
value={p} <FormControlLabel value={p} control={<Radio />} label={p} />
control={<Radio />} )}
label={mapTileProviders[p].name} </For>
/> </RadioGroup>
)} <Show when={Object.keys(currentOverlayDefinition()).length > 0}>
</For> {' '}
</RadioGroup> <div>---</div>
<div>Highlight</div>
<RadioGroup
defaultValue={currentOverlayHighlightedKey()}
onChange={handleOverlayHighlightChange}
>
<For each={Object.keys(currentOverlayDefinition())}>
{(p: string) => (
<FormControlLabel
value={p}
control={<Radio />}
label={p}
/>
)}
</For>
</RadioGroup>
</Show>
</>
}
subTree={undefined}
></Tree>
<Tree
title={t('baseLayer')}
content={
<RadioGroup defaultValue={params.provider} onChange={handleChange}>
<For each={Object.keys(mapTileProviders)}>
{(p: string) => (
<FormControlLabel
value={p}
control={<Radio />}
label={mapTileProviders[p].name}
/>
)}
</For>
</RadioGroup>
}
subTree={undefined}
></Tree>
</Dialog> </Dialog>
</> </>
); );

View File

@ -3,6 +3,7 @@ import { getWpt } from '../db/wpt';
import { returnAgain } from '../workers/dispatcher-worker'; import { returnAgain } from '../workers/dispatcher-worker';
import { getAllGpxes, getGpx } from './gpx'; import { getAllGpxes, getGpx } from './gpx';
import { put } from './lib'; import { put } from './lib';
import { getOverlays } from './overlays';
import { getRte } from './rte'; import { getRte } from './rte';
import { getTrk } from './trk'; import { getTrk } from './trk';
import { getTrkseg } from './trkseg'; import { getTrkseg } from './trkseg';
@ -18,6 +19,7 @@ const methods = {
getTrkseg, getTrkseg,
getWpt, getWpt,
getRte, getRte,
getOverlays,
}; };
const sendUpdate = async (params: any) => { const sendUpdate = async (params: any) => {
@ -79,7 +81,9 @@ const changeHandler = async (change: any) => {
} }
const parentParams = globalThis.watches.get(parentId); const parentParams = globalThis.watches.get(parentId);
debouncedSendUpdates[parentParams.method](parentParams); if (parentParams) {
debouncedSendUpdates[parentParams.method](parentParams);
}
}; };
export default changeHandler; export default changeHandler;

View File

@ -136,6 +136,16 @@ export const initDb = async (params: any) => {
console.log({ caller: 'changes / complete', error }); 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 }); // console.log({ caller: 'initDb / back from db.changes', changes });
// changes.cancel(); // changes.cancel();

18
src/db/overlays.ts Normal file
View File

@ -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;
};

View File

@ -2,6 +2,9 @@ const dict = {
close: 'close', close: 'close',
chooseYourMap: 'Choose your map', chooseYourMap: 'Choose your map',
baseLayer: 'Base layer',
overlay: 'Overlay',
hiking: 'Hiking',
nearby: 'Nearby', nearby: 'Nearby',

View File

@ -4,6 +4,9 @@ const dict = {
close: 'quitter', close: 'quitter',
chooseYourMap: 'Choisissez votre carte', chooseYourMap: 'Choisissez votre carte',
baseLayer: 'Fond de carte',
overlay: 'Sur couche',
hiking: 'Randonnée',
nearby: 'À proximité', nearby: 'À proximité',

View File

@ -27,6 +27,7 @@ const coding = {
const routes = { const routes = {
dbdef: route('dbdef', coding), dbdef: route('dbdef', coding),
state: route('state', coding), state: route('state', coding),
overlays: route('overlays', coding),
account: route('account/:account', coding), account: route('account/:account', coding),
settings: route('settings', coding), settings: route('settings', coding),
gpx: route('gpx/:gpx', coding), gpx: route('gpx/:gpx', coding),

View File

@ -12,6 +12,7 @@ import {
getAllGpxes, getAllGpxes,
getAllGpxesWithSummary, getAllGpxesWithSummary,
} from '../db/gpx'; } from '../db/gpx';
import { putOverlays } from '../db/overlays';
import { putRte } from '../db/rte'; import { putRte } from '../db/rte';
import { putRtept } from '../db/rtept'; import { putRtept } from '../db/rtept';
import { getSettings, putSettings } from '../db/settings'; import { getSettings, putSettings } from '../db/settings';
@ -59,6 +60,8 @@ onmessage = async function (e) {
getState, getState,
setState, setState,
putOverlays,
getAndWatch, getAndWatch,
cancelWatch, cancelWatch,