diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx index edd2fcb243518c5c461006a363e54be8c32af775..47eba03d3a9ceb79afc9bf702fbd52fecfe67021 100644 --- a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx +++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx @@ -1,18 +1,29 @@ -import React, { useEffect, useMemo, useCallback, useState } from 'react'; +import React, { useEffect, useMemo, useCallback } from 'react'; import DeckGL from '@deck.gl/react'; import { FlyToInterpolator, WebMercatorViewport } from '@deck.gl/core'; import { SelectionLayer } from '@deck.gl-community/editable-layers'; import { Coordinate, Layer } from './mapvis.types'; import { VISComponentType, VisualizationPropTypes } from '../../common'; -import { layerTypes, createBaseMap } from './layers'; -import { MapSettings } from './settings'; +import { layerTypes } from './components/layers'; +import { createBaseMap } from './components/BaseMap'; +import { MapSettings } from './MapSettings'; import { Node } from '@graphpolaris/shared/lib/data-access/store/graphQueryResultSlice'; -import { HighlightAlt, SearchOutlined } from '@mui/icons-material'; -import SearchBar from './search'; -export type MapProps = { layer: string }; +export type MapProps = { + layer: string; + node: undefined | string; + lat: string; + lon: string; + enableBrushing: boolean; +}; -const settings: MapProps = { layer: 'node' }; +const settings: MapProps = { + layer: 'node', + node: undefined, + lat: 'gp_latitude', + lon: 'gp_longitude', + enableBrushing: false, +}; const INITIAL_VIEW_STATE = { latitude: 52.1006, @@ -26,14 +37,13 @@ const FLY_SPEED = 1000; const baseLayer = createBaseMap(); -export const MapVis = ({ data, settings, handleSelect, graphMetadata }: VisualizationPropTypes<MapProps>) => { - const [layer, setLayer] = useState<Layer | undefined>(undefined); - const [viewport, setViewport] = useState<Record<string, any>>(INITIAL_VIEW_STATE); - const [hoverObject, setHoverObject] = useState<Node | null>(null); - const [selected, setSelected] = useState<any[]>([]); - const [selectingRectangle, setSelectingRectangle] = useState<boolean>(false); - const [layerIds, setLayerIds] = useState<string[]>([]); - const [isSearching, setIsSearching] = useState<boolean>(false); +export const MapVis = ({ data, settings, updateSettings, graphMetadata, handleSelect }: VisualizationPropTypes<MapProps>) => { + const [layer, setLayer] = React.useState<Layer | undefined>(undefined); + const [viewport, setViewport] = React.useState<Record<string, any>>(INITIAL_VIEW_STATE); + const [hoverObject, setHoverObject] = React.useState<Node | null>(null); + const [selected, setSelected] = React.useState<any[]>([]); + const [isSelecting, setIsSelecting] = React.useState<boolean>(false); + const [selectingRectangle, setSelectingRectangle] = React.useState<boolean>(false); const getFittedViewport = useCallback( (minLat: number, maxLat: number, minLon: number, maxLon: number) => { @@ -66,23 +76,33 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz useEffect(() => { const layerType = settings.layer ? layerTypes?.[settings.layer] : layerTypes.node; - const newLayerId = `layer-${Date.now()}`; setLayer({ + id: Date.now(), + name: 'New layer', type: layerType, config: settings, + visible: true, }); - - setLayerIds((prevIds) => [...prevIds, newLayerId]); }, [settings.layer]); + useEffect(() => { + console.log('configuration.node', settings.node); + }, [settings.node]); + + useEffect(() => { + if (settings.node != undefined && !graphMetadata.nodes.labels.includes(settings.node)) { + updateSettings({ node: undefined }); + } + }, [graphMetadata.nodes.types, data, settings]); + const dataLayer = useMemo(() => { - if (!layer || !settings.layer) return null; + if (!layer || !settings.node || !settings.lat || !settings.lon) return null; const coordinateLookup: { [id: string]: Coordinate } = data.nodes.reduce( (acc, node) => { - const latitude = settings[node.label].lat ? (node?.attributes?.[settings[node.label].lat] as string) : undefined; - const longitude = settings[node.label].lon ? (node?.attributes?.[settings[node.label].lon] as string) : undefined; + const latitude = settings.lat ? (node?.attributes?.[settings.lat] as string) : undefined; + const longitude = settings.lon ? (node?.attributes?.[settings.lon] as string) : undefined; if (!!latitude && !!longitude) { acc[node._id] = [parseFloat(longitude), parseFloat(latitude)]; @@ -94,18 +114,19 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz ); return new layer.type({ + id: `${layer.id}`, graph: data, - metaData: graphMetadata, - config: settings, + visible: layer.visible, + config: layer.config, selected: selected, hoverObject: hoverObject, - getNodeLocation: (d: string) => { - return coordinateLookup[d]; + isSelecting: isSelecting, + getNodeLocation: (d: Node) => { + return coordinateLookup[d._id]; }, flyToBoundingBox: flyToBoundingBox, - setLayerIds: (val: string[]) => setLayerIds(val), }); - }, [layer, data, selected, hoverObject, settings]); + }, [layer, data, selected, hoverObject, isSelecting, settings.lat, settings.lon, settings.node]); const selectionLayer = useMemo( () => @@ -113,29 +134,11 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz new (SelectionLayer as any)({ id: 'selection', selectionType: 'rectangle', - onSelect: ({ pickingInfos }: { pickingInfos: any[] }) => { - if (pickingInfos.length > 0) { - const nodes = []; - const edges = []; - - for (const selectedItem of pickingInfos) { - const { object } = selectedItem; - if (object._id) { - if (object.from & object.to) { - edges.push(object); - } else { - nodes.push(object); - } - } - } - setSelected(nodes.map((node) => node._id)); - handleSelect({ nodes, edges }); - } else { - handleSelect(); - } + onSelect: ({ pickingInfos }: any) => { + setSelected(pickingInfos.map((item: any) => item.object)); setSelectingRectangle(false); }, - layerIds: layerIds, + layerIds: [layer?.id ? layer.id : ''], getTentativeFillColor: () => [22, 37, 67, 100], }), [selectingRectangle, layer], @@ -143,24 +146,8 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz return ( <div className="w-full h-full flex-grow relative overflow-hidden"> - <div className="absolute left-0 top-0 z-50 m-1"> - <div className="cursor-pointer p-1 bg-white shadow-md rounded mb-1" onClick={() => setSelectingRectangle(true)}> - <HighlightAlt /> - </div> - <div className="cursor-pointer p-1 bg-white shadow-md rounded" onClick={() => setIsSearching(!isSearching)}> - <SearchOutlined /> - </div> - </div> - {isSearching && ( - <SearchBar - onSearch={(boundingbox: [number, number, number, number]) => { - flyToBoundingBox(...boundingbox); - setIsSearching(false); - }} - /> - )} <DeckGL - layers={[baseLayer, dataLayer, selectionLayer]} + layers={[baseLayer, dataLayer]} controller={true} initialViewState={viewport} onViewStateChange={({ viewState }) => setViewport(viewState)} @@ -168,7 +155,6 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz if (data) { if (!object) { handleSelect(); - setSelected([]); return; } if (object.hasOwnProperty('attributes') && object.hasOwnProperty('id') && object.hasOwnProperty('label')) { @@ -192,12 +178,6 @@ export const MapVis = ({ data, settings, handleSelect, graphMetadata }: Visualiz setHoverObject(object !== undefined ? object : null); }} /> - <div className="absolute right-0 top-0 p-1 z-50 bg-white bg-opacity-75 text-xs"> - {'© '} - <a className="underline" href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer"> - OpenStreetMap - </a> - </div> </div> ); };