@opengeoweb/core 13.2.1 → 14.0.1

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 +798 -164
  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,7 +1275,9 @@ 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
  }
@@ -1263,7 +1286,7 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1263
1286
  var dimensionValues = isReferenceTimeDimensionAndUseLatestIsAvailable ? [].concat(latestMap.latestOptions, dimensionValuesRaw.slice(hideLatestDuplicate ? 1 : 0)) : dimensionValuesRaw.slice().reverse();
1264
1287
  var extendedDimensionValues = dimensionValues.findIndex(function (dimensionValue) {
1265
1288
  return dimensionValue === selectedDimension.currentValue;
1266
- }) === -1 ? [].concat(dimensionValues, [selectedDimension.currentValue]) : dimensionValues;
1289
+ }) === -1 && selectedDimension.currentValue ? [].concat(dimensionValues, [selectedDimension.currentValue]) : dimensionValues;
1267
1290
  var setDimensionValue = function setDimensionValue(dimensionValue) {
1268
1291
  if (isReferenceTimeDimensionAndUseLatestIsAvailable) {
1269
1292
  var index = latestMap.getIndex(dimensionValue);
@@ -1279,13 +1302,13 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1279
1302
  var isOneOfLatest = isReferenceTimeDimensionAndUseLatestIsAvailable && useLatestReferenceTime;
1280
1303
  var getValue = function getValue() {
1281
1304
  if (isOneOfLatest) {
1282
- return latestMap.getValue(selectedDimension.currentValue);
1305
+ return latestMap.getValue(selectedDimension.currentValue || '') || '';
1283
1306
  }
1284
- return selectedDimension.currentValue;
1307
+ return selectedDimension.currentValue || '';
1285
1308
  };
1286
1309
  var getIndex = function getIndex() {
1287
1310
  if (isOneOfLatest) {
1288
- return latestMap.getIndex(selectedDimension.currentValue);
1311
+ return latestMap.getIndex(selectedDimension.currentValue || '');
1289
1312
  }
1290
1313
  return extendedDimensionValues.findIndex(function (dimensionValue) {
1291
1314
  return dimensionValue === selectedDimension.currentValue;
@@ -1341,7 +1364,7 @@ var DimensionSelectValue = function DimensionSelectValue(_ref) {
1341
1364
  textOverflow: 'ellipsis',
1342
1365
  overflow: 'hidden'
1343
1366
  },
1344
- children: [dimensionValue, !dimensionValue.includes('Latest') && jsxs("i", {
1367
+ children: [dimensionValue, !(dimensionValue != null && dimensionValue.includes('Latest')) && jsxs("i", {
1345
1368
  children: [" ", selectedDimension.units]
1346
1369
  })]
1347
1370
  }), currentIndex === dimensionValues.length && jsx(AlertIcon, {
@@ -1717,9 +1740,81 @@ var OpacitySelect = function OpacitySelect(_ref) {
1717
1740
  });
1718
1741
  };
1719
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
+
1720
1813
  var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1721
1814
  var mapId = _ref.mapId,
1722
1815
  layerId = _ref.layerId,
1816
+ _ref$isFeatureLayer = _ref.isFeatureLayer,
1817
+ isFeatureLayer = _ref$isFeatureLayer === void 0 ? false : _ref$isFeatureLayer,
1723
1818
  onLayerDuplicate = _ref.onLayerDuplicate,
1724
1819
  tooltipTitle = _ref.tooltipTitle,
1725
1820
  icon = _ref.icon;
@@ -1748,7 +1843,10 @@ var LayerManagerMenuButton = function LayerManagerMenuButton(_ref) {
1748
1843
  icon: jsx(Copy, {})
1749
1844
  }],
1750
1845
  tooltipTitle: nonEmptyTooltipTitle,
1751
- buttonIcon: icon
1846
+ buttonIcon: icon,
1847
+ children: isFeatureLayer && jsx(SelectableFeaturesCheckboxConnect, {
1848
+ layerId: layerId
1849
+ })
1752
1850
  });
1753
1851
  };
1754
1852
 
@@ -2070,6 +2168,74 @@ var MissingData = function MissingData(_ref) {
2070
2168
  });
2071
2169
  };
2072
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
+
2073
2239
  var MILLISECONDS_PER_SECOND = 1e3;
2074
2240
  var MAX_DURATION_IN_SECONDS = 60;
2075
2241
  var MIN_DURATION_IN_SECONDS = 0.1;
@@ -2078,7 +2244,9 @@ var DECIMALS_IN_TOOLTIP = 3;
2078
2244
  var LoadDuration = function LoadDuration(_ref) {
2079
2245
  var mapId = _ref.mapId,
2080
2246
  layerId = _ref.layerId;
2081
- var loadDurationLabel = useLoadDurationLabel(mapId, layerId);
2247
+ var _useLoadDurationLabel = useLoadDurationLabel(mapId, layerId),
2248
+ loadDurationLabel = _useLoadDurationLabel[0],
2249
+ percentage = _useLoadDurationLabel[1];
2082
2250
  var _React$useState = React.useState(),
2083
2251
  tooltipText = _React$useState[0],
2084
2252
  setTooltipText = _React$useState[1];
@@ -2095,15 +2263,24 @@ var LoadDuration = function LoadDuration(_ref) {
2095
2263
  setTooltipText(getDurationTooltip(duration));
2096
2264
  }
2097
2265
  },
2098
- children: jsx(Typography, {
2266
+ children: jsxs(Typography, {
2099
2267
  component: "div",
2100
2268
  variant: "subtitle2",
2101
2269
  whiteSpace: "nowrap",
2102
- "data-testid": "loadDuration",
2103
2270
  sx: {
2104
- fontSize: 12
2271
+ fontSize: 12,
2272
+ width: '100%',
2273
+ textAlign: 'center'
2105
2274
  },
2106
- 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
+ })]
2107
2284
  })
2108
2285
  });
2109
2286
  };
@@ -2114,13 +2291,7 @@ var getDurationTooltip = function getDurationTooltip(milliSeconds) {
2114
2291
  return roundToDecimals(milliSeconds / MILLISECONDS_PER_SECOND, DECIMALS_IN_TOOLTIP) + " s";
2115
2292
  };
2116
2293
  var getImageLoadDuration = function getImageLoadDuration(layerId) {
2117
- var layer = webmapUtils.getWMLayerById(layerId);
2118
- var currentRequestedGetMapURL = layer == null ? void 0 : layer.getCurrentRequestedGetMapURL();
2119
- if (currentRequestedGetMapURL === undefined) {
2120
- return undefined;
2121
- }
2122
- // TODO: https://gitlab.com/opengeoweb/geoweb-assets/-/issues/3958
2123
- return 0;
2294
+ return openLayersGetMapImageStore.loadDuration.getLoadDurationForId(layerId);
2124
2295
  };
2125
2296
  var roundToDecimals = function roundToDecimals(num, decimals) {
2126
2297
  return num.toLocaleString('en', {
@@ -2128,6 +2299,20 @@ var roundToDecimals = function roundToDecimals(num, decimals) {
2128
2299
  useGrouping: false
2129
2300
  });
2130
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
+ };
2131
2316
  /**
2132
2317
  * Hook to subscribe to changes in the load duration for a map layer.
2133
2318
  * This will only trigger a render when the load duration rounded down to seconds changes for the given layer and map combination
@@ -2136,26 +2321,12 @@ var roundToDecimals = function roundToDecimals(num, decimals) {
2136
2321
  * @returns {number}
2137
2322
  */
2138
2323
  var useLoadDurationLabel = function useLoadDurationLabel(mapId, layerId) {
2139
- var subscribe = React.useCallback(
2140
- // eslint-disable-next-line no-unused-vars
2141
- function (onStoreChange) {
2142
- return function () {};
2143
- }, []);
2144
- var getSnapshot = React.useCallback(function () {
2145
- var loadDurationMs = getImageLoadDuration(layerId);
2146
- if (loadDurationMs === undefined) {
2147
- return '-';
2148
- }
2149
- var loadDurationInSeconds = loadDurationMs / MILLISECONDS_PER_SECOND;
2150
- if (loadDurationInSeconds > MAX_DURATION_IN_SECONDS) {
2151
- return "> " + MAX_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2152
- }
2153
- if (loadDurationInSeconds < MIN_DURATION_IN_SECONDS) {
2154
- return "< " + MIN_DURATION_IN_SECONDS.toLocaleString('en') + " s";
2155
- }
2156
- return roundToDecimals(loadDurationInSeconds, DECIMALS_IN_LABEL) + " s";
2157
- }, [layerId]);
2158
- 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];
2159
2330
  };
2160
2331
 
2161
2332
  var LeftButtons = function LeftButtons(_ref) {
@@ -2594,10 +2765,17 @@ var DeleteLayerConnect = function DeleteLayerConnect(_ref) {
2594
2765
  var _useCoreTranslation = useCoreTranslation(),
2595
2766
  t = _useCoreTranslation.t;
2596
2767
  var dispatch = useDispatch();
2768
+ var confirmationDialog = useConfirmationDialog();
2597
2769
  var nonEmptyTooltipTitle = tooltipTitle != null ? tooltipTitle : t('layermanager-layer-delete');
2598
2770
  var layerIndex = useSelector(function (store) {
2599
2771
  return mapSelectors.getLayerIndexByLayerId(store, mapId, layerId);
2600
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
+ });
2601
2779
  var layerDelete = React.useCallback(function (_ref2) {
2602
2780
  var mapId = _ref2.mapId,
2603
2781
  layerId = _ref2.layerId;
@@ -2608,13 +2786,32 @@ var DeleteLayerConnect = function DeleteLayerConnect(_ref) {
2608
2786
  origin: layerTypes.LayerActionOrigin.layerManager
2609
2787
  }));
2610
2788
  }, [dispatch, layerIndex]);
2611
- var isLayerEnabled = useSelector(function (store) {
2612
- return layerSelectors.getLayerEnabled(store, layerId);
2613
- });
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]);
2614
2811
  return jsx(CustomIconButton, {
2615
2812
  tooltipTitle: nonEmptyTooltipTitle,
2616
2813
  onClick: function onClick() {
2617
- layerDelete({
2814
+ return onDelete({
2618
2815
  mapId: mapId,
2619
2816
  layerId: layerId
2620
2817
  });
@@ -2967,6 +3164,23 @@ var RenderEDRLayers = function RenderEDRLayers(_ref) {
2967
3164
  });
2968
3165
  };
2969
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
+
2970
3184
  var RenderLayersConnect = function RenderLayersConnect(_ref) {
2971
3185
  var layerId = _ref.layerId,
2972
3186
  mapId = _ref.mapId,
@@ -2982,14 +3196,14 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
2982
3196
  var layerType = useSelector(function (store) {
2983
3197
  return layerSelectors.getLayerType(store, layerId);
2984
3198
  });
2985
- var layerService = useSelector(function (store) {
3199
+ var serviceUrl = useSelector(function (store) {
2986
3200
  return layerSelectors.getLayerService(store, layerId);
2987
3201
  });
2988
3202
  var isLayerEnabled = useSelector(function (store) {
2989
3203
  return layerSelectors.getLayerEnabled(store, layerId);
2990
3204
  });
2991
3205
  var service = useSelector(function (store) {
2992
- return serviceSelectors.getServiceByUrl(store, layerService);
3206
+ return serviceSelectors.getServiceByUrl(store, serviceUrl);
2993
3207
  });
2994
3208
  var layerOptions = useSelector(function (store) {
2995
3209
  return layerSelectors.getLayerOptions(store, layerId);
@@ -2997,7 +3211,7 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
2997
3211
  var serviceSetLayers = React.useCallback(function (payload) {
2998
3212
  dispatch(serviceActions.serviceSetLayers(payload));
2999
3213
  }, [dispatch]);
3000
- var addService = /*#__PURE__*/function () {
3214
+ var addWmsService = /*#__PURE__*/function () {
3001
3215
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(serviceUrl) {
3002
3216
  var _layers, wmService;
3003
3217
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -3032,15 +3246,45 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
3032
3246
  }
3033
3247
  }, _callee, null, [[0, 10]]);
3034
3248
  }));
3035
- return function addService(_x) {
3249
+ return function addWmsService(_x) {
3036
3250
  return _ref2.apply(this, arguments);
3037
3251
  };
3038
3252
  }();
3039
- if (!service) {
3040
- void addService(layerService);
3253
+ var isEdrLayer = layerType === LayerType.edrFeatureLayer;
3254
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3255
+ if (!service && !isEdrLayer && !isFeatureLayer) {
3256
+ void addWmsService(serviceUrl);
3041
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]);
3042
3286
  var layers = useSelector(function (store) {
3043
- return serviceSelectors.getLayersFromServiceSelector(store, layerService);
3287
+ return serviceSelectors.getLayersFromServiceSelector(store, serviceUrl);
3044
3288
  });
3045
3289
  var layerChangeName = React.useCallback(function (_ref3) {
3046
3290
  var layerId = _ref3.layerId,
@@ -3082,6 +3326,11 @@ var RenderLayersConnect = function RenderLayersConnect(_ref) {
3082
3326
  skipLocalStyling: skipLocalStyling
3083
3327
  });
3084
3328
  }
3329
+ if (layerType === LayerType.featureLayer) {
3330
+ return jsx(RenderFeatureLayers, {
3331
+ layerName: layerDisplayName
3332
+ });
3333
+ }
3085
3334
  return jsx(RenderLayers, {
3086
3335
  layers: layers,
3087
3336
  layerName: layerName,
@@ -3103,6 +3352,10 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3103
3352
  tooltipTitle = _ref.tooltipTitle,
3104
3353
  icon = _ref.icon;
3105
3354
  var dispatch = useDispatch();
3355
+ var layerType = useSelector(function (store) {
3356
+ return layerSelectors.getLayerType(store, layerId);
3357
+ });
3358
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3106
3359
  var duplicateLayer = React.useCallback(function (_ref2) {
3107
3360
  var newLayerId = _ref2.newLayerId,
3108
3361
  mapId = _ref2.mapId;
@@ -3116,6 +3369,7 @@ var LayerManagerMenuButtonConnect = function LayerManagerMenuButtonConnect(_ref)
3116
3369
  return jsx(LayerManagerMenuButton, {
3117
3370
  layerId: layerId,
3118
3371
  mapId: mapId,
3372
+ isFeatureLayer: isFeatureLayer,
3119
3373
  onLayerDuplicate: function onLayerDuplicate() {
3120
3374
  duplicateLayer({
3121
3375
  newLayerId: webmapUtils.generateLayerId(),
@@ -3419,6 +3673,7 @@ var CustomDimensionSelectConnect = function CustomDimensionSelectConnect(_ref) {
3419
3673
 
3420
3674
  var LayerInfoButtonConnect = function LayerInfoButtonConnect(_ref) {
3421
3675
  var isLayerMissing = _ref.isLayerMissing,
3676
+ isFeatureLayer = _ref.isFeatureLayer,
3422
3677
  mapId = _ref.mapId,
3423
3678
  serviceUrl = _ref.serviceUrl,
3424
3679
  layerName = _ref.layerName,
@@ -3445,7 +3700,7 @@ var LayerInfoButtonConnect = function LayerInfoButtonConnect(_ref) {
3445
3700
  }
3446
3701
  };
3447
3702
  return jsx(LayerInfoButton, {
3448
- disabled: isLayerMissing,
3703
+ disabled: isLayerMissing || isFeatureLayer,
3449
3704
  isActive: isActive,
3450
3705
  onClick: onClick
3451
3706
  });
@@ -3508,11 +3763,12 @@ var LayerRowConnect = /*#__PURE__*/React.memo(function (_ref) {
3508
3763
  return layerSelectors.getLayerType(store, layerId);
3509
3764
  });
3510
3765
  var isEDRLayer = layerType === LayerType.edrFeatureLayer;
3766
+ var isFeatureLayer = layerType === LayerType.featureLayer;
3511
3767
  var layerServiceUrl = useSelector(function (store) {
3512
3768
  return layerSelectors.getLayerService(store, layerId);
3513
3769
  });
3514
3770
  var isLayerMissing = useSelector(function (store) {
3515
- return layerSelectors.getIsLayerMissing(store, layerId);
3771
+ return !isFeatureLayer ? layerSelectors.getIsLayerMissing(store, layerId) : false;
3516
3772
  });
3517
3773
  renderCounter.count(LayerRowConnect.name);
3518
3774
  return jsx(LayerRow, {
@@ -3573,7 +3829,8 @@ var LayerRowConnect = /*#__PURE__*/React.memo(function (_ref) {
3573
3829
  isLayerMissing: isLayerMissing,
3574
3830
  mapId: mapId,
3575
3831
  serviceUrl: layerServiceUrl,
3576
- layerName: layerName
3832
+ layerName: layerName,
3833
+ isFeatureLayer: isFeatureLayer
3577
3834
  }),
3578
3835
  layerMenuLayout: jsx(LayerManagerMenuButtonConnect, Object.assign({
3579
3836
  mapId: mapId,
@@ -3639,76 +3896,146 @@ var LayerContainerRow = /*#__PURE__*/React.memo(function (_ref) {
3639
3896
  var _React$useTransition = React.useTransition(),
3640
3897
  isPending = _React$useTransition[0],
3641
3898
  startTransition = _React$useTransition[1];
3642
- var _React$useState = React.useState(0),
3643
- rowsToDisplay = _React$useState[0],
3644
- setRowsToDisplay = _React$useState[1];
3645
- var layerIds = useSelector(function (store) {
3899
+ // Separate map layers and feature layers
3900
+ var mapLayerIds = useSelector(function (store) {
3646
3901
  return mapSelectors.getLayerIds(store, mapId);
3647
3902
  });
3648
- var layerLength = layerIds.length;
3649
- 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) {
3650
3927
  var mapId = _ref2.mapId,
3651
3928
  oldIndex = _ref2.oldIndex,
3652
- newIndex = _ref2.newIndex;
3929
+ newIndex = _ref2.newIndex,
3930
+ layerType = _ref2.layerType;
3653
3931
  return dispatch(mapActions.layerMoveLayer({
3654
3932
  mapId: mapId,
3655
3933
  oldIndex: oldIndex,
3656
3934
  newIndex: newIndex,
3657
- origin: layerTypes.LayerActionOrigin.layerManager
3935
+ origin: layerTypes.LayerActionOrigin.layerManager,
3936
+ layerType: layerType
3658
3937
  }));
3659
3938
  }, [dispatch]);
3660
- var _React$useState2 = React.useState(null),
3661
- activeDragIndex = _React$useState2[0],
3662
- setActiveDragIndex = _React$useState2[1];
3663
- var onSetList = function onSetList() {}; // since we use activeDragIndex, we don't need inner state handling of ReactSortable
3664
- var onStart = React.useCallback(function (_ref3) {
3939
+ // Drag handlers for map layers
3940
+ var onSetListMap = function onSetListMap() {};
3941
+ var onStartDragMap = React.useCallback(function (_ref3) {
3665
3942
  var oldIndex = _ref3.oldIndex;
3666
- setActiveDragIndex(oldIndex);
3943
+ setActiveDragIndexMap(oldIndex);
3667
3944
  if (Sortable.ghost) {
3668
3945
  Sortable.ghost.style.opacity = '1';
3669
3946
  }
3670
3947
  }, []);
3671
- var onEnd = React.useCallback(function () {
3672
- if (activeDragIndex !== null) {
3673
- setActiveDragIndex(null);
3948
+ var onEndDragMap = React.useCallback(function () {
3949
+ if (activeDragIndexMap !== null) {
3950
+ setActiveDragIndexMap(null);
3674
3951
  }
3675
- }, [activeDragIndex]);
3676
- var onSortEnd = function onSortEnd(_ref4) {
3952
+ }, [activeDragIndexMap]);
3953
+ var onSortEndMap = function onSortEndMap(_ref4) {
3677
3954
  var oldIndex = _ref4.oldIndex,
3678
3955
  newIndex = _ref4.newIndex;
3679
- setActiveDragIndex(null);
3680
- layerMoveLayer({
3956
+ setActiveDragIndexMap(null);
3957
+ layerMove({
3681
3958
  mapId: mapId,
3682
3959
  oldIndex: oldIndex,
3683
- newIndex: newIndex
3960
+ newIndex: newIndex,
3961
+ layerType: LayerType.mapLayer
3684
3962
  });
3685
3963
  };
3686
- var isSorting = activeDragIndex !== null;
3687
- var isDragDisabled = layerLength === 1;
3688
- var contents = layerIds.map(function (layerId) {
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({
3983
+ mapId: mapId,
3984
+ oldIndex: oldIndex,
3985
+ newIndex: newIndex,
3986
+ layerType: LayerType.featureLayer
3987
+ });
3988
+ };
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) {
3689
3995
  var _settings$dragHandle, _settings$dragHandle2;
3690
3996
  return jsx(LayerRowConnect, {
3691
3997
  mapId: mapId,
3692
3998
  layerId: layerId,
3693
3999
  dragHandle: jsx(DragHandle, {
3694
- isDisabled: isDragDisabled,
3695
- hideTooltip: isSorting || isDragDisabled,
3696
- isSorting: isSorting,
4000
+ isDisabled: isDragDisabledMap,
4001
+ hideTooltip: isSortingMap || isDragDisabledMap,
4002
+ isSorting: isSortingMap,
3697
4003
  icon: settings == null || (_settings$dragHandle = settings.dragHandle) == null ? void 0 : _settings$dragHandle.icon,
3698
4004
  tooltipTitle: settings == null || (_settings$dragHandle2 = settings.dragHandle) == null ? void 0 : _settings$dragHandle2.tooltipTitle
3699
4005
  }),
3700
4006
  settings: settings,
3701
4007
  collapsedColumns: collapsedColumns
3702
- }, "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);
3703
4025
  });
3704
4026
  React.useEffect(function () {
3705
- if (rowsToDisplay < layerLength) {
4027
+ if (rowsToDisplayMap < mapLayerIds.length) {
4028
+ startTransition(function () {
4029
+ setRowsToDisplayMap(rowsToDisplayMap + mapLayerIds.length);
4030
+ });
4031
+ }
4032
+ if (rowsToDisplayFeature < featureLayerIds.length) {
3706
4033
  startTransition(function () {
3707
- setRowsToDisplay(rowsToDisplay + layerLength);
4034
+ setRowsToDisplayFeature(rowsToDisplayFeature + featureLayerIds.length);
3708
4035
  });
3709
4036
  }
3710
- }, [layerLength, rowsToDisplay]);
3711
- return jsx(Grid, Object.assign({
4037
+ }, [mapLayerIds.length, featureLayerIds.length, rowsToDisplayMap, rowsToDisplayFeature]);
4038
+ return jsxs(Grid, Object.assign({
3712
4039
  container: true,
3713
4040
  "data-testid": "layerContainerRow",
3714
4041
  className: "layerContainerRow",
@@ -3724,29 +4051,48 @@ var LayerContainerRow = /*#__PURE__*/React.memo(function (_ref) {
3724
4051
  }
3725
4052
  }
3726
4053
  }, gridProps, {
3727
- children: jsx(ReactSortable, {
4054
+ children: [rowsToDisplayFeature > 0 && jsx(ReactSortable, {
3728
4055
  tag: "div",
3729
- list: layerIds.map(function (layerId) {
4056
+ list: featureLayerIds.map(function (layerId) {
3730
4057
  return {
3731
4058
  id: layerId
3732
4059
  };
3733
4060
  }),
3734
- setList: onSetList,
4061
+ setList: onSetListFeature,
3735
4062
  animation: 200,
3736
- onSort: onSortEnd,
4063
+ onSort: onSortEndFeature,
3737
4064
  handle: ".handle",
3738
4065
  direction: "vertical",
3739
- // hover props
3740
4066
  forceFallback: false,
3741
- onStart: onStart,
3742
- 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,
3743
4089
  style: {
3744
4090
  width: '100%'
3745
4091
  },
3746
4092
  children: isPending ? jsx(LinearProgress, {
3747
- "data-testid": "loading-bar"
3748
- }) : contents.slice(0, rowsToDisplay)
3749
- })
4093
+ "data-testid": "loading-bar-map"
4094
+ }) : mapLayerContents.slice(0, rowsToDisplayMap)
4095
+ })]
3750
4096
  }));
3751
4097
  });
3752
4098
 
@@ -4222,7 +4568,7 @@ var WMSLayerTreeConnect = connectRedux$3(ConnectedTree);
4222
4568
  * Copyright 2024 - The Norwegian Meteorological Institute (MET Norway)
4223
4569
  * */
4224
4570
  var isValidService = function isValidService(service) {
4225
- return Object.prototype.hasOwnProperty.call(service, 'url');
4571
+ return Object.hasOwn(service, 'url');
4226
4572
  };
4227
4573
  var filterServices = function filterServices(presetArray) {
4228
4574
  var hasServices = presetArray && Array.isArray(presetArray) && presetArray.length > 0;
@@ -4552,7 +4898,7 @@ var AddLayersPopup = function AddLayersPopup(_ref) {
4552
4898
  // No error message until new check
4553
4899
  setUrlError('');
4554
4900
  },
4555
- onKeyPress: function onKeyPress(event) {
4901
+ onKeyDown: function onKeyDown(event) {
4556
4902
  if (event.key === 'Enter') {
4557
4903
  handleAddServiceURL();
4558
4904
  }
@@ -6067,7 +6413,7 @@ var connectRedux = connect(function (store, props) {
6067
6413
  secondsPerPx: mapSelectors.getMapTimeSliderSecondsPerPx(store, props.mapId),
6068
6414
  span: mapSelectors.getMapTimeSliderSpan(store, props.mapId),
6069
6415
  timeStep: mapSelectors.getMapTimeStep(store, props.mapId),
6070
- isAnimating: mapSelectors.isAnimating(store, props.mapId),
6416
+ linkedMapAnimationInfo: mapSelectors.linkedMapAnimationInfo(store, props.mapId),
6071
6417
  isAutoUpdating: mapSelectors.isAutoUpdating(store, props.mapId)
6072
6418
  };
6073
6419
  }, {
@@ -6081,6 +6427,7 @@ var TimeSliderCurrentTimeBoxConnectComponent = function TimeSliderCurrentTimeBox
6081
6427
  secondsPerPx = _ref.secondsPerPx,
6082
6428
  span = _ref.span,
6083
6429
  timeStep = _ref.timeStep,
6430
+ linkedMapAnimationInfo = _ref.linkedMapAnimationInfo,
6084
6431
  isAutoUpdating = _ref.isAutoUpdating,
6085
6432
  setCenterTime = _ref.setCenterTime,
6086
6433
  unfilteredSelectedTime = _ref.unfilteredSelectedTime,
@@ -6098,6 +6445,7 @@ var TimeSliderCurrentTimeBoxConnectComponent = function TimeSliderCurrentTimeBox
6098
6445
  dataStartTime: dataStartTime,
6099
6446
  dataEndTime: dataEndTime,
6100
6447
  timeStep: timeStep,
6448
+ linkedMapAnimationInfo: linkedMapAnimationInfo,
6101
6449
  isAutoUpdating: isAutoUpdating,
6102
6450
  unfilteredSelectedTime: unfilteredSelectedTime,
6103
6451
  setUnfilteredSelectedTime: setUnfilteredSelectedTime,
@@ -7346,19 +7694,21 @@ var LocationSearch = function LocationSearch(_ref) {
7346
7694
  setSelectedValue(null);
7347
7695
  }
7348
7696
  },
7349
- InputProps: Object.assign({}, params.InputProps, {
7350
- endAdornment: jsx(CustomIconButton, {
7351
- tooltipTitle: t('search-clear'),
7352
- onClick: function onClick() {
7353
- setInputValue('');
7354
- setSelectedValue(null);
7355
- },
7356
- sx: {
7357
- marginRight: 1
7358
- },
7359
- 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
+ })
7360
7710
  })
7361
- })
7711
+ }
7362
7712
  }));
7363
7713
  }
7364
7714
  })]
@@ -7540,6 +7890,34 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref)
7540
7890
  hoverSelect = _ref.hoverSelect;
7541
7891
  var store = useStore();
7542
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]);
7543
7921
  var updateFeature = React__default.useCallback(function (geojson, reason) {
7544
7922
  if (!layerId) {
7545
7923
  window.console.error('updateFeature without layerId');
@@ -7574,7 +7952,13 @@ var OpenLayersFeatureLayerConnect = function OpenLayersFeatureLayerConnect(_ref)
7574
7952
  featureCollection: !layer.isInEditMode ? layer.geojson : undefined,
7575
7953
  zIndex: zIndex,
7576
7954
  style: style,
7577
- 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
7578
7962
  }), jsx(OpenLayersMapDraw, {
7579
7963
  drawMode: layer.drawMode,
7580
7964
  viewOnlyStyle: style,
@@ -7621,12 +8005,31 @@ var makePrefetchTimeSpan = function makePrefetchTimeSpan(timeSliderStartCenterEn
7621
8005
  end: roundEnd,
7622
8006
  step: timeSliderTimeStepInS
7623
8007
  });
7624
- // eslint-disable-next-line no-constant-condition
7625
8008
  return {
7626
8009
  isAnimating: isAnimating,
7627
8010
  prefetchList: timeSpanList
7628
8011
  };
7629
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
+ };
7630
8033
  var makeLayerInfoPayload = function makeLayerInfoPayload(payload, mapDimensions, mapId) {
7631
8034
  // During intialization, try to base the layer dimension on the current map dimension value.
7632
8035
  var origin = 'onInitializeLayer in OlMapViewLayerConnect';
@@ -7824,6 +8227,54 @@ var useGetOpenLayersView = function useGetOpenLayersView(mapId, store) {
7824
8227
  };
7825
8228
  };
7826
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
+
7827
8278
  /**
7828
8279
  * Connected component used to display the map and selected layers.
7829
8280
  * Includes options to disable the map controls and legend.
@@ -7978,6 +8429,9 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
7978
8429
  });
7979
8430
  var mapPinChangeLocation = React.useCallback(function (clickedLocation) {
7980
8431
  var _hoverLinkedFeature$g;
8432
+ if (disableMapPin) {
8433
+ return;
8434
+ }
7981
8435
  var mapPinLocation = getCenterOfLinkedFeature(hoverLinkedFeature, srs) || clickedLocation;
7982
8436
  var selectedFeatureId = (hoverLinkedFeature == null || (_hoverLinkedFeature$g = hoverLinkedFeature.getId()) == null ? void 0 : _hoverLinkedFeature$g.toString()) || '';
7983
8437
  if (hoverLinkedFeature) {
@@ -8002,7 +8456,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8002
8456
  mapPinLocation: mapPinLocation
8003
8457
  }));
8004
8458
  });
8005
- }, [dispatch, hoverLinkedFeature, linkedFeatures.features, linkedPanelId, mapId, selectedMapIds, srs]);
8459
+ }, [dispatch, disableMapPin, hoverLinkedFeature, linkedFeatures.features, linkedPanelId, mapId, selectedMapIds, srs]);
8006
8460
  var isActiveWindowId = useSelector(function (store) {
8007
8461
  return uiSelectors.getIsActiveWindowId(store, mapId);
8008
8462
  });
@@ -8017,10 +8471,6 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8017
8471
  id: mapId,
8018
8472
  type: [syncConstants.SYNCGROUPS_TYPE_SETTIME, syncConstants.SYNCGROUPS_TYPE_SETBBOX]
8019
8473
  });
8020
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8021
- id: mapId,
8022
- isGetMapLoading: false
8023
- }));
8024
8474
  return function () {
8025
8475
  unregisterMap({
8026
8476
  mapId: mapId
@@ -8030,18 +8480,6 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8030
8480
  });
8031
8481
  };
8032
8482
  }, [dispatch, mapId, registerMap, syncGroupRemoveSource, syncGroupsAddSource, unregisterMap]);
8033
- var onGetMapLoadStart = React.useCallback(function () {
8034
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8035
- id: mapId,
8036
- isGetMapLoading: true
8037
- }));
8038
- }, [dispatch, mapId]);
8039
- var onGetMapLoadReady = React.useCallback(function () {
8040
- dispatch(loadingIndicatorActions.setGetMapIsLoading({
8041
- id: mapId,
8042
- isGetMapLoading: false
8043
- }));
8044
- }, [dispatch, mapId]);
8045
8483
  React.useEffect(function () {
8046
8484
  if (!view) {
8047
8485
  return function () {};
@@ -8095,7 +8533,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8095
8533
  }
8096
8534
  }));
8097
8535
  }, [hoverId, previousHoverId, hoverLinkedFeature, featureProperties, linkedPanelId, dispatch]);
8098
- var prefetchTimespan = makePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList);
8536
+ var prefetchTimespan = usePrefetchTimeSpan(timeSliderStartCenterEndTime, isAnimating, animationList);
8099
8537
  var layerIds = mapLayerIds.join();
8100
8538
  var refetchLayers = React.useCallback(function () {
8101
8539
  mapLayerIds == null || mapLayerIds.forEach(/*#__PURE__*/function () {
@@ -8145,24 +8583,7 @@ var OlMapViewConnect = function OlMapViewConnect(_ref) {
8145
8583
  // eslint-disable-next-line react-hooks/exhaustive-deps
8146
8584
  }, [mapId, updateLayerInformation, layerIds]);
8147
8585
  useSetIntervalWhenVisible(refetchLayers, 60000);
8148
- var isLoading = React.useRef(false);
8149
- // UseEffect for loading indicator
8150
- React.useEffect(function () {
8151
- openLayersGetMapImageStore.addImageEventCallback(function () {
8152
- var checkLoading = !!(openLayersGetMapImageStore.getNumImagesLoading() > 0);
8153
- if (checkLoading !== isLoading.current) {
8154
- if (checkLoading === true) {
8155
- onGetMapLoadStart && onGetMapLoadStart();
8156
- } else {
8157
- onGetMapLoadReady && onGetMapLoadReady();
8158
- }
8159
- isLoading.current = checkLoading;
8160
- }
8161
- }, mapId);
8162
- return function () {
8163
- openLayersGetMapImageStore.removeEventCallback(mapId);
8164
- };
8165
- }, [mapId, onGetMapLoadReady, onGetMapLoadStart]);
8586
+ useMapViewLoadingIndicator(mapId, mapLayerIds);
8166
8587
  var _React$useState2 = React.useState(false),
8167
8588
  debugMode = _React$useState2[0],
8168
8589
  setDebugMode = _React$useState2[1];
@@ -8961,8 +9382,10 @@ var SyncGroupListItem = function SyncGroupListItem(_ref) {
8961
9382
  checked: isChecked,
8962
9383
  tabIndex: -1,
8963
9384
  disableRipple: true,
8964
- inputProps: {
8965
- 'aria-labelledby': source.name
9385
+ slotProps: {
9386
+ input: {
9387
+ 'aria-labelledby': source.name
9388
+ }
8966
9389
  },
8967
9390
  sx: isNotCheckedElseWhere ? styles.checkboxIsActive : styles.isDisabled,
8968
9391
  color: "default"
@@ -9143,8 +9566,10 @@ var SyncGroupViewer = function SyncGroupViewer(_ref) {
9143
9566
  },
9144
9567
  children: t('workspace-time-scroll-off')
9145
9568
  }), jsx(Switch, {
9146
- inputProps: {
9147
- 'aria-label': 'workspace time scroll toggle'
9569
+ slotProps: {
9570
+ input: {
9571
+ 'aria-label': 'workspace time scroll toggle'
9572
+ }
9148
9573
  },
9149
9574
  checked: isTimeScrollingEnabled,
9150
9575
  onChange: function onChange() {
@@ -9658,6 +10083,215 @@ var LanguageSelect = function LanguageSelect(_ref) {
9658
10083
  });
9659
10084
  };
9660
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
+
9661
10295
  /* *
9662
10296
  * Licensed under the Apache License, Version 2.0 (the "License");
9663
10297
  * you may not use this file except in compliance with the License.
@@ -9939,4 +10573,4 @@ var storyUtils = /*#__PURE__*/Object.freeze({
9939
10573
  useDefaultMapSettings: useDefaultMapSettings
9940
10574
  });
9941
10575
 
9942
- 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 };