@opengeoweb/soundings 15.0.0 → 15.1.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.
- package/index.esm.js +464 -130
- package/package.json +8 -8
- package/src/index.d.ts +2 -0
- package/src/lib/api/edr-api/hooks.d.ts +2 -2
- package/src/lib/components/MenuBar/LocationsMenu.d.ts +1 -1
- package/src/lib/components/MenuBar/MenuBar.d.ts +3 -1
- package/src/lib/components/MenuBar/SoundingsMarkersSwitch.d.ts +6 -0
- package/src/lib/components/MenuBar/SoundingsMarkersSwitch.spec.d.ts +1 -0
- package/src/lib/components/MenuBar/SoundingsSourceMenu.d.ts +1 -1
- package/src/lib/components/Soundings/SoundingsConnect.d.ts +3 -3
- package/src/lib/components/SoundingsTimeSlider/SoundingsTimeSliderConnect.d.ts +5 -1
- package/src/lib/store/reducer.d.ts +4 -1
- package/src/lib/store/selectors.d.ts +69 -5
- package/src/lib/store/store.d.ts +3 -0
- package/src/lib/store/types.d.ts +24 -15
- package/src/lib/utils/soundingsLookUp.d.ts +2 -3
package/index.esm.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { Menu, ListSubheader, Typography, MenuItem, Box, Card, Stack, IconButton, Tooltip, LinearProgress, List, ListItem, ListItemIcon, Checkbox, ListItemText, Grid, ListItemButton } from '@mui/material';
|
|
3
|
+
import { range, minBy, isEqual } from 'lodash';
|
|
3
4
|
import React, { useRef, useEffect, useMemo, useState, Fragment as Fragment$1 } from 'react';
|
|
4
|
-
import { useDispatch, useSelector } from 'react-redux';
|
|
5
|
-
import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, CustomToggleButton, dateUtils, CustomSlider, AlertBanner, ToolContainerDraggable, StyledSelect, SearchField, CustomAccordion } from '@opengeoweb/shared';
|
|
5
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
6
|
+
import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, CustomToggleButton, dateUtils, SwitchButton, CustomSlider, AlertBanner, ToolContainerDraggable, StyledSelect, SearchField, CustomAccordion } from '@opengeoweb/shared';
|
|
6
7
|
import { selectorMemoizationOptions, uiSelectors, uiTypes, uiActions, genericSelectors, mapSelectors, genericActions, syncGroupsActions, mapActions, useSetupDialog, storeReducerMap, storeMiddlewares } from '@opengeoweb/store';
|
|
7
8
|
import { ParseISOTimeRangeDuration, parseISO8601IntervalToDateInterval, webmapUtils } from '@opengeoweb/webmap';
|
|
8
9
|
import { MapFeatureClass } from '@opengeoweb/webmap-react';
|
|
@@ -16,7 +17,6 @@ import { timesliderTranslations, TIME_SLIDER_NAMESPACE, BackwardForwardStepButto
|
|
|
16
17
|
import { useResizable } from 'react-resizable-layout';
|
|
17
18
|
import { useQueries } from '@tanstack/react-query';
|
|
18
19
|
import { getHeaders, handleResponse } from '@opengeoweb/api';
|
|
19
|
-
import { range, minBy } from 'lodash';
|
|
20
20
|
import { createSlice, createSelector, combineReducers, configureStore } from '@reduxjs/toolkit';
|
|
21
21
|
import { FixedSizeList } from 'react-window';
|
|
22
22
|
|
|
@@ -30,7 +30,9 @@ var en = {
|
|
|
30
30
|
options: "Options",
|
|
31
31
|
"diagram-SKEWT": "Skew-T",
|
|
32
32
|
"diagram-BIJVOET": "Bijvoet",
|
|
33
|
-
"diagram-EMAGRAM": "Emagram"
|
|
33
|
+
"diagram-EMAGRAM": "Emagram",
|
|
34
|
+
"soundings-toggle-location-markers-label": "Markers",
|
|
35
|
+
"soundings-toggle-location-markers-tooltip": "Show/hide location markers"
|
|
34
36
|
};
|
|
35
37
|
var no = {
|
|
36
38
|
sources: "Kilder",
|
|
@@ -42,7 +44,9 @@ var no = {
|
|
|
42
44
|
options: "Valg",
|
|
43
45
|
"diagram-SKEWT": "Skew-T",
|
|
44
46
|
"diagram-BIJVOET": "Bijvoet",
|
|
45
|
-
"diagram-EMAGRAM": "Emagram"
|
|
47
|
+
"diagram-EMAGRAM": "Emagram",
|
|
48
|
+
"soundings-toggle-location-markers-label": "ikke oversatt",
|
|
49
|
+
"soundings-toggle-location-markers-tooltip": "ikke oversatt"
|
|
46
50
|
};
|
|
47
51
|
var nl = {
|
|
48
52
|
sources: "Bronnen",
|
|
@@ -54,7 +58,9 @@ var nl = {
|
|
|
54
58
|
options: "Opties",
|
|
55
59
|
"diagram-SKEWT": "Skew-T",
|
|
56
60
|
"diagram-BIJVOET": "Bijvoet",
|
|
57
|
-
"diagram-EMAGRAM": "Emagram"
|
|
61
|
+
"diagram-EMAGRAM": "Emagram",
|
|
62
|
+
"soundings-toggle-location-markers-label": "Kaart locaties",
|
|
63
|
+
"soundings-toggle-location-markers-tooltip": "Toon/Verberg locatie punten"
|
|
58
64
|
};
|
|
59
65
|
var fi = {
|
|
60
66
|
sources: "Lähteet",
|
|
@@ -66,7 +72,9 @@ var fi = {
|
|
|
66
72
|
options: "Valinnat",
|
|
67
73
|
"diagram-SKEWT": "Skew-T",
|
|
68
74
|
"diagram-BIJVOET": "Bijvoet",
|
|
69
|
-
"diagram-EMAGRAM": "Emagram"
|
|
75
|
+
"diagram-EMAGRAM": "Emagram",
|
|
76
|
+
"soundings-toggle-location-markers-label": "Merkit",
|
|
77
|
+
"soundings-toggle-location-markers-tooltip": "Näytä/piilota kohdemerkit"
|
|
70
78
|
};
|
|
71
79
|
var soundingsTranslations = {
|
|
72
80
|
en: en,
|
|
@@ -2850,10 +2858,28 @@ const useMultipleSources = (sources, locations, datetime) => {
|
|
|
2850
2858
|
parameterMappings,
|
|
2851
2859
|
verticalRange
|
|
2852
2860
|
}, index) => {
|
|
2853
|
-
//
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2861
|
+
// Find the best matching timestep for this source
|
|
2862
|
+
let dateToUse = '';
|
|
2863
|
+
if (datetime && timesteps[index] && timesteps[index].length > 0) {
|
|
2864
|
+
const requestedTime = new Date(datetime).getTime();
|
|
2865
|
+
const availableTimesteps = timesteps[index];
|
|
2866
|
+
// Check for exact match first
|
|
2867
|
+
if (availableTimesteps.includes(new Date(datetime).toISOString())) {
|
|
2868
|
+
dateToUse = datetime;
|
|
2869
|
+
} else {
|
|
2870
|
+
// Find nearest timestep (prefer earlier timesteps if equidistant)
|
|
2871
|
+
let nearestTimestep = availableTimesteps[0];
|
|
2872
|
+
let minDiff = Math.abs(new Date(availableTimesteps[0]).getTime() - requestedTime);
|
|
2873
|
+
for (const timestep of availableTimesteps) {
|
|
2874
|
+
const diff = Math.abs(new Date(timestep).getTime() - requestedTime);
|
|
2875
|
+
if (diff < minDiff) {
|
|
2876
|
+
minDiff = diff;
|
|
2877
|
+
nearestTimestep = timestep;
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
dateToUse = nearestTimestep;
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2857
2883
|
const queryParams = constructQueryParams(collectionId, url, instanceId, locations[collectionId] || '', dateToUse || '', parameterMappings || defaultParameterMappings, verticalRange || '');
|
|
2858
2884
|
return queryParams;
|
|
2859
2885
|
});
|
|
@@ -3056,15 +3082,39 @@ const initialSoundingsState = {
|
|
|
3056
3082
|
selectedSources: {},
|
|
3057
3083
|
selectedLocations: {},
|
|
3058
3084
|
selectedTime: new Date().toISOString(),
|
|
3085
|
+
diagramType: 'SKEWT',
|
|
3059
3086
|
soundingPanels: {
|
|
3060
|
-
order: [],
|
|
3061
|
-
entities: {
|
|
3062
|
-
|
|
3087
|
+
order: ['soundings', 'windbarbs'],
|
|
3088
|
+
entities: {
|
|
3089
|
+
soundings: {
|
|
3090
|
+
id: 'soundings',
|
|
3091
|
+
name: 'Soundings',
|
|
3092
|
+
isDisplayed: true
|
|
3093
|
+
},
|
|
3094
|
+
windbarbs: {
|
|
3095
|
+
id: 'windbarbs',
|
|
3096
|
+
name: 'Wind Barbs',
|
|
3097
|
+
isDisplayed: true
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
},
|
|
3101
|
+
shouldHideLocationMarkers: false
|
|
3063
3102
|
};
|
|
3064
3103
|
const slice = createSlice({
|
|
3065
3104
|
initialState: initialSoundingsState,
|
|
3066
3105
|
name: 'soundings',
|
|
3067
3106
|
reducers: {
|
|
3107
|
+
registerSoundingsPreset: (draft, payloadAction) => {
|
|
3108
|
+
const preset = payloadAction.payload;
|
|
3109
|
+
if (preset) {
|
|
3110
|
+
draft.selectedSources = preset.selectedSources ?? {};
|
|
3111
|
+
draft.selectedLocations = preset.selectedLocations ?? {};
|
|
3112
|
+
draft.selectedTime = preset.selectedTime ?? new Date().toISOString();
|
|
3113
|
+
draft.diagramType = preset.diagramType ?? 'SKEWT';
|
|
3114
|
+
draft.soundingPanels = preset.soundingPanels ?? initialSoundingsState.soundingPanels;
|
|
3115
|
+
draft.shouldHideLocationMarkers = preset.shouldHideLocationMarkers ?? false;
|
|
3116
|
+
}
|
|
3117
|
+
},
|
|
3068
3118
|
updateSelectedSource: (draft, payloadAction) => {
|
|
3069
3119
|
const {
|
|
3070
3120
|
sourceId,
|
|
@@ -3088,6 +3138,15 @@ const slice = createSlice({
|
|
|
3088
3138
|
} = payloadAction.payload;
|
|
3089
3139
|
draft.selectedTime = selectedTime;
|
|
3090
3140
|
},
|
|
3141
|
+
updateDiagramType: (draft, payloadAction) => {
|
|
3142
|
+
draft.diagramType = payloadAction.payload.diagramType;
|
|
3143
|
+
},
|
|
3144
|
+
toggleLocationMarkers: (draft, payloadAction) => {
|
|
3145
|
+
const {
|
|
3146
|
+
shouldHideLocationMarkers
|
|
3147
|
+
} = payloadAction.payload;
|
|
3148
|
+
draft.shouldHideLocationMarkers = shouldHideLocationMarkers;
|
|
3149
|
+
},
|
|
3091
3150
|
addSoundingPanelsFromPreset: (draft, payloadAction) => {
|
|
3092
3151
|
const {
|
|
3093
3152
|
order,
|
|
@@ -3131,7 +3190,9 @@ const getSourceSelections = createSelector(getSoundingsStore, store => {
|
|
|
3131
3190
|
return store.selectedSources;
|
|
3132
3191
|
}, selectorMemoizationOptions);
|
|
3133
3192
|
const getLocationSelections = createSelector(getSoundingsStore, store => store.selectedLocations, selectorMemoizationOptions);
|
|
3134
|
-
const getSelectedTime = createSelector(getSoundingsStore, store => store.selectedTime, selectorMemoizationOptions);
|
|
3193
|
+
const getSelectedTime = createSelector(getSoundingsStore, store => store.selectedTime ?? new Date().toISOString(), selectorMemoizationOptions);
|
|
3194
|
+
const getDiagramType = createSelector(getSoundingsStore, store => store.diagramType ?? 'SKEWT', selectorMemoizationOptions);
|
|
3195
|
+
const getShouldHideLocationMarkers = createSelector(getSoundingsStore, store => store.shouldHideLocationMarkers ?? false, selectorMemoizationOptions);
|
|
3135
3196
|
const getSelectedSources = createSelector(getSoundingsStore, store => {
|
|
3136
3197
|
const sources = store.selectedSources;
|
|
3137
3198
|
const activeSources = Object.keys(sources).reduce((list, key) => {
|
|
@@ -3139,11 +3200,11 @@ const getSelectedSources = createSelector(getSoundingsStore, store => {
|
|
|
3139
3200
|
if (value.isChecked === true) {
|
|
3140
3201
|
return list.concat({
|
|
3141
3202
|
collectionId: key,
|
|
3142
|
-
url: value.url,
|
|
3203
|
+
url: value.url ?? '',
|
|
3143
3204
|
instanceId: value.instanceId,
|
|
3144
3205
|
verticalRange: value.verticalRange,
|
|
3145
3206
|
parameterMappings: value.parameterMappings,
|
|
3146
|
-
name: value.name
|
|
3207
|
+
name: value.name ?? ''
|
|
3147
3208
|
});
|
|
3148
3209
|
}
|
|
3149
3210
|
return list;
|
|
@@ -3156,6 +3217,27 @@ const getSelectedSourcesAmount = createSelector(getSelectedSources, activeSource
|
|
|
3156
3217
|
const getSelectedSourcesIds = createSelector(getSelectedSources, activeSources => {
|
|
3157
3218
|
return activeSources.map(source => source.collectionId);
|
|
3158
3219
|
}, selectorMemoizationOptions);
|
|
3220
|
+
const getSoundingsPreset = createSelector(getSoundingsStore, soundingsStore => {
|
|
3221
|
+
const {
|
|
3222
|
+
selectedTime,
|
|
3223
|
+
selectedSources,
|
|
3224
|
+
...rest
|
|
3225
|
+
} = soundingsStore;
|
|
3226
|
+
const filteredSources = Object.entries(selectedSources).reduce((acc, [key, value]) => {
|
|
3227
|
+
const {
|
|
3228
|
+
instanceId,
|
|
3229
|
+
...sourceWithoutInstance
|
|
3230
|
+
} = value;
|
|
3231
|
+
return {
|
|
3232
|
+
...acc,
|
|
3233
|
+
[key]: sourceWithoutInstance
|
|
3234
|
+
};
|
|
3235
|
+
}, {});
|
|
3236
|
+
return {
|
|
3237
|
+
...rest,
|
|
3238
|
+
selectedSources: filteredSources
|
|
3239
|
+
};
|
|
3240
|
+
}, selectorMemoizationOptions);
|
|
3159
3241
|
const getSoundingPanelsInOrder = createSelector(getSoundingsStore, store => {
|
|
3160
3242
|
const {
|
|
3161
3243
|
order = [],
|
|
@@ -3167,6 +3249,104 @@ const getSoundingPanelsInOrder = createSelector(getSoundingsStore, store => {
|
|
|
3167
3249
|
return order.map(id => entities[id]);
|
|
3168
3250
|
}, selectorMemoizationOptions);
|
|
3169
3251
|
|
|
3252
|
+
var selectors = /*#__PURE__*/Object.freeze({
|
|
3253
|
+
__proto__: null,
|
|
3254
|
+
getDiagramType: getDiagramType,
|
|
3255
|
+
getLocationSelections: getLocationSelections,
|
|
3256
|
+
getSelectedSources: getSelectedSources,
|
|
3257
|
+
getSelectedSourcesAmount: getSelectedSourcesAmount,
|
|
3258
|
+
getSelectedSourcesIds: getSelectedSourcesIds,
|
|
3259
|
+
getSelectedTime: getSelectedTime,
|
|
3260
|
+
getShouldHideLocationMarkers: getShouldHideLocationMarkers,
|
|
3261
|
+
getSoundingPanelsInOrder: getSoundingPanelsInOrder,
|
|
3262
|
+
getSoundingsPreset: getSoundingsPreset,
|
|
3263
|
+
getSourceSelections: getSourceSelections
|
|
3264
|
+
});
|
|
3265
|
+
|
|
3266
|
+
/* *
|
|
3267
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
3268
|
+
* you may not use this file except in compliance with the License.
|
|
3269
|
+
* You may obtain a copy of the License at
|
|
3270
|
+
*
|
|
3271
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
3272
|
+
*
|
|
3273
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
3274
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
3275
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
3276
|
+
* See the License for the specific language governing permissions and
|
|
3277
|
+
* limitations under the License.
|
|
3278
|
+
*
|
|
3279
|
+
* Copyright 2025 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
|
|
3280
|
+
* Copyright 2025 - Finnish Meteorological Institute (FMI)
|
|
3281
|
+
* Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
|
|
3282
|
+
* */
|
|
3283
|
+
var SoundingsActionOrigin;
|
|
3284
|
+
(function (SoundingsActionOrigin) {
|
|
3285
|
+
SoundingsActionOrigin["soundingsManager"] = "soundingsManager";
|
|
3286
|
+
SoundingsActionOrigin["soundingsComponent"] = "soundingsComponent";
|
|
3287
|
+
})(SoundingsActionOrigin || (SoundingsActionOrigin = {}));
|
|
3288
|
+
|
|
3289
|
+
var types = /*#__PURE__*/Object.freeze({
|
|
3290
|
+
__proto__: null,
|
|
3291
|
+
get SoundingsActionOrigin () { return SoundingsActionOrigin; }
|
|
3292
|
+
});
|
|
3293
|
+
|
|
3294
|
+
const SoundingsMarkersSwitch = ({
|
|
3295
|
+
shouldHideMarkers,
|
|
3296
|
+
toggleMarkers
|
|
3297
|
+
}) => {
|
|
3298
|
+
const {
|
|
3299
|
+
t
|
|
3300
|
+
} = useSoundingsTranslation();
|
|
3301
|
+
return jsxs(Box, {
|
|
3302
|
+
sx: {
|
|
3303
|
+
display: 'flex',
|
|
3304
|
+
flexWrap: 'wrap',
|
|
3305
|
+
alignItems: 'flex-start',
|
|
3306
|
+
'label:first-of-type': {
|
|
3307
|
+
marginLeft: '5px',
|
|
3308
|
+
marginRight: '-5px'
|
|
3309
|
+
},
|
|
3310
|
+
'label:last-of-type': {
|
|
3311
|
+
marginLeft: '-5px'
|
|
3312
|
+
},
|
|
3313
|
+
'.switch-button label': {
|
|
3314
|
+
display: 'none'
|
|
3315
|
+
},
|
|
3316
|
+
'.markers-label': {
|
|
3317
|
+
display: 'none'
|
|
3318
|
+
},
|
|
3319
|
+
'@media (min-width: 720px)': {
|
|
3320
|
+
minWidth: '146px',
|
|
3321
|
+
'.markers-label, .switch-button label': {
|
|
3322
|
+
display: 'initial'
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
},
|
|
3326
|
+
children: [jsx(Typography, {
|
|
3327
|
+
className: "markers-label",
|
|
3328
|
+
sx: {
|
|
3329
|
+
marginTop: '4px'
|
|
3330
|
+
},
|
|
3331
|
+
variant: "body2",
|
|
3332
|
+
children: t('soundings-toggle-location-markers-label')
|
|
3333
|
+
}), jsx(Box, {
|
|
3334
|
+
sx: {
|
|
3335
|
+
marginTop: '-5px'
|
|
3336
|
+
},
|
|
3337
|
+
children: jsx(SwitchButton, {
|
|
3338
|
+
activeLabel: "ON",
|
|
3339
|
+
checked: !shouldHideMarkers,
|
|
3340
|
+
inActiveLabel: "OFF",
|
|
3341
|
+
onChange: event => {
|
|
3342
|
+
toggleMarkers(!event.target.checked);
|
|
3343
|
+
},
|
|
3344
|
+
tooltip: t('soundings-toggle-location-markers-tooltip')
|
|
3345
|
+
})
|
|
3346
|
+
})]
|
|
3347
|
+
});
|
|
3348
|
+
};
|
|
3349
|
+
|
|
3170
3350
|
var MenuOptions;
|
|
3171
3351
|
(function (MenuOptions) {
|
|
3172
3352
|
MenuOptions["soundingsManager"] = "Sd Manager";
|
|
@@ -3180,7 +3360,9 @@ const buttonStyle = {
|
|
|
3180
3360
|
const SoundingsMenuBar = ({
|
|
3181
3361
|
handleClick,
|
|
3182
3362
|
isOpen,
|
|
3183
|
-
selectedSourcesAmount = 0
|
|
3363
|
+
selectedSourcesAmount = 0,
|
|
3364
|
+
shouldHideMarkers,
|
|
3365
|
+
toggleMarkers
|
|
3184
3366
|
}) => {
|
|
3185
3367
|
const {
|
|
3186
3368
|
t
|
|
@@ -3219,6 +3401,9 @@ const SoundingsMenuBar = ({
|
|
|
3219
3401
|
sx: buttonStyle,
|
|
3220
3402
|
variant: "tool",
|
|
3221
3403
|
children: t('locations')
|
|
3404
|
+
}), jsx(SoundingsMarkersSwitch, {
|
|
3405
|
+
shouldHideMarkers: shouldHideMarkers,
|
|
3406
|
+
toggleMarkers: toggleMarkers
|
|
3222
3407
|
})]
|
|
3223
3408
|
});
|
|
3224
3409
|
};
|
|
@@ -3235,6 +3420,14 @@ const MenuBarConnect = ({
|
|
|
3235
3420
|
const isLocationsOpenInStore = useSelector(store => uiSelectors.getisDialogOpen(store, uiTypes.DialogTypes.SoundingsLocations));
|
|
3236
3421
|
const isSoundingsManagerOpenInStore = useSelector(store => uiSelectors.getisDialogOpen(store, uiTypes.DialogTypes.SoundingsManager));
|
|
3237
3422
|
const sourcesAmount = useSelector(getSelectedSourcesAmount);
|
|
3423
|
+
const shouldHideLocationMarkers = useSelector(getShouldHideLocationMarkers);
|
|
3424
|
+
const toggleLocationMarkers = React.useCallback(shouldHide => {
|
|
3425
|
+
dispatch(soundingsActions.toggleLocationMarkers({
|
|
3426
|
+
shouldHideLocationMarkers: shouldHide,
|
|
3427
|
+
panelId: viewId,
|
|
3428
|
+
origin: SoundingsActionOrigin.soundingsComponent
|
|
3429
|
+
}));
|
|
3430
|
+
}, [dispatch, viewId]);
|
|
3238
3431
|
const dispatchActiveMapId = React.useCallback((dialogType, isOpen, activeMapId) => void dispatch(uiActions.setActiveMapIdForDialog({
|
|
3239
3432
|
type: dialogType,
|
|
3240
3433
|
mapId: viewId,
|
|
@@ -3262,7 +3455,9 @@ const MenuBarConnect = ({
|
|
|
3262
3455
|
return jsx(SoundingsMenuBar, {
|
|
3263
3456
|
handleClick: handleClick,
|
|
3264
3457
|
isOpen: isOpen,
|
|
3265
|
-
selectedSourcesAmount: sourcesAmount
|
|
3458
|
+
selectedSourcesAmount: sourcesAmount,
|
|
3459
|
+
shouldHideMarkers: shouldHideLocationMarkers,
|
|
3460
|
+
toggleMarkers: toggleLocationMarkers
|
|
3266
3461
|
});
|
|
3267
3462
|
};
|
|
3268
3463
|
|
|
@@ -3402,24 +3597,33 @@ const roundToClosestTimestep = (timeToRound, availableSteps) => {
|
|
|
3402
3597
|
}
|
|
3403
3598
|
return timeToRound;
|
|
3404
3599
|
};
|
|
3405
|
-
const SoundingsTimeSliderConnect = (
|
|
3600
|
+
const SoundingsTimeSliderConnect = ({
|
|
3601
|
+
viewId
|
|
3602
|
+
}) => {
|
|
3406
3603
|
const selectedTime = useSelector(getSelectedTime);
|
|
3407
3604
|
const sourceSelections = useSelector(getSelectedSources);
|
|
3408
3605
|
const dispatch = useDispatch();
|
|
3409
|
-
const updateSelectedTime = React.useCallback(selectedTime => {
|
|
3606
|
+
const updateSelectedTime = React.useCallback((selectedTime, isInitialCorrection = false) => {
|
|
3410
3607
|
dispatch(soundingsActions.updateSelectedTime({
|
|
3411
|
-
selectedTime
|
|
3608
|
+
selectedTime,
|
|
3609
|
+
panelId: viewId,
|
|
3610
|
+
origin: isInitialCorrection ? SoundingsActionOrigin.soundingsManager : SoundingsActionOrigin.soundingsComponent
|
|
3412
3611
|
}));
|
|
3413
|
-
}, [dispatch]);
|
|
3612
|
+
}, [dispatch, viewId]);
|
|
3414
3613
|
const {
|
|
3415
3614
|
data: timesteps
|
|
3416
3615
|
} = useTimesteps(sourceSelections);
|
|
3417
3616
|
const mergedTimesteps = [...new Set(timesteps.flat())].sort();
|
|
3617
|
+
const hasInitializedTime = React.useRef(false);
|
|
3418
3618
|
// Ensure that the selected time is always one of the available timesteps
|
|
3419
3619
|
const validSelectedTime = roundToClosestTimestep(selectedTime, mergedTimesteps);
|
|
3420
3620
|
useEffect(() => {
|
|
3421
3621
|
if (selectedTime !== validSelectedTime) {
|
|
3422
|
-
|
|
3622
|
+
const isInitial = !hasInitializedTime.current;
|
|
3623
|
+
updateSelectedTime(validSelectedTime, isInitial);
|
|
3624
|
+
if (isInitial) {
|
|
3625
|
+
hasInitializedTime.current = true;
|
|
3626
|
+
}
|
|
3423
3627
|
}
|
|
3424
3628
|
}, [selectedTime, updateSelectedTime, validSelectedTime]);
|
|
3425
3629
|
return jsx(SoundingsTimeSlider, {
|
|
@@ -3458,33 +3662,80 @@ const useGetSize = viewRef => {
|
|
|
3458
3662
|
};
|
|
3459
3663
|
const SoundingsConnect = ({
|
|
3460
3664
|
viewId,
|
|
3461
|
-
|
|
3665
|
+
soundingsPreset
|
|
3462
3666
|
}) => {
|
|
3463
3667
|
const viewRef = React.useRef(null);
|
|
3464
3668
|
const size = useGetSize(viewRef);
|
|
3465
|
-
const [chosenDiagramType, setChosenDiagramType] = React.useState(diagramType);
|
|
3466
3669
|
const geojsonLayerId = React.useRef(webmapUtils.generateLayerId()).current;
|
|
3467
3670
|
const dispatch = useDispatch();
|
|
3671
|
+
const soundingsPresetRef = React.useRef();
|
|
3672
|
+
const presetJustLoadedRef = React.useRef(false);
|
|
3673
|
+
const initialLocationsRef = React.useRef({});
|
|
3674
|
+
const previousLocationsRef = React.useRef({});
|
|
3675
|
+
React.useLayoutEffect(() => {
|
|
3676
|
+
if (soundingsPreset && !isEqual(soundingsPreset, soundingsPresetRef.current)) {
|
|
3677
|
+
soundingsPresetRef.current = soundingsPreset;
|
|
3678
|
+
presetJustLoadedRef.current = true;
|
|
3679
|
+
initialLocationsRef.current = soundingsPreset.selectedLocations || {};
|
|
3680
|
+
previousLocationsRef.current = {};
|
|
3681
|
+
dispatch(soundingsActions.registerSoundingsPreset(soundingsPreset));
|
|
3682
|
+
setTimeout(() => {
|
|
3683
|
+
presetJustLoadedRef.current = false;
|
|
3684
|
+
initialLocationsRef.current = {};
|
|
3685
|
+
}, 500);
|
|
3686
|
+
} else if (!soundingsPreset) {
|
|
3687
|
+
soundingsPresetRef.current = undefined;
|
|
3688
|
+
initialLocationsRef.current = {};
|
|
3689
|
+
previousLocationsRef.current = {};
|
|
3690
|
+
}
|
|
3691
|
+
}, [dispatch, soundingsPreset, viewId]);
|
|
3468
3692
|
const selectedTime = useSelector(getSelectedTime);
|
|
3469
|
-
const sourceSelections = useSelector(getSelectedSources);
|
|
3470
|
-
const locationSelections = useSelector(getLocationSelections);
|
|
3471
|
-
const
|
|
3472
|
-
const
|
|
3693
|
+
const sourceSelections = useSelector(getSelectedSources, shallowEqual);
|
|
3694
|
+
const locationSelections = useSelector(getLocationSelections, shallowEqual);
|
|
3695
|
+
const diagramType = useSelector(getDiagramType);
|
|
3696
|
+
const shouldHideLocationMarkers = useSelector(getShouldHideLocationMarkers);
|
|
3697
|
+
const setChosenDiagramType = React.useCallback(diagramType => {
|
|
3698
|
+
dispatch(soundingsActions.updateDiagramType({
|
|
3699
|
+
diagramType,
|
|
3700
|
+
panelId: viewId,
|
|
3701
|
+
origin: SoundingsActionOrigin.soundingsComponent
|
|
3702
|
+
}));
|
|
3703
|
+
}, [dispatch, viewId]);
|
|
3704
|
+
const selectedFeature = useSelector(state => genericSelectors.getSelectedFeature(state.syncGroups, viewId), shallowEqual);
|
|
3705
|
+
const selectedMapIds = useSelector(state => genericSelectors.getLinkedMaps(state, viewId), shallowEqual);
|
|
3706
|
+
const firstMapId = selectedMapIds[0];
|
|
3473
3707
|
const selectedMapPin = useSelector(state =>
|
|
3474
3708
|
// mapPins are synced so we can arbitrarily choose the first linked map
|
|
3475
|
-
mapSelectors.getPinLocation(state,
|
|
3476
|
-
const
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3709
|
+
mapSelectors.getPinLocation(state, firstMapId), shallowEqual);
|
|
3710
|
+
const collectionsRef = React.useRef();
|
|
3711
|
+
const collections = useMemo(() => {
|
|
3712
|
+
const newCollections = sourceSelections.map(({
|
|
3713
|
+
collectionId,
|
|
3714
|
+
url,
|
|
3715
|
+
name
|
|
3716
|
+
}) => ({
|
|
3717
|
+
id: collectionId,
|
|
3718
|
+
url,
|
|
3719
|
+
name: name || collectionId
|
|
3720
|
+
}));
|
|
3721
|
+
if (isEqual(newCollections, collectionsRef.current)) {
|
|
3722
|
+
return collectionsRef.current;
|
|
3723
|
+
}
|
|
3724
|
+
collectionsRef.current = newCollections;
|
|
3725
|
+
return newCollections;
|
|
3726
|
+
}, [sourceSelections]);
|
|
3485
3727
|
const {
|
|
3486
|
-
data:
|
|
3728
|
+
data: rawLocationData
|
|
3487
3729
|
} = useGetCollectionLocations(collections, true);
|
|
3730
|
+
// Stabilize locationData to prevent infinite loops caused by new array references
|
|
3731
|
+
const locationDataRef = React.useRef();
|
|
3732
|
+
const locationData = useMemo(() => {
|
|
3733
|
+
if (isEqual(rawLocationData, locationDataRef.current)) {
|
|
3734
|
+
return locationDataRef.current;
|
|
3735
|
+
}
|
|
3736
|
+
locationDataRef.current = rawLocationData;
|
|
3737
|
+
return rawLocationData;
|
|
3738
|
+
}, [rawLocationData]);
|
|
3488
3739
|
/* Make sure the map pin is visible when linking new maps */
|
|
3489
3740
|
useEffect(() => {
|
|
3490
3741
|
const toggleMapPinVisibility = displayMapPin => {
|
|
@@ -3502,25 +3753,26 @@ const SoundingsConnect = ({
|
|
|
3502
3753
|
};
|
|
3503
3754
|
}, [dispatch, selectedMapIds]);
|
|
3504
3755
|
// construct and send geojson to map for drawing locations
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3756
|
+
const geoJsonForMap = useMemo(() => ({
|
|
3757
|
+
type: 'FeatureCollection',
|
|
3758
|
+
features: (locationData || []).flatMap(({
|
|
3759
|
+
id: serviceId,
|
|
3760
|
+
features
|
|
3761
|
+
}) => features.map(feature => ({
|
|
3762
|
+
type: 'Feature',
|
|
3763
|
+
geometry: feature.geometry,
|
|
3764
|
+
id: feature.id,
|
|
3765
|
+
properties: {
|
|
3766
|
+
name: feature.properties.name,
|
|
3767
|
+
mapFeatureClass: MapFeatureClass.ObservationStation,
|
|
3768
|
+
highlightSelectedFeature: selectedFeature?.id === feature.id,
|
|
3514
3769
|
id: feature.id,
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
}
|
|
3522
|
-
})))
|
|
3523
|
-
};
|
|
3770
|
+
serviceId,
|
|
3771
|
+
hidden: shouldHideLocationMarkers
|
|
3772
|
+
}
|
|
3773
|
+
})))
|
|
3774
|
+
}), [locationData, selectedFeature?.id, shouldHideLocationMarkers]);
|
|
3775
|
+
useEffect(() => {
|
|
3524
3776
|
dispatch(genericActions.addSharedData({
|
|
3525
3777
|
panelId: viewId,
|
|
3526
3778
|
data: {
|
|
@@ -3530,7 +3782,7 @@ const SoundingsConnect = ({
|
|
|
3530
3782
|
}]
|
|
3531
3783
|
}
|
|
3532
3784
|
}));
|
|
3533
|
-
}, [dispatch, geojsonLayerId,
|
|
3785
|
+
}, [dispatch, geojsonLayerId, geoJsonForMap, viewId]);
|
|
3534
3786
|
useEffect(() => () => {
|
|
3535
3787
|
if (viewId) {
|
|
3536
3788
|
dispatch(syncGroupsActions.deleteSharedData({
|
|
@@ -3541,26 +3793,133 @@ const SoundingsConnect = ({
|
|
|
3541
3793
|
// Map location selection has changed. Update soundings location
|
|
3542
3794
|
// since the location menu may be out of sync
|
|
3543
3795
|
useEffect(() => {
|
|
3796
|
+
if (presetJustLoadedRef.current) {
|
|
3797
|
+
return;
|
|
3798
|
+
}
|
|
3544
3799
|
const serviceId = selectedFeature?.serviceId;
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3800
|
+
const featureId = selectedFeature?.id;
|
|
3801
|
+
if (serviceId && featureId) {
|
|
3802
|
+
const currentLocation = locationSelectionsRef.current[serviceId];
|
|
3803
|
+
const initialLocation = initialLocationsRef.current[serviceId];
|
|
3804
|
+
if (currentLocation !== featureId && initialLocation !== featureId) {
|
|
3805
|
+
dispatch(soundingsActions.updateSelectedLocation({
|
|
3806
|
+
sourceId: serviceId,
|
|
3807
|
+
location: featureId,
|
|
3808
|
+
panelId: viewId,
|
|
3809
|
+
origin: SoundingsActionOrigin.soundingsComponent
|
|
3810
|
+
}));
|
|
3811
|
+
}
|
|
3550
3812
|
}
|
|
3551
|
-
}, [dispatch, selectedFeature?.id, selectedFeature?.serviceId]);
|
|
3552
|
-
//
|
|
3813
|
+
}, [dispatch, selectedFeature?.id, selectedFeature?.serviceId, viewId]);
|
|
3814
|
+
// Use ref to avoid circular dependency when reading locationSelections
|
|
3815
|
+
const locationSelectionsRef = React.useRef(locationSelections);
|
|
3816
|
+
React.useEffect(() => {
|
|
3817
|
+
locationSelectionsRef.current = locationSelections;
|
|
3818
|
+
}, [locationSelections]);
|
|
3819
|
+
// Makes position requests for all user-selected sources for the current map pin position.
|
|
3820
|
+
// Map pin change on its own implies a new position selection.
|
|
3553
3821
|
useEffect(() => {
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
if (
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3822
|
+
if (presetJustLoadedRef.current) {
|
|
3823
|
+
return;
|
|
3824
|
+
}
|
|
3825
|
+
if (!selectedFeature?.id && !selectedMapPin?.id && selectedMapPin?.lon && selectedMapPin.lat) {
|
|
3826
|
+
const newLocation = [selectedMapPin.lon, selectedMapPin.lat];
|
|
3827
|
+
// Update location for all selected sources
|
|
3828
|
+
sourceSelections.forEach(source => {
|
|
3829
|
+
if (source?.collectionId) {
|
|
3830
|
+
const currentLocation = locationSelectionsRef.current[source.collectionId];
|
|
3831
|
+
const isSameLocation = Array.isArray(currentLocation) && currentLocation[0] === newLocation[0] && currentLocation[1] === newLocation[1];
|
|
3832
|
+
if (!isSameLocation) {
|
|
3833
|
+
dispatch(soundingsActions.updateSelectedLocation({
|
|
3834
|
+
sourceId: source.collectionId,
|
|
3835
|
+
location: newLocation,
|
|
3836
|
+
panelId: viewId,
|
|
3837
|
+
origin: SoundingsActionOrigin.soundingsComponent
|
|
3838
|
+
}));
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
});
|
|
3842
|
+
}
|
|
3843
|
+
}, [selectedMapPin, selectedFeature?.id, sourceSelections, dispatch, viewId]);
|
|
3844
|
+
useEffect(() => {
|
|
3845
|
+
if (!locationData || locationData.length === 0) {
|
|
3846
|
+
return;
|
|
3847
|
+
}
|
|
3848
|
+
if (selectedMapIds.length === 0) {
|
|
3849
|
+
return;
|
|
3850
|
+
}
|
|
3851
|
+
let changedSourceId;
|
|
3852
|
+
for (const source of sourceSelections) {
|
|
3853
|
+
if (source?.collectionId) {
|
|
3854
|
+
const currentLocation = locationSelections[source.collectionId];
|
|
3855
|
+
const previousLocation = previousLocationsRef.current[source.collectionId];
|
|
3856
|
+
if (currentLocation !== previousLocation) {
|
|
3857
|
+
changedSourceId = source.collectionId;
|
|
3858
|
+
if (!presetJustLoadedRef.current) {
|
|
3859
|
+
break;
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3864
|
+
if (!changedSourceId) {
|
|
3865
|
+
return;
|
|
3866
|
+
}
|
|
3867
|
+
const selectedLocation = locationSelections[changedSourceId];
|
|
3868
|
+
if (!selectedLocation) {
|
|
3869
|
+
return;
|
|
3870
|
+
}
|
|
3871
|
+
previousLocationsRef.current = {
|
|
3872
|
+
...previousLocationsRef.current,
|
|
3873
|
+
[changedSourceId]: selectedLocation
|
|
3874
|
+
};
|
|
3875
|
+
const serviceData = locationData.find(service => service.id === changedSourceId);
|
|
3876
|
+
if (!serviceData) {
|
|
3877
|
+
return;
|
|
3878
|
+
}
|
|
3879
|
+
if (typeof selectedLocation === 'string') {
|
|
3880
|
+
const foundFeature = serviceData.features.find(feature => feature.id === selectedLocation);
|
|
3881
|
+
if (foundFeature?.geometry.type === 'Point') {
|
|
3882
|
+
const [lon, lat] = foundFeature.geometry.coordinates;
|
|
3883
|
+
const mapPinNeedsUpdate = selectedMapPin?.id !== selectedLocation || selectedMapPin?.lon !== lon || selectedMapPin?.lat !== lat;
|
|
3884
|
+
const featureNeedsUpdate = selectedFeature?.id !== selectedLocation;
|
|
3885
|
+
if (mapPinNeedsUpdate) {
|
|
3886
|
+
selectedMapIds.forEach(mapId => {
|
|
3887
|
+
dispatch(mapActions.setMapPinLocation({
|
|
3888
|
+
mapId,
|
|
3889
|
+
mapPinLocation: {
|
|
3890
|
+
lon,
|
|
3891
|
+
lat,
|
|
3892
|
+
id: selectedLocation
|
|
3893
|
+
}
|
|
3894
|
+
}));
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
if (featureNeedsUpdate) {
|
|
3898
|
+
dispatch(genericActions.addSharedData({
|
|
3899
|
+
panelId: viewId,
|
|
3900
|
+
data: {
|
|
3901
|
+
selectedFeatureId: selectedLocation
|
|
3902
|
+
}
|
|
3903
|
+
}));
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
} else if (Array.isArray(selectedLocation)) {
|
|
3907
|
+
const [lon, lat] = selectedLocation;
|
|
3908
|
+
const needsUpdate = selectedMapPin?.lon !== lon || selectedMapPin?.lat !== lat;
|
|
3909
|
+
if (needsUpdate) {
|
|
3910
|
+
selectedMapIds.forEach(mapId => {
|
|
3911
|
+
dispatch(mapActions.setMapPinLocation({
|
|
3912
|
+
mapId,
|
|
3913
|
+
mapPinLocation: {
|
|
3914
|
+
lon,
|
|
3915
|
+
lat
|
|
3916
|
+
}
|
|
3917
|
+
}));
|
|
3918
|
+
});
|
|
3919
|
+
}
|
|
3562
3920
|
}
|
|
3563
|
-
|
|
3921
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3922
|
+
}, [locationData, locationSelections, sourceSelections, selectedMapIds, dispatch, viewId]);
|
|
3564
3923
|
const {
|
|
3565
3924
|
error,
|
|
3566
3925
|
data,
|
|
@@ -3627,7 +3986,7 @@ const SoundingsConnect = ({
|
|
|
3627
3986
|
},
|
|
3628
3987
|
children: jsx(SharedMouseYProvider, {
|
|
3629
3988
|
children: jsx(SortableAccordions, {
|
|
3630
|
-
chosenDiagramType:
|
|
3989
|
+
chosenDiagramType: diagramType,
|
|
3631
3990
|
data: data,
|
|
3632
3991
|
onOrderChange: changeOrder,
|
|
3633
3992
|
setChosenDiagramType: setChosenDiagramType,
|
|
@@ -3642,7 +4001,9 @@ const SoundingsConnect = ({
|
|
|
3642
4001
|
flex: '0 0 auto',
|
|
3643
4002
|
height: `${TIMESLIDER_HEIGHT}px`
|
|
3644
4003
|
},
|
|
3645
|
-
children: jsx(SoundingsTimeSliderConnect, {
|
|
4004
|
+
children: jsx(SoundingsTimeSliderConnect, {
|
|
4005
|
+
viewId: viewId
|
|
4006
|
+
})
|
|
3646
4007
|
})]
|
|
3647
4008
|
})
|
|
3648
4009
|
})]
|
|
@@ -3718,6 +4079,7 @@ const SoundingsSourceMenu = ({
|
|
|
3718
4079
|
instanceId,
|
|
3719
4080
|
url
|
|
3720
4081
|
} = sourceSelections[collection.id] || {};
|
|
4082
|
+
const sourceUrl = url || collection.url;
|
|
3721
4083
|
const hasInstances = collection.instances.length > 0;
|
|
3722
4084
|
const selectedInstanceId = instanceId || collection.instances[0]?.id || undefined;
|
|
3723
4085
|
return jsxs(ListItem, {
|
|
@@ -3732,7 +4094,7 @@ const SoundingsSourceMenu = ({
|
|
|
3732
4094
|
onChange: event => {
|
|
3733
4095
|
const verticalRange = selectedInstanceId !== undefined ? extractVerticalRange(collection, selectedInstanceId) : '';
|
|
3734
4096
|
updateCollection(collection.id, {
|
|
3735
|
-
url,
|
|
4097
|
+
url: sourceUrl,
|
|
3736
4098
|
isChecked: event.target.checked,
|
|
3737
4099
|
instanceId: selectedInstanceId,
|
|
3738
4100
|
verticalRange
|
|
@@ -3748,7 +4110,7 @@ const SoundingsSourceMenu = ({
|
|
|
3748
4110
|
const instanceId = event.target.value;
|
|
3749
4111
|
const verticalRange = extractVerticalRange(collection, instanceId);
|
|
3750
4112
|
updateCollection(collection.id, {
|
|
3751
|
-
url,
|
|
4113
|
+
url: sourceUrl,
|
|
3752
4114
|
instanceId,
|
|
3753
4115
|
verticalRange
|
|
3754
4116
|
});
|
|
@@ -3811,30 +4173,39 @@ const SoundingsSourceDialogConnect = ({
|
|
|
3811
4173
|
dialogOrder,
|
|
3812
4174
|
setDialogOrder
|
|
3813
4175
|
} = useSetupDialog(uiTypes.DialogTypes.SoundingsSources);
|
|
4176
|
+
const panelId = useSelector(store => uiSelectors.getDialogMapId(store, uiTypes.DialogTypes.SoundingsSources));
|
|
3814
4177
|
const updateCollection = React.useCallback((sourceId, value) => {
|
|
3815
4178
|
dispatch(soundingsActions.updateSelectedSource({
|
|
3816
4179
|
sourceId,
|
|
3817
|
-
value
|
|
4180
|
+
value,
|
|
4181
|
+
panelId,
|
|
4182
|
+
origin: SoundingsActionOrigin.soundingsComponent
|
|
3818
4183
|
}));
|
|
3819
|
-
}, [dispatch]);
|
|
4184
|
+
}, [dispatch, panelId]);
|
|
3820
4185
|
const sourceSelections = useSelector(getSourceSelections);
|
|
3821
4186
|
// Set mappings for each collection
|
|
3822
4187
|
React.useEffect(() => {
|
|
3823
4188
|
soundingsCollections?.forEach(collection => {
|
|
4189
|
+
const currentSelection = sourceSelections[collection.id];
|
|
4190
|
+
if (currentSelection?.url && currentSelection?.parameterMappings) {
|
|
4191
|
+
return;
|
|
4192
|
+
}
|
|
4193
|
+
const newValue = {
|
|
4194
|
+
url: collection.url,
|
|
4195
|
+
isChecked: currentSelection?.isChecked || false,
|
|
4196
|
+
parameterMappings: collection.parameterMappings,
|
|
4197
|
+
...(collection.name && collection.name !== '' ? {
|
|
4198
|
+
name: collection.name
|
|
4199
|
+
} : {})
|
|
4200
|
+
};
|
|
3824
4201
|
dispatch(soundingsActions.updateSelectedSource({
|
|
3825
4202
|
sourceId: collection.id,
|
|
3826
|
-
value:
|
|
3827
|
-
|
|
3828
|
-
isChecked: sourceSelections[collection.id]?.isChecked || false,
|
|
3829
|
-
parameterMappings: collection.parameterMappings,
|
|
3830
|
-
...(collection.name && collection.name !== '' ? {
|
|
3831
|
-
name: collection.name
|
|
3832
|
-
} : {})
|
|
3833
|
-
}
|
|
4203
|
+
value: newValue,
|
|
4204
|
+
origin: SoundingsActionOrigin.soundingsManager
|
|
3834
4205
|
}));
|
|
3835
4206
|
});
|
|
3836
4207
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3837
|
-
}, [dispatch, soundingsCollections]);
|
|
4208
|
+
}, [dispatch, soundingsCollections, panelId]);
|
|
3838
4209
|
const {
|
|
3839
4210
|
data,
|
|
3840
4211
|
isPending,
|
|
@@ -4004,8 +4375,6 @@ const LocationsMenuConnect = ({
|
|
|
4004
4375
|
const locationSelections = useSelector(getLocationSelections);
|
|
4005
4376
|
const selectedSourceIds = useSelector(getSelectedSourcesIds);
|
|
4006
4377
|
const sourcesAmount = useSelector(getSelectedSourcesAmount);
|
|
4007
|
-
const panelId = useSelector(store => uiSelectors.getDialogMapId(store, uiTypes.DialogTypes.SoundingsLocations));
|
|
4008
|
-
const selectedMapIds = useSelector(state => genericSelectors.getLinkedMaps(state, panelId));
|
|
4009
4378
|
const {
|
|
4010
4379
|
data,
|
|
4011
4380
|
isPending,
|
|
@@ -4014,22 +4383,6 @@ const LocationsMenuConnect = ({
|
|
|
4014
4383
|
const services = useMemo(() => {
|
|
4015
4384
|
return data?.filter(service => selectedSourceIds.includes(service.id)) || [];
|
|
4016
4385
|
}, [data, selectedSourceIds]);
|
|
4017
|
-
const handleFeatureSelect = (panelId, featureId) => {
|
|
4018
|
-
dispatch(genericActions.addSharedData({
|
|
4019
|
-
panelId,
|
|
4020
|
-
data: {
|
|
4021
|
-
selectedFeatureId: featureId
|
|
4022
|
-
}
|
|
4023
|
-
}));
|
|
4024
|
-
};
|
|
4025
|
-
const setMapPinLocation = mapPinLocation => {
|
|
4026
|
-
selectedMapIds.forEach(mapId => {
|
|
4027
|
-
dispatch(mapActions.setMapPinLocation({
|
|
4028
|
-
mapId,
|
|
4029
|
-
mapPinLocation
|
|
4030
|
-
}));
|
|
4031
|
-
});
|
|
4032
|
-
};
|
|
4033
4386
|
return jsx(LocationsMenu, {
|
|
4034
4387
|
error: error,
|
|
4035
4388
|
isLoading: isPending,
|
|
@@ -4045,25 +4398,6 @@ const LocationsMenuConnect = ({
|
|
|
4045
4398
|
sourceId,
|
|
4046
4399
|
location: locationId
|
|
4047
4400
|
}));
|
|
4048
|
-
// Use first source. Multiple sources will be implemented later.
|
|
4049
|
-
// https://gitlab.com/opengeoweb/geoweb-assets/-/issues/4254
|
|
4050
|
-
const isFirstSource = sourceId === selectedSourceIds[0];
|
|
4051
|
-
if (!isFirstSource) {
|
|
4052
|
-
return;
|
|
4053
|
-
}
|
|
4054
|
-
if (locationId) {
|
|
4055
|
-
handleFeatureSelect(panelId, locationId);
|
|
4056
|
-
}
|
|
4057
|
-
const foundFeature = services[0].features.find(feature => feature.id === locationId);
|
|
4058
|
-
// check type for typescript
|
|
4059
|
-
if (foundFeature?.geometry.type === 'Point') {
|
|
4060
|
-
const [lon, lat] = foundFeature.geometry.coordinates;
|
|
4061
|
-
setMapPinLocation({
|
|
4062
|
-
lon,
|
|
4063
|
-
lat,
|
|
4064
|
-
id: locationId
|
|
4065
|
-
});
|
|
4066
|
-
}
|
|
4067
4401
|
}
|
|
4068
4402
|
});
|
|
4069
4403
|
};
|
|
@@ -4211,7 +4545,7 @@ const SoundingsManagerConnect = () => {
|
|
|
4211
4545
|
const soundingsLookUp = payload => {
|
|
4212
4546
|
if (payload.componentType === 'Soundings') {
|
|
4213
4547
|
return jsx(SoundingsConnect, {
|
|
4214
|
-
|
|
4548
|
+
soundingsPreset: payload.initialProps,
|
|
4215
4549
|
viewId: payload.id
|
|
4216
4550
|
});
|
|
4217
4551
|
}
|
|
@@ -4246,4 +4580,4 @@ const createMockStore = mockState => configureStore({
|
|
|
4246
4580
|
middleware: getDefaultMiddleware => getDefaultMiddleware().concat(storeMiddlewares)
|
|
4247
4581
|
});
|
|
4248
4582
|
|
|
4249
|
-
export { LocationsMenuConnect, SOUNDINGS_NAMESPACE, SoundingsConnect, SoundingsManagerConnect, SoundingsSourceDialogConnect, createMockStore, initSoundingsI18n, soundingDiagrams, soundingsLookUp, soundingsReducersMap, soundingsTranslations, translateInTestsAndStories, useSoundingsTranslation };
|
|
4583
|
+
export { LocationsMenuConnect, SOUNDINGS_NAMESPACE, SoundingsActionOrigin, SoundingsConnect, SoundingsManagerConnect, SoundingsSourceDialogConnect, types as SoundingsTypes, createMockStore, initSoundingsI18n, soundingDiagrams, soundingsActions, soundingsLookUp, soundingsReducer, soundingsReducersMap, selectors as soundingsSelectors, soundingsTranslations, translateInTestsAndStories, useSoundingsTranslation };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/soundings",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.1.0",
|
|
4
4
|
"description": "GeoWeb soundings library for the opengeoweb project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
"url": "git@gitlab.com:opengeoweb/opengeoweb.git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@opengeoweb/api": "15.
|
|
11
|
+
"@opengeoweb/api": "15.1.0",
|
|
12
12
|
"@tanstack/react-query": "^5.85.5",
|
|
13
13
|
"react": "^18.3.1",
|
|
14
14
|
"d3": "^7.9.0",
|
|
15
15
|
"react-i18next": "^15.1.1",
|
|
16
16
|
"i18next": "^25.0.1",
|
|
17
|
-
"@opengeoweb/shared": "15.
|
|
17
|
+
"@opengeoweb/shared": "15.1.0",
|
|
18
18
|
"@mui/material": "^7.0.1",
|
|
19
|
-
"@opengeoweb/store": "15.
|
|
19
|
+
"@opengeoweb/store": "15.1.0",
|
|
20
20
|
"react-redux": "^9.2.0",
|
|
21
|
-
"@opengeoweb/theme": "15.
|
|
21
|
+
"@opengeoweb/theme": "15.1.0",
|
|
22
22
|
"@reduxjs/toolkit": "^2.6.1",
|
|
23
|
-
"@opengeoweb/time-slider": "15.
|
|
23
|
+
"@opengeoweb/time-slider": "15.1.0",
|
|
24
24
|
"react-window": "^1.8.10",
|
|
25
|
-
"@opengeoweb/webmap": "15.
|
|
25
|
+
"@opengeoweb/webmap": "15.1.0",
|
|
26
26
|
"lodash": "^4.17.21",
|
|
27
27
|
"@types/geojson": "^7946.0.14",
|
|
28
|
-
"@opengeoweb/webmap-react": "15.
|
|
28
|
+
"@opengeoweb/webmap-react": "15.1.0",
|
|
29
29
|
"react-resizable-layout": "^0.7.3",
|
|
30
30
|
"react-sortablejs": "^6.1.4"
|
|
31
31
|
},
|
package/src/index.d.ts
CHANGED
|
@@ -5,3 +5,5 @@ export * from './lib/utils/soundingsLookUp';
|
|
|
5
5
|
export * from './lib/api/edr-api/types';
|
|
6
6
|
export * from './lib/store/store';
|
|
7
7
|
export * from './lib/utils/i18n';
|
|
8
|
+
export * as SoundingsTypes from './lib/store/types';
|
|
9
|
+
export { SoundingsActionOrigin } from './lib/store/types';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { SoundingsCollection } from '@opengeoweb/shared';
|
|
1
|
+
import type { Coordinates, SoundingsCollection } from '@opengeoweb/shared';
|
|
2
2
|
import type { SoundingFeature } from './types';
|
|
3
3
|
import type { ServiceWithLocations } from '../../components/MenuBar/LocationsMenu';
|
|
4
4
|
import type { SoundingsCollectionsWithInstances } from '../../components/Soundings/types';
|
|
5
|
-
import type {
|
|
5
|
+
import type { SourceType } from '../../store/types';
|
|
6
6
|
export declare const sortSoundingFeatures: (data: SoundingFeature[]) => SoundingFeature[];
|
|
7
7
|
export declare const defaultParameterMappings: {
|
|
8
8
|
temperature: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { Coordinates } from '@opengeoweb/shared';
|
|
1
2
|
import type { LocationsResponseFromBE } from '../../api/edr-api/types';
|
|
2
|
-
import type { Coordinates } from '../../store/types';
|
|
3
3
|
export type ServiceWithLocations = LocationsResponseFromBE & {
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
|
@@ -8,6 +8,8 @@ interface SoundingsMenuBarProps {
|
|
|
8
8
|
handleClick: (menuType: MenuOptions) => void;
|
|
9
9
|
isOpen: Record<MenuOptions, boolean>;
|
|
10
10
|
selectedSourcesAmount?: number;
|
|
11
|
+
shouldHideMarkers: boolean;
|
|
12
|
+
toggleMarkers: (shouldHideMarkers: boolean) => void;
|
|
11
13
|
}
|
|
12
|
-
export declare const SoundingsMenuBar: ({ handleClick, isOpen, selectedSourcesAmount, }: SoundingsMenuBarProps) => React.ReactElement;
|
|
14
|
+
export declare const SoundingsMenuBar: ({ handleClick, isOpen, selectedSourcesAmount, shouldHideMarkers, toggleMarkers, }: SoundingsMenuBarProps) => React.ReactElement;
|
|
13
15
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { SourceSelection } from '
|
|
2
|
+
import type { SourceSelection } from '@opengeoweb/shared';
|
|
3
3
|
import type { SoundingsCollectionsWithInstances } from '../Soundings/types';
|
|
4
4
|
interface SoundingsSourceMenuProps {
|
|
5
5
|
soundingsCollections: SoundingsCollectionsWithInstances[] | undefined;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SoundingsStore } from '../../store/types';
|
|
3
3
|
interface SoundingsConnectProps {
|
|
4
4
|
viewId: string;
|
|
5
|
-
|
|
5
|
+
soundingsPreset?: SoundingsStore;
|
|
6
6
|
}
|
|
7
|
-
export declare const SoundingsConnect: ({ viewId,
|
|
7
|
+
export declare const SoundingsConnect: ({ viewId, soundingsPreset, }: SoundingsConnectProps) => React.ReactElement;
|
|
8
8
|
export {};
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
interface SoundingsTimeSliderConnectProps {
|
|
3
|
+
viewId: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const SoundingsTimeSliderConnect: ({ viewId, }: SoundingsTimeSliderConnectProps) => React.ReactElement;
|
|
6
|
+
export {};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { Draft, PayloadAction } from '@reduxjs/toolkit';
|
|
2
|
-
import type { SoundingPanels, SoundingsStore, UpdateLocationPayload, UpdateSourcePayload, UpdateTimePayload } from './types';
|
|
2
|
+
import type { SoundingPanels, SoundingsStore, UpdateLocationPayload, UpdateSourcePayload, UpdateTimePayload, UpdateDiagramTypePayload, ToggleLocationMarkersPayload } from './types';
|
|
3
3
|
export declare const initialSoundingsState: SoundingsStore;
|
|
4
4
|
export declare const soundingsReducer: import("redux").Reducer<SoundingsStore>, soundingsActions: import("@reduxjs/toolkit").CaseReducerActions<{
|
|
5
|
+
registerSoundingsPreset: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<SoundingsStore>) => void;
|
|
5
6
|
updateSelectedSource: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<UpdateSourcePayload>) => void;
|
|
6
7
|
updateSelectedLocation: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<UpdateLocationPayload>) => void;
|
|
7
8
|
updateSelectedTime: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<UpdateTimePayload>) => void;
|
|
9
|
+
updateDiagramType: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<UpdateDiagramTypePayload>) => void;
|
|
10
|
+
toggleLocationMarkers: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<ToggleLocationMarkersPayload>) => void;
|
|
8
11
|
addSoundingPanelsFromPreset: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<SoundingPanels>) => void;
|
|
9
12
|
changeSoundingPanelOrder: (draft: Draft<SoundingsStore>, payloadAction: PayloadAction<{
|
|
10
13
|
newOrderOfIds: string[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SourceSelection } from '@opengeoweb/shared';
|
|
2
|
+
import type { SoundingsModuleState, SoundingsStore, SourceType } from './types';
|
|
2
3
|
export declare const getSourceSelections: ((state: SoundingsModuleState) => Record<string, SourceSelection>) & {
|
|
3
4
|
clearCache: () => void;
|
|
4
5
|
resultsCount: () => number;
|
|
@@ -20,18 +21,18 @@ export declare const getSourceSelections: ((state: SoundingsModuleState) => Reco
|
|
|
20
21
|
memoize: typeof import("reselect").weakMapMemoize;
|
|
21
22
|
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
22
23
|
};
|
|
23
|
-
export declare const getLocationSelections: ((state: SoundingsModuleState) => Record<string, string | import("
|
|
24
|
+
export declare const getLocationSelections: ((state: SoundingsModuleState) => Record<string, string | import("@opengeoweb/shared").Coordinates | undefined>) & {
|
|
24
25
|
clearCache: () => void;
|
|
25
26
|
resultsCount: () => number;
|
|
26
27
|
resetResultsCount: () => void;
|
|
27
28
|
} & {
|
|
28
|
-
resultFunc: (resultFuncArgs_0: SoundingsStore) => Record<string, string | import("
|
|
29
|
-
memoizedResultFunc: ((resultFuncArgs_0: SoundingsStore) => Record<string, string | import("
|
|
29
|
+
resultFunc: (resultFuncArgs_0: SoundingsStore) => Record<string, string | import("@opengeoweb/shared").Coordinates | undefined>;
|
|
30
|
+
memoizedResultFunc: ((resultFuncArgs_0: SoundingsStore) => Record<string, string | import("@opengeoweb/shared").Coordinates | undefined>) & {
|
|
30
31
|
clearCache: () => void;
|
|
31
32
|
resultsCount: () => number;
|
|
32
33
|
resetResultsCount: () => void;
|
|
33
34
|
};
|
|
34
|
-
lastResult: () => Record<string, string | import("
|
|
35
|
+
lastResult: () => Record<string, string | import("@opengeoweb/shared").Coordinates | undefined>;
|
|
35
36
|
dependencies: [(store: SoundingsModuleState) => SoundingsStore];
|
|
36
37
|
recomputations: () => number;
|
|
37
38
|
resetRecomputations: () => void;
|
|
@@ -62,6 +63,48 @@ export declare const getSelectedTime: ((state: SoundingsModuleState) => string)
|
|
|
62
63
|
memoize: typeof import("reselect").weakMapMemoize;
|
|
63
64
|
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
64
65
|
};
|
|
66
|
+
export declare const getDiagramType: ((state: SoundingsModuleState) => "SKEWT" | "BIJVOET" | "EMAGRAM") & {
|
|
67
|
+
clearCache: () => void;
|
|
68
|
+
resultsCount: () => number;
|
|
69
|
+
resetResultsCount: () => void;
|
|
70
|
+
} & {
|
|
71
|
+
resultFunc: (resultFuncArgs_0: SoundingsStore) => "SKEWT" | "BIJVOET" | "EMAGRAM";
|
|
72
|
+
memoizedResultFunc: ((resultFuncArgs_0: SoundingsStore) => "SKEWT" | "BIJVOET" | "EMAGRAM") & {
|
|
73
|
+
clearCache: () => void;
|
|
74
|
+
resultsCount: () => number;
|
|
75
|
+
resetResultsCount: () => void;
|
|
76
|
+
};
|
|
77
|
+
lastResult: () => "SKEWT" | "BIJVOET" | "EMAGRAM";
|
|
78
|
+
dependencies: [(store: SoundingsModuleState) => SoundingsStore];
|
|
79
|
+
recomputations: () => number;
|
|
80
|
+
resetRecomputations: () => void;
|
|
81
|
+
dependencyRecomputations: () => number;
|
|
82
|
+
resetDependencyRecomputations: () => void;
|
|
83
|
+
} & {
|
|
84
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
85
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
86
|
+
};
|
|
87
|
+
export declare const getShouldHideLocationMarkers: ((state: SoundingsModuleState) => boolean) & {
|
|
88
|
+
clearCache: () => void;
|
|
89
|
+
resultsCount: () => number;
|
|
90
|
+
resetResultsCount: () => void;
|
|
91
|
+
} & {
|
|
92
|
+
resultFunc: (resultFuncArgs_0: SoundingsStore) => boolean;
|
|
93
|
+
memoizedResultFunc: ((resultFuncArgs_0: SoundingsStore) => boolean) & {
|
|
94
|
+
clearCache: () => void;
|
|
95
|
+
resultsCount: () => number;
|
|
96
|
+
resetResultsCount: () => void;
|
|
97
|
+
};
|
|
98
|
+
lastResult: () => boolean;
|
|
99
|
+
dependencies: [(store: SoundingsModuleState) => SoundingsStore];
|
|
100
|
+
recomputations: () => number;
|
|
101
|
+
resetRecomputations: () => void;
|
|
102
|
+
dependencyRecomputations: () => number;
|
|
103
|
+
resetDependencyRecomputations: () => void;
|
|
104
|
+
} & {
|
|
105
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
106
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
107
|
+
};
|
|
65
108
|
export declare const getSelectedSources: ((state: SoundingsModuleState) => SourceType[]) & {
|
|
66
109
|
clearCache: () => void;
|
|
67
110
|
resultsCount: () => number;
|
|
@@ -165,6 +208,27 @@ export declare const getSelectedSourcesIds: ((state: SoundingsModuleState) => st
|
|
|
165
208
|
memoize: typeof import("reselect").weakMapMemoize;
|
|
166
209
|
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
167
210
|
};
|
|
211
|
+
export declare const getSoundingsPreset: ((state: SoundingsModuleState) => SoundingsStore) & {
|
|
212
|
+
clearCache: () => void;
|
|
213
|
+
resultsCount: () => number;
|
|
214
|
+
resetResultsCount: () => void;
|
|
215
|
+
} & {
|
|
216
|
+
resultFunc: (resultFuncArgs_0: SoundingsStore) => SoundingsStore;
|
|
217
|
+
memoizedResultFunc: ((resultFuncArgs_0: SoundingsStore) => SoundingsStore) & {
|
|
218
|
+
clearCache: () => void;
|
|
219
|
+
resultsCount: () => number;
|
|
220
|
+
resetResultsCount: () => void;
|
|
221
|
+
};
|
|
222
|
+
lastResult: () => SoundingsStore;
|
|
223
|
+
dependencies: [(store: SoundingsModuleState) => SoundingsStore];
|
|
224
|
+
recomputations: () => number;
|
|
225
|
+
resetRecomputations: () => void;
|
|
226
|
+
dependencyRecomputations: () => number;
|
|
227
|
+
resetDependencyRecomputations: () => void;
|
|
228
|
+
} & {
|
|
229
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
230
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
231
|
+
};
|
|
168
232
|
export declare const getSoundingPanelsInOrder: ((state: SoundingsModuleState) => import("./types").SoundingPanel[]) & {
|
|
169
233
|
clearCache: () => void;
|
|
170
234
|
resultsCount: () => number;
|
package/src/lib/store/store.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Store } from '@reduxjs/toolkit';
|
|
2
2
|
import type { UIModuleState, WebMapStateModuleState } from '@opengeoweb/store';
|
|
3
3
|
import type { SoundingsModuleState } from './types';
|
|
4
|
+
export * as soundingsSelectors from './selectors';
|
|
5
|
+
export { soundingsReducer, soundingsActions } from './reducer';
|
|
6
|
+
export type { SoundingsModuleState, SoundingsStore } from './types';
|
|
4
7
|
export declare const soundingsReducersMap: {
|
|
5
8
|
webmap: import("redux").Reducer<import("dist/libs/store/src/store/map/types").WebMapState>;
|
|
6
9
|
services: import("redux").Reducer<import("dist/libs/store/src/store/map/types").ServiceState>;
|
package/src/lib/store/types.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import type { Coordinates, SourceSelection } from '@opengeoweb/shared';
|
|
2
|
+
export declare enum SoundingsActionOrigin {
|
|
3
|
+
soundingsManager = "soundingsManager",
|
|
4
|
+
soundingsComponent = "soundingsComponent"
|
|
5
|
+
}
|
|
1
6
|
export interface SourceType {
|
|
2
7
|
collectionId: string;
|
|
3
8
|
url: string;
|
|
@@ -6,27 +11,27 @@ export interface SourceType {
|
|
|
6
11
|
parameterMappings?: Record<string, string>;
|
|
7
12
|
name?: string;
|
|
8
13
|
}
|
|
9
|
-
export interface
|
|
14
|
+
export interface SoundingsPayload {
|
|
15
|
+
panelId?: string;
|
|
16
|
+
origin?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface UpdateSourcePayload extends SoundingsPayload {
|
|
10
19
|
sourceId: string;
|
|
11
20
|
value: SourceSelection;
|
|
12
21
|
}
|
|
13
|
-
export interface
|
|
14
|
-
url: string;
|
|
15
|
-
instanceId?: string;
|
|
16
|
-
isChecked?: boolean;
|
|
17
|
-
verticalRange?: string;
|
|
18
|
-
parameterMappings?: Record<string, string>;
|
|
19
|
-
name?: string;
|
|
20
|
-
}
|
|
21
|
-
export interface UpdateLocationPayload {
|
|
22
|
+
export interface UpdateLocationPayload extends SoundingsPayload {
|
|
22
23
|
sourceId: string;
|
|
23
24
|
location: string | Coordinates | undefined;
|
|
24
25
|
}
|
|
25
|
-
export interface UpdateTimePayload {
|
|
26
|
+
export interface UpdateTimePayload extends SoundingsPayload {
|
|
26
27
|
selectedTime: string;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
export interface UpdateDiagramTypePayload extends SoundingsPayload {
|
|
30
|
+
diagramType: 'SKEWT' | 'BIJVOET' | 'EMAGRAM';
|
|
31
|
+
}
|
|
32
|
+
export interface ToggleLocationMarkersPayload extends SoundingsPayload {
|
|
33
|
+
shouldHideLocationMarkers: boolean;
|
|
34
|
+
}
|
|
30
35
|
export interface SoundingPanel {
|
|
31
36
|
id: string;
|
|
32
37
|
name: string;
|
|
@@ -42,9 +47,13 @@ export interface SoundingsStore {
|
|
|
42
47
|
/** key: sourceId, value: locationId or position coordinates */
|
|
43
48
|
selectedLocations: Record<string, string | Coordinates | undefined>;
|
|
44
49
|
/** ISO date, e.g., 2025-01-02T12:00:00.000Z */
|
|
45
|
-
selectedTime
|
|
50
|
+
selectedTime?: string;
|
|
51
|
+
/** Diagram type: SKEWT, BIJVOET, or EMAGRAM */
|
|
52
|
+
diagramType?: 'SKEWT' | 'BIJVOET' | 'EMAGRAM';
|
|
46
53
|
soundingPanels: SoundingPanels;
|
|
54
|
+
/** Whether to hide location markers on the map */
|
|
55
|
+
shouldHideLocationMarkers?: boolean;
|
|
47
56
|
}
|
|
48
57
|
export interface SoundingsModuleState {
|
|
49
|
-
soundings
|
|
58
|
+
soundings?: SoundingsStore;
|
|
50
59
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SoundingsStore } from '../store/types';
|
|
2
2
|
export type SoundingsComponentType = 'Soundings';
|
|
3
3
|
export interface SoundingsLookUpPayload {
|
|
4
4
|
componentType: SoundingsComponentType;
|
|
5
5
|
id: string;
|
|
6
6
|
title?: string;
|
|
7
|
-
|
|
8
|
-
initialProps: Record<string, unknown>;
|
|
7
|
+
initialProps: SoundingsStore;
|
|
9
8
|
}
|
|
10
9
|
export declare const soundingsLookUp: (payload: SoundingsLookUpPayload) => React.JSX.Element | null;
|