mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-12 23:36:00 +00:00
fix(source): enhancing layer control (#223)
* 3.0.82 * version number * 3.0.84 * 3.0.85 * 3.0.86 * 3.0.87 * 3.0.88 * url layer parameter * layer control customizing * 3.0.89 * 3.0.90 * 3.0.91 * typing * 3.0.92 * fixing bug and imports * 3.0.93 * fixing bug on profile-item-create caused by PR 185
This commit is contained in:
parent
82b1f39141
commit
ed9906ae2f
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "utopia-ui",
|
||||
"version": "3.0.86",
|
||||
"version": "3.0.93",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "utopia-ui",
|
||||
"version": "3.0.86",
|
||||
"version": "3.0.93",
|
||||
"license": "GPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@heroicons/react": "^2.0.17",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "utopia-ui",
|
||||
"version": "3.0.86",
|
||||
"version": "3.0.93",
|
||||
"description": "Reuseable React Components to build mapping apps for real life communities and networks",
|
||||
"repository": "https://github.com/utopia-os/utopia-ui",
|
||||
"homepage": "https://utopia-os.org/",
|
||||
|
||||
@ -5,8 +5,8 @@ import LayerSVG from '#assets/layer.svg'
|
||||
import { useIsLayerVisible, useToggleVisibleLayer } from '#components/Map/hooks/useFilter'
|
||||
import { useLayers } from '#components/Map/hooks/useLayers'
|
||||
|
||||
export function LayerControl() {
|
||||
const [open, setOpen] = useState(false)
|
||||
export function LayerControl({ expandLayerControl = false }: { expandLayerControl: boolean }) {
|
||||
const [open, setOpen] = useState(expandLayerControl)
|
||||
|
||||
const layers = useLayers()
|
||||
|
||||
|
||||
@ -101,9 +101,7 @@ export function ItemFormPopup(props: Props) {
|
||||
setSpinner(false)
|
||||
map.closePopup()
|
||||
} else {
|
||||
const item = items.find(
|
||||
(i) => i.user_created?.id === user?.id && i.layer?.id === popupForm.layer.id,
|
||||
)
|
||||
const item = items.find((i) => i.user_created?.id === user?.id && i.layer === popupForm.layer)
|
||||
|
||||
const uuid = crypto.randomUUID()
|
||||
let success = false
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
import { useAddFilterTag, useFilterTags, useResetFilterTags } from './hooks/useFilter'
|
||||
import { useSetTagData, useSetTagApi, useTags } from './hooks/useTags'
|
||||
import { useSetTagData, useSetTagApi } from './hooks/useTags'
|
||||
|
||||
import type { ItemsApi } from '#types/ItemsApi'
|
||||
import type { Tag } from '#types/Tag'
|
||||
@ -42,36 +40,5 @@ export function Tags({ data, api }: { data?: Tag[]; api?: ItemsApi<Tag> }) {
|
||||
// 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 <></>
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ function UtopiaMap({
|
||||
showThemeControl = false,
|
||||
defaultTheme,
|
||||
donationWidget,
|
||||
expandLayerControl,
|
||||
}: {
|
||||
/** height of the map (default '500px') */
|
||||
height?: string
|
||||
@ -82,6 +83,8 @@ function UtopiaMap({
|
||||
defaultTheme?: string
|
||||
/** ask to donate to the Utopia Project OpenCollective campaign (default false) */
|
||||
donationWidget?: boolean
|
||||
/** open layer control on map initialisation */
|
||||
expandLayerControl?: boolean
|
||||
}) {
|
||||
return (
|
||||
<ContextWrapper>
|
||||
@ -100,6 +103,7 @@ function UtopiaMap({
|
||||
donationWidget={donationWidget}
|
||||
showThemeControl={showThemeControl}
|
||||
defaultTheme={defaultTheme}
|
||||
expandLayerControl={expandLayerControl}
|
||||
>
|
||||
{children}
|
||||
</UtopiaMapInner>
|
||||
|
||||
@ -17,7 +17,13 @@ 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,
|
||||
useToggleVisibleLayer,
|
||||
} from './hooks/useFilter'
|
||||
import { useLayers } from './hooks/useLayers'
|
||||
import { useLeafletRefs } from './hooks/useLeafletRefs'
|
||||
import { usePopupForm } from './hooks/usePopupForm'
|
||||
@ -26,6 +32,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'
|
||||
@ -47,6 +54,7 @@ export function UtopiaMapInner({
|
||||
showThemeControl = false,
|
||||
defaultTheme = '',
|
||||
donationWidget,
|
||||
expandLayerControl,
|
||||
}: {
|
||||
children?: React.ReactNode
|
||||
geo?: GeoJsonObject
|
||||
@ -56,6 +64,7 @@ export function UtopiaMapInner({
|
||||
donationWidget?: boolean
|
||||
showThemeControl?: boolean
|
||||
defaultTheme?: string
|
||||
expandLayerControl?: boolean
|
||||
}) {
|
||||
const selectNewItemPosition = useSelectPosition()
|
||||
const setSelectNewItemPosition = useSetSelectPosition()
|
||||
@ -198,6 +207,63 @@ 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) {
|
||||
initializedRef.current = true
|
||||
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 (
|
||||
<div className={`tw:h-full ${selectNewItemPosition != null ? 'crosshair-cursor-enabled' : ''}`}>
|
||||
<Outlet />
|
||||
@ -207,7 +273,7 @@ export function UtopiaMapInner({
|
||||
</Control>
|
||||
<Control position='bottomLeft' zIndex='999' absolute>
|
||||
{showFilterControl && <FilterControl />}
|
||||
{showLayerControl && <LayerControl />}
|
||||
{showLayerControl && <LayerControl expandLayerControl={expandLayerControl ?? false} />}
|
||||
{showGratitudeControl && <GratitudeControl />}
|
||||
</Control>
|
||||
<TileLayer
|
||||
|
||||
@ -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) {
|
||||
|
||||
1
src/types/UtopiaMapProps.d.ts
vendored
1
src/types/UtopiaMapProps.d.ts
vendored
@ -17,4 +17,5 @@ export interface UtopiaMapProps {
|
||||
infoText?: string
|
||||
donationWidget?: boolean
|
||||
defaultTheme?: string
|
||||
expandLayerControl?: boolean
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user