@opengeoweb/core 14.3.0 → 14.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/index.esm.js +1727 -1212
  2. package/package.json +13 -11
  3. package/src/lib/components/ComponentsLookUp/componentsLookUp.d.ts +2 -3
  4. package/src/lib/components/ConfigurableMapConnect/ConfigurableMapConnect.d.ts +1 -0
  5. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/Menubutton/MenuButton.d.ts +2 -0
  6. package/src/lib/components/LocationSearch/types.d.ts +9 -0
  7. package/src/lib/components/LocationSearch/utils.d.ts +4 -0
  8. package/src/lib/components/MapOptions/FeatureInfo/GetFeatureInfoDialog.spec.d.ts +1 -0
  9. package/src/lib/components/MapOptions/MapOptionsButtonConnect.d.ts +8 -0
  10. package/src/lib/components/MapOptions/MeasureTool/MeasureToolButton.d.ts +7 -0
  11. package/src/lib/components/MapOptions/MeasureTool/index.d.ts +2 -0
  12. package/src/lib/components/MapOptions/index.d.ts +4 -0
  13. package/src/lib/components/MapViewConnect/OlMapViewConnect.d.ts +1 -0
  14. package/src/lib/utils/location-api/fakeApi.d.ts +32 -2
  15. package/src/lib/utils/location-api/hooks.d.ts +1 -1
  16. /package/src/lib/components/{FeatureInfo/GetFeatureInfoButtonConnect.spec.d.ts → LocationSearch/Utils.spec.d.ts} +0 -0
  17. /package/src/lib/components/{FeatureInfo → MapOptions/FeatureInfo}/GetFeatureInfoButtonConnect.d.ts +0 -0
  18. /package/src/lib/components/{FeatureInfo/GetFeatureInfoConnect.spec.d.ts → MapOptions/FeatureInfo/GetFeatureInfoButtonConnect.spec.d.ts} +0 -0
  19. /package/src/lib/components/{FeatureInfo → MapOptions/FeatureInfo}/GetFeatureInfoConnect.d.ts +0 -0
  20. /package/src/lib/components/{FeatureInfo/GetFeatureInfoDialog.spec.d.ts → MapOptions/FeatureInfo/GetFeatureInfoConnect.spec.d.ts} +0 -0
  21. /package/src/lib/components/{FeatureInfo → MapOptions/FeatureInfo}/GetFeatureInfoDialog.d.ts +0 -0
  22. /package/src/lib/components/{FeatureInfo → MapOptions/FeatureInfo}/index.d.ts +0 -0
  23. /package/src/lib/components/{FeatureInfo → MapOptions/FeatureInfo}/utils.d.ts +0 -0
package/index.esm.js CHANGED
@@ -2,29 +2,31 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import React__default, { useMemo, useState, useCallback, useEffect, useContext } from 'react';
4
4
  import { Grid, Box, MenuItem, Typography, useTheme, Popper, Fade, ListItem, ListItemButton, ListItemText, ListItemIcon, Checkbox, Tooltip, styled, LinearProgress, FormControl, InputLabel, Paper, List, CircularProgress, ListSubheader, DialogContentText, TextField, InputAdornment, Button, Autocomplete, Switch, Select } from '@mui/material';
5
- import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, CustomIconButton, CustomTooltip, TooltipSelect, AlertIcon, useScrollingInIsolation, sliderHeaderStyle, CustomSlider, ToggleMenu, tooltipContainerStyles, renderCounter, AlertBanner, CustomAccordion, useConfirmationDialog, CustomDialog, PROJECTION, calculateStartSize, useWheelStopPropagation, ToolContainerDraggable, useDebounce, sessionStorageProvider, usePrevious, dateUtils, ErrorBoundary } from '@opengeoweb/shared';
6
- import { CollapseSmall, CollapseMedium, CollapseLarge, CollapseWindow, ExpandWindow, LayersAdd, CloudLoading, ColumnCollapsed, ColumnCollapse, Copy, None, FastForward, AutoUpdateActive, Both, Delete, Visibility, VisibilityOff, DragHandle as DragHandle$1, Cached, Add, MapAdd, WorldMapProjection, Overlayers, Layers, ExitDomain, Info, Search, Exclamation, MyLocation, Close, ThemeWrapper, lightTheme, FlagBritain, FlagNetherlands, FlagFinland, FlagNorway } from '@opengeoweb/theme';
5
+ import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, CustomIconButton, CustomTooltip, TooltipSelect, AlertIcon, useScrollingInIsolation, sliderHeaderStyle, CustomSlider, ToggleMenu, tooltipContainerStyles, renderCounter, AlertBanner, CustomAccordion, useConfirmationDialog, CustomDialog, PROJECTION, calculateStartSize, useWheelStopPropagation, ToolContainerDraggable, sessionStorageProvider, useDebounce, usePrevious, dateUtils, ErrorBoundary } from '@opengeoweb/shared';
6
+ import { CollapseSmall, CollapseMedium, CollapseLarge, CollapseWindow, ExpandWindow, LayersAdd, CloudLoading, ColumnCollapsed, ColumnCollapse, Copy, Delete, None, FastForward, AutoUpdateActive, Both, Visibility, VisibilityOff, DragHandle as DragHandle$1, Cached, Add, MapAdd, WorldMapProjection, Overlayers, Layers, Search, Exclamation, MyLocation, Airplane, Region, Pinned, Close, ExitDomain, LocationInfo, Measure, Options, Info, ThemeWrapper, lightTheme, FlagBritain, FlagNetherlands, FlagFinland, FlagNorway } from '@opengeoweb/theme';
7
7
  import i18n from 'i18next';
8
8
  import { useTranslation, I18nextProvider } from 'react-i18next';
9
9
  import { TIME_SLIDER_NAMESPACE, timesliderTranslations, defaultTimeSpan, BackwardForwardStepButton, PlayButton, defaultTimeStep, AutoUpdateButton, NowButton, handleSetNowEvent, ControlButtons, TimeSpanButton, secondsPerPxFromCanvasWidth, getNewCenterOfFixedPointZoom, TimeStepButton, SpeedButton, AnimationLengthButton, AnimationLength, OptionsMenu, TimeSliderClock, OptionsMenuButton, TimeSliderButtons, TimeSliderCurrentTimeBox, TimeSliderLegend, onsetNewDateDebounced, defaultSecondsPerPx, moveSelectedTimePx, TimeSlider, getFilteredTime } from '@opengeoweb/time-slider';
10
- import { webmapReactTranslations, WEBMAP_REACT_NAMESPACE, webmapTranslations, WEBMAP_NAMESPACE, openLayersGetMapImageStore, LayerInfoButton, useEDRGetCollectionDetails, defaultEdrStyles, LayerInfoDialog, MapControlButton, MapDimensionSelect, dimensionConfig, DimensionSelectDialog, DimensionSelectButton, LegendDialog, LegendButton, MapContext, emptyGeoJSON, MapFeatureClass, setMapCenter, OpenLayersFeatureLayer, OpenLayersMapDraw, makeTimeList, getIsInsideAcceptanceTime, OpenLayersLayer, useSetIntervalWhenVisible, TimeContext, OpenLayersMapView, WMSLayer, genericOpenLayersFeatureStyle, OpenLayersGetFeatureInfo, MapControls, OpenLayersZoomControl, getLayerUpdateInfo, publicLayers } from '@opengeoweb/webmap-react';
10
+ import { webmapReactTranslations, WEBMAP_REACT_NAMESPACE, webmapTranslations, WEBMAP_NAMESPACE, openLayersGetMapImageStore, LayerInfoButton, useEDRGetCollectionDetails, defaultEdrStyles, LayerInfoDialog, MapControlButton, MapDimensionSelect, dimensionConfig, DimensionSelectDialog, DimensionSelectButton, LegendDialog, LegendButton, MapContext, emptyGeoJSON, MapFeatureClass, setMapCenter, OpenLayersFeatureLayer, OpenLayersMapDraw, makeTimeList, getIsInsideAcceptanceTime, OpenLayersLayer, MapMeasure, useSetIntervalWhenVisible, TimeContext, OpenLayersMapView, WMSLayer, genericOpenLayersFeatureStyle, OpenLayersGetFeatureInfo, MapControls, OpenLayersZoomControl, getLayerUpdateInfo, publicLayers } from '@opengeoweb/webmap-react';
11
11
  import { useDispatch, useSelector, connect, useStore, Provider } from 'react-redux';
12
12
  import { ReactSortable } from 'react-sortablejs';
13
13
  import Sortable from 'sortablejs';
14
14
  import { layerTypes, layerSelectors, layerActions, loadingIndicatorSelectors, layerUtils, mapSelectors, serviceSelectors, serviceActions, mapActions, mapEnums, uiSelectors, uiTypes, useSetupDialog, filterLayers, getUserAddedServices, uiActions, drawingToolSelectors, syncGroupsSelectors, syncConstants, getViewObjectForSyncGroup, getViewObjectForMapId, loadingIndicatorActions, genericSelectors, genericActions, defaultLayers, getSingularDrawtoolDrawLayerId, syncGroupsSelector, syncGroupsActions, routerUtils, mapUtils } from '@opengeoweb/store';
15
- import { webmapUtils, LayerType, queryWMSServiceInfo, queryWMSLayers, queryWMSLayersTree, invalidateWMSGetCapabilities, getWMSServiceId, getMapDimURL, generateLayerId, WMJSDimension, getWMLayerById, handleDateUtilsISOString, WMLayer } from '@opengeoweb/webmap';
16
- import _, { isArray, isEqual, throttle, range } from 'lodash';
17
- import { Box as Box$1, styled as styled$1 } from '@mui/system';
15
+ import { webmapUtils, LayerType, queryWMSServiceInfo, queryWMSLayers, queryWMSLayersTree, invalidateWMSGetCapabilities, getWMSServiceId, generateLayerId, WMJSDimension, getMapDimURL, getWMLayerById, handleDateUtilsISOString, WMLayer } from '@opengeoweb/webmap';
16
+ import _, { isArray, range, zip, isEqual, throttle } from 'lodash';
17
+ import { Box as Box$1, Stack, styled as styled$1 } from '@mui/system';
18
18
  import { LayerSelectButtonConnect, LayerSelectConnect, DataExplorerButtonConnect } from '@opengeoweb/layer-select';
19
19
  import { unByKey } from 'ol/Observable';
20
- import axios from 'axios';
21
- import { ImageWMS } from 'ol/source';
22
- import DOMPurify from 'dompurify';
23
20
  import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
24
21
  import { handleResponse } from '@opengeoweb/api';
22
+ import * as turf from '@turf/turf';
23
+ import proj4 from 'proj4';
25
24
  import GeoJSON from 'ol/format/GeoJSON';
26
25
  import { toLonLat } from 'ol/proj';
27
26
  import { getIntersection } from 'ol/extent';
27
+ import axios from 'axios';
28
+ import { ImageWMS } from 'ol/source';
29
+ import DOMPurify from 'dompurify';
28
30
  import { snackbarTypes, snackbarActions, SnackbarWrapperConnect } from '@opengeoweb/snackbar';
29
31
  import { useNavigate } from 'react-router-dom';
30
32
  import * as Sentry from '@sentry/react';
@@ -69,6 +71,8 @@ var en = {
69
71
  "layermanager-layer-leading-both": "Both",
70
72
  "layermanager-layer-delete": "Delete",
71
73
  "layermanager-layer-duplicate": "Duplicate layer",
74
+ "layermanager-layer-duplicate-to-other-maps": "Copy layer to other maps",
75
+ "layermanager-layer-remove-from-other-maps": "Remove layer from other maps",
72
76
  "layermanager-options": "Options",
73
77
  "layermanager-baselayers-tooltip": "Add base layers",
74
78
  "layermanager-header-button-small": "small",
@@ -88,6 +92,9 @@ var en = {
88
92
  "search-my-location": "Find my location",
89
93
  "search-title-long": "Find location, area, postal code, GPS, ...",
90
94
  "search-no-results": "No results",
95
+ "search-airports": "Airports",
96
+ "search-countries-regions-cities": "Countries/Regions/Cities",
97
+ "search-places": "Places",
91
98
  "my-location": "My location",
92
99
  "search-clear": "Clear",
93
100
  "syncgroups-title": "Sync",
@@ -122,7 +129,9 @@ var en = {
122
129
  "delete-dialog-title": "Delete layer",
123
130
  "delete-dialog-description": "Are you sure you want to delete this layer? EDR layers are not yet available in the Layer Select.",
124
131
  "delete-dialog-cancel": "Cancel",
125
- "delete-dialog-confirm": "Delete"
132
+ "delete-dialog-confirm": "Delete",
133
+ "map-options-button": "Location or Measuring tool",
134
+ "map-measure-tool": "Measuring tool"
126
135
  };
127
136
  var fi = {
128
137
  feature_info_title: "Napsauta karttaa nähdäksesi lisätietoja.",
@@ -156,6 +165,8 @@ var fi = {
156
165
  "layermanager-layer-leading-both": "Molemmat",
157
166
  "layermanager-layer-delete": "Poista",
158
167
  "layermanager-layer-duplicate": "Monista karttataso",
168
+ "layermanager-layer-duplicate-to-other-maps": "Kopioi karttataso muihin karttoihin",
169
+ "layermanager-layer-remove-from-other-maps": "Poista karttataso muista kartoista",
159
170
  "layermanager-options": "Valinnat",
160
171
  "layermanager-baselayers-tooltip": "Lisää pohjakartta",
161
172
  "layermanager-header-button-small": "Pieni",
@@ -174,6 +185,9 @@ var fi = {
174
185
  "search-my-location": "Etsi sijaintini",
175
186
  "search-title-long": "Find location, area, postal code, GPS, ...",
176
187
  "search-no-results": "No results",
188
+ "search-airports": "Lentokentät",
189
+ "search-countries-regions-cities": "Maat/Alueet/Kaupungit",
190
+ "search-places": "Paikat",
177
191
  "my-location": "My location",
178
192
  "search-clear": "Clear",
179
193
  "syncgroups-title": "Sync",
@@ -237,6 +251,8 @@ var no = {
237
251
  "layermanager-layer-leading-both": "Begge",
238
252
  "layermanager-layer-delete": "Slett",
239
253
  "layermanager-layer-duplicate": "Duplikat lag",
254
+ "layermanager-layer-duplicate-to-other-maps": "Kopier lag til andre kart",
255
+ "layermanager-layer-remove-from-other-maps": "Fjern lag fra andre kart",
240
256
  "layermanager-options": "Laginnstillinger",
241
257
  "layermanager-baselayers-tooltip": "Legg til basislag",
242
258
  "layermanager-header-button-small": "liten",
@@ -255,6 +271,9 @@ var no = {
255
271
  "search-my-location": "Finn min lokasjon",
256
272
  "search-title-long": "Find location, area, postal code, GPS, ...",
257
273
  "search-no-results": "No results",
274
+ "search-airports": "Flyplasser",
275
+ "search-countries-regions-cities": "Land/Regioner/Byer",
276
+ "search-places": "Steder",
258
277
  "my-location": "Min lokasjon",
259
278
  "search-clear": "Clear",
260
279
  "syncgroups-title": "Synkroniser",
@@ -318,6 +337,8 @@ var nl = {
318
337
  "layermanager-layer-leading-both": "Beide",
319
338
  "layermanager-layer-delete": "Verwijderen",
320
339
  "layermanager-layer-duplicate": "Dupliceren",
340
+ "layermanager-layer-duplicate-to-other-maps": "Kopieer laag naar andere kaarten",
341
+ "layermanager-layer-remove-from-other-maps": "Verwijder laag van andere kaarten",
321
342
  "layermanager-options": "Opties",
322
343
  "layermanager-baselayers-tooltip": "Basislagen toevoegen",
323
344
  "layermanager-header-button-small": "klein",
@@ -336,6 +357,9 @@ var nl = {
336
357
  "search-my-location": "Vind mijn locatie",
337
358
  "search-title-long": "Vind locatie, gebied, postcode, GPS, ...",
338
359
  "search-no-results": "Geen resultaten",
360
+ "search-airports": "Luchthavens",
361
+ "search-countries-regions-cities": "Landen/Regio’s/Steden",
362
+ "search-places": "Plaatsen",
339
363
  "my-location": "Mijn locatie",
340
364
  "search-clear": "Wissen",
341
365
  "syncgroups-title": "Synchroniseren",
@@ -369,7 +393,9 @@ var nl = {
369
393
  "delete-dialog-title": "Laag verwijderen",
370
394
  "delete-dialog-description": "Weet je zeker dat je deze laag wilt verwijderen? EDR lagen zijn nog niet beschikbaar in de Layer Select.",
371
395
  "delete-dialog-cancel": "Annuleren",
372
- "delete-dialog-confirm": "Verwijderen"
396
+ "delete-dialog-confirm": "Verwijderen",
397
+ "map-options-button": "Locatie informatie en Meten",
398
+ "map-measure-tool": "Meten"
373
399
  };
374
400
  var coreTranslations = {
375
401
  en: en,
@@ -1059,7 +1085,7 @@ var LayerSelectButton = function LayerSelectButton(_ref) {
1059
1085
  });
1060
1086
  };
1061
1087
 
1062
- var _excluded$5 = ["settings", "addLayerComponent", "onToggleCollapsed", "collapsedColumns"];
1088
+ var _excluded$6 = ["settings", "addLayerComponent", "onToggleCollapsed", "collapsedColumns"];
1063
1089
  var RowItemCollapse$1 = function RowItemCollapse(_ref) {
1064
1090
  var className = _ref.className,
1065
1091
  title = _ref.title,
@@ -1123,7 +1149,7 @@ var DescriptionRow = function DescriptionRow(_ref2) {
1123
1149
  _ref2$onToggleCollaps = _ref2.onToggleCollapsed,
1124
1150
  onToggleCollapsed = _ref2$onToggleCollaps === void 0 ? function () {} : _ref2$onToggleCollaps,
1125
1151
  collapsedColumns = _ref2.collapsedColumns,
1126
- gridProps = _objectWithoutPropertiesLoose(_ref2, _excluded$5);
1152
+ gridProps = _objectWithoutPropertiesLoose(_ref2, _excluded$6);
1127
1153
  var _useCoreTranslation2 = useCoreTranslation(),
1128
1154
  t = _useCoreTranslation2.t;
1129
1155
  return jsxs(Grid, Object.assign({
@@ -1816,6 +1842,8 @@ var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1816
1842
  _ref$isFeatureLayer = _ref.isFeatureLayer,
1817
1843
  isFeatureLayer = _ref$isFeatureLayer === void 0 ? false : _ref$isFeatureLayer,
1818
1844
  onLayerDuplicate = _ref.onLayerDuplicate,
1845
+ onLayerCopyToOtherMaps = _ref.onLayerCopyToOtherMaps,
1846
+ onLayerRemoveFromOtherMaps = _ref.onLayerRemoveFromOtherMaps,
1819
1847
  tooltipTitle = _ref.tooltipTitle,
1820
1848
  icon = _ref.icon;
1821
1849
  var _useCoreTranslation = useCoreTranslation(),
@@ -1827,6 +1855,12 @@ var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1827
1855
  layerId: layerId
1828
1856
  });
1829
1857
  };
1858
+ var onClickCopyToOtherMaps = function onClickCopyToOtherMaps() {
1859
+ onLayerCopyToOtherMaps && onLayerCopyToOtherMaps();
1860
+ };
1861
+ var onClickRemoveFromOtherMaps = function onClickRemoveFromOtherMaps() {
1862
+ onLayerRemoveFromOtherMaps && onLayerRemoveFromOtherMaps();
1863
+ };
1830
1864
  return jsx(ToggleMenu, {
1831
1865
  buttonTestId: "openMenuButton",
1832
1866
  buttonSx: {
@@ -1841,6 +1875,14 @@ var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1841
1875
  text: t('layermanager-layer-duplicate'),
1842
1876
  action: onClickDuplicate,
1843
1877
  icon: jsx(Copy, {})
1878
+ }, {
1879
+ text: t('layermanager-layer-duplicate-to-other-maps'),
1880
+ action: onClickCopyToOtherMaps,
1881
+ icon: jsx(Copy, {})
1882
+ }, {
1883
+ text: t('layermanager-layer-remove-from-other-maps'),
1884
+ action: onClickRemoveFromOtherMaps,
1885
+ icon: jsx(Delete, {})
1844
1886
  }],
1845
1887
  tooltipTitle: nonEmptyTooltipTitle,
1846
1888
  buttonIcon: icon,
@@ -3181,6 +3223,10 @@ var RenderFeatureLayers = function RenderFeatureLayers(_ref) {
3181
3223
  });
3182
3224
  };
3183
3225
 
3226
+ var formatParameterTitle = function formatParameterTitle(baseTitle, parameterKey) {
3227
+ var title = baseTitle + " (" + parameterKey;
3228
+ return title.length > 100 ? title.substring(0, 100) + "...)" : title + ")";
3229
+ };
3184
3230
  var RenderLayersConnect = function RenderLayersConnect(_ref) {
3185
3231
  var layerId = _ref.layerId,
3186
3232
  mapId = _ref.mapId,
@@ -3263,9 +3309,11 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
3263
3309
  }
3264
3310
  var layers = Object.entries(data == null ? void 0 : data.parameter_names).map(function (parameter) {
3265
3311
  var _ref3, _parameter$1$label;
3312
+ var parameterTitle = (_ref3 = (_parameter$1$label = parameter[1].label) != null ? _parameter$1$label : parameter[1].description) != null ? _ref3 : parameter[0];
3313
+ var title = formatParameterTitle(parameterTitle, parameter[0]);
3266
3314
  return {
3267
3315
  name: parameter[0],
3268
- title: (_ref3 = (_parameter$1$label = parameter[1].label) != null ? _parameter$1$label : parameter[1].description) != null ? _ref3 : parameter[0],
3316
+ title: title,
3269
3317
  styles: defaultEdrStyles,
3270
3318
  leaf: true,
3271
3319
  path: []
@@ -3357,9 +3405,52 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3357
3405
  return layerSelectors.getLayerType(store, layerId);
3358
3406
  });
3359
3407
  var isFeatureLayer = layerType === LayerType.featureLayer;
3360
- var duplicateLayer = React.useCallback(function (_ref2) {
3361
- var newLayerId = _ref2.newLayerId,
3362
- mapId = _ref2.mapId;
3408
+ // get all map ids
3409
+ var allMapIds = useSelector(mapSelectors.getAllMapIds);
3410
+ var allOtherMapIdsExceptCurrentOne = allMapIds.filter(function (id) {
3411
+ return id !== mapId;
3412
+ });
3413
+ var allLayers = useSelector(layerSelectors.getAllLayers);
3414
+ var copyLayerToOtherMaps = React.useCallback(function () {
3415
+ // generate new layer ids
3416
+ var newLayerIds = range(allOtherMapIdsExceptCurrentOne.length).map(function (_) {
3417
+ return webmapUtils.generateLayerId();
3418
+ });
3419
+ // run all duplicateLayer calls in a loop
3420
+ zip(allOtherMapIdsExceptCurrentOne, newLayerIds).forEach(function (_ref2) {
3421
+ var newMapId = _ref2[0],
3422
+ newLayerId = _ref2[1];
3423
+ if (!newMapId || !layerId || !newLayerId) {
3424
+ return;
3425
+ }
3426
+ dispatch(layerActions.duplicateMapLayer({
3427
+ mapId: newMapId,
3428
+ oldLayerId: layerId,
3429
+ newLayerId: newLayerId,
3430
+ origin: layerTypes.LayerActionOrigin.layerManager
3431
+ }));
3432
+ });
3433
+ }, [allOtherMapIdsExceptCurrentOne, dispatch, layerId]);
3434
+ var removeLayerFromAllMaps = React.useCallback(function () {
3435
+ var _allLayers$find;
3436
+ if (!layerId) {
3437
+ return;
3438
+ }
3439
+ var layerName = (_allLayers$find = allLayers.find(function (layer) {
3440
+ return layer.id === layerId;
3441
+ })) == null ? void 0 : _allLayers$find.name;
3442
+ layerName && allLayers.filter(function (layer) {
3443
+ return layer.name === layerName && layer.mapId !== mapId;
3444
+ }).forEach(function (layer) {
3445
+ layer.mapId && layer.id && dispatch(layerActions.layerDelete({
3446
+ mapId: layer.mapId,
3447
+ layerId: layer.id
3448
+ }));
3449
+ });
3450
+ }, [dispatch, allLayers, mapId, layerId]);
3451
+ var duplicateLayer = React.useCallback(function (_ref3) {
3452
+ var newLayerId = _ref3.newLayerId,
3453
+ mapId = _ref3.mapId;
3363
3454
  return dispatch(layerActions.duplicateMapLayer({
3364
3455
  mapId: mapId,
3365
3456
  oldLayerId: layerId,
@@ -3377,6 +3468,8 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3377
3468
  mapId: mapId
3378
3469
  });
3379
3470
  },
3471
+ onLayerCopyToOtherMaps: copyLayerToOtherMaps,
3472
+ onLayerRemoveFromOtherMaps: removeLayerFromAllMaps,
3380
3473
  tooltipTitle: tooltipTitle,
3381
3474
  icon: icon
3382
3475
  });
@@ -3635,12 +3728,12 @@ var MissingDataConnect = function MissingDataConnect(_ref) {
3635
3728
  });
3636
3729
  };
3637
3730
 
3638
- var _excluded$4 = ["layerId", "mapId", "dimensionsToShow"];
3731
+ var _excluded$5 = ["layerId", "mapId", "dimensionsToShow"];
3639
3732
  var CustomDimensionSelectConnect = function CustomDimensionSelectConnect(_ref) {
3640
3733
  var layerId = _ref.layerId,
3641
3734
  mapId = _ref.mapId,
3642
3735
  dimensionsToShow = _ref.dimensionsToShow,
3643
- props = _objectWithoutPropertiesLoose(_ref, _excluded$4);
3736
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
3644
3737
  var _useLayerDimensions = useLayerDimensions(layerId, mapId),
3645
3738
  layerDimensions = _useLayerDimensions.layerDimensions,
3646
3739
  isLayerEnabled = _useLayerDimensions.isLayerEnabled,
@@ -3887,12 +3980,12 @@ var DragHandle = function DragHandle(_ref) {
3887
3980
  });
3888
3981
  };
3889
3982
 
3890
- var _excluded$3 = ["mapId", "settings", "collapsedColumns"];
3983
+ var _excluded$4 = ["mapId", "settings", "collapsedColumns"];
3891
3984
  var LayerContainerRow = /*#__PURE__*/React.memo(function (_ref) {
3892
3985
  var mapId = _ref.mapId,
3893
3986
  settings = _ref.settings,
3894
3987
  collapsedColumns = _ref.collapsedColumns,
3895
- gridProps = _objectWithoutPropertiesLoose(_ref, _excluded$3);
3988
+ gridProps = _objectWithoutPropertiesLoose(_ref, _excluded$4);
3896
3989
  var dispatch = useDispatch();
3897
3990
  var _React$useTransition = React.useTransition(),
3898
3991
  isPending = _React$useTransition[0],
@@ -5002,7 +5095,7 @@ var AddLayersButton = function AddLayersButton(_ref) {
5002
5095
  });
5003
5096
  };
5004
5097
 
5005
- var _excluded$2 = ["mapId", "preloadedAvailableBaseLayers", "preloadedServices", "tooltip", "settings"];
5098
+ var _excluded$3 = ["mapId", "preloadedAvailableBaseLayers", "preloadedServices", "tooltip", "settings"];
5006
5099
  var _onRenderTree = function onRenderTree(_ref) {
5007
5100
  var service = _ref.service,
5008
5101
  mapId = _ref.mapId,
@@ -5023,7 +5116,7 @@ var BaseLayerRow = function BaseLayerRow(_ref2) {
5023
5116
  _ref2$tooltip = _ref2.tooltip,
5024
5117
  tooltip = _ref2$tooltip === void 0 ? '' : _ref2$tooltip,
5025
5118
  settings = _ref2.settings,
5026
- gridProps = _objectWithoutPropertiesLoose(_ref2, _excluded$2);
5119
+ gridProps = _objectWithoutPropertiesLoose(_ref2, _excluded$3);
5027
5120
  var theme = useTheme();
5028
5121
  return jsxs(Grid, Object.assign({
5029
5122
  container: true,
@@ -5969,6 +6062,219 @@ var MultiMapMultiDimensionSelectConnect = function MultiMapMultiDimensionSelectC
5969
6062
  });
5970
6063
  };
5971
6064
 
6065
+ var _excluded$2 = ["showMapId"];
6066
+ var LegendConnectComponent = function LegendConnectComponent(_ref) {
6067
+ var _ref$showMapId = _ref.showMapId,
6068
+ showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
6069
+ _ref$source = _ref.source,
6070
+ source = _ref$source === void 0 ? 'app' : _ref$source,
6071
+ _ref$mapId = _ref.mapId,
6072
+ initialMapId = _ref$mapId === void 0 ? null : _ref$mapId,
6073
+ _ref$multiLegend = _ref.multiLegend,
6074
+ multiLegend = _ref$multiLegend === void 0 ? false : _ref$multiLegend;
6075
+ var legendType = multiLegend ? "legend-" + initialMapId : "legend";
6076
+ var mapIdStore = useSelector(function (store) {
6077
+ return uiSelectors.getDialogMapId(store, legendType);
6078
+ });
6079
+ var _React$useState = React.useState(initialMapId),
6080
+ mapId = _React$useState[0],
6081
+ setMapId = _React$useState[1];
6082
+ React.useEffect(function () {
6083
+ setMapId(mapIdStore);
6084
+ }, [mapIdStore]);
6085
+ var mapLayers = useSelector(function (store) {
6086
+ return mapSelectors.getMapLayers(store, mapId);
6087
+ });
6088
+ var _useSetupDialog = useSetupDialog(legendType, source),
6089
+ dialogOrder = _useSetupDialog.dialogOrder,
6090
+ isDialogOpen = _useSetupDialog.isDialogOpen,
6091
+ uiSource = _useSetupDialog.uiSource,
6092
+ setDialogOrder = _useSetupDialog.setDialogOrder,
6093
+ onCloseDialog = _useSetupDialog.onCloseDialog;
6094
+ return jsx(LegendDialog, {
6095
+ layers: mapLayers,
6096
+ isOpen: isDialogOpen,
6097
+ onClose: onCloseDialog,
6098
+ mapId: mapId,
6099
+ showMapId: showMapId,
6100
+ onMouseDown: setDialogOrder,
6101
+ order: dialogOrder,
6102
+ source: uiSource
6103
+ });
6104
+ };
6105
+ /**
6106
+ * Legend component connected to the store displaying a legend for every layer shown on the active map Id
6107
+ * Please note that in order to use this and open/close the dialog, every map on the screen that should be able to show
6108
+ * a dialog should have the <LegendMapButtonConnect/> which is used to focus the correct map and open the dialog
6109
+ *
6110
+ * Expects the following props:
6111
+ * @param {boolean} showMapId (optional) showMapId: boolean - show the id of the map in the dialog title of which the legend is shown in te dialog
6112
+ * @param {uiTypes.Source} source (optional) source: uiTypes.Source - default is 'app', 'module' makes sure it will be shown on top of the module
6113
+
6114
+ * ``` <LegendConnect legendDialogId={legendDialogId} />```
6115
+ */
6116
+ var LegendConnect = function LegendConnect(_ref2) {
6117
+ var _ref2$showMapId = _ref2.showMapId,
6118
+ showMapId = _ref2$showMapId === void 0 ? false : _ref2$showMapId,
6119
+ props = _objectWithoutPropertiesLoose(_ref2, _excluded$2);
6120
+ return jsx(LegendConnectComponent, Object.assign({
6121
+ showMapId: showMapId
6122
+ }, props));
6123
+ };
6124
+
6125
+ var LegendMapButtonConnect = function LegendMapButtonConnect(_ref) {
6126
+ var mapId = _ref.mapId,
6127
+ _ref$source = _ref.source,
6128
+ source = _ref$source === void 0 ? 'app' : _ref$source,
6129
+ _ref$multiLegend = _ref.multiLegend,
6130
+ multiLegend = _ref$multiLegend === void 0 ? false : _ref$multiLegend;
6131
+ var dispatch = useDispatch();
6132
+ var legendType = multiLegend ? "legend-" + mapId : "legend";
6133
+ var currentActiveMapId = useSelector(function (store) {
6134
+ return uiSelectors.getDialogMapId(store, legendType);
6135
+ });
6136
+ var isOpenInStore = useSelector(function (store) {
6137
+ return uiSelectors.getisDialogOpen(store, legendType);
6138
+ });
6139
+ var openLegendDialog = React.useCallback(function () {
6140
+ dispatch(uiActions.setActiveMapIdForDialog({
6141
+ type: legendType,
6142
+ mapId: mapId,
6143
+ setOpen: currentActiveMapId !== mapId ? true : !isOpenInStore,
6144
+ source: source,
6145
+ origin: mapEnums.MapActionOrigin.map
6146
+ }));
6147
+ }, [currentActiveMapId, dispatch, isOpenInStore, mapId, source, legendType]);
6148
+ var isOpen = currentActiveMapId === mapId && isOpenInStore;
6149
+ return jsx(LegendButton, {
6150
+ isOpen: isOpen,
6151
+ openLegendDialog: openLegendDialog
6152
+ });
6153
+ };
6154
+
6155
+ var SearchControlButtonConnect = function SearchControlButtonConnect(_ref) {
6156
+ var mapId = _ref.mapId,
6157
+ _ref$source = _ref.source,
6158
+ source = _ref$source === void 0 ? 'app' : _ref$source;
6159
+ var _useCoreTranslation = useCoreTranslation(),
6160
+ t = _useCoreTranslation.t;
6161
+ var dispatch = useDispatch();
6162
+ var dialogType = uiTypes.DialogTypes.Search + "-" + mapId;
6163
+ var currentActiveMapId = useSelector(function (store) {
6164
+ return uiSelectors.getDialogMapId(store, dialogType);
6165
+ });
6166
+ var isOpenInStore = useSelector(function (store) {
6167
+ return uiSelectors.getisDialogOpen(store, dialogType);
6168
+ });
6169
+ var openSearchDialog = React__default.useCallback(function () {
6170
+ dispatch(uiActions.setActiveMapIdForDialog({
6171
+ type: dialogType,
6172
+ mapId: mapId,
6173
+ setOpen: currentActiveMapId !== mapId ? true : !isOpenInStore,
6174
+ source: source
6175
+ }));
6176
+ }, [currentActiveMapId, dialogType, dispatch, isOpenInStore, mapId, source]);
6177
+ React__default.useEffect(function () {
6178
+ var handleKeyDown = function handleKeyDown(event) {
6179
+ var target = event.target;
6180
+ if (target.tagName !== 'INPUT' && target.tagName !== 'TEXTAREA' && event.code === 'KeyF' || (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') && event.code === 'Escape') {
6181
+ event.preventDefault();
6182
+ openSearchDialog();
6183
+ }
6184
+ };
6185
+ document.addEventListener('keydown', handleKeyDown);
6186
+ return function () {
6187
+ document.removeEventListener('keydown', handleKeyDown);
6188
+ };
6189
+ }, [openSearchDialog]);
6190
+ return jsx(MapControlButton, {
6191
+ onClick: openSearchDialog,
6192
+ title: t('search-title'),
6193
+ "aria-label": t('search-title-aria'),
6194
+ isActive: isOpenInStore,
6195
+ children: jsx(Search, {})
6196
+ });
6197
+ };
6198
+
6199
+ var MY_LOCATION = 'My location';
6200
+ var locationOptions = {
6201
+ enableHighAccuracy: false,
6202
+ timeout: 10000,
6203
+ maximumAge: 0
6204
+ };
6205
+ var MyMapLocation = function MyMapLocation(_ref) {
6206
+ var _ref$mapId = _ref.mapId,
6207
+ mapId = _ref$mapId === void 0 ? '' : _ref$mapId,
6208
+ _ref$isSelected = _ref.isSelected,
6209
+ isSelected = _ref$isSelected === void 0 ? false : _ref$isSelected,
6210
+ _ref$onUpdateMyLocati = _ref.onUpdateMyLocation,
6211
+ onUpdateMyLocation = _ref$onUpdateMyLocati === void 0 ? function () {} : _ref$onUpdateMyLocati;
6212
+ var theme = useTheme();
6213
+ var _useState = useState(false),
6214
+ isLoading = _useState[0],
6215
+ setIsLoading = _useState[1];
6216
+ var _useState2 = useState(false),
6217
+ hasFailed = _useState2[0],
6218
+ setHasFailed = _useState2[1];
6219
+ var _useCoreTranslation = useCoreTranslation(),
6220
+ t = _useCoreTranslation.t;
6221
+ var handleLocationClick = function handleLocationClick() {
6222
+ if (mapId && isSelected) {
6223
+ onUpdateMyLocation(undefined);
6224
+ } else if (navigator.geolocation && mapId && !isSelected) {
6225
+ setIsLoading(true);
6226
+ setHasFailed(false);
6227
+ navigator.geolocation.getCurrentPosition(function (success) {
6228
+ setIsLoading(false);
6229
+ var _success$coords = success.coords,
6230
+ latitude = _success$coords.latitude,
6231
+ longitude = _success$coords.longitude;
6232
+ var location = {
6233
+ lat: latitude,
6234
+ lon: longitude,
6235
+ name: MY_LOCATION,
6236
+ source: 'MyMapLocation',
6237
+ id: MY_LOCATION
6238
+ };
6239
+ onUpdateMyLocation(location);
6240
+ }, function () {
6241
+ setIsLoading(false);
6242
+ setHasFailed(true);
6243
+ onUpdateMyLocation(undefined);
6244
+ }, locationOptions);
6245
+ }
6246
+ };
6247
+ var chooseIcon = function chooseIcon() {
6248
+ return hasFailed ? jsx(Exclamation, {
6249
+ style: {
6250
+ color: theme.palette.geowebColors.functional.error
6251
+ },
6252
+ "aria-label": "location error"
6253
+ }) : jsx(MyLocation, {
6254
+ "aria-label": "location default"
6255
+ });
6256
+ };
6257
+ return jsx(Box, {
6258
+ sx: {
6259
+ height: 40,
6260
+ padding: 1
6261
+ },
6262
+ children: isLoading ? jsx(CircularProgress, {
6263
+ size: 24,
6264
+ "aria-label": "Location loading",
6265
+ color: "secondary"
6266
+ }) : jsx(CustomIconButton, {
6267
+ tooltipTitle: t('search-my-location'),
6268
+ "aria-label": t('search-my-location'),
6269
+ onClick: handleLocationClick,
6270
+ isSelected: isSelected,
6271
+ variant: "tool",
6272
+ size: "small",
6273
+ children: chooseIcon()
6274
+ })
6275
+ });
6276
+ };
6277
+
5972
6278
  /* *
5973
6279
  * Licensed under the Apache License, Version 2.0 (the "License");
5974
6280
  * you may not use this file except in compliance with the License.
@@ -5982,67 +6288,359 @@ var MultiMapMultiDimensionSelectConnect = function MultiMapMultiDimensionSelectC
5982
6288
  * See the License for the specific language governing permissions and
5983
6289
  * limitations under the License.
5984
6290
  *
5985
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
5986
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
5987
- * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
6291
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6292
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
6293
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
5988
6294
  * */
5989
- /**
5990
- * Get the title for this WMS layer based on its layerId. If not defined, layerId is used instead.
5991
- * @param layerId
5992
- * @returns Title for the layer
5993
- */
5994
- var getTitle = function getTitle(layerId) {
5995
- var wmjsLayer = webmapUtils.getWMLayerById(layerId);
5996
- return wmjsLayer ? wmjsLayer.title || wmjsLayer.name : layerId;
6295
+ var config = sessionStorageProvider.getConfig();
6296
+ var locationBaseUrl = config.GW_LOCATION_BASE_URL;
6297
+ var getLocationBaseUrl = function getLocationBaseUrl() {
6298
+ if (locationBaseUrl === undefined) {
6299
+ var _config = sessionStorageProvider.getConfig();
6300
+ locationBaseUrl = _config.GW_LOCATION_BASE_URL || '';
6301
+ }
6302
+ return locationBaseUrl;
5997
6303
  };
5998
- var getFeatureInfoUrl = function getFeatureInfoUrl(layer, mapPinLocation) {
5999
- /*
6000
- We need a wmjsLayer to build the getfeatureinfo url (getWMSGetFeatureInfoRequestURL function).
6001
- But it seems that its dimension are lazely updated (by ReactMapView).
6002
- Therefore make a clone of this layer and set its dimensions based on the layer object.
6003
- Otherwise we risk making a getfeatureinfo call with outdated dimension values.
6004
- */
6005
- var wmjsLayer = webmapUtils.getWMLayerById(layer.id).cloneLayer();
6006
- if (mapPinLocation) {
6007
- // OpenLayers WMS version
6008
- var source = new ImageWMS({
6009
- url: wmjsLayer.getmapURL,
6010
- params: {
6011
- LAYERS: wmjsLayer.getLayerName()
6304
+ var getLocationList = function getLocationList(search) {
6305
+ return fetch(getLocationBaseUrl() + "/locations?search=" + search).then(handleResponse);
6306
+ };
6307
+ var getLocationDetail = function getLocationDetail(id, source) {
6308
+ return fetch(getLocationBaseUrl() + "/locationdetail?id=" + id + "&source=" + source).then(handleResponse);
6309
+ };
6310
+
6311
+ var useLocationList = function useLocationList(search) {
6312
+ return useQuery({
6313
+ queryKey: ['location-list', search],
6314
+ queryFn: function () {
6315
+ var _queryFn = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
6316
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
6317
+ while (1) switch (_context.prev = _context.next) {
6318
+ case 0:
6319
+ if (!(search.length > 0)) {
6320
+ _context.next = 2;
6321
+ break;
6322
+ }
6323
+ return _context.abrupt("return", getLocationList(search));
6324
+ case 2:
6325
+ return _context.abrupt("return", []);
6326
+ case 3:
6327
+ case "end":
6328
+ return _context.stop();
6329
+ }
6330
+ }, _callee);
6331
+ }));
6332
+ function queryFn() {
6333
+ return _queryFn.apply(this, arguments);
6012
6334
  }
6335
+ return queryFn;
6336
+ }()
6337
+ });
6338
+ };
6339
+ var useLocationDetail = function useLocationDetail(location) {
6340
+ return useQuery({
6341
+ queryKey: ['location-detail', {
6342
+ id: location == null ? void 0 : location.id,
6343
+ source: location == null ? void 0 : location.source
6344
+ }],
6345
+ queryFn: function queryFn() {
6346
+ return getLocationDetail(location.id, location.source);
6347
+ },
6348
+ enabled: !!(location != null && location.id) && !!(location != null && location.source)
6349
+ });
6350
+ };
6351
+
6352
+ var _excluded$1 = ["key"];
6353
+ var LocationSearch = function LocationSearch(_ref) {
6354
+ var isOpen = _ref.isOpen,
6355
+ _ref$mapId = _ref.mapId,
6356
+ mapId = _ref$mapId === void 0 ? '' : _ref$mapId,
6357
+ _ref$onSelectLocation = _ref.onSelectLocation,
6358
+ onSelectLocation = _ref$onSelectLocation === void 0 ? function () {} : _ref$onSelectLocation,
6359
+ _ref$onUpdateMyLocati = _ref.onUpdateMyLocation,
6360
+ onUpdateMyLocation = _ref$onUpdateMyLocati === void 0 ? function () {} : _ref$onUpdateMyLocati,
6361
+ _ref$isMyLocationSele = _ref.isMyLocationSelected,
6362
+ isMyLocationSelected = _ref$isMyLocationSele === void 0 ? false : _ref$isMyLocationSele;
6363
+ var theme = useTheme();
6364
+ var _useCoreTranslation = useCoreTranslation(),
6365
+ t = _useCoreTranslation.t;
6366
+ var _useState = useState(''),
6367
+ inputValue = _useState[0],
6368
+ setInputValue = _useState[1];
6369
+ var _useState2 = useState(null),
6370
+ selectedValue = _useState2[0],
6371
+ setSelectedValue = _useState2[1];
6372
+ var _useState3 = useState(true),
6373
+ dropdownOpen = _useState3[0],
6374
+ setDropdownOpen = _useState3[1];
6375
+ var debouncedInputValue = useDebounce(inputValue, 300);
6376
+ var _useLocationList = useLocationList(debouncedInputValue),
6377
+ locationListData = _useLocationList.data;
6378
+ // For when we are still typing something
6379
+ var _useState4 = useState(null),
6380
+ pendingValue = _useState4[0],
6381
+ setPendingValue = _useState4[1];
6382
+ // Extract predefined locations from BE (and group them)
6383
+ var backendPredefined = useMemo(function () {
6384
+ return (locationListData || []).filter(function (item) {
6385
+ return item.source === 'predefined';
6013
6386
  });
6014
- layer.dimensions && layer.dimensions.forEach(function (dim) {
6015
- var wmDim = wmjsLayer.getDimension(dim.name);
6016
- if (wmDim && wmDim.getValue() !== dim.currentValue) {
6017
- wmDim.setValue(dim.currentValue);
6018
- }
6387
+ }, [locationListData]);
6388
+ var groupedPredefinedAreas = useMemo(function () {
6389
+ return [{
6390
+ header: t('search-airports'),
6391
+ icon: Airplane,
6392
+ items: backendPredefined.filter(function (i) {
6393
+ return i.group === 'airport';
6394
+ })
6395
+ }, {
6396
+ header: t('search-countries-regions-cities'),
6397
+ icon: Region,
6398
+ items: backendPredefined.filter(function (i) {
6399
+ return i.group === 'country' || i.group === 'city' || i.group === 'region';
6400
+ })
6401
+ }, {
6402
+ header: t('search-places'),
6403
+ icon: Pinned,
6404
+ items: backendPredefined.filter(function (i) {
6405
+ return i.group === 'special';
6406
+ })
6407
+ }];
6408
+ }, [backendPredefined, t]);
6409
+ var predefinedOptions = useMemo(function () {
6410
+ return groupedPredefinedAreas.flatMap(function (group) {
6411
+ return group.items.map(function (item) {
6412
+ return Object.assign({}, item, {
6413
+ groupHeader: group.header,
6414
+ groupIcon: group.icon
6415
+ });
6416
+ });
6019
6417
  });
6020
- return source.getFeatureInfoUrl([mapPinLocation.projectionX, mapPinLocation.projectionY], mapPinLocation.resolution, mapPinLocation.srs, {
6021
- INFO_FORMAT: 'text/html'
6022
- }) + "&" + getMapDimURL(wmjsLayer).toString();
6023
- }
6024
- return undefined;
6025
- };
6026
- /**
6027
- * Make a list of GFI Layers to display.
6028
- * @param layers
6029
- * @param mapId
6030
- * @returns
6031
- */
6032
- var getLayersToUpdate = function getLayersToUpdate(mapPinLocation, layers) {
6033
- if (!layers || layers.length === 0 || !mapPinLocation) {
6034
- return [];
6035
- }
6036
- return layers.filter(function (layer) {
6037
- return layer && layer.enabled && !!webmapUtils.getWMLayerById(layer.id);
6038
- }).map(function (layer) {
6039
- var url = getFeatureInfoUrl(layer, mapPinLocation);
6040
- return {
6041
- layerId: layer.id,
6042
- url: url,
6043
- title: getTitle(layer.id)
6418
+ }, [groupedPredefinedAreas]);
6419
+ // Filter predefined options by search string
6420
+ var filteredPredefinedOptions = useMemo(function () {
6421
+ return debouncedInputValue.trim() === '' ? predefinedOptions : predefinedOptions.filter(function (option) {
6422
+ return option.name.toLowerCase().includes(debouncedInputValue.trim().toLowerCase());
6423
+ });
6424
+ }, [debouncedInputValue, predefinedOptions]);
6425
+ // Filter out predefined options from locationListData to avoid duplicates
6426
+ var locationListResults = useMemo(function () {
6427
+ return (locationListData || []).filter(function (result) {
6428
+ return !filteredPredefinedOptions.some(function (predef) {
6429
+ return predef.id === result.id && predef.source === result.source;
6430
+ });
6431
+ });
6432
+ }, [locationListData, filteredPredefinedOptions]);
6433
+ var autocompleteOptions = useMemo(function () {
6434
+ return debouncedInputValue.trim() === '' ? predefinedOptions : [].concat(filteredPredefinedOptions, locationListResults);
6435
+ }, [debouncedInputValue, predefinedOptions, filteredPredefinedOptions, locationListResults]);
6436
+ var _useLocationDetail = useLocationDetail(selectedValue),
6437
+ locationDetail = _useLocationDetail.data,
6438
+ isFetchingDetail = _useLocationDetail.isFetching;
6439
+ useEffect(function () {
6440
+ // Only open dropdown if no location is selected
6441
+ if (isOpen && !selectedValue) {
6442
+ setDropdownOpen(true);
6443
+ }
6444
+ }, [isOpen, selectedValue]);
6445
+ useEffect(function () {
6446
+ // Update pin only on confirmed selection
6447
+ if (!selectedValue || isFetchingDetail || !isOpen) {
6448
+ return;
6449
+ }
6450
+ onSelectLocation(locationDetail);
6451
+ }, [selectedValue, locationDetail, isFetchingDetail, isOpen, onSelectLocation]);
6452
+ React__default.useEffect(function () {
6453
+ var handleKeyDown = function handleKeyDown(event) {
6454
+ if (isOpen && event.key === 'Escape') {
6455
+ if (dropdownOpen) {
6456
+ setDropdownOpen(false);
6457
+ }
6458
+ event.stopPropagation();
6459
+ }
6044
6460
  };
6045
- });
6461
+ document.addEventListener('keydown', handleKeyDown);
6462
+ return function () {
6463
+ document.removeEventListener('keydown', handleKeyDown);
6464
+ };
6465
+ }, [dropdownOpen, isOpen]);
6466
+ return isOpen && mapId ? jsxs(Box, {
6467
+ sx: {
6468
+ display: 'flex',
6469
+ flexDirection: 'row',
6470
+ alignItems: 'center',
6471
+ position: 'absolute',
6472
+ pointerEvents: 'all',
6473
+ zIndex: 99,
6474
+ left: 50,
6475
+ top: 8,
6476
+ backgroundColor: theme.palette.geowebColors.textInputField["default"].fill,
6477
+ height: 40,
6478
+ boxShadow: theme.shadows[6],
6479
+ width: 'calc(100% - 50px)',
6480
+ maxWidth: 380
6481
+ },
6482
+ children: [jsx(MyMapLocation, {
6483
+ mapId: mapId,
6484
+ onUpdateMyLocation: onUpdateMyLocation,
6485
+ isSelected: isMyLocationSelected
6486
+ }), jsx(Autocomplete, Object.assign({
6487
+ autoHighlight: true,
6488
+ disablePortal: true,
6489
+ selectOnFocus: true,
6490
+ open: dropdownOpen,
6491
+ onOpen: function onOpen() {
6492
+ return setDropdownOpen(true);
6493
+ },
6494
+ onClose: function onClose() {
6495
+ return setDropdownOpen(false);
6496
+ },
6497
+ sx: {
6498
+ width: '100%',
6499
+ '&.MuiAutocomplete-root .MuiFilledInput-root': {
6500
+ height: 40,
6501
+ padding: '0px!important',
6502
+ '&:before, &:hover:before': {
6503
+ borderColor: 'transparent'
6504
+ }
6505
+ },
6506
+ '&.MuiAutocomplete-root .MuiInputLabel-root': {
6507
+ lineHeight: '16px',
6508
+ maxWidth: 'calc(100% - 40px)',
6509
+ ':not(.MuiInputLabel-shrink)': {
6510
+ transform: 'translate(12px, 12px) scale(1)'
6511
+ }
6512
+ },
6513
+ '&.MuiAutocomplete-root .MuiFilledInput-input': {
6514
+ lineHeight: '20px',
6515
+ paddingLeft: '12px',
6516
+ paddingTop: '20px'
6517
+ }
6518
+ },
6519
+ getOptionLabel: function getOptionLabel(option) {
6520
+ return option.name;
6521
+ },
6522
+ getOptionKey: function getOptionKey(option) {
6523
+ return option.id + option.name;
6524
+ },
6525
+ filterOptions: function filterOptions(x) {
6526
+ return x;
6527
+ },
6528
+ options: autocompleteOptions
6529
+ }, debouncedInputValue.trim() === '' ? {
6530
+ groupBy: function groupBy(option) {
6531
+ return 'groupHeader' in option && typeof option.groupHeader === 'string' ? option.groupHeader : '';
6532
+ },
6533
+ renderGroup: function renderGroup(params) {
6534
+ return jsxs(React__default.Fragment, {
6535
+ children: [jsx(ListSubheader, {
6536
+ disableSticky: true,
6537
+ sx: {
6538
+ color: theme.palette.primary.main,
6539
+ fontWeight: 400,
6540
+ fontSize: '16px',
6541
+ py: 1,
6542
+ my: 0,
6543
+ minHeight: '26px',
6544
+ lineHeight: 1
6545
+ },
6546
+ children: params.group
6547
+ }), Array.isArray(params.children) ? params.children : [params.children]]
6548
+ }, params.key);
6549
+ }
6550
+ } : {}, {
6551
+ /* eslint-disable @typescript-eslint/no-explicit-any */
6552
+ renderOption: function renderOption(props, option) {
6553
+ var key = props.key,
6554
+ rest = _objectWithoutPropertiesLoose(props, _excluded$1);
6555
+ var icon = null;
6556
+ if (typeof option.groupIcon === 'function') {
6557
+ var Icon = option.groupIcon;
6558
+ var iconElement = jsx(Icon, {
6559
+ sx: {
6560
+ mr: 1
6561
+ },
6562
+ fontSize: "small",
6563
+ "data-testid": option.name + "-svg"
6564
+ });
6565
+ icon = /*#__PURE__*/React__default.cloneElement(iconElement, {}, React__default.Children.map(iconElement.props.children, function (child) {
6566
+ return /*#__PURE__*/React__default.isValidElement(child) ? /*#__PURE__*/React__default.cloneElement(child, {
6567
+ 'data-testid': option.name + "-path"
6568
+ }) : child;
6569
+ }));
6570
+ }
6571
+ return jsxs("li", Object.assign({}, rest, {
6572
+ children: [icon, option.name]
6573
+ }), key);
6574
+ },
6575
+ /* eslint-enable @typescript-eslint/no-explicit-any */
6576
+ noOptionsText: t('search-no-results'),
6577
+ popupIcon: null,
6578
+ clearIcon: null,
6579
+ onChange: function onChange(_event, newValue, reason) {
6580
+ if (newValue && typeof newValue !== 'string') {
6581
+ if (reason === 'selectOption') {
6582
+ // Confirm if user clicked
6583
+ setSelectedValue(newValue);
6584
+ setPendingValue(null);
6585
+ setInputValue(newValue.name);
6586
+ setDropdownOpen(false);
6587
+ } else {
6588
+ // Just a pending result when typing
6589
+ setPendingValue(newValue);
6590
+ setInputValue(newValue.name);
6591
+ }
6592
+ }
6593
+ },
6594
+ value: selectedValue,
6595
+ inputValue: inputValue,
6596
+ isOptionEqualToValue: function isOptionEqualToValue(option, value) {
6597
+ return option.id === value.id;
6598
+ },
6599
+ renderInput: function renderInput(params) {
6600
+ return jsx(TextField, Object.assign({}, params, {
6601
+ autoFocus: true,
6602
+ size: "medium",
6603
+ label: t('search-title-long'),
6604
+ fullWidth: true,
6605
+ variant: "filled",
6606
+ onChange: function onChange(event) {
6607
+ setInputValue(event.target.value);
6608
+ if (selectedValue) {
6609
+ setSelectedValue(null);
6610
+ }
6611
+ },
6612
+ onKeyDown: function onKeyDown(event) {
6613
+ if (event.key === 'Enter' && pendingValue) {
6614
+ setSelectedValue(pendingValue); // confirm selection
6615
+ setPendingValue(null); // clear pending
6616
+ setDropdownOpen(false);
6617
+ event.preventDefault();
6618
+ }
6619
+ if (params.inputProps && typeof params.inputProps.onKeyDown === 'function') {
6620
+ params.inputProps.onKeyDown(event);
6621
+ }
6622
+ },
6623
+ slotProps: {
6624
+ input: Object.assign({}, params.InputProps, {
6625
+ endAdornment: jsx(CustomIconButton, {
6626
+ tooltipTitle: t('search-clear'),
6627
+ onClick: function onClick() {
6628
+ setInputValue('');
6629
+ setSelectedValue(null);
6630
+ setPendingValue(null);
6631
+ onSelectLocation(undefined);
6632
+ },
6633
+ sx: {
6634
+ marginRight: 1
6635
+ },
6636
+ children: jsx(Close, {})
6637
+ })
6638
+ })
6639
+ }
6640
+ }));
6641
+ }
6642
+ }))]
6643
+ }) : null;
6046
6644
  };
6047
6645
 
6048
6646
  /* *
@@ -6058,483 +6656,322 @@ var getLayersToUpdate = function getLayersToUpdate(mapPinLocation, layers) {
6058
6656
  * See the License for the specific language governing permissions and
6059
6657
  * limitations under the License.
6060
6658
  *
6061
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6062
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
6063
- * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
6659
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6660
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
6661
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
6064
6662
  * */
6065
- var sanitizeHTML = function sanitizeHTML(htmlToBeSanitized) {
6066
- return {
6067
- __html: DOMPurify.sanitize(htmlToBeSanitized, {
6068
- ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'table', 'td', 'tr', 'br', 'hr', 'th'],
6069
- ALLOWED_ATTR: ['href']
6070
- })
6071
- };
6663
+ var geometryStyling = {
6664
+ fill: '#FF7800',
6665
+ 'fill-opacity': 0.25,
6666
+ stroke: '#FF7800',
6667
+ 'stroke-opacity': 1,
6668
+ 'stroke-width': 4
6072
6669
  };
6073
-
6074
- var GetFeatureInfoDialog = function GetFeatureInfoDialog(_ref) {
6075
- var layers = _ref.layers,
6076
- isOpen = _ref.isOpen,
6077
- onClose = _ref.onClose,
6078
- _ref$onMouseDown = _ref.onMouseDown,
6079
- onMouseDown = _ref$onMouseDown === void 0 ? function () {} : _ref$onMouseDown,
6080
- mapId = _ref.mapId,
6081
- _ref$showMapId = _ref.showMapId,
6082
- showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
6083
- _ref$order = _ref.order,
6084
- order = _ref$order === void 0 ? 0 : _ref$order,
6085
- _ref$source = _ref.source,
6086
- source = _ref$source === void 0 ? 'app' : _ref$source,
6087
- mapPinLocation = _ref.mapPinLocation;
6088
- var _useCoreTranslation = useCoreTranslation(),
6089
- t = _useCoreTranslation.t;
6090
- /* Ref, state and update function for results per layer map */
6091
- var gfiResultMap = React__default.useRef(new Map()).current;
6092
- var _React$useState = React__default.useState(),
6093
- triggerRerender = _React$useState[1];
6094
- var updateLayerResult = function updateLayerResult(_ref2) {
6095
- var layerId = _ref2.layerId,
6096
- data = _ref2.data,
6097
- isLoading = _ref2.isLoading;
6098
- gfiResultMap.set(layerId, {
6099
- data: data,
6100
- isLoading: isLoading
6101
- });
6102
- triggerRerender("" + layerId + isLoading);
6103
- };
6104
- /* Build a layerlist array with a set of arguments per layer to do the query for */
6105
- var layerToUpdateList = isOpen && mapPinLocation ? getLayersToUpdate(mapPinLocation, layers) : [];
6106
- /*
6107
- Build a string based on the GFI urls. If this changes for whatever reason we need to update.
6108
- These strings can change very often, therefore they need to be debounced and only use the most recent result must be used.
6109
- */
6110
- var debouncedlayerListString = useDebounce(layerToUpdateList.map(function (layer) {
6111
- return layer.url;
6112
- }).join(','), 100);
6113
- /* Do a GFI call to the server and use the updateLayerResult to provide the results. */
6114
- var fetchLayerInfo = /*#__PURE__*/function () {
6115
- var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(url, layerId) {
6116
- var _yield$axios$get, data, errorMessage;
6117
- return _regeneratorRuntime().wrap(function _callee$(_context) {
6118
- while (1) switch (_context.prev = _context.next) {
6119
- case 0:
6120
- _context.prev = 0;
6121
- updateLayerResult({
6122
- layerId: layerId,
6123
- data: '',
6124
- isLoading: true
6125
- });
6126
- _context.next = 4;
6127
- return axios.get(url);
6128
- case 4:
6129
- _yield$axios$get = _context.sent;
6130
- data = _yield$axios$get.data;
6131
- updateLayerResult({
6132
- layerId: layerId,
6133
- data: data,
6134
- isLoading: false
6135
- });
6136
- _context.next = 13;
6137
- break;
6138
- case 9:
6139
- _context.prev = 9;
6140
- _context.t0 = _context["catch"](0);
6141
- errorMessage = _context.t0 instanceof Error ? _context.t0.message : 'fetchLayerInfo failed';
6142
- updateLayerResult({
6143
- layerId: layerId,
6144
- data: errorMessage,
6145
- isLoading: false
6146
- });
6147
- case 13:
6148
- case "end":
6149
- return _context.stop();
6150
- }
6151
- }, _callee, null, [[0, 9]]);
6152
- }));
6153
- return function fetchLayerInfo(_x, _x2) {
6154
- return _ref3.apply(this, arguments);
6155
- };
6156
- }();
6157
- /* For each changed getfeature url string, load new data using WMS GetFeatureInfo */
6158
- React__default.useEffect(function () {
6159
- if (mapPinLocation && isOpen) {
6160
- layerToUpdateList.forEach(function (_ref4) {
6161
- var url = _ref4.url,
6162
- layerId = _ref4.layerId;
6163
- void fetchLayerInfo(url, layerId);
6164
- });
6165
- }
6166
- // eslint-disable-next-line react-hooks/exhaustive-deps
6167
- }, [debouncedlayerListString]);
6168
- var hasLayers = layers && layers.length > 0;
6169
- var stopWheelEventPropagationRef = useWheelStopPropagation();
6170
- return jsx(ToolContainerDraggable, {
6171
- startPosition: {
6172
- right: 10,
6173
- top: 80
6174
- },
6175
- minWidth: 100,
6176
- onClose: onClose,
6177
- title: showMapId ? t('feature_info_marker_info') + " " + mapId : t('feature_info_marker_info'),
6178
- initialMaxHeight: 440,
6179
- isOpen: isOpen,
6180
- "data-testid": "moveable-getfeatureinfo",
6181
- bounds: "parent",
6182
- onMouseDown: onMouseDown,
6183
- order: order,
6184
- source: source,
6185
- children: jsxs(Box, {
6186
- sx: {
6187
- padding: 0
6188
- },
6189
- children: [isOpen && hasLayers && mapPinLocation && jsx(Box, {
6190
- "data-testid": "GetFeatureInfoList",
6191
- ref: stopWheelEventPropagationRef,
6192
- children: layerToUpdateList.map(function (layer) {
6193
- var layerId = layer.layerId,
6194
- title = layer.title,
6195
- url = layer.url;
6196
- var result = gfiResultMap.get(layerId);
6197
- if (!result) {
6198
- return null;
6199
- }
6200
- return jsxs(Grid, {
6201
- sx: {
6202
- margin: '4px 6px 4px 6px',
6203
- padding: '6px',
6204
- backgroundColor: 'geowebColors.cards.cardContainer',
6205
- border: 'solid 1px',
6206
- borderColor: 'geowebColors.cards.cardContainerBorder'
6207
- },
6208
- children: [jsxs(Typography, {
6209
- variant: "subtitle1",
6210
- children: [title, "\xA0", jsx(CustomIconButton, {
6211
- sx: {
6212
- "float": 'right'
6213
- },
6214
- "aria-label": "Open layer featureinfo in another page",
6215
- onClick: function onClick() {
6216
- window.open(url);
6217
- },
6218
- children: jsx(ExitDomain, {})
6219
- })]
6220
- }), !result.isLoading ? jsx("div", {
6221
- style: {
6222
- fontSize: '11px',
6223
- padding: '6px',
6224
- margin: '0',
6225
- fontFamily: 'Roboto,Helvetica,Arial,sans-serif',
6226
- fontWeight: '400',
6227
- lineHeight: '1.75',
6228
- letterSpacing: '0.25px'
6229
- },
6230
- "data-testid": "layer-result-ready-" + layerId,
6231
- // eslint-disable-next-line react/no-danger
6232
- dangerouslySetInnerHTML: sanitizeHTML(result.data)
6233
- }) : jsx("div", {
6234
- "data-testid": "layer-result-loading-" + layerId,
6235
- children: jsx(CircularProgress, {
6236
- "data-testid": "spinner",
6237
- color: "inherit"
6238
- })
6239
- })]
6240
- }, layerId);
6241
- })
6242
- }), hasLayers && !mapPinLocation && jsx(Typography, {
6243
- "data-testid": "click-on-map-for-info",
6244
- variant: "subtitle1",
6245
- sx: {
6246
- padding: '10px'
6247
- },
6248
- children: t('feature_info_title')
6249
- }), !hasLayers && jsx(Typography, {
6250
- "data-testid": "NoLayers",
6251
- variant: "subtitle1",
6252
- sx: {
6253
- padding: '10px'
6254
- },
6255
- children: t('feature_info_no_layers')
6256
- })]
6257
- })
6258
- });
6670
+ var bufferFromZoomLevel = function bufferFromZoomLevel(zoom, lat, viewportWidthPx) {
6671
+ var earthCircumference = 40075016.686;
6672
+ var worldPx = 256 * Math.pow(2, zoom);
6673
+ var metersPerPx = earthCircumference / worldPx;
6674
+ var viewportWidthMeters = metersPerPx * viewportWidthPx;
6675
+ var metersPerDegree = 111320 * Math.cos(lat * Math.PI / 180);
6676
+ // Buffer in degrees (half the viewport width)
6677
+ var buffer = viewportWidthMeters / metersPerDegree / 2;
6678
+ return buffer;
6679
+ };
6680
+ var bboxFromPolygon = function bboxFromPolygon(geom, buffer) {
6681
+ // A bbox is calculated with a buffer (expressed in %)
6682
+ var _turf$bbox = turf.bbox(geom),
6683
+ minX = _turf$bbox[0],
6684
+ minY = _turf$bbox[1],
6685
+ maxX = _turf$bbox[2],
6686
+ maxY = _turf$bbox[3];
6687
+ var width = maxX - minX;
6688
+ var height = maxY - minY;
6689
+ return [minX - width * buffer, minY - height * buffer, maxX + width * buffer, maxY + height * buffer];
6690
+ };
6691
+ var bboxFromPoint = function bboxFromPoint(geom, buffer) {
6692
+ if (geom.type !== 'Point' || !Array.isArray(geom.coordinates)) {
6693
+ throw new Error('bboxFromPoint: geometry must be of type Point');
6694
+ }
6695
+ var _geom$coordinates = geom.coordinates,
6696
+ lon = _geom$coordinates[0],
6697
+ lat = _geom$coordinates[1];
6698
+ var width = 0.01;
6699
+ var height = 0.01;
6700
+ return [lon - width * buffer, lat - height * buffer, lon + width * buffer, lat + height * buffer];
6259
6701
  };
6260
-
6261
- var GetFeatureInfoConnect = function GetFeatureInfoConnect(_ref) {
6262
- var _ref$showMapId = _ref.showMapId,
6263
- showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
6264
- mapId = _ref.mapId;
6265
- var dispatch = useDispatch();
6266
- var getFeatureInfoType = "getfeatureinfo-" + mapId;
6267
- var mapPinLocation = useSelector(function (store) {
6268
- return mapSelectors.getPinLocation(store, mapId);
6269
- });
6270
- var toggleMapPinIsVisible = React.useCallback(function (displayMapPin) {
6271
- dispatch(mapActions.toggleMapPinIsVisible({
6272
- mapId: mapId,
6273
- displayMapPin: displayMapPin
6274
- }));
6275
- }, [dispatch, mapId]);
6276
- var enableMapPin = function enableMapPin() {
6277
- dispatch(mapActions.setDisableMapPin({
6278
- mapId: mapId,
6279
- disableMapPin: false
6280
- }));
6702
+ var makeGeoJSONFeatureFromLocation = function makeGeoJSONFeatureFromLocation(location, mapFeatureClass, t) {
6703
+ var _location$geometry;
6704
+ var collection = {
6705
+ type: 'FeatureCollection',
6706
+ features: []
6281
6707
  };
6282
- var mapLayers = useSelector(function (store) {
6283
- return mapSelectors.getMapLayers(store, mapId);
6708
+ var name = mapFeatureClass === MapFeatureClass.MyLocation ? t('my-location') : location.name;
6709
+ var geometry = Object.assign({}, location.geometry, {
6710
+ properties: Object.assign({}, geometryStyling, {
6711
+ name: name,
6712
+ mapFeatureClass: mapFeatureClass,
6713
+ showNameOnHover: true
6714
+ })
6284
6715
  });
6285
- var _useSetupDialog = useSetupDialog(getFeatureInfoType),
6286
- dialogOrder = _useSetupDialog.dialogOrder,
6287
- isDialogOpen = _useSetupDialog.isDialogOpen,
6288
- uiSource = _useSetupDialog.uiSource,
6289
- setDialogOrder = _useSetupDialog.setDialogOrder,
6290
- onCloseDialog = _useSetupDialog.onCloseDialog;
6291
- React.useEffect(function () {
6292
- toggleMapPinIsVisible(isDialogOpen);
6293
- if (isDialogOpen) {
6294
- enableMapPin();
6716
+ var marker = {
6717
+ type: 'Feature',
6718
+ properties: {
6719
+ name: name,
6720
+ mapFeatureClass: mapFeatureClass,
6721
+ showNameOnHover: true
6722
+ },
6723
+ geometry: {
6724
+ type: 'Point',
6725
+ coordinates: [location.lon, location.lat]
6295
6726
  }
6296
- /* Do not respond on changes of isMapPinVisible, to allow other components to open/close the mappin. */
6297
- // eslint-disable-next-line react-hooks/exhaustive-deps
6298
- }, [isDialogOpen, toggleMapPinIsVisible]);
6299
- return jsx(GetFeatureInfoDialog, {
6300
- layers: mapLayers,
6301
- isOpen: isDialogOpen,
6302
- onClose: onCloseDialog,
6303
- mapId: mapId,
6304
- showMapId: showMapId,
6305
- onMouseDown: setDialogOrder,
6306
- order: dialogOrder,
6307
- source: uiSource,
6308
- mapPinLocation: mapPinLocation
6309
- });
6310
- };
6311
-
6312
- var GetFeatureInfoButtonConnect = function GetFeatureInfoButtonConnect(_ref) {
6313
- var mapId = _ref.mapId,
6314
- _ref$source = _ref.source,
6315
- source = _ref$source === void 0 ? 'app' : _ref$source;
6316
- var _useCoreTranslation = useCoreTranslation(),
6317
- t = _useCoreTranslation.t;
6318
- var dispatch = useDispatch();
6319
- var gfiType = "getfeatureinfo-" + mapId;
6320
- var isOpenInStore = useSelector(function (store) {
6321
- return uiSelectors.getisDialogOpen(store, gfiType);
6322
- });
6323
- var openGfiDialog = React.useCallback(function () {
6324
- dispatch(uiActions.setActiveMapIdForDialog({
6325
- type: gfiType,
6326
- mapId: mapId,
6327
- setOpen: !isOpenInStore,
6328
- source: source,
6329
- origin: mapEnums.MapActionOrigin.map
6330
- }));
6331
- }, [mapId, dispatch, isOpenInStore, source, gfiType]);
6332
- return jsx(MapControlButton, {
6333
- title: t('feature_info_location_info'),
6334
- "data-testid": "open-getfeatureinfo",
6335
- onClick: openGfiDialog,
6336
- isActive: isOpenInStore,
6337
- children: jsx(Info, {})
6338
- });
6727
+ };
6728
+ switch ((_location$geometry = location.geometry) == null ? void 0 : _location$geometry.geometry.type) {
6729
+ case 'Point':
6730
+ case undefined:
6731
+ collection.features.push(marker);
6732
+ break;
6733
+ default:
6734
+ collection.features.push(geometry);
6735
+ }
6736
+ return collection;
6339
6737
  };
6340
-
6341
- var _excluded$1 = ["showMapId"];
6342
- var LegendConnectComponent = function LegendConnectComponent(_ref) {
6343
- var _ref$showMapId = _ref.showMapId,
6344
- showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
6345
- _ref$source = _ref.source,
6346
- source = _ref$source === void 0 ? 'app' : _ref$source,
6347
- _ref$mapId = _ref.mapId,
6348
- initialMapId = _ref$mapId === void 0 ? null : _ref$mapId,
6349
- _ref$multiLegend = _ref.multiLegend,
6350
- multiLegend = _ref$multiLegend === void 0 ? false : _ref$multiLegend;
6351
- var legendType = multiLegend ? "legend-" + initialMapId : "legend";
6352
- var mapIdStore = useSelector(function (store) {
6353
- return uiSelectors.getDialogMapId(store, legendType);
6354
- });
6355
- var _React$useState = React.useState(initialMapId),
6356
- mapId = _React$useState[0],
6357
- setMapId = _React$useState[1];
6358
- React.useEffect(function () {
6359
- setMapId(mapIdStore);
6360
- }, [mapIdStore]);
6361
- var mapLayers = useSelector(function (store) {
6362
- return mapSelectors.getMapLayers(store, mapId);
6363
- });
6364
- var _useSetupDialog = useSetupDialog(legendType, source),
6365
- dialogOrder = _useSetupDialog.dialogOrder,
6366
- isDialogOpen = _useSetupDialog.isDialogOpen,
6367
- uiSource = _useSetupDialog.uiSource,
6368
- setDialogOrder = _useSetupDialog.setDialogOrder,
6369
- onCloseDialog = _useSetupDialog.onCloseDialog;
6370
- return jsx(LegendDialog, {
6371
- layers: mapLayers,
6372
- isOpen: isDialogOpen,
6373
- onClose: onCloseDialog,
6374
- mapId: mapId,
6375
- showMapId: showMapId,
6376
- onMouseDown: setDialogOrder,
6377
- order: dialogOrder,
6378
- source: uiSource
6379
- });
6738
+ var useShiftPressed = function useShiftPressed() {
6739
+ var _React$useState = React__default.useState(false),
6740
+ shiftIsPressed = _React$useState[0],
6741
+ setShiftIsPressed = _React$useState[1];
6742
+ React__default.useEffect(function () {
6743
+ var handleKeyDown = function handleKeyDown(event) {
6744
+ if (event.key === 'Shift') {
6745
+ setShiftIsPressed(true);
6746
+ }
6747
+ };
6748
+ var handleKeyUp = function handleKeyUp(event) {
6749
+ if (event.key === 'Shift') {
6750
+ setShiftIsPressed(false);
6751
+ }
6752
+ };
6753
+ window.addEventListener('keydown', handleKeyDown);
6754
+ window.addEventListener('keyup', handleKeyUp);
6755
+ return function () {
6756
+ window.removeEventListener('keydown', handleKeyDown);
6757
+ window.removeEventListener('keyup', handleKeyUp);
6758
+ };
6759
+ }, []);
6760
+ return shiftIsPressed;
6380
6761
  };
6381
- /**
6382
- * Legend component connected to the store displaying a legend for every layer shown on the active map Id
6383
- * Please note that in order to use this and open/close the dialog, every map on the screen that should be able to show
6384
- * a dialog should have the <LegendMapButtonConnect/> which is used to focus the correct map and open the dialog
6385
- *
6386
- * Expects the following props:
6387
- * @param {boolean} showMapId (optional) showMapId: boolean - show the id of the map in the dialog title of which the legend is shown in te dialog
6388
- * @param {uiTypes.Source} source (optional) source: uiTypes.Source - default is 'app', 'module' makes sure it will be shown on top of the module
6389
-
6390
- * ``` <LegendConnect legendDialogId={legendDialogId} />```
6391
- */
6392
- var LegendConnect = function LegendConnect(_ref2) {
6393
- var _ref2$showMapId = _ref2.showMapId,
6394
- showMapId = _ref2$showMapId === void 0 ? false : _ref2$showMapId,
6395
- props = _objectWithoutPropertiesLoose(_ref2, _excluded$1);
6396
- return jsx(LegendConnectComponent, Object.assign({
6397
- showMapId: showMapId
6398
- }, props));
6762
+ var setBbox = function setBbox(map, bbox) {
6763
+ var to = map.getView().getProjection().getCode();
6764
+ var extent = [].concat(proj4(to, [bbox[0], bbox[1]]), proj4(to, [bbox[2], bbox[3]]));
6765
+ map.getView().fit(extent);
6399
6766
  };
6400
-
6401
- var LegendMapButtonConnect = function LegendMapButtonConnect(_ref) {
6402
- var mapId = _ref.mapId,
6403
- _ref$source = _ref.source,
6404
- source = _ref$source === void 0 ? 'app' : _ref$source,
6405
- _ref$multiLegend = _ref.multiLegend,
6406
- multiLegend = _ref$multiLegend === void 0 ? false : _ref$multiLegend;
6767
+ var useDrawOnMap = function useDrawOnMap(mapId) {
6407
6768
  var dispatch = useDispatch();
6408
- var legendType = multiLegend ? "legend-" + mapId : "legend";
6409
- var currentActiveMapId = useSelector(function (store) {
6410
- return uiSelectors.getDialogMapId(store, legendType);
6769
+ var _useCoreTranslation = useCoreTranslation(),
6770
+ t = _useCoreTranslation.t;
6771
+ var shiftIsPressed = useShiftPressed();
6772
+ var _useContext = useContext(MapContext),
6773
+ map = _useContext.map;
6774
+ var layerIdRef = React__default.useRef();
6775
+ React__default.useEffect(function () {
6776
+ layerIdRef.current = generateLayerId();
6777
+ }, []);
6778
+ var layerId = layerIdRef.current;
6779
+ var isMapPresent = useSelector(function (store) {
6780
+ return mapSelectors.getIsMapPresent(store, mapId);
6411
6781
  });
6412
- var isOpenInStore = useSelector(function (store) {
6413
- return uiSelectors.getisDialogOpen(store, legendType);
6782
+ var isLayerPresent = useSelector(function (store) {
6783
+ return layerSelectors.getIsLayerPresent(store, layerIdRef.current);
6414
6784
  });
6415
- var openLegendDialog = React.useCallback(function () {
6416
- dispatch(uiActions.setActiveMapIdForDialog({
6417
- type: legendType,
6418
- mapId: mapId,
6419
- setOpen: currentActiveMapId !== mapId ? true : !isOpenInStore,
6420
- source: source,
6421
- origin: mapEnums.MapActionOrigin.map
6785
+ var shouldAddLayer = isMapPresent && !isLayerPresent && layerId;
6786
+ React__default.useEffect(function () {
6787
+ if (shouldAddLayer) {
6788
+ dispatch(layerActions.addLayer({
6789
+ mapId: mapId,
6790
+ layerId: layerId,
6791
+ layer: {
6792
+ geojson: emptyGeoJSON,
6793
+ layerType: LayerType.featureLayer
6794
+ },
6795
+ origin: 'LocationSearchConnect'
6796
+ }));
6797
+ }
6798
+ }, [dispatch, layerId, mapId, shouldAddLayer]);
6799
+ var updateGeoJSON = React__default.useCallback(function (location) {
6800
+ var mapFeatureClass = (location == null ? void 0 : location.source) === 'MyMapLocation' ? MapFeatureClass.MyLocation : MapFeatureClass.GenericMarker;
6801
+ var geojson = location ? makeGeoJSONFeatureFromLocation(location, mapFeatureClass, t) : emptyGeoJSON;
6802
+ dispatch(layerActions.updateFeature({
6803
+ layerId: layerId,
6804
+ geojson: geojson
6422
6805
  }));
6423
- }, [currentActiveMapId, dispatch, isOpenInStore, mapId, source, legendType]);
6424
- var isOpen = currentActiveMapId === mapId && isOpenInStore;
6425
- return jsx(LegendButton, {
6426
- isOpen: isOpen,
6427
- openLegendDialog: openLegendDialog
6428
- });
6806
+ }, [dispatch, layerId, t]);
6807
+ var zoomToFeature = React__default.useCallback(function (location) {
6808
+ if (map) {
6809
+ var _location$geometry2;
6810
+ var defaultZoomLevel = 12;
6811
+ setMapCenter(map, location.lon, location.lat, shiftIsPressed ? defaultZoomLevel : undefined);
6812
+ if (shiftIsPressed && location.bbox) {
6813
+ setBbox(map, location.bbox);
6814
+ return;
6815
+ }
6816
+ if (shiftIsPressed && (_location$geometry2 = location.geometry) != null && _location$geometry2.geometry) {
6817
+ var mapSize = map.getSize();
6818
+ if (mapSize) {
6819
+ var buffer = bufferFromZoomLevel(defaultZoomLevel, location.lat, mapSize[0]);
6820
+ var bbox = location.geometry.geometry.type === 'Point' ? bboxFromPoint(location.geometry.geometry, buffer) : bboxFromPolygon(location.geometry.geometry, buffer);
6821
+ setBbox(map, bbox);
6822
+ }
6823
+ }
6824
+ }
6825
+ }, [map, shiftIsPressed]);
6826
+ var onUpdateLocation = React__default.useCallback(function (location) {
6827
+ updateGeoJSON(location);
6828
+ if (location) {
6829
+ zoomToFeature(location);
6830
+ }
6831
+ }, [updateGeoJSON, zoomToFeature]);
6832
+ return [onUpdateLocation];
6429
6833
  };
6430
6834
 
6431
- var SearchControlButtonConnect = function SearchControlButtonConnect(_ref) {
6432
- var mapId = _ref.mapId,
6433
- _ref$source = _ref.source,
6434
- source = _ref$source === void 0 ? 'app' : _ref$source;
6435
- var _useCoreTranslation = useCoreTranslation(),
6436
- t = _useCoreTranslation.t;
6437
- var dispatch = useDispatch();
6835
+ var LocationSearchConnect = function LocationSearchConnect(_ref) {
6836
+ var _ref$mapId = _ref.mapId,
6837
+ mapId = _ref$mapId === void 0 ? '' : _ref$mapId;
6438
6838
  var dialogType = uiTypes.DialogTypes.Search + "-" + mapId;
6439
- var currentActiveMapId = useSelector(function (store) {
6440
- return uiSelectors.getDialogMapId(store, dialogType);
6839
+ var _useSetupDialog = useSetupDialog(dialogType),
6840
+ isDialogOpen = _useSetupDialog.isDialogOpen;
6841
+ var _useDrawOnMap = useDrawOnMap(mapId),
6842
+ updateMapPin = _useDrawOnMap[0];
6843
+ var _useDrawOnMap2 = useDrawOnMap(mapId),
6844
+ updateMyLocation = _useDrawOnMap2[0];
6845
+ var mapLayers = useSelector(function (store) {
6846
+ return layerSelectors.getLayersByMapId(store, mapId);
6441
6847
  });
6442
- var isOpenInStore = useSelector(function (store) {
6443
- return uiSelectors.getisDialogOpen(store, dialogType);
6848
+ var myLocationLayer = mapLayers.find(function (layer) {
6849
+ var _layer$geojson;
6850
+ if ((_layer$geojson = layer.geojson) != null && (_layer$geojson = _layer$geojson.features[0]) != null && (_layer$geojson = _layer$geojson.properties) != null && _layer$geojson.name) {
6851
+ if (layer.geojson.features[0].properties.name === MY_LOCATION) {
6852
+ return true;
6853
+ }
6854
+ }
6855
+ return false;
6444
6856
  });
6445
- var openSearchDialog = React__default.useCallback(function () {
6446
- dispatch(uiActions.setActiveMapIdForDialog({
6447
- type: dialogType,
6448
- mapId: mapId,
6449
- setOpen: currentActiveMapId !== mapId ? true : !isOpenInStore,
6450
- source: source
6451
- }));
6452
- }, [currentActiveMapId, dialogType, dispatch, isOpenInStore, mapId, source]);
6453
- return jsx(MapControlButton, {
6454
- onClick: openSearchDialog,
6455
- title: t('search-title'),
6456
- "aria-label": t('search-title-aria'),
6457
- isActive: isOpenInStore,
6458
- children: jsx(Search, {})
6857
+ var isMyLocationSelected = !!myLocationLayer;
6858
+ return jsx(LocationSearch, {
6859
+ isOpen: isDialogOpen,
6860
+ mapId: mapId,
6861
+ onSelectLocation: updateMapPin,
6862
+ onUpdateMyLocation: updateMyLocation,
6863
+ isMyLocationSelected: isMyLocationSelected
6459
6864
  });
6460
6865
  };
6461
6866
 
6462
- var MY_LOCATION = 'My location';
6463
- var locationOptions = {
6464
- enableHighAccuracy: false,
6465
- timeout: 10000,
6466
- maximumAge: 0
6467
- };
6468
- var MyMapLocation = function MyMapLocation(_ref) {
6469
- var _ref$mapId = _ref.mapId,
6470
- mapId = _ref$mapId === void 0 ? '' : _ref$mapId,
6471
- _ref$isSelected = _ref.isSelected,
6472
- isSelected = _ref$isSelected === void 0 ? false : _ref$isSelected,
6473
- _ref$onUpdateMyLocati = _ref.onUpdateMyLocation,
6474
- onUpdateMyLocation = _ref$onUpdateMyLocati === void 0 ? function () {} : _ref$onUpdateMyLocati;
6475
- var theme = useTheme();
6476
- var _useState = useState(false),
6477
- isLoading = _useState[0],
6478
- setIsLoading = _useState[1];
6479
- var _useState2 = useState(false),
6480
- hasFailed = _useState2[0],
6481
- setHasFailed = _useState2[1];
6482
- var _useCoreTranslation = useCoreTranslation(),
6483
- t = _useCoreTranslation.t;
6484
- var handleLocationClick = function handleLocationClick() {
6485
- if (mapId && isSelected) {
6486
- onUpdateMyLocation(undefined);
6487
- } else if (navigator.geolocation && mapId && !isSelected) {
6488
- setIsLoading(true);
6489
- setHasFailed(false);
6490
- navigator.geolocation.getCurrentPosition(function (success) {
6491
- setIsLoading(false);
6492
- var _success$coords = success.coords,
6493
- latitude = _success$coords.latitude,
6494
- longitude = _success$coords.longitude;
6495
- var location = {
6496
- lat: latitude,
6497
- lon: longitude,
6498
- name: MY_LOCATION,
6499
- source: 'MyMapLocation',
6500
- id: MY_LOCATION
6501
- };
6502
- onUpdateMyLocation(location);
6503
- }, function () {
6504
- setIsLoading(false);
6505
- setHasFailed(true);
6506
- onUpdateMyLocation(undefined);
6507
- }, locationOptions);
6508
- }
6509
- };
6510
- var chooseIcon = function chooseIcon() {
6511
- return hasFailed ? jsx(Exclamation, {
6512
- style: {
6513
- color: theme.palette.geowebColors.functional.error
6514
- },
6515
- "aria-label": "location error"
6516
- }) : jsx(MyLocation, {
6517
- "aria-label": "location default"
6867
+ /* *
6868
+ * Licensed under the Apache License, Version 2.0 (the "License");
6869
+ * you may not use this file except in compliance with the License.
6870
+ * You may obtain a copy of the License at
6871
+ *
6872
+ * http://www.apache.org/licenses/LICENSE-2.0
6873
+ *
6874
+ * Unless required by applicable law or agreed to in writing, software
6875
+ * distributed under the License is distributed on an "AS IS" BASIS,
6876
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6877
+ * See the License for the specific language governing permissions and
6878
+ * limitations under the License.
6879
+ *
6880
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6881
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
6882
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
6883
+ * */
6884
+
6885
+ var types = /*#__PURE__*/Object.freeze({
6886
+ __proto__: null
6887
+ });
6888
+
6889
+ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref) {
6890
+ var layer = _ref.layer,
6891
+ layerId = _ref.layerId,
6892
+ zIndex = _ref.zIndex,
6893
+ style = _ref.style,
6894
+ hoverSelect = _ref.hoverSelect;
6895
+ var store = useStore();
6896
+ var dispatch = useDispatch();
6897
+ var onFeatureClick = React__default.useCallback(function (feature) {
6898
+ var previouslySelectedFeatureIndex = layer.selectedFeatureIndex;
6899
+ var selectedFeatureIndex = layer.geojson.features.findIndex(function (feat) {
6900
+ return feature[0] && feat.id === feature[0].getId();
6518
6901
  });
6519
- };
6520
- return jsx(Box, {
6521
- sx: {
6522
- height: 40,
6523
- padding: 1
6524
- },
6525
- children: isLoading ? jsx(CircularProgress, {
6526
- size: 24,
6527
- "aria-label": "Location loading",
6528
- color: "secondary"
6529
- }) : jsx(CustomIconButton, {
6530
- tooltipTitle: t('search-my-location'),
6531
- "aria-label": t('search-my-location'),
6532
- onClick: handleLocationClick,
6533
- isSelected: isSelected,
6534
- variant: "tool",
6535
- size: "small",
6536
- children: chooseIcon()
6537
- })
6902
+ if (selectedFeatureIndex !== -1 && selectedFeatureIndex !== previouslySelectedFeatureIndex) {
6903
+ dispatch(layerActions.setSelectedFeature({
6904
+ layerId: layerId,
6905
+ selectedFeatureIndex: selectedFeatureIndex
6906
+ }));
6907
+ dispatch(layerActions.updateFeatureProperties({
6908
+ layerId: layerId,
6909
+ properties: {
6910
+ highlightSelectedFeature: true
6911
+ },
6912
+ selectedFeatureIndex: selectedFeatureIndex
6913
+ }));
6914
+ if (previouslySelectedFeatureIndex !== undefined) {
6915
+ dispatch(layerActions.updateFeatureProperties({
6916
+ layerId: layerId,
6917
+ properties: {
6918
+ highlightSelectedFeature: false
6919
+ },
6920
+ selectedFeatureIndex: previouslySelectedFeatureIndex
6921
+ }));
6922
+ }
6923
+ }
6924
+ }, [dispatch, layer.geojson, layer.selectedFeatureIndex, layerId]);
6925
+ var updateFeature = React__default.useCallback(function (geojson, reason) {
6926
+ if (!layerId) {
6927
+ window.console.error('updateFeature without layerId');
6928
+ return;
6929
+ }
6930
+ var activeDrawToolId = drawingToolSelectors.getActiveDrawToolId(store.getState());
6931
+ var activeDrawMode = drawingToolSelectors.getActiveDrawMode(store.getState(), activeDrawToolId);
6932
+ dispatch(layerActions.updateFeature({
6933
+ geojson: geojson,
6934
+ reason: reason,
6935
+ layerId: layerId,
6936
+ shouldAllowMultipleShapes: drawingToolSelectors.getShouldAllowMultipleShapes(store.getState(), activeDrawToolId),
6937
+ geoJSONIntersectionLayerId: drawingToolSelectors.getGeoJSONIntersectionLayerId(store.getState(), activeDrawToolId),
6938
+ geoJSONIntersectionBoundsLayerId: drawingToolSelectors.getGeoJSONIntersectionBoundsLayerId(store.getState(), activeDrawToolId),
6939
+ selectionType: activeDrawMode == null ? void 0 : activeDrawMode.selectionType
6940
+ }));
6941
+ }, [dispatch, store, layerId]);
6942
+ var exitFeatureDrawMode = React__default.useCallback(function (reason) {
6943
+ if (!layerId) {
6944
+ window.console.error('exitFeatureDrawMode without layerId');
6945
+ return;
6946
+ }
6947
+ var activeDrawToolId = drawingToolSelectors.getActiveDrawToolId(store.getState());
6948
+ dispatch(layerActions.exitFeatureDrawMode({
6949
+ reason: reason,
6950
+ layerId: layerId,
6951
+ shouldAllowMultipleShapes: drawingToolSelectors.getShouldAllowMultipleShapes(store.getState(), activeDrawToolId)
6952
+ }));
6953
+ }, [dispatch, store, layerId]);
6954
+ return jsxs(Fragment, {
6955
+ children: [jsx(OpenLayersFeatureLayer, {
6956
+ featureCollection: !layer.isInEditMode ? layer.geojson : undefined,
6957
+ zIndex: zIndex,
6958
+ style: style,
6959
+ hoverSelect: hoverSelect,
6960
+ clickOnFeature: layer.isSelectable ? {
6961
+ onClick: onFeatureClick,
6962
+ hitTolerance: 5
6963
+ } : undefined,
6964
+ visible: layer.enabled,
6965
+ opacity: layer.opacity
6966
+ }), jsx(OpenLayersMapDraw, {
6967
+ drawMode: layer.drawMode,
6968
+ viewOnlyStyle: style,
6969
+ exitDrawModeCallback: exitFeatureDrawMode,
6970
+ geojson: layer.geojson,
6971
+ isInEditMode: layer.isInEditMode || false,
6972
+ selectedFeatureIndex: layer.selectedFeatureIndex || 0,
6973
+ updateGeojson: updateFeature
6974
+ })]
6538
6975
  });
6539
6976
  };
6540
6977
 
@@ -6555,201 +6992,189 @@ var MyMapLocation = function MyMapLocation(_ref) {
6555
6992
  * Copyright 2025 - Finnish Meteorological Institute (FMI)
6556
6993
  * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
6557
6994
  * */
6558
- var config = sessionStorageProvider.getConfig();
6559
- var locationBaseUrl = config.GW_LOCATION_BASE_URL;
6560
- var getLocationBaseUrl = function getLocationBaseUrl() {
6561
- if (locationBaseUrl === undefined) {
6562
- var _config = sessionStorageProvider.getConfig();
6563
- locationBaseUrl = _config.GW_LOCATION_BASE_URL || '';
6995
+ var makePrefetchTimeSpan = function makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, prefetchList) {
6996
+ var timeSliderTimeStepInS = timeSliderStartCenterEndTime.step * 60 * 1000;
6997
+ var prefetchStart = timeSliderStartCenterEndTime.start * 1000;
6998
+ var prefetchEnd = timeSliderStartCenterEndTime.end * 1000;
6999
+ if (isAnimating || !prefetchStart || !prefetchEnd) {
7000
+ return {
7001
+ isAnimating: isAnimating,
7002
+ prefetchList: prefetchList
7003
+ };
6564
7004
  }
6565
- return locationBaseUrl;
6566
- };
6567
- var getLocationList = function getLocationList(search) {
6568
- return fetch(getLocationBaseUrl() + "/locations?search=" + search).then(handleResponse);
7005
+ var roundStart = Math.round(prefetchStart / timeSliderTimeStepInS) * timeSliderTimeStepInS;
7006
+ var roundEnd = Math.round(prefetchEnd / timeSliderTimeStepInS) * timeSliderTimeStepInS + timeSliderTimeStepInS;
7007
+ var timeSpanList = makeTimeList({
7008
+ start: roundStart,
7009
+ end: roundEnd,
7010
+ step: timeSliderTimeStepInS
7011
+ });
7012
+ return {
7013
+ isAnimating: isAnimating,
7014
+ prefetchList: timeSpanList
7015
+ };
6569
7016
  };
6570
- var getLocationDetail = function getLocationDetail(id, source) {
6571
- return fetch(getLocationBaseUrl() + "/locationdetail?id=" + id + "&source=" + source).then(handleResponse);
7017
+ var usePrefetchTimeSpan = function usePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList) {
7018
+ var _useState = useState({
7019
+ isAnimating: isAnimating,
7020
+ prefetchList: animationList || []
7021
+ }),
7022
+ prefetchTimespan = _useState[0],
7023
+ setPrefetchTimeSpan = _useState[1];
7024
+ var makeThrottledPrefetchTimespan = useMemo(function () {
7025
+ return throttle(function (timeSliderStartCenterEndTime, isAnimating, animationList) {
7026
+ return setPrefetchTimeSpan(makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList));
7027
+ }, 500, {
7028
+ leading: true,
7029
+ trailing: true
7030
+ });
7031
+ }, []);
7032
+ useEffect(function () {
7033
+ return makeThrottledPrefetchTimespan(timeSliderStartCenterEndTime, isAnimating, animationList);
7034
+ }, [animationList, isAnimating, makeThrottledPrefetchTimespan, timeSliderStartCenterEndTime]);
7035
+ return prefetchTimespan;
6572
7036
  };
6573
-
6574
- var useLocationList = function useLocationList(search) {
6575
- return useQuery({
6576
- queryKey: ['location-list', search],
6577
- queryFn: function () {
6578
- var _queryFn = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
6579
- return _regeneratorRuntime().wrap(function _callee$(_context) {
6580
- while (1) switch (_context.prev = _context.next) {
6581
- case 0:
6582
- if (!(search.length > 0)) {
6583
- _context.next = 2;
6584
- break;
6585
- }
6586
- return _context.abrupt("return", getLocationList(search));
6587
- case 2:
6588
- return _context.abrupt("return", []);
6589
- case 3:
6590
- case "end":
6591
- return _context.stop();
6592
- }
6593
- }, _callee);
6594
- }));
6595
- function queryFn() {
6596
- return _queryFn.apply(this, arguments);
6597
- }
6598
- return queryFn;
6599
- }()
7037
+ var makeLayerInfoPayload = function makeLayerInfoPayload(payload, mapDimensions, mapId) {
7038
+ // During intialization, try to base the layer dimension on the current map dimension value.
7039
+ var origin = 'onInitializeLayer in OlMapViewLayerConnect';
7040
+ var dimensions = (payload.dimensions || []).map(function (layerDim) {
7041
+ var _find;
7042
+ var currentMapDim = ((_find = (mapDimensions || []).find(function (mapDim) {
7043
+ return mapDim.name === layerDim.name;
7044
+ })) == null ? void 0 : _find.currentValue) || layerDim.currentValue;
7045
+ var wmDim = new WMJSDimension(layerDim);
7046
+ return Object.assign({}, layerDim, {
7047
+ currentValue: wmDim.getClosestValue(currentMapDim, true)
7048
+ });
6600
7049
  });
7050
+ var updatedPayLoad = {
7051
+ origin: origin,
7052
+ layerDimensions: {
7053
+ layerId: payload.layerId,
7054
+ origin: origin,
7055
+ dimensions: dimensions
7056
+ },
7057
+ mapDimensions: {
7058
+ mapId: mapId,
7059
+ origin: origin,
7060
+ dimensions: dimensions
7061
+ }
7062
+ };
7063
+ return updatedPayLoad;
6601
7064
  };
6602
- var useLocationDetail = function useLocationDetail(id, source) {
6603
- if (id === void 0) {
6604
- id = '';
6605
- }
6606
- if (source === void 0) {
6607
- source = '';
6608
- }
6609
- return useQuery({
6610
- queryKey: ['location-detail', {
7065
+ var getCenterOfLinkedFeature = function getCenterOfLinkedFeature(feature, srs) {
7066
+ var _feature$getGeometry;
7067
+ if (feature && ((_feature$getGeometry = feature.getGeometry()) == null ? void 0 : _feature$getGeometry.getType()) === 'Point') {
7068
+ var _feature$getId;
7069
+ var projectionCoords = feature.getGeometry().getCoordinates();
7070
+ var coords = toLonLat(projectionCoords, srs);
7071
+ var id = (feature == null || (_feature$getId = feature.getId()) == null ? void 0 : _feature$getId.toString()) || '';
7072
+ return {
7073
+ lon: coords[0],
7074
+ lat: coords[1],
6611
7075
  id: id,
6612
- source: source
6613
- }],
6614
- queryFn: function queryFn() {
6615
- return getLocationDetail(id, source);
6616
- },
6617
- enabled: !!id
6618
- });
7076
+ serviceId: feature.getProperties().serviceId,
7077
+ collectionId: feature.getProperties().collectionId
7078
+ };
7079
+ }
7080
+ return null;
6619
7081
  };
6620
-
6621
- var LocationSearch = function LocationSearch(_ref) {
6622
- var isOpen = _ref.isOpen,
6623
- _ref$mapId = _ref.mapId,
6624
- mapId = _ref$mapId === void 0 ? '' : _ref$mapId,
6625
- _ref$onSelectLocation = _ref.onSelectLocation,
6626
- onSelectLocation = _ref$onSelectLocation === void 0 ? function () {} : _ref$onSelectLocation,
6627
- _ref$onUpdateMyLocati = _ref.onUpdateMyLocation,
6628
- onUpdateMyLocation = _ref$onUpdateMyLocati === void 0 ? function () {} : _ref$onUpdateMyLocati,
6629
- _ref$isMyLocationSele = _ref.isMyLocationSelected,
6630
- isMyLocationSelected = _ref$isMyLocationSele === void 0 ? false : _ref$isMyLocationSele;
6631
- var theme = useTheme();
6632
- var _useCoreTranslation = useCoreTranslation(),
6633
- t = _useCoreTranslation.t;
6634
- var _useState = useState(''),
6635
- inputValue = _useState[0],
6636
- setInputValue = _useState[1];
6637
- var _useState2 = useState(null),
6638
- selectedValue = _useState2[0],
6639
- setSelectedValue = _useState2[1];
6640
- var debouncedInputValue = useDebounce(inputValue, 300);
6641
- var _useLocationList = useLocationList(debouncedInputValue),
6642
- locationListData = _useLocationList.data;
6643
- var _useLocationDetail = useLocationDetail(selectedValue == null ? void 0 : selectedValue.id, selectedValue == null ? void 0 : selectedValue.source),
6644
- locationDetail = _useLocationDetail.data,
6645
- isFetchingDetail = _useLocationDetail.isFetching;
7082
+ function useFitAndHighlightWarningFeature(_ref) {
7083
+ var view = _ref.view,
7084
+ warningDialogFeatures = _ref.warningDialogFeatures,
7085
+ srs = _ref.srs,
7086
+ mapId = _ref.mapId;
7087
+ var dispatch = useDispatch();
6646
7088
  useEffect(function () {
6647
- if (isFetchingDetail || !isOpen) {
7089
+ var _warningDialogFeature, _geoJsonFeature$prope, _warningDialogFeature2, _geoJsonFeature$bbox;
7090
+ if (!view || !(warningDialogFeatures != null && warningDialogFeatures.length) || !srs) {
6648
7091
  return;
6649
7092
  }
6650
- onSelectLocation(selectedValue ? locationDetail : undefined);
6651
- }, [locationDetail, onSelectLocation, selectedValue, isFetchingDetail, isOpen]);
6652
- return isOpen && mapId ? jsxs(Box, {
6653
- sx: {
6654
- display: 'flex',
6655
- flexDirection: 'row',
6656
- alignItems: 'center',
6657
- position: 'absolute',
6658
- pointerEvents: 'all',
6659
- zIndex: 99,
6660
- left: 50,
6661
- top: 8,
6662
- backgroundColor: theme.palette.geowebColors.textInputField["default"].fill,
6663
- height: 40,
6664
- boxShadow: theme.shadows[6],
6665
- width: 'calc(100% - 50px)',
6666
- maxWidth: 380
6667
- },
6668
- children: [jsx(MyMapLocation, {
6669
- mapId: mapId,
6670
- onUpdateMyLocation: onUpdateMyLocation,
6671
- isSelected: isMyLocationSelected
6672
- }), jsx(Autocomplete, {
6673
- disablePortal: true,
6674
- selectOnFocus: true,
6675
- sx: {
6676
- width: '100%',
6677
- '&.MuiAutocomplete-root .MuiFilledInput-root': {
6678
- height: 40,
6679
- padding: '0px!important',
6680
- '&:before, &:hover:before': {
6681
- borderColor: 'transparent'
6682
- }
6683
- },
6684
- '&.MuiAutocomplete-root .MuiInputLabel-root': {
6685
- lineHeight: '16px',
6686
- maxWidth: 'calc(100% - 40px)',
6687
- ':not(.MuiInputLabel-shrink)': {
6688
- transform: 'translate(12px, 12px) scale(1)'
6689
- }
6690
- },
6691
- '&.MuiAutocomplete-root .MuiFilledInput-input': {
6692
- lineHeight: '20px',
6693
- paddingLeft: '12px',
6694
- paddingTop: '20px'
6695
- }
6696
- },
6697
- getOptionLabel: function getOptionLabel(option) {
6698
- return option.name;
6699
- },
6700
- getOptionKey: function getOptionKey(option) {
6701
- return option.id + option.name;
6702
- },
6703
- filterOptions: function filterOptions(x) {
6704
- return x;
6705
- },
6706
- options: locationListData || [],
6707
- noOptionsText: t('search-no-results'),
6708
- popupIcon: null,
6709
- clearIcon: null,
6710
- onChange: function onChange(_event, newValue) {
6711
- if (newValue && typeof newValue !== 'string') {
6712
- setSelectedValue(newValue);
6713
- setInputValue(newValue.name);
6714
- }
6715
- },
6716
- value: selectedValue,
6717
- inputValue: inputValue,
6718
- isOptionEqualToValue: function isOptionEqualToValue(option, value) {
6719
- return option.id === value.id;
6720
- },
6721
- renderInput: function renderInput(params) {
6722
- return jsx(TextField, Object.assign({}, params, {
6723
- autoFocus: true,
6724
- size: "medium",
6725
- label: t('search-title-long'),
6726
- fullWidth: true,
6727
- variant: "filled",
6728
- onChange: function onChange(event) {
6729
- setInputValue(event.target.value);
6730
- if (selectedValue) {
6731
- setSelectedValue(null);
6732
- }
7093
+ var geoJsonFeature = (_warningDialogFeature = warningDialogFeatures[0]) == null || (_warningDialogFeature = _warningDialogFeature.geoJSON) == null || (_warningDialogFeature = _warningDialogFeature.features) == null ? void 0 : _warningDialogFeature[0];
7094
+ var warningLevel = geoJsonFeature == null || (_geoJsonFeature$prope = geoJsonFeature.properties) == null ? void 0 : _geoJsonFeature$prope.warningLevel;
7095
+ var isAviationWarning = warningLevel === 'SIG' || warningLevel === 'AIR';
7096
+ if (!geoJsonFeature) {
7097
+ return;
7098
+ }
7099
+ var warningDialogFeature = new GeoJSON().readFeature(geoJsonFeature, {
7100
+ featureProjection: srs
7101
+ });
7102
+ var geometry = Array.isArray(warningDialogFeature) ? (_warningDialogFeature2 = warningDialogFeature[0]) == null ? void 0 : _warningDialogFeature2.getGeometry() : warningDialogFeature.getGeometry();
7103
+ if (!geometry) {
7104
+ return;
7105
+ }
7106
+ var featureExtent = (_geoJsonFeature$bbox = geoJsonFeature.bbox) != null ? _geoJsonFeature$bbox : geometry.getExtent();
7107
+ var currentExtent = view.calculateExtent();
7108
+ var intersection = getIntersection(currentExtent, featureExtent);
7109
+ var isCompletelyOutside = !intersection || intersection[0] >= intersection[2] || intersection[1] >= intersection[3];
7110
+ var shouldPan = false;
7111
+ if (isCompletelyOutside) {
7112
+ shouldPan = true;
7113
+ } else {
7114
+ var featureArea = (featureExtent[2] - featureExtent[0]) * (featureExtent[3] - featureExtent[1]);
7115
+ var visibleArea = (intersection[2] - intersection[0]) * (intersection[3] - intersection[1]);
7116
+ var visibleRatio = visibleArea / featureArea;
7117
+ shouldPan = visibleRatio <= 0.5;
7118
+ }
7119
+ if (shouldPan) {
7120
+ view.fit(featureExtent, {
7121
+ duration: 500,
7122
+ padding: [40, 40, 40, 40],
7123
+ maxZoom: 5
7124
+ });
7125
+ }
7126
+ if (!isAviationWarning) {
7127
+ dispatch(layerActions.addLayer({
7128
+ mapId: mapId,
7129
+ layer: {
7130
+ geojson: {
7131
+ type: 'FeatureCollection',
7132
+ features: [geoJsonFeature]
6733
7133
  },
6734
- slotProps: {
6735
- input: Object.assign({}, params.InputProps, {
6736
- endAdornment: jsx(CustomIconButton, {
6737
- tooltipTitle: t('search-clear'),
6738
- onClick: function onClick() {
6739
- setInputValue('');
6740
- setSelectedValue(null);
6741
- },
6742
- sx: {
6743
- marginRight: 1
6744
- },
6745
- children: jsx(Close, {})
6746
- })
6747
- })
6748
- }
7134
+ layerType: LayerType.featureLayer
7135
+ },
7136
+ layerId: 'highlight-layer',
7137
+ origin: 'OlMapViewConnect'
7138
+ }));
7139
+ // eslint-disable-next-line consistent-return
7140
+ return function () {
7141
+ dispatch(layerActions.layerDelete({
7142
+ mapId: mapId,
7143
+ layerId: 'highlight-layer'
6749
7144
  }));
6750
- }
6751
- })]
6752
- }) : null;
7145
+ };
7146
+ }
7147
+ }, [view, warningDialogFeatures, srs, dispatch, mapId]);
7148
+ }
7149
+
7150
+ var OlMapViewLayerConnect = function OlMapViewLayerConnect(layerProps) {
7151
+ var layerId = layerProps.layerId,
7152
+ mapId = layerProps.mapId,
7153
+ zIndex = layerProps.zIndex,
7154
+ debugMode = layerProps.debugMode;
7155
+ var layer = useSelector(function (store) {
7156
+ return layerSelectors.getLayerById(store, layerId);
7157
+ });
7158
+ var mapDimensions = useSelector(function (store) {
7159
+ return mapSelectors.getMapDimensions(store, mapId);
7160
+ });
7161
+ var dispatch = useDispatch();
7162
+ var onInitializeLayer = useCallback(function (initProps) {
7163
+ var updatedPayLoad = makeLayerInfoPayload(initProps, mapDimensions || [], mapId);
7164
+ dispatch(layerActions.onUpdateLayerInformation(updatedPayLoad));
7165
+ }, [dispatch, mapDimensions, mapId]);
7166
+ if (!layerId || !layer) {
7167
+ return null;
7168
+ }
7169
+ var isInsideAcceptanceTime = getIsInsideAcceptanceTime(layer.acceptanceTimeInMinutes, mapDimensions, layer.dimensions);
7170
+ return jsx(OpenLayersLayer, Object.assign({
7171
+ id: "layer-" + (layer == null ? void 0 : layer.id),
7172
+ zIndex: zIndex
7173
+ }, layer, {
7174
+ enabled: isInsideAcceptanceTime && layer.enabled,
7175
+ onInitializeLayer: onInitializeLayer,
7176
+ debugMode: debugMode
7177
+ }), "layer-" + (layer == null ? void 0 : layer.id));
6753
7178
  };
6754
7179
 
6755
7180
  /* *
@@ -6765,136 +7190,93 @@ var LocationSearch = function LocationSearch(_ref) {
6765
7190
  * See the License for the specific language governing permissions and
6766
7191
  * limitations under the License.
6767
7192
  *
6768
- * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6769
- * Copyright 2025 - Finnish Meteorological Institute (FMI)
6770
- * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
7193
+ * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7194
+ * Copyright 2024 - Finnish Meteorological Institute (FMI)
7195
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
6771
7196
  * */
6772
- var geometryStyling = {
6773
- fill: '#FF7800',
6774
- 'fill-opacity': 0.25,
6775
- stroke: '#FF7800',
6776
- 'stroke-opacity': 1,
6777
- 'stroke-width': 4
6778
- };
6779
- var makeGeoJSONFeatureFromLocation = function makeGeoJSONFeatureFromLocation(location, mapFeatureClass, t) {
6780
- var _location$geometry;
6781
- var collection = {
6782
- type: 'FeatureCollection',
6783
- features: []
6784
- };
6785
- var name = mapFeatureClass === MapFeatureClass.MyLocation ? t('my-location') : location.name;
6786
- var geometry = Object.assign({}, location.geometry, {
6787
- properties: Object.assign({}, geometryStyling, {
6788
- name: name,
6789
- mapFeatureClass: mapFeatureClass,
6790
- showNameOnHover: true
6791
- })
6792
- });
6793
- var marker = {
6794
- type: 'Feature',
6795
- properties: {
6796
- name: name,
6797
- mapFeatureClass: mapFeatureClass,
6798
- showNameOnHover: true
6799
- },
6800
- geometry: {
6801
- type: 'Point',
6802
- coordinates: [location.lon, location.lat]
7197
+ var useGetOpenLayersView = function useGetOpenLayersView(mapId, store) {
7198
+ var _useState = useState(),
7199
+ view = _useState[0],
7200
+ setView = _useState[1];
7201
+ var _useState2 = useState(),
7202
+ name = _useState2[0],
7203
+ setName = _useState2[1];
7204
+ var syncGroupState = syncGroupsSelectors.getSynchronizationGroupState(store.getState());
7205
+ var syncGroupView = useMemo(function () {
7206
+ var thisAreaSyncGroupId = syncGroupState.groups.allIds.find(function (id) {
7207
+ var group = syncGroupState.groups.byId[id];
7208
+ return group.type === syncConstants.SYNCGROUPS_TYPE_SETBBOX && group.targets.allIds.indexOf(mapId) !== -1;
7209
+ });
7210
+ return thisAreaSyncGroupId ? getViewObjectForSyncGroup(thisAreaSyncGroupId) : null;
7211
+ }, [mapId, syncGroupState.groups]);
7212
+ useEffect(function () {
7213
+ var mapBbox = mapSelectors.getBbox(store.getState(), mapId);
7214
+ var storedView = syncGroupView || getViewObjectForMapId(mapId);
7215
+ if (storedView.view.getCenter() === undefined && mapBbox.left !== undefined) {
7216
+ storedView.view.fit([mapBbox.left, mapBbox.bottom, mapBbox.right, mapBbox.top]);
6803
7217
  }
7218
+ setName(storedView.name);
7219
+ var setViewFromStoredView = function setViewFromStoredView() {
7220
+ setView(storedView.view);
7221
+ };
7222
+ setViewFromStoredView();
7223
+ var eventKey = storedView.on('change', setViewFromStoredView);
7224
+ return function () {
7225
+ unByKey(eventKey);
7226
+ };
7227
+ }, [syncGroupView, mapId, store]);
7228
+ return {
7229
+ view: view,
7230
+ name: name
6804
7231
  };
6805
- switch ((_location$geometry = location.geometry) == null ? void 0 : _location$geometry.geometry.type) {
6806
- case 'Point':
6807
- case undefined:
6808
- collection.features.push(marker);
6809
- break;
6810
- default:
6811
- collection.features.push(geometry);
6812
- }
6813
- return collection;
6814
- };
6815
- var useDrawOnMap = function useDrawOnMap(mapId) {
6816
- var dispatch = useDispatch();
6817
- var _useCoreTranslation = useCoreTranslation(),
6818
- t = _useCoreTranslation.t;
6819
- var _useContext = useContext(MapContext),
6820
- map = _useContext.map;
6821
- var layerIdRef = React__default.useRef();
6822
- React__default.useEffect(function () {
6823
- layerIdRef.current = generateLayerId();
6824
- }, []);
6825
- var layerId = layerIdRef.current;
6826
- var isMapPresent = useSelector(function (store) {
6827
- return mapSelectors.getIsMapPresent(store, mapId);
6828
- });
6829
- var isLayerPresent = useSelector(function (store) {
6830
- return layerSelectors.getIsLayerPresent(store, layerIdRef.current);
6831
- });
6832
- var shouldAddLayer = isMapPresent && !isLayerPresent && layerId;
6833
- React__default.useEffect(function () {
6834
- if (shouldAddLayer) {
6835
- dispatch(layerActions.addLayer({
6836
- mapId: mapId,
6837
- layerId: layerId,
6838
- layer: {
6839
- geojson: emptyGeoJSON,
6840
- layerType: LayerType.featureLayer
6841
- },
6842
- origin: 'LocationSearchConnect'
6843
- }));
6844
- }
6845
- }, [dispatch, layerId, mapId, shouldAddLayer]);
6846
- var updateGeoJSON = React__default.useCallback(function (location) {
6847
- var mapFeatureClass = (location == null ? void 0 : location.source) === 'MyMapLocation' ? MapFeatureClass.MyLocation : MapFeatureClass.GenericMarker;
6848
- var geojson = location ? makeGeoJSONFeatureFromLocation(location, mapFeatureClass, t) : emptyGeoJSON;
6849
- dispatch(layerActions.updateFeature({
6850
- layerId: layerId,
6851
- geojson: geojson
6852
- }));
6853
- }, [dispatch, layerId, t]);
6854
- var zoomToFeature = React__default.useCallback(function (location) {
6855
- if (map) {
6856
- setMapCenter(map, location.lon, location.lat);
6857
- }
6858
- }, [map]);
6859
- var onUpdateLocation = React__default.useCallback(function (location) {
6860
- updateGeoJSON(location);
6861
- if (location) {
6862
- zoomToFeature(location);
6863
- }
6864
- }, [updateGeoJSON, zoomToFeature]);
6865
- return [onUpdateLocation];
6866
7232
  };
6867
7233
 
6868
- var LocationSearchConnect = function LocationSearchConnect(_ref) {
6869
- var _ref$mapId = _ref.mapId,
6870
- mapId = _ref$mapId === void 0 ? '' : _ref$mapId;
6871
- var dialogType = uiTypes.DialogTypes.Search + "-" + mapId;
6872
- var _useSetupDialog = useSetupDialog(dialogType),
6873
- isDialogOpen = _useSetupDialog.isDialogOpen;
6874
- var _useDrawOnMap = useDrawOnMap(mapId),
6875
- updateMapPin = _useDrawOnMap[0];
6876
- var _useDrawOnMap2 = useDrawOnMap(mapId),
6877
- updateMyLocation = _useDrawOnMap2[0];
6878
- var mapLayers = useSelector(function (store) {
6879
- return layerSelectors.getLayersByMapId(store, mapId);
6880
- });
6881
- var myLocationLayer = mapLayers.find(function (layer) {
6882
- var _layer$geojson;
6883
- if ((_layer$geojson = layer.geojson) != null && (_layer$geojson = _layer$geojson.features[0]) != null && (_layer$geojson = _layer$geojson.properties) != null && _layer$geojson.name) {
6884
- if (layer.geojson.features[0].properties.name === MY_LOCATION) {
6885
- return true;
7234
+ /* *
7235
+ * Licensed under the Apache License, Version 2.0 (the "License");
7236
+ * you may not use this file except in compliance with the License.
7237
+ * You may obtain a copy of the License at
7238
+ *
7239
+ * http://www.apache.org/licenses/LICENSE-2.0
7240
+ *
7241
+ * Unless required by applicable law or agreed to in writing, software
7242
+ * distributed under the License is distributed on an "AS IS" BASIS,
7243
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7244
+ * See the License for the specific language governing permissions and
7245
+ * limitations under the License.
7246
+ *
7247
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7248
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
7249
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
7250
+ * */
7251
+ var LOADING_INDICATOR_UPDATE_INTERVAL_MS = 200;
7252
+ // This hook checks periodically if the loading completeness (percentage) of a set of layerIds has changed. This avoids an action storm of setGetMapIsLoading actions. Should only be used in mapview.
7253
+ var useMapViewLoadingIndicator = function useMapViewLoadingIndicator(mapId, layerIds) {
7254
+ var _useStore = useStore(),
7255
+ dispatch = _useStore.dispatch;
7256
+ var setGetMapLoadingPercentage = React__default.useCallback(function (percentageComplete) {
7257
+ dispatch(loadingIndicatorActions.setGetMapIsLoading({
7258
+ id: mapId,
7259
+ getMapLoadingPercentage: percentageComplete
7260
+ }));
7261
+ }, [dispatch, mapId]);
7262
+ // Check periodically if percentage is changed. If this is the case, dispatch an action.
7263
+ var percentageCompleteRef = React__default.useRef(100);
7264
+ var numberDoneRef = React__default.useRef(0);
7265
+ React__default.useEffect(function () {
7266
+ var intervalId = setInterval(function () {
7267
+ var _openLayersGetMapImag = openLayersGetMapImageStore.loadDuration.getTotalLoadingPercentageForIds(layerIds),
7268
+ percentageComplete = _openLayersGetMapImag.percentage,
7269
+ doneLoading = _openLayersGetMapImag.doneLoading;
7270
+ if (percentageComplete !== percentageCompleteRef.current || doneLoading !== numberDoneRef.current) {
7271
+ numberDoneRef.current = doneLoading;
7272
+ percentageCompleteRef.current = percentageComplete;
7273
+ setGetMapLoadingPercentage(percentageComplete);
6886
7274
  }
6887
- }
6888
- return false;
6889
- });
6890
- var isMyLocationSelected = !!myLocationLayer;
6891
- return jsx(LocationSearch, {
6892
- isOpen: isDialogOpen,
6893
- mapId: mapId,
6894
- onSelectLocation: updateMapPin,
6895
- onUpdateMyLocation: updateMyLocation,
6896
- isMyLocationSelected: isMyLocationSelected
6897
- });
7275
+ }, LOADING_INDICATOR_UPDATE_INTERVAL_MS);
7276
+ return function () {
7277
+ clearInterval(intervalId);
7278
+ };
7279
+ }, [layerIds, mapId, setGetMapLoadingPercentage]);
6898
7280
  };
6899
7281
 
6900
7282
  /* *
@@ -6910,101 +7292,66 @@ var LocationSearchConnect = function LocationSearchConnect(_ref) {
6910
7292
  * See the License for the specific language governing permissions and
6911
7293
  * limitations under the License.
6912
7294
  *
6913
- * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6914
- * Copyright 2025 - Finnish Meteorological Institute (FMI)
6915
- * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
7295
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7296
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
7297
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
6916
7298
  * */
6917
-
6918
- var types = /*#__PURE__*/Object.freeze({
6919
- __proto__: null
6920
- });
6921
-
6922
- var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref) {
6923
- var layer = _ref.layer,
6924
- layerId = _ref.layerId,
6925
- zIndex = _ref.zIndex,
6926
- style = _ref.style,
6927
- hoverSelect = _ref.hoverSelect;
6928
- var store = useStore();
6929
- var dispatch = useDispatch();
6930
- var onFeatureClick = React__default.useCallback(function (feature) {
6931
- var previouslySelectedFeatureIndex = layer.selectedFeatureIndex;
6932
- var selectedFeatureIndex = layer.geojson.features.findIndex(function (feat) {
6933
- return feature[0] && feat.id === feature[0].getId();
7299
+ /**
7300
+ * Get the title for this WMS layer based on its layerId. If not defined, layerId is used instead.
7301
+ * @param layerId
7302
+ * @returns Title for the layer
7303
+ */
7304
+ var getTitle = function getTitle(layerId) {
7305
+ var wmjsLayer = webmapUtils.getWMLayerById(layerId);
7306
+ return wmjsLayer ? wmjsLayer.title || wmjsLayer.name : layerId;
7307
+ };
7308
+ var getFeatureInfoUrl = function getFeatureInfoUrl(layer, mapPinLocation) {
7309
+ /*
7310
+ We need a wmjsLayer to build the getfeatureinfo url (getWMSGetFeatureInfoRequestURL function).
7311
+ But it seems that its dimension are lazely updated (by ReactMapView).
7312
+ Therefore make a clone of this layer and set its dimensions based on the layer object.
7313
+ Otherwise we risk making a getfeatureinfo call with outdated dimension values.
7314
+ */
7315
+ var wmjsLayer = webmapUtils.getWMLayerById(layer.id).cloneLayer();
7316
+ if (mapPinLocation) {
7317
+ // OpenLayers WMS version
7318
+ var source = new ImageWMS({
7319
+ url: wmjsLayer.getmapURL,
7320
+ params: {
7321
+ LAYERS: wmjsLayer.getLayerName()
7322
+ }
6934
7323
  });
6935
- if (selectedFeatureIndex !== -1 && selectedFeatureIndex !== previouslySelectedFeatureIndex) {
6936
- dispatch(layerActions.setSelectedFeature({
6937
- layerId: layerId,
6938
- selectedFeatureIndex: selectedFeatureIndex
6939
- }));
6940
- dispatch(layerActions.updateFeatureProperties({
6941
- layerId: layerId,
6942
- properties: {
6943
- highlightSelectedFeature: true
6944
- },
6945
- selectedFeatureIndex: selectedFeatureIndex
6946
- }));
6947
- if (previouslySelectedFeatureIndex !== undefined) {
6948
- dispatch(layerActions.updateFeatureProperties({
6949
- layerId: layerId,
6950
- properties: {
6951
- highlightSelectedFeature: false
6952
- },
6953
- selectedFeatureIndex: previouslySelectedFeatureIndex
6954
- }));
7324
+ layer.dimensions && layer.dimensions.forEach(function (dim) {
7325
+ var wmDim = wmjsLayer.getDimension(dim.name);
7326
+ if (wmDim && wmDim.getValue() !== dim.currentValue) {
7327
+ wmDim.setValue(dim.currentValue);
6955
7328
  }
6956
- }
6957
- }, [dispatch, layer.geojson, layer.selectedFeatureIndex, layerId]);
6958
- var updateFeature = React__default.useCallback(function (geojson, reason) {
6959
- if (!layerId) {
6960
- window.console.error('updateFeature without layerId');
6961
- return;
6962
- }
6963
- var activeDrawToolId = drawingToolSelectors.getActiveDrawToolId(store.getState());
6964
- var activeDrawMode = drawingToolSelectors.getActiveDrawMode(store.getState(), activeDrawToolId);
6965
- dispatch(layerActions.updateFeature({
6966
- geojson: geojson,
6967
- reason: reason,
6968
- layerId: layerId,
6969
- shouldAllowMultipleShapes: drawingToolSelectors.getShouldAllowMultipleShapes(store.getState(), activeDrawToolId),
6970
- geoJSONIntersectionLayerId: drawingToolSelectors.getGeoJSONIntersectionLayerId(store.getState(), activeDrawToolId),
6971
- geoJSONIntersectionBoundsLayerId: drawingToolSelectors.getGeoJSONIntersectionBoundsLayerId(store.getState(), activeDrawToolId),
6972
- selectionType: activeDrawMode == null ? void 0 : activeDrawMode.selectionType
6973
- }));
6974
- }, [dispatch, store, layerId]);
6975
- var exitFeatureDrawMode = React__default.useCallback(function (reason) {
6976
- if (!layerId) {
6977
- window.console.error('exitFeatureDrawMode without layerId');
6978
- return;
6979
- }
6980
- var activeDrawToolId = drawingToolSelectors.getActiveDrawToolId(store.getState());
6981
- dispatch(layerActions.exitFeatureDrawMode({
6982
- reason: reason,
6983
- layerId: layerId,
6984
- shouldAllowMultipleShapes: drawingToolSelectors.getShouldAllowMultipleShapes(store.getState(), activeDrawToolId)
6985
- }));
6986
- }, [dispatch, store, layerId]);
6987
- return jsxs(Fragment, {
6988
- children: [jsx(OpenLayersFeatureLayer, {
6989
- featureCollection: !layer.isInEditMode ? layer.geojson : undefined,
6990
- zIndex: zIndex,
6991
- style: style,
6992
- hoverSelect: hoverSelect,
6993
- clickOnFeature: layer.isSelectable ? {
6994
- onClick: onFeatureClick,
6995
- hitTolerance: 5
6996
- } : undefined,
6997
- visible: layer.enabled,
6998
- opacity: layer.opacity
6999
- }), jsx(OpenLayersMapDraw, {
7000
- drawMode: layer.drawMode,
7001
- viewOnlyStyle: style,
7002
- exitDrawModeCallback: exitFeatureDrawMode,
7003
- geojson: layer.geojson,
7004
- isInEditMode: layer.isInEditMode || false,
7005
- selectedFeatureIndex: layer.selectedFeatureIndex || 0,
7006
- updateGeojson: updateFeature
7007
- })]
7329
+ });
7330
+ return source.getFeatureInfoUrl([mapPinLocation.projectionX, mapPinLocation.projectionY], mapPinLocation.resolution, mapPinLocation.srs, {
7331
+ INFO_FORMAT: 'text/html'
7332
+ }) + "&" + getMapDimURL(wmjsLayer).toString();
7333
+ }
7334
+ return undefined;
7335
+ };
7336
+ /**
7337
+ * Make a list of GFI Layers to display.
7338
+ * @param layers
7339
+ * @param mapId
7340
+ * @returns
7341
+ */
7342
+ var getLayersToUpdate = function getLayersToUpdate(mapPinLocation, layers) {
7343
+ if (!layers || layers.length === 0 || !mapPinLocation) {
7344
+ return [];
7345
+ }
7346
+ return layers.filter(function (layer) {
7347
+ return layer && layer.enabled && !!webmapUtils.getWMLayerById(layer.id);
7348
+ }).map(function (layer) {
7349
+ var url = getFeatureInfoUrl(layer, mapPinLocation);
7350
+ return {
7351
+ layerId: layer.id,
7352
+ url: url,
7353
+ title: getTitle(layer.id)
7354
+ };
7008
7355
  });
7009
7356
  };
7010
7357
 
@@ -7021,295 +7368,387 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref)
7021
7368
  * See the License for the specific language governing permissions and
7022
7369
  * limitations under the License.
7023
7370
  *
7024
- * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7025
- * Copyright 2025 - Finnish Meteorological Institute (FMI)
7026
- * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
7371
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7372
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
7373
+ * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
7027
7374
  * */
7028
- var makePrefetchTimeSpan = function makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, prefetchList) {
7029
- var timeSliderTimeStepInS = timeSliderStartCenterEndTime.step * 60 * 1000;
7030
- var prefetchStart = timeSliderStartCenterEndTime.start * 1000;
7031
- var prefetchEnd = timeSliderStartCenterEndTime.end * 1000;
7032
- if (isAnimating || !prefetchStart || !prefetchEnd) {
7033
- return {
7034
- isAnimating: isAnimating,
7035
- prefetchList: prefetchList
7036
- };
7037
- }
7038
- var roundStart = Math.round(prefetchStart / timeSliderTimeStepInS) * timeSliderTimeStepInS;
7039
- var roundEnd = Math.round(prefetchEnd / timeSliderTimeStepInS) * timeSliderTimeStepInS + timeSliderTimeStepInS;
7040
- var timeSpanList = makeTimeList({
7041
- start: roundStart,
7042
- end: roundEnd,
7043
- step: timeSliderTimeStepInS
7044
- });
7375
+ var sanitizeHTML = function sanitizeHTML(htmlToBeSanitized) {
7045
7376
  return {
7046
- isAnimating: isAnimating,
7047
- prefetchList: timeSpanList
7377
+ __html: DOMPurify.sanitize(htmlToBeSanitized, {
7378
+ ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'table', 'td', 'tr', 'br', 'hr', 'th'],
7379
+ ALLOWED_ATTR: ['href']
7380
+ })
7048
7381
  };
7049
7382
  };
7050
- var usePrefetchTimeSpan = function usePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList) {
7051
- var _useState = useState({
7052
- isAnimating: isAnimating,
7053
- prefetchList: animationList || []
7054
- }),
7055
- prefetchTimespan = _useState[0],
7056
- setPrefetchTimeSpan = _useState[1];
7057
- var makeThrottledPrefetchTimespan = useMemo(function () {
7058
- return throttle(function (timeSliderStartCenterEndTime, isAnimating, animationList) {
7059
- return setPrefetchTimeSpan(makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList));
7060
- }, 500, {
7061
- leading: true,
7062
- trailing: true
7063
- });
7064
- }, []);
7065
- useEffect(function () {
7066
- return makeThrottledPrefetchTimespan(timeSliderStartCenterEndTime, isAnimating, animationList);
7067
- }, [animationList, isAnimating, makeThrottledPrefetchTimespan, timeSliderStartCenterEndTime]);
7068
- return prefetchTimespan;
7069
- };
7070
- var makeLayerInfoPayload = function makeLayerInfoPayload(payload, mapDimensions, mapId) {
7071
- // During intialization, try to base the layer dimension on the current map dimension value.
7072
- var origin = 'onInitializeLayer in OlMapViewLayerConnect';
7073
- var dimensions = (payload.dimensions || []).map(function (layerDim) {
7074
- var _find;
7075
- var currentMapDim = ((_find = (mapDimensions || []).find(function (mapDim) {
7076
- return mapDim.name === layerDim.name;
7077
- })) == null ? void 0 : _find.currentValue) || layerDim.currentValue;
7078
- var wmDim = new WMJSDimension(layerDim);
7079
- return Object.assign({}, layerDim, {
7080
- currentValue: wmDim.getClosestValue(currentMapDim, true)
7383
+
7384
+ var GetFeatureInfoDialog = function GetFeatureInfoDialog(_ref) {
7385
+ var layers = _ref.layers,
7386
+ isOpen = _ref.isOpen,
7387
+ onClose = _ref.onClose,
7388
+ _ref$onMouseDown = _ref.onMouseDown,
7389
+ onMouseDown = _ref$onMouseDown === void 0 ? function () {} : _ref$onMouseDown,
7390
+ mapId = _ref.mapId,
7391
+ _ref$showMapId = _ref.showMapId,
7392
+ showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
7393
+ _ref$order = _ref.order,
7394
+ order = _ref$order === void 0 ? 0 : _ref$order,
7395
+ _ref$source = _ref.source,
7396
+ source = _ref$source === void 0 ? 'app' : _ref$source,
7397
+ mapPinLocation = _ref.mapPinLocation;
7398
+ var _useCoreTranslation = useCoreTranslation(),
7399
+ t = _useCoreTranslation.t;
7400
+ /* Ref, state and update function for results per layer map */
7401
+ var gfiResultMap = React__default.useRef(new Map()).current;
7402
+ var _React$useState = React__default.useState(),
7403
+ triggerRerender = _React$useState[1];
7404
+ var updateLayerResult = function updateLayerResult(_ref2) {
7405
+ var layerId = _ref2.layerId,
7406
+ data = _ref2.data,
7407
+ isLoading = _ref2.isLoading;
7408
+ gfiResultMap.set(layerId, {
7409
+ data: data,
7410
+ isLoading: isLoading
7081
7411
  });
7082
- });
7083
- var updatedPayLoad = {
7084
- origin: origin,
7085
- layerDimensions: {
7086
- layerId: payload.layerId,
7087
- origin: origin,
7088
- dimensions: dimensions
7089
- },
7090
- mapDimensions: {
7091
- mapId: mapId,
7092
- origin: origin,
7093
- dimensions: dimensions
7094
- }
7412
+ triggerRerender("" + layerId + isLoading);
7095
7413
  };
7096
- return updatedPayLoad;
7097
- };
7098
- var getCenterOfLinkedFeature = function getCenterOfLinkedFeature(feature, srs) {
7099
- var _feature$getGeometry;
7100
- if (feature && ((_feature$getGeometry = feature.getGeometry()) == null ? void 0 : _feature$getGeometry.getType()) === 'Point') {
7101
- var _feature$getId;
7102
- var projectionCoords = feature.getGeometry().getCoordinates();
7103
- var coords = toLonLat(projectionCoords, srs);
7104
- var id = (feature == null || (_feature$getId = feature.getId()) == null ? void 0 : _feature$getId.toString()) || '';
7105
- return {
7106
- lon: coords[0],
7107
- lat: coords[1],
7108
- id: id,
7109
- serviceId: feature.getProperties().serviceId,
7110
- collectionId: feature.getProperties().collectionId
7414
+ /* Build a layerlist array with a set of arguments per layer to do the query for */
7415
+ var layerToUpdateList = isOpen && mapPinLocation ? getLayersToUpdate(mapPinLocation, layers) : [];
7416
+ /*
7417
+ Build a string based on the GFI urls. If this changes for whatever reason we need to update.
7418
+ These strings can change very often, therefore they need to be debounced and only use the most recent result must be used.
7419
+ */
7420
+ var debouncedlayerListString = useDebounce(layerToUpdateList.map(function (layer) {
7421
+ return layer.url;
7422
+ }).join(','), 100);
7423
+ /* Do a GFI call to the server and use the updateLayerResult to provide the results. */
7424
+ var fetchLayerInfo = /*#__PURE__*/function () {
7425
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(url, layerId) {
7426
+ var _yield$axios$get, data, errorMessage;
7427
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
7428
+ while (1) switch (_context.prev = _context.next) {
7429
+ case 0:
7430
+ _context.prev = 0;
7431
+ updateLayerResult({
7432
+ layerId: layerId,
7433
+ data: '',
7434
+ isLoading: true
7435
+ });
7436
+ _context.next = 4;
7437
+ return axios.get(url);
7438
+ case 4:
7439
+ _yield$axios$get = _context.sent;
7440
+ data = _yield$axios$get.data;
7441
+ updateLayerResult({
7442
+ layerId: layerId,
7443
+ data: data,
7444
+ isLoading: false
7445
+ });
7446
+ _context.next = 13;
7447
+ break;
7448
+ case 9:
7449
+ _context.prev = 9;
7450
+ _context.t0 = _context["catch"](0);
7451
+ errorMessage = _context.t0 instanceof Error ? _context.t0.message : 'fetchLayerInfo failed';
7452
+ updateLayerResult({
7453
+ layerId: layerId,
7454
+ data: errorMessage,
7455
+ isLoading: false
7456
+ });
7457
+ case 13:
7458
+ case "end":
7459
+ return _context.stop();
7460
+ }
7461
+ }, _callee, null, [[0, 9]]);
7462
+ }));
7463
+ return function fetchLayerInfo(_x, _x2) {
7464
+ return _ref3.apply(this, arguments);
7111
7465
  };
7112
- }
7113
- return null;
7114
- };
7115
- function useFitAndHighlightWarningFeature(_ref) {
7116
- var view = _ref.view,
7117
- warningDialogFeatures = _ref.warningDialogFeatures,
7118
- srs = _ref.srs,
7119
- mapId = _ref.mapId;
7120
- var dispatch = useDispatch();
7121
- useEffect(function () {
7122
- var _warningDialogFeature, _geoJsonFeature$prope, _warningDialogFeature2, _geoJsonFeature$bbox;
7123
- if (!view || !(warningDialogFeatures != null && warningDialogFeatures.length) || !srs) {
7124
- return;
7125
- }
7126
- var geoJsonFeature = (_warningDialogFeature = warningDialogFeatures[0]) == null || (_warningDialogFeature = _warningDialogFeature.geoJSON) == null || (_warningDialogFeature = _warningDialogFeature.features) == null ? void 0 : _warningDialogFeature[0];
7127
- var warningLevel = geoJsonFeature == null || (_geoJsonFeature$prope = geoJsonFeature.properties) == null ? void 0 : _geoJsonFeature$prope.warningLevel;
7128
- var isAviationWarning = warningLevel === 'SIG' || warningLevel === 'AIR';
7129
- if (!geoJsonFeature) {
7130
- return;
7131
- }
7132
- var warningDialogFeature = new GeoJSON().readFeature(geoJsonFeature, {
7133
- featureProjection: srs
7134
- });
7135
- var geometry = Array.isArray(warningDialogFeature) ? (_warningDialogFeature2 = warningDialogFeature[0]) == null ? void 0 : _warningDialogFeature2.getGeometry() : warningDialogFeature.getGeometry();
7136
- if (!geometry) {
7137
- return;
7138
- }
7139
- var featureExtent = (_geoJsonFeature$bbox = geoJsonFeature.bbox) != null ? _geoJsonFeature$bbox : geometry.getExtent();
7140
- var currentExtent = view.calculateExtent();
7141
- var intersection = getIntersection(currentExtent, featureExtent);
7142
- var isCompletelyOutside = !intersection || intersection[0] >= intersection[2] || intersection[1] >= intersection[3];
7143
- var shouldPan = false;
7144
- if (isCompletelyOutside) {
7145
- shouldPan = true;
7146
- } else {
7147
- var featureArea = (featureExtent[2] - featureExtent[0]) * (featureExtent[3] - featureExtent[1]);
7148
- var visibleArea = (intersection[2] - intersection[0]) * (intersection[3] - intersection[1]);
7149
- var visibleRatio = visibleArea / featureArea;
7150
- shouldPan = visibleRatio <= 0.5;
7151
- }
7152
- if (shouldPan) {
7153
- view.fit(featureExtent, {
7154
- duration: 500,
7155
- padding: [40, 40, 40, 40],
7156
- maxZoom: 5
7466
+ }();
7467
+ /* For each changed getfeature url string, load new data using WMS GetFeatureInfo */
7468
+ React__default.useEffect(function () {
7469
+ if (mapPinLocation && isOpen) {
7470
+ layerToUpdateList.forEach(function (_ref4) {
7471
+ var url = _ref4.url,
7472
+ layerId = _ref4.layerId;
7473
+ void fetchLayerInfo(url, layerId);
7157
7474
  });
7158
7475
  }
7159
- if (!isAviationWarning) {
7160
- dispatch(layerActions.addLayer({
7161
- mapId: mapId,
7162
- layer: {
7163
- geojson: {
7164
- type: 'FeatureCollection',
7165
- features: [geoJsonFeature]
7166
- },
7167
- layerType: LayerType.featureLayer
7476
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7477
+ }, [debouncedlayerListString]);
7478
+ var hasLayers = layers && layers.length > 0;
7479
+ var stopWheelEventPropagationRef = useWheelStopPropagation();
7480
+ return jsx(ToolContainerDraggable, {
7481
+ startPosition: {
7482
+ right: 10,
7483
+ top: 80
7484
+ },
7485
+ minWidth: 100,
7486
+ onClose: onClose,
7487
+ title: showMapId ? t('feature_info_marker_info') + " " + mapId : t('feature_info_marker_info'),
7488
+ initialMaxHeight: 440,
7489
+ isOpen: isOpen,
7490
+ "data-testid": "moveable-getfeatureinfo",
7491
+ bounds: "parent",
7492
+ onMouseDown: onMouseDown,
7493
+ order: order,
7494
+ source: source,
7495
+ children: jsxs(Box, {
7496
+ sx: {
7497
+ padding: 0
7498
+ },
7499
+ children: [isOpen && hasLayers && mapPinLocation && jsx(Box, {
7500
+ "data-testid": "GetFeatureInfoList",
7501
+ ref: stopWheelEventPropagationRef,
7502
+ children: layerToUpdateList.map(function (layer) {
7503
+ var layerId = layer.layerId,
7504
+ title = layer.title,
7505
+ url = layer.url;
7506
+ var result = gfiResultMap.get(layerId);
7507
+ if (!result) {
7508
+ return null;
7509
+ }
7510
+ return jsxs(Grid, {
7511
+ sx: {
7512
+ margin: '4px 6px 4px 6px',
7513
+ padding: '6px',
7514
+ backgroundColor: 'geowebColors.cards.cardContainer',
7515
+ border: 'solid 1px',
7516
+ borderColor: 'geowebColors.cards.cardContainerBorder'
7517
+ },
7518
+ children: [jsxs(Typography, {
7519
+ variant: "subtitle1",
7520
+ children: [title, "\xA0", jsx(CustomIconButton, {
7521
+ sx: {
7522
+ "float": 'right'
7523
+ },
7524
+ "aria-label": "Open layer featureinfo in another page",
7525
+ onClick: function onClick() {
7526
+ window.open(url);
7527
+ },
7528
+ children: jsx(ExitDomain, {})
7529
+ })]
7530
+ }), !result.isLoading ? jsx("div", {
7531
+ style: {
7532
+ fontSize: '11px',
7533
+ padding: '6px',
7534
+ margin: '0',
7535
+ fontFamily: 'Roboto,Helvetica,Arial,sans-serif',
7536
+ fontWeight: '400',
7537
+ lineHeight: '1.75',
7538
+ letterSpacing: '0.25px'
7539
+ },
7540
+ "data-testid": "layer-result-ready-" + layerId,
7541
+ // eslint-disable-next-line react/no-danger
7542
+ dangerouslySetInnerHTML: sanitizeHTML(result.data)
7543
+ }) : jsx("div", {
7544
+ "data-testid": "layer-result-loading-" + layerId,
7545
+ children: jsx(CircularProgress, {
7546
+ "data-testid": "spinner",
7547
+ color: "inherit"
7548
+ })
7549
+ })]
7550
+ }, layerId);
7551
+ })
7552
+ }), hasLayers && !mapPinLocation && jsx(Typography, {
7553
+ "data-testid": "click-on-map-for-info",
7554
+ variant: "subtitle1",
7555
+ sx: {
7556
+ padding: '10px'
7168
7557
  },
7169
- layerId: 'highlight-layer',
7170
- origin: 'OlMapViewConnect'
7171
- }));
7172
- // eslint-disable-next-line consistent-return
7173
- return function () {
7174
- dispatch(layerActions.layerDelete({
7175
- mapId: mapId,
7176
- layerId: 'highlight-layer'
7177
- }));
7178
- };
7179
- }
7180
- }, [view, warningDialogFeatures, srs, dispatch, mapId]);
7181
- }
7558
+ children: t('feature_info_title')
7559
+ }), !hasLayers && jsx(Typography, {
7560
+ "data-testid": "NoLayers",
7561
+ variant: "subtitle1",
7562
+ sx: {
7563
+ padding: '10px'
7564
+ },
7565
+ children: t('feature_info_no_layers')
7566
+ })]
7567
+ })
7568
+ });
7569
+ };
7182
7570
 
7183
- var OlMapViewLayerConnect = function OlMapViewLayerConnect(layerProps) {
7184
- var layerId = layerProps.layerId,
7185
- mapId = layerProps.mapId,
7186
- zIndex = layerProps.zIndex,
7187
- debugMode = layerProps.debugMode;
7188
- var layer = useSelector(function (store) {
7189
- return layerSelectors.getLayerById(store, layerId);
7571
+ var GetFeatureInfoConnect = function GetFeatureInfoConnect(_ref) {
7572
+ var _ref$showMapId = _ref.showMapId,
7573
+ showMapId = _ref$showMapId === void 0 ? false : _ref$showMapId,
7574
+ mapId = _ref.mapId;
7575
+ var dispatch = useDispatch();
7576
+ var getFeatureInfoType = "getfeatureinfo-" + mapId;
7577
+ var mapPinLocation = useSelector(function (store) {
7578
+ return mapSelectors.getPinLocation(store, mapId);
7190
7579
  });
7191
- var mapDimensions = useSelector(function (store) {
7192
- return mapSelectors.getMapDimensions(store, mapId);
7580
+ var toggleMapPinIsVisible = React.useCallback(function (displayMapPin) {
7581
+ dispatch(mapActions.toggleMapPinIsVisible({
7582
+ mapId: mapId,
7583
+ displayMapPin: displayMapPin
7584
+ }));
7585
+ }, [dispatch, mapId]);
7586
+ var enableMapPin = function enableMapPin() {
7587
+ dispatch(mapActions.setDisableMapPin({
7588
+ mapId: mapId,
7589
+ disableMapPin: false
7590
+ }));
7591
+ };
7592
+ var mapLayers = useSelector(function (store) {
7593
+ return mapSelectors.getMapLayers(store, mapId);
7594
+ });
7595
+ var _useSetupDialog = useSetupDialog(getFeatureInfoType),
7596
+ dialogOrder = _useSetupDialog.dialogOrder,
7597
+ isDialogOpen = _useSetupDialog.isDialogOpen,
7598
+ uiSource = _useSetupDialog.uiSource,
7599
+ setDialogOrder = _useSetupDialog.setDialogOrder,
7600
+ onCloseDialog = _useSetupDialog.onCloseDialog;
7601
+ React.useEffect(function () {
7602
+ toggleMapPinIsVisible(isDialogOpen);
7603
+ if (isDialogOpen) {
7604
+ enableMapPin();
7605
+ }
7606
+ /* Do not respond on changes of isMapPinVisible, to allow other components to open/close the mappin. */
7607
+ // eslint-disable-next-line react-hooks/exhaustive-deps
7608
+ }, [isDialogOpen, toggleMapPinIsVisible]);
7609
+ return jsx(GetFeatureInfoDialog, {
7610
+ layers: mapLayers,
7611
+ isOpen: isDialogOpen,
7612
+ onClose: onCloseDialog,
7613
+ mapId: mapId,
7614
+ showMapId: showMapId,
7615
+ onMouseDown: setDialogOrder,
7616
+ order: dialogOrder,
7617
+ source: uiSource,
7618
+ mapPinLocation: mapPinLocation
7193
7619
  });
7194
- var dispatch = useDispatch();
7195
- var onInitializeLayer = useCallback(function (initProps) {
7196
- var updatedPayLoad = makeLayerInfoPayload(initProps, mapDimensions || [], mapId);
7197
- dispatch(layerActions.onUpdateLayerInformation(updatedPayLoad));
7198
- }, [dispatch, mapDimensions, mapId]);
7199
- if (!layerId || !layer) {
7200
- return null;
7201
- }
7202
- var isInsideAcceptanceTime = getIsInsideAcceptanceTime(layer.acceptanceTimeInMinutes, mapDimensions, layer.dimensions);
7203
- return jsx(OpenLayersLayer, Object.assign({
7204
- id: "layer-" + (layer == null ? void 0 : layer.id),
7205
- zIndex: zIndex
7206
- }, layer, {
7207
- enabled: isInsideAcceptanceTime && layer.enabled,
7208
- onInitializeLayer: onInitializeLayer,
7209
- debugMode: debugMode
7210
- }), "layer-" + (layer == null ? void 0 : layer.id));
7211
7620
  };
7212
7621
 
7213
- /* *
7214
- * Licensed under the Apache License, Version 2.0 (the "License");
7215
- * you may not use this file except in compliance with the License.
7216
- * You may obtain a copy of the License at
7217
- *
7218
- * http://www.apache.org/licenses/LICENSE-2.0
7219
- *
7220
- * Unless required by applicable law or agreed to in writing, software
7221
- * distributed under the License is distributed on an "AS IS" BASIS,
7222
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7223
- * See the License for the specific language governing permissions and
7224
- * limitations under the License.
7225
- *
7226
- * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7227
- * Copyright 2024 - Finnish Meteorological Institute (FMI)
7228
- * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
7229
- * */
7230
- var useGetOpenLayersView = function useGetOpenLayersView(mapId, store) {
7231
- var _useState = useState(),
7232
- view = _useState[0],
7233
- setView = _useState[1];
7234
- var _useState2 = useState(),
7235
- name = _useState2[0],
7236
- setName = _useState2[1];
7237
- var syncGroupState = syncGroupsSelectors.getSynchronizationGroupState(store.getState());
7238
- var syncGroupView = useMemo(function () {
7239
- var thisAreaSyncGroupId = syncGroupState.groups.allIds.find(function (id) {
7240
- var group = syncGroupState.groups.byId[id];
7241
- return group.type === syncConstants.SYNCGROUPS_TYPE_SETBBOX && group.targets.allIds.indexOf(mapId) !== -1;
7242
- });
7243
- return thisAreaSyncGroupId ? getViewObjectForSyncGroup(thisAreaSyncGroupId) : null;
7244
- }, [mapId, syncGroupState.groups]);
7245
- useEffect(function () {
7246
- var mapBbox = mapSelectors.getBbox(store.getState(), mapId);
7247
- var storedView = syncGroupView || getViewObjectForMapId(mapId);
7248
- if (storedView.view.getCenter() === undefined && mapBbox.left !== undefined) {
7249
- storedView.view.fit([mapBbox.left, mapBbox.bottom, mapBbox.right, mapBbox.top]);
7250
- }
7251
- setName(storedView.name);
7252
- var setViewFromStoredView = function setViewFromStoredView() {
7253
- setView(storedView.view);
7622
+ var GetFeatureInfoButtonConnect = function GetFeatureInfoButtonConnect(_ref) {
7623
+ var mapId = _ref.mapId,
7624
+ _ref$source = _ref.source,
7625
+ source = _ref$source === void 0 ? 'app' : _ref$source;
7626
+ var _useCoreTranslation = useCoreTranslation(),
7627
+ t = _useCoreTranslation.t;
7628
+ var dispatch = useDispatch();
7629
+ var gfiType = "getfeatureinfo-" + mapId;
7630
+ var isOpenInStore = useSelector(function (store) {
7631
+ return uiSelectors.getisDialogOpen(store, gfiType);
7632
+ });
7633
+ var openGfiDialog = React.useCallback(function () {
7634
+ dispatch(uiActions.setActiveMapIdForDialog({
7635
+ type: gfiType,
7636
+ mapId: mapId,
7637
+ setOpen: !isOpenInStore,
7638
+ source: source,
7639
+ origin: mapEnums.MapActionOrigin.map
7640
+ }));
7641
+ }, [mapId, dispatch, isOpenInStore, source, gfiType]);
7642
+ React.useEffect(function () {
7643
+ var handleKeyPress = function handleKeyPress(event) {
7644
+ if (event.isTrusted && document.activeElement === document.body) {
7645
+ if (event.key === 'i') {
7646
+ openGfiDialog();
7647
+ }
7648
+ }
7254
7649
  };
7255
- setViewFromStoredView();
7256
- var eventKey = storedView.on('change', setViewFromStoredView);
7650
+ document.addEventListener('keyup', handleKeyPress);
7257
7651
  return function () {
7258
- unByKey(eventKey);
7652
+ document.removeEventListener('keyup', handleKeyPress);
7259
7653
  };
7260
- }, [syncGroupView, mapId, store]);
7261
- return {
7262
- view: view,
7263
- name: name
7264
- };
7654
+ }, [openGfiDialog]);
7655
+ return jsx(MapControlButton, {
7656
+ title: t('feature_info_location_info'),
7657
+ "data-testid": "open-getfeatureinfo",
7658
+ onClick: openGfiDialog,
7659
+ isActive: isOpenInStore,
7660
+ children: jsx(LocationInfo, {})
7661
+ });
7265
7662
  };
7266
7663
 
7267
- /* *
7268
- * Licensed under the Apache License, Version 2.0 (the "License");
7269
- * you may not use this file except in compliance with the License.
7270
- * You may obtain a copy of the License at
7271
- *
7272
- * http://www.apache.org/licenses/LICENSE-2.0
7273
- *
7274
- * Unless required by applicable law or agreed to in writing, software
7275
- * distributed under the License is distributed on an "AS IS" BASIS,
7276
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7277
- * See the License for the specific language governing permissions and
7278
- * limitations under the License.
7279
- *
7280
- * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
7281
- * Copyright 2025 - Finnish Meteorological Institute (FMI)
7282
- * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
7283
- * */
7284
- var LOADING_INDICATOR_UPDATE_INTERVAL_MS = 200;
7285
- // This hook checks periodically if the loading completeness (percentage) of a set of layerIds has changed. This avoids an action storm of setGetMapIsLoading actions. Should only be used in mapview.
7286
- var useMapViewLoadingIndicator = function useMapViewLoadingIndicator(mapId, layerIds) {
7287
- var _useStore = useStore(),
7288
- dispatch = _useStore.dispatch;
7289
- var setGetMapLoadingPercentage = React__default.useCallback(function (percentageComplete) {
7290
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
7291
- id: mapId,
7292
- getMapLoadingPercentage: percentageComplete
7293
- }));
7294
- }, [dispatch, mapId]);
7295
- // Check periodically if percentage is changed. If this is the case, dispatch an action.
7296
- var percentageCompleteRef = React__default.useRef(100);
7297
- var numberDoneRef = React__default.useRef(0);
7298
- React__default.useEffect(function () {
7299
- var intervalId = setInterval(function () {
7300
- var _openLayersGetMapImag = openLayersGetMapImageStore.loadDuration.getTotalLoadingPercentageForIds(layerIds),
7301
- percentageComplete = _openLayersGetMapImag.percentage,
7302
- doneLoading = _openLayersGetMapImag.doneLoading;
7303
- if (percentageComplete !== percentageCompleteRef.current || doneLoading !== numberDoneRef.current) {
7304
- numberDoneRef.current = doneLoading;
7305
- percentageCompleteRef.current = percentageComplete;
7306
- setGetMapLoadingPercentage(percentageComplete);
7664
+ var MeasureToolButton = function MeasureToolButton(_ref) {
7665
+ var isActive = _ref.isActive,
7666
+ setIsActive = _ref.setIsActive;
7667
+ var _useCoreTranslation = useCoreTranslation(),
7668
+ t = _useCoreTranslation.t;
7669
+ React.useEffect(function () {
7670
+ var handleKeyPress = function handleKeyPress(event) {
7671
+ if (event.isTrusted && document.activeElement === document.body) {
7672
+ if (event.key === 'm') {
7673
+ setIsActive(!isActive);
7674
+ }
7307
7675
  }
7308
- }, LOADING_INDICATOR_UPDATE_INTERVAL_MS);
7676
+ };
7677
+ document.addEventListener('keyup', handleKeyPress);
7309
7678
  return function () {
7310
- clearInterval(intervalId);
7679
+ document.removeEventListener('keyup', handleKeyPress);
7311
7680
  };
7312
- }, [layerIds, mapId, setGetMapLoadingPercentage]);
7681
+ }, [isActive, setIsActive]);
7682
+ return jsxs(Fragment, {
7683
+ children: [jsx(MapControlButton, {
7684
+ title: t('map-measure-tool'),
7685
+ "data-testid": "measure-tool-button",
7686
+ onClick: function onClick() {
7687
+ return setIsActive(!isActive);
7688
+ },
7689
+ isActive: isActive,
7690
+ children: jsx(Measure, {})
7691
+ }), isActive ? jsx(MapMeasure, {}) : null]
7692
+ });
7693
+ };
7694
+
7695
+ var MapOptionsButtonConnect = function MapOptionsButtonConnect(_ref) {
7696
+ var mapId = _ref.mapId,
7697
+ _ref$getFeatureInfo = _ref.getFeatureInfo,
7698
+ getFeatureInfo = _ref$getFeatureInfo === void 0 ? false : _ref$getFeatureInfo,
7699
+ _ref$measureTool = _ref.measureTool,
7700
+ measureTool = _ref$measureTool === void 0 ? false : _ref$measureTool;
7701
+ var _useCoreTranslation = useCoreTranslation(),
7702
+ t = _useCoreTranslation.t;
7703
+ var _React$useState = React.useState(false),
7704
+ isMapOptionsOpen = _React$useState[0],
7705
+ setIsMapOptionsOpen = _React$useState[1];
7706
+ var _React$useState2 = React.useState(false),
7707
+ isMeasureToolActive = _React$useState2[0],
7708
+ setIsMeasureToolActive = _React$useState2[1];
7709
+ var gfiType = "getfeatureinfo-" + mapId;
7710
+ var isFeatureInfoActive = useSelector(function (store) {
7711
+ return uiSelectors.getisDialogOpen(store, gfiType);
7712
+ });
7713
+ React.useEffect(function () {
7714
+ if (!isMapOptionsOpen && (isMeasureToolActive || isFeatureInfoActive)) {
7715
+ setIsMapOptionsOpen(true);
7716
+ }
7717
+ }, [isFeatureInfoActive, isMapOptionsOpen, isMeasureToolActive]);
7718
+ return getFeatureInfo && measureTool ? jsxs(Stack, {
7719
+ direction: "row",
7720
+ spacing: 1,
7721
+ marginBottom: 1,
7722
+ children: [jsx(MapControlButton, {
7723
+ title: t('map-options-button'),
7724
+ "data-testid": "map-options-button",
7725
+ onClick: function onClick() {
7726
+ return setIsMapOptionsOpen(!isMapOptionsOpen);
7727
+ },
7728
+ shouldShowExtraOptionsIndicator: true,
7729
+ optionsActive: isMapOptionsOpen || isMeasureToolActive || isFeatureInfoActive,
7730
+ children: jsx(Options, {})
7731
+ }), jsxs(Stack, {
7732
+ direction: "row",
7733
+ spacing: 1,
7734
+ sx: {
7735
+ display: isMapOptionsOpen ? 'flex' : 'none'
7736
+ },
7737
+ children: [getFeatureInfo && jsx(GetFeatureInfoButtonConnect, {
7738
+ mapId: mapId
7739
+ }), measureTool && jsx(MeasureToolButton, {
7740
+ isActive: isMeasureToolActive,
7741
+ setIsActive: setIsMeasureToolActive
7742
+ })]
7743
+ })]
7744
+ }) : jsxs(Fragment, {
7745
+ children: [getFeatureInfo && jsx(GetFeatureInfoButtonConnect, {
7746
+ mapId: mapId
7747
+ }), measureTool && jsx(MeasureToolButton, {
7748
+ isActive: isMeasureToolActive,
7749
+ setIsActive: setIsMeasureToolActive
7750
+ })]
7751
+ });
7313
7752
  };
7314
7753
 
7315
7754
  /**
@@ -7621,22 +8060,28 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7621
8060
  }, [mapId, updateLayerInformation, layerIds]);
7622
8061
  useSetIntervalWhenVisible(refetchLayers, 60000);
7623
8062
  useMapViewLoadingIndicator(mapId, mapLayerIds);
7624
- var _React$useState2 = React.useState(false),
7625
- debugMode = _React$useState2[0],
7626
- setDebugMode = _React$useState2[1];
8063
+ var _React$useState2 = React.useState({
8064
+ debugMode: false
8065
+ }),
8066
+ mapMode = _React$useState2[0],
8067
+ setMapMode = _React$useState2[1];
7627
8068
  React.useEffect(function () {
7628
8069
  var handleKeyPress = function handleKeyPress(event) {
7629
- if (event.isTrusted && event.key === 'd' && document.activeElement === document.body) {
7630
- setDebugMode(function (prev) {
7631
- return !prev;
7632
- });
8070
+ if (event.isTrusted && document.activeElement === document.body) {
8071
+ if (event.key === 'd') {
8072
+ setMapMode(function (prev) {
8073
+ return Object.assign({}, prev, {
8074
+ debugMode: !prev.debugMode
8075
+ });
8076
+ });
8077
+ }
7633
8078
  }
7634
8079
  };
7635
8080
  document.addEventListener('keyup', handleKeyPress);
7636
8081
  return function () {
7637
8082
  document.removeEventListener('keyup', handleKeyPress);
7638
8083
  };
7639
- }, [debugMode]);
8084
+ }, [mapMode]);
7640
8085
  var homeExtent = React.useMemo(function () {
7641
8086
  return initialBbox && [initialBbox.left, initialBbox.bottom, initialBbox.right, initialBbox.top];
7642
8087
  }, [initialBbox]);
@@ -7686,7 +8131,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7686
8131
  return jsx(OlMapViewLayerConnect, {
7687
8132
  layerId: layerId,
7688
8133
  zIndex: mapLayerIds.length - zIndex + 1000,
7689
- debugMode: debugMode,
8134
+ debugMode: mapMode.debugMode,
7690
8135
  mapId: mapId
7691
8136
  }, "layer-" + layerId);
7692
8137
  }), overLayers.map(function (layer, zIndex) {
@@ -7741,8 +8186,10 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7741
8186
  mapId: mapId
7742
8187
  }), (controls == null ? void 0 : controls.dimensionSelect) && jsx(MultiDimensionSelectMapButtonsConnect, {
7743
8188
  mapId: mapId
7744
- }), (controls == null ? void 0 : controls.getFeatureInfo) && jsx(GetFeatureInfoButtonConnect, {
7745
- mapId: mapId
8189
+ }), jsx(MapOptionsButtonConnect, {
8190
+ mapId: mapId,
8191
+ getFeatureInfo: controls == null ? void 0 : controls.getFeatureInfo,
8192
+ measureTool: controls == null ? void 0 : controls.measureToolButton
7746
8193
  }), controls == null ? void 0 : controls.additionalMapControls]
7747
8194
  }), (controls == null ? void 0 : controls.multiLegend) && jsx(LegendConnect, {
7748
8195
  showMapId: true,
@@ -8726,7 +9173,7 @@ var TimeSliderConnect = function TimeSliderConnect(_ref) {
8726
9173
  });
8727
9174
  };
8728
9175
 
8729
- var _excluded = ["id", "dockedLayerManagerSize", "title", "layers", "dimensions", "shouldAutoUpdate", "shouldAnimate", "shouldAutoFetch", "initialBbox", "srs", "shouldShowZoomControls", "displayMapPin", "showTimeSlider", "disableTimeSlider", "displayTimeInMap", "displayLayerManagerAndLegendButtonInMap", "displayDimensionSelectButtonInMap", "multiLegend", "shouldShowLayerManager", "shouldShowDockedLayerManager", "showClock", "displayGetFeatureInfoButtonInMap", "shouldDisplayDrawControls", "displaySearchButtonInMap", "displayDataExplorerButtonOnMap", "mapControls", "children", "shouldDisablePrefetching", "tileServerSettings", "featureStyle"];
9176
+ var _excluded = ["id", "dockedLayerManagerSize", "title", "layers", "dimensions", "shouldAutoUpdate", "shouldAnimate", "shouldAutoFetch", "initialBbox", "srs", "shouldShowZoomControls", "displayMapPin", "showTimeSlider", "disableTimeSlider", "displayTimeInMap", "displayLayerManagerAndLegendButtonInMap", "displayDimensionSelectButtonInMap", "multiLegend", "shouldShowLayerManager", "shouldShowDockedLayerManager", "showClock", "displayGetFeatureInfoButtonInMap", "shouldDisplayDrawControls", "displaySearchButtonInMap", "displayDataExplorerButtonOnMap", "mapControls", "children", "shouldDisablePrefetching", "tileServerSettings", "featureStyle", "shouldDisplayMeasureToolButton"];
8730
9177
  var titleStyle = function titleStyle(theme) {
8731
9178
  return {
8732
9179
  position: 'absolute',
@@ -8798,9 +9245,10 @@ var ConfigurableMapConnect = function ConfigurableMapConnect(_ref) {
8798
9245
  tileServerSettings = _ref.tileServerSettings,
8799
9246
  _ref$featureStyle = _ref.featureStyle,
8800
9247
  featureStyle = _ref$featureStyle === void 0 ? genericOpenLayersFeatureStyle : _ref$featureStyle,
9248
+ _ref$shouldDisplayMea = _ref.shouldDisplayMeasureToolButton,
9249
+ shouldDisplayMeasureToolButton = _ref$shouldDisplayMea === void 0 ? false : _ref$shouldDisplayMea,
8801
9250
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
8802
9251
  var dispatch = useDispatch();
8803
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
8804
9252
  var mapId = React__default.useRef(id || webmapUtils.generateMapId()).current;
8805
9253
  var _ref2 = (_useSelector = useSelector(mapSelectors.getdefaultMapSettings)) != null ? _useSelector : {},
8806
9254
  customLayers = _ref2.layers,
@@ -8903,9 +9351,10 @@ var ConfigurableMapConnect = function ConfigurableMapConnect(_ref) {
8903
9351
  dimensionSelect: displayDimensionSelectButtonInMap,
8904
9352
  getFeatureInfo: displayGetFeatureInfoButtonInMap,
8905
9353
  dataExplorerButton: displayDataExplorerButtonOnMap,
9354
+ measureToolButton: shouldDisplayMeasureToolButton,
8906
9355
  additionalMapControls: mapControls
8907
9356
  };
8908
- }, [title, displaySearchButtonInMap, shouldShowZoomControls, displayLayerManagerAndLegendButtonInMap, multiLegend, displayDimensionSelectButtonInMap, displayGetFeatureInfoButtonInMap, displayDataExplorerButtonOnMap, mapControls]);
9357
+ }, [title, displaySearchButtonInMap, shouldShowZoomControls, displayLayerManagerAndLegendButtonInMap, multiLegend, displayDimensionSelectButtonInMap, displayGetFeatureInfoButtonInMap, displayDataExplorerButtonOnMap, shouldDisplayMeasureToolButton, mapControls]);
8909
9358
  return React__default.useMemo(function () {
8910
9359
  renderCounter.count(ConfigurableMapConnect.name + "_" + mapId);
8911
9360
  return jsxs(Box, {
@@ -9292,6 +9741,7 @@ var componentsLookUp = function componentsLookUp(_ref) {
9292
9741
  id: id,
9293
9742
  "data-testid": "coreConfigurableMapConnect",
9294
9743
  displayGetFeatureInfoButtonInMap: true,
9744
+ shouldDisplayMeasureToolButton: true,
9295
9745
  shouldDisplayDrawControls: shouldDisplayDrawControls,
9296
9746
  displaySearchButtonInMap: displaySearchButtonInMap,
9297
9747
  displayDataExplorerButtonOnMap: displayDataExplorerButtonOnMap,
@@ -10325,6 +10775,31 @@ var SelectedFeaturesDialogConnect = function SelectedFeaturesDialogConnect() {
10325
10775
  * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
10326
10776
  * */
10327
10777
  var fakeLocationList = [{
10778
+ id: 'P001',
10779
+ name: 'Test Airport P',
10780
+ source: 'predefined',
10781
+ group: 'airport'
10782
+ }, {
10783
+ id: 'C001',
10784
+ name: 'Finland',
10785
+ source: 'predefined',
10786
+ group: 'country'
10787
+ }, {
10788
+ id: 'C002',
10789
+ name: 'The Netherlands',
10790
+ source: 'predefined',
10791
+ group: 'country'
10792
+ }, {
10793
+ id: 'C003',
10794
+ name: 'Norway',
10795
+ source: 'predefined',
10796
+ group: 'country'
10797
+ }, {
10798
+ id: 'hotel_korpilampi',
10799
+ name: 'Hotel Korpilampi',
10800
+ source: 'predefined',
10801
+ group: 'special'
10802
+ }, {
10328
10803
  id: 'EHAM',
10329
10804
  name: 'Amsterdam Airport Schiphol - EHAM',
10330
10805
  source: 'A'
@@ -10358,6 +10833,46 @@ var fakeLocationList = [{
10358
10833
  source: 'G'
10359
10834
  }];
10360
10835
  var fakeLocationDetailList = [{
10836
+ id: 'P001',
10837
+ name: 'Test Airport P',
10838
+ source: 'predefined',
10839
+ group: 'airport',
10840
+ lat: 52.3,
10841
+ lon: 4.7,
10842
+ geometry: null
10843
+ }, {
10844
+ id: 'C001',
10845
+ name: 'Finland',
10846
+ source: 'predefined',
10847
+ group: 'country',
10848
+ lat: 64,
10849
+ lon: 26,
10850
+ bbox: [20.5486367, 59.690894673, 31.5867034, 70.0922932]
10851
+ }, {
10852
+ id: 'C002',
10853
+ name: 'The Netherlands',
10854
+ source: 'predefined',
10855
+ group: 'country',
10856
+ lat: 52.25,
10857
+ lon: 5.75,
10858
+ bbox: [3.35837827202, 50.7503674993741, 7.22749859212922, 53.5550145156973]
10859
+ }, {
10860
+ id: 'C003',
10861
+ name: 'Norway',
10862
+ source: 'predefined',
10863
+ group: 'country',
10864
+ lat: 62,
10865
+ lon: 10,
10866
+ bbox: [4.504130421063497, 57.959537164107346, 31.168391344451287, 71.1854764998959]
10867
+ }, {
10868
+ id: 'hotel_korpilampi',
10869
+ name: 'Hotel Korpilampi',
10870
+ source: 'predefined',
10871
+ group: 'special',
10872
+ lat: 60.3248395915,
10873
+ lon: 24.7299337387,
10874
+ bbox: [24.7259155527, 60.3235458164, 24.7339503079, 60.3268439875]
10875
+ }, {
10361
10876
  id: 'EHAM',
10362
10877
  name: 'Amsterdam Airport Schiphol - EHAM',
10363
10878
  source: 'A',