From 8ebaf9a0fd8a0326504dbd3221565fa3e157ad96 Mon Sep 17 00:00:00 2001 From: Mustafa Saifee Date: Sat, 26 Oct 2024 14:49:42 +0300 Subject: [PATCH] Fix issue with the geohub map --- package-lock.json | 4 +- package.json | 2 +- .../Maps/GeoHubMap/GeoHubMultipleMap.tsx | 151 +++++++++++++++++ .../Graphs/Maps/GeoHubMap/GeoHubSingleMap.tsx | 133 +++++++++++++++ .../Graphs/Maps/GeoHubMap/index.tsx | 156 ++++-------------- 5 files changed, 320 insertions(+), 126 deletions(-) create mode 100644 src/Components/Graphs/Maps/GeoHubMap/GeoHubMultipleMap.tsx create mode 100644 src/Components/Graphs/Maps/GeoHubMap/GeoHubSingleMap.tsx diff --git a/package-lock.json b/package-lock.json index 22fd416..8ed5ec3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@undp-data/undp-visualization-library", - "version": "0.1.23", + "version": "0.1.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@undp-data/undp-visualization-library", - "version": "0.1.23", + "version": "0.1.24", "license": "MIT", "dependencies": { "ajv": "^8.17.1", diff --git a/package.json b/package.json index 0fec837..23a1aa7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@undp-data/undp-visualization-library", - "version": "0.1.23", + "version": "0.1.24", "main": "./dist/index.umd.cjs", "module": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/src/Components/Graphs/Maps/GeoHubMap/GeoHubMultipleMap.tsx b/src/Components/Graphs/Maps/GeoHubMap/GeoHubMultipleMap.tsx new file mode 100644 index 0000000..b57b575 --- /dev/null +++ b/src/Components/Graphs/Maps/GeoHubMap/GeoHubMultipleMap.tsx @@ -0,0 +1,151 @@ +import { useRef, useEffect, useState } from 'react'; +import maplibreGl from 'maplibre-gl'; +import * as pmtiles from 'pmtiles'; +import 'maplibre-gl/dist/maplibre-gl.css'; +import { select } from 'd3-selection'; +import { fetchAndParseJSON } from '../../../../Utils/fetchAndParseData'; +import { filterData } from '../../../../Utils/transformData/filterData'; + +interface Props { + mapStyle: string; + center?: [number, number]; + zoomLevel?: number; + width?: number; + height?: number; + relativeHeight?: number; + minHeight?: number; + includeLayers?: string[]; + excludeLayers?: string[]; +} + +export function GeoHubMultipleMap(props: Props) { + const { + mapStyle, + height, + width, + relativeHeight, + center, + zoomLevel, + minHeight, + includeLayers, + excludeLayers, + } = props; + + const [svgWidth, setSvgWidth] = useState(0); + const [svgHeight, setSvgHeight] = useState(0); + const graphDiv = useRef(null); + const mapContainer = useRef(null); + const mapRef = useRef(null); + useEffect(() => { + const resizeObserver = new ResizeObserver(entries => { + setSvgWidth(width || entries[0].target.clientWidth || 620); + }); + if (graphDiv.current) { + setSvgHeight(graphDiv.current.clientHeight || 480); + setSvgWidth(graphDiv.current.clientWidth || 620); + if (!width) resizeObserver.observe(graphDiv.current); + } + return () => resizeObserver.disconnect(); + }, [graphDiv?.current, width]); + useEffect(() => { + if (mapContainer.current && svgWidth && !mapRef.current) { + fetchAndParseJSON(mapStyle).then(d => { + const mapDiv = select(mapContainer.current); + mapDiv.selectAll('div').remove(); + const protocol = new pmtiles.Protocol(); + maplibreGl.addProtocol('pmtiles', protocol.tile); + const mapObj: any = { + container: mapContainer.current as any, + style: + !includeLayers && !excludeLayers + ? d + : { + ...d, + layers: filterData(d.layers, [ + { + column: 'id', + includeValues: includeLayers, + excludeValues: excludeLayers, + }, + ]), + }, + }; + if (center) { + mapObj.center = center; + } + if (zoomLevel) { + mapObj.zoom = zoomLevel; + } + mapRef.current = new maplibreGl.Map(mapObj); + mapRef.current.addControl( + new maplibreGl.NavigationControl({ + visualizePitch: true, + showZoom: true, + showCompass: true, + }), + 'bottom-right', + ); + mapRef.current.addControl(new maplibreGl.ScaleControl(), 'bottom-left'); + }); + } + }, [ + mapContainer.current, + svgWidth, + center, + zoomLevel, + includeLayers, + excludeLayers, + ]); + useEffect(() => { + if (mapRef.current) { + fetchAndParseJSON(mapStyle).then(d => { + const mapStyleObj: any = { + ...d, + layers: filterData(d.layers, [ + { + column: 'id', + includeValues: includeLayers, + excludeValues: excludeLayers, + }, + ]), + }; + mapRef.current.setStyle(mapStyleObj); + }); + } + }, [mapStyle]); + return ( +
+ {(width || svgWidth) && (height || svgHeight) ? ( +
minHeight + ? (width || svgWidth) * relativeHeight + : minHeight + : (width || svgWidth) * relativeHeight + : svgHeight), + }} + > +
+
+ ) : null} +
+ ); +} diff --git a/src/Components/Graphs/Maps/GeoHubMap/GeoHubSingleMap.tsx b/src/Components/Graphs/Maps/GeoHubMap/GeoHubSingleMap.tsx new file mode 100644 index 0000000..ae988e2 --- /dev/null +++ b/src/Components/Graphs/Maps/GeoHubMap/GeoHubSingleMap.tsx @@ -0,0 +1,133 @@ +import { useRef, useEffect, useState } from 'react'; +import maplibreGl from 'maplibre-gl'; +import * as pmtiles from 'pmtiles'; +import 'maplibre-gl/dist/maplibre-gl.css'; +import { select } from 'd3-selection'; +import { fetchAndParseJSON } from '../../../../Utils/fetchAndParseData'; +import { filterData } from '../../../../Utils/transformData/filterData'; + +interface Props { + mapStyle: string; + center?: [number, number]; + zoomLevel?: number; + width?: number; + height?: number; + relativeHeight?: number; + minHeight?: number; + includeLayers?: string[]; + excludeLayers?: string[]; +} + +export function GeoHubSingleMap(props: Props) { + const { + mapStyle, + height, + width, + relativeHeight, + center, + zoomLevel, + minHeight, + includeLayers, + excludeLayers, + } = props; + const [svgWidth, setSvgWidth] = useState(0); + const [svgHeight, setSvgHeight] = useState(0); + const graphDiv = useRef(null); + const mapContainer = useRef(null); + useEffect(() => { + const resizeObserver = new ResizeObserver(entries => { + setSvgWidth(width || entries[0].target.clientWidth || 620); + }); + if (graphDiv.current) { + setSvgHeight(graphDiv.current.clientHeight || 480); + setSvgWidth(graphDiv.current.clientWidth || 620); + if (!width) resizeObserver.observe(graphDiv.current); + } + return () => resizeObserver.disconnect(); + }, [graphDiv?.current, width]); + useEffect(() => { + if (mapContainer.current && svgWidth) { + fetchAndParseJSON(mapStyle).then(d => { + const mapDiv = select(mapContainer.current); + mapDiv.selectAll('div').remove(); + const protocol = new pmtiles.Protocol(); + maplibreGl.addProtocol('pmtiles', protocol.tile); + const mapObj: any = { + container: mapContainer.current as any, + style: + !includeLayers && !excludeLayers + ? d + : { + ...d, + layers: filterData(d.layers, [ + { + column: 'id', + includeValues: includeLayers, + excludeValues: excludeLayers, + }, + ]), + }, + }; + if (center) { + mapObj.center = center; + } + if (zoomLevel) { + mapObj.zoom = zoomLevel; + } + const map = new maplibreGl.Map(mapObj); + map.addControl( + new maplibreGl.NavigationControl({ + visualizePitch: true, + showZoom: true, + showCompass: true, + }), + 'bottom-right', + ); + map.addControl(new maplibreGl.ScaleControl(), 'bottom-left'); + }); + } + }, [ + mapContainer.current, + svgWidth, + mapStyle, + center, + zoomLevel, + includeLayers, + excludeLayers, + ]); + return ( +
+ {(width || svgWidth) && (height || svgHeight) ? ( +
minHeight + ? (width || svgWidth) * relativeHeight + : minHeight + : (width || svgWidth) * relativeHeight + : svgHeight), + }} + > +
+
+ ) : null} +
+ ); +} diff --git a/src/Components/Graphs/Maps/GeoHubMap/index.tsx b/src/Components/Graphs/Maps/GeoHubMap/index.tsx index 6dee515..0a9710f 100644 --- a/src/Components/Graphs/Maps/GeoHubMap/index.tsx +++ b/src/Components/Graphs/Maps/GeoHubMap/index.tsx @@ -1,14 +1,10 @@ -import { useRef, useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import Select, { createFilter } from 'react-select'; -import maplibreGl from 'maplibre-gl'; -import * as pmtiles from 'pmtiles'; -import 'maplibre-gl/dist/maplibre-gl.css'; -import { select } from 'd3-selection'; import { GraphHeader } from '../../../Elements/GraphHeader'; import { GraphFooter } from '../../../Elements/GraphFooter'; import { UNDPColorModule } from '../../../ColorPalette'; -import { fetchAndParseJSON } from '../../../../Utils/fetchAndParseData'; -import { filterData } from '../../../../Utils/transformData/filterData'; +import { GeoHubMultipleMap } from './GeoHubMultipleMap'; +import { GeoHubSingleMap } from './GeoHubSingleMap'; interface Props { mapStyle: string | { style: string; name: string }[]; @@ -57,98 +53,20 @@ export function GeoHubMap(props: Props) { excludeLayers, } = props; - const [svgWidth, setSvgWidth] = useState(0); const [selectedMapStyle, setSelectedMapStyle] = useState( typeof mapStyle === 'string' ? mapStyle : mapStyle[0].style, ); - const [svgHeight, setSvgHeight] = useState(0); - const graphDiv = useRef(null); - const mapContainer = useRef(null); - const mapRef = useRef(null); + useEffect(() => { + setSelectedMapStyle( + typeof mapStyle === 'string' ? mapStyle : mapStyle[0].style, + ); + }, [mapStyle]); const filterConfig = { ignoreCase: true, ignoreAccents: true, trim: true, }; - useEffect(() => { - const resizeObserver = new ResizeObserver(entries => { - setSvgWidth(width || entries[0].target.clientWidth || 620); - }); - if (graphDiv.current) { - setSvgHeight(graphDiv.current.clientHeight || 480); - setSvgWidth(graphDiv.current.clientWidth || 620); - if (!width) resizeObserver.observe(graphDiv.current); - } - return () => resizeObserver.disconnect(); - }, [graphDiv?.current, width]); - useEffect(() => { - if (mapContainer.current && svgWidth && !mapRef.current) { - fetchAndParseJSON(selectedMapStyle).then(d => { - const mapDiv = select(mapContainer.current); - mapDiv.selectAll('div').remove(); - const protocol = new pmtiles.Protocol(); - maplibreGl.addProtocol('pmtiles', protocol.tile); - const mapObj: any = { - container: mapContainer.current as any, - style: - !includeLayers && !excludeLayers - ? d - : { - ...d, - layers: filterData(d.layers, [ - { - column: 'id', - includeValues: includeLayers, - excludeValues: excludeLayers, - }, - ]), - }, - }; - if (center) { - mapObj.center = center; - } - if (zoomLevel) { - mapObj.zoom = zoomLevel; - } - mapRef.current = new maplibreGl.Map(mapObj); - mapRef.current.addControl( - new maplibreGl.NavigationControl({ - visualizePitch: true, - showZoom: true, - showCompass: true, - }), - 'bottom-right', - ); - mapRef.current.addControl(new maplibreGl.ScaleControl(), 'bottom-left'); - }); - } - }, [ - mapContainer.current, - svgWidth, - selectedMapStyle, - center, - zoomLevel, - includeLayers, - excludeLayers, - ]); - useEffect(() => { - if (mapRef.current) { - fetchAndParseJSON(selectedMapStyle).then(d => { - const mapStyleObj: any = { - ...d, - layers: filterData(d.layers, [ - { - column: 'id', - includeValues: includeLayers, - excludeValues: excludeLayers, - }, - ]), - }; - mapRef.current.setStyle(mapStyleObj); - }); - } - }, [selectedMapStyle]); return (
)} -
- {(width || svgWidth) && (height || svgHeight) ? ( -
minHeight - ? (width || svgWidth) * relativeHeight - : minHeight - : (width || svgWidth) * relativeHeight - : svgHeight), - }} - > -
-
- ) : null} -
+ {typeof mapStyle === 'string' ? ( + + ) : ( + + )} {source || footNote ? (