-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #78 from Vizzuality/SKY30-129-fe-implement-the-too…
…ltip-for [SKY30-129]: tooltips for remaining layers
- Loading branch information
Showing
9 changed files
with
420 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
frontend/src/containers/data-tool/content/map/popup/generic/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; | ||
|
||
import { useMap } from 'react-map-gl'; | ||
|
||
import type { Feature } from 'geojson'; | ||
import { useAtomValue } from 'jotai'; | ||
|
||
import { layersInteractiveIdsAtom, popupAtom } from '@/containers/data-tool/store'; | ||
import { format } from '@/lib/utils/formats'; | ||
import { useGetLayersId } from '@/types/generated/layer'; | ||
import { LayerTyped, InteractionConfig } from '@/types/layers'; | ||
|
||
const TERMS_CLASSES = 'font-mono font-bold uppercase'; | ||
|
||
const GenericPopup = ({ | ||
locationId, | ||
...restConfig | ||
}: InteractionConfig & { locationId: number }) => { | ||
const [rendered, setRendered] = useState(false); | ||
const DATA_REF = useRef<Feature['properties'] | undefined>(); | ||
const { default: map } = useMap(); | ||
const { events } = restConfig; | ||
|
||
const popup = useAtomValue(popupAtom); | ||
const layersInteractiveIds = useAtomValue(layersInteractiveIdsAtom); | ||
|
||
const layerQuery = useGetLayersId( | ||
locationId, | ||
{ | ||
populate: 'metadata', | ||
}, | ||
{ | ||
query: { | ||
select: ({ data }) => ({ | ||
source: (data.attributes as LayerTyped).config?.source, | ||
click: (data.attributes as LayerTyped)?.interaction_config?.events.find( | ||
(ev) => ev.type === 'click' | ||
), | ||
}), | ||
}, | ||
} | ||
); | ||
|
||
const { source } = layerQuery.data; | ||
|
||
const DATA = useMemo(() => { | ||
if (source?.type === 'vector' && rendered && popup && map) { | ||
const point = map.project(popup.lngLat); | ||
|
||
// check if the point is outside the canvas | ||
if ( | ||
point.x < 0 || | ||
point.x > map.getCanvas().width || | ||
point.y < 0 || | ||
point.y > map.getCanvas().height | ||
) { | ||
return DATA_REF.current; | ||
} | ||
|
||
const query = map.queryRenderedFeatures(point, { | ||
layers: layersInteractiveIds, | ||
}); | ||
|
||
const d = query.find((d) => { | ||
return d.source === source.id; | ||
})?.properties; | ||
|
||
DATA_REF.current = d; | ||
|
||
if (d) { | ||
return DATA_REF.current; | ||
} | ||
} | ||
|
||
return DATA_REF.current; | ||
}, [popup, source, layersInteractiveIds, map, rendered]); | ||
|
||
// handle renderer | ||
const handleMapRender = useCallback(() => { | ||
setRendered(map?.loaded() && map?.areTilesLoaded()); | ||
}, [map]); | ||
|
||
useEffect(() => { | ||
map?.on('render', handleMapRender); | ||
|
||
setRendered(map?.loaded() && map?.areTilesLoaded()); | ||
|
||
return () => { | ||
map?.off('render', handleMapRender); | ||
}; | ||
}, [map, handleMapRender]); | ||
|
||
if (!DATA) return null; | ||
|
||
const values = events.find((ev) => ev.type === 'click')?.values; | ||
const name = values?.find((v) => v.label === 'Name'); | ||
const restValues = values?.filter((v) => v.label !== 'Name') ?? []; | ||
|
||
return ( | ||
<> | ||
<div className="space-y-2"> | ||
{name && <h3 className="text-xl font-semibold line-clamp-2">{DATA?.[name.key]}</h3>} | ||
<dl className="space-y-2"> | ||
{restValues.map(({ key, label, format: customFormat }) => ( | ||
<div key={key}> | ||
<dt className={TERMS_CLASSES}>{label}</dt> | ||
<dd className="font-mono first-letter:uppercase"> | ||
{customFormat && format({ value: DATA[key], ...customFormat })} | ||
{!customFormat && DATA[key]} | ||
</dd> | ||
</div> | ||
))} | ||
</dl> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default GenericPopup; |
108 changes: 98 additions & 10 deletions
108
frontend/src/containers/data-tool/content/map/popup/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.