diff --git a/.betterer.results b/.betterer.results index bacb77a2253..8c04156fcf0 100644 --- a/.betterer.results +++ b/.betterer.results @@ -2336,8 +2336,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "1"] ], "public/app/features/geo/utils/frameVectorSource.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Do not use any type assertions.", "1"] + [0, 0, 0, "Do not use any type assertions.", "0"] ], "public/app/features/inspector/InspectDataOptions.tsx:5381": [ [0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"], @@ -3760,9 +3759,6 @@ exports[`better eslint`] = { "public/app/plugins/panel/geomap/types.ts:5381": [ [0, 0, 0, "Do not re-export imported variable (\`./panelcfg.gen\`)", "0"] ], - "public/app/plugins/panel/geomap/utils/layers.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"] - ], "public/app/plugins/panel/geomap/utils/tooltip.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"] diff --git a/jest.config.js b/jest.config.js index 0882834ab48..0bee3d4cfe7 100644 --- a/jest.config.js +++ b/jest.config.js @@ -30,6 +30,11 @@ const esModules = [ 'react-data-grid', '@grafana/llm', 'pkce-challenge', + 'quickselect', + 'rbush', + 'earcut', + 'pbf', + 'geotiff', ].join('|'); module.exports = { diff --git a/package.json b/package.json index debaa94858a..231711d3d3b 100644 --- a/package.json +++ b/package.json @@ -371,7 +371,7 @@ "moveable": "0.53.0", "nanoid": "^5.0.9", "node-forge": "^1.3.1", - "ol": "7.4.0", + "ol": "10.6.0", "ol-ext": "4.0.33", "pluralize": "^8.0.0", "prismjs": "1.30.0", diff --git a/packages/grafana-data/package.json b/packages/grafana-data/package.json index 9d43bc9b4fa..64a027650c9 100644 --- a/packages/grafana-data/package.json +++ b/packages/grafana-data/package.json @@ -72,7 +72,7 @@ "marked-mangle": "1.1.11", "moment": "2.30.1", "moment-timezone": "0.5.47", - "ol": "7.4.0", + "ol": "10.6.0", "papaparse": "5.5.3", "react-use": "17.6.0", "rxjs": "7.8.2", diff --git a/packages/grafana-data/src/geo/layer.ts b/packages/grafana-data/src/geo/layer.ts index 18ed9b6a6df..ec522923e61 100644 --- a/packages/grafana-data/src/geo/layer.ts +++ b/packages/grafana-data/src/geo/layer.ts @@ -1,4 +1,4 @@ -import { Map as OpenLayersMap } from 'ol'; +import OpenLayersMap from 'ol/Map'; import BaseLayer from 'ol/layer/Base'; import { ReactNode } from 'react'; diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index a8fd784f58c..61f0d9a0d15 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -98,7 +98,7 @@ "micro-memoize": "^4.1.2", "moment": "2.30.1", "monaco-editor": "0.34.1", - "ol": "7.4.0", + "ol": "10.6.0", "prismjs": "1.30.0", "rc-cascader": "3.34.0", "rc-drawer": "7.3.0", diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx index ba5cc0749f1..c66ed4be81c 100644 --- a/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx +++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/TableCellActions.tsx @@ -1,5 +1,5 @@ -import { WKT } from 'ol/format'; -import { Geometry } from 'ol/geom'; +import WKT from 'ol/format/WKT'; +import Geometry from 'ol/geom/Geometry'; import { FieldType } from '@grafana/data'; import { t } from '@grafana/i18n'; diff --git a/public/app/features/geo/utils/frameVectorSource.ts b/public/app/features/geo/utils/frameVectorSource.ts index a996aa55f88..7642c2afd48 100644 --- a/public/app/features/geo/utils/frameVectorSource.ts +++ b/public/app/features/geo/utils/frameVectorSource.ts @@ -1,14 +1,24 @@ -import { Feature } from 'ol'; -import { Geometry, LineString, Point } from 'ol/geom'; +import Feature from 'ol/Feature'; +import { Geometry } from 'ol/geom'; import VectorSource from 'ol/source/Vector'; -import { DataFrame, Field } from '@grafana/data'; +import { DataFrame } from '@grafana/data'; import { getGeometryField, LocationFieldMatchers } from './location'; export interface FrameVectorSourceOptions {} -export class FrameVectorSource extends VectorSource { +// Helper function to create properly typed Features +function createFeature(properties: { + frame: DataFrame; + rowIndex: number; + geometry: T; +}): Feature { + const feature = new Feature(properties); + return feature; +} + +export class FrameVectorSource extends VectorSource> { constructor(public location: LocationFieldMatchers) { super({}); } @@ -22,11 +32,12 @@ export class FrameVectorSource extends VectorSour } for (let i = 0; i < frame.length; i++) { + const geometry = info.field.values[i] as T; this.addFeatureInternal( - new Feature({ + createFeature({ frame, rowIndex: i, - geometry: info.field.values[i] as T, + geometry, }) ); } @@ -34,27 +45,4 @@ export class FrameVectorSource extends VectorSour // only call this at the end this.changed(); } - - updateLineString(frame: DataFrame) { - this.clear(true); - const info = getGeometryField(frame, this.location); - if (!info.field) { - this.changed(); - return; - } - - //eslint-disable-next-line - const field = info.field as unknown as Field; - const geometry: Geometry = new LineString(field.values.map((p) => p.getCoordinates())); - this.addFeatureInternal( - new Feature({ - frame, - rowIndex: 0, - geometry: geometry as T, - }) - ); - - // only call this at the end - this.changed(); - } } diff --git a/public/app/plugins/panel/geomap/GeomapPanel.tsx b/public/app/plugins/panel/geomap/GeomapPanel.tsx index 9c406873728..14399a2893d 100644 --- a/public/app/plugins/panel/geomap/GeomapPanel.tsx +++ b/public/app/plugins/panel/geomap/GeomapPanel.tsx @@ -1,6 +1,8 @@ import { css } from '@emotion/css'; import { Global } from '@emotion/react'; -import { Map as OpenLayersMap, MapBrowserEvent, View } from 'ol'; +import OpenLayersMap from 'ol/Map'; +import MapBrowserEvent from 'ol/MapBrowserEvent'; +import View from 'ol/View'; import Attribution from 'ol/control/Attribution'; import ScaleLine from 'ol/control/ScaleLine'; import Zoom from 'ol/control/Zoom'; @@ -273,11 +275,11 @@ export class GeomapPanel extends Component { this.setState({ ttipOpen: false, ttip: undefined }); }; - pointerClickListener = (evt: MapBrowserEvent) => { + pointerClickListener = (evt: MapBrowserEvent) => { pointerClickListener(evt, this); }; - pointerMoveListener = (evt: MapBrowserEvent) => { + pointerMoveListener = (evt: MapBrowserEvent) => { pointerMoveListener(evt, this); }; diff --git a/public/app/plugins/panel/geomap/components/DebugOverlay.tsx b/public/app/plugins/panel/geomap/components/DebugOverlay.tsx index ae838fef89b..de267de908f 100644 --- a/public/app/plugins/panel/geomap/components/DebugOverlay.tsx +++ b/public/app/plugins/panel/geomap/components/DebugOverlay.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import { Map } from 'ol'; +import Map from 'ol/Map'; import { Coordinate } from 'ol/coordinate'; import { transform } from 'ol/proj'; import { PureComponent } from 'react'; diff --git a/public/app/plugins/panel/geomap/components/MeasureVectorLayer.ts b/public/app/plugins/panel/geomap/components/MeasureVectorLayer.ts index 0c6dc3ea15f..f1ff42c083d 100644 --- a/public/app/plugins/panel/geomap/components/MeasureVectorLayer.ts +++ b/public/app/plugins/panel/geomap/components/MeasureVectorLayer.ts @@ -200,24 +200,24 @@ export class MeasureVectorLayer extends VectorLayer { } const segmentPoint = new Point(segment.getCoordinateAt(0.5)); this.segmentStyles[count].setGeometry(segmentPoint); - this.segmentStyles[count].getText().setText(label); + this.segmentStyles[count].getText()?.setText(label); styles.push(this.segmentStyles[count]); count++; }); } if (label!) { this.labelStyle.setGeometry(point!); - this.labelStyle.getText().setText(label); + this.labelStyle.getText()?.setText(label); styles.push(this.labelStyle); } if ( tip && type === 'Point' && geometry instanceof Point && - !this.modify.getOverlay().getSource().getFeatures().length + !this.modify.getOverlay().getSource()?.getFeatures().length ) { this.tipPoint = geometry; - this.tipStyle.getText().setText(tip); + this.tipStyle.getText()?.setText(tip); styles.push(this.tipStyle); } } diff --git a/public/app/plugins/panel/geomap/layers/basemaps/carto.ts b/public/app/plugins/panel/geomap/layers/basemaps/carto.ts index 45f65b2b267..92f3c54502f 100644 --- a/public/app/plugins/panel/geomap/layers/basemaps/carto.ts +++ b/public/app/plugins/panel/geomap/layers/basemaps/carto.ts @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import TileLayer from 'ol/layer/Tile'; import XYZ from 'ol/source/XYZ'; @@ -33,7 +33,12 @@ export const carto: MapLayerRegistryItem = { * Function that configures transformation and returns a transformer * @param options */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => ({ + create: async ( + map: OpenLayersMap, + options: MapLayerOptions, + eventBus: EventBus, + theme: GrafanaTheme2 + ) => ({ init: () => { const cfg = { ...defaultCartoConfig, ...options.config }; let style: string | undefined = cfg.theme; diff --git a/public/app/plugins/panel/geomap/layers/basemaps/esri.ts b/public/app/plugins/panel/geomap/layers/basemaps/esri.ts index 87c3bb96170..b19e0e0679d 100644 --- a/public/app/plugins/panel/geomap/layers/basemaps/esri.ts +++ b/public/app/plugins/panel/geomap/layers/basemaps/esri.ts @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { MapLayerRegistryItem, MapLayerOptions, GrafanaTheme2, RegistryItem, Registry, EventBus } from '@grafana/data'; @@ -60,7 +60,12 @@ export const esriXYZTiles: MapLayerRegistryItem = { description: 'Add layer from an ESRI ArcGIS MapServer', isBaseMap: true, - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async ( + map: OpenLayersMap, + options: MapLayerOptions, + eventBus: EventBus, + theme: GrafanaTheme2 + ) => { const cfg = { ...options.config }; const svc = publicServiceRegistry.getIfExists(cfg.server ?? DEFAULT_SERVICE)!; if (svc.id !== CUSTOM_SERVICE) { diff --git a/public/app/plugins/panel/geomap/layers/basemaps/generic.ts b/public/app/plugins/panel/geomap/layers/basemaps/generic.ts index 1642465584c..2ed2a022037 100644 --- a/public/app/plugins/panel/geomap/layers/basemaps/generic.ts +++ b/public/app/plugins/panel/geomap/layers/basemaps/generic.ts @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import TileLayer from 'ol/layer/Tile'; import XYZ from 'ol/source/XYZ'; @@ -23,7 +23,12 @@ export const xyzTiles: MapLayerRegistryItem = { description: 'Add map from a generic tile layer', isBaseMap: true, - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => ({ + create: async ( + map: OpenLayersMap, + options: MapLayerOptions, + eventBus: EventBus, + theme: GrafanaTheme2 + ) => ({ init: () => { const cfg = { ...options.config }; if (!cfg.url) { diff --git a/public/app/plugins/panel/geomap/layers/basemaps/osm.ts b/public/app/plugins/panel/geomap/layers/basemaps/osm.ts index b826b79a0c4..c644702b1ca 100644 --- a/public/app/plugins/panel/geomap/layers/basemaps/osm.ts +++ b/public/app/plugins/panel/geomap/layers/basemaps/osm.ts @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; @@ -14,7 +14,7 @@ export const standard: MapLayerRegistryItem = { * Function that configures transformation and returns a transformer * @param options */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus) => ({ + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus) => ({ init: () => { return new TileLayer({ source: new OSM(), diff --git a/public/app/plugins/panel/geomap/layers/data/dayNightLayer.tsx b/public/app/plugins/panel/geomap/layers/data/dayNightLayer.tsx index 346c922900c..1908e147ca1 100644 --- a/public/app/plugins/panel/geomap/layers/data/dayNightLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/dayNightLayer.tsx @@ -1,5 +1,5 @@ import Feature from 'ol/Feature'; -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import Point from 'ol/geom/Point'; import { Group as LayerGroup } from 'ol/layer'; import VectorImage from 'ol/layer/VectorImage'; @@ -60,7 +60,7 @@ export const dayNightLayer: MapLayerRegistryItem = { * @param options * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultConfig, diff --git a/public/app/plugins/panel/geomap/layers/data/geojsonDynamic.ts b/public/app/plugins/panel/geomap/layers/data/geojsonDynamic.ts index 55f96810eb5..b09aa0a2576 100644 --- a/public/app/plugins/panel/geomap/layers/data/geojsonDynamic.ts +++ b/public/app/plugins/panel/geomap/layers/data/geojsonDynamic.ts @@ -1,5 +1,5 @@ import { FeatureLike } from 'ol/Feature'; -import OlMap from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { unByKey } from 'ol/Observable'; import GeoJSON from 'ol/format/GeoJSON'; import VectorImage from 'ol/layer/VectorImage'; @@ -78,7 +78,7 @@ export const dynamicGeoJSONLayer: MapLayerRegistryItem, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { const config = { ...defaultOptions, ...options.config }; const source = new VectorSource({ diff --git a/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts b/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts index 03ff6603504..b5d0a6da133 100644 --- a/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts +++ b/public/app/plugins/panel/geomap/layers/data/geojsonLayer.ts @@ -1,5 +1,5 @@ import { FeatureLike } from 'ol/Feature'; -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { unByKey } from 'ol/Observable'; import GeoJSON from 'ol/format/GeoJSON'; import VectorImage from 'ol/layer/VectorImage'; @@ -73,7 +73,7 @@ export const geojsonLayer: MapLayerRegistryItem = { * Function that configures transformation and returns a transformer * @param options */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { const config = { ...defaultOptions, ...options.config }; // Interpolate variables in the URL diff --git a/public/app/plugins/panel/geomap/layers/data/heatMap.tsx b/public/app/plugins/panel/geomap/layers/data/heatMap.tsx index 1ae068fc38a..9e1af30413d 100644 --- a/public/app/plugins/panel/geomap/layers/data/heatMap.tsx +++ b/public/app/plugins/panel/geomap/layers/data/heatMap.tsx @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { Point } from 'ol/geom'; import * as layer from 'ol/layer'; @@ -46,9 +46,11 @@ export const heatmapLayer: MapLayerRegistryItem = { /** * Function that configures transformation and returns a transformer + * @param map * @param options + * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { const config = { ...defaultOptions, ...options.config }; const location = await getLocationMatchers(options.location); diff --git a/public/app/plugins/panel/geomap/layers/data/lastPointTracker.ts b/public/app/plugins/panel/geomap/layers/data/lastPointTracker.ts index 300324d5539..42436808daf 100644 --- a/public/app/plugins/panel/geomap/layers/data/lastPointTracker.ts +++ b/public/app/plugins/panel/geomap/layers/data/lastPointTracker.ts @@ -1,5 +1,5 @@ import Feature from 'ol/Feature'; -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import * as layer from 'ol/layer'; import * as source from 'ol/source'; import * as style from 'ol/style'; @@ -25,9 +25,11 @@ export const lastPointTracker: MapLayerRegistryItem = { /** * Function that configures transformation and returns a transformer + * @param map * @param options + * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { const point = new Feature({}); const config = { ...defaultOptions, ...options.config }; diff --git a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx index d58446b9552..001177223ed 100644 --- a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx @@ -1,4 +1,4 @@ -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { Point } from 'ol/geom'; import { VectorImage } from 'ol/layer'; import LayerGroup from 'ol/layer/Group'; @@ -14,6 +14,7 @@ import { GrafanaTheme2, FrameGeometrySourceMode, EventBus, + PanelOptionsEditorBuilder, } from '@grafana/data'; import { t } from '@grafana/i18n'; import { FrameVectorSource } from 'app/features/geo/utils/frameVectorSource'; @@ -68,7 +69,7 @@ export const markersLayer: MapLayerRegistryItem = { * @param options * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultOptions, @@ -221,7 +222,7 @@ export const markersLayer: MapLayerRegistryItem = { }, // Marker overlay options - registerOptionsUI: (builder) => { + registerOptionsUI: (builder: PanelOptionsEditorBuilder>) => { builder .addCustomEditor({ id: 'config.style', diff --git a/public/app/plugins/panel/geomap/layers/data/networkLayer.tsx b/public/app/plugins/panel/geomap/layers/data/networkLayer.tsx index 733c938fd95..e6375e79159 100644 --- a/public/app/plugins/panel/geomap/layers/data/networkLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/networkLayer.tsx @@ -1,7 +1,6 @@ import { isNumber } from 'lodash'; -import { Feature } from 'ol'; -import { FeatureLike } from 'ol/Feature'; -import Map from 'ol/Map'; +import Feature, { FeatureLike } from 'ol/Feature'; +import OpenLayersMap from 'ol/Map'; import { Geometry, LineString, Point, SimpleGeometry } from 'ol/geom'; import VectorImage from 'ol/layer/VectorImage'; import { Fill, Stroke, Style, Text } from 'ol/style'; @@ -76,10 +75,9 @@ export const networkLayer: MapLayerRegistryItem = { * Function that configures transformation and returns a transformer * @param map * @param options - * @param eventBus * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultOptions, @@ -90,9 +88,8 @@ export const networkLayer: MapLayerRegistryItem = { const edgeStyle = await getStyleConfigState(config.edgeStyle); const location = await getLocationMatchers(options.location); const source = new FrameVectorSource(location); - const vectorLayer = new VectorImage({ - source, + source }); const hasArrows = config.arrow === 1 || config.arrow === -1 || config.arrow === 2; diff --git a/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx b/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx index ffd64aa03cd..86932984cc2 100644 --- a/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/photosLayer.tsx @@ -1,12 +1,21 @@ import { FeatureLike } from 'ol/Feature'; -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import VectorImage from 'ol/layer/VectorImage'; import { Stroke, Style } from 'ol/style'; import Photo from 'ol-ext/style/Photo'; -import { MapLayerRegistryItem, PanelData, GrafanaTheme2, EventBus, PluginState, FieldType, Field } from '@grafana/data'; +import { + MapLayerRegistryItem, + PanelData, + GrafanaTheme2, + EventBus, + PluginState, + FieldType, + Field, + MapLayerOptions, +} from '@grafana/data'; import { t } from '@grafana/i18n'; -import { FrameGeometrySourceMode, MapLayerOptions } from '@grafana/schema'; +import { FrameGeometrySourceMode } from '@grafana/schema'; import { findField } from 'app/features/dimensions/utils'; import { FrameVectorSource } from 'app/features/geo/utils/frameVectorSource'; import { getLocationMatchers } from 'app/features/geo/utils/location'; @@ -70,7 +79,7 @@ export const photosLayer: MapLayerRegistryItem = { * @param options * @param theme */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultOptions, diff --git a/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx b/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx index 366b687c5aa..16fd90076bd 100644 --- a/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/routeLayer.tsx @@ -1,6 +1,6 @@ import { isNumber } from 'lodash'; import Feature, { FeatureLike } from 'ol/Feature'; -import Map from 'ol/Map'; +import OpenLayersMap from 'ol/Map'; import { LineString, Point, SimpleGeometry } from 'ol/geom'; import { Group as LayerGroup } from 'ol/layer'; import VectorImage from 'ol/layer/VectorImage'; @@ -20,9 +20,10 @@ import { DataHoverClearEvent, DataFrame, FieldType, - colorManipulator + colorManipulator, + MapLayerOptions, } from '@grafana/data'; -import { MapLayerOptions, FrameGeometrySourceMode } from '@grafana/schema'; +import { FrameGeometrySourceMode } from '@grafana/schema'; import { FrameVectorSource } from 'app/features/geo/utils/frameVectorSource'; import { getGeometryField, getLocationMatchers } from 'app/features/geo/utils/location'; @@ -84,7 +85,7 @@ export const routeLayer: MapLayerRegistryItem = { * Function that configures transformation and returns a transformer * @param options */ - create: async (map: Map, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { + create: async (map: OpenLayersMap, options: MapLayerOptions, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultOptions, @@ -102,7 +103,7 @@ export const routeLayer: MapLayerRegistryItem = { const styleBase = routeStyle(style.base); if (style.config.size && style.config.size.fixed) { // Applies width to base style if specified - styleBase.getStroke().setWidth(style.config.size.fixed); + styleBase.getStroke()?.setWidth(style.config.size.fixed); } vectorLayer.setStyle(styleBase); } else { @@ -306,7 +307,30 @@ export const routeLayer: MapLayerRegistryItem = { style.dims = getStyleDimension(frame, style, theme); } - source.updateLineString(frame); + source.clear(true); + const info = getGeometryField(frame, location); + if (!info.field) { + source.changed(); + break; + } + const coords: number[][] = []; + for (const v of info.field.values) { + if (v instanceof Point) { + coords.push(v.getCoordinates()); + } + } + if (coords.length >= 2) { + const geometry = new LineString(coords); + source['addFeatureInternal']( + new Feature({ + frame, + rowIndex: 0, + geometry, + }) + ); + } + source.changed(); + break; // Only the first frame for now! } }, diff --git a/public/app/plugins/panel/geomap/layers/registry.ts b/public/app/plugins/panel/geomap/layers/registry.ts index 8657a55cb36..15e6fbb7861 100644 --- a/public/app/plugins/panel/geomap/layers/registry.ts +++ b/public/app/plugins/panel/geomap/layers/registry.ts @@ -1,4 +1,4 @@ -import { Map as OpenLayersMap } from 'ol'; +import OpenLayersMap from 'ol/Map'; import { MapLayerRegistryItem, diff --git a/public/app/plugins/panel/geomap/style/markers.test.ts b/public/app/plugins/panel/geomap/style/markers.test.ts index 610df9ebcf4..c7ce4cb845b 100644 --- a/public/app/plugins/panel/geomap/style/markers.test.ts +++ b/public/app/plugins/panel/geomap/style/markers.test.ts @@ -1,6 +1,14 @@ import { getPublicOrAbsoluteUrl } from 'app/features/dimensions/resource'; -import { getWebGLStyle } from './markers'; +import { + getWebGLStyle, + baseCircleStyle, + baseShapeStyle, + sizeExpression, + opacityExpression, + rotationExpression, + offsetExpression, +} from './markers'; // Mock dependencies jest.mock('app/features/dimensions/resource', () => ({ @@ -14,40 +22,30 @@ describe('getWebGLStyle', () => { it('returns default circle style when no symbol is provided', async () => { const result = await getWebGLStyle(); - expect(result).toEqual({ - symbol: { - symbolType: 'circle', - size: ['get', 'size', 'number'], - color: ['color', ['get', 'red'], ['get', 'green'], ['get', 'blue']], - offset: ['array', ['get', 'offsetX'], ['get', 'offsetY']], - rotation: ['get', 'rotation', 'number'], - opacity: ['get', 'opacity', 'number'], - }, - }); + expect(result).toEqual(baseCircleStyle); }); it('returns circle style for known WebGL regular shape', async () => { const result = await getWebGLStyle('img/icons/marker/circle.svg'); - if (result.symbol) { - expect(result.symbol.symbolType).toBe('circle'); - expect(result.symbol).not.toHaveProperty('src'); - } + expect(result).toEqual(baseCircleStyle); }); - it('returns square style for known WebGL regular shape', async () => { + it('returns shape style for square WebGL regular shape', async () => { const result = await getWebGLStyle('img/icons/marker/square.svg'); - if (result.symbol) { - expect(result.symbol.symbolType).toBe('square'); - expect(result.symbol).not.toHaveProperty('src'); - } + expect(result).toEqual({ + ...baseShapeStyle, + 'shape-points': 4, + 'shape-angle': Math.PI / 4, + }); }); - it('returns triangle style for known WebGL regular shape', async () => { + it('returns shape style for triangle WebGL regular shape', async () => { const result = await getWebGLStyle('img/icons/marker/triangle.svg'); - if (result.symbol) { - expect(result.symbol.symbolType).toBe('triangle'); - expect(result.symbol).not.toHaveProperty('src'); - } + expect(result).toEqual({ + ...baseShapeStyle, + 'shape-points': 3, + 'shape-angle': 0, + }); }); it('returns image style with src for custom SVG symbol', async () => { @@ -62,10 +60,12 @@ describe('getWebGLStyle', () => { } as Response) ); const result = await getWebGLStyle('test.svg'); - if (result.symbol) { - expect(result.symbol.symbolType).toBe('image'); - expect(result.symbol.src).toContain('data:image/svg+xml'); - } + expect(result['icon-src']).toContain('data:image/svg+xml'); + expect(result['icon-width']).toEqual(sizeExpression); + expect(result['icon-height']).toEqual(sizeExpression); + expect(result['icon-opacity']).toEqual(opacityExpression); + expect(result['icon-rotation']).toEqual(rotationExpression); + expect(result['icon-displacement']).toEqual(offsetExpression); }); it('includes background circle with opacity-adjusted stroke when opacity is provided', async () => { @@ -79,12 +79,10 @@ describe('getWebGLStyle', () => { } as Response) ); const result = await getWebGLStyle('custom.svg', 0.5); - if (result.symbol?.src) { - expect(result.symbol.symbolType).toBe('image'); - expect(result.symbol.src).toContain('circle'); - const decodedSrc = decodeURIComponent(result.symbol.src); - expect(decodedSrc).toContain('stroke="rgba(255,255,255,0.2)"'); // 0.1 / 0.5 = 0.2 - } + const iconSrc = result['icon-src'] as string; + expect(iconSrc).toContain('circle'); + const decodedSrc = decodeURIComponent(iconSrc); + expect(decodedSrc).toContain('stroke="rgba(255,255,255,0.2)"'); // 0.1 / 0.5 = 0.2 }); it('handles fetch error gracefully', async () => { @@ -94,10 +92,8 @@ describe('getWebGLStyle', () => { (getPublicOrAbsoluteUrl as jest.Mock).mockReturnValue('error.svg'); global.fetch = jest.fn(() => Promise.reject(new Error('Fetch failed'))); const result = await getWebGLStyle('error.svg'); - if (result.symbol) { - expect(result.symbol.symbolType).toBe('image'); - expect(result.symbol.src).toBe(''); // Empty SVG - } + expect(result['icon-src']).toBe(''); // Empty SVG + // Verify console.error was called with the expected error expect(consoleErrorSpy).toHaveBeenCalledWith(new Error('Fetch failed')); diff --git a/public/app/plugins/panel/geomap/style/markers.ts b/public/app/plugins/panel/geomap/style/markers.ts index b54e3fd54f6..fd8682866ca 100644 --- a/public/app/plugins/panel/geomap/style/markers.ts +++ b/public/app/plugins/panel/geomap/style/markers.ts @@ -1,5 +1,5 @@ import { Fill, RegularShape, Stroke, Circle, Style, Icon, Text } from 'ol/style'; -import { LiteralStyle } from 'ol/style/literal'; +import type { FlatStyle } from 'ol/style/flat'; import tinycolor from 'tinycolor2'; import { Registry, RegistryItem, textUtil } from '@grafana/data'; @@ -32,12 +32,6 @@ const MarkerShapePath = { x: 'img/icons/marker/x-mark.svg', }; -const WebGLRegularShapes: Record = { - circle: 'img/icons/marker/circle.svg', - square: 'img/icons/marker/square.svg', - triangle: 'img/icons/marker/triangle.svg', -}; - export function getFillColor(cfg: StyleConfigValues) { const opacity = cfg.opacity == null ? 0.8 : cfg.opacity; if (opacity === 1) { @@ -319,34 +313,75 @@ export function getMarkerAsPath(shape?: string): string | undefined { return undefined; } -// Returns literal style for WebGL markers -export async function getWebGLStyle(symbol?: string, opacity?: number): Promise { - // style expressions - const symbolStyle: LiteralStyle = { - symbol: { - symbolType: 'circle', - size: ['get', 'size', 'number'], - color: ['color', ['get', 'red'], ['get', 'green'], ['get', 'blue']], - offset: ['array', ['get', 'offsetX'], ['get', 'offsetY']], - rotation: ['get', 'rotation', 'number'], - opacity: ['get', 'opacity', 'number'], - }, - }; - // set symbolType and src if a symbol is provided - if (symbol && symbolStyle.symbol) { - const imageString = 'image'; - const symbolType = Object.keys(WebGLRegularShapes).find((key) => WebGLRegularShapes[key] === symbol) ?? imageString; - symbolStyle.symbol = { ...symbolStyle.symbol, symbolType }; - if (symbolType === imageString) { - const backgroundOpacity = opacity === 0 ? 0 : 0.1 / (opacity ?? 1); - symbolStyle.symbol = { - ...symbolStyle.symbol, - src: await prepareSVG(getPublicOrAbsoluteUrl(symbol), undefined, backgroundOpacity), - }; - } +// Common expressions used across different style types +export const colorExpression = ['color', ['get', 'red'], ['get', 'green'], ['get', 'blue'], ['get', 'opacity']]; +export const sizeExpression = ['get', 'size']; +export const opacityExpression = ['get', 'opacity']; +export const rotationExpression = ['get', 'rotation']; +export const offsetExpression = ['array', ['get', 'offsetX'], ['get', 'offsetY']]; + +// Base style for regular shapes +export const baseShapeStyle = { + 'shape-radius': ['/', sizeExpression, 2], + 'shape-fill-color': colorExpression, + 'shape-stroke-color': colorExpression, + 'shape-stroke-width': 1, + 'shape-opacity': opacityExpression, + 'shape-rotation': rotationExpression, + 'shape-displacement': offsetExpression, +}; + +// Base style for circles +export const baseCircleStyle = { + 'circle-radius': ['/', sizeExpression, 2], + 'circle-fill-color': colorExpression, + 'circle-stroke-color': colorExpression, + 'circle-stroke-width': 1, + 'circle-opacity': opacityExpression, + 'circle-displacement': offsetExpression, +}; + +// Returns style configuration for WebGL markers +export async function getWebGLStyle(symbol?: string, opacity?: number): Promise { + // Handle circle explicitly (before generic SVG check) + if (symbol === MarkerShapePath.circle) { + return baseCircleStyle; } - return symbolStyle; + // Handle square as WebGL regular shape + if (symbol === MarkerShapePath.square) { + return { + ...baseShapeStyle, + 'shape-points': 4, + 'shape-angle': Math.PI / 4, + }; + } + + // Handle triangle as WebGL regular shape + if (symbol === MarkerShapePath.triangle) { + return { + ...baseShapeStyle, + 'shape-points': 3, + 'shape-angle': 0, + }; + } + + // Handle custom SVG symbols and other shapes as icons + if (symbol && symbol.endsWith('.svg')) { + const backgroundOpacity = opacity === 0 ? 0 : 0.1 / (opacity ?? 1); + return { + 'icon-src': await prepareSVG(getPublicOrAbsoluteUrl(symbol), undefined, backgroundOpacity), + 'icon-width': sizeExpression, + 'icon-height': sizeExpression, + 'icon-opacity': opacityExpression, + 'icon-rotation': rotationExpression, + 'icon-displacement': offsetExpression, + 'icon-color': colorExpression, + }; + } + + // Default to circle (also handles MarkerShapePath.circle) + return baseCircleStyle; } // Will prepare symbols as necessary @@ -388,7 +423,7 @@ export async function getMarkerMaker(symbol?: string, hasTextLabel?: boolean): P image: new RegularShape({ fill: new Fill({ color: 'rgba(0,0,0,0)' }), points: 4, - radius: cfg.size, + radius: radius, rotation: (rotation * Math.PI) / 180 + Math.PI / 4, }), }), diff --git a/public/app/plugins/panel/geomap/types.ts b/public/app/plugins/panel/geomap/types.ts index 22804bc6b29..2ef58f6e65e 100644 --- a/public/app/plugins/panel/geomap/types.ts +++ b/public/app/plugins/panel/geomap/types.ts @@ -1,5 +1,5 @@ -import { Map as OpenLayersMap } from 'ol'; import { FeatureLike } from 'ol/Feature'; +import OpenLayersMap from 'ol/Map'; import { Units } from 'ol/control/ScaleLine'; import BaseLayer from 'ol/layer/Base'; import { Subject } from 'rxjs'; diff --git a/public/app/plugins/panel/geomap/utils/checkFeatureMatchesStyleRule.test.ts b/public/app/plugins/panel/geomap/utils/checkFeatureMatchesStyleRule.test.ts index 7dc2d839ea0..60e90245fba 100644 --- a/public/app/plugins/panel/geomap/utils/checkFeatureMatchesStyleRule.test.ts +++ b/public/app/plugins/panel/geomap/utils/checkFeatureMatchesStyleRule.test.ts @@ -1,4 +1,4 @@ -import { Feature } from 'ol'; +import Feature from 'ol/Feature'; import { ComparisonOperation } from '@grafana/schema'; diff --git a/public/app/plugins/panel/geomap/utils/getFeatures.test.ts b/public/app/plugins/panel/geomap/utils/getFeatures.test.ts index 0b2b31a3f45..787503a5eff 100644 --- a/public/app/plugins/panel/geomap/utils/getFeatures.test.ts +++ b/public/app/plugins/panel/geomap/utils/getFeatures.test.ts @@ -1,4 +1,4 @@ -import { Feature } from 'ol'; +import Feature from 'ol/Feature'; import { Point } from 'ol/geom'; import { GeometryTypeId } from '../style/types'; diff --git a/public/app/plugins/panel/geomap/utils/layers.ts b/public/app/plugins/panel/geomap/utils/layers.ts index 8c20a95ad0f..a6e9ecbbff0 100644 --- a/public/app/plugins/panel/geomap/utils/layers.ts +++ b/public/app/plugins/panel/geomap/utils/layers.ts @@ -1,5 +1,6 @@ -import { Map as OpenLayersMap } from 'ol'; import { FeatureLike } from 'ol/Feature'; +import OpenLayersMap from 'ol/Map'; +import BaseLayer from 'ol/layer/Base'; import LayerGroup from 'ol/layer/Group'; import WebGLPointsLayer from 'ol/layer/WebGLPoints'; import { Subject } from 'rxjs'; @@ -14,6 +15,8 @@ import { MapLayerState } from '../types'; import { getNextLayerName } from './utils'; +const layerStateMap = new WeakMap(); + export const applyLayerFilter = ( handler: MapLayerHandler, options: MapLayerOptions, @@ -148,18 +151,16 @@ export async function initLayer( }; panel.byName.set(UID, state); - // eslint-disable-next-line - (state.layer as any).__state = state; + layerStateMap.set(state.layer, state); // Pass state into WebGLPointsLayers contained in a LayerGroup if (layer instanceof LayerGroup) { layer .getLayers() .getArray() - .forEach((layer) => { + .forEach((layer: BaseLayer) => { if (layer instanceof WebGLPointsLayer) { - // eslint-disable-next-line - (layer as any).__state = state; + layerStateMap.set(layer, state); } }); } @@ -169,6 +170,6 @@ export async function initLayer( return state; } -export const getMapLayerState = (l: any): MapLayerState => { - return l?.__state; +export const getMapLayerState = (l: BaseLayer | undefined): MapLayerState | undefined => { + return l ? layerStateMap.get(l) : undefined; }; diff --git a/public/app/plugins/panel/geomap/utils/tooltip.test.ts b/public/app/plugins/panel/geomap/utils/tooltip.test.ts index a5b721da7d4..3f006391ad6 100644 --- a/public/app/plugins/panel/geomap/utils/tooltip.test.ts +++ b/public/app/plugins/panel/geomap/utils/tooltip.test.ts @@ -1,4 +1,5 @@ -import { Feature, MapBrowserEvent } from 'ol'; +import Feature from 'ol/Feature'; +import MapBrowserEvent from 'ol/MapBrowserEvent'; import { Point } from 'ol/geom'; import WebGLPointsLayer from 'ol/layer/WebGLPoints'; import VectorSource from 'ol/source/Vector'; @@ -55,9 +56,9 @@ jest.mock('./layers', () => { describe('tooltip utils', () => { let panel: GeomapPanel; - let mockEvent: MapBrowserEvent; - let mockWebGLLayer: WebGLPointsLayer>; - let mockVectorSource: VectorSource; + let mockEvent: MapBrowserEvent; + let mockWebGLLayer: WebGLPointsLayer>>; + let mockVectorSource: VectorSource>; // Consolidated feature constants let feature1: Feature; @@ -72,12 +73,15 @@ describe('tooltip utils', () => { // Create mock objects panel = new GeomapPanel({} as PanelProps); + + // Create a proper MouseEvent instance to pass the instanceof check + const mouseEvent = new MouseEvent('pointermove'); + Object.defineProperty(mouseEvent, 'pageX', { value: 100 }); + Object.defineProperty(mouseEvent, 'pageY', { value: 100 }); + mockEvent = { - originalEvent: { - pageX: 100, - pageY: 100, - }, - } as MapBrowserEvent; + originalEvent: mouseEvent, + } as MapBrowserEvent; // Create features for testing feature1 = new Feature({ @@ -111,19 +115,16 @@ describe('tooltip utils', () => { }); // Create mock vector source - mockVectorSource = new VectorSource(); + mockVectorSource = new VectorSource>(); mockVectorSource.forEachFeature = jest.fn(); // Create mock WebGL layer mockWebGLLayer = new WebGLPointsLayer({ source: mockVectorSource, style: { - symbol: { - symbolType: 'circle', - size: 8, - color: '#000000', - opacity: 1, - }, + 'circle-radius': 8, + 'circle-fill-color': '#000000', + 'circle-opacity': 1, }, }); mockWebGLLayer.getSource = jest.fn().mockReturnValue(mockVectorSource); diff --git a/public/app/plugins/panel/geomap/utils/tooltip.ts b/public/app/plugins/panel/geomap/utils/tooltip.ts index 81ed086afac..05ed7e781f6 100644 --- a/public/app/plugins/panel/geomap/utils/tooltip.ts +++ b/public/app/plugins/panel/geomap/utils/tooltip.ts @@ -1,6 +1,6 @@ import { debounce } from 'lodash'; -import { MapBrowserEvent } from 'ol'; import { FeatureLike } from 'ol/Feature'; +import MapBrowserEvent from 'ol/MapBrowserEvent'; import { Point } from 'ol/geom'; import WebGLPointsLayer from 'ol/layer/WebGLPoints'; import { toLonLat } from 'ol/proj'; @@ -16,14 +16,17 @@ import { getMapLayerState } from './layers'; export const setTooltipListeners = (panel: GeomapPanel) => { // Tooltip listener - panel.map?.on('singleclick', panel.pointerClickListener); - panel.map?.on('pointermove', debounce(panel.pointerMoveListener, 200)); + panel.map?.on('singleclick', (evt) => pointerClickListener(evt, panel)); + panel.map?.on( + 'pointermove', + debounce((evt) => pointerMoveListener(evt, panel), 200) + ); panel.map?.getViewport().addEventListener('mouseout', (evt: MouseEvent) => { panel.props.eventBus.publish(new DataHoverClearEvent()); }); }; -export const pointerClickListener = (evt: MapBrowserEvent, panel: GeomapPanel) => { +export const pointerClickListener = (evt: MapBrowserEvent, panel: GeomapPanel) => { if (pointerMoveListener(evt, panel)) { evt.preventDefault(); evt.stopPropagation(); @@ -32,7 +35,7 @@ export const pointerClickListener = (evt: MapBrowserEvent, panel: Ge } }; -export const pointerMoveListener = (evt: MapBrowserEvent, panel: GeomapPanel) => { +export const pointerMoveListener = (evt: MapBrowserEvent, panel: GeomapPanel) => { // If measure menu is open, bypass tooltip logic and display measuring mouse events if (panel.state.measureMenuActive) { return true; @@ -43,6 +46,10 @@ export const pointerMoveListener = (evt: MapBrowserEvent, panel: Geo return false; } + if (!(evt.originalEvent instanceof MouseEvent)) { + return false; + } + const mouse = evt.originalEvent; const pixel = panel.map.getEventPixel(mouse); const hover = toLonLat(panel.map.getCoordinateFromPixel(pixel)); diff --git a/public/app/plugins/panel/geomap/utils/utils.test.ts b/public/app/plugins/panel/geomap/utils/utils.test.ts index 44995c1857f..6ea2c428435 100644 --- a/public/app/plugins/panel/geomap/utils/utils.test.ts +++ b/public/app/plugins/panel/geomap/utils/utils.test.ts @@ -38,8 +38,8 @@ import { hasVariableDependencies, hasLayerData } from './utils'; // Test fixtures const createTestFeature = () => new Feature(new Point([0, 0])); -const createTestVectorSource = (hasFeature = false): VectorSource => { - const source = new VectorSource(); +const createTestVectorSource = (hasFeature = false): VectorSource> => { + const source = new VectorSource>(); if (hasFeature) { source.addFeature(createTestFeature()); } @@ -47,12 +47,9 @@ const createTestVectorSource = (hasFeature = false): VectorSource => { }; const createTestWebGLStyle = () => ({ - symbol: { - symbolType: 'circle', - size: 8, - color: '#000000', - opacity: 1, - }, + 'circle-radius': 8, + 'circle-fill-color': '#000000', + 'circle-opacity': 1, }); describe('hasVariableDependencies', () => { diff --git a/public/app/plugins/panel/geomap/utils/utils.ts b/public/app/plugins/panel/geomap/utils/utils.ts index 615466f339a..f3efa3c1b4f 100644 --- a/public/app/plugins/panel/geomap/utils/utils.ts +++ b/public/app/plugins/panel/geomap/utils/utils.ts @@ -1,4 +1,5 @@ -import { Map as OpenLayersMap } from 'ol'; +import Feature from 'ol/Feature'; +import OpenLayersMap from 'ol/Map'; import Geometry from 'ol/geom/Geometry'; import Point from 'ol/geom/Point'; import { defaults as interactionDefaults } from 'ol/interaction'; @@ -178,9 +179,9 @@ export const isUrl = (url: string) => { export function hasLayerData( layer: | LayerGroup - | VectorLayer> - | VectorImage> - | WebGLPointsLayer> + | VectorLayer>> + | VectorImage>> + | WebGLPointsLayer>> | TileLayer | ImageLayer | BaseLayer diff --git a/yarn.lock b/yarn.lock index cdd4a49083c..a86de0b5b0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3094,7 +3094,7 @@ __metadata: marked-mangle: "npm:1.1.11" moment: "npm:2.30.1" moment-timezone: "npm:0.5.47" - ol: "npm:7.4.0" + ol: "npm:10.6.0" papaparse: "npm:5.5.3" react: "npm:18.3.1" react-dom: "npm:18.3.1" @@ -3771,7 +3771,7 @@ __metadata: monaco-editor: "npm:0.34.1" msw: "npm:^2.10.2" msw-storybook-addon: "npm:^2.0.5" - ol: "npm:7.4.0" + ol: "npm:10.6.0" prismjs: "npm:1.30.0" process: "npm:^0.11.10" rc-cascader: "npm:3.34.0" @@ -5010,48 +5010,6 @@ __metadata: languageName: node linkType: hard -"@mapbox/jsonlint-lines-primitives@github:mapbox/jsonlint#commit=e31b7289baedf3e1000d7ae7edd42268212c9954": - version: 2.0.2 - resolution: "@mapbox/jsonlint-lines-primitives@https://github.com/mapbox/jsonlint.git#commit=e31b7289baedf3e1000d7ae7edd42268212c9954" - checksum: 10/660bd93beac97f0f4bdcfbbded3282efaf2ab4debb99da55f7fb7b27250e0dfa7dd572a9040802fdc008c71d0bb5ff7e565a7426177fda6c3d17e9bf1598bbaf - languageName: node - linkType: hard - -"@mapbox/mapbox-gl-style-spec@npm:^13.23.1": - version: 13.25.0 - resolution: "@mapbox/mapbox-gl-style-spec@npm:13.25.0" - dependencies: - "@mapbox/jsonlint-lines-primitives": "npm:~2.0.2" - "@mapbox/point-geometry": "npm:^0.1.0" - "@mapbox/unitbezier": "npm:^0.0.0" - csscolorparser: "npm:~1.0.2" - json-stringify-pretty-compact: "npm:^2.0.0" - minimist: "npm:^1.2.5" - rw: "npm:^1.3.3" - sort-object: "npm:^0.3.2" - bin: - gl-style-composite: bin/gl-style-composite.js - gl-style-format: bin/gl-style-format.js - gl-style-migrate: bin/gl-style-migrate.js - gl-style-validate: bin/gl-style-validate.js - checksum: 10/cabd9629bde72fe961f9a9d957534f75eb74bddb10068bf7b43fa73868eeb857a31196a12dc2a4532ab732bc7d38392e9bd4582fa9021ef9a5c3465e964201d2 - languageName: node - linkType: hard - -"@mapbox/point-geometry@npm:^0.1.0": - version: 0.1.0 - resolution: "@mapbox/point-geometry@npm:0.1.0" - checksum: 10/f6f78ac8a7f798efb19db6eb1a9e05da7ba942102f5347c1a673d94202d0c606ec3f522efa3e76d583cdca46fb96dde52c3d37234f162d21df42f9e8c4f182bd - languageName: node - linkType: hard - -"@mapbox/unitbezier@npm:^0.0.0": - version: 0.0.0 - resolution: "@mapbox/unitbezier@npm:0.0.0" - checksum: 10/211fc5b0a40fafa0127baf87938a6a00535b22b51bec95df2f6141cf1dd50339bca2a9729c7a9803cdee5c2b4e0e3323a882655c74f1a86e557096684196e1ff - languageName: node - linkType: hard - "@mdx-js/react@npm:^3.0.0": version: 3.0.1 resolution: "@mdx-js/react@npm:3.0.1" @@ -9867,6 +9825,13 @@ __metadata: languageName: node linkType: hard +"@types/rbush@npm:4.0.0": + version: 4.0.0 + resolution: "@types/rbush@npm:4.0.0" + checksum: 10/ee37c7fa322a83af4e754180022253b7e2bbbb853c9a6d8ffce1ea1e59bbb0eef3a347e2f37934bb1afa4d40ea2ea44409d7cee751cb8ac8dbded13dc9160a64 + languageName: node + linkType: hard + "@types/react-color@npm:3.0.13": version: 3.0.13 resolution: "@types/react-color@npm:3.0.13" @@ -14083,13 +14048,6 @@ __metadata: languageName: node linkType: hard -"csscolorparser@npm:~1.0.2": - version: 1.0.3 - resolution: "csscolorparser@npm:1.0.3" - checksum: 10/b46b9032eaace69e5bb151bb64473547d8e48813b45395c1923cde1c87674bbd030c99536f44373e092de6afdca1a8134933a1503e779aaeb703b7c7897f5eca - languageName: node - linkType: hard - "cssesc@npm:^3.0.0": version: 3.0.0 resolution: "cssesc@npm:3.0.0" @@ -15357,10 +15315,10 @@ __metadata: languageName: node linkType: hard -"earcut@npm:^2.2.3": - version: 2.2.4 - resolution: "earcut@npm:2.2.4" - checksum: 10/ca8b24714cc2fa67f98fbca6ddcf64bb42ee8d75d0b4f1a81486b3282b0f7f1bf9ec49ad4d02149985886a0c8a03a173463f2acb1f51fa0bb7ba2e1d4aa1254d +"earcut@npm:^3.0.0": + version: 3.0.1 + resolution: "earcut@npm:3.0.1" + checksum: 10/92786b5a35276a099eb2545bd7183e31a8ddd34f0d24d26eb26a280bcf7d35dcf5a01cd8712343bfbe504849229d01ff4771aa4ed0d8d900083afaa01d732b5c languageName: node linkType: hard @@ -17582,9 +17540,9 @@ __metadata: languageName: node linkType: hard -"geotiff@npm:^2.0.7": - version: 2.0.7 - resolution: "geotiff@npm:2.0.7" +"geotiff@npm:^2.1.3": + version: 2.1.3 + resolution: "geotiff@npm:2.1.3" dependencies: "@petamoriken/float16": "npm:^3.4.7" lerc: "npm:^3.0.0" @@ -17593,7 +17551,8 @@ __metadata: quick-lru: "npm:^6.1.1" web-worker: "npm:^1.2.0" xml-utils: "npm:^1.0.2" - checksum: 10/7d309ef9e7fee0aef39117ef045cf35d30be91621e0df643cd86d363519907706bdc6e0f6f4dc2ebcc0ce085eab18fd5801aca9c162606cdd293c7b616070d1a + zstddec: "npm:^0.1.0" + checksum: 10/91475680b882c11e6c28b4538c8703da03a13fa1b3f8f9d456aa3b274cb71fb01f04aadb29006c3a607c20b724b936a95899ad8ef65d26a11eed59ba9f81c61f languageName: node linkType: hard @@ -18376,7 +18335,7 @@ __metadata: node-forge: "npm:^1.3.1" node-notifier: "npm:10.0.1" nx: "npm:20.7.1" - ol: "npm:7.4.0" + ol: "npm:10.6.0" ol-ext: "npm:4.0.33" openapi-types: "npm:^12.1.3" pa11y-ci: "npm:^3.1.0" @@ -19304,7 +19263,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.1.12, ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10/d9f2557a59036f16c282aaeb107832dc957a93d73397d89bbad4eb1130560560eb695060145e8e6b3b498b15ab95510226649a0b8f52ae06583575419fe10fc4 @@ -21347,13 +21306,6 @@ __metadata: languageName: node linkType: hard -"json-stringify-pretty-compact@npm:^2.0.0": - version: 2.0.0 - resolution: "json-stringify-pretty-compact@npm:2.0.0" - checksum: 10/08f2725eef0a37bfd554aaa1ce551bc973e13f2c3dc86dd40b10ae6c08b3851b84946db672877e994e1fd1d904a578941c176609864e4f1a48b6d8f51fc2ac5f - languageName: node - linkType: hard - "json-stringify-safe@npm:^5.0.1, json-stringify-safe@npm:~5.0.1": version: 5.0.1 resolution: "json-stringify-safe@npm:5.0.1" @@ -22413,13 +22365,6 @@ __metadata: languageName: node linkType: hard -"mapbox-to-css-font@npm:^2.4.1": - version: 2.4.1 - resolution: "mapbox-to-css-font@npm:2.4.1" - checksum: 10/224fc0f39a2f546bbe5b69a67a4e8c54928606cac44490650ee711723747edb393b4936c0005bcc72cb12f70b31fab50078a65e3e27e0f3e7d65f1ab8a3a253b - languageName: node - linkType: hard - "marked-mangle@npm:1.1.11": version: 1.1.11 resolution: "marked-mangle@npm:1.1.11" @@ -24164,27 +24109,16 @@ __metadata: languageName: node linkType: hard -"ol-mapbox-style@npm:^10.1.0": +"ol@npm:10.6.0": version: 10.6.0 - resolution: "ol-mapbox-style@npm:10.6.0" + resolution: "ol@npm:10.6.0" dependencies: - "@mapbox/mapbox-gl-style-spec": "npm:^13.23.1" - mapbox-to-css-font: "npm:^2.4.1" - ol: "npm:^7.3.0" - checksum: 10/069421f5260b6d7b02e6f753eef5e9e10d3a86df8fe425aab1317b5e3d75684709b4b506e4c47e9840abeb503066c64a73dd29ec4a1cf65a8cbc484e91c70bfb - languageName: node - linkType: hard - -"ol@npm:7.4.0, ol@npm:^7.3.0": - version: 7.4.0 - resolution: "ol@npm:7.4.0" - dependencies: - earcut: "npm:^2.2.3" - geotiff: "npm:^2.0.7" - ol-mapbox-style: "npm:^10.1.0" - pbf: "npm:3.2.1" - rbush: "npm:^3.0.1" - checksum: 10/c83698fddd02fdd497e92bffee7ca7d4059f64d28a0be7a7781981f129b6636cacbee894aed331a572f066fe1e56a4cf22861c51e1efddb7fbb58c4bf5606ece + "@types/rbush": "npm:4.0.0" + earcut: "npm:^3.0.0" + geotiff: "npm:^2.1.3" + pbf: "npm:4.0.1" + rbush: "npm:^4.0.0" + checksum: 10/942fe6c0b55b24a6b1538d78ad221962476bfcba5b1316f427235d50aa817ca5ed805e8d3b5c6129b5da245ba0b66cd8bf359403230bb939648a1a78bffb0ca3 languageName: node linkType: hard @@ -25090,15 +25024,14 @@ __metadata: languageName: node linkType: hard -"pbf@npm:3.2.1": - version: 3.2.1 - resolution: "pbf@npm:3.2.1" +"pbf@npm:4.0.1": + version: 4.0.1 + resolution: "pbf@npm:4.0.1" dependencies: - ieee754: "npm:^1.1.12" resolve-protobuf-schema: "npm:^2.1.0" bin: pbf: bin/pbf - checksum: 10/566a64424063b07f46d3e2cb2288094a60b0a45efea48fd4030f527143b0e9c611399ebd3a6fd56db51908f2006defef5e09a1b2a027db9481a59a41156a540c + checksum: 10/9e2821fec1511cdaacf205c1279a33991119a2b8469208071d22e6204162dc8a4d216f647ce92759601e3d685fa913d4739278a86aa9ac126d04a1a3ac66bf12 languageName: node linkType: hard @@ -26222,10 +26155,10 @@ __metadata: languageName: node linkType: hard -"quickselect@npm:^2.0.0": - version: 2.0.0 - resolution: "quickselect@npm:2.0.0" - checksum: 10/ed2e78431050d223fb75da20ee98011aef1a03f7cb04e1a32ee893402e640be3cfb76d72e9dbe01edf3bb457ff6a62e5c2d85748424d1aa531f6ba50daef098c +"quickselect@npm:^3.0.0": + version: 3.0.0 + resolution: "quickselect@npm:3.0.0" + checksum: 10/8f72bedb8bb14bce5c3767c55f567bc296fa3ca9d98ba385e3867e434463bc633feee1eddf3dfec17914b7e88feeb08c7b313cf47114a8ff11bf964f77f51cfc languageName: node linkType: hard @@ -26321,12 +26254,12 @@ __metadata: languageName: node linkType: hard -"rbush@npm:^3.0.1": - version: 3.0.1 - resolution: "rbush@npm:3.0.1" +"rbush@npm:^4.0.0": + version: 4.0.1 + resolution: "rbush@npm:4.0.1" dependencies: - quickselect: "npm:^2.0.0" - checksum: 10/489e2e7d9889888ad533518f194e3ab7cc19b1f1365a38ee99fbdda542a47f41cda7dc89870180050f4d04ea402e9ff294e1d767d03c0f1694e0028b7609eec9 + quickselect: "npm:^3.0.0" + checksum: 10/8db2f9b464ee31cbb13237e762140c27f4de517a470d1639f840cc606b1f917f64f6273178b2f07c93d95c44cc068cc0c25c84ad40c4a483404e60d17c054eec languageName: node linkType: hard @@ -28334,7 +28267,7 @@ __metadata: languageName: node linkType: hard -"rw@npm:1, rw@npm:^1.3.3": +"rw@npm:1": version: 1.3.3 resolution: "rw@npm:1.3.3" checksum: 10/e90985d64777a00f4ab5f8c0bfea2fb5645c6bda5238840afa339c8a4f86f776e8ce83731155643a7425a0b27ce89077dab27b2f57519996ba4d2fe54cac1941 @@ -29335,20 +29268,6 @@ __metadata: languageName: node linkType: hard -"sort-asc@npm:^0.1.0": - version: 0.1.0 - resolution: "sort-asc@npm:0.1.0" - checksum: 10/c130223336a9431edd4c12cf0a4893eb9327591f8c9d9ccd1b27a42f7657b4bb84807d7150d79fc52ab7d1e9691684897de7ef2a6a3516d32349af68d2705d57 - languageName: node - linkType: hard - -"sort-desc@npm:^0.1.1": - version: 0.1.1 - resolution: "sort-desc@npm:0.1.1" - checksum: 10/f2a2568f4eaf9a7315700ae9e46e74ae7b395f24323bf807f07b20269a7c162b549b0bac6d5bb8e26f7ee15af72a74fdaf09d47257227dbe31c4ac8f13b19e1d - languageName: node - linkType: hard - "sort-keys@npm:^2.0.0": version: 2.0.0 resolution: "sort-keys@npm:2.0.0" @@ -29367,16 +29286,6 @@ __metadata: languageName: node linkType: hard -"sort-object@npm:^0.3.2": - version: 0.3.2 - resolution: "sort-object@npm:0.3.2" - dependencies: - sort-asc: "npm:^0.1.0" - sort-desc: "npm:^0.1.1" - checksum: 10/701fac8b49e9c720f4e5f4b70e995a795771dbecab2368b2e362c5c02cc269418a061f3303c47137d22fc3fe1ded03b4fd4215edec0960c4721274d320dae2b4 - languageName: node - linkType: hard - "source-list-map@npm:^2.0.0, source-list-map@npm:^2.0.1": version: 2.0.1 resolution: "source-list-map@npm:2.0.1" @@ -33037,3 +32946,10 @@ __metadata: checksum: 10/0e35432dcca7f053e63f5dd491a87c78abe0d981817547252c3b6d05f0f58788695d1a69724759c6501dff3fd62929be24c9f314a3625179bee889150f7a61fa languageName: node linkType: hard + +"zstddec@npm:^0.1.0": + version: 0.1.0 + resolution: "zstddec@npm:0.1.0" + checksum: 10/818d7a7b910509bed32a5ae42352dc45e87e4ee8470c27352859824540efceb9643864afbbb93564beb76822d72a946a6ee7cfbf01627ee34a1cd9656f2857b8 + languageName: node + linkType: hard