@opengeoweb/warnings 15.2.0 → 15.3.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 +808 -12
- package/package.json +12 -12
- package/src/index.d.ts +1 -0
- package/src/lib/components/WarningsMapView/WarningsMapView.d.ts +1 -0
- package/src/lib/components/WarningsTimeline/WarningBlock.d.ts +10 -0
- package/src/lib/components/WarningsTimeline/WarningsTimeline.d.ts +6 -0
- package/src/lib/components/WarningsTimeline/WarningsTimeline.spec.d.ts +1 -0
- package/src/lib/components/WarningsTimeline/WarningsTimeline.stories.d.ts +12 -0
- package/src/lib/components/WarningsTimeline/WarningsTimelineConnect.d.ts +5 -0
- package/src/lib/components/WarningsTimeline/WarningsTimelineConnect.spec.d.ts +1 -0
- package/src/lib/components/WarningsTimeline/index.d.ts +4 -0
- package/src/lib/components/WarningsTimeline/warningBlockColors.d.ts +16 -0
- package/src/lib/components/WarningsTimeline/warningBlockColors.spec.d.ts +1 -0
- package/src/lib/components/WarningsTimeline/warningsTimelineUtils.d.ts +15 -0
- package/src/lib/components/WarningsTimeline/warningsTimelineUtils.spec.d.ts +1 -0
package/index.esm.js
CHANGED
|
@@ -2,28 +2,32 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useDispatch, useSelector } from 'react-redux';
|
|
3
3
|
import { uiTypes, uiActions, getSingularDrawtoolDrawLayerId, drawingToolSelectors, layerSelectors, uiSelectors, layerActions, drawingToolActions, mapListener, layersListener, drawingToolListener, syncGroupsListener, openlayersListener, syncGroupsReducer, drawingToolReducer, uiReducer, layerReducer, mapReducer, useSetupDialog, genericSelectors, useUpdateSharedData, genericActions, selectorMemoizationOptions } from '@opengeoweb/store';
|
|
4
4
|
import { Polygons, CoastalEvent, TemperatureLow, TemperatureHigh, Rain, Snow, Lightning, Fog, Wind, Thunderstorm, SevereMountainWaves, VulcanicEruption, Haze, FreezingPrecipitation, ModerateAircraftIcing, SevereAircraftIcing, ModerateTurbulence, SevereTurbulence, SandStorm, RadioactiveMaterials, ExitDomain, Share, Edit, Delete, DrawPolygon, Visibility, Add, breakpoints, DragHandle, Info, ArrowUpCompact, ArrowDownCompact, Copy, Update, Cancel, Success, Expire, Remove, Options, ChevronDown, ChevronUp, Close, Clock } from '@opengeoweb/theme';
|
|
5
|
-
import { WEBMAP_REACT_NAMESPACE, defaultPolygon, emptyGeoJSON, MapControlButton, defaultSmoothLine, defaultLineString, defaultFreehandLine, defaultOval, defaultCircle,
|
|
5
|
+
import { WEBMAP_REACT_NAMESPACE, defaultPolygon, emptyGeoJSON, MapControlButton, defaultSmoothLine, defaultLineString, defaultFreehandLine, defaultOval, defaultCircle, defaultRotatableBox, defaultSquare, defaultLocation, defaultPoint, defaultDelete, getDrawModeIdFromSelectionType, getIcon, rewindGeometry, getGeoJSONPropertyValue, currentlySupportedDrawModes, defaultLayers, viewUtils, OpenLayersMapView, MapControls, OpenLayersZoomControl, OpenLayersLayer, OpenLayersFeatureLayer, genericOpenLayersFeatureStyle, DEFAULT_GEOJSON_STYLE_FILL_OPACITY, FEATURE_DRAW_FILL_COLOR, FEATURE_DRAW_SECONDARY_FILL_COLOR, FEATURE_DRAW_STROKE_COLOR } from '@opengeoweb/webmap-react';
|
|
6
6
|
import { SHARED_NAMESPACE, useConfirmationDialog, sessionStorageProvider, dateUtils, ConfirmationDialog, AlertBanner, ToggleMenu, calculateStartSize, ToolContainerDraggable, CustomIconButton, usePrevious, usePreventBrowserClose, CustomTooltip, Avatar, getInitials, SwitchButton, Filter, CustomToggleButton, FilterChip, TooltipSelect, LastUpdateTime, StatusTag, FilterOption, getAxiosErrorMessage, CustomDialog, ConfirmationButtons, ErrorBoundary } from '@opengeoweb/shared';
|
|
7
7
|
import { createEntityAdapter, createSlice, createSelector, createListenerMiddleware, current, combineReducers, configureStore } from '@reduxjs/toolkit';
|
|
8
8
|
import { t } from 'i18next';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
10
10
|
import { defaultBbox } from '@opengeoweb/core';
|
|
11
|
-
import { FORM_FIELDS_NAMESPACE, useDraftFormHelpers, ReactHookFormSelect, ReactHookFormHiddenInput, isValidGeoJsonCoordinates, ReactHookFormTextField, ReactHookFormProvider, defaultFormOptions, errorMessages, isEmpty, ReactHookFormDateTime, isXHoursAfter, isXHoursBefore } from '@opengeoweb/form-fields';
|
|
11
|
+
import { FORM_FIELDS_NAMESPACE, useDraftFormHelpers, ReactHookFormSelect, ReactHookFormHiddenInput, isValidGeoJsonCoordinates, ReactHookFormTextField, ReactHookFormProvider, defaultFormOptions, errorMessages, isEmpty as isEmpty$1, ReactHookFormDateTime, isXHoursAfter, isXHoursBefore } from '@opengeoweb/form-fields';
|
|
12
12
|
import { SA_NAMESPACE, isInstanceOfCancelSigmet, getDefaultValidFromValue, isInstanceOfCancelAirmet, getDefaultValidUntilValue, useShortTestHelpers, ProductAction, SigmetForm, AirmetForm, isVAPhenomenon, getConfirmationDialogCancelLabel, getConfirmationDialogButtonLabel, getConfirmationDialogContent, getConfirmationDialogTitle, CancelSigmetVolcanicMovements, createAirmetPostParameter, createSigmetPostParameter, prepareCancelSigmet, getProductFormMode, findSequenceNumber, getSequenceStyling } from '@opengeoweb/sigmet-airmet';
|
|
13
13
|
import { LayerType, generateMapId } from '@opengeoweb/webmap';
|
|
14
14
|
import React, { useRef, useState, useEffect, useMemo, useCallback } from 'react';
|
|
15
15
|
import { useAuthenticationContext as useAuthenticationContext$1 } from '@opengeoweb/authentication';
|
|
16
|
-
import { MenuItem, Grid, Box, Typography, styled, ListItem, Paper, ListItemButton, Stack, LinearProgress, Button, FormHelperText, Card, CardContent, Tabs, Tab, useTheme, FormControl, CircularProgress, Menu, ListItemText, DialogTitle, DialogContent, Switch, RadioGroup, FormControlLabel, Radio, InputAdornment, Collapse } from '@mui/material';
|
|
16
|
+
import { MenuItem, Grid, Box, Typography, styled, ListItem, Paper, ListItemButton, Stack, LinearProgress, Button, FormHelperText, Card, CardContent, Tabs, Tab, useTheme, FormControl, CircularProgress, Menu, ListItemText, DialogTitle, DialogContent, Switch, RadioGroup, FormControlLabel, Radio, InputAdornment, Collapse, Tooltip } from '@mui/material';
|
|
17
17
|
import { useQueryClient, useMutation, queryOptions, QueryClient, useQuery } from '@tanstack/react-query';
|
|
18
18
|
import { getHeaders, handleResponse, AirmetPhenomena, SigmetPhenomena, useAuthQuery, useAuthenticationContext, optimisticUpdate, ProductStatus } from '@opengeoweb/api';
|
|
19
19
|
import { snackbarListener, snackbarReducer, snackbarActions, snackbarTypes } from '@opengeoweb/snackbar';
|
|
20
20
|
import { List, useListRef } from 'react-window';
|
|
21
21
|
import { isEqual, cloneDeep, clamp, concat, groupBy, pick } from 'lodash';
|
|
22
22
|
import { useFormContext, useForm, FormProvider } from 'react-hook-form';
|
|
23
|
+
import { isEmpty, createEmpty, extend } from 'ol/extent';
|
|
24
|
+
import GeoJSON from 'ol/format/GeoJSON';
|
|
23
25
|
import { ReactSortable } from 'react-sortablejs';
|
|
24
26
|
import { LocalizationProvider } from '@mui/x-date-pickers';
|
|
25
27
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
|
26
28
|
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
|
|
29
|
+
import Box$1 from '@mui/material/Box';
|
|
30
|
+
import Tooltip$1 from '@mui/material/Tooltip';
|
|
27
31
|
|
|
28
32
|
var en = {
|
|
29
33
|
"drawing-tool-form-tools": "Tools",
|
|
@@ -84,6 +88,11 @@ var en = {
|
|
|
84
88
|
"warning-level-moderate": "Moderate",
|
|
85
89
|
"warning-level-severe": "Severe",
|
|
86
90
|
"warning-level-extreme": "Extreme",
|
|
91
|
+
"warning-level-letter-moderate": "M",
|
|
92
|
+
"warning-level-letter-severe": "S",
|
|
93
|
+
"warning-level-letter-extreme": "E",
|
|
94
|
+
"warning-level-letter-SIG": "SIG",
|
|
95
|
+
"warning-level-letter-AIR": "AIR",
|
|
87
96
|
"warning-level-SIG": "Sigmet",
|
|
88
97
|
"warning-level-AIR": "Airmet",
|
|
89
98
|
"warning-phenomenon": "Phenomenon",
|
|
@@ -347,6 +356,11 @@ var nl = {
|
|
|
347
356
|
"warning-level-moderate": "Gematigd",
|
|
348
357
|
"warning-level-severe": "Ernstig",
|
|
349
358
|
"warning-level-extreme": "Extreem",
|
|
359
|
+
"warning-level-letter-moderate": "G",
|
|
360
|
+
"warning-level-letter-severe": "E",
|
|
361
|
+
"warning-level-letter-extreme": "X",
|
|
362
|
+
"warning-level-letter-SIG": "SIG",
|
|
363
|
+
"warning-level-letter-AIR": "AIR",
|
|
350
364
|
"warning-phenomenon": "Fenomeen",
|
|
351
365
|
"warning-phenomenon-wind": "Windstoten",
|
|
352
366
|
"warning-phenomenon-fog": "Dichte mist",
|
|
@@ -567,6 +581,11 @@ var fi = {
|
|
|
567
581
|
"warning-level-moderate": "Kohtalainen",
|
|
568
582
|
"warning-level-severe": "Vakava",
|
|
569
583
|
"warning-level-extreme": "Äärimmäinen",
|
|
584
|
+
"warning-level-letter-moderate": "K",
|
|
585
|
+
"warning-level-letter-severe": "V",
|
|
586
|
+
"warning-level-letter-extreme": "Ä",
|
|
587
|
+
"warning-level-letter-SIG": "SIG",
|
|
588
|
+
"warning-level-letter-AIR": "AIR",
|
|
570
589
|
"warning-phenomenon": "Sääilmiö",
|
|
571
590
|
"warning-phenomenon-wind": "Tuuli",
|
|
572
591
|
"warning-phenomenon-fog": "Sumu",
|
|
@@ -739,6 +758,11 @@ var no = {
|
|
|
739
758
|
"warning-level-moderate": "Moderat",
|
|
740
759
|
"warning-level-severe": "Stor",
|
|
741
760
|
"warning-level-extreme": "Ekstrem",
|
|
761
|
+
"warning-level-letter-moderate": "M",
|
|
762
|
+
"warning-level-letter-severe": "S",
|
|
763
|
+
"warning-level-letter-extreme": "E",
|
|
764
|
+
"warning-level-letter-SIG": "SIG",
|
|
765
|
+
"warning-level-letter-AIR": "AIR",
|
|
742
766
|
"warning-phenomenon": "Fenomen",
|
|
743
767
|
"warning-phenomenon-wind": "Vind",
|
|
744
768
|
"warning-phenomenon-fog": "Tåke",
|
|
@@ -883,6 +907,11 @@ var areaObjectLoaderType = uiTypes.DialogTypes.AreaObjectLoader;
|
|
|
883
907
|
function _OverloadYield(e, d) {
|
|
884
908
|
this.v = e, this.k = d;
|
|
885
909
|
}
|
|
910
|
+
function _arrayLikeToArray(r, a) {
|
|
911
|
+
(null == a || a > r.length) && (a = r.length);
|
|
912
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
913
|
+
return n;
|
|
914
|
+
}
|
|
886
915
|
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
887
916
|
try {
|
|
888
917
|
var i = n[a](c),
|
|
@@ -908,6 +937,23 @@ function _asyncToGenerator(n) {
|
|
|
908
937
|
});
|
|
909
938
|
};
|
|
910
939
|
}
|
|
940
|
+
function _createForOfIteratorHelperLoose(r, e) {
|
|
941
|
+
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
942
|
+
if (t) return (t = t.call(r)).next.bind(t);
|
|
943
|
+
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {
|
|
944
|
+
t && (r = t);
|
|
945
|
+
var o = 0;
|
|
946
|
+
return function () {
|
|
947
|
+
return o >= r.length ? {
|
|
948
|
+
done: true
|
|
949
|
+
} : {
|
|
950
|
+
done: false,
|
|
951
|
+
value: r[o++]
|
|
952
|
+
};
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
956
|
+
}
|
|
911
957
|
function _objectWithoutPropertiesLoose(r, e) {
|
|
912
958
|
if (null == r) return {};
|
|
913
959
|
var t = {};
|
|
@@ -1092,6 +1138,13 @@ function _regeneratorValues(e) {
|
|
|
1092
1138
|
}
|
|
1093
1139
|
throw new TypeError(typeof e + " is not iterable");
|
|
1094
1140
|
}
|
|
1141
|
+
function _unsupportedIterableToArray(r, a) {
|
|
1142
|
+
if (r) {
|
|
1143
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
1144
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
1145
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1095
1148
|
function _regeneratorRuntime() {
|
|
1096
1149
|
|
|
1097
1150
|
var r = _regenerator(),
|
|
@@ -4279,7 +4332,7 @@ var drawToolConfig = [{
|
|
|
4279
4332
|
secondaryMode: defaultOval
|
|
4280
4333
|
}, {
|
|
4281
4334
|
primaryMode: defaultSquare,
|
|
4282
|
-
secondaryMode:
|
|
4335
|
+
secondaryMode: defaultRotatableBox
|
|
4283
4336
|
}, {
|
|
4284
4337
|
primaryMode: defaultPoint,
|
|
4285
4338
|
secondaryMode: defaultLocation
|
|
@@ -6864,12 +6917,30 @@ var AreaObjectLoader = function AreaObjectLoader(_ref) {
|
|
|
6864
6917
|
});
|
|
6865
6918
|
};
|
|
6866
6919
|
|
|
6920
|
+
var EXTENT_PADDING = 50;
|
|
6921
|
+
function getGeojsonExtent(featureCollection, viewSrs, dataSrs) {
|
|
6922
|
+
var format = new GeoJSON();
|
|
6923
|
+
var features = format.readFeatures(featureCollection, {
|
|
6924
|
+
dataProjection: dataSrs,
|
|
6925
|
+
featureProjection: viewSrs
|
|
6926
|
+
});
|
|
6927
|
+
var extent = createEmpty();
|
|
6928
|
+
for (var _iterator = _createForOfIteratorHelperLoose(features), _step; !(_step = _iterator()).done;) {
|
|
6929
|
+
var feat = _step.value;
|
|
6930
|
+
var geo = feat.getGeometry();
|
|
6931
|
+
if (geo) {
|
|
6932
|
+
extend(extent, geo.getExtent());
|
|
6933
|
+
}
|
|
6934
|
+
}
|
|
6935
|
+
return extent;
|
|
6936
|
+
}
|
|
6867
6937
|
var WarningsMapView = function WarningsMapView(_ref) {
|
|
6868
6938
|
var _defaultMapPreset$lay, _defaultMapPreset$lay2, _viewRef$current;
|
|
6869
6939
|
var geojsonFeature = _ref.geojsonFeature,
|
|
6870
6940
|
defaultMapPreset = _ref.defaultMapPreset,
|
|
6871
6941
|
_ref$isSnapshot = _ref.isSnapshot,
|
|
6872
6942
|
isSnapshot = _ref$isSnapshot === void 0 ? false : _ref$isSnapshot;
|
|
6943
|
+
var containerRef = useRef(null);
|
|
6873
6944
|
var defaultMapPresetBbox = geojsonFeature != null && geojsonFeature.features.length ? undefined : defaultBbox;
|
|
6874
6945
|
var defaultBbox$1 = (defaultMapPreset == null ? void 0 : defaultMapPreset.proj) || defaultMapPresetBbox;
|
|
6875
6946
|
var defaultBaseLayer = (defaultMapPreset == null || (_defaultMapPreset$lay = defaultMapPreset.layers) == null ? void 0 : _defaultMapPreset$lay.find(function (layer) {
|
|
@@ -6885,12 +6956,36 @@ var WarningsMapView = function WarningsMapView(_ref) {
|
|
|
6885
6956
|
};
|
|
6886
6957
|
var viewRef = useRef(viewUtils.makeView());
|
|
6887
6958
|
React.useEffect(function () {
|
|
6959
|
+
var _geojsonFeature$featu;
|
|
6888
6960
|
if (viewRef.current.getProjection().getCode() !== (defaultBbox$1 == null ? void 0 : defaultBbox$1.srs)) {
|
|
6889
6961
|
viewRef.current = viewUtils.makeView(defaultBbox$1 == null ? void 0 : defaultBbox$1.srs);
|
|
6890
6962
|
}
|
|
6891
|
-
|
|
6963
|
+
var isNew = (defaultBbox$1 == null ? void 0 : defaultBbox$1.bbox) && !(geojsonFeature != null && geojsonFeature.features.length);
|
|
6964
|
+
if (isNew) {
|
|
6965
|
+
viewUtils.setViewFromExtent(viewRef.current, defaultBbox$1 == null ? void 0 : defaultBbox$1.bbox);
|
|
6966
|
+
return;
|
|
6967
|
+
}
|
|
6968
|
+
if (geojsonFeature != null && (_geojsonFeature$featu = geojsonFeature.features) != null && _geojsonFeature$featu.length) {
|
|
6969
|
+
var viewSrs = viewRef.current.getProjection().getCode();
|
|
6970
|
+
var extent = getGeojsonExtent(geojsonFeature, viewSrs, 'EPSG:4326');
|
|
6971
|
+
if (!isEmpty(extent)) {
|
|
6972
|
+
var el = containerRef.current;
|
|
6973
|
+
var rect = el == null ? void 0 : el.getBoundingClientRect();
|
|
6974
|
+
var size = rect && rect.width > 0 && rect.height > 0 ? [Math.round(rect.width), Math.round(rect.height)] : undefined;
|
|
6975
|
+
viewRef.current.fit(extent, {
|
|
6976
|
+
size: size,
|
|
6977
|
+
padding: [EXTENT_PADDING, EXTENT_PADDING, EXTENT_PADDING, EXTENT_PADDING],
|
|
6978
|
+
maxZoom: 12,
|
|
6979
|
+
duration: 0
|
|
6980
|
+
});
|
|
6981
|
+
return;
|
|
6982
|
+
}
|
|
6983
|
+
}
|
|
6984
|
+
// fallback
|
|
6985
|
+
viewUtils.setViewFromFeature(viewRef.current, geojsonFeature);
|
|
6892
6986
|
}, [defaultBbox$1, geojsonFeature]);
|
|
6893
6987
|
return jsx("div", {
|
|
6988
|
+
ref: containerRef,
|
|
6894
6989
|
style: {
|
|
6895
6990
|
height: '200px',
|
|
6896
6991
|
width: '100%'
|
|
@@ -7198,18 +7293,18 @@ var WarningLevel;
|
|
|
7198
7293
|
var LevelColors = {
|
|
7199
7294
|
moderate: {
|
|
7200
7295
|
color: '#FAE21E',
|
|
7201
|
-
textColor: '#
|
|
7202
|
-
borderColor: '#
|
|
7296
|
+
textColor: '#3A3400',
|
|
7297
|
+
borderColor: '#A08F07'
|
|
7203
7298
|
},
|
|
7204
7299
|
severe: {
|
|
7205
7300
|
color: '#E27000',
|
|
7206
7301
|
textColor: '#051039',
|
|
7207
|
-
borderColor: '#
|
|
7302
|
+
borderColor: '#9C4D00'
|
|
7208
7303
|
},
|
|
7209
7304
|
extreme: {
|
|
7210
7305
|
color: '#D62A20',
|
|
7211
7306
|
textColor: '#ffffff',
|
|
7212
|
-
borderColor: '#
|
|
7307
|
+
borderColor: '#890101'
|
|
7213
7308
|
}
|
|
7214
7309
|
};
|
|
7215
7310
|
var getLevelStyle = function getLevelStyle(levelColor) {
|
|
@@ -7327,7 +7422,7 @@ var ProbabilityField = function ProbabilityField(_ref) {
|
|
|
7327
7422
|
var onChangeProbability = function onChangeProbability() {
|
|
7328
7423
|
void trigger('probability');
|
|
7329
7424
|
// We don't want to trigger the missing value validation
|
|
7330
|
-
if (!isEmpty(getValues('level'))) {
|
|
7425
|
+
if (!isEmpty$1(getValues('level'))) {
|
|
7331
7426
|
void trigger('level');
|
|
7332
7427
|
}
|
|
7333
7428
|
};
|
|
@@ -7436,7 +7531,7 @@ var _isMaxHoursAfterCurrentTime = function isMaxHoursAfterCurrentTime(value, t)
|
|
|
7436
7531
|
});
|
|
7437
7532
|
};
|
|
7438
7533
|
var _isMinHoursAfterValidFrom = function isMinHoursAfterValidFrom(value, validFromValue, t) {
|
|
7439
|
-
if (isEmpty(value) || isEmpty(validFromValue) || !dateUtils.isValidIsoDateString(validFromValue)) {
|
|
7534
|
+
if (isEmpty$1(value) || isEmpty$1(validFromValue) || !dateUtils.isValidIsoDateString(validFromValue)) {
|
|
7440
7535
|
return true;
|
|
7441
7536
|
}
|
|
7442
7537
|
var duration = dateUtils.differenceInHours(new Date(value), new Date(validFromValue));
|
|
@@ -14091,4 +14186,705 @@ ComponentsLookUpWrapper) {
|
|
|
14091
14186
|
}
|
|
14092
14187
|
};
|
|
14093
14188
|
|
|
14094
|
-
|
|
14189
|
+
/* *
|
|
14190
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
14191
|
+
* you may not use this file except in compliance with the License.
|
|
14192
|
+
* You may obtain a copy of the License at
|
|
14193
|
+
*
|
|
14194
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14195
|
+
*
|
|
14196
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14197
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14198
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14199
|
+
* See the License for the specific language governing permissions and
|
|
14200
|
+
* limitations under the License.
|
|
14201
|
+
*
|
|
14202
|
+
* Copyright 2026 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
|
|
14203
|
+
* Copyright 2026 - Finnish Meteorological Institute (FMI)
|
|
14204
|
+
* Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
|
|
14205
|
+
* */
|
|
14206
|
+
var draftStripes = function draftStripes(stripeColor, bgColor) {
|
|
14207
|
+
return "repeating-linear-gradient(\n -45deg,\n transparent,\n transparent 8px,\n " + stripeColor + " 8px,\n " + stripeColor + " 9px\n ), " + bgColor;
|
|
14208
|
+
};
|
|
14209
|
+
var TimelineColors = {
|
|
14210
|
+
// Public warnings - Extreme (Red)
|
|
14211
|
+
extreme: {
|
|
14212
|
+
published: {
|
|
14213
|
+
background: LevelColors.extreme.color,
|
|
14214
|
+
border: LevelColors.extreme.borderColor,
|
|
14215
|
+
iconColor: LevelColors.extreme.textColor,
|
|
14216
|
+
letterColor: LevelColors.extreme.textColor
|
|
14217
|
+
},
|
|
14218
|
+
draft: {
|
|
14219
|
+
background: '#F1D0D0',
|
|
14220
|
+
stripeColor: 'rgba(255, 255, 255, 0.5)',
|
|
14221
|
+
border: LevelColors.extreme.borderColor,
|
|
14222
|
+
iconColor: LevelColors.extreme.color,
|
|
14223
|
+
letterColor: LevelColors.extreme.color
|
|
14224
|
+
},
|
|
14225
|
+
expired: {
|
|
14226
|
+
background: '#EFEFEF',
|
|
14227
|
+
border: LevelColors.extreme.borderColor,
|
|
14228
|
+
iconColor: LevelColors.extreme.color,
|
|
14229
|
+
letterColor: LevelColors.extreme.color
|
|
14230
|
+
}
|
|
14231
|
+
},
|
|
14232
|
+
// Public warnings - Severe (Orange)
|
|
14233
|
+
severe: {
|
|
14234
|
+
published: {
|
|
14235
|
+
background: LevelColors.severe.color,
|
|
14236
|
+
border: LevelColors.severe.borderColor,
|
|
14237
|
+
iconColor: 'white',
|
|
14238
|
+
letterColor: 'white'
|
|
14239
|
+
},
|
|
14240
|
+
draft: {
|
|
14241
|
+
background: '#FADDC2',
|
|
14242
|
+
stripeColor: 'rgba(255, 255, 255, 0.5)',
|
|
14243
|
+
border: '#E27000',
|
|
14244
|
+
iconColor: '#9C4D00',
|
|
14245
|
+
letterColor: '#9C4D00'
|
|
14246
|
+
},
|
|
14247
|
+
expired: {
|
|
14248
|
+
background: '#EFEFEF',
|
|
14249
|
+
border: '#E27000',
|
|
14250
|
+
iconColor: '#9C4D00',
|
|
14251
|
+
letterColor: '#9C4D00'
|
|
14252
|
+
}
|
|
14253
|
+
},
|
|
14254
|
+
// Public warnings - Moderate (Yellow)
|
|
14255
|
+
moderate: {
|
|
14256
|
+
published: {
|
|
14257
|
+
background: LevelColors.moderate.color,
|
|
14258
|
+
border: LevelColors.moderate.borderColor,
|
|
14259
|
+
iconColor: '#3A3400',
|
|
14260
|
+
letterColor: '#3A3400'
|
|
14261
|
+
},
|
|
14262
|
+
draft: {
|
|
14263
|
+
background: '#FFFACE',
|
|
14264
|
+
stripeColor: 'rgba(250, 226, 28, 0.5)',
|
|
14265
|
+
// Yellow stripes
|
|
14266
|
+
border: LevelColors.moderate.borderColor,
|
|
14267
|
+
iconColor: '#3A3400',
|
|
14268
|
+
letterColor: '#3A3400'
|
|
14269
|
+
},
|
|
14270
|
+
expired: {
|
|
14271
|
+
background: '#EFEFEF',
|
|
14272
|
+
border: LevelColors.moderate.borderColor,
|
|
14273
|
+
iconColor: '#3A3400',
|
|
14274
|
+
letterColor: '#3A3400'
|
|
14275
|
+
}
|
|
14276
|
+
},
|
|
14277
|
+
// Aviation (SIGMET/AIRMET) - Blue
|
|
14278
|
+
aviation: {
|
|
14279
|
+
published: {
|
|
14280
|
+
background: '#186DFF',
|
|
14281
|
+
border: '#0800B9',
|
|
14282
|
+
iconColor: '#FFFFFF',
|
|
14283
|
+
letterColor: '#FFFFFF'
|
|
14284
|
+
},
|
|
14285
|
+
draft: {
|
|
14286
|
+
background: '#E3EDFF',
|
|
14287
|
+
stripeColor: 'rgba(255, 255, 255, 0.5)',
|
|
14288
|
+
border: '#0800B9',
|
|
14289
|
+
iconColor: '#0800B9',
|
|
14290
|
+
letterColor: '#0800B9'
|
|
14291
|
+
},
|
|
14292
|
+
expired: {
|
|
14293
|
+
background: '#EFEFEF',
|
|
14294
|
+
border: '#0800B9',
|
|
14295
|
+
iconColor: '#186DFF',
|
|
14296
|
+
letterColor: '#186DFF'
|
|
14297
|
+
}
|
|
14298
|
+
},
|
|
14299
|
+
// Default/fallback
|
|
14300
|
+
"default": {
|
|
14301
|
+
published: {
|
|
14302
|
+
background: '#FFFFFF',
|
|
14303
|
+
border: '#AAAAAA',
|
|
14304
|
+
iconColor: '#333333',
|
|
14305
|
+
letterColor: '#333333'
|
|
14306
|
+
},
|
|
14307
|
+
draft: {
|
|
14308
|
+
background: '#FFFFFF',
|
|
14309
|
+
stripeColor: 'rgba(255, 255, 255, 0.5)',
|
|
14310
|
+
border: '#AAAAAA',
|
|
14311
|
+
iconColor: '#333333',
|
|
14312
|
+
letterColor: '#333333'
|
|
14313
|
+
},
|
|
14314
|
+
expired: {
|
|
14315
|
+
background: '#EFEFEF',
|
|
14316
|
+
border: '#AAAAAA',
|
|
14317
|
+
iconColor: '#333333',
|
|
14318
|
+
letterColor: '#333333'
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
};
|
|
14322
|
+
var getThemeForLevel = function getThemeForLevel(level, isAviation) {
|
|
14323
|
+
if (isAviation) {
|
|
14324
|
+
return TimelineColors.aviation;
|
|
14325
|
+
}
|
|
14326
|
+
switch (level) {
|
|
14327
|
+
case WarningLevel.extreme:
|
|
14328
|
+
return TimelineColors.extreme;
|
|
14329
|
+
case WarningLevel.severe:
|
|
14330
|
+
return TimelineColors.severe;
|
|
14331
|
+
case WarningLevel.moderate:
|
|
14332
|
+
return TimelineColors.moderate;
|
|
14333
|
+
default:
|
|
14334
|
+
return TimelineColors["default"];
|
|
14335
|
+
}
|
|
14336
|
+
};
|
|
14337
|
+
var getBlockStyle = function getBlockStyle(level, status, isAviation) {
|
|
14338
|
+
var theme = getThemeForLevel(level, isAviation);
|
|
14339
|
+
if (status === PublicWarningStatus.DRAFT || status === PublicWarningStatus.DRAFT_PUBLISHED) {
|
|
14340
|
+
var _theme$draft = theme.draft,
|
|
14341
|
+
stripeColor = _theme$draft.stripeColor,
|
|
14342
|
+
background = _theme$draft.background,
|
|
14343
|
+
border = _theme$draft.border,
|
|
14344
|
+
iconColor = _theme$draft.iconColor,
|
|
14345
|
+
letterColor = _theme$draft.letterColor;
|
|
14346
|
+
return {
|
|
14347
|
+
background: draftStripes(stripeColor, background),
|
|
14348
|
+
border: "1px solid " + border,
|
|
14349
|
+
borderColor: border,
|
|
14350
|
+
iconColor: iconColor,
|
|
14351
|
+
letterColor: letterColor
|
|
14352
|
+
};
|
|
14353
|
+
}
|
|
14354
|
+
if (status === PublicWarningStatus.EXPIRED) {
|
|
14355
|
+
return {
|
|
14356
|
+
background: theme.expired.background,
|
|
14357
|
+
border: "1px solid " + theme.expired.border,
|
|
14358
|
+
borderColor: theme.expired.border,
|
|
14359
|
+
iconColor: theme.expired.iconColor,
|
|
14360
|
+
letterColor: theme.expired.letterColor
|
|
14361
|
+
};
|
|
14362
|
+
}
|
|
14363
|
+
// Published (default)
|
|
14364
|
+
return {
|
|
14365
|
+
background: theme.published.background,
|
|
14366
|
+
border: "1px solid " + theme.published.border,
|
|
14367
|
+
borderColor: theme.published.border,
|
|
14368
|
+
iconColor: theme.published.iconColor,
|
|
14369
|
+
letterColor: theme.published.letterColor
|
|
14370
|
+
};
|
|
14371
|
+
};
|
|
14372
|
+
|
|
14373
|
+
/* *
|
|
14374
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
14375
|
+
* you may not use this file except in compliance with the License.
|
|
14376
|
+
* You may obtain a copy of the License at
|
|
14377
|
+
*
|
|
14378
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14379
|
+
*
|
|
14380
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14381
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14382
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14383
|
+
* See the License for the specific language governing permissions and
|
|
14384
|
+
* limitations under the License.
|
|
14385
|
+
*
|
|
14386
|
+
* Copyright 2026 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
|
|
14387
|
+
* Copyright 2026 - Finnish Meteorological Institute (FMI)
|
|
14388
|
+
* Copyright 2026 - The Norwegian Meteorological Institute (MET Norway)
|
|
14389
|
+
* */
|
|
14390
|
+
var EDGE_PADDING = 24;
|
|
14391
|
+
var SIZE_THRESHOLDS = {
|
|
14392
|
+
xxs: 24,
|
|
14393
|
+
xs: 50,
|
|
14394
|
+
sm: 100
|
|
14395
|
+
};
|
|
14396
|
+
var getTimelineX = function getTimelineX(targetTime, timelineStart, timelineEnd, drawableWidth) {
|
|
14397
|
+
var totalTimelineDuration = timelineEnd.getTime() - timelineStart.getTime();
|
|
14398
|
+
if (totalTimelineDuration <= 0) {
|
|
14399
|
+
return 0;
|
|
14400
|
+
}
|
|
14401
|
+
var elapsedMs = targetTime.getTime() - timelineStart.getTime();
|
|
14402
|
+
return EDGE_PADDING + elapsedMs / totalTimelineDuration * drawableWidth;
|
|
14403
|
+
};
|
|
14404
|
+
var getTimeFromX = function getTimeFromX(x, timelineStart, timelineEnd, drawableWidth) {
|
|
14405
|
+
var totalTimelineDuration = timelineEnd.getTime() - timelineStart.getTime();
|
|
14406
|
+
if (drawableWidth <= 0) {
|
|
14407
|
+
return new Date(timelineStart);
|
|
14408
|
+
}
|
|
14409
|
+
var adjustedX = x - EDGE_PADDING;
|
|
14410
|
+
var ratio = adjustedX / drawableWidth;
|
|
14411
|
+
var timeMs = timelineStart.getTime() + ratio * totalTimelineDuration;
|
|
14412
|
+
return new Date(timeMs);
|
|
14413
|
+
};
|
|
14414
|
+
var generateTicks = function generateTicks(timelineStart, timelineEnd) {
|
|
14415
|
+
var ticks = [];
|
|
14416
|
+
var hourInterval = 3;
|
|
14417
|
+
var current = new Date(timelineStart);
|
|
14418
|
+
current.setUTCMinutes(0, 0, 0);
|
|
14419
|
+
if (current < timelineStart) {
|
|
14420
|
+
current.setUTCHours(current.getUTCHours() + 1);
|
|
14421
|
+
}
|
|
14422
|
+
while (current <= timelineEnd) {
|
|
14423
|
+
var hour = current.getUTCHours();
|
|
14424
|
+
if (hour === 0) {
|
|
14425
|
+
ticks.push({
|
|
14426
|
+
time: new Date(current),
|
|
14427
|
+
type: 'day'
|
|
14428
|
+
});
|
|
14429
|
+
} else if (hour % hourInterval === 0) {
|
|
14430
|
+
ticks.push({
|
|
14431
|
+
time: new Date(current),
|
|
14432
|
+
type: 'major'
|
|
14433
|
+
});
|
|
14434
|
+
} else {
|
|
14435
|
+
ticks.push({
|
|
14436
|
+
time: new Date(current),
|
|
14437
|
+
type: 'dashed'
|
|
14438
|
+
});
|
|
14439
|
+
}
|
|
14440
|
+
current.setUTCHours(current.getUTCHours() + 1);
|
|
14441
|
+
}
|
|
14442
|
+
return ticks;
|
|
14443
|
+
};
|
|
14444
|
+
var getTickLineStyle = function getTickLineStyle(tickType) {
|
|
14445
|
+
if (tickType === 'day') {
|
|
14446
|
+
return {
|
|
14447
|
+
width: '2px',
|
|
14448
|
+
borderLeft: '2px solid #ABC3FF'
|
|
14449
|
+
};
|
|
14450
|
+
}
|
|
14451
|
+
if (tickType === 'dashed') {
|
|
14452
|
+
return {
|
|
14453
|
+
width: '1px',
|
|
14454
|
+
borderLeft: '1px dashed #E7ECFA'
|
|
14455
|
+
};
|
|
14456
|
+
}
|
|
14457
|
+
return {
|
|
14458
|
+
width: '1px',
|
|
14459
|
+
borderLeft: '1px solid #90caf9'
|
|
14460
|
+
};
|
|
14461
|
+
};
|
|
14462
|
+
var getBlockSize = function getBlockSize(width) {
|
|
14463
|
+
if (width < SIZE_THRESHOLDS.xxs) {
|
|
14464
|
+
return 'xxs';
|
|
14465
|
+
}
|
|
14466
|
+
if (width < SIZE_THRESHOLDS.xs) {
|
|
14467
|
+
return 'xs';
|
|
14468
|
+
}
|
|
14469
|
+
if (width < SIZE_THRESHOLDS.sm) {
|
|
14470
|
+
return 's';
|
|
14471
|
+
}
|
|
14472
|
+
return 'l';
|
|
14473
|
+
};
|
|
14474
|
+
|
|
14475
|
+
/**
|
|
14476
|
+
* Gets the author/editor from a warning.
|
|
14477
|
+
* For airmet/sigmet warnings, author is in sigmetAirmetDetails.
|
|
14478
|
+
* For public/maritime warnings, editor is on the base warning.
|
|
14479
|
+
*/
|
|
14480
|
+
var getWarningAuthor = function getWarningAuthor(warning) {
|
|
14481
|
+
if ('sigmetAirmetDetails' in warning) {
|
|
14482
|
+
var _warning$sigmetAirmet, _warning$sigmetAirmet2;
|
|
14483
|
+
return (_warning$sigmetAirmet = (_warning$sigmetAirmet2 = warning.sigmetAirmetDetails) == null ? void 0 : _warning$sigmetAirmet2.author) != null ? _warning$sigmetAirmet : warning.editor;
|
|
14484
|
+
}
|
|
14485
|
+
return warning.editor;
|
|
14486
|
+
};
|
|
14487
|
+
var formatPeriod = function formatPeriod(from, until) {
|
|
14488
|
+
var ff = new Date(from);
|
|
14489
|
+
var uu = new Date(until);
|
|
14490
|
+
var dateOpts = {
|
|
14491
|
+
day: 'numeric',
|
|
14492
|
+
month: 'short',
|
|
14493
|
+
timeZone: 'UTC'
|
|
14494
|
+
};
|
|
14495
|
+
var timeOpts = {
|
|
14496
|
+
hour: '2-digit',
|
|
14497
|
+
minute: '2-digit',
|
|
14498
|
+
hour12: false,
|
|
14499
|
+
timeZone: 'UTC'
|
|
14500
|
+
};
|
|
14501
|
+
var fDate = ff.toLocaleDateString('en-GB', dateOpts);
|
|
14502
|
+
var uDate = uu.toLocaleDateString('en-GB', dateOpts);
|
|
14503
|
+
var fTime = ff.toLocaleTimeString('en-GB', timeOpts);
|
|
14504
|
+
var uTime = uu.toLocaleTimeString('en-GB', timeOpts);
|
|
14505
|
+
return fDate === uDate ? fDate + " " + fTime + " \u2013 " + uTime + " UTC" : fDate + " " + fTime + " \u2013 " + uDate + " " + uTime + " UTC";
|
|
14506
|
+
};
|
|
14507
|
+
var getTooltipContent = function getTooltipContent(warning, t) {
|
|
14508
|
+
var warningDetail = warning.warningDetail,
|
|
14509
|
+
status = warning.status,
|
|
14510
|
+
type = warning.type;
|
|
14511
|
+
var author = getWarningAuthor(warning);
|
|
14512
|
+
var isAviation = type === 'sigmet' || type === 'airmet';
|
|
14513
|
+
var phenomenonEntry = warningPhenomena.find(function (entry) {
|
|
14514
|
+
return entry.key === warningDetail.phenomenon;
|
|
14515
|
+
});
|
|
14516
|
+
var phenomenonLabel = phenomenonEntry ? t(phenomenonEntry.translationKey) : warningDetail.phenomenon;
|
|
14517
|
+
var line1 = isAviation ? [type.toUpperCase(), phenomenonLabel].filter(Boolean).join(' · ') : [phenomenonLabel, warningDetail.level, warningDetail.probability ? warningDetail.probability + "%" : null].filter(Boolean).join(' · ');
|
|
14518
|
+
var period = warningDetail.validFrom && warningDetail.validUntil ? formatPeriod(warningDetail.validFrom, warningDetail.validUntil) : null;
|
|
14519
|
+
var meta = [author, status].filter(Boolean).join(' · ');
|
|
14520
|
+
return jsxs(Box, {
|
|
14521
|
+
sx: {
|
|
14522
|
+
fontSize: 12,
|
|
14523
|
+
lineHeight: 1.6
|
|
14524
|
+
},
|
|
14525
|
+
children: [jsx(Box, {
|
|
14526
|
+
sx: {
|
|
14527
|
+
fontWeight: 600
|
|
14528
|
+
},
|
|
14529
|
+
children: line1
|
|
14530
|
+
}), period ? jsx(Box, {
|
|
14531
|
+
children: period
|
|
14532
|
+
}) : null, meta ? jsx(Box, {
|
|
14533
|
+
children: meta
|
|
14534
|
+
}) : null]
|
|
14535
|
+
});
|
|
14536
|
+
};
|
|
14537
|
+
var WarningBlock = function WarningBlock(_ref) {
|
|
14538
|
+
var warning = _ref.warning,
|
|
14539
|
+
left = _ref.left,
|
|
14540
|
+
top = _ref.top,
|
|
14541
|
+
width = _ref.width;
|
|
14542
|
+
var _useWarningsTranslati = useWarningsTranslation(),
|
|
14543
|
+
t = _useWarningsTranslati.t;
|
|
14544
|
+
var warningDetail = warning.warningDetail,
|
|
14545
|
+
status = warning.status,
|
|
14546
|
+
type = warning.type;
|
|
14547
|
+
var author = getWarningAuthor(warning);
|
|
14548
|
+
var isAviation = type === 'sigmet' || type === 'airmet';
|
|
14549
|
+
var level = warningDetail.level || null;
|
|
14550
|
+
var letter = level ? t("warning-level-letter-" + level) : '';
|
|
14551
|
+
var _getBlockStyle = getBlockStyle(level, status, isAviation),
|
|
14552
|
+
background = _getBlockStyle.background,
|
|
14553
|
+
border = _getBlockStyle.border,
|
|
14554
|
+
iconColor = _getBlockStyle.iconColor,
|
|
14555
|
+
letterColor = _getBlockStyle.letterColor;
|
|
14556
|
+
var size = getBlockSize(width);
|
|
14557
|
+
var elements = [];
|
|
14558
|
+
if (size === 's' || size === 'l') {
|
|
14559
|
+
elements.push(jsx(Box, {
|
|
14560
|
+
sx: {
|
|
14561
|
+
fontSize: 16,
|
|
14562
|
+
fontWeight: 600,
|
|
14563
|
+
lineHeight: '80%',
|
|
14564
|
+
color: letterColor
|
|
14565
|
+
},
|
|
14566
|
+
children: letter
|
|
14567
|
+
}, "letter"));
|
|
14568
|
+
}
|
|
14569
|
+
if (size !== 'xxs') {
|
|
14570
|
+
elements.push(jsx(Box, {
|
|
14571
|
+
sx: {
|
|
14572
|
+
display: 'flex',
|
|
14573
|
+
alignItems: 'center',
|
|
14574
|
+
justifyContent: 'center',
|
|
14575
|
+
color: iconColor,
|
|
14576
|
+
fontSize: 18
|
|
14577
|
+
},
|
|
14578
|
+
children: getPhenomenaIcon(warningDetail.phenomenon) || null
|
|
14579
|
+
}, "icon"));
|
|
14580
|
+
}
|
|
14581
|
+
if (size === 'l') {
|
|
14582
|
+
elements.push(jsx(Box, {
|
|
14583
|
+
sx: {
|
|
14584
|
+
border: '0.5px solid white',
|
|
14585
|
+
borderRadius: '50%'
|
|
14586
|
+
},
|
|
14587
|
+
children: jsx(WarningAvatar, {
|
|
14588
|
+
editor: author != null ? author : ''
|
|
14589
|
+
})
|
|
14590
|
+
}, "avatar"));
|
|
14591
|
+
}
|
|
14592
|
+
return jsx(Tooltip, {
|
|
14593
|
+
placement: "top",
|
|
14594
|
+
title: getTooltipContent(warning, t),
|
|
14595
|
+
children: jsx(Box, {
|
|
14596
|
+
"data-testid": "warning-block",
|
|
14597
|
+
sx: {
|
|
14598
|
+
position: 'absolute',
|
|
14599
|
+
left: left,
|
|
14600
|
+
top: top,
|
|
14601
|
+
width: width,
|
|
14602
|
+
height: 28,
|
|
14603
|
+
padding: '4px 8px',
|
|
14604
|
+
background: background,
|
|
14605
|
+
border: border,
|
|
14606
|
+
borderRadius: 1,
|
|
14607
|
+
display: 'flex',
|
|
14608
|
+
alignItems: 'center',
|
|
14609
|
+
justifyContent: elements.length === 1 ? 'center' : 'space-between',
|
|
14610
|
+
overflow: 'hidden'
|
|
14611
|
+
},
|
|
14612
|
+
children: elements
|
|
14613
|
+
})
|
|
14614
|
+
});
|
|
14615
|
+
};
|
|
14616
|
+
|
|
14617
|
+
var WARNING_BLOCK_HEIGHT = 34;
|
|
14618
|
+
var DEFAULT_VISIBLE_ROWS = 10;
|
|
14619
|
+
var TIMELINE_BAR_HEIGHT = 40;
|
|
14620
|
+
var PIXELS_PER_HOUR = 30;
|
|
14621
|
+
var MS_PER_HOUR = 60 * 60 * 1000;
|
|
14622
|
+
var MS_PER_DAY = 24 * MS_PER_HOUR;
|
|
14623
|
+
var WarningsTimeline = function WarningsTimeline(_ref) {
|
|
14624
|
+
var warnings = _ref.warnings;
|
|
14625
|
+
var timelineWarnings = React.useMemo(function () {
|
|
14626
|
+
var _warnings$filter;
|
|
14627
|
+
return (_warnings$filter = warnings == null ? void 0 : warnings.filter(function (warning) {
|
|
14628
|
+
return Boolean(warning.warningDetail.validFrom) && Boolean(warning.warningDetail.validUntil);
|
|
14629
|
+
})) != null ? _warnings$filter : [];
|
|
14630
|
+
}, [warnings]);
|
|
14631
|
+
var warningsAreaRef = React.useRef(null);
|
|
14632
|
+
var timeAxisRef = React.useRef(null);
|
|
14633
|
+
var _React$useState = React.useState(0),
|
|
14634
|
+
containerWidth = _React$useState[0],
|
|
14635
|
+
setContainerWidth = _React$useState[1];
|
|
14636
|
+
React.useEffect(function () {
|
|
14637
|
+
if (!warningsAreaRef.current) {
|
|
14638
|
+
return undefined;
|
|
14639
|
+
}
|
|
14640
|
+
var resizeObserver = new ResizeObserver(function (entries) {
|
|
14641
|
+
for (var _iterator = _createForOfIteratorHelperLoose(entries), _step; !(_step = _iterator()).done;) {
|
|
14642
|
+
var entry = _step.value;
|
|
14643
|
+
setContainerWidth(entry.contentRect.width);
|
|
14644
|
+
}
|
|
14645
|
+
});
|
|
14646
|
+
resizeObserver.observe(warningsAreaRef.current);
|
|
14647
|
+
return function () {
|
|
14648
|
+
return resizeObserver.disconnect();
|
|
14649
|
+
};
|
|
14650
|
+
}, []);
|
|
14651
|
+
var handleWarningsScroll = React.useCallback(function () {
|
|
14652
|
+
if (warningsAreaRef.current && timeAxisRef.current) {
|
|
14653
|
+
timeAxisRef.current.scrollLeft = warningsAreaRef.current.scrollLeft;
|
|
14654
|
+
}
|
|
14655
|
+
}, []);
|
|
14656
|
+
var _React$useState2 = React.useState(function () {
|
|
14657
|
+
return new Date();
|
|
14658
|
+
}),
|
|
14659
|
+
now = _React$useState2[0],
|
|
14660
|
+
setNow = _React$useState2[1];
|
|
14661
|
+
React.useEffect(function () {
|
|
14662
|
+
var id = setInterval(function () {
|
|
14663
|
+
return setNow(new Date());
|
|
14664
|
+
}, MS_PER_HOUR / 60);
|
|
14665
|
+
return function () {
|
|
14666
|
+
return clearInterval(id);
|
|
14667
|
+
};
|
|
14668
|
+
}, []);
|
|
14669
|
+
var _React$useMemo = React.useMemo(function () {
|
|
14670
|
+
var snapshotNow = new Date();
|
|
14671
|
+
var defaultStart = new Date(snapshotNow.getTime() - MS_PER_DAY);
|
|
14672
|
+
var defaultEnd = new Date(snapshotNow.getTime() + 3 * MS_PER_DAY);
|
|
14673
|
+
if (!timelineWarnings.length) {
|
|
14674
|
+
return {
|
|
14675
|
+
timelineStart: defaultStart,
|
|
14676
|
+
timelineEnd: defaultEnd
|
|
14677
|
+
};
|
|
14678
|
+
}
|
|
14679
|
+
var warningMin = Number.POSITIVE_INFINITY;
|
|
14680
|
+
var warningMax = Number.NEGATIVE_INFINITY;
|
|
14681
|
+
for (var _iterator2 = _createForOfIteratorHelperLoose(timelineWarnings), _step2; !(_step2 = _iterator2()).done;) {
|
|
14682
|
+
var warning = _step2.value;
|
|
14683
|
+
var _warning$warningDetai = warning.warningDetail,
|
|
14684
|
+
validFrom = _warning$warningDetai.validFrom,
|
|
14685
|
+
validUntil = _warning$warningDetai.validUntil;
|
|
14686
|
+
if (validFrom) {
|
|
14687
|
+
warningMin = Math.min(warningMin, new Date(validFrom).getTime());
|
|
14688
|
+
}
|
|
14689
|
+
if (validUntil) {
|
|
14690
|
+
warningMax = Math.max(warningMax, new Date(validUntil).getTime());
|
|
14691
|
+
}
|
|
14692
|
+
}
|
|
14693
|
+
// Floor earliest warning to previous 3-hour boundary, then subtract 3h to get some 'air'
|
|
14694
|
+
var warningStartDate = new Date(warningMin);
|
|
14695
|
+
warningStartDate.setUTCMinutes(0, 0, 0);
|
|
14696
|
+
var flooredHour = warningStartDate.getUTCHours() - warningStartDate.getUTCHours() % 3 - 3;
|
|
14697
|
+
warningStartDate.setUTCHours(flooredHour);
|
|
14698
|
+
var minTime = Math.min(defaultStart.getTime(), warningStartDate.getTime());
|
|
14699
|
+
// End is bound by the last warning
|
|
14700
|
+
return {
|
|
14701
|
+
timelineStart: new Date(minTime),
|
|
14702
|
+
timelineEnd: new Date(warningMax)
|
|
14703
|
+
};
|
|
14704
|
+
}, [timelineWarnings]),
|
|
14705
|
+
timelineStart = _React$useMemo.timelineStart,
|
|
14706
|
+
timelineEnd = _React$useMemo.timelineEnd;
|
|
14707
|
+
var totalMs = timelineEnd.getTime() - timelineStart.getTime();
|
|
14708
|
+
var totalHours = totalMs / MS_PER_HOUR;
|
|
14709
|
+
var contentWidth = Math.max(containerWidth, totalHours * PIXELS_PER_HOUR);
|
|
14710
|
+
var fullWidth = contentWidth + 2 * EDGE_PADDING;
|
|
14711
|
+
var ticks = generateTicks(timelineStart, timelineEnd);
|
|
14712
|
+
var _React$useState3 = React.useState(null),
|
|
14713
|
+
hoverTimelineX = _React$useState3[0],
|
|
14714
|
+
setHoverTimelineX = _React$useState3[1];
|
|
14715
|
+
var hoverTime = hoverTimelineX !== null ? getTimeFromX(hoverTimelineX, timelineStart, timelineEnd, contentWidth).toLocaleString('en-GB', {
|
|
14716
|
+
day: 'numeric',
|
|
14717
|
+
month: 'short',
|
|
14718
|
+
hour: '2-digit',
|
|
14719
|
+
minute: '2-digit',
|
|
14720
|
+
timeZone: 'UTC'
|
|
14721
|
+
}) + " UTC" : '';
|
|
14722
|
+
var handleTimeAxisMouseMove = React.useCallback(function (event) {
|
|
14723
|
+
var _timeAxisRef$current$, _timeAxisRef$current;
|
|
14724
|
+
var rect = event.currentTarget.getBoundingClientRect();
|
|
14725
|
+
// Only show tooltip when mouse is below the top 10px (away from scrollbar)
|
|
14726
|
+
if (event.clientY - rect.top < 10) {
|
|
14727
|
+
setHoverTimelineX(null);
|
|
14728
|
+
return;
|
|
14729
|
+
}
|
|
14730
|
+
setHoverTimelineX(event.clientX - rect.left + ((_timeAxisRef$current$ = (_timeAxisRef$current = timeAxisRef.current) == null ? void 0 : _timeAxisRef$current.scrollLeft) != null ? _timeAxisRef$current$ : 0));
|
|
14731
|
+
}, []);
|
|
14732
|
+
var handleTimeAxisMouseLeave = React.useCallback(function () {
|
|
14733
|
+
setHoverTimelineX(null);
|
|
14734
|
+
}, []);
|
|
14735
|
+
var currentTimeX = getTimelineX(now, timelineStart, timelineEnd, contentWidth);
|
|
14736
|
+
var showCurrentTime = now.getTime() >= timelineStart.getTime() && now.getTime() <= timelineEnd.getTime();
|
|
14737
|
+
return jsxs(Box$1, {
|
|
14738
|
+
sx: {
|
|
14739
|
+
width: '100%',
|
|
14740
|
+
height: '100%',
|
|
14741
|
+
display: 'flex',
|
|
14742
|
+
flexDirection: 'column'
|
|
14743
|
+
},
|
|
14744
|
+
children: [jsx(Box$1, {
|
|
14745
|
+
onScroll: handleWarningsScroll,
|
|
14746
|
+
ref: warningsAreaRef,
|
|
14747
|
+
sx: {
|
|
14748
|
+
flex: 1,
|
|
14749
|
+
overflow: 'auto',
|
|
14750
|
+
minHeight: 0
|
|
14751
|
+
},
|
|
14752
|
+
children: jsx(Box$1, {
|
|
14753
|
+
sx: {
|
|
14754
|
+
width: fullWidth,
|
|
14755
|
+
position: 'relative'
|
|
14756
|
+
},
|
|
14757
|
+
children: jsxs(Box$1, {
|
|
14758
|
+
sx: {
|
|
14759
|
+
position: 'relative',
|
|
14760
|
+
height: Math.max(timelineWarnings.length * WARNING_BLOCK_HEIGHT, DEFAULT_VISIBLE_ROWS * WARNING_BLOCK_HEIGHT)
|
|
14761
|
+
},
|
|
14762
|
+
children: [ticks.map(function (tick) {
|
|
14763
|
+
var x = getTimelineX(tick.time, timelineStart, timelineEnd, contentWidth);
|
|
14764
|
+
var lineStyle = getTickLineStyle(tick.type);
|
|
14765
|
+
return jsx(Box$1, {
|
|
14766
|
+
sx: Object.assign({
|
|
14767
|
+
position: 'absolute',
|
|
14768
|
+
left: x,
|
|
14769
|
+
top: 0,
|
|
14770
|
+
bottom: 0
|
|
14771
|
+
}, lineStyle)
|
|
14772
|
+
}, tick.time.toISOString());
|
|
14773
|
+
}), showCurrentTime ? jsx(Box$1, {
|
|
14774
|
+
sx: {
|
|
14775
|
+
position: 'absolute',
|
|
14776
|
+
left: currentTimeX,
|
|
14777
|
+
top: 0,
|
|
14778
|
+
bottom: 0,
|
|
14779
|
+
width: '3px',
|
|
14780
|
+
bgcolor: '#0051DD',
|
|
14781
|
+
zIndex: 10
|
|
14782
|
+
}
|
|
14783
|
+
}) : null, timelineWarnings.map(function (warning, index) {
|
|
14784
|
+
var warningDetail = warning.warningDetail;
|
|
14785
|
+
var validFrom = new Date(warningDetail.validFrom);
|
|
14786
|
+
var validUntil = new Date(warningDetail.validUntil);
|
|
14787
|
+
var left = getTimelineX(validFrom, timelineStart, timelineEnd, contentWidth);
|
|
14788
|
+
var right = getTimelineX(validUntil, timelineStart, timelineEnd, contentWidth);
|
|
14789
|
+
var blockWidth = Math.max(0, right - left);
|
|
14790
|
+
return jsx(WarningBlock, {
|
|
14791
|
+
left: left,
|
|
14792
|
+
top: index * WARNING_BLOCK_HEIGHT,
|
|
14793
|
+
warning: warning,
|
|
14794
|
+
width: blockWidth
|
|
14795
|
+
}, warning.id);
|
|
14796
|
+
})]
|
|
14797
|
+
})
|
|
14798
|
+
})
|
|
14799
|
+
}), jsx(Tooltip$1, {
|
|
14800
|
+
enterDelay: 150,
|
|
14801
|
+
followCursor: true,
|
|
14802
|
+
leaveDelay: 0,
|
|
14803
|
+
placement: "top",
|
|
14804
|
+
slotProps: {
|
|
14805
|
+
popper: {
|
|
14806
|
+
sx: {
|
|
14807
|
+
pointerEvents: 'none'
|
|
14808
|
+
}
|
|
14809
|
+
}
|
|
14810
|
+
},
|
|
14811
|
+
title: hoverTime,
|
|
14812
|
+
children: jsx(Box$1, {
|
|
14813
|
+
onMouseLeave: handleTimeAxisMouseLeave,
|
|
14814
|
+
onMouseMove: handleTimeAxisMouseMove,
|
|
14815
|
+
ref: timeAxisRef,
|
|
14816
|
+
sx: {
|
|
14817
|
+
height: TIMELINE_BAR_HEIGHT,
|
|
14818
|
+
overflow: 'hidden',
|
|
14819
|
+
borderTop: '1px solid #ccc'
|
|
14820
|
+
},
|
|
14821
|
+
children: jsx(Box$1, {
|
|
14822
|
+
sx: {
|
|
14823
|
+
width: fullWidth,
|
|
14824
|
+
position: 'relative',
|
|
14825
|
+
height: '100%'
|
|
14826
|
+
},
|
|
14827
|
+
children: ticks.filter(function (tick) {
|
|
14828
|
+
return tick.type === 'day' || tick.time.getUTCHours() % 3 === 0;
|
|
14829
|
+
}).map(function (tick) {
|
|
14830
|
+
var x = getTimelineX(tick.time, timelineStart, timelineEnd, contentWidth);
|
|
14831
|
+
var hour = tick.time.getUTCHours();
|
|
14832
|
+
var hourLabel = String(hour).padStart(2, '0') + ":00";
|
|
14833
|
+
var isDayBoundary = tick.type === 'day';
|
|
14834
|
+
var dateStr = tick.time.toLocaleDateString('en-GB', {
|
|
14835
|
+
day: 'numeric',
|
|
14836
|
+
month: 'short',
|
|
14837
|
+
timeZone: 'UTC'
|
|
14838
|
+
});
|
|
14839
|
+
return jsxs(Box$1, {
|
|
14840
|
+
sx: {
|
|
14841
|
+
position: 'absolute',
|
|
14842
|
+
left: x,
|
|
14843
|
+
top: 2,
|
|
14844
|
+
transform: 'translateX(-50%)',
|
|
14845
|
+
textAlign: 'center',
|
|
14846
|
+
lineHeight: 1.1
|
|
14847
|
+
},
|
|
14848
|
+
children: [jsx(Box$1, {
|
|
14849
|
+
component: "span",
|
|
14850
|
+
sx: {
|
|
14851
|
+
fontSize: isDayBoundary ? 14 : 12,
|
|
14852
|
+
fontWeight: isDayBoundary ? 'bold' : 'normal',
|
|
14853
|
+
color: isDayBoundary ? '#333' : '#666'
|
|
14854
|
+
},
|
|
14855
|
+
children: hourLabel
|
|
14856
|
+
}), isDayBoundary ? jsx(Box$1, {
|
|
14857
|
+
sx: {
|
|
14858
|
+
fontSize: 12,
|
|
14859
|
+
color: '#666'
|
|
14860
|
+
},
|
|
14861
|
+
children: dateStr
|
|
14862
|
+
}) : null]
|
|
14863
|
+
}, "label-" + tick.time.toISOString());
|
|
14864
|
+
})
|
|
14865
|
+
})
|
|
14866
|
+
})
|
|
14867
|
+
})]
|
|
14868
|
+
});
|
|
14869
|
+
};
|
|
14870
|
+
|
|
14871
|
+
var WarningsTimelineConnect = function WarningsTimelineConnect(_ref) {
|
|
14872
|
+
_ref.panelId;
|
|
14873
|
+
var _useWarningsTranslati = useWarningsTranslation(),
|
|
14874
|
+
t = _useWarningsTranslati.t;
|
|
14875
|
+
var _useAuthenticationCon = useAuthenticationContext$1(),
|
|
14876
|
+
isLoggedIn = _useAuthenticationCon.isLoggedIn;
|
|
14877
|
+
var warnings = [];
|
|
14878
|
+
if (!isLoggedIn) {
|
|
14879
|
+
return jsx(AlertBanner, {
|
|
14880
|
+
dataTestId: "warnings-timeline-auth-error",
|
|
14881
|
+
severity: "error",
|
|
14882
|
+
title: t('error-auth-login')
|
|
14883
|
+
});
|
|
14884
|
+
}
|
|
14885
|
+
return jsx(WarningsTimeline, {
|
|
14886
|
+
warnings: warnings
|
|
14887
|
+
});
|
|
14888
|
+
};
|
|
14889
|
+
|
|
14890
|
+
export { DrawingToolConnect, Wrapper as DrawingToolForm, DrawingToolFormConnect, DrawingToolMapButtonConnect, ObjectManagerConnect, ObjectManagerMapButtonConnect, PublicWarningsFormDialog, PublicWarningsFormDialogConnect, WARN_NAMESPACE, WarningsTimeline, WarningsTimelineConnect, componentsLookUp, createMockStore, isAlreadyEdited, selectors as publicWarningsSelectors, useObjectDrawDialogAction, warningFormConfirmationOptions, warningsDrawingsActions, warningsDrawingsReducer, warningsFiltersActions, warningsFiltersReducer, warningsFormActions, warningsFormListener, warningsFormReducer, warningsMiddlewares, warningsReducersMap, warningsTranslations };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/warnings",
|
|
3
|
-
"version": "15.
|
|
3
|
+
"version": "15.3.0",
|
|
4
4
|
"description": "GeoWeb warinings 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.
|
|
12
|
-
"@opengeoweb/shared": "15.
|
|
13
|
-
"@opengeoweb/store": "15.
|
|
14
|
-
"@opengeoweb/webmap-react": "15.
|
|
11
|
+
"@opengeoweb/api": "15.3.0",
|
|
12
|
+
"@opengeoweb/shared": "15.3.0",
|
|
13
|
+
"@opengeoweb/store": "15.3.0",
|
|
14
|
+
"@opengeoweb/webmap-react": "15.3.0",
|
|
15
15
|
"@tanstack/react-query": "^5.85.5",
|
|
16
16
|
"react-redux": "^9.2.0",
|
|
17
|
-
"@opengeoweb/theme": "15.
|
|
18
|
-
"@opengeoweb/form-fields": "15.
|
|
17
|
+
"@opengeoweb/theme": "15.3.0",
|
|
18
|
+
"@opengeoweb/form-fields": "15.3.0",
|
|
19
19
|
"react-hook-form": "^7.50.1",
|
|
20
20
|
"lodash": "^4.17.21",
|
|
21
21
|
"@reduxjs/toolkit": "^2.6.1",
|
|
22
|
-
"@opengeoweb/snackbar": "15.
|
|
22
|
+
"@opengeoweb/snackbar": "15.3.0",
|
|
23
23
|
"react-window": "^2.2.6",
|
|
24
24
|
"axios": "^1.7.7",
|
|
25
|
-
"@opengeoweb/core": "15.
|
|
26
|
-
"@opengeoweb/webmap": "15.
|
|
27
|
-
"@opengeoweb/authentication": "15.
|
|
28
|
-
"@opengeoweb/sigmet-airmet": "15.
|
|
25
|
+
"@opengeoweb/core": "15.3.0",
|
|
26
|
+
"@opengeoweb/webmap": "15.3.0",
|
|
27
|
+
"@opengeoweb/authentication": "15.3.0",
|
|
28
|
+
"@opengeoweb/sigmet-airmet": "15.3.0",
|
|
29
29
|
"react-i18next": "^15.1.1",
|
|
30
30
|
"i18next": "^25.0.1",
|
|
31
31
|
"@mui/material": "^7.0.1",
|
package/src/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './lib/components/DrawingTool';
|
|
|
4
4
|
export * from './lib/components/DrawingToolForm';
|
|
5
5
|
export * from './lib/components/PublicWarningsFormDialog';
|
|
6
6
|
export * from './lib/components/ComponentsLookUp';
|
|
7
|
+
export * from './lib/components/WarningsTimeline';
|
|
7
8
|
export * from './lib/store';
|
|
8
9
|
export { WARN_NAMESPACE } from './lib/utils/i18n';
|
|
9
10
|
export { warningsTranslations };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FeatureCollection } from 'geojson';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import type { MapPreset } from '@opengeoweb/store';
|
|
4
|
+
export declare const EXTENT_PADDING = 50;
|
|
4
5
|
interface WarningsMapViewProps {
|
|
5
6
|
geojsonFeature?: FeatureCollection | undefined;
|
|
6
7
|
defaultMapPreset?: MapPreset;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Warning } from '../../store/warningsForm/types';
|
|
3
|
+
interface WarningBlockProps {
|
|
4
|
+
warning: Warning;
|
|
5
|
+
left: number;
|
|
6
|
+
top: number;
|
|
7
|
+
width: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const WarningBlock: React.FC<WarningBlockProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
import { WarningsTimeline } from './WarningsTimeline';
|
|
3
|
+
declare const _default: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: import("react").FC<import("./WarningsTimeline").WarningsTimelineProps>;
|
|
6
|
+
tags: string[];
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
|
9
|
+
type Story = StoryObj<typeof WarningsTimeline>;
|
|
10
|
+
export declare const ShortRange: Story;
|
|
11
|
+
export declare const LongRange: Story;
|
|
12
|
+
export declare const NoWarnings: Story;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PublicWarningStatus } from '../../store/warningsForm/types';
|
|
2
|
+
import { WarningLevel } from '../PublicWarningsForm/LevelField';
|
|
3
|
+
/**
|
|
4
|
+
* Timeline Block Color Theme
|
|
5
|
+
*
|
|
6
|
+
* Organized by warning type (public warnings by level, aviation)
|
|
7
|
+
* Each type has colors for each status: published, draft, expired
|
|
8
|
+
*/
|
|
9
|
+
export interface BlockStyle {
|
|
10
|
+
background: string;
|
|
11
|
+
border: string;
|
|
12
|
+
borderColor: string;
|
|
13
|
+
iconColor: string;
|
|
14
|
+
letterColor: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const getBlockStyle: (level: WarningLevel | null, status: PublicWarningStatus | undefined, isAviation: boolean) => BlockStyle;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const EDGE_PADDING = 24;
|
|
2
|
+
export type TickType = 'day' | 'major' | 'dashed';
|
|
3
|
+
export interface Tick {
|
|
4
|
+
time: Date;
|
|
5
|
+
type: TickType;
|
|
6
|
+
}
|
|
7
|
+
export type BlockSize = 'xxs' | 'xs' | 's' | 'l';
|
|
8
|
+
export declare const getTimelineX: (targetTime: Date, timelineStart: Date, timelineEnd: Date, drawableWidth: number) => number;
|
|
9
|
+
export declare const getTimeFromX: (x: number, timelineStart: Date, timelineEnd: Date, drawableWidth: number) => Date;
|
|
10
|
+
export declare const generateTicks: (timelineStart: Date, timelineEnd: Date) => Tick[];
|
|
11
|
+
export declare const getTickLineStyle: (tickType: TickType) => {
|
|
12
|
+
width: string;
|
|
13
|
+
borderLeft: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const getBlockSize: (width: number) => BlockSize;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|