Skip to content

Commit

Permalink
fix: Upgrade mapbox-gl (#1400)
Browse files Browse the repository at this point in the history
I upgrading mapbox-gl, in order to use the fitBounds with
alternative projections.
  • Loading branch information
AliceR authored Feb 3, 2025
2 parents 027d5c5 + e40b575 commit 5e65894
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 113 deletions.
2 changes: 1 addition & 1 deletion app/scripts/components/common/blocks/block-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function MapBlock(props: MapBlockProps) {
parallels: projectionParallels
});
return {
...projection,
...(projection as object),
id: projectionId
};
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BasemapId, Option } from './basemap';
import { MbProjectionOptions, ProjectionOptions } from '$types/veda';
import { ProjectionOptions } from '$types/veda';

export interface MapOptionsProps {
onProjectionChange: (projection: ProjectionOptions) => void;
Expand All @@ -19,7 +19,7 @@ export interface ProjectionConicOptions {

export interface ProjectionListItem {
id: ProjectionOptions['id'];
mbId: MbProjectionOptions['name'];
mbId: mapboxgl.ProjectionSpecification['name'];
label: string;
isCustom?: boolean;
conicValues?: ProjectionConicOptions;
Expand Down
3 changes: 2 additions & 1 deletion app/scripts/components/common/map/map-component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback, ReactElement, useMemo, Ref } from 'react';
import ReactMapGlMap, { LngLatBoundsLike, MapRef } from 'react-map-gl';
import { debounce } from 'lodash';
import { ProjectionSpecification } from 'mapbox-gl';
import useMapStyle from './hooks/use-map-style';
import { useMapsContext } from './hooks/use-maps';
import { convertProjectionToMapbox } from './controls/map-options/projections';
Expand Down Expand Up @@ -81,7 +82,7 @@ export default function MapComponent({
mapStyle={style as any}
onMove={onMove}
onLoad={onMapLoad}
projection={mapboxProjection}
projection={mapboxProjection as ProjectionSpecification}
maxBounds={maxMapBounds}
interactive={interactive}
>
Expand Down
18 changes: 10 additions & 8 deletions app/scripts/components/common/map/style-generators/basemap.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useQuery } from '@tanstack/react-query';
import { AnySourceImpl, Layer, Style } from 'mapbox-gl';
import { StyleSpecification } from 'mapbox-gl';
import { useEffect, useMemo, useState } from 'react';
import {
BasemapId,
Expand Down Expand Up @@ -35,7 +35,9 @@ export function Basemap({
}: BasemapProps) {
const { envMapboxToken } = useVedaUI();
const { updateStyle } = useMapStyle();
const [baseStyle, setBaseStyle] = useState<Style | undefined>(undefined);
const [baseStyle, setBaseStyle] = useState<StyleSpecification | undefined>(
undefined
);

const basemapStyles = useMemo(
() => getBasemapStyles(envMapboxToken),
Expand All @@ -62,7 +64,7 @@ export function Basemap({
);

useEffect(() => {
setBaseStyle(styleJson as Style);
setBaseStyle(styleJson as StyleSpecification);
}, [styleJson]);

// Apply labels and boundaries options, by setting visibility on related
Expand All @@ -76,15 +78,15 @@ export function Basemap({
// this id from the list of groups in the metadata section of the style.
const labelsGroupIds = mapGroupNameToGroupId(
GROUPS_BY_OPTION.labels,
baseStyle.metadata['mapbox:groups']
baseStyle.metadata?.['mapbox:groups']
);
const boundariesGroupIds = mapGroupNameToGroupId(
GROUPS_BY_OPTION.boundaries,
baseStyle.metadata['mapbox:groups']
baseStyle.metadata?.['mapbox:groups']
);

const layers = baseStyle.layers.map((layer) => {
const layerGroup = (layer as Layer).metadata?.['mapbox:group'];
const layerGroup = layer.metadata?.['mapbox:group'];

if (layerGroup) {
const isLabelsLayer = labelsGroupIds.includes(layerGroup);
Expand All @@ -100,7 +102,7 @@ export function Basemap({
return {
...layer,
layout: {
...(layer as Layer).layout,
...layer.layout,
visibility
},
metadata: {
Expand All @@ -115,7 +117,7 @@ export function Basemap({

updateStyle({
generatorId: 'basemap',
sources: baseStyle.sources as Record<string, AnySourceImpl>,
sources: baseStyle.sources,
layers: layers as ExtendedLayer[]
});
}, [updateStyle, labelsOption, boundariesOption, baseStyle]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useMemo } from 'react';
import qs from 'qs';
import { RasterSource, RasterLayer } from 'mapbox-gl';
import { RasterSourceSpecification, RasterLayerSpecification } from 'mapbox-gl';

import { BaseGeneratorParams } from '../types';
import useMapStyle from '../hooks/use-map-style';
Expand Down Expand Up @@ -56,14 +56,14 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) {
arrayFormat: 'comma'
});

const zarrSource: RasterSource = {
const zarrSource: RasterSourceSpecification = {
type: 'raster',
url: `${tileApiEndpoint}?${tileParamsAsString}`
};

const rasterOpacity = typeof opacity === 'number' ? opacity / 100 : 1;

const zarrLayer: RasterLayer = {
const zarrLayer: RasterLayerSpecification = {
id: id,
type: 'raster',
source: id,
Expand Down Expand Up @@ -93,6 +93,7 @@ export function RasterPaintLayer(props: RasterPaintLayerProps) {
},
// sourceParams not included, but using a stringified version of it to
// detect changes (haveSourceParamsChanged)
// eslint-disable-next-line react-hooks/exhaustive-deps
[
updateStyle,
id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import qs from 'qs';
import {
AnyLayer,
AnySourceImpl,
GeoJSONSourceRaw,
LayerSpecification,
SourceSpecification,
GeoJSONSourceSpecification,
LngLatBoundsLike,
RasterLayer,
RasterSource,
SymbolLayer
RasterLayerSpecification,
RasterSourceSpecification,
SymbolLayerSpecification
} from 'mapbox-gl';
import { useTheme } from 'styled-components';
import { featureCollection, point } from '@turf/helpers';
Expand Down Expand Up @@ -360,8 +361,8 @@ export function RasterTimeseries(props: RasterTimeseriesProps) {
const controller = new AbortController();

async function run() {
let layers: AnyLayer[] = [];
let sources: Record<string, AnySourceImpl> = {};
let layers: LayerSpecification[] = [];
let sources: Record<string, SourceSpecification> = {};

if (mosaicUrl) {
const tileParams = qs.stringify(
Expand Down Expand Up @@ -392,14 +393,14 @@ export function RasterTimeseries(props: RasterTimeseriesProps) {
'WMTSCapabilities.xml'
);

const mosaicSource: RasterSource = {
const mosaicSource: RasterSourceSpecification = {
type: 'raster',
url: tilejsonUrl
};

const rasterOpacity = typeof opacity === 'number' ? opacity / 100 : 1;

const mosaicLayer: RasterLayer = {
const mosaicLayer: RasterLayerSpecification = {
id: id,
type: 'raster',
source: id,
Expand Down Expand Up @@ -449,14 +450,14 @@ export function RasterTimeseries(props: RasterTimeseriesProps) {

if (points && minZoom > 0) {
const pointsSourceId = `${id}-points`;
const pointsSource: GeoJSONSourceRaw = {
const pointsSource: GeoJSONSourceSpecification = {
type: 'geojson',
data: featureCollection(
points.map((p) => point(p.center, { bounds: p.bounds }))
)
};

const pointsLayer: SymbolLayer = {
const pointsLayer: SymbolLayerSpecification = {
type: 'symbol',
id: pointsSourceId,
source: pointsSourceId,
Expand All @@ -476,7 +477,7 @@ export function RasterTimeseries(props: RasterTimeseriesProps) {
};
sources = {
...sources,
[pointsSourceId]: pointsSource as AnySourceImpl
[pointsSourceId]: pointsSource as SourceSpecification
};
layers = [...layers, pointsLayer];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import qs from 'qs';
import { AnyLayer, AnySourceImpl, VectorSourceImpl } from 'mapbox-gl';
import {
LayerSpecification,
SourceSpecification,
VectorSourceSpecification
} from 'mapbox-gl';
import { useTheme } from 'styled-components';
import endOfDay from 'date-fns/endOfDay';
import startOfDay from 'date-fns/startOfDay';
Expand Down Expand Up @@ -131,11 +135,11 @@ export function VectorTimeseries(props: VectorTimeseriesProps) {

const vectorOpacity = typeof opacity === 'number' ? opacity / 100 : 1;

const sources: Record<string, AnySourceImpl> = {
const sources: Record<string, SourceSpecification> = {
[id]: {
type: 'vector',
tiles: [`${featuresApiEndpoint}/tiles/{z}/{x}/{y}?${tileParams}`]
} as VectorSourceImpl
} as VectorSourceSpecification
};

const layers = [
Expand Down Expand Up @@ -234,7 +238,7 @@ export function VectorTimeseries(props: VectorTimeseriesProps) {
}
}
: undefined
].filter(Boolean) as AnyLayer[];
].filter(Boolean) as LayerSpecification[];

updateStyle({
generatorId,
Expand Down
34 changes: 23 additions & 11 deletions app/scripts/components/common/map/styles.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { AnySourceImpl, Layer, Style } from 'mapbox-gl';
import {
LayerSpecification,
SourceSpecification,
StyleSpecification
} from 'mapbox-gl';
import React, {
ReactNode,
createContext,
Expand All @@ -16,7 +20,7 @@ import {

export interface StylesContextType {
updateStyle: (params: GeneratorStyleParams) => void;
style?: Style;
style?: StyleSpecification;
updateMetaData?: (params: unknown) => void;
metaData?: unknown;
isCompared?: boolean;
Expand Down Expand Up @@ -53,7 +57,7 @@ const generateStyle = (
stylesData: Record<string, GeneratorStyleParams>,
currentMapStyle
) => {
let sources: Record<string, AnySourceImpl> = {};
let sources: Record<string, SourceSpecification> = {};
let layers: ExtendedLayer[] = [];

Object.entries(stylesData).forEach(([generatorId, generatorParams]) => {
Expand All @@ -64,10 +68,12 @@ const generateStyle = (
};

const generatorLayers = generatorParams.layers.map((generatorLayer) => {
const metadata: ExtendedMetadata = generatorLayer.metadata ?? {};
metadata.generatorId = generatorId;
const metadata: ExtendedMetadata = {
...(generatorLayer.metadata ?? {}),
generatorId
};

const mapLayer = { ...generatorLayer, metadata } as Layer;
const mapLayer = { ...generatorLayer, metadata } as LayerSpecification;

if (generatorParams.params?.hidden) {
mapLayer.layout = {
Expand All @@ -84,13 +90,19 @@ const generateStyle = (
// Allow sort as it uses a copy of the array so mutating is ok
/* eslint-disable-next-line fp/no-mutating-methods */
layers = [...layers].sort((layerA, layerB) => {
const layerAOrder = layerA.metadata?.layerOrderPosition;
const layerBOrder = layerB.metadata?.layerOrderPosition;
const layerAOrder =
(layerA.metadata as ExtendedMetadata).layerOrderPosition ??
'basemap-background';
const layerBOrder =
(layerB.metadata as ExtendedMetadata).layerOrderPosition ??
'basemap-background';
const layerAIndex = LAYER_ORDER.indexOf(layerAOrder);
const layerBIndex = LAYER_ORDER.indexOf(layerBOrder);
const layerOrder = layerAIndex - layerBIndex;
const generatorA = stylesData[layerA.metadata?.generatorId];
const generatorB = stylesData[layerB.metadata?.generatorId];
const generatorA =
stylesData[(layerA.metadata as ExtendedMetadata).generatorId];
const generatorB =
stylesData[(layerB.metadata as ExtendedMetadata).generatorId];
const generatorOrder =
generatorA.params?.generatorOrder !== undefined &&
generatorB.params?.generatorOrder !== undefined
Expand Down Expand Up @@ -146,7 +158,7 @@ export function Styles({
Record<string, GeneratorStyleParams>
>({});

const [style, setStyle] = useState<Style>({
const [style, setStyle] = useState<StyleSpecification>({
version: DEFAULT_MAPBOX_STYLE_VERSION,
glyphs: DEFAULT_GLYPHS_SOURCE,
sprite: DEFAULT_SPRITE_SOURCE,
Expand Down
9 changes: 5 additions & 4 deletions app/scripts/components/common/map/types.d.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Feature, Polygon } from 'geojson';
import { AnyLayer, AnySourceImpl } from 'mapbox-gl';
import { LayerSpecification, SourceSpecification } from 'mapbox-gl';
import { ActionStatus } from '$utils/status';

export interface ExtendedMetadata {
layerOrderPosition?: LayerOrderPosition;
generatorId: string;
[key: string]: any;
}

export type ExtendedLayer = AnyLayer & {
metadata?: ExtendedMetadata;
export type ExtendedLayer = LayerSpecification & {
metadata?: ExtendedMetadata | unknown;
};

export interface BaseGeneratorParams {
Expand All @@ -19,7 +20,7 @@ export interface BaseGeneratorParams {
export interface GeneratorStyleParams {
generatorId: string;
layers: ExtendedLayer[];
sources: Record<string, AnySourceImpl>;
sources: Record<string, SourceSpecification>;
metadata?: Record<string, unknown>;
params?: BaseGeneratorParams;
}
Expand Down
8 changes: 5 additions & 3 deletions app/scripts/components/common/map/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ export function checkFitBoundsFromLayer(
if (!layerBounds || !mapInstance) return false;

const [minXLayer, minYLayer, maxXLayer, maxYLayer] = layerBounds;
const [[minXMap, minYMap], [maxXMap, maxYMap]] = mapInstance
.getBounds()
.toArray();
const bounds = mapInstance.getBounds();
if (!bounds) {
return false;
}
const [[minXMap, minYMap], [maxXMap, maxYMap]] = bounds.toArray();
const isOutside =
maxXLayer < minXMap ||
minXLayer > maxXMap ||
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useCallback, useEffect } from 'react';
import { useAtomValue } from 'jotai';
import styled, { css } from 'styled-components';
import { MapRef } from 'react-map-gl';
import { LngLatBoundsLike, MapRef } from 'react-map-gl';
import { glsp, themeVal } from '@devseed-ui/theme-provider';
import { Button, createButtonStyles } from '@devseed-ui/button';
import bbox from '@turf/bbox';
Expand Down
8 changes: 5 additions & 3 deletions app/scripts/components/exploration/components/map/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function ExplorationMap(props: ExplorationMapProps) {

// Check if there's layer information for this dataset.
const layerMetadata = style.layers.find(
(l) => l.metadata?.id === dataset.data.id
(l) => (l.metadata as { id: string }).id === dataset.data.id
);

// Skip if no metadata.
Expand All @@ -115,8 +115,10 @@ export function ExplorationMap(props: ExplorationMapProps) {
meta: {
...currentMeta,
tileUrls: {
wmtsTileUrl: layerMetadata.metadata.wmtsTileUrl,
xyzTileUrl: layerMetadata.metadata.xyzTileUrl
wmtsTileUrl: (layerMetadata.metadata as { wmtsTileUrl: string })
.wmtsTileUrl,
xyzTileUrl: (layerMetadata.metadata as { xyzTileUrl: string })
.xyzTileUrl
}
}
};
Expand Down
Loading

0 comments on commit 5e65894

Please sign in to comment.