From baafaa43b14b589a9940d603f663d4da4b565fc1 Mon Sep 17 00:00:00 2001 From: Anton Tranelis Date: Thu, 22 May 2025 12:40:02 +0200 Subject: [PATCH] url layer parameter --- src/Components/Map/Tags.tsx | 31 ------------ src/Components/Map/UtopiaMapInner.tsx | 65 +++++++++++++++++++++++++- src/Components/Map/hooks/useFilter.tsx | 24 +++++++++- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/Components/Map/Tags.tsx b/src/Components/Map/Tags.tsx index fb435f1a..ebaaa6cb 100644 --- a/src/Components/Map/Tags.tsx +++ b/src/Components/Map/Tags.tsx @@ -42,36 +42,5 @@ export function Tags({ data, api }: { data?: Tag[]; api?: ItemsApi }) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, data]) - const location = useLocation() - const addFilterTag = useAddFilterTag() - const resetFilterTags = useResetFilterTags() - const tags = useTags() - const filterTags = useFilterTags() - - useEffect(() => { - const params = new URLSearchParams(location.search) - const urlTags = params.get('tags') - const decodedTags = urlTags ? decodeURIComponent(urlTags) : '' - const decodedTagsArray = decodedTags.split(';') - if ( - decodedTagsArray.some( - (ut) => !filterTags.find((ft) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()), - ) || - filterTags.some( - (ft) => - !decodedTagsArray.find((ut) => ut.toLocaleLowerCase() === ft.name.toLocaleLowerCase()), - ) - ) { - resetFilterTags() - decodedTagsArray.map((urlTag) => { - const tag = tags.find((t) => t.name.toLocaleLowerCase() === urlTag.toLocaleLowerCase()) - tag && addFilterTag(tag) - return null - }) - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [location, tags]) - return <> } diff --git a/src/Components/Map/UtopiaMapInner.tsx b/src/Components/Map/UtopiaMapInner.tsx index ca5056fa..690d2410 100644 --- a/src/Components/Map/UtopiaMapInner.tsx +++ b/src/Components/Map/UtopiaMapInner.tsx @@ -17,7 +17,15 @@ import { useTheme } from '#components/AppShell/hooks/useTheme' import { containsUUID } from '#utils/ContainsUUID' import { useClusterRef, useSetClusterRef } from './hooks/useClusterRef' -import { useAddVisibleLayer } from './hooks/useFilter' +import { + useAddFilterTag, + useAddVisibleLayer, + useFilterTags, + useResetFilterTags, + useResetVisibleLayers, + useToggleVisibleLayer, + useVisibleLayer, +} from './hooks/useFilter' import { useLayers } from './hooks/useLayers' import { useLeafletRefs } from './hooks/useLeafletRefs' import { @@ -25,6 +33,7 @@ import { useSetMapClicked, useSetSelectPosition, } from './hooks/useSelectPosition' +import { useTags } from './hooks/useTags' import AddButton from './Subcomponents/AddButton' import { Control } from './Subcomponents/Controls/Control' import { FilterControl } from './Subcomponents/Controls/FilterControl' @@ -200,6 +209,60 @@ export function UtopiaMapInner({ } } + const addFilterTag = useAddFilterTag() + const resetFilterTags = useResetFilterTags() + const tags = useTags() + const filterTags = useFilterTags() + + useEffect(() => { + const params = new URLSearchParams(location.search) + const urlTags = params.get('tags') + const decodedTags = urlTags ? decodeURIComponent(urlTags) : '' + const decodedTagsArray = decodedTags.split(';').filter(Boolean) + + const urlDiffersFromState = + decodedTagsArray.some( + (ut) => !filterTags.find((ft) => ut.toLowerCase() === ft.name.toLowerCase()), + ) || + filterTags.some( + (ft) => !decodedTagsArray.find((ut) => ut.toLowerCase() === ft.name.toLowerCase()), + ) + + if (urlDiffersFromState) { + resetFilterTags() + decodedTagsArray.forEach((urlTag) => { + const match = tags.find((t) => t.name.toLowerCase() === urlTag.toLowerCase()) + if (match) addFilterTag(match) + }) + } + }, [location, tags, filterTags, addFilterTag, resetFilterTags]) + + const toggleVisibleLayer = useToggleVisibleLayer() + const allLayers = useLayers() + + const initializedRef = useRef(false) + + useEffect(() => { + if (initializedRef.current || allLayers.length === 0) return + + const params = new URLSearchParams(location.search) + const urlLayersParam = params.get('layers') + if (!urlLayersParam) return + + const urlLayerNames = urlLayersParam.split(',').filter(Boolean) + + const layerNamesToHide = allLayers + .map((l) => l.name) + .filter((name) => !urlLayerNames.includes(name)) + + layerNamesToHide.forEach((name) => { + const match = allLayers.find((l) => l.name === name) + if (match) toggleVisibleLayer(match) + }) + + initializedRef.current = true + }, [location, allLayers, toggleVisibleLayer]) + return (
diff --git a/src/Components/Map/hooks/useFilter.tsx b/src/Components/Map/hooks/useFilter.tsx index febc6bfd..d7733f04 100644 --- a/src/Components/Map/hooks/useFilter.tsx +++ b/src/Components/Map/hooks/useFilter.tsx @@ -4,7 +4,7 @@ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable no-case-declarations */ -import { useCallback, useReducer, createContext, useContext, useState } from 'react' +import { useCallback, useReducer, createContext, useContext, useState, useEffect } from 'react' import { useNavigate } from 'react-router-dom' import { useLayers } from './useLayers' @@ -100,6 +100,28 @@ function useFilterManager(initialTags: Tag[]): { } }, initialLayers) + const allLayers = useLayers() + + useEffect(() => { + if (allLayers.length === 0) return + + const visibleNames = visibleLayers.map((l) => l.name) + const allNames = allLayers.map((l) => l.name) + const params = new URLSearchParams(location.search) + + const allVisible = + visibleNames.length === allNames.length && + visibleNames.every((name) => allNames.includes(name)) + + if (allVisible) { + params.delete('layers') + } else { + params.set('layers', visibleNames.join(',')) + } + + navigate(`${location.pathname}?${params.toString()}`, { replace: true }) + }, [visibleLayers, allLayers, navigate]) + const [visibleGroupTypes, dispatchGroupTypes] = useReducer( (state: string[], action: ActionType) => { switch (action.type) {