Skip to content

Commit

Permalink
build(deps): upgrade map packages
Browse files Browse the repository at this point in the history
- upgrade `deck.gl`, `@loaders.gl`, `react-map-gl`, `maplibre-gl`, and `@turf/*` packages to latest.
- remove `deck.gl/typed`, now that deck.gl has full typescript support.
- replace `readPixelsToArray` in the interactions library.
- replace `feature.id` with `feature.properties.id` throughout the deck.gl layer code. Feature ID now seems to be stored on `feature.properties`.
  • Loading branch information
eatyourgreens committed Mar 10, 2025
1 parent 0aeef21 commit 64c062e
Show file tree
Hide file tree
Showing 25 changed files with 2,577 additions and 1,059 deletions.
3,462 changes: 2,461 additions & 1,001 deletions frontend/package-lock.json

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,35 @@
"private": true,
"type": "module",
"dependencies": {
"@deck.gl/extensions": "8.9",
"@deck.gl/extensions": "^9.1.4",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@loaders.gl/core": "^4.2.2",
"@loaders.gl/wkt": "^4.2.2",
"@loaders.gl/core": "^4.3.3",
"@loaders.gl/images": "4.3.3",
"@loaders.gl/wkt": "^4.3.3",
"@mui/icons-material": "^6.1.0",
"@mui/lab": "^6.0.0-beta.9",
"@mui/material": "^6.1.0",
"@mui/x-data-grid": "^7.24.1",
"@mui/x-tree-view": "^7.5.0",
"@react-hook/debounce": "^4.0.0",
"@recoiljs/refine": "^0.1.1",
"@turf/bbox": "^6.5.0",
"@turf/bbox-polygon": "^6.5.0",
"@turf/buffer": "^6.5.0",
"@turf/bbox": "^7.2.0",
"@turf/bbox-polygon": "^7.2.0",
"@turf/buffer": "^7.2.0",
"d3-array": "^3.1.1",
"d3-color": "^3.0.1",
"d3-ease": "^3.0.1",
"d3-scale": "^4.0.2",
"d3-scale-chromatic": "^3.0.0",
"deck.gl": "8.9",
"deck.gl": "^9.1.4",
"immer": "^10.1.1",
"json-stable-stringify": "^1.0.1",
"lodash": "^4.17.21",
"maplibre-gl": "^4.3.2",
"maplibre-gl": "^5.2.0",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-map-gl": "^7.1.0",
"react-map-gl": "^8.0.1",
"react-router-dom": "^6.23.1",
"react-spring-bottom-sheet": "^3.4.1",
"react-vega": "^7.6.0",
Expand Down
1 change: 0 additions & 1 deletion frontend/src/app/map/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const AppNavigationControl = withProps(MapHudNavigationControl, {
const AppScaleControl = withProps(MapHudScaleControl, {
maxWidth: 100,
unit: 'metric',
capturePointerMove: true,
});

const AppAttributionControl = withProps(MapHudAttributionControl, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { VectorLegend } from 'lib/map/legend/VectorLegend';
import { getDroughtDataAccessor } from './data-access';
import { getDroughtOptionsDataFormats } from './data-formats';
import { DroughtOptionsHoverDescription } from './DroughtOptionsHoverDescription';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';

export function droughtOptionsViewLayer({ fieldSpec, colorSpec }): ViewLayer {
const dataFn = getDroughtDataAccessor(fieldSpec);
Expand All @@ -30,7 +31,7 @@ export function droughtOptionsViewLayer({ fieldSpec, colorSpec }): ViewLayer {
},
fn: ({ deckProps, selection, zoom }) => {
const target = selection?.target as VectorTarget;
const selectedFeatureIds = [target?.feature.id];
const selectedFeatureIds = [getFeatureId(target?.feature)];
return selectableMvtLayer(
{
selectionOptions: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { VectorLegend } from 'lib/map/legend/VectorLegend';
import { getDroughtDataAccessor } from './data-access';
import { getDroughtRiskDataFormats } from './data-formats';
import { DroughtRisksHoverDescription } from './DroughtRisksHoverDescription';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';

export function droughtRiskViewLayer({ fieldSpec, colorSpec }): ViewLayer {
const dataFn = getDroughtDataAccessor(fieldSpec);
Expand All @@ -31,7 +32,7 @@ export function droughtRiskViewLayer({ fieldSpec, colorSpec }): ViewLayer {

fn: ({ deckProps, selection }) => {
const target = selection?.target as VectorTarget;
const selectedFeatureIds = [target?.feature.id];
const selectedFeatureIds = [getFeatureId(target?.feature)];
return selectableMvtLayer(
{
selectionOptions: {
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/data-layers/hazards/hazard-view-layer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createElement } from 'react';
import GL from '@luma.gl/constants';
import { HazardParams } from './domains';

import { rasterTileLayer } from 'lib/deck/layers/raster-tile-layer';
Expand Down Expand Up @@ -34,7 +33,7 @@ export function getHazardId<
}

export function hazardViewLayer(hazardType: string, hazardParams: HazardParams): ViewLayer {
const magFilter = hazardType === 'cyclone' ? GL.NEAREST : GL.LINEAR;
const magFilter = hazardType === 'cyclone' ? 'nearest' : 'linear';

const { returnPeriod, rcp, epoch, confidence } = hazardParams;

Expand All @@ -52,8 +51,7 @@ export function hazardViewLayer(hazardType: string, hazardParams: HazardParams):
return rasterTileLayer(
{
textureParameters: {
[GL.TEXTURE_MAG_FILTER]: magFilter,
// [GL.TEXTURE_MAG_FILTER]: zoom < 12 ? GL.NEAREST : GL.NEAREST_MIPMAP_LINEAR,
magFilter,
},
opacity: hazardType === 'cyclone' ? 0.6 : 1,
},
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/data-layers/marine/marine-view-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { fillColor } from 'lib/deck/props/style';
import { VectorLegend } from 'lib/map/legend/VectorLegend';

import { SolutionHoverDescription } from './MarineHoverDescription';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';

function filterRange(value: boolean) {
return value ? [1, 1] : [0, 1];
Expand All @@ -21,7 +22,7 @@ export function marineViewLayer({ dataFn, colorFn, filters }): ViewLayer {
interactionGroup: 'solutions',
fn: ({ deckProps, selection }) => {
const target = selection?.target as VectorTarget;
const selectedFeatureIds = [target?.feature.id];
const selectedFeatureIds = [getFeatureId(target?.feature)];
return selectableMvtLayer(
{
selectionOptions: {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/data-layers/regions/population-view-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { VectorLegend } from 'lib/map/legend/VectorLegend';
import { RegionLevel } from './metadata';
import { REGIONS_SOURCE } from './source';
import { RegionHoverDescription } from './RegionHoverDescription';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';

export function populationViewLayer(regionLevel: RegionLevel): ViewLayer {
const source = REGIONS_SOURCE;
Expand Down Expand Up @@ -43,7 +44,7 @@ export function populationViewLayer(regionLevel: RegionLevel): ViewLayer {
}),
fn: ({ deckProps, zoom, selection }) => {
const target = selection?.target as VectorTarget;
const selectedFeatureIds = [target?.feature.id];
const selectedFeatureIds = [getFeatureId(target?.feature)];
return selectableMvtLayer(
{ selectionOptions: { selectedFeatureIds } },
deckProps,
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/data-layers/risks/risk-view-layer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createElement } from 'react';
import GL from '@luma.gl/constants';
import { RiskParams } from './domains';

import { rasterTileLayer } from 'lib/deck/layers/raster-tile-layer';
Expand Down Expand Up @@ -58,7 +57,7 @@ export function riskViewLayer(riskType: string, riskParams: RiskParams): ViewLay
return rasterTileLayer(
{
textureParameters: {
[GL.TEXTURE_MAG_FILTER]: GL.LINEAR,
magFilter: 'linear',
},
opacity: riskType === 'cyclone' ? 0.6 : 1,
},
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/details/features/FeatureSidebar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { selectionState } from 'lib/state/interactions/interaction-state';
import mockFeature from 'mocks/details/features/mockFeature.json';
import mockFeatureDetails from 'mocks/details/features/mockFeatureDetails.json';
import { FeatureSidebar } from './FeatureSidebar';
import { Layer } from 'deck.gl/typed';
import { Layer } from 'deck.gl';

function FixedWidthDecorator(Story) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { selectionState } from 'lib/state/interactions/interaction-state';
import mockTerrestrialFeature from 'mocks/details/solutions/mockTerrestrialFeature.json';
import mockMarineFeature from 'mocks/details/solutions/mockMarineFeature.json';
import { SolutionsSidebar } from './SolutionsSidebar';
import { Layer } from 'deck.gl/typed';
import { Layer } from 'deck.gl';

function FixedWidthDecorator(Story) {
return (
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/lib/data-map/BaseMap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MapViewState } from 'deck.gl/typed';
import { MapViewState } from 'deck.gl';
import { StyleSpecification } from 'maplibre-gl';
import { FC, ReactNode } from 'react';
import { Map } from 'react-map-gl/maplibre';
Expand All @@ -25,7 +25,9 @@ const MapGLMap: FC<BaseMapProps> = ({ children, mapStyle, onMove, viewState }) =
keyboard={false}
touchZoomRotate={true}
touchPitch={false}
antialias={true}
canvasContextAttributes={{
antialias: true,
}}
attributionControl={false}
>
{children}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/lib/data-map/DataMap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MapboxOverlay } from '@deck.gl/mapbox/typed';
import type { MapboxOverlay } from '@deck.gl/mapbox';
import { useMap } from 'react-map-gl/maplibre';
import { FC, useRef } from 'react';
import { useRecoilValue } from 'recoil';
Expand All @@ -10,7 +10,7 @@ import { useSaveViewLayers, viewLayersFlatState } from 'lib/state/layers/view-la
import { viewLayersParamsState } from 'lib/state/layers/view-layers-params';
import { DeckGLOverlay } from 'lib/map/DeckGLOverlay';
import { ViewLayer, ViewLayerParams } from 'lib/data-map/view-layers';
import { LayersList } from 'deck.gl/typed';
import { LayersList } from 'deck.gl';

// set a convention where the view layer id is either the first part of the deck id before the @ sign, or it's the whole id
function lookupViewForDeck(deckLayerId: string) {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/data-map/layers/assets/asset-view-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { VectorTarget } from 'lib/data-map/types';
import { selectableMvtLayer } from 'lib/deck/layers/selectable-mvt-layer';
import { VectorLegend } from 'lib/map/legend/VectorLegend';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';

import { ASSETS_SOURCE } from './source';

Expand Down Expand Up @@ -38,7 +39,7 @@ export function assetViewLayer(
fn({ deckProps, zoom, selection }: ViewLayerFunctionOptions) {
const styleParams = this?.styleParams;
const target = selection?.target as VectorTarget;
const selectedFeatureIds = [target?.feature.id];
const selectedFeatureIds = [getFeatureId(target?.feature)];
return selectableMvtLayer(
{
selectionOptions: {
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/lib/data-map/layers/assets/data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { dataLoaderManager } from 'lib/data-loader/data-loader-manager';
import { FieldSpec } from 'lib/data-map/view-layers';
import { featureProperty } from 'lib/deck/props/data-source';
import { Accessor, withTriggers } from 'lib/deck/props/getters';
import { getFeatureId } from 'lib/deck/utils/get-feature-id';
import { sumOrNone } from 'lib/helpers';

function getExpectedDamageKey(direct: boolean, hazard: string, rcp: string, epoch: number) {
Expand Down Expand Up @@ -54,10 +55,10 @@ export function getAssetDataAccessor(layer: string, fieldSpec: FieldSpec) {
} else if (fieldGroup === 'damages_return_period') {
// return return period damages dynamically loaded from API
const dataLoader = dataLoaderManager.getDataLoader(layer, fieldSpec);
return withLoaderTriggers((f) => dataLoader.getData(f.id), dataLoader);
return withLoaderTriggers((f) => dataLoader.getData(getFeatureId(f)), dataLoader);
} else if (fieldGroup === 'adaptation') {
const dataLoader = dataLoaderManager.getDataLoader(layer, fieldSpec);
return withLoaderTriggers((f) => dataLoader.getData(f.id), dataLoader);
return withLoaderTriggers((f) => dataLoader.getData(getFeatureId(f)), dataLoader);
} else {
// field other than damages - use field name as key
return featureProperty(field);
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/data-map/view-layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ScaleSequential } from 'd3-scale';
import { DataLoader } from 'lib/data-loader/data-loader';
import { Accessor } from 'lib/deck/props/getters';
import { InteractionTarget, VectorTarget, RasterTarget } from './types';
import { Layer } from 'deck.gl/typed';
import { Layer } from 'deck.gl';

export interface FieldSpec {
fieldGroup: string;
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/lib/deck/layers/data-loader-layer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DataLoader } from 'lib/data-loader/data-loader';
import { MapGeoJSONFeature } from 'maplibre-gl';
import { getFeatureId } from '../utils/get-feature-id';

export interface DataLoaderOptions {
dataLoader: DataLoader;
Expand All @@ -13,7 +13,7 @@ export function dataLoaderLayer(tileProps, { dataLoader }: DataLoaderOptions) {
tile: { content },
} = tileProps;
if (content && dataLoader) {
const ids: number[] = !dataLoader.hasData ? content.map((f: MapGeoJSONFeature) => f.id) : [];
const ids: number[] = !dataLoader.hasData ? content.map(getFeatureId) : [];

dataLoader.loadDataForIds(ids);
}
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/deck/layers/tile-selection-layer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataFilterExtension } from '@deck.gl/extensions';

import { geoJsonLayer } from './base';
import { getFeatureId } from '../utils/get-feature-id';

export interface TileSelectionLayerOptions {
selectedFeatureIds: number[] | null;
Expand Down Expand Up @@ -39,7 +40,7 @@ export function tileSelectionLayer(
},

// use on-GPU filter extension to only show the selected features
getFilterValue: (x) => (selectedFeatureIds?.includes(x.id) ? 1 : 0),
getFilterValue: (x) => (selectedFeatureIds?.includes(getFeatureId(x)) ? 1 : 0),
filterRange: [1, 1],
extensions: [new DataFilterExtension({ filterSize: 1 })],
});
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/deck/props/style.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GeoJsonLayerProps } from 'deck.gl/typed';
import { GeoJsonLayerProps } from 'deck.gl';

import { Getter } from './getters';

Expand Down
41 changes: 41 additions & 0 deletions frontend/src/lib/deck/utils/get-feature-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export interface FeatureWithIdAndProperties {
id?: number | string;
properties?: { id?: number | string } & Record<string, unknown>;
}

/** Get feature ID either from feature.id, or from a unique ID property.
* Handles a deck.gl quirk where the ID is moved inside properties object in some cases.
* Handles string IDs by parsing them to numbers (returns undefined if parsing fails).
*/
export function getFeatureId(
feature: FeatureWithIdAndProperties,
uniqueIdProperty?: string,
): number | undefined {
if (feature == null) {
return undefined;
}

let id;
if (uniqueIdProperty) {
id = feature.properties?.[uniqueIdProperty];
} else {
// try properties.id because deck.gl seems to currently move the ID inside properties object in some cases
id = feature.id ?? feature.properties?.id;
}

if (id == null) {
return undefined;
}

if (typeof id === 'number') {
return id;
}

const parsedId = parseInt(id, 10);

if (isNaN(parsedId)) {
return undefined;
}

return parsedId;
}
2 changes: 1 addition & 1 deletion frontend/src/lib/map/DeckGLOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MapboxOverlay, MapboxOverlayProps } from '@deck.gl/mapbox/typed';
import { MapboxOverlay, MapboxOverlayProps } from '@deck.gl/mapbox';
import { forwardRef, useImperativeHandle } from 'react';
import { useControl } from 'react-map-gl/maplibre';

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/map/MapBoundsFitter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { WebMercatorViewport } from 'deck.gl/typed';
import { WebMercatorViewport } from 'deck.gl';
import { FC, useEffect } from 'react';
import { useMap } from 'react-map-gl/maplibre';
import { atom, useRecoilValue, useResetRecoilState } from 'recoil';
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/map/hud/map-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AttributionControl, NavigationControl, ScaleControl } from 'react-map-gl';
import { AttributionControl, NavigationControl, ScaleControl } from 'react-map-gl/maplibre';

import { withProps } from 'lib/react/with-props';

Expand Down
6 changes: 5 additions & 1 deletion frontend/src/lib/state/interactions/interaction-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ const selectionChangeEffect =
interactionGroup: id,
interactionStyle: 'vector', // raster selection is not supported at present.
viewLayer: { id: viewLayerId },
target: { feature: { id: parseInt(featureId) } },
target: {
feature: {
id: parseInt(featureId),
},
},
});
} else {
setSelf(null);
Expand Down
Loading

0 comments on commit 64c062e

Please sign in to comment.