2023-01-16 17:25:38 +00:00
|
|
|
import { Button, Grid, IconButton } from '@suid/material';
|
2022-12-29 21:55:48 +00:00
|
|
|
import { Feature } from 'ol';
|
|
|
|
import { Geometry } from 'ol/geom';
|
|
|
|
import { getLength } from 'ol/sphere';
|
|
|
|
import { Component, createSignal, For, Show } from 'solid-js';
|
|
|
|
import { useI18n } from '@solid-primitives/i18n';
|
|
|
|
import EditIcon from '@suid/icons-material/Edit';
|
2023-01-16 15:55:30 +00:00
|
|
|
import TravelExploreIcon from '@suid/icons-material/TravelExplore';
|
2023-01-16 17:25:38 +00:00
|
|
|
import AddLocationAltIcon from '@suid/icons-material/AddLocationAlt';
|
|
|
|
import OpenInNewIcon from '@suid/icons-material/OpenInNew';
|
|
|
|
import CallIcon from '@suid/icons-material/Call';
|
2022-12-29 21:55:48 +00:00
|
|
|
import { Paper, Stack } from '@suid/material';
|
|
|
|
import styled from '@suid/material/styles/styled';
|
|
|
|
import Dialog from '../dialog';
|
2022-12-30 20:03:37 +00:00
|
|
|
import Tree from '../tree';
|
2023-01-02 16:27:55 +00:00
|
|
|
import { GpxViewer } from '../gpx';
|
2023-01-16 16:27:49 +00:00
|
|
|
import { Browser } from '@capacitor/browser';
|
2022-11-29 21:12:50 +00:00
|
|
|
|
|
|
|
const Item = styled(Paper)(({ theme }) => ({
|
|
|
|
...theme.typography.body2,
|
|
|
|
padding: theme.spacing(1),
|
2022-12-29 21:55:48 +00:00
|
|
|
textAlign: 'center',
|
2022-11-29 21:12:50 +00:00
|
|
|
color: theme.palette.text.secondary,
|
|
|
|
}));
|
|
|
|
|
|
|
|
const [open, setOpen] = createSignal(false);
|
|
|
|
|
|
|
|
let selectedFeatures: Feature[] = [];
|
2023-01-16 15:16:22 +00:00
|
|
|
let vectorLayerFeatures: Feature[] = [];
|
2022-12-30 20:03:37 +00:00
|
|
|
let hierarchy: any = {};
|
2022-11-29 21:12:50 +00:00
|
|
|
|
2022-12-29 21:55:48 +00:00
|
|
|
const level2Key = (feature: Feature) =>
|
|
|
|
feature.get('context').wptId ||
|
|
|
|
feature.get('context').rteId ||
|
|
|
|
feature.get('context').trkId;
|
|
|
|
|
2022-11-29 21:12:50 +00:00
|
|
|
export const clickHandler = (event: any) => {
|
2022-12-30 20:12:46 +00:00
|
|
|
hierarchy = {};
|
2022-11-29 21:12:50 +00:00
|
|
|
const pixel = [event.originalEvent.x, event.originalEvent.y];
|
|
|
|
const features = event.map.getFeaturesAtPixel(pixel, { hitTolerance: 30 });
|
2023-01-15 14:42:53 +00:00
|
|
|
console.log({ caller: 'Infos.tsx / clickHandler', features, event });
|
|
|
|
selectedFeatures.map((feature) => {
|
|
|
|
if (feature.set) {
|
|
|
|
feature.set('isSelected', false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
selectedFeatures = features.filter((feature: any) => feature.get('context'));
|
2023-01-16 15:16:22 +00:00
|
|
|
vectorLayerFeatures = features.filter(
|
|
|
|
(feature: any) => !feature.get('context')
|
|
|
|
);
|
|
|
|
|
2022-12-29 21:55:48 +00:00
|
|
|
selectedFeatures.sort((f1: Feature, f2: Feature) => {
|
|
|
|
const ctx1 = f1.get('context');
|
|
|
|
const ctx2 = f2.get('context');
|
|
|
|
if (ctx1.gpxId < ctx2.gpxId) {
|
|
|
|
return 1;
|
|
|
|
} else if (ctx1.gpxId > ctx2.gpxId) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
const level2Key1 = level2Key(f1);
|
|
|
|
const level2Key2 = level2Key(f2);
|
|
|
|
if (level2Key1 < level2Key2) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (level2Key1 > level2Key2) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (ctx1.trksegId < ctx2.trksegId) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (ctx1.trksegId > ctx2.trksegId) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
selectedFeatures.map((feature: Feature<Geometry>) => {
|
|
|
|
const gpxId = feature.get('context').gpxId;
|
|
|
|
if (!hierarchy.hasOwnProperty(gpxId)) {
|
2023-01-03 10:39:17 +00:00
|
|
|
hierarchy[gpxId] = { type: 'gpx' };
|
2022-12-29 21:55:48 +00:00
|
|
|
}
|
|
|
|
const l2key = level2Key(feature);
|
|
|
|
if (!hierarchy[gpxId].hasOwnProperty(l2key)) {
|
2023-01-03 10:39:17 +00:00
|
|
|
hierarchy[gpxId][l2key] = {};
|
2022-12-29 21:55:48 +00:00
|
|
|
if (feature.get('type') === 'trkseg') {
|
|
|
|
hierarchy[gpxId][l2key].type = 'trk';
|
|
|
|
} else {
|
|
|
|
hierarchy[gpxId][l2key].type = feature.get('type');
|
2023-01-03 10:39:17 +00:00
|
|
|
hierarchy[gpxId][l2key].feature = feature;
|
2022-12-29 21:55:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (feature.get('type') === 'trkseg') {
|
|
|
|
const trksegId = feature.get('context').trksegId;
|
|
|
|
if (!hierarchy[gpxId][l2key].hasOwnProperty(trksegId)) {
|
|
|
|
hierarchy[gpxId][l2key][trksegId] = {
|
2022-12-30 20:03:37 +00:00
|
|
|
type: 'trkseg',
|
|
|
|
feature,
|
2022-12-29 21:55:48 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2022-11-29 21:12:50 +00:00
|
|
|
console.log({
|
2022-12-29 21:55:48 +00:00
|
|
|
caller: '<Infos/> / clickHandler',
|
2022-11-29 21:12:50 +00:00
|
|
|
event,
|
|
|
|
features,
|
2022-12-29 21:55:48 +00:00
|
|
|
hierarchy,
|
2023-01-16 15:16:22 +00:00
|
|
|
vectorLayerFeatures,
|
2022-11-29 21:12:50 +00:00
|
|
|
});
|
2023-01-15 14:42:53 +00:00
|
|
|
selectedFeatures.map((feature: Feature<Geometry>) => {
|
2022-12-29 21:55:48 +00:00
|
|
|
const id = feature.get('id');
|
|
|
|
feature.set('isSelected', true);
|
2022-12-21 17:54:56 +00:00
|
|
|
// const geometry = feature.getGeometry();
|
|
|
|
// const length = getLength(geometry, { projection: "EPSG:4326" });
|
2022-11-29 21:12:50 +00:00
|
|
|
console.log({
|
2022-12-29 21:55:48 +00:00
|
|
|
caller: '<Infos/> / clickHandler / feature',
|
2022-11-29 21:12:50 +00:00
|
|
|
event,
|
|
|
|
feature,
|
|
|
|
id,
|
2022-12-21 17:54:56 +00:00
|
|
|
// geometry,
|
|
|
|
// length,
|
2022-11-29 21:12:50 +00:00
|
|
|
});
|
|
|
|
});
|
2023-01-16 15:16:22 +00:00
|
|
|
if (selectedFeatures.length > 0 || vectorLayerFeatures.length > 0) {
|
2022-11-29 21:12:50 +00:00
|
|
|
setOpen(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-12-30 20:03:37 +00:00
|
|
|
const FeaturesTree: Component<{ featuresHierarchy: any }> = ({
|
|
|
|
featuresHierarchy,
|
|
|
|
}) => {
|
|
|
|
return (
|
|
|
|
<Tree
|
2023-01-16 15:16:22 +00:00
|
|
|
title={featuresHierarchy.type || 'voyages'}
|
2022-12-30 20:03:37 +00:00
|
|
|
content={undefined}
|
|
|
|
subTree={Object.keys(featuresHierarchy)
|
|
|
|
.filter((key: string) => key.startsWith('gpx/'))
|
|
|
|
.map((key: string) => (
|
2023-01-03 11:07:23 +00:00
|
|
|
<GpxViewer gpxId={key} restrictToHierarchy={featuresHierarchy[key]} />
|
2022-12-30 20:03:37 +00:00
|
|
|
))}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-11-29 21:12:50 +00:00
|
|
|
const Infos: Component<{}> = (props) => {
|
2022-11-30 12:58:55 +00:00
|
|
|
const [t, { add, locale, dict }] = useI18n();
|
2022-11-30 21:44:02 +00:00
|
|
|
const handleClick = () => {
|
2022-11-29 21:12:50 +00:00
|
|
|
setOpen(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2022-12-29 21:55:48 +00:00
|
|
|
<Dialog closeHandler={handleClick} open={open()} title={t('nearby')}>
|
2022-11-30 21:44:02 +00:00
|
|
|
<Stack
|
|
|
|
spacing={1}
|
2022-12-29 21:55:48 +00:00
|
|
|
direction='column'
|
|
|
|
alignItems='center'
|
|
|
|
sx={{ width: 'calc(100% - 5px)' }}
|
2022-11-30 21:44:02 +00:00
|
|
|
>
|
2023-01-16 15:16:22 +00:00
|
|
|
<Tree
|
|
|
|
title='everything'
|
|
|
|
content={undefined}
|
|
|
|
subTree={
|
|
|
|
<>
|
|
|
|
<Tree
|
|
|
|
title='osm'
|
|
|
|
content={undefined}
|
|
|
|
subTree={
|
|
|
|
<>
|
|
|
|
<For each={vectorLayerFeatures}>
|
|
|
|
{(feature) => (
|
|
|
|
<Tree
|
2023-01-16 15:55:30 +00:00
|
|
|
title={
|
|
|
|
<>
|
|
|
|
<div>
|
|
|
|
{`${feature.get('class')}
|
|
|
|
${feature.get('name') || ''}`}
|
|
|
|
</div>
|
|
|
|
<div>
|
2023-01-16 17:25:38 +00:00
|
|
|
<IconButton>
|
|
|
|
<AddLocationAltIcon />
|
|
|
|
</IconButton>
|
2023-01-16 16:27:49 +00:00
|
|
|
<IconButton
|
|
|
|
onClick={async () => {
|
|
|
|
await Browser.open({
|
2023-01-16 17:25:38 +00:00
|
|
|
url: `https://www.qwant.com/?q=${encodeURIComponent(
|
|
|
|
feature.get('class') +
|
|
|
|
' ' +
|
|
|
|
feature.get('name') || ''
|
|
|
|
)}&t=web`,
|
2023-01-16 16:27:49 +00:00
|
|
|
});
|
|
|
|
}}
|
|
|
|
>
|
2023-01-16 15:55:30 +00:00
|
|
|
<TravelExploreIcon />
|
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
}
|
2023-01-16 15:16:22 +00:00
|
|
|
content={
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
{console.log({
|
|
|
|
caller: 'Infos / vector layer feature',
|
|
|
|
properties: feature.getProperties(),
|
|
|
|
})}
|
|
|
|
</>
|
|
|
|
<For each={Object.keys(feature.getProperties())}>
|
|
|
|
{(key: string) => (
|
2023-01-16 17:25:38 +00:00
|
|
|
<div>
|
|
|
|
<Show
|
|
|
|
when={key === 'website'}
|
|
|
|
fallback={
|
|
|
|
<Show
|
|
|
|
when={key === 'phone'}
|
|
|
|
fallback={`${key}: ${
|
|
|
|
feature.getProperties()[key]
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<Button
|
|
|
|
size='small'
|
|
|
|
startIcon={<CallIcon />}
|
|
|
|
href={
|
|
|
|
'tel:' +
|
|
|
|
feature.getProperties()[key]
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{feature.getProperties()[key]}
|
|
|
|
</Button>
|
|
|
|
</Show>
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<Button
|
|
|
|
size='small'
|
|
|
|
startIcon={<OpenInNewIcon />}
|
|
|
|
onClick={async () => {
|
|
|
|
await Browser.open({
|
|
|
|
url: feature.getProperties()[key],
|
|
|
|
});
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{feature.getProperties()[key]}
|
|
|
|
</Button>
|
|
|
|
</Show>
|
|
|
|
</div>
|
2023-01-16 15:16:22 +00:00
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
subTree={undefined}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<FeaturesTree featuresHierarchy={hierarchy} />
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
/>
|
2022-11-30 21:44:02 +00:00
|
|
|
</Stack>
|
2022-11-29 21:12:50 +00:00
|
|
|
</Dialog>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default Infos;
|