@opengeoweb/core 13.1.1 → 14.0.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 (28) hide show
  1. package/index.esm.js +821 -171
  2. package/package.json +10 -10
  3. package/src/lib/components/LayerInfoConnect/LayerInfoButtonConnect.d.ts +1 -0
  4. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/DimensionSelect/DimensionSelectValue.d.ts +3 -1
  5. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/DimensionSelect/DimensionSelectValue.spec.d.ts +1 -0
  6. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/LoadDuration/LoadDuration.d.ts +8 -0
  7. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/LoadDuration/LoadingIndicatorProgressBar.d.ts +9 -0
  8. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/LoadDuration/LoadingIndicatorProgressBar.spec.d.ts +1 -0
  9. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/Menubutton/MenuButton.d.ts +1 -0
  10. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/RenderLayers/RenderFeatureLayers.d.ts +6 -0
  11. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/SelectableFeaturesCheckbox/SelectableFeaturesCheckbox.d.ts +8 -0
  12. package/src/lib/components/LayerManager/LayerContainerRow/LayerRow/SelectableFeaturesCheckbox/SelectableFeaturesCheckboxConnect.d.ts +6 -0
  13. package/src/lib/components/LayerManager/LayerManagerConnect.stories.d.ts +1 -0
  14. package/src/lib/components/LayerManager/index.d.ts +1 -0
  15. package/src/lib/components/MapDrawToolRedux/OpenLayersFeatureLayerConnect.d.ts +1 -1
  16. package/src/lib/components/MapViewConnect/olMapUtils.d.ts +1 -0
  17. package/src/lib/components/MapViewConnect/useMapViewLoadingIndicator.d.ts +1 -0
  18. package/src/lib/components/MapViewConnect/useMapViewLoadingIndicator.spec.d.ts +1 -0
  19. package/src/lib/components/SelectedFeaturesDialog/SelectedFeature.d.ts +8 -0
  20. package/src/lib/components/SelectedFeaturesDialog/SelectedFeaturesDialog.d.ts +14 -0
  21. package/src/lib/components/SelectedFeaturesDialog/SelectedFeaturesDialogConnect.d.ts +2 -0
  22. package/src/lib/components/SelectedFeaturesDialog/SelectedFeaturesDialogConnect.spec.d.ts +1 -0
  23. package/src/lib/components/SelectedFeaturesDialog/SelectedFeaturesDialogConnect.stories.d.ts +7 -0
  24. package/src/lib/components/SelectedFeaturesDialog/storyUtils.d.ts +3 -0
  25. package/src/lib/components/TimeSliderConnect/TimeSliderCurrentTimeBoxConnect.d.ts +8 -0
  26. package/src/lib/index.d.ts +3 -2
  27. package/src/lib/store/store.d.ts +1 -0
  28. package/src/lib/components/EDR/TimeawareEDRLocation.stories.d.ts +0 -15
package/index.esm.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import React__default, { useState, useCallback, useEffect, useContext, useMemo } from 'react';
4
- import { Grid, Box, MenuItem, Typography, useTheme, Popper, Fade, Tooltip, styled, Checkbox, LinearProgress, FormControl, InputLabel, Paper, List, ListItemButton, ListItemText, CircularProgress, ListSubheader, DialogContentText, TextField, InputAdornment, Button, Autocomplete, ListItemIcon, Switch, Select } from '@mui/material';
5
- import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, CustomIconButton, CustomTooltip, TooltipSelect, AlertIcon, useScrollingInIsolation, sliderHeaderStyle, CustomSlider, ToggleMenu, tooltipContainerStyles, renderCounter, AlertBanner, CustomAccordion, CustomDialog, PROJECTION, calculateStartSize, useWheelStopPropagation, ToolContainerDraggable, dateUtils, useDebounce, sessionStorageProvider, usePrevious, ErrorBoundary } from '@opengeoweb/shared';
3
+ import React__default, { useMemo, useState, useCallback, useEffect, useContext } from 'react';
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, dateUtils, useDebounce, sessionStorageProvider, usePrevious, ErrorBoundary } from '@opengeoweb/shared';
6
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';
7
7
  import i18n from 'i18next';
8
8
  import { useTranslation, I18nextProvider } from 'react-i18next';
9
9
  import { TIME_SLIDER_NAMESPACE, timesliderTranslations, defaultTimeSpan, SpeedButton, TimeStepButton, AnimationLengthButton, AnimationLength, TimeSpanButton, secondsPerPxFromCanvasWidth, getNewCenterOfFixedPointZoom, OptionsMenuButton, PlayButton, defaultTimeStep, BackwardForwardStepButton, AutoUpdateButton, NowButton, handleSetNowEvent, TimeSliderButtons, TimeSliderCurrentTimeBox, TimeSliderLegend, onsetNewDateDebounced, defaultSecondsPerPx, moveSelectedTimePx, TimeSlider, getFilteredTime, ControlButtons, OptionsMenu, TimeSliderClock } from '@opengeoweb/time-slider';
10
- import { webmapReactTranslations, WEBMAP_REACT_NAMESPACE, webmapTranslations, WEBMAP_NAMESPACE, LayerInfoButton, LayerInfoDialog, MapControlButton, MapDimensionSelect, dimensionConfig, DimensionSelectDialog, DimensionSelectButton, LegendDialog, LegendButton, MapContext, emptyGeoJSON, MapFeatureClass, setMapCenter, OpenLayersFeatureLayer, OpenLayersMapDraw, makeTimeList, getIsInsideAcceptanceTime, OpenLayersLayer, useSetIntervalWhenVisible, openLayersGetMapImageStore, TimeContext, OpenLayersMapView, WMSLayer, genericOpenLayersFeatureStyle, OpenLayersGetFeatureInfo, MapControls, OpenLayersZoomControl, getLayerUpdateInfo, publicLayers } from '@opengeoweb/webmap-react';
10
+ import { webmapReactTranslations, WEBMAP_REACT_NAMESPACE, webmapTranslations, WEBMAP_NAMESPACE, openLayersGetMapImageStore, LayerInfoButton, useEDRLayerCollection, 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';
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
- import { layerTypes, layerUtils, mapSelectors, layerActions, layerSelectors, serviceSelectors, serviceActions, mapActions, mapEnums, uiSelectors, uiTypes, useSetupDialog, filterLayers, getUserAddedServices, uiActions, genericActions, syncGroupsSelectors, drawingToolSelectors, syncConstants, getViewObjectForSyncGroup, getViewObjectForMapId, genericSelectors, loadingIndicatorActions, defaultLayers, getSingularDrawtoolDrawLayerId, syncGroupsSelector, syncGroupsActions, routerUtils, mapUtils } from '@opengeoweb/store';
14
+ import { layerTypes, layerSelectors, layerActions, loadingIndicatorSelectors, layerUtils, mapSelectors, serviceSelectors, serviceActions, mapActions, mapEnums, uiSelectors, uiTypes, useSetupDialog, filterLayers, getUserAddedServices, uiActions, genericActions, syncGroupsSelectors, drawingToolSelectors, syncConstants, getViewObjectForSyncGroup, getViewObjectForMapId, loadingIndicatorActions, genericSelectors, defaultLayers, getSingularDrawtoolDrawLayerId, syncGroupsSelector, syncGroupsActions, routerUtils, mapUtils } from '@opengeoweb/store';
15
15
  import { webmapUtils, LayerType, queryWMSServiceInfo, queryWMSLayers, queryWMSLayersTree, invalidateWMSGetCapabilities, getWMSServiceId, handleDateUtilsISOString, getMapDimURL, generateLayerId, WMJSDimension, getWMLayerById, WMLayer } from '@opengeoweb/webmap';
16
- import _, { isArray, isEqual, range } from 'lodash';
16
+ import _, { isArray, isEqual, throttle, range } from 'lodash';
17
17
  import { Box as Box$1, styled as styled$1 } from '@mui/system';
18
18
  import { LayerSelectButtonConnect, LayerSelectConnect, DataExplorerButtonConnect } from '@opengeoweb/layer-select';
19
19
  import { unByKey } from 'ol/Observable';
@@ -105,6 +105,7 @@ var en = {
105
105
  "layermanager-acceptance-time-off": "off",
106
106
  "layermanager-acceptance-time-exact": "exact",
107
107
  "layermanager-dimensions-none": "Layer has no time dimension",
108
+ "layermanager-selectable-features": "Selectable features",
108
109
  feature_info_marker_info: "Event marker info",
109
110
  feature_info_location_info: "Get information for a specific location",
110
111
  "language-select": "Language",
@@ -114,7 +115,14 @@ var en = {
114
115
  "workspace-time-scroll-on": "ON",
115
116
  "workspace-time-scroll-info": "This feature affects all views in this workspace",
116
117
  "workspace-time-scroll-toggle-on": "Workspace time scroll ON",
117
- "workspace-time-scroll-toggle-off": "Workspace time scroll OFF"
118
+ "workspace-time-scroll-toggle-off": "Workspace time scroll OFF",
119
+ "featureinfo-title": "Feature info",
120
+ "featureinfo-id": "ID",
121
+ "featureinfo-location": "Location",
122
+ "delete-dialog-title": "Delete layer",
123
+ "delete-dialog-description": "Are you sure you want to delete this layer? EDR layers are not yet available in the Layer Select.",
124
+ "delete-dialog-cancel": "Cancel",
125
+ "delete-dialog-confirm": "Delete"
118
126
  };
119
127
  var fi = {
120
128
  feature_info_title: "Napsauta karttaa nähdäksesi lisätietoja.",
@@ -192,7 +200,10 @@ var fi = {
192
200
  "workspace-time-scroll-on": "PÄÄLLÄ",
193
201
  "workspace-time-scroll-info": "Tämä ominaisuus vaikuttaa kaikkiin näkymiin tämän työtilan sisällä",
194
202
  "workspace-time-scroll-toggle-on": "Työtilan aika scrollaus PÄÄLLÄ",
195
- "workspace-time-scroll-toggle-off": "Työtilan aika scrollaus POIS PÄÄLTÄ"
203
+ "workspace-time-scroll-toggle-off": "Työtilan aika scrollaus POIS PÄÄLTÄ",
204
+ "featureinfo-title": "Ominaisuuden tiedot",
205
+ "featureinfo-id": "ID",
206
+ "featureinfo-location": "Paikka"
196
207
  };
197
208
  var no = {
198
209
  feature_info_title: "Klikk på kartet for å få mer informasjon.",
@@ -270,7 +281,10 @@ var no = {
270
281
  "workspace-time-scroll-on": "ikke oversatt",
271
282
  "workspace-time-scroll-info": "ikke oversatt",
272
283
  "workspace-time-scroll-toggle-on": "ikke oversatt",
273
- "workspace-time-scroll-toggle-off": "ikke oversatt"
284
+ "workspace-time-scroll-toggle-off": "ikke oversatt",
285
+ "featureinfo-title": "ikke oversatt",
286
+ "featureinfo-id": "ikke oversatt",
287
+ "featureinfo-location": "ikke oversatt"
274
288
  };
275
289
  var nl = {
276
290
  feature_info_title: "Klik op de kaart voor informatie.",
@@ -348,7 +362,14 @@ var nl = {
348
362
  "workspace-time-scroll-on": "niet vertaald",
349
363
  "workspace-time-scroll-info": "niet vertaald",
350
364
  "workspace-time-scroll-toggle-on": "niet vertaald",
351
- "workspace-time-scroll-toggle-off": "niet vertaald"
365
+ "workspace-time-scroll-toggle-off": "niet vertaald",
366
+ "featureinfo-title": "niet vertaald",
367
+ "featureinfo-id": "niet vertaald",
368
+ "featureinfo-location": "niet vertaald",
369
+ "delete-dialog-title": "Laag verwijderen",
370
+ "delete-dialog-description": "Weet je zeker dat je deze laag wilt verwijderen? EDR lagen zijn nog niet beschikbaar in de Layer Select.",
371
+ "delete-dialog-cancel": "Annuleren",
372
+ "delete-dialog-confirm": "Verwijderen"
352
373
  };
353
374
  var coreTranslations = {
354
375
  en: en,
@@ -1254,13 +1275,18 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1254
1275
  var _useCoreTranslation = useCoreTranslation(),
1255
1276
  t = _useCoreTranslation.t;
1256
1277
  var dimensionValuesRaw = generatedValues.toReversed().slice(0, 100);
1257
- var latestMap = createLatestMap(dimensionValuesRaw);
1278
+ var latestMap = useMemo(function () {
1279
+ return createLatestMap(dimensionValuesRaw);
1280
+ }, [dimensionValuesRaw]);
1258
1281
  if (!(selectedDimension != null && selectedDimension.name) || !(dimensionValuesRaw != null && dimensionValuesRaw.length)) {
1259
1282
  return null;
1260
1283
  }
1261
1284
  var isReferenceTimeDimensionAndUseLatestIsAvailable = selectedDimension.name === 'reference_time' && useLatestReferenceTime !== undefined;
1262
1285
  var latestValue = dimensionValuesRaw[0];
1263
1286
  var dimensionValues = isReferenceTimeDimensionAndUseLatestIsAvailable ? [].concat(latestMap.latestOptions, dimensionValuesRaw.slice(hideLatestDuplicate ? 1 : 0)) : dimensionValuesRaw.slice().reverse();
1287
+ var extendedDimensionValues = dimensionValues.findIndex(function (dimensionValue) {
1288
+ return dimensionValue === selectedDimension.currentValue;
1289
+ }) === -1 && selectedDimension.currentValue ? [].concat(dimensionValues, [selectedDimension.currentValue]) : dimensionValues;
1264
1290
  var setDimensionValue = function setDimensionValue(dimensionValue) {
1265
1291
  if (isReferenceTimeDimensionAndUseLatestIsAvailable) {
1266
1292
  var index = latestMap.getIndex(dimensionValue);
@@ -1276,15 +1302,15 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1276
1302
  var isOneOfLatest = isReferenceTimeDimensionAndUseLatestIsAvailable && useLatestReferenceTime;
1277
1303
  var getValue = function getValue() {
1278
1304
  if (isOneOfLatest) {
1279
- return latestMap.getValue(selectedDimension.currentValue);
1305
+ return latestMap.getValue(selectedDimension.currentValue || '') || '';
1280
1306
  }
1281
- return selectedDimension.currentValue;
1307
+ return selectedDimension.currentValue || '';
1282
1308
  };
1283
1309
  var getIndex = function getIndex() {
1284
1310
  if (isOneOfLatest) {
1285
- return latestMap.getIndex(selectedDimension.currentValue);
1311
+ return latestMap.getIndex(selectedDimension.currentValue || '');
1286
1312
  }
1287
- return dimensionValues.findIndex(function (dimensionValue) {
1313
+ return extendedDimensionValues.findIndex(function (dimensionValue) {
1288
1314
  return dimensionValue === selectedDimension.currentValue;
1289
1315
  });
1290
1316
  };
@@ -1297,7 +1323,7 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1297
1323
  tooltip: tooltip,
1298
1324
  isEnabled: isEnabled,
1299
1325
  value: getValue(),
1300
- list: dimensionValues.map(function (dimensionValue) {
1326
+ list: extendedDimensionValues.map(function (dimensionValue) {
1301
1327
  return {
1302
1328
  value: dimensionValue
1303
1329
  };
@@ -1318,18 +1344,31 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1318
1344
  children: [jsx(MenuItem, {
1319
1345
  disabled: true,
1320
1346
  children: t('layermanager-dimensions-total-values', {
1321
- total_dimensions: dimensionValues.length
1347
+ total_dimensions: extendedDimensionValues.length
1322
1348
  })
1323
- }), dimensionValues.map(function (dimensionValue) {
1349
+ }), extendedDimensionValues.map(function (dimensionValue, currentIndex) {
1324
1350
  var _valueMappings$select;
1325
1351
  return jsx(MenuItem, {
1326
1352
  value: dimensionValue,
1327
- children: (valueMappings == null || (_valueMappings$select = valueMappings[selectedDimension.name]) == null ? void 0 : _valueMappings$select.call(valueMappings, dimensionValue, isReferenceTimeDimensionAndUseLatestIsAvailable ? latestValue : undefined)) || jsxs("span", {
1328
- style: {
1329
- whiteSpace: 'nowrap'
1353
+ children: (valueMappings == null || (_valueMappings$select = valueMappings[selectedDimension.name]) == null ? void 0 : _valueMappings$select.call(valueMappings, dimensionValue, isReferenceTimeDimensionAndUseLatestIsAvailable ? latestValue : undefined)) || jsxs(Box, {
1354
+ sx: {
1355
+ display: 'flex',
1356
+ alignItems: 'center',
1357
+ '& .MuiSvgIcon-root': {
1358
+ fill: 'currentcolor!important'
1359
+ }
1330
1360
  },
1331
- children: [dimensionValue, !dimensionValue.includes('Latest') && jsxs("i", {
1332
- children: [" ", selectedDimension.units]
1361
+ children: [jsxs("span", {
1362
+ style: {
1363
+ whiteSpace: 'nowrap',
1364
+ textOverflow: 'ellipsis',
1365
+ overflow: 'hidden'
1366
+ },
1367
+ children: [dimensionValue, !(dimensionValue != null && dimensionValue.includes('Latest')) && jsxs("i", {
1368
+ children: [" ", selectedDimension.units]
1369
+ })]
1370
+ }), currentIndex === dimensionValues.length && jsx(AlertIcon, {
1371
+ severity: "error"
1333
1372
  })]
1334
1373
  })
1335
1374
  }, dimensionValue);
@@ -1701,9 +1740,81 @@ var OpacitySelect = function OpacitySelect(_ref) {
1701
1740
  });
1702
1741
  };
1703
1742
 
1743
+ var SelectableFeatures = function SelectableFeatures(_ref) {
1744
+ var layerId = _ref.layerId,
1745
+ isSelectable = _ref.isSelectable,
1746
+ onToggleSelectable = _ref.onToggleSelectable;
1747
+ var _useCoreTranslation = useCoreTranslation(),
1748
+ t = _useCoreTranslation.t;
1749
+ var onClickCheckbox = function onClickCheckbox() {
1750
+ onToggleSelectable();
1751
+ };
1752
+ return jsx(ListItem, {
1753
+ disablePadding: true,
1754
+ sx: {
1755
+ width: '100%',
1756
+ height: '100%',
1757
+ borderBottom: '1px solid #E0E0E0'
1758
+ },
1759
+ children: jsxs(ListItemButton, {
1760
+ role: undefined,
1761
+ onClick: function onClick() {
1762
+ return onClickCheckbox();
1763
+ },
1764
+ disableGutters: true,
1765
+ sx: {
1766
+ paddingX: '16px',
1767
+ paddingY: '6px',
1768
+ height: '100%'
1769
+ },
1770
+ children: [jsx(ListItemText, {
1771
+ id: "selectablefeatures-checkbox-" + layerId,
1772
+ primary: jsx(Typography, {
1773
+ sx: {
1774
+ "float": 'left',
1775
+ fontSize: '16px'
1776
+ },
1777
+ children: t('layermanager-selectable-features')
1778
+ })
1779
+ }), jsx(ListItemIcon, {
1780
+ sx: {
1781
+ width: '42px'
1782
+ },
1783
+ children: jsx(Checkbox, {
1784
+ "data-testid": "selectablefeatures-checkbox-" + layerId,
1785
+ checked: isSelectable,
1786
+ tabIndex: -1,
1787
+ disableRipple: true,
1788
+ name: "selectablefeatures-checkbox-" + layerId
1789
+ })
1790
+ })]
1791
+ })
1792
+ });
1793
+ };
1794
+
1795
+ var SelectableFeaturesCheckboxConnect = function SelectableFeaturesCheckboxConnect(_ref) {
1796
+ var layerId = _ref.layerId;
1797
+ var dispatch = useDispatch();
1798
+ var isSelectable = useSelector(function (store) {
1799
+ return layerSelectors.getIsLayerSelectable(store, layerId);
1800
+ });
1801
+ var toggleSelectable = React.useCallback(function () {
1802
+ return dispatch(layerActions.toggleSelectableFeatures({
1803
+ layerId: layerId
1804
+ }));
1805
+ }, [dispatch, layerId]);
1806
+ return jsx(SelectableFeatures, {
1807
+ layerId: layerId,
1808
+ onToggleSelectable: toggleSelectable,
1809
+ isSelectable: isSelectable
1810
+ });
1811
+ };
1812
+
1704
1813
  var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1705
1814
  var mapId = _ref.mapId,
1706
1815
  layerId = _ref.layerId,
1816
+ _ref$isFeatureLayer = _ref.isFeatureLayer,
1817
+ isFeatureLayer = _ref$isFeatureLayer === void 0 ? false : _ref$isFeatureLayer,
1707
1818
  onLayerDuplicate = _ref.onLayerDuplicate,
1708
1819
  tooltipTitle = _ref.tooltipTitle,
1709
1820
  icon = _ref.icon;
@@ -1732,7 +1843,10 @@ var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1732
1843
  icon: jsx(Copy, {})
1733
1844
  }],
1734
1845
  tooltipTitle: nonEmptyTooltipTitle,
1735
- buttonIcon: icon
1846
+ buttonIcon: icon,
1847
+ children: isFeatureLayer && jsx(SelectableFeaturesCheckboxConnect, {
1848
+ layerId: layerId
1849
+ })
1736
1850
  });
1737
1851
  };
1738
1852
 
@@ -2054,6 +2168,74 @@ var MissingData = function MissingData(_ref) {
2054
2168
  });
2055
2169
  };
2056
2170
 
2171
+ /* *
2172
+ * Licensed under the Apache License, Version 2.0 (the "License");
2173
+ * you may not use this file except in compliance with the License.
2174
+ * You may obtain a copy of the License at
2175
+ *
2176
+ * http://www.apache.org/licenses/LICENSE-2.0
2177
+ *
2178
+ * Unless required by applicable law or agreed to in writing, software
2179
+ * distributed under the License is distributed on an "AS IS" BASIS,
2180
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2181
+ * See the License for the specific language governing permissions and
2182
+ * limitations under the License.
2183
+ *
2184
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2185
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
2186
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
2187
+ * */
2188
+ var loadingIndicatorContainerStyle = {
2189
+ "float": 'left',
2190
+ zIndex: 1,
2191
+ overflow: 'hidden'
2192
+ };
2193
+ var colorBackground = '#444444ff';
2194
+ var colorLoading = '#287DFF';
2195
+ var colorLoaded = '#00bf0e';
2196
+ var loadingIndicatorStyle = {
2197
+ display: 'block',
2198
+ marginTop: '20px',
2199
+ marginLeft: '0x',
2200
+ padding: 0,
2201
+ position: 'absolute',
2202
+ background: colorBackground
2203
+ };
2204
+ var clamp = function clamp(number, min, max) {
2205
+ return Math.max(min, Math.min(number, max));
2206
+ };
2207
+ var LoadingIndicatorProgressBar = function LoadingIndicatorProgressBar(_ref) {
2208
+ var progressPercentage = _ref.progressPercentage,
2209
+ _ref$width = _ref.width,
2210
+ loadingBarWidthInPx = _ref$width === void 0 ? 24 : _ref$width,
2211
+ _ref$height = _ref.height,
2212
+ loadingBarHeightPx = _ref$height === void 0 ? 3 : _ref$height,
2213
+ _ref$top = _ref.top,
2214
+ top = _ref$top === void 0 ? 20 : _ref$top,
2215
+ _ref$left = _ref.left,
2216
+ left = _ref$left === void 0 ? 0 : _ref$left;
2217
+ var width = clamp(progressPercentage, 0, 100) / (100 / loadingBarWidthInPx);
2218
+ var style = Object.assign({}, loadingIndicatorStyle, {
2219
+ width: loadingBarWidthInPx + "px",
2220
+ height: loadingBarHeightPx + "px",
2221
+ marginTop: top + "px",
2222
+ marginLeft: left + "px"
2223
+ });
2224
+ return progressPercentage >= 0 ? jsxs("span", {
2225
+ style: loadingIndicatorContainerStyle,
2226
+ "data-testid": "loadDurationProgressBar",
2227
+ children: [jsx("span", {
2228
+ style: style
2229
+ }), jsx("span", {
2230
+ "data-testid": "LoadingIndicatorProgressBarSpan",
2231
+ style: Object.assign({}, style, {
2232
+ width: width + "px",
2233
+ background: progressPercentage < 100 ? colorLoading : colorLoaded
2234
+ })
2235
+ })]
2236
+ }) : jsx("span", {});
2237
+ };
2238
+
2057
2239
  var MILLISECONDS_PER_SECOND = 1e3;
2058
2240
  var MAX_DURATION_IN_SECONDS = 60;
2059
2241
  var MIN_DURATION_IN_SECONDS = 0.1;
@@ -2062,7 +2244,9 @@ var DECIMALS_IN_TOOLTIP = 3;
2062
2244
  var LoadDuration = function LoadDuration(_ref) {
2063
2245
  var mapId = _ref.mapId,
2064
2246
  layerId = _ref.layerId;
2065
- var loadDurationLabel = useLoadDurationLabel(mapId, layerId);
2247
+ var _useLoadDurationLabel = useLoadDurationLabel(mapId, layerId),
2248
+ loadDurationLabel = _useLoadDurationLabel[0],
2249
+ percentage = _useLoadDurationLabel[1];
2066
2250
  var _React$useState = React.useState(),
2067
2251
  tooltipText = _React$useState[0],
2068
2252
  setTooltipText = _React$useState[1];
@@ -2079,15 +2263,24 @@ var LoadDuration = function LoadDuration(_ref) {
2079
2263
  setTooltipText(getDurationTooltip(duration));
2080
2264
  }
2081
2265
  },
2082
- children: jsx(Typography, {
2266
+ children: jsxs(Typography, {
2083
2267
  component: "div",
2084
2268
  variant: "subtitle2",
2085
2269
  whiteSpace: "nowrap",
2086
- "data-testid": "loadDuration",
2087
2270
  sx: {
2088
- fontSize: 12
2271
+ fontSize: 12,
2272
+ width: '100%',
2273
+ textAlign: 'center'
2089
2274
  },
2090
- children: loadDurationLabel
2275
+ children: [percentage < 100 && jsx(LoadingIndicatorProgressBar, {
2276
+ progressPercentage: percentage,
2277
+ width: 32,
2278
+ height: 4,
2279
+ top: 17
2280
+ }), jsx("span", {
2281
+ "data-testid": "loadDuration",
2282
+ children: loadDurationLabel
2283
+ })]
2091
2284
  })
2092
2285
  });
2093
2286
  };
@@ -2098,13 +2291,7 @@ var getDurationTooltip = function getDurationTooltip(milliSeconds) {
2098
2291
  return roundToDecimals(milliSeconds / MILLISECONDS_PER_SECOND, DECIMALS_IN_TOOLTIP) + " s";
2099
2292
  };
2100
2293
  var getImageLoadDuration = function getImageLoadDuration(layerId) {
2101
- var layer = webmapUtils.getWMLayerById(layerId);
2102
- var currentRequestedGetMapURL = layer == null ? void 0 : layer.getCurrentRequestedGetMapURL();
2103
- if (currentRequestedGetMapURL === undefined) {
2104
- return undefined;
2105
- }
2106
- // TODO: https://gitlab.com/opengeoweb/geoweb-assets/-/issues/3958
2107
- return 0;
2294
+ return openLayersGetMapImageStore.loadDuration.getLoadDurationForId(layerId);
2108
2295
  };
2109
2296
  var roundToDecimals = function roundToDecimals(num, decimals) {
2110
2297
  return num.toLocaleString('en', {
@@ -2112,6 +2299,20 @@ var roundToDecimals = function roundToDecimals(num, decimals) {
2112
2299
  useGrouping: false
2113
2300
  });
2114
2301
  };
2302
+ var getLoadDurationLabel = function getLoadDurationLabel(layerId) {
2303
+ var loadDurationMs = getImageLoadDuration(layerId);
2304
+ if (loadDurationMs === undefined) {
2305
+ return '-';
2306
+ }
2307
+ var loadDurationInSeconds = loadDurationMs / MILLISECONDS_PER_SECOND;
2308
+ if (loadDurationInSeconds > MAX_DURATION_IN_SECONDS) {
2309
+ return "> " + MAX_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2310
+ }
2311
+ if (loadDurationInSeconds < MIN_DURATION_IN_SECONDS) {
2312
+ return "< " + MIN_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2313
+ }
2314
+ return roundToDecimals(loadDurationInSeconds, DECIMALS_IN_LABEL) + " s";
2315
+ };
2115
2316
  /**
2116
2317
  * Hook to subscribe to changes in the load duration for a map layer.
2117
2318
  * This will only trigger a render when the load duration rounded down to seconds changes for the given layer and map combination
@@ -2120,26 +2321,12 @@ var roundToDecimals = function roundToDecimals(num, decimals) {
2120
2321
  * @returns {number}
2121
2322
  */
2122
2323
  var useLoadDurationLabel = function useLoadDurationLabel(mapId, layerId) {
2123
- var subscribe = React.useCallback(
2124
- // eslint-disable-next-line no-unused-vars
2125
- function (onStoreChange) {
2126
- return function () {};
2127
- }, []);
2128
- var getSnapshot = React.useCallback(function () {
2129
- var loadDurationMs = getImageLoadDuration(layerId);
2130
- if (loadDurationMs === undefined) {
2131
- return '-';
2132
- }
2133
- var loadDurationInSeconds = loadDurationMs / MILLISECONDS_PER_SECOND;
2134
- if (loadDurationInSeconds > MAX_DURATION_IN_SECONDS) {
2135
- return "> " + MAX_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2136
- }
2137
- if (loadDurationInSeconds < MIN_DURATION_IN_SECONDS) {
2138
- return "< " + MIN_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2139
- }
2140
- return roundToDecimals(loadDurationInSeconds, DECIMALS_IN_LABEL) + " s";
2141
- }, [layerId]);
2142
- return React.useSyncExternalStore(subscribe, getSnapshot);
2324
+ // Selector which triggers update of all labels in the layer manager when percentage of the map changes.
2325
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2326
+ useSelector(function (store) {
2327
+ return loadingIndicatorSelectors.getMapLoadingPercentage(store, mapId);
2328
+ });
2329
+ return [getLoadDurationLabel(layerId), openLayersGetMapImageStore.loadDuration.getTotalLoadingPercentageForIds([layerId]).percentage];
2143
2330
  };
2144
2331
 
2145
2332
  var LeftButtons = function LeftButtons(_ref) {
@@ -2578,10 +2765,17 @@ var DeleteLayerConnect = function DeleteLayerConnect(_ref) {
2578
2765
  var _useCoreTranslation = useCoreTranslation(),
2579
2766
  t = _useCoreTranslation.t;
2580
2767
  var dispatch = useDispatch();
2768
+ var confirmationDialog = useConfirmationDialog();
2581
2769
  var nonEmptyTooltipTitle = tooltipTitle != null ? tooltipTitle : t('layermanager-layer-delete');
2582
2770
  var layerIndex = useSelector(function (store) {
2583
2771
  return mapSelectors.getLayerIndexByLayerId(store, mapId, layerId);
2584
2772
  });
2773
+ var layerType = useSelector(function (store) {
2774
+ return layerSelectors.getLayerType(store, layerId);
2775
+ });
2776
+ var isLayerEnabled = useSelector(function (store) {
2777
+ return layerSelectors.getLayerEnabled(store, layerId);
2778
+ });
2585
2779
  var layerDelete = React.useCallback(function (_ref2) {
2586
2780
  var mapId = _ref2.mapId,
2587
2781
  layerId = _ref2.layerId;
@@ -2592,13 +2786,32 @@ var DeleteLayerConnect = function DeleteLayerConnect(_ref) {
2592
2786
  origin: layerTypes.LayerActionOrigin.layerManager
2593
2787
  }));
2594
2788
  }, [dispatch, layerIndex]);
2595
- var isLayerEnabled = useSelector(function (store) {
2596
- return layerSelectors.getLayerEnabled(store, layerId);
2597
- });
2789
+ var onDelete = React.useCallback(function (_ref3) {
2790
+ var mapId = _ref3.mapId,
2791
+ layerId = _ref3.layerId;
2792
+ if (layerType === LayerType.edrFeatureLayer) {
2793
+ void confirmationDialog({
2794
+ title: t('delete-dialog-title'),
2795
+ description: t('delete-dialog-description'),
2796
+ confirmLabel: t('delete-dialog-confirm'),
2797
+ cancelLabel: t('delete-dialog-cancel')
2798
+ }).then(function () {
2799
+ layerDelete({
2800
+ mapId: mapId,
2801
+ layerId: layerId
2802
+ });
2803
+ });
2804
+ } else {
2805
+ layerDelete({
2806
+ mapId: mapId,
2807
+ layerId: layerId
2808
+ });
2809
+ }
2810
+ }, [layerType, confirmationDialog, t, layerDelete]);
2598
2811
  return jsx(CustomIconButton, {
2599
2812
  tooltipTitle: nonEmptyTooltipTitle,
2600
2813
  onClick: function onClick() {
2601
- layerDelete({
2814
+ return onDelete({
2602
2815
  mapId: mapId,
2603
2816
  layerId: layerId
2604
2817
  });
@@ -2951,6 +3164,23 @@ var RenderEDRLayers = function RenderEDRLayers(_ref) {
2951
3164
  });
2952
3165
  };
2953
3166
 
3167
+ var RenderFeatureLayers = function RenderFeatureLayers(_ref) {
3168
+ var layerName = _ref.layerName;
3169
+ return jsx(CustomTooltip, {
3170
+ title: layerName,
3171
+ children: jsx(Typography, {
3172
+ variant: "caption",
3173
+ sx: {
3174
+ fontWeight: 'medium',
3175
+ paddingLeft: '8px',
3176
+ textOverflow: 'ellipsis',
3177
+ overflow: 'hidden'
3178
+ },
3179
+ children: layerName
3180
+ })
3181
+ });
3182
+ };
3183
+
2954
3184
  var RenderLayersConnect = function RenderLayersConnect(_ref) {
2955
3185
  var layerId = _ref.layerId,
2956
3186
  mapId = _ref.mapId,
@@ -2966,14 +3196,14 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
2966
3196
  var layerType = useSelector(function (store) {
2967
3197
  return layerSelectors.getLayerType(store, layerId);
2968
3198
  });
2969
- var layerService = useSelector(function (store) {
3199
+ var serviceUrl = useSelector(function (store) {
2970
3200
  return layerSelectors.getLayerService(store, layerId);
2971
3201
  });
2972
3202
  var isLayerEnabled = useSelector(function (store) {
2973
3203
  return layerSelectors.getLayerEnabled(store, layerId);
2974
3204
  });
2975
3205
  var service = useSelector(function (store) {
2976
- return serviceSelectors.getServiceByUrl(store, layerService);
3206
+ return serviceSelectors.getServiceByUrl(store, serviceUrl);
2977
3207
  });
2978
3208
  var layerOptions = useSelector(function (store) {
2979
3209
  return layerSelectors.getLayerOptions(store, layerId);
@@ -2981,7 +3211,7 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
2981
3211
  var serviceSetLayers = React.useCallback(function (payload) {
2982
3212
  dispatch(serviceActions.serviceSetLayers(payload));
2983
3213
  }, [dispatch]);
2984
- var addService = /*#__PURE__*/function () {
3214
+ var addWmsService = /*#__PURE__*/function () {
2985
3215
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(serviceUrl) {
2986
3216
  var _layers, wmService;
2987
3217
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -3016,15 +3246,45 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
3016
3246
  }
3017
3247
  }, _callee, null, [[0, 10]]);
3018
3248
  }));
3019
- return function addService(_x) {
3249
+ return function addWmsService(_x) {
3020
3250
  return _ref2.apply(this, arguments);
3021
3251
  };
3022
3252
  }();
3023
- if (!service) {
3024
- void addService(layerService);
3253
+ var isEdrLayer = layerType === LayerType.edrFeatureLayer;
3254
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3255
+ if (!service && !isEdrLayer && !isFeatureLayer) {
3256
+ void addWmsService(serviceUrl);
3025
3257
  }
3258
+ var _useEDRLayerCollectio = useEDRLayerCollection(serviceUrl, '', isEdrLayer),
3259
+ data = _useEDRLayerCollectio.data;
3260
+ React.useEffect(function () {
3261
+ if (!(data != null && data.parameter_names) || service) {
3262
+ return;
3263
+ }
3264
+ var layers = Object.entries(data == null ? void 0 : data.parameter_names).map(function (parameter) {
3265
+ return {
3266
+ name: parameter[0],
3267
+ title: parameter[1].label,
3268
+ styles: defaultEdrStyles,
3269
+ leaf: true,
3270
+ path: []
3271
+ };
3272
+ }).sort(function (paramA, paramB) {
3273
+ var _paramA$title, _paramB$title;
3274
+ return ((_paramA$title = paramA.title) != null ? _paramA$title : '').localeCompare((_paramB$title = paramB.title) != null ? _paramB$title : '');
3275
+ });
3276
+ serviceSetLayers({
3277
+ id: data.id,
3278
+ name: data.title || 'EDR collection',
3279
+ serviceUrl: serviceUrl,
3280
+ "abstract": data.description,
3281
+ layers: layers,
3282
+ scope: 'system',
3283
+ type: 'EDR'
3284
+ });
3285
+ }, [data, serviceUrl, service, serviceSetLayers]);
3026
3286
  var layers = useSelector(function (store) {
3027
- return serviceSelectors.getLayersFromServiceSelector(store, layerService);
3287
+ return serviceSelectors.getLayersFromServiceSelector(store, serviceUrl);
3028
3288
  });
3029
3289
  var layerChangeName = React.useCallback(function (_ref3) {
3030
3290
  var layerId = _ref3.layerId,
@@ -3066,6 +3326,11 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
3066
3326
  skipLocalStyling: skipLocalStyling
3067
3327
  });
3068
3328
  }
3329
+ if (layerType === LayerType.featureLayer) {
3330
+ return jsx(RenderFeatureLayers, {
3331
+ layerName: layerDisplayName
3332
+ });
3333
+ }
3069
3334
  return jsx(RenderLayers, {
3070
3335
  layers: layers,
3071
3336
  layerName: layerName,
@@ -3087,6 +3352,10 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3087
3352
  tooltipTitle = _ref.tooltipTitle,
3088
3353
  icon = _ref.icon;
3089
3354
  var dispatch = useDispatch();
3355
+ var layerType = useSelector(function (store) {
3356
+ return layerSelectors.getLayerType(store, layerId);
3357
+ });
3358
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3090
3359
  var duplicateLayer = React.useCallback(function (_ref2) {
3091
3360
  var newLayerId = _ref2.newLayerId,
3092
3361
  mapId = _ref2.mapId;
@@ -3100,6 +3369,7 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3100
3369
  return jsx(LayerManagerMenuButton, {
3101
3370
  layerId: layerId,
3102
3371
  mapId: mapId,
3372
+ isFeatureLayer: isFeatureLayer,
3103
3373
  onLayerDuplicate: function onLayerDuplicate() {
3104
3374
  duplicateLayer({
3105
3375
  newLayerId: webmapUtils.generateLayerId(),
@@ -3403,6 +3673,7 @@ var CustomDimensionSelectConnect = function CustomDimensionSelectConnect(_ref) {
3403
3673
 
3404
3674
  var LayerInfoButtonConnect = function LayerInfoButtonConnect(_ref) {
3405
3675
  var isLayerMissing = _ref.isLayerMissing,
3676
+ isFeatureLayer = _ref.isFeatureLayer,
3406
3677
  mapId = _ref.mapId,
3407
3678
  serviceUrl = _ref.serviceUrl,
3408
3679
  layerName = _ref.layerName,
@@ -3429,7 +3700,7 @@ var LayerInfoButtonConnect = function LayerInfoButtonConnect(_ref) {
3429
3700
  }
3430
3701
  };
3431
3702
  return jsx(LayerInfoButton, {
3432
- disabled: isLayerMissing,
3703
+ disabled: isLayerMissing || isFeatureLayer,
3433
3704
  isActive: isActive,
3434
3705
  onClick: onClick
3435
3706
  });
@@ -3492,11 +3763,12 @@ var LayerRowConnect = /*#__PURE__*/React.memo(function (_ref) {
3492
3763
  return layerSelectors.getLayerType(store, layerId);
3493
3764
  });
3494
3765
  var isEDRLayer = layerType === LayerType.edrFeatureLayer;
3766
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3495
3767
  var layerServiceUrl = useSelector(function (store) {
3496
3768
  return layerSelectors.getLayerService(store, layerId);
3497
3769
  });
3498
3770
  var isLayerMissing = useSelector(function (store) {
3499
- return layerSelectors.getIsLayerMissing(store, layerId);
3771
+ return !isFeatureLayer ? layerSelectors.getIsLayerMissing(store, layerId) : false;
3500
3772
  });
3501
3773
  renderCounter.count(LayerRowConnect.name);
3502
3774
  return jsx(LayerRow, {
@@ -3557,7 +3829,8 @@ var LayerRowConnect = /*#__PURE__*/React.memo(function (_ref) {
3557
3829
  isLayerMissing: isLayerMissing,
3558
3830
  mapId: mapId,
3559
3831
  serviceUrl: layerServiceUrl,
3560
- layerName: layerName
3832
+ layerName: layerName,
3833
+ isFeatureLayer: isFeatureLayer
3561
3834
  }),
3562
3835
  layerMenuLayout: jsx(LayerManagerMenuButtonConnect, Object.assign({
3563
3836
  mapId: mapId,
@@ -3623,76 +3896,146 @@ var LayerContainerRow = /*#__PURE__*/React.memo(function (_ref) {
3623
3896
  var _React$useTransition = React.useTransition(),
3624
3897
  isPending = _React$useTransition[0],
3625
3898
  startTransition = _React$useTransition[1];
3626
- var _React$useState = React.useState(0),
3627
- rowsToDisplay = _React$useState[0],
3628
- setRowsToDisplay = _React$useState[1];
3629
- var layerIds = useSelector(function (store) {
3899
+ // Separate map layers and feature layers
3900
+ var mapLayerIds = useSelector(function (store) {
3630
3901
  return mapSelectors.getLayerIds(store, mapId);
3631
3902
  });
3632
- var layerLength = layerIds.length;
3633
- var layerMoveLayer = React.useCallback(function (_ref2) {
3903
+ var featureLayers = useSelector(function (store) {
3904
+ return mapSelectors.getMapFeatureLayers(store, mapId);
3905
+ });
3906
+ // State for drag and display for each list
3907
+ var _React$useState = React.useState(null),
3908
+ activeDragIndexMap = _React$useState[0],
3909
+ setActiveDragIndexMap = _React$useState[1];
3910
+ var _React$useState2 = React.useState(null),
3911
+ activeDragIndexFeature = _React$useState2[0],
3912
+ setActiveDragIndexFeature = _React$useState2[1];
3913
+ var _React$useState3 = React.useState(0),
3914
+ rowsToDisplayMap = _React$useState3[0],
3915
+ setRowsToDisplayMap = _React$useState3[1];
3916
+ var _React$useState4 = React.useState(0),
3917
+ rowsToDisplayFeature = _React$useState4[0],
3918
+ setRowsToDisplayFeature = _React$useState4[1];
3919
+ var featureLayerIds = React.useMemo(function () {
3920
+ return featureLayers.filter(function (layer) {
3921
+ return layer.name !== undefined && layer.id !== undefined;
3922
+ }).map(function (layer) {
3923
+ return layer.id;
3924
+ });
3925
+ }, [featureLayers]);
3926
+ var layerMove = React.useCallback(function (_ref2) {
3634
3927
  var mapId = _ref2.mapId,
3635
3928
  oldIndex = _ref2.oldIndex,
3636
- newIndex = _ref2.newIndex;
3929
+ newIndex = _ref2.newIndex,
3930
+ layerType = _ref2.layerType;
3637
3931
  return dispatch(mapActions.layerMoveLayer({
3638
3932
  mapId: mapId,
3639
3933
  oldIndex: oldIndex,
3640
3934
  newIndex: newIndex,
3641
- origin: layerTypes.LayerActionOrigin.layerManager
3935
+ origin: layerTypes.LayerActionOrigin.layerManager,
3936
+ layerType: layerType
3642
3937
  }));
3643
3938
  }, [dispatch]);
3644
- var _React$useState2 = React.useState(null),
3645
- activeDragIndex = _React$useState2[0],
3646
- setActiveDragIndex = _React$useState2[1];
3647
- var onSetList = function onSetList() {}; // since we use activeDragIndex, we don't need inner state handling of ReactSortable
3648
- var onStart = React.useCallback(function (_ref3) {
3939
+ // Drag handlers for map layers
3940
+ var onSetListMap = function onSetListMap() {};
3941
+ var onStartDragMap = React.useCallback(function (_ref3) {
3649
3942
  var oldIndex = _ref3.oldIndex;
3650
- setActiveDragIndex(oldIndex);
3943
+ setActiveDragIndexMap(oldIndex);
3651
3944
  if (Sortable.ghost) {
3652
3945
  Sortable.ghost.style.opacity = '1';
3653
3946
  }
3654
3947
  }, []);
3655
- var onEnd = React.useCallback(function () {
3656
- if (activeDragIndex !== null) {
3657
- setActiveDragIndex(null);
3948
+ var onEndDragMap = React.useCallback(function () {
3949
+ if (activeDragIndexMap !== null) {
3950
+ setActiveDragIndexMap(null);
3658
3951
  }
3659
- }, [activeDragIndex]);
3660
- var onSortEnd = function onSortEnd(_ref4) {
3952
+ }, [activeDragIndexMap]);
3953
+ var onSortEndMap = function onSortEndMap(_ref4) {
3661
3954
  var oldIndex = _ref4.oldIndex,
3662
3955
  newIndex = _ref4.newIndex;
3663
- setActiveDragIndex(null);
3664
- layerMoveLayer({
3956
+ setActiveDragIndexMap(null);
3957
+ layerMove({
3958
+ mapId: mapId,
3959
+ oldIndex: oldIndex,
3960
+ newIndex: newIndex,
3961
+ layerType: LayerType.mapLayer
3962
+ });
3963
+ };
3964
+ // Drag handlers for feature layers
3965
+ var onSetListFeature = function onSetListFeature() {};
3966
+ var onStartDragFeature = React.useCallback(function (_ref5) {
3967
+ var oldIndex = _ref5.oldIndex;
3968
+ setActiveDragIndexFeature(oldIndex);
3969
+ if (Sortable.ghost) {
3970
+ Sortable.ghost.style.opacity = '1';
3971
+ }
3972
+ }, []);
3973
+ var onEndDragFeature = React.useCallback(function () {
3974
+ if (activeDragIndexFeature !== null) {
3975
+ setActiveDragIndexFeature(null);
3976
+ }
3977
+ }, [activeDragIndexFeature]);
3978
+ var onSortEndFeature = function onSortEndFeature(_ref6) {
3979
+ var oldIndex = _ref6.oldIndex,
3980
+ newIndex = _ref6.newIndex;
3981
+ setActiveDragIndexFeature(null);
3982
+ layerMove({
3665
3983
  mapId: mapId,
3666
3984
  oldIndex: oldIndex,
3667
- newIndex: newIndex
3985
+ newIndex: newIndex,
3986
+ layerType: LayerType.featureLayer
3668
3987
  });
3669
3988
  };
3670
- var isSorting = activeDragIndex !== null;
3671
- var isDragDisabled = layerLength === 1;
3672
- var contents = layerIds.map(function (layerId) {
3989
+ // Display logic for each list
3990
+ var isSortingMap = activeDragIndexMap !== null;
3991
+ var isSortingFeature = activeDragIndexFeature !== null;
3992
+ var isDragDisabledMap = mapLayerIds.length === 1;
3993
+ var isDragDisabledFeature = featureLayerIds.length === 1;
3994
+ var mapLayerContents = mapLayerIds.map(function (layerId) {
3673
3995
  var _settings$dragHandle, _settings$dragHandle2;
3674
3996
  return jsx(LayerRowConnect, {
3675
3997
  mapId: mapId,
3676
3998
  layerId: layerId,
3677
3999
  dragHandle: jsx(DragHandle, {
3678
- isDisabled: isDragDisabled,
3679
- hideTooltip: isSorting || isDragDisabled,
3680
- isSorting: isSorting,
4000
+ isDisabled: isDragDisabledMap,
4001
+ hideTooltip: isSortingMap || isDragDisabledMap,
4002
+ isSorting: isSortingMap,
3681
4003
  icon: settings == null || (_settings$dragHandle = settings.dragHandle) == null ? void 0 : _settings$dragHandle.icon,
3682
4004
  tooltipTitle: settings == null || (_settings$dragHandle2 = settings.dragHandle) == null ? void 0 : _settings$dragHandle2.tooltipTitle
3683
4005
  }),
3684
4006
  settings: settings,
3685
4007
  collapsedColumns: collapsedColumns
3686
- }, "layerRowConnect-" + layerId);
4008
+ }, "layerRowConnect-map-" + layerId);
4009
+ });
4010
+ var featureLayerContents = featureLayerIds.map(function (layerId) {
4011
+ var _settings$dragHandle3, _settings$dragHandle4;
4012
+ return jsx(LayerRowConnect, {
4013
+ mapId: mapId,
4014
+ layerId: layerId,
4015
+ dragHandle: jsx(DragHandle, {
4016
+ isDisabled: isDragDisabledFeature,
4017
+ hideTooltip: isSortingFeature || isDragDisabledFeature,
4018
+ isSorting: isSortingFeature,
4019
+ icon: settings == null || (_settings$dragHandle3 = settings.dragHandle) == null ? void 0 : _settings$dragHandle3.icon,
4020
+ tooltipTitle: settings == null || (_settings$dragHandle4 = settings.dragHandle) == null ? void 0 : _settings$dragHandle4.tooltipTitle
4021
+ }),
4022
+ settings: settings,
4023
+ collapsedColumns: collapsedColumns
4024
+ }, "layerRowConnect-feature-" + layerId);
3687
4025
  });
3688
4026
  React.useEffect(function () {
3689
- if (rowsToDisplay < layerLength) {
4027
+ if (rowsToDisplayMap < mapLayerIds.length) {
4028
+ startTransition(function () {
4029
+ setRowsToDisplayMap(rowsToDisplayMap + mapLayerIds.length);
4030
+ });
4031
+ }
4032
+ if (rowsToDisplayFeature < featureLayerIds.length) {
3690
4033
  startTransition(function () {
3691
- setRowsToDisplay(rowsToDisplay + layerLength);
4034
+ setRowsToDisplayFeature(rowsToDisplayFeature + featureLayerIds.length);
3692
4035
  });
3693
4036
  }
3694
- }, [layerLength, rowsToDisplay]);
3695
- return jsx(Grid, Object.assign({
4037
+ }, [mapLayerIds.length, featureLayerIds.length, rowsToDisplayMap, rowsToDisplayFeature]);
4038
+ return jsxs(Grid, Object.assign({
3696
4039
  container: true,
3697
4040
  "data-testid": "layerContainerRow",
3698
4041
  className: "layerContainerRow",
@@ -3708,29 +4051,48 @@ var LayerContainerRow = /*#__PURE__*/React.memo(function (_ref) {
3708
4051
  }
3709
4052
  }
3710
4053
  }, gridProps, {
3711
- children: jsx(ReactSortable, {
4054
+ children: [rowsToDisplayFeature > 0 && jsx(ReactSortable, {
3712
4055
  tag: "div",
3713
- list: layerIds.map(function (layerId) {
4056
+ list: featureLayerIds.map(function (layerId) {
3714
4057
  return {
3715
4058
  id: layerId
3716
4059
  };
3717
4060
  }),
3718
- setList: onSetList,
4061
+ setList: onSetListFeature,
3719
4062
  animation: 200,
3720
- onSort: onSortEnd,
4063
+ onSort: onSortEndFeature,
3721
4064
  handle: ".handle",
3722
4065
  direction: "vertical",
3723
- // hover props
3724
4066
  forceFallback: false,
3725
- onStart: onStart,
3726
- onEnd: onEnd,
4067
+ onStart: onStartDragFeature,
4068
+ onEnd: onEndDragFeature,
4069
+ style: {
4070
+ width: '100%',
4071
+ marginBottom: '8px'
4072
+ },
4073
+ children: featureLayerContents.slice(0, rowsToDisplayFeature)
4074
+ }), jsx(ReactSortable, {
4075
+ tag: "div",
4076
+ list: mapLayerIds.map(function (layerId) {
4077
+ return {
4078
+ id: layerId
4079
+ };
4080
+ }),
4081
+ setList: onSetListMap,
4082
+ animation: 200,
4083
+ onSort: onSortEndMap,
4084
+ handle: ".handle",
4085
+ direction: "vertical",
4086
+ forceFallback: false,
4087
+ onStart: onStartDragMap,
4088
+ onEnd: onEndDragMap,
3727
4089
  style: {
3728
4090
  width: '100%'
3729
4091
  },
3730
4092
  children: isPending ? jsx(LinearProgress, {
3731
- "data-testid": "loading-bar"
3732
- }) : contents.slice(0, rowsToDisplay)
3733
- })
4093
+ "data-testid": "loading-bar-map"
4094
+ }) : mapLayerContents.slice(0, rowsToDisplayMap)
4095
+ })]
3734
4096
  }));
3735
4097
  });
3736
4098
 
@@ -4206,7 +4568,7 @@ var WMSLayerTreeConnect = connectRedux$3(ConnectedTree);
4206
4568
  * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
4207
4569
  * */
4208
4570
  var isValidService = function isValidService(service) {
4209
- return Object.prototype.hasOwnProperty.call(service, 'url');
4571
+ return Object.hasOwn(service, 'url');
4210
4572
  };
4211
4573
  var filterServices = function filterServices(presetArray) {
4212
4574
  var hasServices = presetArray && Array.isArray(presetArray) && presetArray.length > 0;
@@ -4536,7 +4898,7 @@ var AddLayersPopup = function AddLayersPopup(_ref) {
4536
4898
  // No error message until new check
4537
4899
  setUrlError('');
4538
4900
  },
4539
- onKeyPress: function onKeyPress(event) {
4901
+ onKeyDown: function onKeyDown(event) {
4540
4902
  if (event.key === 'Enter') {
4541
4903
  handleAddServiceURL();
4542
4904
  }
@@ -6051,7 +6413,7 @@ var connectRedux = connect(function (store, props) {
6051
6413
  secondsPerPx: mapSelectors.getMapTimeSliderSecondsPerPx(store, props.mapId),
6052
6414
  span: mapSelectors.getMapTimeSliderSpan(store, props.mapId),
6053
6415
  timeStep: mapSelectors.getMapTimeStep(store, props.mapId),
6054
- isAnimating: mapSelectors.isAnimating(store, props.mapId),
6416
+ linkedMapAnimationInfo: mapSelectors.linkedMapAnimationInfo(store, props.mapId),
6055
6417
  isAutoUpdating: mapSelectors.isAutoUpdating(store, props.mapId)
6056
6418
  };
6057
6419
  }, {
@@ -6065,6 +6427,7 @@ var TimeSliderCurrentTimeBoxConnectComponent = function TimeSliderCurrentTimeBox
6065
6427
  secondsPerPx = _ref.secondsPerPx,
6066
6428
  span = _ref.span,
6067
6429
  timeStep = _ref.timeStep,
6430
+ linkedMapAnimationInfo = _ref.linkedMapAnimationInfo,
6068
6431
  isAutoUpdating = _ref.isAutoUpdating,
6069
6432
  setCenterTime = _ref.setCenterTime,
6070
6433
  unfilteredSelectedTime = _ref.unfilteredSelectedTime,
@@ -6082,6 +6445,7 @@ var TimeSliderCurrentTimeBoxConnectComponent = function TimeSliderCurrentTimeBox
6082
6445
  dataStartTime: dataStartTime,
6083
6446
  dataEndTime: dataEndTime,
6084
6447
  timeStep: timeStep,
6448
+ linkedMapAnimationInfo: linkedMapAnimationInfo,
6085
6449
  isAutoUpdating: isAutoUpdating,
6086
6450
  unfilteredSelectedTime: unfilteredSelectedTime,
6087
6451
  setUnfilteredSelectedTime: setUnfilteredSelectedTime,
@@ -7330,19 +7694,21 @@ var LocationSearch = function LocationSearch(_ref) {
7330
7694
  setSelectedValue(null);
7331
7695
  }
7332
7696
  },
7333
- InputProps: Object.assign({}, params.InputProps, {
7334
- endAdornment: jsx(CustomIconButton, {
7335
- tooltipTitle: t('search-clear'),
7336
- onClick: function onClick() {
7337
- setInputValue('');
7338
- setSelectedValue(null);
7339
- },
7340
- sx: {
7341
- marginRight: 1
7342
- },
7343
- children: jsx(Close, {})
7697
+ slotProps: {
7698
+ input: Object.assign({}, params.InputProps, {
7699
+ endAdornment: jsx(CustomIconButton, {
7700
+ tooltipTitle: t('search-clear'),
7701
+ onClick: function onClick() {
7702
+ setInputValue('');
7703
+ setSelectedValue(null);
7704
+ },
7705
+ sx: {
7706
+ marginRight: 1
7707
+ },
7708
+ children: jsx(Close, {})
7709
+ })
7344
7710
  })
7345
- })
7711
+ }
7346
7712
  }));
7347
7713
  }
7348
7714
  })]
@@ -7524,6 +7890,34 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref)
7524
7890
  hoverSelect = _ref.hoverSelect;
7525
7891
  var store = useStore();
7526
7892
  var dispatch = useDispatch();
7893
+ var onFeatureClick = React__default.useCallback(function (feature) {
7894
+ var previouslySelectedFeatureIndex = layer.selectedFeatureIndex;
7895
+ var selectedFeatureIndex = layer.geojson.features.findIndex(function (feat) {
7896
+ return feature[0] && feat.id === feature[0].getId();
7897
+ });
7898
+ if (selectedFeatureIndex !== -1 && selectedFeatureIndex !== previouslySelectedFeatureIndex) {
7899
+ dispatch(layerActions.setSelectedFeature({
7900
+ layerId: layerId,
7901
+ selectedFeatureIndex: selectedFeatureIndex
7902
+ }));
7903
+ dispatch(layerActions.updateFeatureProperties({
7904
+ layerId: layerId,
7905
+ properties: {
7906
+ highlightSelectedFeature: true
7907
+ },
7908
+ selectedFeatureIndex: selectedFeatureIndex
7909
+ }));
7910
+ if (previouslySelectedFeatureIndex !== undefined) {
7911
+ dispatch(layerActions.updateFeatureProperties({
7912
+ layerId: layerId,
7913
+ properties: {
7914
+ highlightSelectedFeature: false
7915
+ },
7916
+ selectedFeatureIndex: previouslySelectedFeatureIndex
7917
+ }));
7918
+ }
7919
+ }
7920
+ }, [dispatch, layer.geojson, layer.selectedFeatureIndex, layerId]);
7527
7921
  var updateFeature = React__default.useCallback(function (geojson, reason) {
7528
7922
  if (!layerId) {
7529
7923
  window.console.error('updateFeature without layerId');
@@ -7558,7 +7952,13 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref)
7558
7952
  featureCollection: !layer.isInEditMode ? layer.geojson : undefined,
7559
7953
  zIndex: zIndex,
7560
7954
  style: style,
7561
- hoverSelect: hoverSelect
7955
+ hoverSelect: hoverSelect,
7956
+ clickOnFeature: layer.isSelectable ? {
7957
+ onClick: onFeatureClick,
7958
+ hitTolerance: 5
7959
+ } : undefined,
7960
+ visible: layer.enabled,
7961
+ opacity: layer.opacity
7562
7962
  }), jsx(OpenLayersMapDraw, {
7563
7963
  drawMode: layer.drawMode,
7564
7964
  viewOnlyStyle: style,
@@ -7605,12 +8005,31 @@ var makePrefetchTimeSpan = function makePrefetchTimeSpan(timeSliderStartCenterEn
7605
8005
  end: roundEnd,
7606
8006
  step: timeSliderTimeStepInS
7607
8007
  });
7608
- // eslint-disable-next-line no-constant-condition
7609
8008
  return {
7610
8009
  isAnimating: isAnimating,
7611
8010
  prefetchList: timeSpanList
7612
8011
  };
7613
8012
  };
8013
+ var usePrefetchTimeSpan = function usePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList) {
8014
+ var _useState = useState({
8015
+ isAnimating: isAnimating,
8016
+ prefetchList: animationList || []
8017
+ }),
8018
+ prefetchTimespan = _useState[0],
8019
+ setPrefetchTimeSpan = _useState[1];
8020
+ var makeThrottledPrefetchTimespan = useMemo(function () {
8021
+ return throttle(function (timeSliderStartCenterEndTime, isAnimating, animationList) {
8022
+ return setPrefetchTimeSpan(makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList));
8023
+ }, 500, {
8024
+ leading: true,
8025
+ trailing: true
8026
+ });
8027
+ }, []);
8028
+ useEffect(function () {
8029
+ return makeThrottledPrefetchTimespan(timeSliderStartCenterEndTime, isAnimating, animationList);
8030
+ }, [animationList, isAnimating, makeThrottledPrefetchTimespan, timeSliderStartCenterEndTime]);
8031
+ return prefetchTimespan;
8032
+ };
7614
8033
  var makeLayerInfoPayload = function makeLayerInfoPayload(payload, mapDimensions, mapId) {
7615
8034
  // During intialization, try to base the layer dimension on the current map dimension value.
7616
8035
  var origin = 'onInitializeLayer in OlMapViewLayerConnect';
@@ -7808,6 +8227,54 @@ var useGetOpenLayersView = function useGetOpenLayersView(mapId, store) {
7808
8227
  };
7809
8228
  };
7810
8229
 
8230
+ /* *
8231
+ * Licensed under the Apache License, Version 2.0 (the "License");
8232
+ * you may not use this file except in compliance with the License.
8233
+ * You may obtain a copy of the License at
8234
+ *
8235
+ * http://www.apache.org/licenses/LICENSE-2.0
8236
+ *
8237
+ * Unless required by applicable law or agreed to in writing, software
8238
+ * distributed under the License is distributed on an "AS IS" BASIS,
8239
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8240
+ * See the License for the specific language governing permissions and
8241
+ * limitations under the License.
8242
+ *
8243
+ * Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8244
+ * Copyright 2025 - Finnish Meteorological Institute (FMI)
8245
+ * Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
8246
+ * */
8247
+ var LOADING_INDICATOR_UPDATE_INTERVAL_MS = 200;
8248
+ // 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.
8249
+ var useMapViewLoadingIndicator = function useMapViewLoadingIndicator(mapId, layerIds) {
8250
+ var _useStore = useStore(),
8251
+ dispatch = _useStore.dispatch;
8252
+ var setGetMapLoadingPercentage = React__default.useCallback(function (percentageComplete) {
8253
+ dispatch(loadingIndicatorActions.setGetMapIsLoading({
8254
+ id: mapId,
8255
+ getMapLoadingPercentage: percentageComplete
8256
+ }));
8257
+ }, [dispatch, mapId]);
8258
+ // Check periodically if percentage is changed. If this is the case, dispatch an action.
8259
+ var percentageCompleteRef = React__default.useRef(100);
8260
+ var numberDoneRef = React__default.useRef(0);
8261
+ React__default.useEffect(function () {
8262
+ var intervalId = setInterval(function () {
8263
+ var _openLayersGetMapImag = openLayersGetMapImageStore.loadDuration.getTotalLoadingPercentageForIds(layerIds),
8264
+ percentageComplete = _openLayersGetMapImag.percentage,
8265
+ doneLoading = _openLayersGetMapImag.doneLoading;
8266
+ if (percentageComplete !== percentageCompleteRef.current || doneLoading !== numberDoneRef.current) {
8267
+ numberDoneRef.current = doneLoading;
8268
+ percentageCompleteRef.current = percentageComplete;
8269
+ setGetMapLoadingPercentage(percentageComplete);
8270
+ }
8271
+ }, LOADING_INDICATOR_UPDATE_INTERVAL_MS);
8272
+ return function () {
8273
+ clearInterval(intervalId);
8274
+ };
8275
+ }, [layerIds, mapId, setGetMapLoadingPercentage]);
8276
+ };
8277
+
7811
8278
  /**
7812
8279
  * Connected component used to display the map and selected layers.
7813
8280
  * Includes options to disable the map controls and legend.
@@ -7962,6 +8429,9 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7962
8429
  });
7963
8430
  var mapPinChangeLocation = React.useCallback(function (clickedLocation) {
7964
8431
  var _hoverLinkedFeature$g;
8432
+ if (disableMapPin) {
8433
+ return;
8434
+ }
7965
8435
  var mapPinLocation = getCenterOfLinkedFeature(hoverLinkedFeature, srs) || clickedLocation;
7966
8436
  var selectedFeatureId = (hoverLinkedFeature == null || (_hoverLinkedFeature$g = hoverLinkedFeature.getId()) == null ? void 0 : _hoverLinkedFeature$g.toString()) || '';
7967
8437
  if (hoverLinkedFeature) {
@@ -7986,7 +8456,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7986
8456
  mapPinLocation: mapPinLocation
7987
8457
  }));
7988
8458
  });
7989
- }, [dispatch, hoverLinkedFeature, linkedFeatures.features, linkedPanelId, mapId, selectedMapIds, srs]);
8459
+ }, [dispatch, disableMapPin, hoverLinkedFeature, linkedFeatures.features, linkedPanelId, mapId, selectedMapIds, srs]);
7990
8460
  var isActiveWindowId = useSelector(function (store) {
7991
8461
  return uiSelectors.getIsActiveWindowId(store, mapId);
7992
8462
  });
@@ -8001,10 +8471,6 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8001
8471
  id: mapId,
8002
8472
  type: [syncConstants.SYNCGROUPS_TYPE_SETTIME, syncConstants.SYNCGROUPS_TYPE_SETBBOX]
8003
8473
  });
8004
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8005
- id: mapId,
8006
- isGetMapLoading: false
8007
- }));
8008
8474
  return function () {
8009
8475
  unregisterMap({
8010
8476
  mapId: mapId
@@ -8014,18 +8480,6 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8014
8480
  });
8015
8481
  };
8016
8482
  }, [dispatch, mapId, registerMap, syncGroupRemoveSource, syncGroupsAddSource, unregisterMap]);
8017
- var onGetMapLoadStart = React.useCallback(function () {
8018
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8019
- id: mapId,
8020
- isGetMapLoading: true
8021
- }));
8022
- }, [dispatch, mapId]);
8023
- var onGetMapLoadReady = React.useCallback(function () {
8024
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8025
- id: mapId,
8026
- isGetMapLoading: false
8027
- }));
8028
- }, [dispatch, mapId]);
8029
8483
  React.useEffect(function () {
8030
8484
  if (!view) {
8031
8485
  return function () {};
@@ -8079,7 +8533,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8079
8533
  }
8080
8534
  }));
8081
8535
  }, [hoverId, previousHoverId, hoverLinkedFeature, featureProperties, linkedPanelId, dispatch]);
8082
- var prefetchTimespan = makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList);
8536
+ var prefetchTimespan = usePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList);
8083
8537
  var layerIds = mapLayerIds.join();
8084
8538
  var refetchLayers = React.useCallback(function () {
8085
8539
  mapLayerIds == null || mapLayerIds.forEach(/*#__PURE__*/function () {
@@ -8129,24 +8583,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8129
8583
  // eslint-disable-next-line react-hooks/exhaustive-deps
8130
8584
  }, [mapId, updateLayerInformation, layerIds]);
8131
8585
  useSetIntervalWhenVisible(refetchLayers, 60000);
8132
- var isLoading = React.useRef(false);
8133
- // UseEffect for loading indicator
8134
- React.useEffect(function () {
8135
- openLayersGetMapImageStore.addImageEventCallback(function () {
8136
- var checkLoading = !!(openLayersGetMapImageStore.getNumImagesLoading() > 0);
8137
- if (checkLoading !== isLoading.current) {
8138
- if (checkLoading === true) {
8139
- onGetMapLoadStart && onGetMapLoadStart();
8140
- } else {
8141
- onGetMapLoadReady && onGetMapLoadReady();
8142
- }
8143
- isLoading.current = checkLoading;
8144
- }
8145
- }, mapId);
8146
- return function () {
8147
- openLayersGetMapImageStore.removeEventCallback(mapId);
8148
- };
8149
- }, [mapId, onGetMapLoadReady, onGetMapLoadStart]);
8586
+ useMapViewLoadingIndicator(mapId, mapLayerIds);
8150
8587
  var _React$useState2 = React.useState(false),
8151
8588
  debugMode = _React$useState2[0],
8152
8589
  setDebugMode = _React$useState2[1];
@@ -8945,8 +9382,10 @@ var SyncGroupListItem = function SyncGroupListItem(_ref) {
8945
9382
  checked: isChecked,
8946
9383
  tabIndex: -1,
8947
9384
  disableRipple: true,
8948
- inputProps: {
8949
- 'aria-labelledby': source.name
9385
+ slotProps: {
9386
+ input: {
9387
+ 'aria-labelledby': source.name
9388
+ }
8950
9389
  },
8951
9390
  sx: isNotCheckedElseWhere ? styles.checkboxIsActive : styles.isDisabled,
8952
9391
  color: "default"
@@ -9127,8 +9566,10 @@ var SyncGroupViewer = function SyncGroupViewer(_ref) {
9127
9566
  },
9128
9567
  children: t('workspace-time-scroll-off')
9129
9568
  }), jsx(Switch, {
9130
- inputProps: {
9131
- 'aria-label': 'workspace time scroll toggle'
9569
+ slotProps: {
9570
+ input: {
9571
+ 'aria-label': 'workspace time scroll toggle'
9572
+ }
9132
9573
  },
9133
9574
  checked: isTimeScrollingEnabled,
9134
9575
  onChange: function onChange() {
@@ -9642,6 +10083,215 @@ var LanguageSelect = function LanguageSelect(_ref) {
9642
10083
  });
9643
10084
  };
9644
10085
 
10086
+ var textStyle = {
10087
+ lineHeight: '20px',
10088
+ letterSpacing: '0.25px'
10089
+ };
10090
+ var textStyleWithMargin = Object.assign({}, textStyle, {
10091
+ marginBottom: 1
10092
+ });
10093
+ var SelectedFeature = function SelectedFeature(_ref) {
10094
+ var feature = _ref.feature,
10095
+ layerName = _ref.layerName;
10096
+ var _useCoreTranslation = useCoreTranslation(),
10097
+ t = _useCoreTranslation.t;
10098
+ var getFormattedCoordinates = function getFormattedCoordinates(lat, lon) {
10099
+ var latHemisphere = lat >= 0 ? 'N' : 'S';
10100
+ var lonHemisphere = lon >= 0 ? 'E' : 'W';
10101
+ return Math.abs(lat) + "\xB0 " + latHemisphere + ", " + Math.abs(lon) + "\xB0 " + lonHemisphere;
10102
+ };
10103
+ var formattedCoordinates = useMemo(function () {
10104
+ if (feature && feature.geometry.type === 'Point') {
10105
+ var latitude = feature.geometry.coordinates[1];
10106
+ var longitude = feature.geometry.coordinates[0];
10107
+ return getFormattedCoordinates(latitude, longitude);
10108
+ }
10109
+ return '';
10110
+ }, [feature]);
10111
+ var featureInfoKeys = useMemo(function () {
10112
+ return feature ? Object.keys(feature.properties || {}).filter(function (key) {
10113
+ return !['id', 'geometry', 'hover', 'highlightSelectedFeature'].includes(key);
10114
+ }).sort() : [];
10115
+ }, [feature]);
10116
+ return jsx(CustomAccordion, {
10117
+ title: layerName,
10118
+ children: jsxs(Box, {
10119
+ sx: {
10120
+ minWidth: '12rem',
10121
+ paddingX: '1rem'
10122
+ },
10123
+ children: [jsx(Typography, {
10124
+ variant: "caption",
10125
+ sx: textStyle,
10126
+ color: "textSecondary",
10127
+ children: t('featureinfo-id')
10128
+ }), jsx(Typography, {
10129
+ variant: "body2",
10130
+ sx: textStyleWithMargin,
10131
+ children: feature.id
10132
+ }), jsx(Typography, {
10133
+ variant: "caption",
10134
+ sx: textStyle,
10135
+ color: "textSecondary",
10136
+ children: t('featureinfo-location')
10137
+ }), jsx(Typography, {
10138
+ variant: "body2",
10139
+ sx: textStyleWithMargin,
10140
+ children: formattedCoordinates
10141
+ }), featureInfoKeys.map(function (key) {
10142
+ var _feature$properties;
10143
+ return jsxs(React__default.Fragment, {
10144
+ children: [jsx(Typography, {
10145
+ variant: "caption",
10146
+ sx: textStyle,
10147
+ color: "textSecondary",
10148
+ children: t("" + key)
10149
+ }), jsx(Typography, {
10150
+ variant: "body2",
10151
+ sx: textStyleWithMargin,
10152
+ children: (_feature$properties = feature.properties) == null || (_feature$properties = _feature$properties[key]) == null ? void 0 : _feature$properties.toString()
10153
+ })]
10154
+ }, key);
10155
+ })]
10156
+ })
10157
+ }, layerName);
10158
+ };
10159
+
10160
+ var SelectedFeaturesDialog = function SelectedFeaturesDialog(_ref) {
10161
+ var onClose = _ref.onClose,
10162
+ isOpen = _ref.isOpen,
10163
+ _ref$onMouseDown = _ref.onMouseDown,
10164
+ onMouseDown = _ref$onMouseDown === void 0 ? function () {} : _ref$onMouseDown,
10165
+ _ref$order = _ref.order,
10166
+ order = _ref$order === void 0 ? 0 : _ref$order,
10167
+ _ref$source = _ref.source,
10168
+ source = _ref$source === void 0 ? 'app' : _ref$source,
10169
+ _ref$startPosition = _ref.startPosition,
10170
+ startPosition = _ref$startPosition === void 0 ? {
10171
+ top: 85,
10172
+ left: 50
10173
+ } : _ref$startPosition,
10174
+ features = _ref.features;
10175
+ var minSize = {
10176
+ width: 400,
10177
+ height: 200
10178
+ };
10179
+ var _useCoreTranslation = useCoreTranslation(),
10180
+ t = _useCoreTranslation.t;
10181
+ var stopWheelEventPropagationRef = useWheelStopPropagation();
10182
+ return jsx(ToolContainerDraggable, {
10183
+ title: t('featureinfo-title'),
10184
+ startSize: {
10185
+ width: 510,
10186
+ height: 500
10187
+ },
10188
+ minWidth: minSize.width,
10189
+ minHeight: minSize.height,
10190
+ startPosition: startPosition,
10191
+ isOpen: isOpen,
10192
+ onClose: onClose,
10193
+ "data-testid": "featureInfoWindow",
10194
+ onMouseDown: onMouseDown,
10195
+ order: order,
10196
+ source: source,
10197
+ className: "featureInfo",
10198
+ children: jsx(Box, {
10199
+ ref: stopWheelEventPropagationRef,
10200
+ onKeyDown: function onKeyDown(event) {
10201
+ event.stopPropagation();
10202
+ },
10203
+ style: {
10204
+ paddingTop: '8px',
10205
+ paddingBottom: '8px'
10206
+ },
10207
+ "data-testid": "dataExplorerInfoBox",
10208
+ children: Object.entries(features).map(function (_ref2) {
10209
+ var key = _ref2[0],
10210
+ value = _ref2[1];
10211
+ return jsx(SelectedFeature, {
10212
+ feature: value,
10213
+ layerName: key
10214
+ }, key);
10215
+ })
10216
+ })
10217
+ });
10218
+ };
10219
+
10220
+ var SelectedFeaturesDialogConnect = function SelectedFeaturesDialogConnect() {
10221
+ var dispatch = useDispatch();
10222
+ var _useSetupDialog = useSetupDialog(uiTypes.DialogTypes.SelectedFeatures),
10223
+ dialogOrder = _useSetupDialog.dialogOrder,
10224
+ setDialogOrder = _useSetupDialog.setDialogOrder,
10225
+ onCloseDialog = _useSetupDialog.onCloseDialog,
10226
+ isDialogOpen = _useSetupDialog.isDialogOpen,
10227
+ uiSource = _useSetupDialog.uiSource;
10228
+ var activeMapId = useSelector(function (store) {
10229
+ return uiSelectors.getActiveWindowId(store);
10230
+ });
10231
+ var featureLayers = useSelector(function (store) {
10232
+ return mapSelectors.getMapFeatureLayers(store, activeMapId);
10233
+ });
10234
+ var selectedFeatureLayers = useMemo(function () {
10235
+ return featureLayers.filter(function (layer) {
10236
+ return layer.isSelectable && layer.selectedFeatureIndex !== undefined;
10237
+ });
10238
+ }, [featureLayers]);
10239
+ var selectedFeatures = useMemo(function () {
10240
+ var featuresMap = {};
10241
+ selectedFeatureLayers.forEach(function (layer) {
10242
+ var _layer$geojson;
10243
+ var feature = (_layer$geojson = layer.geojson) == null ? void 0 : _layer$geojson.features[layer.selectedFeatureIndex];
10244
+ if (feature && layer.name) {
10245
+ featuresMap[layer.name] = feature;
10246
+ }
10247
+ });
10248
+ return featuresMap;
10249
+ }, [selectedFeatureLayers]);
10250
+ // Deselect the selected features and close the dialog
10251
+ var closeDialog = useCallback(function () {
10252
+ selectedFeatureLayers.forEach(function (layer) {
10253
+ dispatch(layerActions.setSelectedFeature({
10254
+ layerId: layer.id,
10255
+ selectedFeatureIndex: undefined
10256
+ }));
10257
+ dispatch(layerActions.updateFeatureProperties({
10258
+ layerId: layer.id,
10259
+ properties: {
10260
+ highlightSelectedFeature: false
10261
+ },
10262
+ selectedFeatureIndex: layer.selectedFeatureIndex
10263
+ }));
10264
+ });
10265
+ onCloseDialog();
10266
+ }, [dispatch, onCloseDialog, selectedFeatureLayers]);
10267
+ useEffect(function () {
10268
+ if (Object.entries(selectedFeatures).length > 0 && activeMapId !== undefined) {
10269
+ dispatch(uiActions.setActiveMapIdForDialog({
10270
+ type: uiTypes.DialogTypes.SelectedFeatures,
10271
+ mapId: activeMapId,
10272
+ setOpen: true,
10273
+ source: 'app'
10274
+ }));
10275
+ } else {
10276
+ onCloseDialog();
10277
+ }
10278
+ }, [activeMapId, onCloseDialog, dispatch, selectedFeatures]);
10279
+ return React.useMemo(function () {
10280
+ return jsx(SelectedFeaturesDialog, {
10281
+ isOpen: isDialogOpen,
10282
+ onClose: closeDialog,
10283
+ onMouseDown: setDialogOrder,
10284
+ order: dialogOrder,
10285
+ source: uiSource,
10286
+ startPosition: {
10287
+ top: 85,
10288
+ left: 50
10289
+ },
10290
+ features: selectedFeatures
10291
+ });
10292
+ }, [dialogOrder, isDialogOpen, closeDialog, setDialogOrder, uiSource, selectedFeatures]);
10293
+ };
10294
+
9645
10295
  /* *
9646
10296
  * Licensed under the Apache License, Version 2.0 (the "License");
9647
10297
  * you may not use this file except in compliance with the License.
@@ -9923,4 +10573,4 @@ var storyUtils = /*#__PURE__*/Object.freeze({
9923
10573
  useDefaultMapSettings: useDefaultMapSettings
9924
10574
  });
9925
10575
 
9926
- export { CORE_NAMESPACE, ConfigurableMapConnect, CoreI18nProvider, CoreStoreProvider, CoreThemeProvider, CoreThemeStoreProvider, DemoWrapper, DemoWrapperConnect, HarmonieTempAndPrecipPreset, LanguageSelect, LayerInfoButtonConnect, LayerInfoDialogConnect, LayerManager, BaseLayerRow as LayerManagerBaseLayerRow, LayerManagerConnect, DescriptionRow as LayerManagerDescriptionRow, HeaderOptions as LayerManagerHeaderOptions, LayerContainerRow as LayerManagerLayerContainerRow, LayerManagerMapButtonConnect, LegendConnect, LegendMapButtonConnect, LocationSearch, LocationSearchConnect, types as LocationSearchTypes, MultiDimensionSelectMapButtonsConnect, MultiMapMultiDimensionSelectConnect as MultiMapDimensionSelectConnect, MultiMapViewConnect, MyMapLocation, OlMapViewConnect, RouterWrapperConnect, SearchControlButtonConnect, SentryRecordButton, SyncGroupViewerConnect, TimeSliderConnect, componentsLookUp, coreTranslations, defaultBbox, defaultConfigurations, fakeLocationDetailList, fakeLocationList, filterMapPresets, filterServices, filterTimeSeriesServices, getCenterOfLinkedFeature, getLanguageFromLocalStorage, languageLocalStorageKey, locationApiEndpoints, makeLayerInfoPayload, makePrefetchTimeSpan, saveLanguageToLocalStorage, storyUtils, testLayers, useFetchServices, useFitAndHighlightWarningFeature, useGetOpenLayersView, useLocationDetail, useLocationList, useUpdateTimeSpan, useUpdateTimestep };
10576
+ export { CORE_NAMESPACE, ConfigurableMapConnect, CoreI18nProvider, CoreStoreProvider, CoreThemeProvider, CoreThemeStoreProvider, DemoWrapper, DemoWrapperConnect, HarmonieTempAndPrecipPreset, LanguageSelect, LayerInfoButtonConnect, LayerInfoDialogConnect, LayerManager, BaseLayerRow as LayerManagerBaseLayerRow, LayerManagerConnect, DescriptionRow as LayerManagerDescriptionRow, HeaderOptions as LayerManagerHeaderOptions, LayerContainerRow as LayerManagerLayerContainerRow, LayerManagerMapButtonConnect, LegendConnect, LegendMapButtonConnect, LoadingIndicatorProgressBar, LocationSearch, LocationSearchConnect, types as LocationSearchTypes, MultiDimensionSelectMapButtonsConnect, MultiMapMultiDimensionSelectConnect as MultiMapDimensionSelectConnect, MultiMapViewConnect, MyMapLocation, OlMapViewConnect, RouterWrapperConnect, SearchControlButtonConnect, SelectedFeaturesDialogConnect, SentryRecordButton, SyncGroupViewerConnect, TimeSliderConnect, componentsLookUp, coreTranslations, defaultBbox, defaultConfigurations, fakeLocationDetailList, fakeLocationList, filterMapPresets, filterServices, filterTimeSeriesServices, getCenterOfLinkedFeature, getLanguageFromLocalStorage, languageLocalStorageKey, locationApiEndpoints, makeLayerInfoPayload, makePrefetchTimeSpan, saveLanguageToLocalStorage, storyUtils, testLayers, useFetchServices, useFitAndHighlightWarningFeature, useGetOpenLayersView, useLocationDetail, useLocationList, usePrefetchTimeSpan, useUpdateTimeSpan, useUpdateTimestep };