Skip to content
Snippets Groups Projects

geo intergation

Merged Leonardo Christino requested to merge feat/get_intergation into main
1 file
+ 15
3
Compare changes
  • Side-by-side
  • Inline
import React from 'react';
import { MapPanel, LayerPanel } from './components';
import GraphModel from './graphModel';
import { GraphType, Layer } from './types';
import React, { useEffect, useMemo } from 'react';
import DeckGL from '@deck.gl/react';
import { FlyToInterpolator, MapView, 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 { GraphMetaData } from '@graphpolaris/shared/lib/data-access/statistics';
import { SettingsContainer } from '../../components/config';
import { layerTypes } from './components/layers';
import { createBaseMap } from './components/BaseMap';
import { Input, useML } from '../../..';
import { GraphMetadata } from '@graphpolaris/shared/lib/data-access/statistics';
export type MapProps = {};
export type MapProps = {
layer: undefined | string;
node: undefined | string;
lat: undefined | string;
lon: undefined | string;
};
const configuration: MapProps = {
layer: 'node',
node: undefined,
lat: 'gp_latitude',
lon: 'gp_longitude',
};
const INITIAL_VIEW_STATE = {
latitude: 52.1006,
longitude: 5.6464,
zoom: 6,
bearing: 0,
pitch: 0,
};
const FLY_SPEED = 1000;
const configuration: MapProps = {};
export const MapVis = ({ data, configuration, updateSettings, graphMetadata }: VisualizationPropTypes) => {
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);
export default function MapVis({ data }: VisualizationPropTypes) {
const [layers, setLayers] = React.useState<Layer[]>([]);
const [showFilter, setShowFilter] = React.useState<boolean>(false);
const getFittedViewport = (minLat: number, maxLat: number, minLon: number, maxLon: number) => {
const viewportWebMercator = new WebMercatorViewport(viewport).fitBounds(
[
[minLon, minLat],
[maxLon, maxLat],
],
{ padding: 20 },
);
const { zoom, longitude, latitude } = viewportWebMercator;
return { zoom, longitude, latitude };
};
let graph = React.useMemo(() => {
try {
const graphModel = new GraphModel();
graphModel.consumeMessageFromBackend(data);
return graphModel;
} catch (e) {
console.error(e);
return null;
const flyToBoundingBox = (minLat: number, maxLat: number, minLon: number, maxLon: number, options = {}) => {
const fittedViewport = getFittedViewport(minLat, maxLat, minLon, maxLon);
setViewport((prevViewport) => ({
...prevViewport,
...options,
...fittedViewport,
transitionDuration: FLY_SPEED,
transitionInterpolator: new FlyToInterpolator(),
}));
};
useEffect(() => {
if (configuration.layer) {
const layerType = layerTypes[configuration.layer] as any;
setLayer({
id: Date.now(),
name: 'New layer',
type: layerType,
config: {
...layerType.layerOptions,
},
visible: true,
});
}
}, [configuration.layer]);
useEffect(() => {
if (!graphMetadata.nodes.labels.includes(configuration.node)) {
updateSettings({ node: undefined });
}
}, [data]);
}, [graphMetadata.nodes.types, data, configuration]);
const dataLayer = useMemo(() => {
if (!layer || !configuration.node || !configuration.lat || !configuration.lon) return null;
const coordinateLookup: { [id: string]: Coordinate } = data.nodes.reduce(
(acc, node) => {
// const latitude = getProperty(node, configuration.lat);
// const longitude = getProperty(node, configuration.lon);
const latitude = node?.attributes?.[configuration.lat] as string | undefined;
const longitude = node?.attributes?.[configuration.lon] as string | undefined;
if (!graph) return <div>No data</div>;
if (!!latitude && !!longitude) {
acc[node.id] = [parseFloat(longitude), parseFloat(latitude)];
}
return acc;
},
{} as { [id: string]: Coordinate },
);
return new layer.type({
id: `${layer.id}`,
graph: data,
visible: layer.visible,
config: layer.config,
selected: selected,
hoverObject: hoverObject,
isSelecting: isSelecting,
getNodeLocation: (id: string) => coordinateLookup[id],
flyToBoundingBox: flyToBoundingBox,
});
}, [layer, data, selected, hoverObject, isSelecting, configuration.lat, configuration.lon, configuration.node]);
const selectionLayer = useMemo(
() =>
selectingRectangle &&
new (SelectionLayer as any)({
id: 'selection',
selectionType: 'rectangle',
onSelect: ({ pickingInfos }: any) => {
setSelected(pickingInfos.map((item: any) => item.object));
setSelectingRectangle(false);
},
layerIds: [layer?.id ? layer.id : ''],
getTentativeFillColor: () => [22, 37, 67, 100],
}),
[selectingRectangle, layer],
);
const handleSelect = (info: any, event: any) => {
const shiftPressed = event.srcEvent.shiftKey;
setIsSelecting(shiftPressed);
setSelected((prevSelected) => {
if (!shiftPressed) {
return info.object !== undefined ? [info.object] : [];
} else {
const selectedIndex = prevSelected.findIndex((obj) => obj === info.object);
if (selectedIndex !== -1) {
prevSelected.splice(selectedIndex, 1);
} else {
prevSelected.push(info.object);
}
return [...prevSelected];
}
});
};
return (
<div className="flex flex-row justify-between overflow-hidden h-full w-full font-sans">
<MapPanel graph={graph} layers={layers} showFilter={showFilter} setShowFilter={setShowFilter} />
{/* <LayerPanel layers={layers} setLayers={setLayers} graphInfo={graph.getGraphInfo()} setShowFilter={setShowFilter} /> */}
<div className="w-full h-full flex-grow relative">
<DeckGL
layers={[createBaseMap(), dataLayer, selectionLayer]}
controller={true}
initialViewState={viewport}
onViewStateChange={({ viewState }) => setViewport(viewState)}
onClick={handleSelect}
onHover={({ object }) => {
setHoverObject(object !== undefined ? object : null);
}}
/>
</div>
);
}
};
const MapSettings = ({
configuration,
graph,
graphMetadata,
updateSettings,
}: {
configuration: MapProps;
graph: GraphMetaData;
graphMetadata: GraphMetadata;
updateSettings: (val: any) => void;
}) => {
return <div>To be implemented</div>;
// const spatialAttributes = useMemo(() => {
// if (!configuration.node) return [];
// return Object.entries(graphMetadata.nodes.types[configuration.node].attributes)
// .filter((kv) => kv[1].dimension === 'spatial')
// .map((kv) => kv[0]);
// }, [configuration.node]);
const spatialAttributes = useMemo(() => {
if (!configuration.node) return [];
return Object.entries(graphMetadata.nodes.types[configuration.node].attributes).map((kv) => kv[0]);
}, [configuration.node]);
return (
<SettingsContainer>
<span className="text-xs font-semibold">Data layer</span>
<Input
type="dropdown"
value={configuration.layer}
options={Object.keys(layerTypes)}
onChange={(val) => updateSettings({ layer: val })}
/>
<span className="text-xs font-semibold">Node Label</span>
<Input
type="dropdown"
value={configuration.node}
options={[...Object.keys(graphMetadata.nodes.types)]}
disabled={Object.keys(graphMetadata.nodes.types).length < 1}
onChange={(val) => updateSettings({ node: val })}
/>
<span className="text-xs font-semibold">Location accessor (lat)</span>
<Input
type="dropdown"
value={configuration.lat}
options={[...spatialAttributes]}
disabled={!configuration.node || spatialAttributes.length < 1}
onChange={(val) => updateSettings({ lat: val })}
/>
<span className="text-xs font-semibold">Location accessor (lon)</span>
<Input
type="dropdown"
value={configuration.lon}
options={[...spatialAttributes]}
disabled={!configuration.node || spatialAttributes.length < 1}
onChange={(val) => updateSettings({ lon: val })}
/>
</SettingsContainer>
);
};
export const MapComponent: VISComponentType = {
@@ -52,3 +234,5 @@ export const MapComponent: VISComponentType = {
settings: MapSettings,
configuration: configuration,
};
export default MapComponent;
Loading