@opengeoweb/soundings 12.12.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.esm.js +184 -27
- package/package.json +10 -9
- package/src/lib/api/edr-api/api.d.ts +2 -1
- package/src/lib/api/edr-api/fakeApi.d.ts +15 -0
- package/src/lib/api/edr-api/hooks.d.ts +5 -1
- package/src/lib/api/edr-api/types.d.ts +4 -1
- package/src/lib/api/edr-api/utils.d.ts +2 -2
- package/src/lib/components/Soundings/constants.d.ts +1 -0
package/index.esm.js
CHANGED
|
@@ -3,17 +3,18 @@ import React, { useRef, useEffect, useMemo, useState, Fragment as Fragment$1 } f
|
|
|
3
3
|
import { useSelector, useDispatch } from 'react-redux';
|
|
4
4
|
import { Box, Stack, Menu, ListSubheader, Typography, MenuItem, Tooltip, LinearProgress, Card, List, ListItem, ListItemIcon, Checkbox, ListItemText, Grid, ListItemButton } from '@mui/material';
|
|
5
5
|
import { safelyInitI18nForTestsAndStories, sharedTranslations, SHARED_NAMESPACE, dateUtils, CustomSlider, CustomToggleButton, AlertBanner, ToolContainerDraggable, StyledSelect, SearchField, CustomAccordion } from '@opengeoweb/shared';
|
|
6
|
+
import { selectorMemoizationOptions, uiSelectors, uiTypes, uiActions, genericActions, useSetupDialog, storeReducerMap, storeMiddlewares } from '@opengeoweb/store';
|
|
7
|
+
import { ParseISOTimeRangeDuration, parseISO8601IntervalToDateInterval, webmapUtils } from '@opengeoweb/webmap';
|
|
8
|
+
import { MapFeatureClass } from '@opengeoweb/webmap-react';
|
|
6
9
|
import * as d3 from 'd3';
|
|
7
10
|
import { useQueries } from '@tanstack/react-query';
|
|
8
11
|
import { getHeaders, handleResponse } from '@opengeoweb/api';
|
|
9
|
-
import { ParseISOTimeRangeDuration, parseISO8601IntervalToDateInterval } from '@opengeoweb/webmap';
|
|
10
12
|
import { range, minBy } from 'lodash';
|
|
11
|
-
import { timesliderTranslations,
|
|
13
|
+
import { timesliderTranslations, TIME_SLIDER_NAMESPACE, BackwardForwardStepButton } from '@opengeoweb/time-slider';
|
|
12
14
|
import i18n from 'i18next';
|
|
13
15
|
export { default as i18n } from 'i18next';
|
|
14
16
|
import { useTranslation } from 'react-i18next';
|
|
15
17
|
import { createSlice, createSelector, combineReducers, configureStore } from '@reduxjs/toolkit';
|
|
16
|
-
import { selectorMemoizationOptions, uiSelectors, uiTypes, uiActions, useSetupDialog, storeReducerMap, storeMiddlewares } from '@opengeoweb/store';
|
|
17
18
|
import { Sources } from '@opengeoweb/theme';
|
|
18
19
|
import { FixedSizeList } from 'react-window';
|
|
19
20
|
|
|
@@ -89,11 +90,12 @@ var soundingsTranslations = {
|
|
|
89
90
|
* Copyright 2025 - Finnish Meteorological Institute (FMI)
|
|
90
91
|
* Copyright 2025 - The Norwegian Meteorological Institute (MET Norway)
|
|
91
92
|
* */
|
|
92
|
-
// Define pressure and temperature values for static lines
|
|
93
|
+
// Define pressure [hPa] and temperature [°C] values for static lines
|
|
93
94
|
const maxPressure = 1050;
|
|
94
95
|
const minPressure = 150;
|
|
95
96
|
const staticPressureArray = [maxPressure];
|
|
96
97
|
const dp = -5;
|
|
98
|
+
const minEmagramTemperature = -80;
|
|
97
99
|
const minTemperature = -40;
|
|
98
100
|
const maxTemperature = 40.6;
|
|
99
101
|
let pressure = maxPressure;
|
|
@@ -298,17 +300,64 @@ const drawAxes = ({
|
|
|
298
300
|
if (diagramType !== 'BIJVOET') {
|
|
299
301
|
// Create x-axis with intervals
|
|
300
302
|
const xTicks = xScale.ticks(10);
|
|
301
|
-
const
|
|
303
|
+
const xNegativeDisplacement = () => {
|
|
304
|
+
if (diagramType === 'SKEWT') {
|
|
305
|
+
return '-0.25em';
|
|
306
|
+
}
|
|
307
|
+
if (diagramType === 'EMAGRAM') {
|
|
308
|
+
return '-.5em';
|
|
309
|
+
}
|
|
310
|
+
return '0em';
|
|
311
|
+
};
|
|
312
|
+
const xPositiveDisplacement = () => {
|
|
313
|
+
if (diagramType === 'SKEWT') {
|
|
314
|
+
return '-0.2em';
|
|
315
|
+
}
|
|
316
|
+
if (diagramType === 'EMAGRAM') {
|
|
317
|
+
return '0.0em';
|
|
318
|
+
}
|
|
319
|
+
return '0em';
|
|
320
|
+
};
|
|
321
|
+
const xStringToSignedNumber = xString => {
|
|
322
|
+
const str = xString.replace(/[^\d.-]/g, '');
|
|
323
|
+
const xStringHasSomeLeadingCharacters = xString.length > str.length;
|
|
324
|
+
const xValue = xStringHasSomeLeadingCharacters ? -parseInt(str, 10) : parseInt(xString, 10);
|
|
325
|
+
return xValue;
|
|
326
|
+
};
|
|
302
327
|
svg.append('g').attr('type', 'x-axis').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickValues(xTicks).tickSizeInner(0).tickSizeOuter(0));
|
|
303
|
-
// Reformat in the case of the
|
|
328
|
+
// Reformat in the case of the zero tick label
|
|
304
329
|
// to add the unit part
|
|
305
|
-
svg.selectAll('g[type="x-axis"] .tick').filter(function
|
|
306
|
-
|
|
330
|
+
svg.selectAll('g[type="x-axis"] .tick').filter(function isZero() {
|
|
331
|
+
const xString = d3.select(this).select('text').text();
|
|
332
|
+
const xValue = xStringToSignedNumber(xString);
|
|
333
|
+
return xValue === 0; // Always true for SkewT and Emagram as they have a 0°C crossing
|
|
307
334
|
}).each(function txt() {
|
|
308
335
|
const unitPart = '°C';
|
|
309
336
|
d3.select(this).select('text')
|
|
310
337
|
// tspan necessary to use a different font-size
|
|
311
|
-
.append('tspan').text(unitPart).attr('font-size', '11px').attr('dy', '0.04em');
|
|
338
|
+
.append('tspan').text(unitPart).attr('font-size', '11px').attr('dy', '0.04em').attr('dx', '0.0em');
|
|
339
|
+
});
|
|
340
|
+
svg.selectAll('g[type="x-axis"] .tick').filter(function isLessThanZero() {
|
|
341
|
+
const xString = d3.select(this).select('text').text();
|
|
342
|
+
const xValue = xStringToSignedNumber(xString);
|
|
343
|
+
return xValue < 0;
|
|
344
|
+
}).each(function txt() {
|
|
345
|
+
d3.select(this).select('text').attr('dx', xNegativeDisplacement());
|
|
346
|
+
});
|
|
347
|
+
svg.selectAll('g[type="x-axis"] .tick').filter(function isGreaterThanZero() {
|
|
348
|
+
const xString = d3.select(this).select('text').text();
|
|
349
|
+
const xValue = xStringToSignedNumber(xString);
|
|
350
|
+
return xValue > 0;
|
|
351
|
+
}).each(function txt() {
|
|
352
|
+
d3.select(this).select('text').attr('dx', xPositiveDisplacement());
|
|
353
|
+
});
|
|
354
|
+
const xMiddleValue = xTicks[xTicks.length - 1];
|
|
355
|
+
svg.selectAll('g[type="x-axis"] .tick').filter(function isLast() {
|
|
356
|
+
const xString = d3.select(this).select('text').text();
|
|
357
|
+
const xValue = xStringToSignedNumber(xString);
|
|
358
|
+
return xValue === xMiddleValue;
|
|
359
|
+
}).each(function txt() {
|
|
360
|
+
d3.select(this).select('text').attr('dx', xNegativeDisplacement());
|
|
312
361
|
});
|
|
313
362
|
}
|
|
314
363
|
// Create y-axis with intervals
|
|
@@ -965,7 +1014,8 @@ const drawDryAdiabats = ({
|
|
|
965
1014
|
dp,
|
|
966
1015
|
diagramType
|
|
967
1016
|
}) => {
|
|
968
|
-
|
|
1017
|
+
const minT = diagramType === 'EMAGRAM' ? minEmagramTemperature : minTemperature;
|
|
1018
|
+
for (let Tbase = minT; Tbase < 240; Tbase += 10) {
|
|
969
1019
|
let Pnew = staticPressureArray[0];
|
|
970
1020
|
let Tnew = Tbase;
|
|
971
1021
|
const Px = [];
|
|
@@ -1453,8 +1503,10 @@ const Soundings = ({
|
|
|
1453
1503
|
diagramType
|
|
1454
1504
|
});
|
|
1455
1505
|
const svgRectangle = svgRef.current.getBoundingClientRect();
|
|
1506
|
+
const minT = diagramType === 'EMAGRAM' ? minEmagramTemperature : minTemperature;
|
|
1507
|
+
const maxT = maxTemperature;
|
|
1456
1508
|
// Set scales for temperature and pressure
|
|
1457
|
-
const [xScale, yScale] = createScales(diagramType, width, height, minPressure, maxPressure,
|
|
1509
|
+
const [xScale, yScale] = createScales(diagramType, width, height, minPressure, maxPressure, minT, maxT);
|
|
1458
1510
|
// Add axis'
|
|
1459
1511
|
drawAxes({
|
|
1460
1512
|
svg,
|
|
@@ -1468,8 +1520,8 @@ const Soundings = ({
|
|
|
1468
1520
|
diagramType,
|
|
1469
1521
|
dp,
|
|
1470
1522
|
staticPressureArray,
|
|
1471
|
-
minTemperature,
|
|
1472
|
-
maxTemperature,
|
|
1523
|
+
minTemperature: minT,
|
|
1524
|
+
maxTemperature: maxT,
|
|
1473
1525
|
height,
|
|
1474
1526
|
width,
|
|
1475
1527
|
xScale,
|
|
@@ -1656,6 +1708,9 @@ const getCollectionLocations = (collectionId, baseUrl) => fetch(`${baseUrl}/coll
|
|
|
1656
1708
|
const getCollectionInstances = (collectionId, baseUrl) => fetch(`${baseUrl}/collections/${collectionId}/instances`, {
|
|
1657
1709
|
headers: getHeaders()
|
|
1658
1710
|
}).then(handleResponse);
|
|
1711
|
+
const getCollectionDetails = (collectionId, baseUrl) => fetch(`${baseUrl}/collections/${collectionId}`, {
|
|
1712
|
+
headers: getHeaders()
|
|
1713
|
+
}).then(handleResponse);
|
|
1659
1714
|
const getEdrCollectionForLocation = (collectionId, baseUrl, instanceId, locationId, parameters, datetime, verticalRange) => {
|
|
1660
1715
|
const url = new URL(`${baseUrl}/collections/${collectionId}${instanceId ? `/instances/${instanceId}` : ''}/locations/${locationId}`);
|
|
1661
1716
|
url.searchParams.append('parameter-name', parameters.join(','));
|
|
@@ -1872,12 +1927,19 @@ const parseDurationWithRepeats = dateString => {
|
|
|
1872
1927
|
const numOfRepeats = Number(parts[0].substring(1));
|
|
1873
1928
|
const start = new Date(parts[1]).getTime();
|
|
1874
1929
|
const interval = parseISO8601IntervalToDateInterval(parts[2]).getTime();
|
|
1930
|
+
// If number of values too big, it will mess up the timeslider, set to 1500 max
|
|
1931
|
+
if (numOfRepeats >= 1500) {
|
|
1932
|
+
const iterations = range(1500);
|
|
1933
|
+
const newStart = start + interval * (numOfRepeats - 1499); // Move start so its 1500 steps from end
|
|
1934
|
+
const dateStrings = iterations.map(i => newStart + i * interval).map(millis => new Date(millis).toISOString());
|
|
1935
|
+
return dateStrings;
|
|
1936
|
+
}
|
|
1875
1937
|
const iterations = range(numOfRepeats);
|
|
1876
1938
|
const dateStrings = iterations.map(i => start + i * interval).map(millis => new Date(millis).toISOString());
|
|
1877
1939
|
return dateStrings;
|
|
1878
1940
|
};
|
|
1879
|
-
const
|
|
1880
|
-
const timeExtentValues =
|
|
1941
|
+
const getTimestepsFromInstanceOrCollection = instanceOrCollection => {
|
|
1942
|
+
const timeExtentValues = instanceOrCollection?.extent?.temporal?.values;
|
|
1881
1943
|
if (!timeExtentValues) {
|
|
1882
1944
|
return [];
|
|
1883
1945
|
}
|
|
@@ -1890,7 +1952,10 @@ const getTimestepsFromInstance = instance => {
|
|
|
1890
1952
|
}
|
|
1891
1953
|
// <start>/<end>[/P<period>]
|
|
1892
1954
|
if (currentValue.match(/.*\/.*P?.*/)) {
|
|
1893
|
-
const
|
|
1955
|
+
const parts = currentValue.split('/');
|
|
1956
|
+
// In case no period defined, set to default 1H
|
|
1957
|
+
const defaultInterval = parts[2] === undefined ? 'PT1H' : undefined;
|
|
1958
|
+
const parseObject = new ParseISOTimeRangeDuration(currentValue, defaultInterval);
|
|
1894
1959
|
const timeValues = range(parseObject.getTimeSteps()).map(timestep => parseObject.getDateAtTimeStep(timestep).toISOString());
|
|
1895
1960
|
return [...parsedSteps, ...timeValues];
|
|
1896
1961
|
}
|
|
@@ -2033,12 +2098,21 @@ const useTimesteps = sourceSelections => {
|
|
|
2033
2098
|
}) => ({
|
|
2034
2099
|
queryKey: ['edr-soundings-instances', collectionId],
|
|
2035
2100
|
queryFn: async () => {
|
|
2036
|
-
|
|
2101
|
+
// If instance id passed, use this to fetch time extent
|
|
2102
|
+
if (instanceId && instanceId !== '') {
|
|
2103
|
+
const data = await getCollectionInstances(collectionId, url);
|
|
2104
|
+
return data;
|
|
2105
|
+
}
|
|
2106
|
+
// Otherwise, use collection details
|
|
2107
|
+
const data = await getCollectionDetails(collectionId, url);
|
|
2037
2108
|
return data;
|
|
2038
2109
|
},
|
|
2039
2110
|
select: data => {
|
|
2040
|
-
|
|
2041
|
-
|
|
2111
|
+
if (data.instances !== undefined) {
|
|
2112
|
+
const instance = data.instances.find(instance => instance.id === instanceId);
|
|
2113
|
+
return getTimestepsFromInstanceOrCollection(instance);
|
|
2114
|
+
}
|
|
2115
|
+
return getTimestepsFromInstanceOrCollection(data);
|
|
2042
2116
|
}
|
|
2043
2117
|
})), [sourceSelections]);
|
|
2044
2118
|
const results = useQueries({
|
|
@@ -2067,19 +2141,57 @@ const useGetCollectionsInstances = (collections, isDialogOpen) => {
|
|
|
2067
2141
|
url: collection.url
|
|
2068
2142
|
};
|
|
2069
2143
|
}) || [], [collections]);
|
|
2070
|
-
|
|
2144
|
+
// Fetch collection details
|
|
2145
|
+
const queriesCollection = useMemo(() => collectionIds.map(({
|
|
2071
2146
|
id,
|
|
2072
2147
|
url
|
|
2073
2148
|
}) => {
|
|
2074
2149
|
return {
|
|
2075
|
-
queryKey: ['edr-soundings-
|
|
2150
|
+
queryKey: ['edr-soundings-collection-details', id, url],
|
|
2076
2151
|
queryFn: async () => {
|
|
2077
|
-
const data = await
|
|
2152
|
+
const data = await getCollectionDetails(id, url);
|
|
2078
2153
|
return data;
|
|
2079
2154
|
},
|
|
2080
2155
|
enabled: isDialogOpen
|
|
2081
2156
|
};
|
|
2082
2157
|
}), [collectionIds, isDialogOpen]);
|
|
2158
|
+
const resultsCollection = useQueries({
|
|
2159
|
+
queries: queriesCollection,
|
|
2160
|
+
combine: queryResults => {
|
|
2161
|
+
const data = queryResults.map(result => {
|
|
2162
|
+
return result.data?.data_queries?.instances !== undefined;
|
|
2163
|
+
});
|
|
2164
|
+
const isPending = queryResults.some(result => result.isPending);
|
|
2165
|
+
const error = queryResults.find(result => result?.error)?.error;
|
|
2166
|
+
return {
|
|
2167
|
+
data,
|
|
2168
|
+
isPending,
|
|
2169
|
+
error
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2173
|
+
// Fetch instance details for collections that have instances
|
|
2174
|
+
const queries = useMemo(() => {
|
|
2175
|
+
return collectionIds.map(({
|
|
2176
|
+
id,
|
|
2177
|
+
url
|
|
2178
|
+
}, index) => {
|
|
2179
|
+
return {
|
|
2180
|
+
queryKey: ['edr-soundings-instances', id, resultsCollection.data],
|
|
2181
|
+
queryFn: async () => {
|
|
2182
|
+
// Only fetch if there are instances for this collection
|
|
2183
|
+
if (resultsCollection.data[index]) {
|
|
2184
|
+
const data = await getCollectionInstances(id, url);
|
|
2185
|
+
return data;
|
|
2186
|
+
}
|
|
2187
|
+
return {
|
|
2188
|
+
instances: []
|
|
2189
|
+
};
|
|
2190
|
+
},
|
|
2191
|
+
enabled: isDialogOpen && resultsCollection.data !== undefined
|
|
2192
|
+
};
|
|
2193
|
+
});
|
|
2194
|
+
}, [collectionIds, isDialogOpen, resultsCollection]);
|
|
2083
2195
|
const results = useQueries({
|
|
2084
2196
|
queries,
|
|
2085
2197
|
combine: queryResults => {
|
|
@@ -2102,12 +2214,16 @@ const useGetCollectionsInstances = (collections, isDialogOpen) => {
|
|
|
2102
2214
|
instances: results.data[index] || []
|
|
2103
2215
|
};
|
|
2104
2216
|
});
|
|
2217
|
+
const errorResult = results.error || resultsCollection.error;
|
|
2218
|
+
const isPendingResult = results.isPending || resultsCollection.isPending;
|
|
2105
2219
|
return {
|
|
2106
2220
|
...results,
|
|
2221
|
+
isPending: isPendingResult,
|
|
2222
|
+
error: errorResult,
|
|
2107
2223
|
data: dataWithCollectionInfo
|
|
2108
2224
|
};
|
|
2109
2225
|
};
|
|
2110
|
-
const useGetCollectionLocations = (collections,
|
|
2226
|
+
const useGetCollectionLocations = (collections, enabled) => {
|
|
2111
2227
|
const edrQueries = useMemo(() => collections?.map(collection => ({
|
|
2112
2228
|
queryKey: ['edr-locations', collection.id],
|
|
2113
2229
|
queryFn: async () => {
|
|
@@ -2118,8 +2234,8 @@ const useGetCollectionLocations = (collections, isDialogOpen) => {
|
|
|
2118
2234
|
name: collection.name
|
|
2119
2235
|
};
|
|
2120
2236
|
},
|
|
2121
|
-
enabled
|
|
2122
|
-
})), [collections,
|
|
2237
|
+
enabled
|
|
2238
|
+
})), [collections, enabled]);
|
|
2123
2239
|
return useQueries({
|
|
2124
2240
|
queries: edrQueries,
|
|
2125
2241
|
combine: results => {
|
|
@@ -2158,14 +2274,14 @@ const initSoundingsI18n = () => {
|
|
|
2158
2274
|
ns: SOUNDINGS_NAMESPACE,
|
|
2159
2275
|
translations: soundingsTranslations
|
|
2160
2276
|
}, {
|
|
2161
|
-
ns:
|
|
2277
|
+
ns: TIME_SLIDER_NAMESPACE,
|
|
2162
2278
|
translations: timesliderTranslations
|
|
2163
2279
|
}, {
|
|
2164
2280
|
ns: SHARED_NAMESPACE,
|
|
2165
2281
|
translations: sharedTranslations
|
|
2166
2282
|
}]);
|
|
2167
2283
|
};
|
|
2168
|
-
const ns = [SOUNDINGS_NAMESPACE,
|
|
2284
|
+
const ns = [SOUNDINGS_NAMESPACE, TIME_SLIDER_NAMESPACE, SHARED_NAMESPACE];
|
|
2169
2285
|
const translateKeyOutsideComponents = (key, params = undefined) => i18n.t(key, {
|
|
2170
2286
|
ns,
|
|
2171
2287
|
...params
|
|
@@ -2643,9 +2759,50 @@ const SoundingsConnect = ({
|
|
|
2643
2759
|
diagramType = 'SKEWT'
|
|
2644
2760
|
}) => {
|
|
2645
2761
|
const [chosenDiagramType, setChosenDiagramType] = React.useState(diagramType);
|
|
2762
|
+
const geojsonLayerId = React.useRef(webmapUtils.generateLayerId()).current;
|
|
2763
|
+
const dispatch = useDispatch();
|
|
2646
2764
|
const selectedTime = useSelector(getSelectedTime);
|
|
2647
2765
|
const sourceSelections = useSelector(getSelectedSources);
|
|
2648
2766
|
const locationSelections = useSelector(getLocationSelections);
|
|
2767
|
+
const collections = sourceSelections.map(({
|
|
2768
|
+
collectionId,
|
|
2769
|
+
url,
|
|
2770
|
+
name
|
|
2771
|
+
}) => ({
|
|
2772
|
+
id: collectionId,
|
|
2773
|
+
url,
|
|
2774
|
+
name: name || collectionId
|
|
2775
|
+
}));
|
|
2776
|
+
const {
|
|
2777
|
+
data: locationData
|
|
2778
|
+
} = useGetCollectionLocations(collections, true);
|
|
2779
|
+
useEffect(() => {
|
|
2780
|
+
const simpleGeoJson = {
|
|
2781
|
+
type: 'FeatureCollection',
|
|
2782
|
+
features: (locationData || []).flatMap(({
|
|
2783
|
+
id: serviceId,
|
|
2784
|
+
features
|
|
2785
|
+
}) => features.map(feature => ({
|
|
2786
|
+
type: 'Feature',
|
|
2787
|
+
geometry: feature.geometry,
|
|
2788
|
+
properties: {
|
|
2789
|
+
...feature.properties,
|
|
2790
|
+
mapFeatureClass: MapFeatureClass.ObservationStation
|
|
2791
|
+
},
|
|
2792
|
+
id: feature.id,
|
|
2793
|
+
serviceId // TODO: remove in follow-up if not needed https://gitlab.com/opengeoweb/opengeoweb/-/issues/6312
|
|
2794
|
+
})))
|
|
2795
|
+
};
|
|
2796
|
+
dispatch(genericActions.addSharedData({
|
|
2797
|
+
panelId: viewId,
|
|
2798
|
+
data: {
|
|
2799
|
+
features: [{
|
|
2800
|
+
id: geojsonLayerId,
|
|
2801
|
+
geoJSON: simpleGeoJson
|
|
2802
|
+
}]
|
|
2803
|
+
}
|
|
2804
|
+
}));
|
|
2805
|
+
}, [collections, dispatch, geojsonLayerId, locationData, sourceSelections, viewId]);
|
|
2649
2806
|
const {
|
|
2650
2807
|
error,
|
|
2651
2808
|
data,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/soundings",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"description": "GeoWeb soundings library for the opengeoweb project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -8,23 +8,24 @@
|
|
|
8
8
|
"url": "git@gitlab.com:opengeoweb/opengeoweb.git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@opengeoweb/api": "
|
|
12
|
-
"@tanstack/react-query": "^5.
|
|
11
|
+
"@opengeoweb/api": "13.0.0",
|
|
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": "
|
|
17
|
+
"@opengeoweb/shared": "13.0.0",
|
|
18
18
|
"@mui/material": "^7.0.1",
|
|
19
|
-
"@opengeoweb/store": "
|
|
19
|
+
"@opengeoweb/store": "13.0.0",
|
|
20
20
|
"react-redux": "^9.2.0",
|
|
21
|
-
"@opengeoweb/theme": "
|
|
21
|
+
"@opengeoweb/theme": "13.0.0",
|
|
22
22
|
"@reduxjs/toolkit": "^2.6.1",
|
|
23
|
-
"@opengeoweb/
|
|
23
|
+
"@opengeoweb/time-slider": "13.0.0",
|
|
24
24
|
"react-window": "^1.8.10",
|
|
25
|
-
"@opengeoweb/webmap": "
|
|
25
|
+
"@opengeoweb/webmap": "13.0.0",
|
|
26
26
|
"lodash": "^4.17.21",
|
|
27
|
-
"@types/geojson": "^7946.0.14"
|
|
27
|
+
"@types/geojson": "^7946.0.14",
|
|
28
|
+
"@opengeoweb/webmap-react": "13.0.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"eslint-plugin-storybook": "9.0.17"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CoverageCollection } from '@opengeoweb/shared';
|
|
2
|
-
import { LocationsResponseFromBE, SoundingsInstances } from './types';
|
|
2
|
+
import { CollectionDetails, LocationsResponseFromBE, SoundingsInstances } from './types';
|
|
3
3
|
export declare const getCollectionLocations: (collectionId: string, baseUrl: string) => Promise<LocationsResponseFromBE>;
|
|
4
4
|
export declare const getCollectionInstances: (collectionId: string, baseUrl: string) => Promise<SoundingsInstances>;
|
|
5
|
+
export declare const getCollectionDetails: (collectionId: string, baseUrl: string) => Promise<CollectionDetails>;
|
|
5
6
|
export declare const getEdrCollectionForLocation: (collectionId: string, baseUrl: string, instanceId: string | undefined, locationId: string, parameters: string[], datetime: string, verticalRange: string) => Promise<CoverageCollection>;
|
|
6
7
|
export declare const getEdrCollectionForPosition: (collectionId: string, baseUrl: string, instanceId: string | undefined, coordinates: [number, number], parameters: string[], datetime: string, verticalRange: string) => Promise<CoverageCollection>;
|
|
@@ -1 +1,16 @@
|
|
|
1
|
+
export declare const helsinkiLat = 60.192059;
|
|
2
|
+
export declare const helsinkiLon = 24.945831;
|
|
3
|
+
export declare const helsinki = "Helsinki";
|
|
4
|
+
export declare const mockLocations: {
|
|
5
|
+
features: {
|
|
6
|
+
id: string;
|
|
7
|
+
geometry: {
|
|
8
|
+
type: string;
|
|
9
|
+
coordinates: number[];
|
|
10
|
+
};
|
|
11
|
+
properties: {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
1
16
|
export declare const fmiEdrCollectionsHandlers: import("msw").HttpHandler[];
|
|
@@ -33,7 +33,11 @@ export declare const useGetCollectionsInstances: (collections?: SoundingsCollect
|
|
|
33
33
|
isPending: boolean;
|
|
34
34
|
error: Error | null | undefined;
|
|
35
35
|
};
|
|
36
|
-
export declare const useGetCollectionLocations:
|
|
36
|
+
export declare const useGetCollectionLocations: <SoundingsCollectionLike extends {
|
|
37
|
+
id: string;
|
|
38
|
+
url: string;
|
|
39
|
+
name: string;
|
|
40
|
+
}>(collections: SoundingsCollectionLike[], enabled?: boolean) => {
|
|
37
41
|
data: ServiceWithLocations[] | undefined;
|
|
38
42
|
isPending: boolean;
|
|
39
43
|
error: Error | null | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Geometry } from 'geojson';
|
|
2
|
-
import { EDRInstance } from '@opengeoweb/shared';
|
|
2
|
+
import { EDRInstance, EdrParameter } from '@opengeoweb/shared';
|
|
3
3
|
export interface FeaturesFromBE {
|
|
4
4
|
id: string;
|
|
5
5
|
type: string;
|
|
@@ -31,5 +31,8 @@ export type SoundingsInstance = EDRInstance;
|
|
|
31
31
|
export interface SoundingsInstances {
|
|
32
32
|
instances: SoundingsInstance[];
|
|
33
33
|
}
|
|
34
|
+
export interface CollectionDetails extends EDRInstance {
|
|
35
|
+
parameter_names: Record<string, EdrParameter>;
|
|
36
|
+
}
|
|
34
37
|
export declare const soundingDiagrams: readonly ["SKEWT", "BIJVOET", "EMAGRAM"];
|
|
35
38
|
export type SoundingDiagramType = (typeof soundingDiagrams)[number];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CoverageCollection } from '@opengeoweb/shared';
|
|
2
|
-
import { SoundingFeature, SoundingsInstance } from './types';
|
|
2
|
+
import { CollectionDetails, SoundingFeature, SoundingsInstance } from './types';
|
|
3
3
|
export declare function parseCoverageCollection(response: CoverageCollection, parameterMappings: Record<string, string>): SoundingFeature[];
|
|
4
4
|
/**
|
|
5
5
|
* Parse duration with repeats
|
|
@@ -7,4 +7,4 @@ export declare function parseCoverageCollection(response: CoverageCollection, pa
|
|
|
7
7
|
* @returns Array of ISO datetime strings, e.g., ['2025-04-22T09:00:00.000Z', ...]
|
|
8
8
|
*/
|
|
9
9
|
export declare const parseDurationWithRepeats: (dateString: string) => string[];
|
|
10
|
-
export declare const
|
|
10
|
+
export declare const getTimestepsFromInstanceOrCollection: (instanceOrCollection?: SoundingsInstance | CollectionDetails) => string[];
|
|
@@ -2,6 +2,7 @@ export declare const maxPressure = 1050;
|
|
|
2
2
|
export declare const minPressure = 150;
|
|
3
3
|
export declare const staticPressureArray: number[];
|
|
4
4
|
export declare const dp = -5;
|
|
5
|
+
export declare const minEmagramTemperature = -80;
|
|
5
6
|
export declare const minTemperature = -40;
|
|
6
7
|
export declare const maxTemperature = 40.6;
|
|
7
8
|
export declare const T_KAPPA = 0.2857;
|