@opengeoweb/warnings 9.15.0 → 9.16.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 CHANGED
@@ -1,212 +1,26 @@
1
1
  import * as React from 'react';
2
- import React__default, { useState, useEffect } from 'react';
2
+ import React__default, { useState, useEffect, useRef } from 'react';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
- import { Polygons, Share, ExitDomain, Edit, Delete, ThemeWrapper, lightTheme, DrawPolygon, Visibility, Add, Wind, Fog, Lightning, Snow, Rain, TemperatureHigh, TemperatureLow, CoastalEvent, breakpoints, Options, VisibilityOff, Success } from '@opengeoweb/theme';
5
- import { uiTypes, uiActions, getSingularDrawtoolDrawLayerId, drawtoolSelectors, layerSelectors, uiSelectors, mapStoreActions, drawtoolActions, layerActions, useSetupDialog, coreModuleConfig } from '@opengeoweb/store';
4
+ import { Polygons, Share, ExitDomain, Edit, Delete, DrawPolygon, Visibility, Add, Wind, Fog, Lightning, Snow, Rain, TemperatureHigh, TemperatureLow, CoastalEvent, breakpoints, Options, VisibilityOff, Success } from '@opengeoweb/theme';
5
+ import { uiTypes, uiActions, getSingularDrawtoolDrawLayerId, drawtoolSelectors, layerSelectors, uiSelectors, mapStoreActions, drawtoolActions, layerActions, useSetupDialog } from '@opengeoweb/store';
6
6
  import { emptyGeoJSON, MapControlButton, getIcon, rewindGeometry, getGeoJSONPropertyValue, currentlySupportedDrawModes, MapView, MapViewLayer, defaultLayers, getFeatureExtent } from '@opengeoweb/webmap-react';
7
- import { handleOutsideComponentTranslations, useConfirmationDialog, ToggleMenu, dateUtils, calculateStartSize, ToolContainerDraggable, AlertBanner, ConfirmationDialog, getAxiosErrorMessage, pollingIntervalTimeout, isAxiosError as isAxiosError$1, withEggs, usePrevious, CustomIconButton, CustomTooltip, Avatar, getInitials, SwitchButton, LastUpdateTime, StatusTag, ErrorBoundary } from '@opengeoweb/shared';
8
- import { initReactI18next, useTranslation, I18nextProvider } from 'react-i18next';
9
- import { createEntityAdapter, createSlice, createSelector, createListenerMiddleware } from '@reduxjs/toolkit';
10
- import i18n from 'i18next';
7
+ import { handleOutsideComponentTranslations, useConfirmationDialog, ToggleMenu, dateUtils, calculateStartSize, ToolContainerDraggable, AlertBanner, ConfirmationDialog, getAxiosErrorMessage, usePrevious, CustomIconButton, CustomTooltip, Avatar, getInitials, SwitchButton, LastUpdateTime, StatusTag, ErrorBoundary, pollingIntervalTimeout, isAxiosError as isAxiosError$1 } from '@opengeoweb/shared';
8
+ import { useTranslation } from 'react-i18next';
9
+ import { createEntityAdapter, createSlice, createSelector, createListenerMiddleware, isAnyOf } from '@reduxjs/toolkit';
10
+ import 'i18next';
11
11
  import { snackbarActions } from '@opengeoweb/snackbar';
12
12
  import { styled, Box, Typography, ListItem, Grid, Paper, ListItemButton, Stack, LinearProgress, Button, FormHelperText, MenuItem, Tabs, Tab, FormControl, Card, CardContent, ListItemIcon, CircularProgress, List } from '@mui/material';
13
13
  import { VariableSizeList } from 'react-window';
14
14
  import AutoSizer from 'react-virtualized-auto-sizer';
15
15
  import { DATE_FORMAT_FNS, ReactHookFormHiddenInput, isValidGeoJsonCoordinates, ReactHookFormSelect, ReactHookFormTextField, ReactHookFormProvider, defaultFormOptions, useDraftFormHelpers, errorMessages, ReactHookFormDateTime, isValidDate, isXHoursBefore, isXHoursAfter, isEmpty } from '@opengeoweb/form-fields';
16
16
  import { getApi, createApiInstance, createNonAuthApiInstance, createFakeApiInstance, ApiProvider } from '@opengeoweb/api';
17
- import { createStore } from '@redux-eggs/redux-toolkit';
18
- import { useAuthenticationContext } from '@opengeoweb/authentication';
19
- import { takeLatest, call as call$c, put, select, delay } from 'redux-saga/effects';
20
- import { isAxiosError } from 'axios';
21
17
  import { useFormContext } from 'react-hook-form';
22
18
  import { isEqual, cloneDeep, clamp } from 'lodash';
19
+ import { useAuthenticationContext } from '@opengeoweb/authentication';
23
20
  import { produce } from 'immer';
24
21
  import { generateMapId, LayerType, getWMJSMapById, WMBBOX } from '@opengeoweb/webmap';
25
22
  import { defaultBbox } from '@opengeoweb/core';
26
-
27
- /******************************************************************************
28
- Copyright (c) Microsoft Corporation.
29
-
30
- Permission to use, copy, modify, and/or distribute this software for any
31
- purpose with or without fee is hereby granted.
32
-
33
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
34
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
35
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
36
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
37
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
38
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39
- PERFORMANCE OF THIS SOFTWARE.
40
- ***************************************************************************** */
41
-
42
- function __rest(s, e) {
43
- var t = {};
44
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
45
- t[p] = s[p];
46
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
47
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
48
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
49
- t[p[i]] = s[p[i]];
50
- }
51
- return t;
52
- }
53
-
54
- function __awaiter(thisArg, _arguments, P, generator) {
55
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
56
- return new (P || (P = Promise))(function (resolve, reject) {
57
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
58
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
59
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
60
- step((generator = generator.apply(thisArg, _arguments || [])).next());
61
- });
62
- }
63
-
64
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
65
- var e = new Error(message);
66
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
67
- };
68
-
69
- /* *
70
- * Licensed under the Apache License, Version 2.0 (the "License");
71
- * you may not use this file except in compliance with the License.
72
- * You may obtain a copy of the License at
73
- *
74
- * http://www.apache.org/licenses/LICENSE-2.0
75
- *
76
- * Unless required by applicable law or agreed to in writing, software
77
- * distributed under the License is distributed on an "AS IS" BASIS,
78
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79
- * See the License for the specific language governing permissions and
80
- * limitations under the License.
81
- *
82
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
83
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
84
- * */
85
- const objectDialogType = uiTypes.DialogTypes.ObjectManager;
86
- const drawingDialogType = uiTypes.DialogTypes.DrawingTool;
87
-
88
- /* *
89
- * Licensed under the Apache License, Version 2.0 (the "License");
90
- * you may not use this file except in compliance with the License.
91
- * You may obtain a copy of the License at
92
- *
93
- * http://www.apache.org/licenses/LICENSE-2.0
94
- *
95
- * Unless required by applicable law or agreed to in writing, software
96
- * distributed under the License is distributed on an "AS IS" BASIS,
97
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
98
- * See the License for the specific language governing permissions and
99
- * limitations under the License.
100
- *
101
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
102
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
103
- * */
104
- const drawAdapter = createEntityAdapter({
105
- selectId: draw => draw.drawingInstanceId
106
- });
107
- const initialState$2 = drawAdapter.getInitialState();
108
- const slice$2 = createSlice({
109
- initialState: initialState$2,
110
- name: 'drawingForm',
111
- reducers: {
112
- setDrawValues: (draft, action) => {
113
- if (draft.entities[action.payload.drawingInstanceId]) {
114
- drawAdapter.setOne(draft, action.payload);
115
- }
116
- },
117
- // action caught in drawings/listener
118
- submitDrawValues: (
119
- // eslint-disable-next-line no-unused-vars
120
- draft,
121
- // eslint-disable-next-line no-unused-vars
122
- action) => {},
123
- setFormDirty: (draft, action) => {
124
- const {
125
- drawingInstanceId,
126
- isFormDirty
127
- } = action.payload;
128
- if (draft.entities[drawingInstanceId]) {
129
- drawAdapter.updateOne(draft, {
130
- id: drawingInstanceId,
131
- changes: {
132
- isFormDirty
133
- }
134
- });
135
- }
136
- }
137
- },
138
- extraReducers: builder => {
139
- builder
140
- // register draw dialog
141
- .addCase(uiActions.registerDialog, (draft, action) => {
142
- const {
143
- type
144
- } = action.payload;
145
- if (type === drawingDialogType) {
146
- drawAdapter.addOne(draft, {
147
- drawingInstanceId: type,
148
- objectName: '',
149
- id: ''
150
- });
151
- }
152
- })
153
- // unregister draw dialog
154
- .addCase(uiActions.unregisterDialog, (draft, action) => {
155
- const {
156
- type
157
- } = action.payload;
158
- if (type === drawingDialogType) {
159
- drawAdapter.removeOne(draft, type);
160
- }
161
- })
162
- // reset draw dialog formDirty when dialog closes
163
- .addCase(uiActions.setActiveMapIdForDialog, (draft, action) => {
164
- const {
165
- type,
166
- setOpen
167
- } = action.payload;
168
- if (type === drawingDialogType && !setOpen) {
169
- drawAdapter.updateOne(draft, {
170
- id: type,
171
- changes: {
172
- isFormDirty: false
173
- }
174
- });
175
- }
176
- });
177
- }
178
- });
179
- const {
180
- reducer: reducer$2
181
- } = slice$2;
182
- const drawActions = slice$2.actions;
183
-
184
- /* *
185
- * Licensed under the Apache License, Version 2.0 (the "License");
186
- * you may not use this file except in compliance with the License.
187
- * You may obtain a copy of the License at
188
- *
189
- * http://www.apache.org/licenses/LICENSE-2.0
190
- *
191
- * Unless required by applicable law or agreed to in writing, software
192
- * distributed under the License is distributed on an "AS IS" BASIS,
193
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
194
- * See the License for the specific language governing permissions and
195
- * limitations under the License.
196
- *
197
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
198
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
199
- * */
200
- const {
201
- selectById: selectDrawByInstanceId
202
- } = drawAdapter.getSelectors(state => {
203
- var _a;
204
- return (_a = state === null || state === void 0 ? void 0 : state.drawings) !== null && _a !== void 0 ? _a : {
205
- entities: {},
206
- ids: []
207
- };
208
- });
209
- const getWarningFormDirty = createSelector(selectDrawByInstanceId, drawing => (drawing === null || drawing === void 0 ? void 0 : drawing.isFormDirty) || false);
23
+ import { isAxiosError } from 'axios';
210
24
 
211
25
  var en = {
212
26
  "drawing-tool-form-tools": "Tools",
@@ -273,6 +87,7 @@ var en = {
273
87
  "warning-phenomenon-low-temp": "Low temperature",
274
88
  "warning-phenomenon-funnel-cloud": "Funnel cloud",
275
89
  "warning-phenomenon-coastal-event": "Coastal event",
90
+ "warning-probability-moderate-level-invalid": "Probability should be at least 30% when level is moderate",
276
91
  "warning-valid-from": "Valid from",
277
92
  "warning-valid-until": "Valid until",
278
93
  "warning-valid-from-error-before-current": "Valid from time cannot be before current time",
@@ -376,6 +191,7 @@ var nl = {
376
191
  "warning-phenomenon-low-temp": "Koude",
377
192
  "warning-phenomenon-funnel-cloud": "Hozen",
378
193
  "warning-phenomenon-coastal-event": "Kust incident",
194
+ "warning-probability-moderate-level-invalid": "Waarschijnlijkheid moet tenminste 30% zijn als Niveau Gematigd is",
379
195
  "warning-valid-from": "Geldig vanaf",
380
196
  "warning-valid-until": "Geldig tot",
381
197
  "warning-valid-from-error-before-current": "Starttijd mag niet eerder zijn dan huidige tijd",
@@ -479,6 +295,7 @@ var fi = {
479
295
  "warning-phenomenon-low-temp": "ei käännetty",
480
296
  "warning-phenomenon-funnel-cloud": "ei käännetty",
481
297
  "warning-phenomenon-coastal-event": "ei käännetty",
298
+ "warning-probability-moderate-level-invalid": "ei käännetty",
482
299
  "warning-valid-from": "ei käännetty",
483
300
  "warning-valid-until": "ei käännetty",
484
301
  "warning-valid-from-error-before-current": "ei käännetty",
@@ -582,6 +399,7 @@ var no = {
582
399
  "warning-phenomenon-low-temp": "ikke oversatt",
583
400
  "warning-phenomenon-funnel-cloud": "ikke oversatt",
584
401
  "warning-phenomenon-coastal-event": "ikke oversatt",
402
+ "warning-probability-moderate-level-invalid": "ikke oversatt",
585
403
  "warning-valid-from": "ikke oversatt",
586
404
  "warning-valid-until": "ikke oversatt",
587
405
  "warning-valid-from-error-before-current": "ikke oversatt",
@@ -627,6 +445,48 @@ var warningsTranslations = {
627
445
  no: no
628
446
  };
629
447
 
448
+ /******************************************************************************
449
+ Copyright (c) Microsoft Corporation.
450
+
451
+ Permission to use, copy, modify, and/or distribute this software for any
452
+ purpose with or without fee is hereby granted.
453
+
454
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
455
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
456
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
457
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
458
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
459
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
460
+ PERFORMANCE OF THIS SOFTWARE.
461
+ ***************************************************************************** */
462
+
463
+ function __rest(s, e) {
464
+ var t = {};
465
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
466
+ t[p] = s[p];
467
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
468
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
469
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
470
+ t[p[i]] = s[p[i]];
471
+ }
472
+ return t;
473
+ }
474
+
475
+ function __awaiter(thisArg, _arguments, P, generator) {
476
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
477
+ return new (P || (P = Promise))(function (resolve, reject) {
478
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
479
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
480
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
481
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
482
+ });
483
+ }
484
+
485
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
486
+ var e = new Error(message);
487
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
488
+ };
489
+
630
490
  /* *
631
491
  * Licensed under the Apache License, Version 2.0 (the "License");
632
492
  * you may not use this file except in compliance with the License.
@@ -643,32 +503,8 @@ var warningsTranslations = {
643
503
  * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
644
504
  * Copyright 2023 - Finnish Meteorological Institute (FMI)
645
505
  * */
646
- const WARN_NAMESPACE = 'warn';
647
- const defaultLanguage = 'en';
648
- const initWarnI18n = () => {
649
- i18n.use(initReactI18next).init({
650
- lng: defaultLanguage,
651
- ns: WARN_NAMESPACE,
652
- interpolation: {
653
- escapeValue: false
654
- },
655
- resources: {
656
- en: {
657
- [`${WARN_NAMESPACE}`]: warningsTranslations.en
658
- },
659
- nl: {
660
- [`${WARN_NAMESPACE}`]: warningsTranslations.nl
661
- },
662
- fi: {
663
- [`${WARN_NAMESPACE}`]: warningsTranslations.fi
664
- },
665
- no: {
666
- [`${WARN_NAMESPACE}`]: warningsTranslations.no
667
- }
668
- }
669
- });
670
- };
671
- const outsideComponentTranslations = handleOutsideComponentTranslations(warningsTranslations, WARN_NAMESPACE);
506
+ const objectDialogType = uiTypes.DialogTypes.ObjectManager;
507
+ const drawingDialogType = uiTypes.DialogTypes.DrawingTool;
672
508
 
673
509
  /* *
674
510
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -686,19 +522,161 @@ const outsideComponentTranslations = handleOutsideComponentTranslations(warnings
686
522
  * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
687
523
  * Copyright 2023 - Finnish Meteorological Institute (FMI)
688
524
  * */
689
- const confirmationDialogOptions = t => {
690
- return {
691
- cancelLabel: t('close-dialog-cancel'),
692
- title: t('close-draw-dialog-title'),
693
- description: t('close-dialog-description'),
694
- confirmLabel: t('close-dialog-confirm'),
695
- catchOnCancel: true
696
- };
697
- };
698
- const useCloseDrawDialog = ({
699
- mapId,
700
- source
701
- }) => {
525
+ const drawAdapter = createEntityAdapter({
526
+ selectId: draw => draw.drawingInstanceId
527
+ });
528
+ const initialState$2 = drawAdapter.getInitialState();
529
+ const slice$2 = createSlice({
530
+ initialState: initialState$2,
531
+ name: 'drawingForm',
532
+ reducers: {
533
+ setDrawValues: (draft, action) => {
534
+ if (draft.entities[action.payload.drawingInstanceId]) {
535
+ drawAdapter.setOne(draft, action.payload);
536
+ }
537
+ },
538
+ // action caught in drawings/listener
539
+ submitDrawValues: (
540
+ // eslint-disable-next-line no-unused-vars
541
+ draft,
542
+ // eslint-disable-next-line no-unused-vars
543
+ action) => {},
544
+ setFormDirty: (draft, action) => {
545
+ const {
546
+ drawingInstanceId,
547
+ isFormDirty
548
+ } = action.payload;
549
+ if (draft.entities[drawingInstanceId]) {
550
+ drawAdapter.updateOne(draft, {
551
+ id: drawingInstanceId,
552
+ changes: {
553
+ isFormDirty
554
+ }
555
+ });
556
+ }
557
+ }
558
+ },
559
+ extraReducers: builder => {
560
+ builder
561
+ // register draw dialog
562
+ .addCase(uiActions.registerDialog, (draft, action) => {
563
+ const {
564
+ type
565
+ } = action.payload;
566
+ if (type === drawingDialogType) {
567
+ drawAdapter.addOne(draft, {
568
+ drawingInstanceId: type,
569
+ objectName: '',
570
+ id: ''
571
+ });
572
+ }
573
+ })
574
+ // unregister draw dialog
575
+ .addCase(uiActions.unregisterDialog, (draft, action) => {
576
+ const {
577
+ type
578
+ } = action.payload;
579
+ if (type === drawingDialogType) {
580
+ drawAdapter.removeOne(draft, type);
581
+ }
582
+ })
583
+ // reset draw dialog formDirty when dialog closes
584
+ .addCase(uiActions.setActiveMapIdForDialog, (draft, action) => {
585
+ const {
586
+ type,
587
+ setOpen
588
+ } = action.payload;
589
+ if (type === drawingDialogType && !setOpen) {
590
+ drawAdapter.updateOne(draft, {
591
+ id: type,
592
+ changes: {
593
+ isFormDirty: false
594
+ }
595
+ });
596
+ }
597
+ });
598
+ }
599
+ });
600
+ const {
601
+ reducer: reducer$2
602
+ } = slice$2;
603
+ const drawActions = slice$2.actions;
604
+
605
+ /* *
606
+ * Licensed under the Apache License, Version 2.0 (the "License");
607
+ * you may not use this file except in compliance with the License.
608
+ * You may obtain a copy of the License at
609
+ *
610
+ * http://www.apache.org/licenses/LICENSE-2.0
611
+ *
612
+ * Unless required by applicable law or agreed to in writing, software
613
+ * distributed under the License is distributed on an "AS IS" BASIS,
614
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
615
+ * See the License for the specific language governing permissions and
616
+ * limitations under the License.
617
+ *
618
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
619
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
620
+ * */
621
+ const {
622
+ selectById: selectDrawByInstanceId
623
+ } = drawAdapter.getSelectors(state => {
624
+ var _a;
625
+ return (_a = state === null || state === void 0 ? void 0 : state.drawings) !== null && _a !== void 0 ? _a : {
626
+ entities: {},
627
+ ids: []
628
+ };
629
+ });
630
+ const getWarningFormDirty = createSelector(selectDrawByInstanceId, drawing => (drawing === null || drawing === void 0 ? void 0 : drawing.isFormDirty) || false);
631
+
632
+ /* *
633
+ * Licensed under the Apache License, Version 2.0 (the "License");
634
+ * you may not use this file except in compliance with the License.
635
+ * You may obtain a copy of the License at
636
+ *
637
+ * http://www.apache.org/licenses/LICENSE-2.0
638
+ *
639
+ * Unless required by applicable law or agreed to in writing, software
640
+ * distributed under the License is distributed on an "AS IS" BASIS,
641
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
642
+ * See the License for the specific language governing permissions and
643
+ * limitations under the License.
644
+ *
645
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
646
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
647
+ * */
648
+ const WARN_NAMESPACE = 'warn';
649
+ const outsideComponentTranslations = handleOutsideComponentTranslations(warningsTranslations, WARN_NAMESPACE);
650
+
651
+ /* *
652
+ * Licensed under the Apache License, Version 2.0 (the "License");
653
+ * you may not use this file except in compliance with the License.
654
+ * You may obtain a copy of the License at
655
+ *
656
+ * http://www.apache.org/licenses/LICENSE-2.0
657
+ *
658
+ * Unless required by applicable law or agreed to in writing, software
659
+ * distributed under the License is distributed on an "AS IS" BASIS,
660
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
661
+ * See the License for the specific language governing permissions and
662
+ * limitations under the License.
663
+ *
664
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
665
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
666
+ * */
667
+ const confirmationDialogOptions = t => {
668
+ return {
669
+ cancelLabel: t('close-dialog-cancel'),
670
+ title: t('close-draw-dialog-title'),
671
+ description: t('close-dialog-description'),
672
+ confirmLabel: t('close-dialog-confirm'),
673
+ catchOnCancel: true
674
+ };
675
+ };
676
+ const useCloseDrawDialog = ({
677
+ mapId,
678
+ source
679
+ }) => {
702
680
  const {
703
681
  t
704
682
  } = useTranslation(WARN_NAMESPACE);
@@ -767,7 +745,7 @@ const useCloseObjectDialog = ({
767
745
  }) => {
768
746
  const dispatch = useDispatch();
769
747
  const drawLayerId = getSingularDrawtoolDrawLayerId(mapId);
770
- const objectGeoJSONShape = useSelector(store => layerSelectors.getFeatureLayerGeoJSON(store, drawLayerId));
748
+ const featureLayerContainsGeoJSON = useSelector(store => layerSelectors.getHasFeatureLayerGeoJSON(store, drawLayerId));
771
749
  const closeObjectDialog = (shouldReset = true) => {
772
750
  // reset active object
773
751
  if (shouldReset) {
@@ -784,7 +762,7 @@ const useCloseObjectDialog = ({
784
762
  setOpen: false,
785
763
  source
786
764
  }));
787
- if (objectGeoJSONShape && shouldReset) {
765
+ if (featureLayerContainsGeoJSON && shouldReset) {
788
766
  dispatch(mapStoreActions.layerChangeGeojson({
789
767
  layerId: drawLayerId,
790
768
  geojson: emptyGeoJSON
@@ -801,11 +779,11 @@ const useDialogOptions = ({
801
779
  const isDialogOpen = useSelector(store => uiSelectors.getisDialogOpen(store, dialogType));
802
780
  const dialogMapId = useSelector(store => uiSelectors.getDialogMapId(store, dialogType));
803
781
  const dialogLayerId = getSingularDrawtoolDrawLayerId(dialogMapId);
804
- const geoJSON = useSelector(store => layerSelectors.getFeatureLayerGeoJSON(store, dialogLayerId));
782
+ const hasGeoJSON = useSelector(store => layerSelectors.getHasFeatureLayerGeoJSON(store, dialogLayerId));
805
783
  return {
806
784
  isDialogOpen,
807
785
  dialogMapId,
808
- geoJSON,
786
+ hasGeoJSON,
809
787
  dialogLayerId
810
788
  };
811
789
  };
@@ -822,7 +800,7 @@ const useObjectDrawDialogAction = ({
822
800
  // draw selectors
823
801
  const {
824
802
  isDialogOpen: isDrawDialogOpen,
825
- geoJSON: drawDialogGeoJSON,
803
+ hasGeoJSON: drawDialogLayerHasGeoJSON,
826
804
  dialogLayerId: drawDialogLayerId
827
805
  } = useDialogOptions({
828
806
  dialogType: drawingDialogType
@@ -832,7 +810,7 @@ const useObjectDrawDialogAction = ({
832
810
  // object selectors
833
811
  const {
834
812
  isDialogOpen: isObjectDialogOpen,
835
- geoJSON: objectGeoJSONShape,
813
+ hasGeoJSON: objectDialogLayerHasGeoJSON,
836
814
  dialogLayerId: objectDialogLayerId
837
815
  } = useDialogOptions({
838
816
  dialogType: objectDialogType
@@ -851,7 +829,7 @@ const useObjectDrawDialogAction = ({
851
829
  return;
852
830
  }
853
831
  }
854
- if (drawDialogGeoJSON) {
832
+ if (drawDialogLayerHasGeoJSON) {
855
833
  clearGeoJSON(drawDialogLayerId);
856
834
  }
857
835
  closeDrawDialog(true);
@@ -864,11 +842,11 @@ const useObjectDrawDialogAction = ({
864
842
  source
865
843
  }));
866
844
  // move shape to screen
867
- if (isObjectDialogOpen && objectGeoJSONShape) {
845
+ if (isObjectDialogOpen && objectDialogLayerHasGeoJSON) {
868
846
  // update new shape
869
- dispatch(mapStoreActions.layerChangeGeojson({
847
+ dispatch(mapStoreActions.layerSetGeojsonFromLayer({
870
848
  layerId: currentDrawLayerId,
871
- geojson: objectGeoJSONShape
849
+ sourceLayerId: objectDialogLayerId
872
850
  }));
873
851
  // remove current shape
874
852
  clearGeoJSON(objectDialogLayerId);
@@ -876,7 +854,7 @@ const useObjectDrawDialogAction = ({
876
854
  });
877
855
  const openDrawDialog = newGeoJSON => {
878
856
  if (isObjectDialogOpen) {
879
- if (objectGeoJSONShape) {
857
+ if (objectDialogLayerHasGeoJSON) {
880
858
  clearGeoJSON(objectDialogLayerId);
881
859
  }
882
860
  const shouldResetShape = newGeoJSON === undefined;
@@ -895,11 +873,11 @@ const useObjectDrawDialogAction = ({
895
873
  geoJSONLayerId: currentDrawLayerId
896
874
  }));
897
875
  // move shape to screen
898
- if (isDrawDialogOpen && drawDialogGeoJSON) {
876
+ if (isDrawDialogOpen && drawDialogLayerHasGeoJSON) {
899
877
  // update new shape
900
- dispatch(mapStoreActions.layerChangeGeojson({
878
+ dispatch(mapStoreActions.layerSetGeojsonFromLayer({
901
879
  layerId: currentDrawLayerId,
902
- geojson: drawDialogGeoJSON
880
+ sourceLayerId: drawDialogLayerId
903
881
  }));
904
882
  // remove current shape
905
883
  clearGeoJSON(drawDialogLayerId);
@@ -5346,6 +5324,7 @@ var warningListJSON = [
5346
5324
  status: "DRAFT",
5347
5325
  editor: "user.name",
5348
5326
  warningDetail: {
5327
+ id: "550c2b5e-937d-11ee-a1bf-0ab3cf8a98c1",
5349
5328
  phenomenon: "fog",
5350
5329
  geoJSON: {
5351
5330
  type: "FeatureCollection",
@@ -5389,7 +5368,9 @@ var warningListJSON = [
5389
5368
  validFrom: "2023-12-05T14:48:09Z",
5390
5369
  validUntil: "2023-12-05T18:48:09Z",
5391
5370
  level: "moderate",
5392
- probability: 30
5371
+ probability: 30,
5372
+ descriptionOriginal: "This is the original description",
5373
+ descriptionTranslation: "This is the translation"
5393
5374
  }
5394
5375
  },
5395
5376
  {
@@ -5699,399 +5680,69 @@ var warningListJSON = [
5699
5680
  "fill-opacity": 0.2,
5700
5681
  "stroke-width": 2,
5701
5682
  selectionType: "poly",
5702
- "stroke-opacity": 1
5703
- }
5704
- }
5705
- ]
5706
- },
5707
- validFrom: "2023-12-05T14:47:50Z",
5708
- validUntil: "2023-12-05T20:47:50Z",
5709
- level: "moderate",
5710
- probability: 40
5711
- }
5712
- },
5713
- {
5714
- id: "3f756602-937d-11ee-a1bf-0ab3cf8a98c1",
5715
- lastUpdatedTime: "2023-12-05T14:47:43Z",
5716
- status: "EXPIRED",
5717
- warningDetail: {
5718
- phenomenon: "thunderstorm",
5719
- geoJSON: {
5720
- type: "FeatureCollection",
5721
- features: [
5722
- {
5723
- type: "Feature",
5724
- geometry: {
5725
- type: "Polygon",
5726
- coordinates: [
5727
- [
5728
- [
5729
- 5.0950448864466225,
5730
- 53.492000941975654
5731
- ],
5732
- [
5733
- 4.280148780801422,
5734
- 52.46455621916433
5735
- ],
5736
- [
5737
- 6.878229305858475,
5738
- 52.98133263853793
5739
- ],
5740
- [
5741
- 5.0950448864466225,
5742
- 53.492000941975654
5743
- ]
5744
- ]
5745
- ]
5746
- },
5747
- properties: {
5748
- fill: "#ff7800",
5749
- stroke: "#ff7800",
5750
- "fill-opacity": 0.2,
5751
- "stroke-width": 2,
5752
- selectionType: "poly",
5753
- "stroke-opacity": 1
5754
- }
5755
- }
5756
- ]
5757
- },
5758
- validFrom: "2023-12-05T14:47:34Z",
5759
- validUntil: "2023-12-05T20:47:34Z",
5760
- level: "extreme",
5761
- probability: 40
5762
- }
5763
- }
5764
- ];
5765
-
5766
- /* *
5767
- * Licensed under the Apache License, Version 2.0 (the "License");
5768
- * you may not use this file except in compliance with the License.
5769
- * You may obtain a copy of the License at
5770
- *
5771
- * http://www.apache.org/licenses/LICENSE-2.0
5772
- *
5773
- * Unless required by applicable law or agreed to in writing, software
5774
- * distributed under the License is distributed on an "AS IS" BASIS,
5775
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5776
- * See the License for the specific language governing permissions and
5777
- * limitations under the License.
5778
- *
5779
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
5780
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
5781
- * */
5782
- const drawingList = drawingListJSON;
5783
- const drawingsListFullContent = drawingsListFullContentJSON;
5784
- const warningList = warningListJSON;
5785
-
5786
- const ERROR_NOT_FOUND = 'Request failed with status code 400';
5787
- const MOCK_USERNAME = 'user.name';
5788
- const extractDrawingDetailsFromJSON = drawingId => {
5789
- return drawingsListFullContent.find(element => element.id === drawingId);
5790
- };
5791
- const getApiRoutes = axiosInstance => ({
5792
- // drawings
5793
- getDrawings: () => {
5794
- return axiosInstance.get('/drawings').then(() => {
5795
- return {
5796
- data: drawingList
5797
- };
5798
- });
5799
- },
5800
- getDrawingDetails: drawingId => {
5801
- return axiosInstance.get(`/drawings/${drawingId}`).then(() => {
5802
- if (!extractDrawingDetailsFromJSON(drawingId)) {
5803
- throw new Error(ERROR_NOT_FOUND);
5804
- }
5805
- return {
5806
- data: extractDrawingDetailsFromJSON(drawingId)
5807
- };
5808
- });
5809
- },
5810
- updateDrawing: (drawingId, data) => {
5811
- // eslint-disable-next-line no-console
5812
- console.log('api: save drawing', drawingId, data);
5813
- return axiosInstance.post(`/drawings/${drawingId}/`, data);
5814
- },
5815
- saveDrawingAs: data => {
5816
- // eslint-disable-next-line no-console
5817
- console.log('api: save drawing as', data);
5818
- return axiosInstance.post(`/drawings/`, data).then(() => 'new-drawing-id');
5819
- },
5820
- deleteDrawing: drawingId => {
5821
- // eslint-disable-next-line no-console
5822
- console.log('api: delete drawing', drawingId);
5823
- drawingList.splice(drawingList.findIndex(drawing => drawing.id === drawingId), 1);
5824
- return axiosInstance.post(`/drawings/${drawingId}?delete=true`);
5825
- },
5826
- // public warnings
5827
- getWarnings: () => {
5828
- return axiosInstance.get(`/warnings/`).then(() => ({
5829
- data: warningList
5830
- }));
5831
- },
5832
- saveWarningAs: data => {
5833
- // eslint-disable-next-line no-console
5834
- console.log('api: save warning as', data);
5835
- return axiosInstance.post(`/warnings/`, data).then(() => 'new-warning-id');
5836
- },
5837
- updateWarning: (warningId, data) => {
5838
- // eslint-disable-next-line no-console
5839
- console.log(`api: update warning ${warningId}`, data);
5840
- return axiosInstance.post(`/warnings/${warningId}/`, data);
5841
- },
5842
- deleteWarning: warningId => {
5843
- // eslint-disable-next-line no-console
5844
- console.log('api: delete warning', warningId);
5845
- warningList.splice(warningList.findIndex(warning => warning.id === warningId), 1);
5846
- return axiosInstance.post(`/warnings/${warningId}?delete=true`);
5847
- },
5848
- toggleEditorWarning: (warningId, isEditor) => {
5849
- // eslint-disable-next-line no-console
5850
- console.log('api: toggle editor warning', warningId, isEditor);
5851
- const index = warningList.findIndex(warning => warning.id === warningId);
5852
- warningList.splice(index, 1, Object.assign(Object.assign({}, warningList[index]), {
5853
- editor: isEditor ? MOCK_USERNAME : null
5854
- }));
5855
- return axiosInstance.post(`/warnings/${warningId}?editor=${isEditor ? 'true' : 'false'}`);
5856
- }
5857
- });
5858
- // used in storybook
5859
- const createApi = () => {
5860
- const instance = createFakeApiInstance();
5861
- return getApiRoutes(instance);
5862
- };
5863
-
5864
- const getErrorMessage = error => isAxiosError(error) ? getAxiosErrorMessage(error) : error.message;
5865
- function* saveOrUpdateWarning(publicWarning) {
5866
- const warningsApi = yield call$c(getWarningsApi);
5867
- if (publicWarning.warningDetail.id) {
5868
- yield call$c(warningsApi.updateWarning, publicWarning.warningDetail.id, publicWarning);
5869
- return publicWarning;
5870
- }
5871
- const newWarningId = yield call$c(warningsApi.saveWarningAs, publicWarning);
5872
- return Object.assign(Object.assign({}, publicWarning), {
5873
- warningDetail: Object.assign(Object.assign({}, publicWarning.warningDetail), {
5874
- id: newWarningId
5875
- })
5876
- });
5877
- }
5878
- const getToggleEditorSuccessMessage = isEditor => outsideComponentTranslations[isEditor ? 'warning-editor-add-editor' : 'warning-editor-remove-editor'];
5879
- function* toggleEditorWarningSaga({
5880
- payload
5881
- }) {
5882
- try {
5883
- const {
5884
- warningId,
5885
- isEditor,
5886
- username
5887
- } = payload;
5888
- const warningsApi = yield call$c(getWarningsApi);
5889
- yield call$c(warningsApi.toggleEditorWarning, warningId, isEditor);
5890
- // update list to show correct avatar
5891
- yield put(publicWarningActions.fetchWarnings());
5892
- yield put(publicWarningFormActions.toggleEditorWarningSuccess({
5893
- isEditor,
5894
- username,
5895
- message: getToggleEditorSuccessMessage(isEditor)
5896
- }));
5897
- } catch (error) {
5898
- yield call$c(errorSaga, getErrorMessage(error));
5899
- }
5900
- }
5901
- function* publishWarningSaga({
5902
- payload
5903
- }) {
5904
- try {
5905
- const {
5906
- publicWarning
5907
- } = payload;
5908
- const publishedWarning = yield call$c(saveOrUpdateWarning, publicWarning);
5909
- yield put(publicWarningFormActions.publishWarningSuccess({
5910
- publicWarning: publishedWarning,
5911
- message: outsideComponentTranslations['warning-publish-succes']
5912
- }));
5913
- yield put(uiActions.setToggleOpenDialog({
5914
- type: publicWarningDialogType,
5915
- setOpen: false
5916
- }));
5917
- } catch (error) {
5918
- yield call$c(errorSaga, getErrorMessage(error));
5919
- }
5920
- }
5921
- function* saveWarningSaga({
5922
- payload
5923
- }) {
5924
- try {
5925
- const {
5926
- publicWarning
5927
- } = payload;
5928
- const savedWarning = yield call$c(saveOrUpdateWarning, publicWarning);
5929
- yield put(publicWarningFormActions.saveWarningSuccess({
5930
- publicWarning: savedWarning,
5931
- message: outsideComponentTranslations['warning-save-succes']
5932
- }));
5933
- } catch (error) {
5934
- yield call$c(errorSaga, getErrorMessage(error));
5935
- }
5936
- }
5937
- function* successSaga({
5938
- payload
5939
- }) {
5940
- const {
5941
- message
5942
- } = payload;
5943
- yield put(snackbarActions.openSnackbar({
5944
- message
5945
- }));
5946
- yield call$c(toggleDialogLoadingSaga, false);
5947
- }
5948
- function* errorSaga(message) {
5949
- yield put(publicWarningFormActions.setFormError({
5950
- message
5951
- }));
5952
- yield call$c(toggleDialogLoadingSaga, false);
5953
- }
5954
- function* toggleDialogLoadingSaga(isLoading) {
5955
- const isDialogOpen = yield select(uiSelectors.getDialogDetailsByType, publicWarningDialogType);
5956
- if (isDialogOpen) {
5957
- yield put(uiActions.toggleIsLoadingDialog({
5958
- isLoading,
5959
- type: publicWarningDialogType
5960
- }));
5961
- }
5962
- }
5963
- function* openDialogSaga() {
5964
- yield put(uiActions.setToggleOpenDialog({
5965
- setOpen: true,
5966
- type: publicWarningDialogType
5967
- }));
5968
- }
5969
- function* publicWarningRootSaga() {
5970
- // requests
5971
- yield takeLatest(publicWarningFormActions.toggleEditorWarning, toggleEditorWarningSaga);
5972
- yield takeLatest(publicWarningFormActions.publishWarning, publishWarningSaga);
5973
- yield takeLatest(publicWarningFormActions.saveWarning, saveWarningSaga);
5974
- // side effects ui/snackbar
5975
- yield takeLatest([publicWarningFormActions.publishWarningSuccess, publicWarningFormActions.saveWarningSuccess, publicWarningFormActions.toggleEditorWarningSuccess], successSaga);
5976
- yield takeLatest([publicWarningFormActions.publishWarning, publicWarningFormActions.saveWarning], toggleDialogLoadingSaga, true);
5977
- yield takeLatest(publicWarningFormActions.openPublicWarningFormDialog, openDialogSaga);
5978
- }
5979
-
5980
- /* *
5981
- * Licensed under the Apache License, Version 2.0 (the "License");
5982
- * you may not use this file except in compliance with the License.
5983
- * You may obtain a copy of the License at
5984
- *
5985
- * http://www.apache.org/licenses/LICENSE-2.0
5986
- *
5987
- * Unless required by applicable law or agreed to in writing, software
5988
- * distributed under the License is distributed on an "AS IS" BASIS,
5989
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5990
- * See the License for the specific language governing permissions and
5991
- * limitations under the License.
5992
- *
5993
- * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
5994
- * Copyright 2023 - Finnish Meteorological Institute (FMI)
5995
- * */
5996
- const getLastUpdatedTimeFormatted = () => dateUtils.dateToString(dateUtils.utc(), DATE_FORMAT_LASTUPDATEDTIME);
5997
- function* fetchWarningsSaga() {
5998
- try {
5999
- const warningsApi = yield call$c(getWarningsApi);
6000
- const {
6001
- data: warnings
6002
- } = yield call$c(warningsApi.getWarnings);
6003
- const lastUpdatedTime = getLastUpdatedTimeFormatted();
6004
- yield put(publicWarningActions.fetchWarningsSuccess({
6005
- warnings,
6006
- lastUpdatedTime
6007
- }));
6008
- yield delay(pollingIntervalTimeout);
6009
- yield put(publicWarningActions.fetchWarnings());
6010
- } catch (error) {
6011
- yield put(publicWarningActions.fetchWarningsError({
6012
- error: {
6013
- name: error.name,
6014
- message: error.message
6015
- }
6016
- }));
6017
- }
6018
- }
6019
- function* refetchWarnings() {
6020
- yield put(publicWarningActions.fetchWarnings());
6021
- }
6022
- function* publicWarnings() {
6023
- yield takeLatest(publicWarningActions.fetchWarnings, fetchWarningsSaga);
6024
- yield takeLatest([publicWarningFormActions.publishWarningSuccess, publicWarningFormActions.saveWarningSuccess], refetchWarnings);
6025
- }
6026
-
6027
- /* *
6028
- * Licensed under the Apache License, Version 2.0 (the "License");
6029
- * you may not use this file except in compliance with the License.
6030
- * You may obtain a copy of the License at
6031
- *
6032
- * http://www.apache.org/licenses/LICENSE-2.0
6033
- *
6034
- * Unless required by applicable law or agreed to in writing, software
6035
- * distributed under the License is distributed on an "AS IS" BASIS,
6036
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6037
- * See the License for the specific language governing permissions and
6038
- * limitations under the License.
6039
- *
6040
- * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6041
- * Copyright 2024 - Finnish Meteorological Institute (FMI)
6042
- * */
6043
- const getSnackbarMessage = (objectName, id) => id ? `Object "${objectName}" ${outsideComponentTranslations['update-succes']}!` : `Object "${objectName}" ${outsideComponentTranslations['save-succes']}!`;
6044
- const drawingsListener = createListenerMiddleware();
6045
- drawingsListener.startListening({
6046
- actionCreator: drawActions.submitDrawValues,
6047
- effect: ({
6048
- payload
6049
- }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
6050
- listenerApi.cancelActiveListeners();
6051
- const {
6052
- id
6053
- } = payload,
6054
- formValues = __rest(payload, ["id"]);
6055
- try {
6056
- listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
6057
- isLoading: true,
6058
- type: drawingDialogType
6059
- }));
6060
- const warningsApi = getWarningsApi();
6061
- if (!id) {
6062
- const newID = yield warningsApi.saveDrawingAs(formValues);
6063
- listenerApi.dispatch(drawActions.setDrawValues({
6064
- drawingInstanceId: drawingDialogType,
6065
- id: newID,
6066
- objectName: formValues.objectName
6067
- }));
6068
- } else {
6069
- yield warningsApi.updateDrawing(id, formValues);
6070
- }
6071
- listenerApi.dispatch(uiActions.setErrorDialog({
6072
- type: drawingDialogType,
6073
- error: ''
6074
- }));
6075
- listenerApi.dispatch(snackbarActions.openSnackbar({
6076
- message: getSnackbarMessage(formValues.objectName, id)
6077
- }));
6078
- listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
6079
- isLoading: false,
6080
- type: drawingDialogType
6081
- }));
6082
- } catch (error) {
6083
- listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
6084
- isLoading: false,
6085
- type: drawingDialogType
6086
- }));
6087
- const errorMessage = isAxiosError$1(error) ? getAxiosErrorMessage(error) : error.message;
6088
- listenerApi.dispatch(uiActions.setErrorDialog({
6089
- type: drawingDialogType,
6090
- error: errorMessage
6091
- }));
6092
- }
6093
- })
6094
- });
5683
+ "stroke-opacity": 1
5684
+ }
5685
+ }
5686
+ ]
5687
+ },
5688
+ validFrom: "2023-12-05T14:47:50Z",
5689
+ validUntil: "2023-12-05T20:47:50Z",
5690
+ level: "moderate",
5691
+ probability: 40
5692
+ }
5693
+ },
5694
+ {
5695
+ id: "3f756602-937d-11ee-a1bf-0ab3cf8a98c1",
5696
+ lastUpdatedTime: "2023-12-05T14:47:43Z",
5697
+ status: "EXPIRED",
5698
+ warningDetail: {
5699
+ phenomenon: "thunderstorm",
5700
+ geoJSON: {
5701
+ type: "FeatureCollection",
5702
+ features: [
5703
+ {
5704
+ type: "Feature",
5705
+ geometry: {
5706
+ type: "Polygon",
5707
+ coordinates: [
5708
+ [
5709
+ [
5710
+ 5.0950448864466225,
5711
+ 53.492000941975654
5712
+ ],
5713
+ [
5714
+ 4.280148780801422,
5715
+ 52.46455621916433
5716
+ ],
5717
+ [
5718
+ 6.878229305858475,
5719
+ 52.98133263853793
5720
+ ],
5721
+ [
5722
+ 5.0950448864466225,
5723
+ 53.492000941975654
5724
+ ]
5725
+ ]
5726
+ ]
5727
+ },
5728
+ properties: {
5729
+ fill: "#ff7800",
5730
+ stroke: "#ff7800",
5731
+ "fill-opacity": 0.2,
5732
+ "stroke-width": 2,
5733
+ selectionType: "poly",
5734
+ "stroke-opacity": 1
5735
+ }
5736
+ }
5737
+ ]
5738
+ },
5739
+ validFrom: "2023-12-05T14:47:34Z",
5740
+ validUntil: "2023-12-05T20:47:34Z",
5741
+ level: "extreme",
5742
+ probability: 40
5743
+ }
5744
+ }
5745
+ ];
6095
5746
 
6096
5747
  /* *
6097
5748
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -6109,52 +5760,86 @@ drawingsListener.startListening({
6109
5760
  * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6110
5761
  * Copyright 2023 - Finnish Meteorological Institute (FMI)
6111
5762
  * */
6112
- const drawingModuleConfig = {
6113
- id: 'drawing-module',
6114
- reducersMap: {
6115
- drawings: reducer$2,
6116
- publicWarningForm: reducer,
6117
- publicWarnings: reducer$1
6118
- },
6119
- sagas: [publicWarningRootSaga, publicWarnings],
6120
- middlewares: [drawingsListener.middleware]
6121
- };
5763
+ const drawingList = drawingListJSON;
5764
+ const drawingsListFullContent = drawingsListFullContentJSON;
5765
+ const warningList = warningListJSON;
6122
5766
 
6123
- createStore();
6124
- const WarningsThemeProvider = ({
6125
- children,
6126
- theme: _theme = lightTheme
6127
- }) => {
6128
- return /*#__PURE__*/React.createElement(WarningsI18nProvider, null, /*#__PURE__*/React.createElement(ThemeWrapper, {
6129
- theme: _theme
6130
- }, children));
5767
+ const ERROR_NOT_FOUND = 'Request failed with status code 400';
5768
+ const MOCK_USERNAME = 'user.name';
5769
+ const extractDrawingDetailsFromJSON = drawingId => {
5770
+ return drawingsListFullContent.find(element => element.id === drawingId);
6131
5771
  };
6132
- withEggs([...coreModuleConfig, drawingModuleConfig])(_a => {
6133
- var {
6134
- children
6135
- } = _a,
6136
- props = __rest(_a, ["children"]);
6137
- return /*#__PURE__*/React.createElement(WarningsThemeProvider, Object.assign({}, props), children);
5772
+ const getApiRoutes = axiosInstance => ({
5773
+ // drawings
5774
+ getDrawings: () => {
5775
+ return axiosInstance.get('/drawings').then(() => {
5776
+ return {
5777
+ data: drawingList
5778
+ };
5779
+ });
5780
+ },
5781
+ getDrawingDetails: drawingId => {
5782
+ return axiosInstance.get(`/drawings/${drawingId}`).then(() => {
5783
+ if (!extractDrawingDetailsFromJSON(drawingId)) {
5784
+ throw new Error(ERROR_NOT_FOUND);
5785
+ }
5786
+ return {
5787
+ data: extractDrawingDetailsFromJSON(drawingId)
5788
+ };
5789
+ });
5790
+ },
5791
+ updateDrawing: (drawingId, data) => {
5792
+ // eslint-disable-next-line no-console
5793
+ console.log('api: save drawing', drawingId, data);
5794
+ return axiosInstance.post(`/drawings/${drawingId}/`, data);
5795
+ },
5796
+ saveDrawingAs: data => {
5797
+ // eslint-disable-next-line no-console
5798
+ console.log('api: save drawing as', data);
5799
+ return axiosInstance.post(`/drawings/`, data).then(() => 'new-drawing-id');
5800
+ },
5801
+ deleteDrawing: drawingId => {
5802
+ // eslint-disable-next-line no-console
5803
+ console.log('api: delete drawing', drawingId);
5804
+ drawingList.splice(drawingList.findIndex(drawing => drawing.id === drawingId), 1);
5805
+ return axiosInstance.post(`/drawings/${drawingId}?delete=true`);
5806
+ },
5807
+ // public warnings
5808
+ getWarnings: () => {
5809
+ return axiosInstance.get(`/warnings/`).then(() => ({
5810
+ data: warningList
5811
+ }));
5812
+ },
5813
+ saveWarningAs: data => {
5814
+ // eslint-disable-next-line no-console
5815
+ console.log('api: save warning as', data);
5816
+ return axiosInstance.post(`/warnings/`, data).then(() => 'new-warning-id');
5817
+ },
5818
+ updateWarning: (warningId, data) => {
5819
+ // eslint-disable-next-line no-console
5820
+ console.log(`api: update warning ${warningId}`, data);
5821
+ return axiosInstance.post(`/warnings/${warningId}/`, data);
5822
+ },
5823
+ deleteWarning: warningId => {
5824
+ // eslint-disable-next-line no-console
5825
+ console.log('api: delete warning', warningId);
5826
+ warningList.splice(warningList.findIndex(warning => warning.id === warningId), 1);
5827
+ return axiosInstance.post(`/warnings/${warningId}?delete=true`);
5828
+ },
5829
+ toggleEditorWarning: (warningId, isEditor) => {
5830
+ // eslint-disable-next-line no-console
5831
+ console.log('api: toggle editor warning', warningId, isEditor);
5832
+ const index = warningList.findIndex(warning => warning.id === warningId);
5833
+ warningList.splice(index, 1, Object.assign(Object.assign({}, warningList[index]), {
5834
+ editor: isEditor ? MOCK_USERNAME : null
5835
+ }));
5836
+ return axiosInstance.post(`/warnings/${warningId}?editor=${isEditor ? 'true' : 'false'}`);
5837
+ }
6138
5838
  });
6139
- const WarningsTranslationsWrapper = ({
6140
- children
6141
- }) => {
6142
- const {
6143
- i18n
6144
- } = useTranslation();
6145
- React.useEffect(() => {
6146
- i18n.addResourceBundle('en', WARN_NAMESPACE, warningsTranslations.en);
6147
- i18n.addResourceBundle('nl', WARN_NAMESPACE, warningsTranslations.nl);
6148
- }, [i18n]);
6149
- return children;
6150
- };
6151
- const WarningsI18nProvider = ({
6152
- children
6153
- }) => {
6154
- initWarnI18n();
6155
- return /*#__PURE__*/React.createElement(I18nextProvider, {
6156
- i18n: i18n
6157
- }, children);
5839
+ // used in storybook
5840
+ const createApi = () => {
5841
+ const instance = createFakeApiInstance();
5842
+ return getApiRoutes(instance);
6158
5843
  };
6159
5844
 
6160
5845
  /* *
@@ -6179,13 +5864,13 @@ const WarningsModuleProvider = ({
6179
5864
  onSetAuth,
6180
5865
  children
6181
5866
  }) => {
6182
- return /*#__PURE__*/React.createElement(WarningsTranslationsWrapper, null, /*#__PURE__*/React.createElement(ApiProvider, {
5867
+ return /*#__PURE__*/React.createElement(ApiProvider, {
6183
5868
  config: config,
6184
5869
  auth: auth,
6185
5870
  onSetAuth: onSetAuth,
6186
5871
  createApi: config !== undefined ? createApi$1 : createApi,
6187
5872
  name: API_NAME
6188
- }, children));
5873
+ }, children);
6189
5874
  };
6190
5875
 
6191
5876
  /* *
@@ -6920,7 +6605,7 @@ const DEFAULT_WARNING_DIALOG_POSITION = {
6920
6605
  left: 60
6921
6606
  };
6922
6607
  const DEFAULT_WARNING_DIALOG_MIN_SIZE = {
6923
- width: 320,
6608
+ width: 264,
6924
6609
  height: 300
6925
6610
  };
6926
6611
  const PublicWarningsFormDialog = ({
@@ -6951,8 +6636,25 @@ const PublicWarningsFormDialog = ({
6951
6636
  const onChangeMode = () => {
6952
6637
  _onChangeFormMode(!_isReadOnly);
6953
6638
  };
6639
+ const fullTitle = title || t('public-warning-title');
6954
6640
  return /*#__PURE__*/React.createElement(ToolContainerDraggable, Object.assign({
6955
- title: title || t('public-warning-title'),
6641
+ title: _shouldHideFormMode ? fullTitle : undefined
6642
+ }, !_shouldHideFormMode && {
6643
+ leftHeaderComponent: ( /*#__PURE__*/React.createElement(Box, {
6644
+ className: "header-title"
6645
+ }, /*#__PURE__*/React.createElement(Typography, {
6646
+ variant: "h2",
6647
+ noWrap: true,
6648
+ sx: {
6649
+ fontSize: 12,
6650
+ fontWeight: 500,
6651
+ lineHeight: '22px',
6652
+ marginTop: '-1px',
6653
+ paddingLeft: 1
6654
+ },
6655
+ role: "heading"
6656
+ }, fullTitle)))
6657
+ }, {
6956
6658
  startSize: sizeInState,
6957
6659
  minWidth: minSize.width,
6958
6660
  minHeight: minSize.height,
@@ -7707,7 +7409,7 @@ const CustomTabPanel = props => {
7707
7409
  disabled: isDisabled
7708
7410
  }, /*#__PURE__*/React__default.createElement(MenuItem, {
7709
7411
  value: "NL"
7710
- }, t('warning-description-NL'))))), value === index ? children : null);
7412
+ }, t('warning-description-NL'))))), children);
7711
7413
  };
7712
7414
  const DescriptionField = ({
7713
7415
  isDisabled: _isDisabled = false,
@@ -7716,12 +7418,31 @@ const DescriptionField = ({
7716
7418
  const {
7717
7419
  t
7718
7420
  } = useTranslation(WARN_NAMESPACE);
7719
- const [value, setValue] = React__default.useState(0);
7421
+ const {
7422
+ isRequired
7423
+ } = useDraftFormHelpers();
7424
+ const {
7425
+ formState
7426
+ } = useFormContext();
7427
+ const [activeTab, setActiveTab] = React__default.useState(0);
7720
7428
  const handleChange = (event, newValue) => {
7721
- setValue(newValue);
7429
+ setActiveTab(newValue);
7722
7430
  };
7431
+ const lastSubmitCount = useRef(0);
7432
+ // next code shows the tab for the textarea which is in the invalid state
7433
+ useEffect(() => {
7434
+ if (formState.submitCount === lastSubmitCount.current) {
7435
+ return;
7436
+ }
7437
+ lastSubmitCount.current = formState.submitCount;
7438
+ if ('descriptionOriginal' in formState.errors) {
7439
+ setActiveTab(0);
7440
+ } else if ('descriptionTranslation' in formState.errors) {
7441
+ setActiveTab(1);
7442
+ }
7443
+ }, [formState.errors, formState.submitCount]);
7723
7444
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Tabs, Object.assign({
7724
- value: value,
7445
+ value: activeTab,
7725
7446
  onChange: handleChange,
7726
7447
  "aria-label": "description tabs"
7727
7448
  }, _isDisabled && {
@@ -7740,29 +7461,39 @@ const DescriptionField = ({
7740
7461
  label: t('warning-description-translation'),
7741
7462
  disabled: _isDisabled
7742
7463
  }, a11yProps(1)))), /*#__PURE__*/React__default.createElement(CustomTabPanel, {
7743
- value: value,
7464
+ value: activeTab,
7744
7465
  index: 0,
7745
7466
  isDisabled: _isDisabled,
7746
7467
  isReadOnly: _isReadOnly
7747
7468
  }, /*#__PURE__*/React__default.createElement(ReactHookFormTextField, {
7748
- rules: {},
7469
+ rules: {
7470
+ validate: {
7471
+ isRequired
7472
+ }
7473
+ },
7749
7474
  minRows: 4,
7750
7475
  name: "descriptionOriginal",
7751
7476
  multiline: true,
7752
7477
  disabled: _isDisabled,
7753
- isReadOnly: _isReadOnly
7478
+ isReadOnly: _isReadOnly,
7479
+ onKeyDown: event => event.stopPropagation()
7754
7480
  })), /*#__PURE__*/React__default.createElement(CustomTabPanel, {
7755
- value: value,
7481
+ value: activeTab,
7756
7482
  index: 1,
7757
7483
  isDisabled: _isDisabled,
7758
7484
  isReadOnly: _isReadOnly
7759
7485
  }, /*#__PURE__*/React__default.createElement(ReactHookFormTextField, {
7760
- rules: {},
7486
+ rules: {
7487
+ validate: {
7488
+ isRequired
7489
+ }
7490
+ },
7761
7491
  minRows: 4,
7762
7492
  name: "descriptionTranslation",
7763
7493
  multiline: true,
7764
7494
  disabled: _isDisabled,
7765
- isReadOnly: _isReadOnly
7495
+ isReadOnly: _isReadOnly,
7496
+ onKeyDown: event => event.stopPropagation()
7766
7497
  })));
7767
7498
  };
7768
7499
 
@@ -8010,10 +7741,14 @@ const LevelField = ({
8010
7741
  isRequired
8011
7742
  } = useDraftFormHelpers();
8012
7743
  const {
8013
- watch
7744
+ watch,
7745
+ trigger
8014
7746
  } = useFormContext();
8015
7747
  const selectedLevel = watch('level');
8016
7748
  const levelDetails = levelOptions(t).find(level => level.key === selectedLevel);
7749
+ const onChangeLevel = () => {
7750
+ trigger(['level', 'probability']);
7751
+ };
8017
7752
  return /*#__PURE__*/React.createElement(ReactHookFormSelect, {
8018
7753
  name: "level",
8019
7754
  label: t('warning-level'),
@@ -8030,7 +7765,8 @@ const LevelField = ({
8030
7765
  }
8031
7766
  },
8032
7767
  disabled: _isDisabled || _isReadOnly,
8033
- isReadOnly: _isReadOnly
7768
+ isReadOnly: _isReadOnly,
7769
+ onChange: onChangeLevel
8034
7770
  }, levelOptions(t).map(level => ( /*#__PURE__*/React.createElement(MenuItem, {
8035
7771
  value: level.key,
8036
7772
  key: level.key,
@@ -8091,7 +7827,9 @@ const ValidFrom = ({
8091
7827
  const {
8092
7828
  trigger
8093
7829
  } = useFormContext();
8094
- const onChangeValidFrom = () => trigger('validUntil');
7830
+ const onChangeValidFrom = () => {
7831
+ trigger(['validFrom', 'validUntil']);
7832
+ };
8095
7833
  return /*#__PURE__*/React.createElement(ReactHookFormDateTime, {
8096
7834
  name: "validFrom",
8097
7835
  rules: {
@@ -8156,8 +7894,12 @@ const ValidUntil = ({
8156
7894
  isRequired
8157
7895
  } = useDraftFormHelpers();
8158
7896
  const {
8159
- getValues
7897
+ getValues,
7898
+ trigger
8160
7899
  } = useFormContext();
7900
+ const onChangeValidUntil = () => {
7901
+ trigger(['validFrom', 'validUntil']);
7902
+ };
8161
7903
  return /*#__PURE__*/React.createElement(ReactHookFormDateTime, {
8162
7904
  name: "validUntil",
8163
7905
  rules: {
@@ -8175,7 +7917,8 @@ const ValidUntil = ({
8175
7917
  label: t('warning-valid-until'),
8176
7918
  disablePast: true,
8177
7919
  disabled: isDisabled || isReadOnly,
8178
- isReadOnly: isReadOnly
7920
+ isReadOnly: isReadOnly,
7921
+ onChange: onChangeValidUntil
8179
7922
  });
8180
7923
  };
8181
7924
 
@@ -8215,33 +7958,97 @@ const WarningsMapView = ({
8215
7958
  geojson: geojsonFeature,
8216
7959
  layerType: LayerType.featureLayer
8217
7960
  };
8218
- // Zoom to the geojson when the geojsonFeature is updated in an already mounted map component
8219
- zoomToFeature(mapId, geojsonFeature);
8220
- return /*#__PURE__*/React.createElement("div", {
8221
- style: {
8222
- height: '200px',
8223
- width: '100%'
7961
+ // Zoom to the geojson when the geojsonFeature is updated in an already mounted map component
7962
+ zoomToFeature(mapId, geojsonFeature);
7963
+ return /*#__PURE__*/React.createElement("div", {
7964
+ style: {
7965
+ height: '200px',
7966
+ width: '100%'
7967
+ }
7968
+ }, /*#__PURE__*/React.createElement(MapView, {
7969
+ bbox: _defaultBbox.bbox,
7970
+ srs: _defaultBbox.srs,
7971
+ mapId: mapId,
7972
+ showScaleBar: false,
7973
+ onWMJSMount: mapId => {
7974
+ const webmapjs = getWMJSMapById(mapId);
7975
+ webmapjs.hideMouseCursorProperties();
7976
+ if (!geojsonFeature) {
7977
+ return;
7978
+ }
7979
+ // Zoom to the geojson when the map is ready
7980
+ zoomToFeature(mapId, geojsonFeature);
7981
+ },
7982
+ holdShiftToScroll: true
7983
+ }, /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, defaultLayers.baseLayerGrey, {
7984
+ id: `${mapId}_baseLayer}`
7985
+ })), warningLayer.geojson && /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, warningLayer)), /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, defaultLayers.overLayer, {
7986
+ id: `${mapId}_overlayer}`
7987
+ }))));
7988
+ };
7989
+
7990
+ /* *
7991
+ * Licensed under the Apache License, Version 2.0 (the "License");
7992
+ * you may not use this file except in compliance with the License.
7993
+ * You may obtain a copy of the License at
7994
+ *
7995
+ * http://www.apache.org/licenses/LICENSE-2.0
7996
+ *
7997
+ * Unless required by applicable law or agreed to in writing, software
7998
+ * distributed under the License is distributed on an "AS IS" BASIS,
7999
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8000
+ * See the License for the specific language governing permissions and
8001
+ * limitations under the License.
8002
+ *
8003
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
8004
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
8005
+ * */
8006
+ const probablityOptions = [100, 90, 80, 70, 60, 50, 40, 30, 20, 10];
8007
+ const defaultProbability = 30;
8008
+ const ProbabilityField = ({
8009
+ isDisabled,
8010
+ isReadOnly
8011
+ }) => {
8012
+ const {
8013
+ t
8014
+ } = useTranslation(WARN_NAMESPACE);
8015
+ const {
8016
+ trigger,
8017
+ getValues
8018
+ } = useFormContext();
8019
+ const {
8020
+ isRequired
8021
+ } = useDraftFormHelpers();
8022
+ const isValidProbabilityForLevel = (value, fieldValues) => {
8023
+ if (fieldValues['level'] === 'moderate' && value < 30) {
8024
+ return t('warning-probability-moderate-level-invalid');
8025
+ }
8026
+ return true;
8027
+ };
8028
+ const onChangeProbability = () => {
8029
+ trigger('probability');
8030
+ // We don't want to trigger the missing value validation
8031
+ if (!isEmpty(getValues('level'))) {
8032
+ trigger('level');
8224
8033
  }
8225
- }, /*#__PURE__*/React.createElement(MapView, {
8226
- bbox: _defaultBbox.bbox,
8227
- srs: _defaultBbox.srs,
8228
- mapId: mapId,
8229
- showScaleBar: false,
8230
- onWMJSMount: mapId => {
8231
- const webmapjs = getWMJSMapById(mapId);
8232
- webmapjs.hideMouseCursorProperties();
8233
- if (!geojsonFeature) {
8234
- return;
8034
+ };
8035
+ return /*#__PURE__*/React.createElement(ReactHookFormSelect, {
8036
+ name: "probability",
8037
+ label: t('warning-probability'),
8038
+ rules: {
8039
+ validate: {
8040
+ isRequired,
8041
+ isValidProbabilityForLevel
8235
8042
  }
8236
- // Zoom to the geojson when the map is ready
8237
- zoomToFeature(mapId, geojsonFeature);
8238
8043
  },
8239
- holdShiftToScroll: true
8240
- }, /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, defaultLayers.baseLayerGrey, {
8241
- id: `${mapId}_baseLayer}`
8242
- })), warningLayer.geojson && /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, warningLayer)), /*#__PURE__*/React.createElement(MapViewLayer, Object.assign({}, defaultLayers.overLayer, {
8243
- id: `${mapId}_overlayer}`
8244
- }))));
8044
+ disabled: isDisabled || isReadOnly,
8045
+ isReadOnly: isReadOnly,
8046
+ defaultValue: defaultProbability,
8047
+ onChange: onChangeProbability
8048
+ }, probablityOptions.map(probability => ( /*#__PURE__*/React.createElement(MenuItem, {
8049
+ value: probability,
8050
+ key: probability
8051
+ }, probability, " %"))));
8245
8052
  };
8246
8053
 
8247
8054
  const getEmptyPublicWarning = () => {
@@ -8294,7 +8101,6 @@ const spinnerSx = {
8294
8101
  margin: 'auto',
8295
8102
  marginLeft: 1
8296
8103
  };
8297
- const probablityOptions = [100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0];
8298
8104
  const ContainerWrapper = styled('div')(() => ({
8299
8105
  containerType: 'size',
8300
8106
  height: '100%'
@@ -8522,16 +8328,10 @@ const Form = ({
8522
8328
  item: true,
8523
8329
  xs: 12,
8524
8330
  sm: 6
8525
- }, /*#__PURE__*/React.createElement(ReactHookFormSelect, {
8526
- name: "probability",
8527
- label: t('warning-probability'),
8528
- rules: {},
8529
- disabled: areFieldsDisabled || _isReadOnly2,
8331
+ }, /*#__PURE__*/React.createElement(ProbabilityField, {
8332
+ isDisabled: areFieldsDisabled,
8530
8333
  isReadOnly: _isReadOnly2
8531
- }, probablityOptions.map(probability => ( /*#__PURE__*/React.createElement(MenuItem, {
8532
- value: probability,
8533
- key: probability
8534
- }, probability, " %")))))), /*#__PURE__*/React.createElement(Grid, {
8334
+ }))), /*#__PURE__*/React.createElement(Grid, {
8535
8335
  item: true,
8536
8336
  xs: 12,
8537
8337
  container: true,
@@ -8618,6 +8418,7 @@ const PublicWarningsForm = props => {
8618
8418
  const defaultValues = getFormData(publicWarningDetails, object);
8619
8419
  return /*#__PURE__*/React.createElement(ReactHookFormProvider, {
8620
8420
  options: Object.assign(Object.assign({}, defaultFormOptions), {
8421
+ mode: 'onSubmit',
8621
8422
  defaultValues
8622
8423
  })
8623
8424
  }, /*#__PURE__*/React.createElement(Form, Object.assign({}, props)));
@@ -9101,7 +8902,8 @@ const WarningsOnStatus = ({
9101
8902
  marginLeft: -0.5
9102
8903
  }
9103
8904
  }, ((_a = warning.warningDetail) === null || _a === void 0 ? void 0 : _a.level) && (levelDetails === null || levelDetails === void 0 ? void 0 : levelDetails.title) || '-')), /*#__PURE__*/React__default.createElement(WarningListColumnContent, {
9104
- status: status
8905
+ status: status,
8906
+ width: 96
9105
8907
  }, status === 'DRAFT' ? ( /*#__PURE__*/React__default.createElement(Box, {
9106
8908
  sx: {
9107
8909
  position: 'relative',
@@ -9509,16 +9311,308 @@ const componentsLookUp = (payload, apiProps) => {
9509
9311
  switch (componentType) {
9510
9312
  case warningListViewPreset.componentType:
9511
9313
  if (apiProps && apiProps.config) {
9512
- return /*#__PURE__*/React.createElement(WarningsTranslationsWrapper, null, /*#__PURE__*/React.createElement(PublicWarningApiWrapper, Object.assign({}, apiProps, {
9314
+ return /*#__PURE__*/React.createElement(PublicWarningApiWrapper, Object.assign({}, apiProps, {
9513
9315
  "data-testid": "publicWarningModule"
9514
- })));
9316
+ }));
9515
9317
  }
9516
- return /*#__PURE__*/React.createElement(WarningsTranslationsWrapper, null, /*#__PURE__*/React.createElement(PublicWarningListConnect, {
9318
+ return /*#__PURE__*/React.createElement(PublicWarningListConnect, {
9517
9319
  "data-testid": "publicWarningList"
9518
- }));
9320
+ });
9519
9321
  default:
9520
9322
  return null;
9521
9323
  }
9522
9324
  };
9523
9325
 
9524
- export { DrawingToolConnect, Wrapper as DrawingToolForm, DrawingToolFormConnect, DrawingToolMapButtonConnect, ObjectManagerConnect, ObjectManagerMapButtonConnect, PublicWarningApiWrapper, PublicWarningsFormDialog, PublicWarningsFormDialogConnect, WarningsModuleProvider, componentsLookUp, drawingModuleConfig, isAlreadyEdited, useObjectDrawDialogAction, warningFormConfirmationOptions };
9326
+ const getErrorMessage = error => isAxiosError(error) ? getAxiosErrorMessage(error) : error.message;
9327
+ const getToggleEditorSuccessMessage = isEditor => outsideComponentTranslations[isEditor ? 'warning-editor-add-editor' : 'warning-editor-remove-editor'];
9328
+ const publicWarningFormListener = createListenerMiddleware();
9329
+ publicWarningFormListener.startListening({
9330
+ actionCreator: publicWarningFormActions.toggleEditorWarning,
9331
+ effect: ({
9332
+ payload
9333
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9334
+ listenerApi.cancelActiveListeners();
9335
+ try {
9336
+ const {
9337
+ warningId,
9338
+ isEditor,
9339
+ username
9340
+ } = payload;
9341
+ const warningsApi = getWarningsApi();
9342
+ yield warningsApi.toggleEditorWarning(warningId, isEditor);
9343
+ // update list to show correct avatar
9344
+ listenerApi.dispatch(publicWarningActions.fetchWarnings());
9345
+ listenerApi.dispatch(publicWarningFormActions.toggleEditorWarningSuccess({
9346
+ isEditor,
9347
+ username,
9348
+ message: getToggleEditorSuccessMessage(isEditor)
9349
+ }));
9350
+ } catch (error) {
9351
+ const isDialogOpen = uiSelectors.getisDialogOpen(listenerApi.getState(), publicWarningDialogType);
9352
+ errorEffect(listenerApi.dispatch, getErrorMessage(error), isDialogOpen);
9353
+ }
9354
+ })
9355
+ });
9356
+ publicWarningFormListener.startListening({
9357
+ actionCreator: publicWarningFormActions.publishWarning,
9358
+ effect: ({
9359
+ payload
9360
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9361
+ listenerApi.cancelActiveListeners();
9362
+ try {
9363
+ const {
9364
+ publicWarning
9365
+ } = payload;
9366
+ const publishedWarning = yield saveOrUpdateWarning(publicWarning);
9367
+ listenerApi.dispatch(publicWarningFormActions.publishWarningSuccess({
9368
+ publicWarning: publishedWarning,
9369
+ message: outsideComponentTranslations['warning-publish-succes']
9370
+ }));
9371
+ listenerApi.dispatch(uiActions.setToggleOpenDialog({
9372
+ type: publicWarningDialogType,
9373
+ setOpen: false
9374
+ }));
9375
+ } catch (error) {
9376
+ const isDialogOpen = uiSelectors.getisDialogOpen(listenerApi.getState(), publicWarningDialogType);
9377
+ errorEffect(listenerApi.dispatch, getErrorMessage(error), isDialogOpen);
9378
+ }
9379
+ })
9380
+ });
9381
+ publicWarningFormListener.startListening({
9382
+ actionCreator: publicWarningFormActions.saveWarning,
9383
+ effect: ({
9384
+ payload
9385
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9386
+ listenerApi.cancelActiveListeners();
9387
+ try {
9388
+ const {
9389
+ publicWarning
9390
+ } = payload;
9391
+ const savedWarning = yield saveOrUpdateWarning(publicWarning);
9392
+ listenerApi.dispatch(publicWarningFormActions.saveWarningSuccess({
9393
+ publicWarning: savedWarning,
9394
+ message: outsideComponentTranslations['warning-save-succes']
9395
+ }));
9396
+ } catch (error) {
9397
+ const isDialogOpen = uiSelectors.getisDialogOpen(listenerApi.getState(), publicWarningDialogType);
9398
+ errorEffect(listenerApi.dispatch, getErrorMessage(error), isDialogOpen);
9399
+ }
9400
+ })
9401
+ });
9402
+ // Side effects/snackbar listeners
9403
+ publicWarningFormListener.startListening({
9404
+ matcher: isAnyOf(publicWarningFormActions.publishWarningSuccess, publicWarningFormActions.saveWarningSuccess, publicWarningFormActions.toggleEditorWarningSuccess),
9405
+ effect: ({
9406
+ payload
9407
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9408
+ listenerApi.cancelActiveListeners();
9409
+ const {
9410
+ message
9411
+ } = payload;
9412
+ listenerApi.dispatch(snackbarActions.openSnackbar({
9413
+ message
9414
+ }));
9415
+ const isDialogOpen = uiSelectors.getisDialogOpen(listenerApi.getState(), publicWarningDialogType);
9416
+ toggleDialogLoadingEffect(listenerApi.dispatch, isDialogOpen, false);
9417
+ })
9418
+ });
9419
+ publicWarningFormListener.startListening({
9420
+ matcher: isAnyOf(publicWarningFormActions.publishWarning, publicWarningFormActions.saveWarning),
9421
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9422
+ listenerApi.cancelActiveListeners();
9423
+ const isDialogOpen = uiSelectors.getisDialogOpen(listenerApi.getState(), publicWarningDialogType);
9424
+ toggleDialogLoadingEffect(listenerApi.dispatch, isDialogOpen, true);
9425
+ })
9426
+ });
9427
+ publicWarningFormListener.startListening({
9428
+ actionCreator: publicWarningFormActions.openPublicWarningFormDialog,
9429
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9430
+ listenerApi.cancelActiveListeners();
9431
+ listenerApi.dispatch(uiActions.setToggleOpenDialog({
9432
+ setOpen: true,
9433
+ type: publicWarningDialogType
9434
+ }));
9435
+ })
9436
+ });
9437
+ const saveOrUpdateWarning = publicWarning => __awaiter(void 0, void 0, void 0, function* () {
9438
+ const warningsApi = getWarningsApi();
9439
+ if (publicWarning.warningDetail.id) {
9440
+ yield warningsApi.updateWarning(publicWarning.warningDetail.id, publicWarning);
9441
+ return publicWarning;
9442
+ }
9443
+ const newWarningId = yield warningsApi.saveWarningAs(publicWarning);
9444
+ return Object.assign(Object.assign({}, publicWarning), {
9445
+ warningDetail: Object.assign(Object.assign({}, publicWarning.warningDetail), {
9446
+ id: newWarningId
9447
+ })
9448
+ });
9449
+ });
9450
+ const toggleDialogLoadingEffect = (dispatch, isDialogOpen, isLoading) => {
9451
+ if (isDialogOpen) {
9452
+ dispatch(uiActions.toggleIsLoadingDialog({
9453
+ isLoading,
9454
+ type: publicWarningDialogType
9455
+ }));
9456
+ }
9457
+ };
9458
+ const errorEffect = (dispatch, message, isDialogOpen) => {
9459
+ dispatch(publicWarningFormActions.setFormError({
9460
+ message
9461
+ }));
9462
+ toggleDialogLoadingEffect(dispatch, isDialogOpen, false);
9463
+ };
9464
+
9465
+ /* *
9466
+ * Licensed under the Apache License, Version 2.0 (the "License");
9467
+ * you may not use this file except in compliance with the License.
9468
+ * You may obtain a copy of the License at
9469
+ *
9470
+ * http://www.apache.org/licenses/LICENSE-2.0
9471
+ *
9472
+ * Unless required by applicable law or agreed to in writing, software
9473
+ * distributed under the License is distributed on an "AS IS" BASIS,
9474
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9475
+ * See the License for the specific language governing permissions and
9476
+ * limitations under the License.
9477
+ *
9478
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
9479
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
9480
+ * */
9481
+ const getLastUpdatedTimeFormatted = () => dateUtils.dateToString(dateUtils.utc(), DATE_FORMAT_LASTUPDATEDTIME);
9482
+ const publicWarningsListener = createListenerMiddleware();
9483
+ publicWarningsListener.startListening({
9484
+ actionCreator: publicWarningActions.fetchWarnings,
9485
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9486
+ listenerApi.cancelActiveListeners();
9487
+ try {
9488
+ const warningsApi = getWarningsApi();
9489
+ const {
9490
+ data: warnings
9491
+ } = yield warningsApi.getWarnings();
9492
+ const lastUpdatedTime = getLastUpdatedTimeFormatted();
9493
+ listenerApi.dispatch(publicWarningActions.fetchWarningsSuccess({
9494
+ warnings,
9495
+ lastUpdatedTime
9496
+ }));
9497
+ yield listenerApi.delay(pollingIntervalTimeout);
9498
+ listenerApi.dispatch(publicWarningActions.fetchWarnings());
9499
+ } catch (error) {
9500
+ // Don't set an error if the cancelActiveListeners was invoked (which throws a TaskAbortError)
9501
+ if ((error === null || error === void 0 ? void 0 : error.code) !== 'listener-cancelled') {
9502
+ listenerApi.dispatch(publicWarningActions.fetchWarningsError({
9503
+ error: {
9504
+ name: error.name,
9505
+ message: error.message
9506
+ }
9507
+ }));
9508
+ }
9509
+ }
9510
+ })
9511
+ });
9512
+ publicWarningsListener.startListening({
9513
+ matcher: isAnyOf(publicWarningFormActions.publishWarningSuccess, publicWarningFormActions.saveWarningSuccess),
9514
+ effect: (_, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9515
+ listenerApi.cancelActiveListeners();
9516
+ listenerApi.dispatch(publicWarningActions.fetchWarnings());
9517
+ })
9518
+ });
9519
+
9520
+ /* *
9521
+ * Licensed under the Apache License, Version 2.0 (the "License");
9522
+ * you may not use this file except in compliance with the License.
9523
+ * You may obtain a copy of the License at
9524
+ *
9525
+ * http://www.apache.org/licenses/LICENSE-2.0
9526
+ *
9527
+ * Unless required by applicable law or agreed to in writing, software
9528
+ * distributed under the License is distributed on an "AS IS" BASIS,
9529
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9530
+ * See the License for the specific language governing permissions and
9531
+ * limitations under the License.
9532
+ *
9533
+ * Copyright 2024 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
9534
+ * Copyright 2024 - Finnish Meteorological Institute (FMI)
9535
+ * */
9536
+ const getSnackbarMessage = (objectName, id) => id ? `Object "${objectName}" ${outsideComponentTranslations['update-succes']}!` : `Object "${objectName}" ${outsideComponentTranslations['save-succes']}!`;
9537
+ const drawingsListener = createListenerMiddleware();
9538
+ drawingsListener.startListening({
9539
+ actionCreator: drawActions.submitDrawValues,
9540
+ effect: ({
9541
+ payload
9542
+ }, listenerApi) => __awaiter(void 0, void 0, void 0, function* () {
9543
+ listenerApi.cancelActiveListeners();
9544
+ const {
9545
+ id
9546
+ } = payload,
9547
+ formValues = __rest(payload, ["id"]);
9548
+ try {
9549
+ listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
9550
+ isLoading: true,
9551
+ type: drawingDialogType
9552
+ }));
9553
+ const warningsApi = getWarningsApi();
9554
+ if (!id) {
9555
+ const newID = yield warningsApi.saveDrawingAs(formValues);
9556
+ listenerApi.dispatch(drawActions.setDrawValues({
9557
+ drawingInstanceId: drawingDialogType,
9558
+ id: newID,
9559
+ objectName: formValues.objectName
9560
+ }));
9561
+ } else {
9562
+ yield warningsApi.updateDrawing(id, formValues);
9563
+ }
9564
+ listenerApi.dispatch(uiActions.setErrorDialog({
9565
+ type: drawingDialogType,
9566
+ error: ''
9567
+ }));
9568
+ listenerApi.dispatch(snackbarActions.openSnackbar({
9569
+ message: getSnackbarMessage(formValues.objectName, id)
9570
+ }));
9571
+ listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
9572
+ isLoading: false,
9573
+ type: drawingDialogType
9574
+ }));
9575
+ } catch (error) {
9576
+ // Don't do anything if the cancelActiveListeners was invoked (which throws a TaskAbortError)
9577
+ if (error.code !== 'listener-cancelled') {
9578
+ listenerApi.dispatch(uiActions.toggleIsLoadingDialog({
9579
+ isLoading: false,
9580
+ type: drawingDialogType
9581
+ }));
9582
+ const errorMessage = isAxiosError$1(error) ? getAxiosErrorMessage(error) : error.message;
9583
+ listenerApi.dispatch(uiActions.setErrorDialog({
9584
+ type: drawingDialogType,
9585
+ error: errorMessage
9586
+ }));
9587
+ }
9588
+ }
9589
+ })
9590
+ });
9591
+
9592
+ /* *
9593
+ * Licensed under the Apache License, Version 2.0 (the "License");
9594
+ * you may not use this file except in compliance with the License.
9595
+ * You may obtain a copy of the License at
9596
+ *
9597
+ * http://www.apache.org/licenses/LICENSE-2.0
9598
+ *
9599
+ * Unless required by applicable law or agreed to in writing, software
9600
+ * distributed under the License is distributed on an "AS IS" BASIS,
9601
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9602
+ * See the License for the specific language governing permissions and
9603
+ * limitations under the License.
9604
+ *
9605
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
9606
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
9607
+ * */
9608
+ const drawingModuleConfig = {
9609
+ id: 'drawing-module',
9610
+ reducersMap: {
9611
+ drawings: reducer$2,
9612
+ publicWarningForm: reducer,
9613
+ publicWarnings: reducer$1
9614
+ },
9615
+ middlewares: [drawingsListener.middleware, publicWarningsListener.middleware, publicWarningFormListener.middleware]
9616
+ };
9617
+
9618
+ export { DrawingToolConnect, Wrapper as DrawingToolForm, DrawingToolFormConnect, DrawingToolMapButtonConnect, ObjectManagerConnect, ObjectManagerMapButtonConnect, PublicWarningApiWrapper, PublicWarningsFormDialog, PublicWarningsFormDialogConnect, WarningsModuleProvider, componentsLookUp, drawingModuleConfig, isAlreadyEdited, useObjectDrawDialogAction, warningFormConfirmationOptions, warningsTranslations };