From 6e75a712d0b9d43ebb9548240cbb6d0645ef2415 Mon Sep 17 00:00:00 2001 From: Jim O'Donnell Date: Mon, 1 Jul 2024 11:04:02 +0100 Subject: [PATCH] refactor(frontend): raster layer renderLegend and renderTooltip - Add `renderLegend` and `renderTooltip` functions to the hazards view layer. - Refactor raster tooltips and legends to use these new functions. --- .../config/hazards/HazardHoverDescription.tsx | 24 +++++++++++++++++++ frontend/src/config/hazards/HazardLegend.tsx | 13 ++++++++++ .../src/config/hazards/hazard-view-layer.ts | 19 +++++++++++++-- frontend/src/config/hazards/metadata.ts | 19 +++++++++++++++ frontend/src/config/interaction-groups.ts | 9 ++----- frontend/src/lib/data-map/view-layers.ts | 2 ++ frontend/src/map/legend/MapLegend.tsx | 5 +--- frontend/src/map/legend/RasterLegend.tsx | 16 ++++++------- .../content/RasterHoverDescription.tsx | 23 ++++++------------ 9 files changed, 92 insertions(+), 38 deletions(-) create mode 100644 frontend/src/config/hazards/HazardHoverDescription.tsx create mode 100644 frontend/src/config/hazards/HazardLegend.tsx diff --git a/frontend/src/config/hazards/HazardHoverDescription.tsx b/frontend/src/config/hazards/HazardHoverDescription.tsx new file mode 100644 index 00000000..9df0beca --- /dev/null +++ b/frontend/src/config/hazards/HazardHoverDescription.tsx @@ -0,0 +1,24 @@ +import { FC } from 'react'; + +import { InteractionTarget, RasterTarget } from 'state/interactions/use-interactions'; +import { RasterHoverDescription } from 'map/tooltip/content/RasterHoverDescription'; + +import { HAZARDS_METADATA, HAZARD_COLOR_MAPS } from './metadata'; + +export const HazardHoverDescription: FC<{ hoveredObject: InteractionTarget }> = ({ + hoveredObject, +}) => { + const { target, viewLayer } = hoveredObject; + + const { label, dataUnit } = HAZARDS_METADATA[viewLayer.id]; + const { scheme, range } = HAZARD_COLOR_MAPS[viewLayer.id]; + return ( + + ); +}; diff --git a/frontend/src/config/hazards/HazardLegend.tsx b/frontend/src/config/hazards/HazardLegend.tsx new file mode 100644 index 00000000..e3cb2222 --- /dev/null +++ b/frontend/src/config/hazards/HazardLegend.tsx @@ -0,0 +1,13 @@ +import { FC } from 'react'; + +import { RasterLegend } from 'map/legend/RasterLegend'; +import { ViewLayer } from 'lib/data-map/view-layers'; + +import { HAZARD_COLOR_MAPS, HAZARDS_METADATA } from 'config/hazards/metadata'; + +export const HazardLegend: FC<{ viewLayer: ViewLayer }> = ({ viewLayer }) => { + const { id } = viewLayer; + const { label, dataUnit } = HAZARDS_METADATA[id]; + const { scheme, range } = HAZARD_COLOR_MAPS[id]; + return ; +}; diff --git a/frontend/src/config/hazards/hazard-view-layer.ts b/frontend/src/config/hazards/hazard-view-layer.ts index 09afff2a..02c66871 100644 --- a/frontend/src/config/hazards/hazard-view-layer.ts +++ b/frontend/src/config/hazards/hazard-view-layer.ts @@ -1,10 +1,14 @@ +import { createElement } from 'react'; import GL from '@luma.gl/constants'; import { HazardParams } from 'config/hazards/domains'; import { rasterTileLayer } from 'lib/deck/layers/raster-tile-layer'; import { ViewLayer } from 'lib/data-map/view-layers'; +import { InteractionTarget, RasterTarget } from 'state/interactions/use-interactions'; -import { RASTER_COLOR_MAPS } from '../color-maps'; +import { HazardLegend } from './HazardLegend'; +import { HazardHoverDescription } from './HazardHoverDescription'; +import { HAZARD_COLOR_MAPS } from './metadata'; import { HAZARD_SOURCE } from './source'; export function getHazardId< @@ -43,7 +47,7 @@ export function hazardViewLayer(hazardType: string, hazardParams: HazardParams): interactionGroup: 'hazards', params: { hazardType, hazardParams }, fn: ({ deckProps }) => { - const { scheme, range } = RASTER_COLOR_MAPS[hazardType]; + const { scheme, range } = HAZARD_COLOR_MAPS[hazardType]; return rasterTileLayer( { @@ -61,5 +65,16 @@ export function hazardViewLayer(hazardType: string, hazardParams: HazardParams): }, ); }, + renderLegend() { + return createElement(HazardLegend, { + key: hazardType, + viewLayer: this, + }); + }, + renderTooltip(hover: InteractionTarget) { + return createElement(HazardHoverDescription, { + hoveredObject: hover, + }); + }, }; } diff --git a/frontend/src/config/hazards/metadata.ts b/frontend/src/config/hazards/metadata.ts index e8bc30de..7f8fb732 100644 --- a/frontend/src/config/hazards/metadata.ts +++ b/frontend/src/config/hazards/metadata.ts @@ -17,5 +17,24 @@ export const HAZARDS_METADATA = { }, }; +export const HAZARD_COLOR_MAPS = { + fluvial: { + scheme: 'blues', + range: [0, 10], + }, + coastal: { + scheme: 'greens', + range: [0, 10], + }, + surface: { + scheme: 'purples', + range: [0, 10], + }, + cyclone: { + scheme: 'reds', + range: [0, 75], + }, +}; + export const HAZARDS_MAP_ORDER = ['cyclone', 'fluvial', 'surface', 'coastal']; export const HAZARDS_UI_ORDER = ['fluvial', 'surface', 'coastal', 'cyclone']; diff --git a/frontend/src/config/interaction-groups.ts b/frontend/src/config/interaction-groups.ts index bb35e2b4..30e1c78a 100644 --- a/frontend/src/config/interaction-groups.ts +++ b/frontend/src/config/interaction-groups.ts @@ -6,10 +6,9 @@ import { RasterTarget, } from 'state/interactions/use-interactions'; -import { HAZARDS_METADATA } from './hazards/metadata'; +import { HazardHoverDescription } from './hazards/HazardHoverDescription'; import { VectorHoverDescription } from 'map/tooltip/content/VectorHoverDescription'; -import { RasterHoverDescription } from 'map/tooltip/content/RasterHoverDescription'; import { RegionHoverDescription } from 'map/tooltip/content/RegionHoverDescription'; import { SolutionHoverDescription } from 'map/tooltip/content/SolutionHoverDescription'; import { DroughtHoverDescription } from 'map/tooltip/content/DroughtHoverDescription'; @@ -64,10 +63,6 @@ export const INTERACTION_GROUPS = new Map([ ], ]); -export const labelsMetadata = { - ...HAZARDS_METADATA, -}; - type MapDataLayer = InteractionTarget; export const tooltipLayers: Map> = new Map< @@ -75,7 +70,7 @@ export const tooltipLayers: Map> = n FC<{ hoveredObject: MapDataLayer }> >([ ['assets', VectorHoverDescription], - ['hazards', RasterHoverDescription], + ['hazards', HazardHoverDescription], ['regions', RegionHoverDescription], ['solutions', SolutionHoverDescription], ['drought', DroughtHoverDescription], diff --git a/frontend/src/lib/data-map/view-layers.ts b/frontend/src/lib/data-map/view-layers.ts index 94b5a20e..1251ad75 100644 --- a/frontend/src/lib/data-map/view-layers.ts +++ b/frontend/src/lib/data-map/view-layers.ts @@ -56,6 +56,8 @@ export interface ViewLayer { legendDataFormatsFn?: ViewLayerDataFormatFunction; spatialType?: string; interactionGroup?: string; + renderLegend?: () => JSX.Element; + renderTooltip?: (hoveredObject: InteractionTarget) => JSX.Element; } export function viewOnlyLayer(id, fn): ViewLayer { diff --git a/frontend/src/map/legend/MapLegend.tsx b/frontend/src/map/legend/MapLegend.tsx index 1f12beaa..fb2ce324 100644 --- a/frontend/src/map/legend/MapLegend.tsx +++ b/frontend/src/map/legend/MapLegend.tsx @@ -4,7 +4,6 @@ import { ColorMap, FormatConfig } from 'lib/data-map/view-layers'; import { useRecoilValue } from 'recoil'; import { viewLayersFlatState } from 'state/layers/view-layers-flat'; import { viewLayersParamsState } from 'state/layers/view-layers-params'; -import { RasterLegend } from './RasterLegend'; import { VectorLegend } from './VectorLegend'; import { Stack, Box, Paper, Divider } from '@mui/material'; import { MobileTabContentWatcher } from 'pages/map/layouts/mobile/tab-has-content'; @@ -63,9 +62,7 @@ export const MapLegend: FC = () => { }> - {hazardViewLayers.map((viewLayer) => ( - - ))} + {hazardViewLayers.map((viewLayer) => viewLayer.renderLegend())} {Object.entries(dataColorMaps).map(([legendKey, { colorMap, formatConfig }]) => ( ))} diff --git a/frontend/src/map/legend/RasterLegend.tsx b/frontend/src/map/legend/RasterLegend.tsx index a64b8642..7727cb33 100644 --- a/frontend/src/map/legend/RasterLegend.tsx +++ b/frontend/src/map/legend/RasterLegend.tsx @@ -1,23 +1,21 @@ -import { RASTER_COLOR_MAPS } from 'config/color-maps'; -import { labelsMetadata } from 'config/interaction-groups'; -import { ViewLayer } from 'lib/data-map/view-layers'; import { FC, useCallback } from 'react'; import { GradientLegend } from './GradientLegend'; import { useRasterColorMapValues } from './use-color-map-values'; export interface ColorValue { color: string; - value: any; + value: number; } export interface RasterColorMapValues { colorMapValues: ColorValue[]; rangeTruncated: [boolean, boolean]; } -export const RasterLegend: FC<{ viewLayer: ViewLayer }> = ({ viewLayer }) => { - const { id } = viewLayer; - const { label, dataUnit } = labelsMetadata[id]; - const { scheme, range } = RASTER_COLOR_MAPS[id]; - +export const RasterLegend: FC<{ + label: string; + dataUnit: string; + scheme: string; + range: [number, number]; +}> = ({ label, dataUnit, scheme, range }) => { const { error, loading, colorMapValues } = useRasterColorMapValues(scheme, range); const getValueLabel = useCallback( diff --git a/frontend/src/map/tooltip/content/RasterHoverDescription.tsx b/frontend/src/map/tooltip/content/RasterHoverDescription.tsx index b5ddd342..587be969 100644 --- a/frontend/src/map/tooltip/content/RasterHoverDescription.tsx +++ b/frontend/src/map/tooltip/content/RasterHoverDescription.tsx @@ -1,10 +1,5 @@ import { FC, useMemo } from 'react'; -import { InteractionTarget, RasterTarget } from 'state/interactions/use-interactions'; - -import { RASTER_COLOR_MAPS } from 'config/color-maps'; -import { labelsMetadata } from 'config/interaction-groups'; - import { useRasterColorMapValues } from '../../legend/use-color-map-values'; import { ColorBox } from './ColorBox'; import { Box } from '@mui/material'; @@ -28,17 +23,13 @@ function formatHazardValue(color, value, dataUnit) { ); } -export const RasterHoverDescription: FC<{ hoveredObject: InteractionTarget }> = ({ - hoveredObject, -}) => { - const { color } = hoveredObject.target; - - const { - viewLayer: { id }, - } = hoveredObject; - const { label, dataUnit } = labelsMetadata[id]; - const { scheme, range } = RASTER_COLOR_MAPS[id]; - +export const RasterHoverDescription: FC<{ + color: [number, number, number, number]; + label: string; + dataUnit: string; + scheme: string; + range: [number, number]; +}> = ({ color, label, dataUnit, scheme, range }) => { const title = `${label}`; const { colorMapValues } = useRasterColorMapValues(scheme, range);