@opengeoweb/taf 4.11.0 → 4.12.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,17 +1,17 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
- import { TextField, Grid, Box, Button, IconButton, Chip, Typography, FormLabel, Switch, Card, Tabs, Tab, Dialog, MenuList, MenuItem, Backdrop, CircularProgress } from '@mui/material';
3
+ import { Grid, Button, IconButton, Chip, Box, Typography, FormLabel, Switch, TextField, Card, Tabs, Tab, Dialog, MenuList, MenuItem, Backdrop, CircularProgress } from '@mui/material';
4
4
  import { useFormContext, Controller, useFieldArray } from 'react-hook-form';
5
5
  import { useDispatch } from 'react-redux';
6
6
  import { ReactSortable } from 'react-sortablejs';
7
7
  import Sortable from 'sortablejs';
8
8
  import { useAuthenticationContext } from '@opengeoweb/authentication';
9
9
  import { getDeepProperty, ReactHookFormHiddenInput, ReactHookFormProvider } from '@opengeoweb/form-fields';
10
- import { HIDDEN_INPUT_HELPER_IS_DRAFT, useIsMounted, ToggleMenu, CustomTooltip, ToolContainerDraggable, Avatar, getInitials, useConfirmationDialog, useDraftFormHelpers, usePreventBrowserClose, ToolButton, ToolHeader, AlertBanner, getErrorMessage as getErrorMessage$1, getWarningMessage, ConfirmationServiceProvider, usePoller, ErrorBoundary } from '@opengeoweb/shared';
10
+ import { HIDDEN_INPUT_HELPER_IS_DRAFT, useIsMounted, CustomTooltip, ToolContainerDraggable, Avatar, getInitials, ToggleMenu, useConfirmationDialog, useDraftFormHelpers, usePreventBrowserClose, ToolButton, ToolHeader, AlertBanner, getErrorMessage as getErrorMessage$1, getWarningMessage, ConfirmationServiceProvider, usePoller, ErrorBoundary } from '@opengeoweb/shared';
11
11
  import { snackbarActions } from '@opengeoweb/core';
12
12
  import moment from 'moment';
13
13
  import { isEqual } from 'lodash';
14
- import { Add, Delete, Close, DragHandle as DragHandle$1, ThumbsUp, Clock, Cancel, Success, Edit, Export, ListItem, Cached } from '@opengeoweb/theme';
14
+ import { DragHandle as DragHandle$1, ThumbsUp, Add, Delete, Close, Clock, Cancel, Success, Edit, Export, ListItem, Cached } from '@opengeoweb/theme';
15
15
  import ReactDOM from 'react-dom';
16
16
  import { useApiContext, createApiInstance, createFakeApiInstance, ApiProvider } from '@opengeoweb/api';
17
17
  import LinearProgress from '@mui/material/LinearProgress';
@@ -157,6 +157,158 @@ function __awaiter(thisArg, _arguments, P, generator) {
157
157
  });
158
158
  }
159
159
 
160
+ /* *
161
+ * Licensed under the Apache License, Version 2.0 (the "License");
162
+ * you may not use this file except in compliance with the License.
163
+ * You may obtain a copy of the License at
164
+ *
165
+ * http://www.apache.org/licenses/LICENSE-2.0
166
+ *
167
+ * Unless required by applicable law or agreed to in writing, software
168
+ * distributed under the License is distributed on an "AS IS" BASIS,
169
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
170
+ * See the License for the specific language governing permissions and
171
+ * limitations under the License.
172
+ *
173
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
174
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
175
+ * */
176
+ var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
177
+ switch (tafAction) {
178
+ case 'AMEND':
179
+ case 'DRAFT_AMEND':
180
+ return 'DRAFT_AMEND';
181
+
182
+ case 'CORRECT':
183
+ case 'DRAFT_CORRECT':
184
+ return 'DRAFT_CORRECT';
185
+
186
+ default:
187
+ return 'DRAFT';
188
+ }
189
+ };
190
+
191
+ var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
192
+ switch (tafAction) {
193
+ case 'AMEND':
194
+ case 'DRAFT_AMEND':
195
+ return 'AMEND';
196
+
197
+ case 'CORRECT':
198
+ case 'DRAFT_CORRECT':
199
+ return 'CORRECT';
200
+
201
+ default:
202
+ return 'PUBLISH';
203
+ }
204
+ };
205
+
206
+ var buttonsStyle = {
207
+ button: {
208
+ minWidth: {
209
+ xs: '56px',
210
+ sm: '64px'
211
+ },
212
+ width: {
213
+ xs: '56px',
214
+ sm: '64px'
215
+ },
216
+ marginLeft: {
217
+ xs: 0.5,
218
+ sm: 1
219
+ },
220
+ marginTop: 3,
221
+ marginBottom: 3
222
+ }
223
+ };
224
+
225
+ var ViewModeButtons = function ViewModeButtons(_ref) {
226
+ var canBe = _ref.canBe,
227
+ onTafViewModeButtonPress = _ref.onTafViewModeButtonPress;
228
+ return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default.createElement(Button, {
229
+ "data-testid": "canceltaf",
230
+ variant: "tertiary",
231
+ onClick: function onClick() {
232
+ return onTafViewModeButtonPress('CANCEL');
233
+ }
234
+ }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
235
+ "data-testid": "correcttaf",
236
+ variant: "tertiary",
237
+ onClick: function onClick() {
238
+ return onTafViewModeButtonPress('CORRECT');
239
+ }
240
+ }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default.createElement(Button, {
241
+ "data-testid": "amendtaf",
242
+ variant: "tertiary",
243
+ onClick: function onClick() {
244
+ return onTafViewModeButtonPress('AMEND');
245
+ }
246
+ }, "Amend"));
247
+ };
248
+
249
+ var TafFormButtons = function TafFormButtons(_ref2) {
250
+ var _ref2$isFormDisabled = _ref2.isFormDisabled,
251
+ isFormDisabled = _ref2$isFormDisabled === void 0 ? false : _ref2$isFormDisabled,
252
+ tafAction = _ref2.tafAction,
253
+ _ref2$canBe = _ref2.canBe,
254
+ canBe = _ref2$canBe === void 0 ? [] : _ref2$canBe,
255
+ onTafEditModeButtonPress = _ref2.onTafEditModeButtonPress,
256
+ onTafViewModeButtonPress = _ref2.onTafViewModeButtonPress;
257
+ return /*#__PURE__*/React__default.createElement(Grid, {
258
+ container: true,
259
+ justifyContent: "flex-end",
260
+ sx: buttonsStyle,
261
+ columns: 24
262
+ }, /*#__PURE__*/React__default.createElement(Grid, {
263
+ item: true,
264
+ container: true,
265
+ justifyContent: "flex-end",
266
+ columns: 24,
267
+ xs: 24,
268
+ sm: 23
269
+ }, isFormDisabled ? /*#__PURE__*/React__default.createElement(ViewModeButtons, {
270
+ canBe: canBe,
271
+ onTafViewModeButtonPress: onTafViewModeButtonPress
272
+ }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
273
+ "data-testid": "cleartaf",
274
+ variant: "tertiary",
275
+ onClick: function onClick() {
276
+ // Simply discard the changes and close the dialog.
277
+ onTafEditModeButtonPress('CLEAR');
278
+ }
279
+ }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
280
+ "data-testid": "savedrafttaf",
281
+ variant: "tertiary",
282
+ onClick: function onClick() {
283
+ /* Save the TAF as draft:
284
+ if action NEW or DRAFT - new status will be DRAFT -- default
285
+ if action AMEND - new status will be DRAFT_AMENDED
286
+ if action CORRECT - new status will be DRAFT_CORRECTED
287
+ if action DRAFT_AMEND - new status will be DRAFT_AMENDED
288
+ if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
289
+ */
290
+ onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
291
+ }
292
+ }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
293
+ "data-testid": "publishtaf",
294
+ variant: "tertiary",
295
+ onClick: function onClick() {
296
+ /* Publish the TAF:
297
+ if action NEW or DRAFT - new status will be PUBLISHED -- default
298
+ if action AMEND - new status will be AMENDED
299
+ if action CORRECT - new status will be CORRECTED
300
+ if action DRAFT_AMEND - new status will be AMENDED
301
+ if action DRAFT_CORRECT - new status will be CORRECTED
302
+ */
303
+ onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
304
+ }
305
+ }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
306
+ item: true,
307
+ columns: 24,
308
+ sm: 1
309
+ }));
310
+ };
311
+
160
312
  /* *
161
313
  * Licensed under the Apache License, Version 2.0 (the "License");
162
314
  * you may not use this file except in compliance with the License.
@@ -459,8 +611,8 @@ var validateOverlapWithFM = function validateOverlapWithFM(currentChangeGroup, n
459
611
  * See the License for the specific language governing permissions and
460
612
  * limitations under the License.
461
613
  *
462
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
463
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
614
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
615
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
464
616
  * */
465
617
  var prependZeroes = function prependZeroes(value, totalDigits) {
466
618
  var valueAsString = value.toString();
@@ -468,6 +620,9 @@ var prependZeroes = function prependZeroes(value, totalDigits) {
468
620
  return "0".concat(newVal);
469
621
  }, valueAsString);
470
622
  };
623
+ var getFieldValue = function getFieldValue(fieldValue) {
624
+ return fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.trim().toUpperCase();
625
+ };
471
626
 
472
627
  var config$1 = [{
473
628
  key: 'range',
@@ -2431,7 +2586,8 @@ var getConfirmationDialogTitle = function getConfirmationDialogTitle(action) {
2431
2586
  }; // Check if the amended/corrected TAF has been changed. Only compare the fields users are able to fill in
2432
2587
  // (i.e. exclude baseforecast valid time as that gets updated when doing an amendment automatically outside of the users influence)
2433
2588
 
2434
- var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormDirty, originalTaf, currentTaf) {
2589
+ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(originalTaf, currentTaf) {
2590
+ if (originalTaf === null || currentTaf === null) return false;
2435
2591
  var originalBaseF = originalTaf.baseForecast,
2436
2592
  originalChG = originalTaf.changeGroups;
2437
2593
  var currentBaseF = currentTaf.baseForecast,
@@ -2443,7 +2599,7 @@ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormD
2443
2599
  currentBaseF.valid;
2444
2600
  var currentNoValid = __rest(currentBaseF, ["valid"]);
2445
2601
 
2446
- return isFormDirty && (!isEqual(originalNoValid, currentNoValid) || !isEqual(originalChG, currentChG));
2602
+ return !isEqual(originalNoValid, currentNoValid) || !isEqual(originalChG, currentChG);
2447
2603
  };
2448
2604
  var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
2449
2605
  switch (action) {
@@ -2495,13 +2651,30 @@ var emptyChangegroup = {
2495
2651
  change: '',
2496
2652
  probability: ''
2497
2653
  };
2498
- var getTafStatusLabel = function getTafStatusLabel(status) {
2654
+ var getTafStatusLabel = function getTafStatusLabel(status, action, isFormDisabled) {
2655
+ // See if we need to base status label on action if form is not disabled and action passed
2656
+ var baseOnAction = isFormDisabled !== undefined && !isFormDisabled && action;
2657
+
2658
+ if (baseOnAction && action === 'AMEND' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2659
+ return 'new amendment';
2660
+ }
2661
+
2662
+ if (baseOnAction && action === 'CORRECT' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2663
+ return 'new correction';
2664
+ }
2665
+
2499
2666
  switch (status) {
2500
2667
  case 'DRAFT_AMENDED':
2501
- return 'draft amended';
2668
+ return 'draft amendment';
2502
2669
 
2503
2670
  case 'DRAFT_CORRECTED':
2504
- return 'draft corrected';
2671
+ return 'draft correction';
2672
+
2673
+ case 'AMENDED':
2674
+ return 'published amendment';
2675
+
2676
+ case 'CORRECTED':
2677
+ return 'published correction';
2505
2678
 
2506
2679
  default:
2507
2680
  return status.toLocaleLowerCase();
@@ -2640,192 +2813,56 @@ var fromStatusToAction = function fromStatusToAction(tafStatus) {
2640
2813
  var isFormDirty = function isFormDirty(dirtyFields) {
2641
2814
  return Object.keys(dirtyFields).length > 0;
2642
2815
  };
2816
+ var getFormRowPosition = function getFormRowPosition(formRow) {
2817
+ var _formRow$getBoundingC = formRow.getBoundingClientRect(),
2818
+ top = _formRow$getBoundingC.top,
2819
+ left = _formRow$getBoundingC.left,
2820
+ height = _formRow$getBoundingC.height;
2643
2821
 
2644
- var textFieldStyle = function textFieldStyle(theme) {
2822
+ var newTop = top + height;
2645
2823
  return {
2646
- // input
2647
- marginRight: '2px',
2648
- marginBottom: '4px',
2649
- width: 56,
2650
- height: 46,
2651
- input: {
2652
- textAlign: 'center',
2653
- fontSize: 10,
2654
- fontWeight: 500,
2655
- paddingLeft: 0,
2656
- paddingRight: 0,
2657
- '&.Mui-disabled': {
2658
- color: 'geowebColors.typographyAndIcons.text',
2659
- WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
2660
- },
2661
- // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
2662
- '&:-webkit-autofill': {
2663
- WebkitTransitionDelay: '86400s' // 1 day delay
2824
+ top: newTop,
2825
+ left: left
2826
+ };
2827
+ };
2664
2828
 
2665
- }
2666
- },
2667
- label: {
2668
- transformOrigin: 'center top',
2669
- right: 0,
2670
- textAlign: 'center',
2671
- fontSize: '10px',
2672
- '&.Mui-disabled': {
2673
- color: 'geowebColors.captions.captionStatus.rgba'
2674
- },
2675
- whiteSpace: 'nowrap',
2676
- maxWidth: '100%',
2677
- transform: 'translate(0px, 16px) scale(1)'
2678
- },
2679
- // shrink
2680
- ' .MuiInputLabel-shrink': {
2681
- transform: 'translate(2px, 10px) scale(0.75) !important',
2682
- letterSpacing: '0.33px',
2683
- textAlign: 'left'
2684
- },
2685
- // root
2686
- '&': {
2687
- '.Mui-error.MuiFilledInput-root': {
2688
- backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
2829
+ /* *
2830
+ * Licensed under the Apache License, Version 2.0 (the "License");
2831
+ * you may not use this file except in compliance with the License.
2832
+ * You may obtain a copy of the License at
2833
+ *
2834
+ * http://www.apache.org/licenses/LICENSE-2.0
2835
+ *
2836
+ * Unless required by applicable law or agreed to in writing, software
2837
+ * distributed under the License is distributed on an "AS IS" BASIS,
2838
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2839
+ * See the License for the specific language governing permissions and
2840
+ * limitations under the License.
2841
+ *
2842
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2843
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
2844
+ * */
2845
+
2846
+ var DragHandle = function DragHandle(_ref) {
2847
+ var _ref$isSorting = _ref.isSorting,
2848
+ isSorting = _ref$isSorting === void 0 ? false : _ref$isSorting,
2849
+ _ref$isDisabled = _ref.isDisabled,
2850
+ isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
2851
+ index = _ref.index;
2852
+ return /*#__PURE__*/React__default.createElement(IconButton, {
2853
+ className: "handle",
2854
+ "data-testid": "dragHandle-".concat(index),
2855
+ disableRipple: true,
2856
+ disabled: isDisabled,
2857
+ size: "large",
2858
+ sx: {
2859
+ backgroundColor: 'transparent',
2860
+ '&:hover': {
2861
+ backgroundColor: 'transparent'
2689
2862
  },
2690
- '.Mui-disabled:before': {
2691
- borderColor: 'transparent'
2692
- }
2863
+ cursor: isSorting ? 'grabbing' : 'grab'
2693
2864
  }
2694
- };
2695
- };
2696
-
2697
- var getTafErrors = function getTafErrors(name, errors) {
2698
- var nameAsArray = name.split('.');
2699
-
2700
- if (nameAsArray[0].includes('changeGroups')) {
2701
- if (errors.changeGroups) {
2702
- var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
2703
- var restArray = nameAsArray.slice(1);
2704
- return getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
2705
- } // No changegroup errors
2706
-
2707
-
2708
- return null;
2709
- }
2710
-
2711
- return getDeepProperty(nameAsArray, errors);
2712
- };
2713
-
2714
- var getDisplayValue = function getDisplayValue(value, disabled) {
2715
- return disabled && !value ? '-' : value;
2716
- };
2717
- var BaseTextField = /*#__PURE__*/React__default.memo(function (props) {
2718
- return /*#__PURE__*/React__default.createElement(TextField, Object.assign({
2719
- type: "text",
2720
- variant: "filled",
2721
- sx: textFieldStyle
2722
- }, props));
2723
- }, function (prevProps, nextProps) {
2724
- return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
2725
- });
2726
-
2727
- var TafFormTextField = function TafFormTextField(_ref) {
2728
- var label = _ref.label,
2729
- _ref$disabled = _ref.disabled,
2730
- disabled = _ref$disabled === void 0 ? false : _ref$disabled,
2731
- _ref$name = _ref.name,
2732
- name = _ref$name === void 0 ? '' : _ref$name,
2733
- _ref$onChange = _ref.onChange,
2734
- onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
2735
- _ref$onBlur = _ref.onBlur,
2736
- onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
2737
- _ref$defaultValue = _ref.defaultValue,
2738
- defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
2739
- _ref$formatter = _ref.formatter,
2740
- formatter = _ref$formatter === void 0 ? null : _ref$formatter,
2741
- rules = _ref.rules,
2742
- _ref$autoComplete = _ref.autoComplete,
2743
- autoComplete = _ref$autoComplete === void 0 ? [] : _ref$autoComplete,
2744
- _ref$autoFocus = _ref.autoFocus,
2745
- autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus;
2746
-
2747
- var _useFormContext = useFormContext(),
2748
- control = _useFormContext.control,
2749
- setValue = _useFormContext.setValue,
2750
- errors = _useFormContext.formState.errors;
2751
-
2752
- var fieldErrors = getTafErrors(name, errors);
2753
-
2754
- var _React$useState = React__default.useState(null),
2755
- _React$useState2 = _slicedToArray(_React$useState, 2),
2756
- maxLength = _React$useState2[0],
2757
- setMaxLength = _React$useState2[1];
2758
-
2759
- var onKeyDown = React__default.useCallback(function (event) {
2760
- var target = event.target;
2761
- var currentValue = target.value,
2762
- selectionStart = target.selectionStart,
2763
- selectionEnd = target.selectionEnd;
2764
- var textSelection = currentValue.substring(selectionStart, selectionEnd);
2765
-
2766
- if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
2767
- var pressedKey = event.key.toString().toUpperCase();
2768
- var foundValue = autoComplete.find(function (el) {
2769
- return el.key === pressedKey;
2770
- }) || null;
2771
-
2772
- if (foundValue) {
2773
- setValue(name, foundValue.value, {
2774
- shouldDirty: true
2775
- });
2776
- setMaxLength(foundValue.value.length);
2777
- event.preventDefault();
2778
- }
2779
- }
2780
- }, [name, autoComplete, setValue]);
2781
- var onChangeField = React__default.useCallback(function (event, callback) {
2782
- var valueUppercase = event.currentTarget.value.toUpperCase();
2783
-
2784
- if (autoComplete) {
2785
- var exist = autoComplete.find(function (e) {
2786
- return e.value === valueUppercase;
2787
- });
2788
- var newMaxLength = exist ? valueUppercase.length : null;
2789
- setMaxLength(newMaxLength);
2790
- }
2791
-
2792
- callback(valueUppercase);
2793
- onChange(valueUppercase);
2794
- }, [onChange, autoComplete]);
2795
- var onBlurField = React__default.useCallback(function (callback) {
2796
- callback();
2797
- onBlur();
2798
- }, [onBlur]);
2799
- var hasError = !!fieldErrors;
2800
- return /*#__PURE__*/React__default.createElement(Controller, {
2801
- render: function render(_ref2) {
2802
- var field = _ref2.field;
2803
- var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
2804
- return /*#__PURE__*/React__default.createElement(BaseTextField, {
2805
- label: label,
2806
- disabled: disabled,
2807
- name: name,
2808
- value: displayValue,
2809
- inputRef: field.ref,
2810
- onChange: function onChange(e) {
2811
- return onChangeField(e, field.onChange);
2812
- },
2813
- onKeyDown: onKeyDown,
2814
- error: hasError,
2815
- onBlur: function onBlur() {
2816
- return onBlurField(field.onBlur);
2817
- },
2818
- inputProps: {
2819
- maxLength: maxLength
2820
- },
2821
- autoFocus: autoFocus
2822
- });
2823
- },
2824
- name: name,
2825
- control: control,
2826
- defaultValue: defaultValue,
2827
- rules: rules
2828
- });
2865
+ }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
2829
2866
  };
2830
2867
 
2831
2868
  /* *
@@ -2841,27 +2878,77 @@ var TafFormTextField = function TafFormTextField(_ref) {
2841
2878
  * See the License for the specific language governing permissions and
2842
2879
  * limitations under the License.
2843
2880
  *
2844
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2845
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2881
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2882
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
2846
2883
  * */
2847
- // messages
2848
- var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
2849
- var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
2850
-
2851
- var validateChangeField = function validateChangeField(value) {
2852
- var trimmedValue = value.trim();
2853
- var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
2854
- return isValid ? true : invalidChangeMessage;
2884
+ var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
2885
+ return Object.assign(Object.assign({}, error), {
2886
+ isChangeGroup: isChangeGroup,
2887
+ rowIndex: rowIndex
2888
+ });
2855
2889
  };
2856
- var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
2857
- var trimmedProbValue = valueProb.trim();
2858
- var trimmedValue = value.trim();
2890
+ var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
2891
+ switch (sumOfErrors) {
2892
+ case 0:
2893
+ return '0 issues';
2859
2894
 
2860
- if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
2861
- return invalidChangeProbCombinationMessage;
2895
+ case 1:
2896
+ return '1 issue';
2897
+
2898
+ default:
2899
+ return "".concat(sumOfErrors, " issues");
2862
2900
  }
2901
+ };
2902
+ var getErrorValues = function getErrorValues(fieldErrors) {
2903
+ var isChangeGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2904
+ var rowIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
2905
+ if (!fieldErrors) return [];
2906
+ return Object.keys(fieldErrors).reduce(function (list, key) {
2907
+ var error = Object.assign({}, fieldErrors[key]);
2863
2908
 
2864
- return true;
2909
+ if (error.ref) {
2910
+ return list.concat(getCustomError(error, isChangeGroup, rowIndex));
2911
+ }
2912
+
2913
+ return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
2914
+ }, []);
2915
+ };
2916
+ var filterDuplicateErrors = function filterDuplicateErrors(errors) {
2917
+ return errors.reduce(function (list, error) {
2918
+ // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
2919
+ if (error.type === 'validateRequiredSub') {
2920
+ var exist = list.find(function (e) {
2921
+ return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
2922
+ });
2923
+ return exist ? list : list.concat(error);
2924
+ }
2925
+
2926
+ if (error.type === 'validateRequiredMainOptional') {
2927
+ var _exist = list.find(function (e) {
2928
+ return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
2929
+ });
2930
+
2931
+ return _exist ? list : list.concat(error);
2932
+ }
2933
+
2934
+ return list.concat(error);
2935
+ }, []);
2936
+ };
2937
+ var getErrors = function getErrors(errors) {
2938
+ var errorList = Object.keys(errors).reduce(function (list, key) {
2939
+ var errorValue = errors[key]; // changeGroups
2940
+
2941
+ if (Array.isArray(errorValue)) {
2942
+ var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
2943
+ return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
2944
+ }, []);
2945
+ return list.concat.apply(list, _toConsumableArray(errorValues));
2946
+ } // baseForecast
2947
+
2948
+
2949
+ return list.concat(getErrorValues(errorValue, false, -1));
2950
+ }, []);
2951
+ return errorList;
2865
2952
  };
2866
2953
 
2867
2954
  /* *
@@ -2880,524 +2967,246 @@ var validateChangeFieldInterField = function validateChangeFieldInterField(value
2880
2967
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2881
2968
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
2882
2969
  * */
2883
- // messages
2884
- var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
2885
2970
 
2886
- var validateProbabilityField = function validateProbabilityField(value) {
2887
- var trimmedValue = value.trim();
2888
- var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
2889
- return isValid ? true : invalidProbabilityMessage;
2890
- };
2971
+ var IssuesButton = function IssuesButton(_ref) {
2972
+ var _ref$errors = _ref.errors,
2973
+ errors = _ref$errors === void 0 ? {} : _ref$errors,
2974
+ _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
2975
+ isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
2976
+ _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
2977
+ setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
2978
+ return null;
2979
+ } : _ref$setIsIssuesPaneO;
2980
+ var errorList = filterDuplicateErrors(getErrors(errors));
2981
+ var totalErrors = errorList.length;
2982
+ var errorStatus = totalErrors > 0 ? 'error' : 'success';
2983
+ var buttonColor = "geowebColors.functional.".concat(errorStatus);
2891
2984
 
2892
- /* *
2893
- * Licensed under the Apache License, Version 2.0 (the "License");
2894
- * you may not use this file except in compliance with the License.
2895
- * You may obtain a copy of the License at
2896
- *
2897
- * http://www.apache.org/licenses/LICENSE-2.0
2898
- *
2899
- * Unless required by applicable law or agreed to in writing, software
2900
- * distributed under the License is distributed on an "AS IS" BASIS,
2901
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2902
- * See the License for the specific language governing permissions and
2903
- * limitations under the License.
2904
- *
2905
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2906
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
2907
- * */
2985
+ var toggleIssuesPane = function toggleIssuesPane(newPosition) {
2986
+ return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
2987
+ };
2908
2988
 
2909
- var TafFormOptionsButton = function TafFormOptionsButton(_ref) {
2910
- var isChangeGroup = _ref.isChangeGroup,
2911
- addChangeGroupBelow = _ref.addChangeGroupBelow,
2912
- addChangeGroupAbove = _ref.addChangeGroupAbove,
2913
- removeChangeGroup = _ref.removeChangeGroup,
2914
- clearRow = _ref.clearRow,
2915
- index = _ref.index;
2916
- var insertAbove = {
2917
- text: 'Insert 1 row above',
2918
- icon: /*#__PURE__*/React.createElement(Add, null),
2919
- action: addChangeGroupAbove
2920
- };
2921
- var insertBelow = {
2922
- text: 'Insert 1 row below',
2923
- icon: /*#__PURE__*/React.createElement(Add, null),
2924
- action: addChangeGroupBelow
2925
- };
2926
- var deleteRow = {
2927
- text: 'Delete row',
2928
- icon: /*#__PURE__*/React.createElement(Delete, null),
2929
- action: removeChangeGroup
2930
- };
2931
- var clear = {
2932
- text: 'Clear row',
2933
- icon: /*#__PURE__*/React.createElement(Close, null),
2934
- action: clearRow
2935
- };
2936
- var menuItemsBaseForecast = [insertBelow, clear];
2937
- var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
2938
- return /*#__PURE__*/React.createElement(ToggleMenu, {
2939
- buttonTestId: "tafFormOptions[".concat(index, "]"),
2940
- buttonSx: {
2941
- marginTop: '10px',
2942
- marginLeft: '4px'
2943
- },
2944
- menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
2945
- });
2946
- };
2989
+ var onClickButton = function onClickButton(event) {
2990
+ var _a;
2947
2991
 
2948
- var getDefaultValue = function getDefaultValue(fieldName, data) {
2949
- if (!data) {
2950
- return '';
2951
- }
2992
+ var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
2993
+ left = _event$currentTarget$.left,
2994
+ top = _event$currentTarget$.top;
2952
2995
 
2953
- return getDeepProperty(fieldName.split('.'), data) || '';
2954
- };
2996
+ var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
2997
+ top: 0,
2998
+ left: 0
2999
+ };
3000
+ var newPosition = {
3001
+ left: left - parentOffset.left + 100,
3002
+ top: top - parentOffset.top
3003
+ };
3004
+ toggleIssuesPane(newPosition);
3005
+ };
2955
3006
 
2956
- var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
2957
- return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
2958
- ];
3007
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3008
+ title: "View details"
3009
+ }, /*#__PURE__*/React.createElement(Chip, {
3010
+ "data-testid": "issuesButton",
3011
+ className: "status-".concat(errorStatus),
3012
+ size: "small",
3013
+ label: getIssuesLabel(totalErrors),
3014
+ onClick: onClickButton,
3015
+ sx: {
3016
+ width: '74px',
3017
+ color: '#ffffff',
3018
+ backgroundColor: buttonColor,
3019
+ '&:hover': {
3020
+ backgroundColor: buttonColor
3021
+ },
3022
+ '&:focus': {
3023
+ backgroundColor: buttonColor
3024
+ },
3025
+ fontSize: 12
3026
+ }
3027
+ }));
2959
3028
  };
2960
3029
 
2961
- var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2962
- var isNotRequiredForAction = _a.isNotRequiredForAction,
2963
- _a$isChangeGroup = _a.isChangeGroup,
2964
- isChangeGroup = _a$isChangeGroup === void 0 ? false : _a$isChangeGroup,
2965
- _a$disabled = _a.disabled,
2966
- disabled = _a$disabled === void 0 ? false : _a$disabled,
2967
- _a$index = _a.index,
2968
- index = _a$index === void 0 ? -1 : _a$index,
2969
- onRemoveChangeGroup = _a.onRemoveChangeGroup,
2970
- _a$field = _a.field,
2971
- field = _a$field === void 0 ? null : _a$field,
2972
- _a$dragHandle = _a.dragHandle,
2973
- dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
2974
- onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
2975
- onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
2976
- onClearRow = _a.onClearRow,
2977
- props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
2978
-
2979
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
2980
- var fieldNames = getFieldNames(isChangeGroup, index);
2981
-
2982
- var _useFormContext = useFormContext(),
2983
- getValues = _useFormContext.getValues,
2984
- trigger = _useFormContext.trigger; // cross-field required validation
2985
-
2986
-
2987
- var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
2988
- _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
2989
- mainFields = _getRequiredCrossFiel2[0],
2990
- mainOptionalFields = _getRequiredCrossFiel2[1],
2991
- subFields = _getRequiredCrossFiel2[2];
2992
-
2993
- var hasFieldsValue = function hasFieldsValue(fields) {
2994
- return fields.map(getValues).find(function (field) {
2995
- return !!field;
2996
- });
2997
- }; // Used to validate the required field for change groups: Valid
2998
-
2999
-
3000
- var validateRequiredMain = function validateRequiredMain(value) {
3001
- return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3002
- }; // Used to ensure either probability or change is entered, or both
3003
-
3004
-
3005
- var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3006
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3007
- }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
3008
-
3009
-
3010
- var validateRequiredSub = function validateRequiredSub(value) {
3011
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3012
- }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3030
+ var getPaneTitle = function getPaneTitle(sumOfErrors) {
3031
+ switch (sumOfErrors) {
3032
+ case 0:
3033
+ return 'Looks good';
3013
3034
 
3035
+ case 1:
3036
+ return 'There is an issue to address';
3014
3037
 
3015
- var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3016
- var changeField = getValues("".concat(namePrefix, ".change"));
3017
- var visibilityField = getValues("".concat(namePrefix, ".visibility"));
3018
- var isFM = changeField && changeField.trim() === 'FM';
3019
- var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3038
+ default:
3039
+ return 'There are a few issues to address';
3040
+ }
3041
+ };
3020
3042
 
3021
- if (isNotRequiredForAction(value) !== true && !value.length) {
3022
- if (isChangeGroup && isFM || !isChangeGroup) {
3023
- // exception for CavOK
3024
- if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3025
- return true;
3026
- } // exception for visibility > 5000
3043
+ var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3044
+ if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3045
+ // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3046
+ var fieldNumber = fieldNumberedValue + 1;
3047
+ return "".concat(errorTitle, " ").concat(fieldNumber);
3048
+ }
3027
3049
 
3050
+ return errorTitle;
3051
+ };
3052
+ var getErrorMessage = function getErrorMessage(error, index) {
3053
+ var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3054
+ var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3055
+ return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(error.message);
3056
+ };
3057
+ var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3058
+ var useIssuesPane = function useIssuesPane() {
3059
+ var _React$useState = React.useState(false),
3060
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3061
+ isIssuesPaneOpen = _React$useState2[0],
3062
+ setIsIssuesPaneOpen = _React$useState2[1];
3028
3063
 
3029
- if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3030
- return true;
3031
- }
3064
+ var _React$useState3 = React.useState(null),
3065
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3066
+ startPosition = _React$useState4[0],
3067
+ setStartPosition = _React$useState4[1];
3032
3068
 
3033
- return "".concat(fieldName, " is required");
3034
- }
3035
- }
3069
+ var _React$useState5 = React.useState(false),
3070
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
3071
+ hasUserDragged = _React$useState6[0],
3072
+ setHasUserDragged = _React$useState6[1];
3036
3073
 
3037
- return true;
3074
+ var onUserHasDragged = function onUserHasDragged() {
3075
+ return setHasUserDragged(true);
3038
3076
  };
3039
3077
 
3040
- var validatePreviousRow = React__default.useCallback(function () {
3041
- if (isChangeGroup && index > 0) {
3042
- var _getValues = getValues(),
3043
- validDateEnd = _getValues.validDateEnd,
3044
- validDateStart = _getValues.validDateStart,
3045
- changeGroups = _getValues.changeGroups;
3046
-
3047
- var currentChangeGroup = changeGroups[index];
3048
- var previousChangeGroup = changeGroups[index - 1];
3049
- return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3078
+ var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3079
+ if (!hasUserDragged) {
3080
+ setStartPosition(newPosition);
3050
3081
  }
3051
3082
 
3052
- return true;
3053
- }, [index, isChangeGroup, getValues]);
3054
-
3055
- var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3056
- var indexedFieldName = "changeGroups[".concat(rowIndex, "].").concat(fieldname);
3057
- var rowValue = getValues(indexedFieldName);
3058
- return rowValue ? [indexedFieldName] : [];
3083
+ setIsIssuesPaneOpen(isOpen);
3059
3084
  };
3060
3085
 
3061
- var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3062
- return getFieldFromRow('valid', index + 1);
3086
+ var onCloseIssuesPane = function onCloseIssuesPane() {
3087
+ return setIsIssuesPaneOpen(false);
3063
3088
  };
3064
3089
 
3065
- var validateNextRows = React__default.useCallback(function () {
3066
- if (isChangeGroup) {
3067
- var _getValues2 = getValues(),
3068
- validDateEnd = _getValues2.validDateEnd,
3069
- validDateStart = _getValues2.validDateStart,
3070
- changeGroups = _getValues2.changeGroups;
3071
-
3072
- var currentChangeGroup = changeGroups[index];
3073
- var nextChangeGroups = changeGroups.slice(index + 1);
3074
- return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3075
- }
3076
-
3077
- return true;
3078
- }, [index, isChangeGroup, getValues]);
3079
-
3080
- var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3081
- var _getValues3 = getValues(),
3082
- changeGroups = _getValues3.changeGroups;
3083
-
3084
- var previousChangeGroups = changeGroups.slice(0, rowIndex);
3085
- var validFields = previousChangeGroups.map(function (_element, index) {
3086
- return getFieldFromRow('valid', index)[0];
3087
- });
3088
- return validFields;
3090
+ return {
3091
+ isIssuesPaneOpen: isIssuesPaneOpen,
3092
+ startPosition: startPosition,
3093
+ onToggleIssuesPane: onToggleIssuesPane,
3094
+ onCloseIssuesPane: onCloseIssuesPane,
3095
+ onUserHasDragged: onUserHasDragged
3089
3096
  };
3097
+ };
3090
3098
 
3091
- var addChangeGroupBelow = React__default.useCallback(function () {
3092
- onAddChangeGroupBelow(index);
3093
- }, [onAddChangeGroupBelow, index]);
3094
- var addChangeGroupAbove = React__default.useCallback(function () {
3095
- onAddChangeGroupAbove(index);
3096
- }, [onAddChangeGroupAbove, index]);
3097
- var clearRow = React__default.useCallback(function () {
3098
- onClearRow(index);
3099
- }, [onClearRow, index]);
3100
- return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
3101
- sx: {
3102
- marginTop: '8px',
3103
- backgroundColor: 'geowebColors.cards.cardContainer',
3104
- position: 'relative',
3105
- '&.sortable-chosen': {
3106
- boxShadow: 1
3107
- },
3108
- '&.sortable-ghost': {
3109
- opacity: 0.5
3110
- }
3111
- },
3112
- justifyContent: "flex-start",
3113
- "data-testid": "row-".concat(namePrefix),
3114
- container: true,
3115
- ref: ref
3116
- }, props), /*#__PURE__*/React__default.createElement(Grid, {
3117
- columns: 24,
3118
- item: true,
3119
- container: true,
3120
- justifyContent: "flex-end",
3121
- xs: 24,
3122
- sm: 23
3123
- }, !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
3124
- label: "Type",
3125
- name: fieldNames.messageType,
3126
- disabled: true
3127
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3128
- label: "Location",
3129
- name: "location",
3130
- disabled: true
3131
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3132
- formatter: formatIssueTime,
3133
- label: "Issue time",
3134
- name: "issueDate",
3135
- disabled: true
3136
- })), isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box, {
3137
- sx: {
3138
- width: 56,
3139
- marginRight: '2px'
3140
- }
3141
- }, !disabled && dragHandle), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3142
- label: "Prob",
3143
- name: fieldNames.probability,
3144
- disabled: disabled,
3145
- defaultValue: getDefaultValue('probability', field),
3146
- rules: {
3147
- validate: {
3148
- validateRequiredMainOptional: validateRequiredMainOptional,
3149
- validateProbabilityField: validateProbabilityField
3150
- }
3151
- },
3152
- autoComplete: [{
3153
- key: '3',
3154
- value: 'PROB30'
3155
- }, {
3156
- key: '4',
3157
- value: 'PROB40'
3158
- }],
3159
- onBlur: function onBlur() {
3160
- if (isChangeGroup) {
3161
- var nextValidFieldName = getValidFieldFromNextRow();
3162
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
3163
- }
3164
- }
3165
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3166
- label: "Change",
3167
- name: fieldNames.change,
3168
- disabled: disabled,
3169
- defaultValue: getDefaultValue('change', field),
3170
- rules: {
3171
- validate: {
3172
- validateRequiredMainOptional: validateRequiredMainOptional,
3173
- validateChangeField: validateChangeField,
3174
- validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3175
- return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3176
- }
3177
- }
3178
- },
3179
- autoComplete: [{
3180
- key: 'T',
3181
- value: 'TEMPO'
3182
- }, {
3183
- key: 'B',
3184
- value: 'BECMG'
3185
- }, {
3186
- key: 'F',
3187
- value: 'FM'
3188
- }],
3189
- onBlur: function onBlur() {
3190
- if (isChangeGroup) {
3191
- var nextValidFieldName = getValidFieldFromNextRow();
3192
- var previousValidFieldNames = getPreviousValidFields(index);
3193
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3194
- }
3195
- }
3196
- })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3197
- label: "Valid",
3198
- name: fieldNames.valid,
3199
- // always disabled for baseforecast row
3200
- disabled: !isChangeGroup ? true : disabled,
3201
- defaultValue: getDefaultValue('valid', field),
3202
- rules: {
3203
- validate: {
3204
- validateRequiredMain: validateRequiredMain,
3205
- validateValidField: function validateValidField$1(value) {
3206
- return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3207
- },
3208
- validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3209
- return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3210
- },
3211
- validatePreviousRow: validatePreviousRow,
3212
- validateNextRows: validateNextRows
3213
- }
3214
- },
3215
- onBlur: function onBlur() {
3216
- if (isChangeGroup) {
3217
- var nextValidFieldName = getValidFieldFromNextRow();
3218
- var previousValidFieldNames = getPreviousValidFields(index);
3219
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3220
- }
3221
- }
3222
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3223
- label: "Wind",
3224
- name: fieldNames.wind,
3225
- disabled: disabled,
3226
- defaultValue: getDefaultValue('wind', field),
3227
- rules: {
3228
- validate: {
3229
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3230
- return _validateRequiredMainFields(value, 'Wind');
3231
- },
3232
- validateRequiredSub: validateRequiredSub,
3233
- validateWindField: function validateWindField$1(value) {
3234
- return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3235
- }
3236
- }
3237
- },
3238
- onBlur: function onBlur() {
3239
- if (isChangeGroup) {
3240
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
3241
- }
3242
- },
3243
- autoFocus: !isChangeGroup
3244
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3245
- label: "Visibility",
3246
- name: fieldNames.visibility,
3247
- disabled: disabled,
3248
- defaultValue: getDefaultValue('visibility', field),
3249
- rules: {
3250
- validate: {
3251
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3252
- return _validateRequiredMainFields(value, 'Visibility');
3253
- },
3254
- validateRequiredSub: validateRequiredSub,
3255
- validateVisibilityField: validateVisibilityField
3256
- }
3257
- },
3258
- autoComplete: [{
3259
- key: 'C',
3260
- value: 'CAVOK'
3261
- }],
3262
- onBlur: function onBlur() {
3263
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3264
- trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3265
- }
3266
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3267
- label: "Weather",
3268
- name: fieldNames.weather1,
3269
- disabled: disabled,
3270
- defaultValue: getDefaultValue('weather.weather1', field),
3271
- rules: {
3272
- validate: {
3273
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3274
- return _validateRequiredMainFields(value, 'Weather');
3275
- },
3276
- validateRequiredSub: validateRequiredSub,
3277
- validateWeatherField: function validateWeatherField$1(value) {
3278
- return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3279
- }
3280
- }
3099
+ var IssuesPane = function IssuesPane(_ref) {
3100
+ var _ref$errorList = _ref.errorList,
3101
+ errorList = _ref$errorList === void 0 ? [] : _ref$errorList,
3102
+ isOpen = _ref.isOpen,
3103
+ handleClose = _ref.handleClose,
3104
+ _ref$startPosition = _ref.startPosition,
3105
+ startPosition = _ref$startPosition === void 0 ? {
3106
+ left: 20,
3107
+ top: 50
3108
+ } : _ref$startPosition,
3109
+ _ref$onUserHasDragged = _ref.onUserHasDragged,
3110
+ onUserHasDragged = _ref$onUserHasDragged === void 0 ? function () {} : _ref$onUserHasDragged;
3111
+ var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3112
+ return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3113
+ startSize: {
3114
+ width: '577px',
3115
+ height: '200px'
3281
3116
  },
3282
- onBlur: function onBlur() {
3283
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3284
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3285
- }
3286
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3287
- label: "Weather",
3288
- name: fieldNames.weather2,
3289
- disabled: disabled,
3290
- defaultValue: getDefaultValue('weather.weather2', field),
3291
- rules: {
3292
- validate: {
3293
- validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3294
- return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3295
- }
3117
+ startPosition: startPosition,
3118
+ minWidth: 300,
3119
+ onClose: handleClose,
3120
+ title: getPaneTitle(errorList.length),
3121
+ headerSize: "xs",
3122
+ isOpen: isOpen,
3123
+ "data-testid": "moveable-issues-pane",
3124
+ bounds: "parent",
3125
+ onDragEnd: function onDragEnd(event) {
3126
+ if (event.x !== 0 && event.y !== 0) {
3127
+ onUserHasDragged();
3296
3128
  }
3297
- },
3298
- onBlur: function onBlur() {
3299
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3300
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3301
3129
  }
3302
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3303
- label: "Weather",
3304
- name: fieldNames.weather3,
3305
- disabled: disabled,
3306
- defaultValue: getDefaultValue('weather.weather3', field),
3307
- rules: {
3308
- validate: {
3309
- validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3310
- return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3311
- }
3312
- }
3313
- },
3314
- onBlur: function onBlur() {
3315
- return trigger([fieldNames.wind, fieldNames.cloud1]);
3130
+ }, /*#__PURE__*/React.createElement(Box, {
3131
+ component: "div",
3132
+ sx: {
3133
+ marginTop: '16px',
3134
+ marginLeft: '24px'
3316
3135
  }
3317
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3318
- label: "Cloud",
3319
- name: fieldNames.cloud1,
3320
- disabled: disabled,
3321
- defaultValue: getDefaultValue('cloud.cloud1', field),
3322
- rules: {
3323
- validate: {
3324
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3325
- return _validateRequiredMainFields(value, 'Clouds');
3326
- },
3327
- validateRequiredSub: validateRequiredSub,
3328
- validateFirstCloud: function validateFirstCloud$1(value) {
3329
- return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3330
- }
3331
- }
3136
+ }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3137
+ component: "div",
3138
+ sx: {
3139
+ fontSize: '4rem'
3332
3140
  },
3333
- onBlur: function onBlur() {
3334
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3335
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3141
+ "data-testid": "zeroIssuesImage"
3142
+ }, /*#__PURE__*/React.createElement(ThumbsUp, {
3143
+ sx: {
3144
+ height: '69px',
3145
+ width: '58px'
3336
3146
  }
3337
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3338
- label: "Cloud",
3339
- name: fieldNames.cloud2,
3340
- disabled: disabled,
3341
- defaultValue: getDefaultValue('cloud.cloud2', field),
3342
- rules: {
3343
- validate: {
3344
- validateSecondCloud: function validateSecondCloud$1(value) {
3345
- return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3346
- }
3347
- }
3348
- },
3349
- onBlur: function onBlur() {
3350
- return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3351
- }
3352
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3353
- label: "Cloud",
3354
- name: fieldNames.cloud3,
3355
- disabled: disabled,
3356
- defaultValue: getDefaultValue('cloud.cloud3', field),
3357
- rules: {
3358
- validate: {
3359
- validateThirdCloud: function validateThirdCloud$1(value) {
3360
- return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3361
- }
3362
- }
3363
- },
3364
- onBlur: function onBlur() {
3365
- return trigger(fieldNames.cloud4);
3366
- }
3367
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3368
- label: "Cloud",
3369
- name: fieldNames.cloud4,
3370
- disabled: disabled,
3371
- defaultValue: getDefaultValue('cloud.cloud4', field),
3372
- rules: {
3373
- validate: {
3374
- validateFourthCloud: function validateFourthCloud$1(value) {
3375
- return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3376
- }
3377
- }
3378
- }
3379
- })), !disabled && /*#__PURE__*/React__default.createElement(Grid, {
3380
- item: true,
3381
- container: true,
3382
- justifyContent: "flex-end",
3383
- alignItems: "flex-end",
3384
- xs: 24,
3385
- sm: 1,
3386
- sx: {
3387
- marginBottom: '16px'
3388
- },
3389
- columns: 24
3390
- }, /*#__PURE__*/React__default.createElement(TafFormOptionsButton, {
3391
- isChangeGroup: isChangeGroup,
3392
- addChangeGroupBelow: addChangeGroupBelow,
3393
- addChangeGroupAbove: addChangeGroupAbove,
3394
- removeChangeGroup: function removeChangeGroup() {
3395
- return onRemoveChangeGroup(index);
3396
- },
3397
- clearRow: clearRow,
3398
- index: index
3399
- })));
3147
+ })), errorList.length > 0 && errorList.map(function (error, index) {
3148
+ return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3149
+ , {
3150
+ // eslint-disable-next-line react/no-array-index-key
3151
+ key: "message-".concat(index),
3152
+ variant: "body1",
3153
+ "data-testid": "errorMessage"
3154
+ }, getErrorMessage(error, index));
3155
+ }))), rootElement);
3156
+ };
3157
+
3158
+ var TafModuleContext = /*#__PURE__*/React.createContext({
3159
+ onValidateForm: null,
3160
+ registerValidateForm: null,
3161
+ tafAction: null,
3162
+ setTafAction: null,
3163
+ onPreventCloseView: null
3400
3164
  });
3165
+ var useTafModuleContext = function useTafModuleContext() {
3166
+ return React.useContext(TafModuleContext);
3167
+ };
3168
+ var useTafModuleState = function useTafModuleState(_ref) {
3169
+ var onPreventCloseView = _ref.onPreventCloseView;
3170
+
3171
+ var _React$useState = React.useState(function () {
3172
+ return new Promise(function () {
3173
+ return true;
3174
+ });
3175
+ }),
3176
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3177
+ onValidateForm = _React$useState2[0],
3178
+ registerValidateForm = _React$useState2[1];
3179
+
3180
+ var _React$useState3 = React.useState(),
3181
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3182
+ tafAction = _React$useState4[0],
3183
+ setTafAction = _React$useState4[1];
3184
+
3185
+ var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3186
+ registerValidateForm(function () {
3187
+ return promiseToRegister;
3188
+ });
3189
+ };
3190
+
3191
+ return {
3192
+ onValidateForm: onValidateForm,
3193
+ registerValidateForm: onRegisterValidateForm,
3194
+ tafAction: tafAction,
3195
+ setTafAction: setTafAction,
3196
+ onPreventCloseView: onPreventCloseView
3197
+ };
3198
+ };
3199
+ var TafModuleProvider = function TafModuleProvider(_ref2) {
3200
+ var children = _ref2.children,
3201
+ _ref2$onPreventCloseV = _ref2.onPreventCloseView,
3202
+ onPreventCloseView = _ref2$onPreventCloseV === void 0 ? function () {} : _ref2$onPreventCloseV;
3203
+ var contextState = useTafModuleState({
3204
+ onPreventCloseView: onPreventCloseView
3205
+ });
3206
+ return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3207
+ value: contextState
3208
+ }, children);
3209
+ };
3401
3210
 
3402
3211
  /* *
3403
3212
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -3412,143 +3221,227 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3412
3221
  * See the License for the specific language governing permissions and
3413
3222
  * limitations under the License.
3414
3223
  *
3415
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3416
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3224
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3225
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3417
3226
  * */
3418
- var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3419
- switch (tafAction) {
3420
- case 'AMEND':
3421
- case 'DRAFT_AMEND':
3422
- return 'DRAFT_AMEND';
3423
-
3424
- case 'CORRECT':
3425
- case 'DRAFT_CORRECT':
3426
- return 'DRAFT_CORRECT';
3427
-
3428
- default:
3429
- return 'DRAFT';
3227
+ var styles = {
3228
+ label: {
3229
+ color: 'geowebColors.buttons.tertiary.default.color',
3230
+ opacity: 1,
3231
+ fontSize: '12px',
3232
+ fontWeight: 500
3430
3233
  }
3431
3234
  };
3432
3235
 
3433
- var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3434
- switch (tafAction) {
3435
- case 'AMEND':
3436
- case 'DRAFT_AMEND':
3437
- return 'AMEND';
3438
-
3439
- case 'CORRECT':
3440
- case 'DRAFT_CORRECT':
3441
- return 'CORRECT';
3236
+ var SwitchButton = function SwitchButton(props) {
3237
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3238
+ title: "Switch mode"
3239
+ }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(FormLabel, {
3240
+ sx: styles.label
3241
+ }, "Viewer"), /*#__PURE__*/React.createElement(Switch, Object.assign({
3242
+ "data-testid": "switchMode"
3243
+ }, props)), /*#__PURE__*/React.createElement(FormLabel, {
3244
+ sx: styles.label
3245
+ }, "Editor")));
3246
+ };
3442
3247
 
3443
- default:
3444
- return 'PUBLISH';
3445
- }
3248
+ var TafAvatar = function TafAvatar(_ref) {
3249
+ var editor = _ref.editor,
3250
+ _ref$tooltipPlacement = _ref.tooltipPlacement,
3251
+ tooltipPlacement = _ref$tooltipPlacement === void 0 ? 'bottom' : _ref$tooltipPlacement;
3252
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3253
+ title: "Editor: ".concat(editor),
3254
+ placement: tooltipPlacement
3255
+ }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Avatar, {
3256
+ size: "small"
3257
+ }, getInitials(editor))));
3446
3258
  };
3447
3259
 
3448
- var buttonsStyle = {
3449
- button: {
3450
- minWidth: {
3451
- xs: '56px',
3452
- sm: '64px'
3260
+ var textFieldStyle = function textFieldStyle(theme) {
3261
+ return {
3262
+ // input
3263
+ marginRight: '2px',
3264
+ marginBottom: '4px',
3265
+ width: 56,
3266
+ height: 46,
3267
+ input: {
3268
+ textAlign: 'center',
3269
+ fontSize: 10,
3270
+ fontWeight: 500,
3271
+ paddingLeft: 0,
3272
+ paddingRight: 0,
3273
+ '&.Mui-disabled': {
3274
+ color: 'geowebColors.typographyAndIcons.text',
3275
+ WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
3276
+ },
3277
+ // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
3278
+ '&:-webkit-autofill': {
3279
+ WebkitTransitionDelay: '86400s' // 1 day delay
3280
+
3281
+ }
3453
3282
  },
3454
- width: {
3455
- xs: '56px',
3456
- sm: '64px'
3283
+ label: {
3284
+ transformOrigin: 'center top',
3285
+ right: 0,
3286
+ textAlign: 'center',
3287
+ fontSize: '10px',
3288
+ '&.Mui-disabled': {
3289
+ color: 'geowebColors.captions.captionStatus.rgba'
3290
+ },
3291
+ whiteSpace: 'nowrap',
3292
+ maxWidth: '100%',
3293
+ transform: 'translate(0px, 16px) scale(1)'
3457
3294
  },
3458
- marginLeft: {
3459
- xs: 0.5,
3460
- sm: 1
3295
+ // shrink
3296
+ ' .MuiInputLabel-shrink': {
3297
+ transform: 'translate(2px, 10px) scale(0.75) !important',
3298
+ letterSpacing: '0.33px',
3299
+ textAlign: 'left'
3461
3300
  },
3462
- marginTop: 3,
3463
- marginBottom: 3
3464
- }
3465
- };
3466
-
3467
- var ViewModeButtons = function ViewModeButtons(_ref) {
3468
- var canBe = _ref.canBe,
3469
- onTafViewModeButtonPress = _ref.onTafViewModeButtonPress;
3470
- return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default.createElement(Button, {
3471
- "data-testid": "canceltaf",
3472
- variant: "tertiary",
3473
- onClick: function onClick() {
3474
- return onTafViewModeButtonPress('CANCEL');
3475
- }
3476
- }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
3477
- "data-testid": "correcttaf",
3478
- variant: "tertiary",
3479
- onClick: function onClick() {
3480
- return onTafViewModeButtonPress('CORRECT');
3481
- }
3482
- }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default.createElement(Button, {
3483
- "data-testid": "amendtaf",
3484
- variant: "tertiary",
3485
- onClick: function onClick() {
3486
- return onTafViewModeButtonPress('AMEND');
3301
+ // root
3302
+ '&': {
3303
+ '.Mui-error.MuiFilledInput-root': {
3304
+ backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
3305
+ },
3306
+ '.Mui-disabled:before': {
3307
+ borderColor: 'transparent'
3308
+ }
3487
3309
  }
3488
- }, "Amend"));
3310
+ };
3489
3311
  };
3490
3312
 
3491
- var TafFormButtons = function TafFormButtons(_ref2) {
3492
- var _ref2$isFormDisabled = _ref2.isFormDisabled,
3493
- isFormDisabled = _ref2$isFormDisabled === void 0 ? false : _ref2$isFormDisabled,
3494
- tafAction = _ref2.tafAction,
3495
- _ref2$canBe = _ref2.canBe,
3496
- canBe = _ref2$canBe === void 0 ? [] : _ref2$canBe,
3497
- onTafEditModeButtonPress = _ref2.onTafEditModeButtonPress,
3498
- onTafViewModeButtonPress = _ref2.onTafViewModeButtonPress;
3499
- return /*#__PURE__*/React__default.createElement(Grid, {
3500
- container: true,
3501
- justifyContent: "flex-end",
3502
- sx: buttonsStyle,
3503
- columns: 24
3504
- }, /*#__PURE__*/React__default.createElement(Grid, {
3505
- item: true,
3506
- container: true,
3507
- justifyContent: "flex-end",
3508
- columns: 24,
3509
- xs: 24,
3510
- sm: 23
3511
- }, isFormDisabled ? /*#__PURE__*/React__default.createElement(ViewModeButtons, {
3512
- canBe: canBe,
3513
- onTafViewModeButtonPress: onTafViewModeButtonPress
3514
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
3515
- "data-testid": "cleartaf",
3516
- variant: "tertiary",
3517
- onClick: function onClick() {
3518
- // Simply discard the changes and close the dialog.
3519
- onTafEditModeButtonPress('CLEAR');
3520
- }
3521
- }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
3522
- "data-testid": "savedrafttaf",
3523
- variant: "tertiary",
3524
- onClick: function onClick() {
3525
- /* Save the TAF as draft:
3526
- if action NEW or DRAFT - new status will be DRAFT -- default
3527
- if action AMEND - new status will be DRAFT_AMENDED
3528
- if action CORRECT - new status will be DRAFT_CORRECTED
3529
- if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3530
- if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3531
- */
3532
- onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
3313
+ var getTafErrors = function getTafErrors(name, errors) {
3314
+ var nameAsArray = name.split('.');
3315
+
3316
+ if (nameAsArray[0].includes('changeGroups')) {
3317
+ if (errors.changeGroups) {
3318
+ var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
3319
+ var restArray = nameAsArray.slice(1);
3320
+ return getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
3321
+ } // No changegroup errors
3322
+
3323
+
3324
+ return null;
3325
+ }
3326
+
3327
+ return getDeepProperty(nameAsArray, errors);
3328
+ };
3329
+
3330
+ var getDisplayValue = function getDisplayValue(value, disabled) {
3331
+ return disabled && !value ? '-' : value;
3332
+ };
3333
+ var BaseTextField = /*#__PURE__*/React__default.memo(function (props) {
3334
+ return /*#__PURE__*/React__default.createElement(TextField, Object.assign({
3335
+ type: "text",
3336
+ variant: "filled",
3337
+ sx: textFieldStyle
3338
+ }, props));
3339
+ }, function (prevProps, nextProps) {
3340
+ return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
3341
+ });
3342
+
3343
+ var TafFormTextField = function TafFormTextField(_ref) {
3344
+ var label = _ref.label,
3345
+ _ref$disabled = _ref.disabled,
3346
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
3347
+ _ref$name = _ref.name,
3348
+ name = _ref$name === void 0 ? '' : _ref$name,
3349
+ _ref$onChange = _ref.onChange,
3350
+ onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
3351
+ _ref$onBlur = _ref.onBlur,
3352
+ onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
3353
+ _ref$defaultValue = _ref.defaultValue,
3354
+ defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
3355
+ _ref$formatter = _ref.formatter,
3356
+ formatter = _ref$formatter === void 0 ? null : _ref$formatter,
3357
+ rules = _ref.rules,
3358
+ _ref$autoComplete = _ref.autoComplete,
3359
+ autoComplete = _ref$autoComplete === void 0 ? [] : _ref$autoComplete,
3360
+ _ref$autoFocus = _ref.autoFocus,
3361
+ autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus;
3362
+
3363
+ var _useFormContext = useFormContext(),
3364
+ control = _useFormContext.control,
3365
+ setValue = _useFormContext.setValue,
3366
+ errors = _useFormContext.formState.errors;
3367
+
3368
+ var fieldErrors = getTafErrors(name, errors);
3369
+
3370
+ var _React$useState = React__default.useState(null),
3371
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3372
+ maxLength = _React$useState2[0],
3373
+ setMaxLength = _React$useState2[1];
3374
+
3375
+ var onKeyDown = React__default.useCallback(function (event) {
3376
+ var target = event.target;
3377
+ var currentValue = target.value,
3378
+ selectionStart = target.selectionStart,
3379
+ selectionEnd = target.selectionEnd;
3380
+ var textSelection = currentValue.substring(selectionStart, selectionEnd);
3381
+
3382
+ if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
3383
+ var pressedKey = event.key.toString().toUpperCase();
3384
+ var foundValue = autoComplete.find(function (el) {
3385
+ return el.key === pressedKey;
3386
+ }) || null;
3387
+
3388
+ if (foundValue) {
3389
+ setValue(name, foundValue.value, {
3390
+ shouldDirty: true
3391
+ });
3392
+ setMaxLength(foundValue.value.length);
3393
+ event.preventDefault();
3394
+ }
3533
3395
  }
3534
- }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
3535
- "data-testid": "publishtaf",
3536
- variant: "tertiary",
3537
- onClick: function onClick() {
3538
- /* Publish the TAF:
3539
- if action NEW or DRAFT - new status will be PUBLISHED -- default
3540
- if action AMEND - new status will be AMENDED
3541
- if action CORRECT - new status will be CORRECTED
3542
- if action DRAFT_AMEND - new status will be AMENDED
3543
- if action DRAFT_CORRECT - new status will be CORRECTED
3544
- */
3545
- onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
3396
+ }, [name, autoComplete, setValue]);
3397
+ var onChangeField = React__default.useCallback(function (event, callback) {
3398
+ var valueUppercase = event.currentTarget.value.toUpperCase();
3399
+
3400
+ if (autoComplete) {
3401
+ var exist = autoComplete.find(function (e) {
3402
+ return e.value === valueUppercase;
3403
+ });
3404
+ var newMaxLength = exist ? valueUppercase.length : null;
3405
+ setMaxLength(newMaxLength);
3546
3406
  }
3547
- }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
3548
- item: true,
3549
- columns: 24,
3550
- sm: 1
3551
- }));
3407
+
3408
+ callback(valueUppercase);
3409
+ onChange(valueUppercase);
3410
+ }, [onChange, autoComplete]);
3411
+ var onBlurField = React__default.useCallback(function (callback) {
3412
+ callback();
3413
+ onBlur();
3414
+ }, [onBlur]);
3415
+ var hasError = !!fieldErrors;
3416
+ return /*#__PURE__*/React__default.createElement(Controller, {
3417
+ render: function render(_ref2) {
3418
+ var field = _ref2.field;
3419
+ var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
3420
+ return /*#__PURE__*/React__default.createElement(BaseTextField, {
3421
+ label: label,
3422
+ disabled: disabled,
3423
+ name: name,
3424
+ value: displayValue,
3425
+ inputRef: field.ref,
3426
+ onChange: function onChange(e) {
3427
+ return onChangeField(e, field.onChange);
3428
+ },
3429
+ onKeyDown: onKeyDown,
3430
+ error: hasError,
3431
+ onBlur: function onBlur() {
3432
+ return onBlurField(field.onBlur);
3433
+ },
3434
+ inputProps: {
3435
+ maxLength: maxLength
3436
+ },
3437
+ autoFocus: autoFocus
3438
+ });
3439
+ },
3440
+ name: name,
3441
+ control: control,
3442
+ defaultValue: defaultValue,
3443
+ rules: rules
3444
+ });
3552
3445
  };
3553
3446
 
3554
3447
  /* *
@@ -3564,30 +3457,27 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3564
3457
  * See the License for the specific language governing permissions and
3565
3458
  * limitations under the License.
3566
3459
  *
3567
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3568
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3460
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3461
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3569
3462
  * */
3570
3463
 
3571
- var DragHandle = function DragHandle(_ref) {
3572
- var _ref$isSorting = _ref.isSorting,
3573
- isSorting = _ref$isSorting === void 0 ? false : _ref$isSorting,
3574
- _ref$isDisabled = _ref.isDisabled,
3575
- isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
3576
- index = _ref.index;
3577
- return /*#__PURE__*/React__default.createElement(IconButton, {
3578
- className: "handle",
3579
- "data-testid": "dragHandle-".concat(index),
3580
- disableRipple: true,
3581
- disabled: isDisabled,
3582
- size: "large",
3583
- sx: {
3584
- backgroundColor: 'transparent',
3585
- '&:hover': {
3586
- backgroundColor: 'transparent'
3587
- },
3588
- cursor: isSorting ? 'grabbing' : 'grab'
3589
- }
3590
- }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
3464
+ var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
3465
+ var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
3466
+
3467
+ var validateChangeField = function validateChangeField(value) {
3468
+ var trimmedValue = getFieldValue(value);
3469
+ var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
3470
+ return isValid ? true : invalidChangeMessage;
3471
+ };
3472
+ var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
3473
+ var trimmedProbValue = getFieldValue(valueProb);
3474
+ var trimmedValue = getFieldValue(value);
3475
+
3476
+ if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
3477
+ return invalidChangeProbCombinationMessage;
3478
+ }
3479
+
3480
+ return true;
3591
3481
  };
3592
3482
 
3593
3483
  /* *
@@ -3603,77 +3493,16 @@ var DragHandle = function DragHandle(_ref) {
3603
3493
  * See the License for the specific language governing permissions and
3604
3494
  * limitations under the License.
3605
3495
  *
3606
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3607
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3496
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3497
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3608
3498
  * */
3609
- var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
3610
- return Object.assign(Object.assign({}, error), {
3611
- isChangeGroup: isChangeGroup,
3612
- rowIndex: rowIndex
3613
- });
3614
- };
3615
- var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
3616
- switch (sumOfErrors) {
3617
- case 0:
3618
- return '0 issues';
3619
3499
 
3620
- case 1:
3621
- return '1 issue';
3500
+ var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
3622
3501
 
3623
- default:
3624
- return "".concat(sumOfErrors, " issues");
3625
- }
3626
- };
3627
- var getErrorValues = function getErrorValues(fieldErrors) {
3628
- var isChangeGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
3629
- var rowIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
3630
- if (!fieldErrors) return [];
3631
- return Object.keys(fieldErrors).reduce(function (list, key) {
3632
- var error = Object.assign({}, fieldErrors[key]);
3633
-
3634
- if (error.ref) {
3635
- return list.concat(getCustomError(error, isChangeGroup, rowIndex));
3636
- }
3637
-
3638
- return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
3639
- }, []);
3640
- };
3641
- var filterDuplicateErrors = function filterDuplicateErrors(errors) {
3642
- return errors.reduce(function (list, error) {
3643
- // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
3644
- if (error.type === 'validateRequiredSub') {
3645
- var exist = list.find(function (e) {
3646
- return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
3647
- });
3648
- return exist ? list : list.concat(error);
3649
- }
3650
-
3651
- if (error.type === 'validateRequiredMainOptional') {
3652
- var _exist = list.find(function (e) {
3653
- return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
3654
- });
3655
-
3656
- return _exist ? list : list.concat(error);
3657
- }
3658
-
3659
- return list.concat(error);
3660
- }, []);
3661
- };
3662
- var getErrors = function getErrors(errors) {
3663
- var errorList = Object.keys(errors).reduce(function (list, key) {
3664
- var errorValue = errors[key]; // changeGroups
3665
-
3666
- if (Array.isArray(errorValue)) {
3667
- var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
3668
- return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
3669
- }, []);
3670
- return list.concat.apply(list, _toConsumableArray(errorValues));
3671
- } // baseForecast
3672
-
3673
-
3674
- return list.concat(getErrorValues(errorValue, false, -1));
3675
- }, []);
3676
- return errorList;
3502
+ var validateProbabilityField = function validateProbabilityField(value) {
3503
+ var trimmedValue = getFieldValue(value);
3504
+ var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
3505
+ return isValid ? true : invalidProbabilityMessage;
3677
3506
  };
3678
3507
 
3679
3508
  /* *
@@ -3689,281 +3518,504 @@ var getErrors = function getErrors(errors) {
3689
3518
  * See the License for the specific language governing permissions and
3690
3519
  * limitations under the License.
3691
3520
  *
3692
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3693
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3521
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3522
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3694
3523
  * */
3695
3524
 
3696
- var IssuesButton = function IssuesButton(_ref) {
3697
- var _ref$errors = _ref.errors,
3698
- errors = _ref$errors === void 0 ? {} : _ref$errors,
3699
- _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
3700
- isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
3701
- _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
3702
- setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
3703
- return null;
3704
- } : _ref$setIsIssuesPaneO;
3705
- var errorList = filterDuplicateErrors(getErrors(errors));
3706
- var totalErrors = errorList.length;
3707
- var errorStatus = totalErrors > 0 ? 'error' : 'success';
3708
- var buttonColor = "geowebColors.functional.".concat(errorStatus);
3709
-
3710
- var toggleIssuesPane = function toggleIssuesPane(newPosition) {
3711
- return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
3525
+ var TafFormOptionsButton = function TafFormOptionsButton(_ref) {
3526
+ var isChangeGroup = _ref.isChangeGroup,
3527
+ addChangeGroupBelow = _ref.addChangeGroupBelow,
3528
+ addChangeGroupAbove = _ref.addChangeGroupAbove,
3529
+ removeChangeGroup = _ref.removeChangeGroup,
3530
+ clearRow = _ref.clearRow,
3531
+ index = _ref.index;
3532
+ var insertAbove = {
3533
+ text: 'Insert 1 row above',
3534
+ icon: /*#__PURE__*/React.createElement(Add, null),
3535
+ action: addChangeGroupAbove
3712
3536
  };
3537
+ var insertBelow = {
3538
+ text: 'Insert 1 row below',
3539
+ icon: /*#__PURE__*/React.createElement(Add, null),
3540
+ action: addChangeGroupBelow
3541
+ };
3542
+ var deleteRow = {
3543
+ text: 'Delete row',
3544
+ icon: /*#__PURE__*/React.createElement(Delete, null),
3545
+ action: removeChangeGroup
3546
+ };
3547
+ var clear = {
3548
+ text: 'Clear row',
3549
+ icon: /*#__PURE__*/React.createElement(Close, null),
3550
+ action: clearRow
3551
+ };
3552
+ var menuItemsBaseForecast = [insertBelow, clear];
3553
+ var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
3554
+ return /*#__PURE__*/React.createElement(ToggleMenu, {
3555
+ buttonTestId: "tafFormOptions[".concat(index, "]"),
3556
+ buttonSx: {
3557
+ marginTop: '10px',
3558
+ marginLeft: '4px'
3559
+ },
3560
+ menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
3561
+ });
3562
+ };
3713
3563
 
3714
- var onClickButton = function onClickButton(event) {
3715
- var _a;
3716
-
3717
- var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
3718
- left = _event$currentTarget$.left,
3719
- top = _event$currentTarget$.top;
3564
+ var getDefaultValue = function getDefaultValue(fieldName, data) {
3565
+ if (!data) {
3566
+ return '';
3567
+ }
3720
3568
 
3721
- var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3722
- top: 0,
3723
- left: 0
3724
- };
3725
- var newPosition = {
3726
- left: left - parentOffset.left + 100,
3727
- top: top - parentOffset.top
3728
- };
3729
- toggleIssuesPane(newPosition);
3730
- };
3569
+ return getDeepProperty(fieldName.split('.'), data) || '';
3570
+ };
3731
3571
 
3732
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3733
- title: "View details"
3734
- }, /*#__PURE__*/React.createElement(Chip, {
3735
- "data-testid": "issuesButton",
3736
- className: "status-".concat(errorStatus),
3737
- size: "small",
3738
- label: getIssuesLabel(totalErrors),
3739
- onClick: onClickButton,
3740
- sx: {
3741
- width: '74px',
3742
- color: '#ffffff',
3743
- backgroundColor: buttonColor,
3744
- '&:hover': {
3745
- backgroundColor: buttonColor
3746
- },
3747
- '&:focus': {
3748
- backgroundColor: buttonColor
3749
- },
3750
- fontSize: 12
3751
- }
3752
- }));
3572
+ var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
3573
+ return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
3574
+ ];
3753
3575
  };
3754
3576
 
3755
- var getPaneTitle = function getPaneTitle(sumOfErrors) {
3756
- switch (sumOfErrors) {
3757
- case 0:
3758
- return 'Looks good';
3577
+ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3578
+ var isNotRequiredForAction = _a.isNotRequiredForAction,
3579
+ _a$isChangeGroup = _a.isChangeGroup,
3580
+ isChangeGroup = _a$isChangeGroup === void 0 ? false : _a$isChangeGroup,
3581
+ _a$disabled = _a.disabled,
3582
+ disabled = _a$disabled === void 0 ? false : _a$disabled,
3583
+ _a$index = _a.index,
3584
+ index = _a$index === void 0 ? -1 : _a$index,
3585
+ onRemoveChangeGroup = _a.onRemoveChangeGroup,
3586
+ _a$field = _a.field,
3587
+ field = _a$field === void 0 ? null : _a$field,
3588
+ _a$dragHandle = _a.dragHandle,
3589
+ dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
3590
+ onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
3591
+ onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
3592
+ onClearRow = _a.onClearRow,
3593
+ props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
3759
3594
 
3760
- case 1:
3761
- return 'There is an issue to address';
3595
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
3596
+ var fieldNames = getFieldNames(isChangeGroup, index);
3762
3597
 
3763
- default:
3764
- return 'There are a few issues to address';
3765
- }
3766
- };
3598
+ var _useFormContext = useFormContext(),
3599
+ getValues = _useFormContext.getValues,
3600
+ trigger = _useFormContext.trigger; // cross-field required validation
3767
3601
 
3768
- var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3769
- if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3770
- // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3771
- var fieldNumber = fieldNumberedValue + 1;
3772
- return "".concat(errorTitle, " ").concat(fieldNumber);
3773
- }
3774
3602
 
3775
- return errorTitle;
3776
- };
3777
- var getErrorMessage = function getErrorMessage(error, index) {
3778
- var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3779
- var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3780
- return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(error.message);
3781
- };
3782
- var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3783
- var useIssuesPane = function useIssuesPane() {
3784
- var _React$useState = React.useState(false),
3785
- _React$useState2 = _slicedToArray(_React$useState, 2),
3786
- isIssuesPaneOpen = _React$useState2[0],
3787
- setIsIssuesPaneOpen = _React$useState2[1];
3603
+ var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
3604
+ _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
3605
+ mainFields = _getRequiredCrossFiel2[0],
3606
+ mainOptionalFields = _getRequiredCrossFiel2[1],
3607
+ subFields = _getRequiredCrossFiel2[2];
3788
3608
 
3789
- var _React$useState3 = React.useState(null),
3790
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3791
- startPosition = _React$useState4[0],
3792
- setStartPosition = _React$useState4[1];
3609
+ var hasFieldsValue = function hasFieldsValue(fields) {
3610
+ return fields.map(getValues).find(function (field) {
3611
+ return !!field;
3612
+ });
3613
+ }; // Used to validate the required field for change groups: Valid
3793
3614
 
3794
- var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3795
- if (!startPosition) {
3796
- setStartPosition(newPosition);
3615
+
3616
+ var validateRequiredMain = function validateRequiredMain(value) {
3617
+ return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3618
+ }; // Used to ensure either probability or change is entered, or both
3619
+
3620
+
3621
+ var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3622
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3623
+ }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
3624
+
3625
+
3626
+ var validateRequiredSub = function validateRequiredSub(value) {
3627
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3628
+ }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3629
+
3630
+
3631
+ var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3632
+ var changeField = getValues("".concat(namePrefix, ".change"));
3633
+ var visibilityField = getValues("".concat(namePrefix, ".visibility"));
3634
+ var isFM = changeField && changeField.trim() === 'FM';
3635
+ var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3636
+
3637
+ if (isNotRequiredForAction(value) !== true && !value.length) {
3638
+ if (isChangeGroup && isFM || !isChangeGroup) {
3639
+ // exception for CavOK
3640
+ if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3641
+ return true;
3642
+ } // exception for visibility > 5000
3643
+
3644
+
3645
+ if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3646
+ return true;
3647
+ }
3648
+
3649
+ return "".concat(fieldName, " is required");
3650
+ }
3651
+ }
3652
+
3653
+ return true;
3654
+ };
3655
+
3656
+ var validatePreviousRow = React__default.useCallback(function () {
3657
+ if (isChangeGroup && index > 0) {
3658
+ var _getValues = getValues(),
3659
+ validDateEnd = _getValues.validDateEnd,
3660
+ validDateStart = _getValues.validDateStart,
3661
+ changeGroups = _getValues.changeGroups;
3662
+
3663
+ var currentChangeGroup = changeGroups[index];
3664
+ var previousChangeGroup = changeGroups[index - 1];
3665
+ return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3666
+ }
3667
+
3668
+ return true;
3669
+ }, [index, isChangeGroup, getValues]);
3670
+
3671
+ var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3672
+ var indexedFieldName = "changeGroups[".concat(rowIndex, "].").concat(fieldname);
3673
+ var rowValue = getValues(indexedFieldName);
3674
+ return rowValue ? [indexedFieldName] : [];
3675
+ };
3676
+
3677
+ var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3678
+ return getFieldFromRow('valid', index + 1);
3679
+ };
3680
+
3681
+ var validateNextRows = React__default.useCallback(function () {
3682
+ if (isChangeGroup) {
3683
+ var _getValues2 = getValues(),
3684
+ validDateEnd = _getValues2.validDateEnd,
3685
+ validDateStart = _getValues2.validDateStart,
3686
+ changeGroups = _getValues2.changeGroups;
3687
+
3688
+ var currentChangeGroup = changeGroups[index];
3689
+ var nextChangeGroups = changeGroups.slice(index + 1);
3690
+ return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3691
+ }
3692
+
3693
+ return true;
3694
+ }, [index, isChangeGroup, getValues]);
3695
+
3696
+ var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3697
+ var _getValues3 = getValues(),
3698
+ changeGroups = _getValues3.changeGroups;
3699
+
3700
+ var previousChangeGroups = changeGroups.slice(0, rowIndex);
3701
+ var validFields = previousChangeGroups.map(function (_element, index) {
3702
+ return getFieldFromRow('valid', index)[0];
3703
+ });
3704
+ return validFields;
3705
+ };
3706
+
3707
+ var addChangeGroupBelow = React__default.useCallback(function () {
3708
+ onAddChangeGroupBelow(index);
3709
+ }, [onAddChangeGroupBelow, index]);
3710
+ var addChangeGroupAbove = React__default.useCallback(function () {
3711
+ onAddChangeGroupAbove(index);
3712
+ }, [onAddChangeGroupAbove, index]);
3713
+ var clearRow = React__default.useCallback(function () {
3714
+ onClearRow(index);
3715
+ }, [onClearRow, index]);
3716
+ return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
3717
+ sx: {
3718
+ marginTop: '8px',
3719
+ backgroundColor: 'geowebColors.cards.cardContainer',
3720
+ position: 'relative',
3721
+ '&.sortable-chosen': {
3722
+ boxShadow: 1
3723
+ },
3724
+ '&.sortable-ghost': {
3725
+ opacity: 0.5
3726
+ }
3727
+ },
3728
+ justifyContent: "flex-start",
3729
+ "data-testid": "row-".concat(namePrefix),
3730
+ container: true,
3731
+ ref: ref
3732
+ }, props, {
3733
+ className: "formRow"
3734
+ }), /*#__PURE__*/React__default.createElement(Grid, {
3735
+ columns: 24,
3736
+ item: true,
3737
+ container: true,
3738
+ justifyContent: "flex-end",
3739
+ xs: 24,
3740
+ sm: 23
3741
+ }, !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
3742
+ label: "Type",
3743
+ name: fieldNames.messageType,
3744
+ disabled: true
3745
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3746
+ label: "Location",
3747
+ name: "location",
3748
+ disabled: true
3749
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3750
+ formatter: formatIssueTime,
3751
+ label: "Issue time",
3752
+ name: "issueDate",
3753
+ disabled: true
3754
+ })), isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box, {
3755
+ sx: {
3756
+ width: 56,
3757
+ marginRight: '2px'
3758
+ }
3759
+ }, !disabled && dragHandle), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3760
+ label: "Prob",
3761
+ name: fieldNames.probability,
3762
+ disabled: disabled,
3763
+ defaultValue: getDefaultValue('probability', field),
3764
+ rules: {
3765
+ validate: {
3766
+ validateRequiredMainOptional: validateRequiredMainOptional,
3767
+ validateProbabilityField: validateProbabilityField
3768
+ }
3769
+ },
3770
+ autoComplete: [{
3771
+ key: '3',
3772
+ value: 'PROB30'
3773
+ }, {
3774
+ key: '4',
3775
+ value: 'PROB40'
3776
+ }],
3777
+ onBlur: function onBlur() {
3778
+ if (isChangeGroup) {
3779
+ var nextValidFieldName = getValidFieldFromNextRow();
3780
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
3781
+ }
3782
+ }
3783
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3784
+ label: "Change",
3785
+ name: fieldNames.change,
3786
+ disabled: disabled,
3787
+ defaultValue: getDefaultValue('change', field),
3788
+ rules: {
3789
+ validate: {
3790
+ validateRequiredMainOptional: validateRequiredMainOptional,
3791
+ validateChangeField: validateChangeField,
3792
+ validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3793
+ return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3794
+ }
3795
+ }
3796
+ },
3797
+ autoComplete: [{
3798
+ key: 'T',
3799
+ value: 'TEMPO'
3800
+ }, {
3801
+ key: 'B',
3802
+ value: 'BECMG'
3803
+ }, {
3804
+ key: 'F',
3805
+ value: 'FM'
3806
+ }],
3807
+ onBlur: function onBlur() {
3808
+ if (isChangeGroup) {
3809
+ var nextValidFieldName = getValidFieldFromNextRow();
3810
+ var previousValidFieldNames = getPreviousValidFields(index);
3811
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3812
+ }
3813
+ }
3814
+ })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3815
+ label: "Valid",
3816
+ name: fieldNames.valid,
3817
+ // always disabled for baseforecast row
3818
+ disabled: !isChangeGroup ? true : disabled,
3819
+ defaultValue: getDefaultValue('valid', field),
3820
+ rules: {
3821
+ validate: {
3822
+ validateRequiredMain: validateRequiredMain,
3823
+ validateValidField: function validateValidField$1(value) {
3824
+ return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3825
+ },
3826
+ validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3827
+ return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3828
+ },
3829
+ validatePreviousRow: validatePreviousRow,
3830
+ validateNextRows: validateNextRows
3831
+ }
3832
+ },
3833
+ onBlur: function onBlur() {
3834
+ if (isChangeGroup) {
3835
+ var nextValidFieldName = getValidFieldFromNextRow();
3836
+ var previousValidFieldNames = getPreviousValidFields(index);
3837
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3838
+ }
3839
+ }
3840
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3841
+ label: "Wind",
3842
+ name: fieldNames.wind,
3843
+ disabled: disabled,
3844
+ defaultValue: getDefaultValue('wind', field),
3845
+ rules: {
3846
+ validate: {
3847
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3848
+ return _validateRequiredMainFields(value, 'Wind');
3849
+ },
3850
+ validateRequiredSub: validateRequiredSub,
3851
+ validateWindField: function validateWindField$1(value) {
3852
+ return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3853
+ }
3854
+ }
3855
+ },
3856
+ onBlur: function onBlur() {
3857
+ if (isChangeGroup) {
3858
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
3859
+ }
3860
+ },
3861
+ autoFocus: !isChangeGroup
3862
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3863
+ label: "Visibility",
3864
+ name: fieldNames.visibility,
3865
+ disabled: disabled,
3866
+ defaultValue: getDefaultValue('visibility', field),
3867
+ rules: {
3868
+ validate: {
3869
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3870
+ return _validateRequiredMainFields(value, 'Visibility');
3871
+ },
3872
+ validateRequiredSub: validateRequiredSub,
3873
+ validateVisibilityField: validateVisibilityField
3874
+ }
3875
+ },
3876
+ autoComplete: [{
3877
+ key: 'C',
3878
+ value: 'CAVOK'
3879
+ }],
3880
+ onBlur: function onBlur() {
3881
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3882
+ trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3883
+ }
3884
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3885
+ label: "Weather",
3886
+ name: fieldNames.weather1,
3887
+ disabled: disabled,
3888
+ defaultValue: getDefaultValue('weather.weather1', field),
3889
+ rules: {
3890
+ validate: {
3891
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3892
+ return _validateRequiredMainFields(value, 'Weather');
3893
+ },
3894
+ validateRequiredSub: validateRequiredSub,
3895
+ validateWeatherField: function validateWeatherField$1(value) {
3896
+ return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3897
+ }
3898
+ }
3899
+ },
3900
+ onBlur: function onBlur() {
3901
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3902
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3903
+ }
3904
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3905
+ label: "Weather",
3906
+ name: fieldNames.weather2,
3907
+ disabled: disabled,
3908
+ defaultValue: getDefaultValue('weather.weather2', field),
3909
+ rules: {
3910
+ validate: {
3911
+ validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3912
+ return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3913
+ }
3914
+ }
3915
+ },
3916
+ onBlur: function onBlur() {
3917
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3918
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3919
+ }
3920
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3921
+ label: "Weather",
3922
+ name: fieldNames.weather3,
3923
+ disabled: disabled,
3924
+ defaultValue: getDefaultValue('weather.weather3', field),
3925
+ rules: {
3926
+ validate: {
3927
+ validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3928
+ return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3929
+ }
3930
+ }
3931
+ },
3932
+ onBlur: function onBlur() {
3933
+ return trigger([fieldNames.wind, fieldNames.cloud1]);
3934
+ }
3935
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3936
+ label: "Cloud",
3937
+ name: fieldNames.cloud1,
3938
+ disabled: disabled,
3939
+ defaultValue: getDefaultValue('cloud.cloud1', field),
3940
+ rules: {
3941
+ validate: {
3942
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3943
+ return _validateRequiredMainFields(value, 'Clouds');
3944
+ },
3945
+ validateRequiredSub: validateRequiredSub,
3946
+ validateFirstCloud: function validateFirstCloud$1(value) {
3947
+ return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3948
+ }
3949
+ }
3950
+ },
3951
+ onBlur: function onBlur() {
3952
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3953
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3797
3954
  }
3798
-
3799
- setIsIssuesPaneOpen(isOpen);
3800
- };
3801
-
3802
- var onCloseIssuesPane = function onCloseIssuesPane() {
3803
- return setIsIssuesPaneOpen(false);
3804
- };
3805
-
3806
- return {
3807
- isIssuesPaneOpen: isIssuesPaneOpen,
3808
- startPosition: startPosition,
3809
- onToggleIssuesPane: onToggleIssuesPane,
3810
- onCloseIssuesPane: onCloseIssuesPane
3811
- };
3812
- };
3813
-
3814
- var IssuesPane = function IssuesPane(_ref) {
3815
- var _ref$errorList = _ref.errorList,
3816
- errorList = _ref$errorList === void 0 ? [] : _ref$errorList,
3817
- isOpen = _ref.isOpen,
3818
- handleClose = _ref.handleClose,
3819
- _ref$startPosition = _ref.startPosition,
3820
- startPosition = _ref$startPosition === void 0 ? {
3821
- left: 20,
3822
- top: 50
3823
- } : _ref$startPosition;
3824
- var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3825
- return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3826
- startSize: {
3827
- width: '577px',
3828
- height: '200px'
3955
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3956
+ label: "Cloud",
3957
+ name: fieldNames.cloud2,
3958
+ disabled: disabled,
3959
+ defaultValue: getDefaultValue('cloud.cloud2', field),
3960
+ rules: {
3961
+ validate: {
3962
+ validateSecondCloud: function validateSecondCloud$1(value) {
3963
+ return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3964
+ }
3965
+ }
3829
3966
  },
3830
- startPosition: startPosition,
3831
- minWidth: 300,
3832
- onClose: handleClose,
3833
- title: getPaneTitle(errorList.length),
3834
- headerSize: "xs",
3835
- isOpen: isOpen,
3836
- "data-testid": "moveable-issues-pane",
3837
- bounds: "parent"
3838
- }, /*#__PURE__*/React.createElement(Box, {
3839
- component: "div",
3840
- sx: {
3841
- marginTop: '16px',
3842
- marginLeft: '24px'
3967
+ onBlur: function onBlur() {
3968
+ return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3843
3969
  }
3844
- }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3845
- component: "div",
3846
- sx: {
3847
- fontSize: '4rem'
3970
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3971
+ label: "Cloud",
3972
+ name: fieldNames.cloud3,
3973
+ disabled: disabled,
3974
+ defaultValue: getDefaultValue('cloud.cloud3', field),
3975
+ rules: {
3976
+ validate: {
3977
+ validateThirdCloud: function validateThirdCloud$1(value) {
3978
+ return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3979
+ }
3980
+ }
3848
3981
  },
3849
- "data-testid": "zeroIssuesImage"
3850
- }, /*#__PURE__*/React.createElement(ThumbsUp, {
3851
- sx: {
3852
- height: '69px',
3853
- width: '58px'
3982
+ onBlur: function onBlur() {
3983
+ return trigger(fieldNames.cloud4);
3854
3984
  }
3855
- })), errorList.length > 0 && errorList.map(function (error, index) {
3856
- return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3857
- , {
3858
- // eslint-disable-next-line react/no-array-index-key
3859
- key: "message-".concat(index),
3860
- variant: "body1",
3861
- "data-testid": "errorMessage"
3862
- }, getErrorMessage(error, index));
3863
- }))), rootElement);
3864
- };
3865
-
3866
- var TafModuleContext = /*#__PURE__*/React.createContext({
3867
- onValidateForm: null,
3868
- registerValidateForm: null,
3869
- tafAction: null,
3870
- setTafAction: null,
3871
- onPreventCloseView: null
3985
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3986
+ label: "Cloud",
3987
+ name: fieldNames.cloud4,
3988
+ disabled: disabled,
3989
+ defaultValue: getDefaultValue('cloud.cloud4', field),
3990
+ rules: {
3991
+ validate: {
3992
+ validateFourthCloud: function validateFourthCloud$1(value) {
3993
+ return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3994
+ }
3995
+ }
3996
+ }
3997
+ })), !disabled && /*#__PURE__*/React__default.createElement(Grid, {
3998
+ item: true,
3999
+ container: true,
4000
+ justifyContent: "flex-end",
4001
+ alignItems: "flex-end",
4002
+ xs: 24,
4003
+ sm: 1,
4004
+ sx: {
4005
+ marginBottom: '16px'
4006
+ },
4007
+ columns: 24
4008
+ }, /*#__PURE__*/React__default.createElement(TafFormOptionsButton, {
4009
+ isChangeGroup: isChangeGroup,
4010
+ addChangeGroupBelow: addChangeGroupBelow,
4011
+ addChangeGroupAbove: addChangeGroupAbove,
4012
+ removeChangeGroup: function removeChangeGroup() {
4013
+ return onRemoveChangeGroup(index);
4014
+ },
4015
+ clearRow: clearRow,
4016
+ index: index
4017
+ })));
3872
4018
  });
3873
- var useTafModuleContext = function useTafModuleContext() {
3874
- return React.useContext(TafModuleContext);
3875
- };
3876
- var useTafModuleState = function useTafModuleState(_ref) {
3877
- var onPreventCloseView = _ref.onPreventCloseView;
3878
-
3879
- var _React$useState = React.useState(function () {
3880
- return new Promise(function () {
3881
- return true;
3882
- });
3883
- }),
3884
- _React$useState2 = _slicedToArray(_React$useState, 2),
3885
- onValidateForm = _React$useState2[0],
3886
- registerValidateForm = _React$useState2[1];
3887
-
3888
- var _React$useState3 = React.useState(),
3889
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3890
- tafAction = _React$useState4[0],
3891
- setTafAction = _React$useState4[1];
3892
-
3893
- var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3894
- registerValidateForm(function () {
3895
- return promiseToRegister;
3896
- });
3897
- };
3898
-
3899
- return {
3900
- onValidateForm: onValidateForm,
3901
- registerValidateForm: onRegisterValidateForm,
3902
- tafAction: tafAction,
3903
- setTafAction: setTafAction,
3904
- onPreventCloseView: onPreventCloseView
3905
- };
3906
- };
3907
- var TafModuleProvider = function TafModuleProvider(_ref2) {
3908
- var children = _ref2.children,
3909
- _ref2$onPreventCloseV = _ref2.onPreventCloseView,
3910
- onPreventCloseView = _ref2$onPreventCloseV === void 0 ? function () {} : _ref2$onPreventCloseV;
3911
- var contextState = useTafModuleState({
3912
- onPreventCloseView: onPreventCloseView
3913
- });
3914
- return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3915
- value: contextState
3916
- }, children);
3917
- };
3918
-
3919
- /* *
3920
- * Licensed under the Apache License, Version 2.0 (the "License");
3921
- * you may not use this file except in compliance with the License.
3922
- * You may obtain a copy of the License at
3923
- *
3924
- * http://www.apache.org/licenses/LICENSE-2.0
3925
- *
3926
- * Unless required by applicable law or agreed to in writing, software
3927
- * distributed under the License is distributed on an "AS IS" BASIS,
3928
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3929
- * See the License for the specific language governing permissions and
3930
- * limitations under the License.
3931
- *
3932
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3933
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3934
- * */
3935
- var styles = {
3936
- label: {
3937
- color: 'geowebColors.buttons.tertiary.default.color',
3938
- opacity: 1,
3939
- fontSize: '12px',
3940
- fontWeight: 500
3941
- }
3942
- };
3943
-
3944
- var SwitchButton = function SwitchButton(props) {
3945
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3946
- title: "Switch mode"
3947
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(FormLabel, {
3948
- sx: styles.label
3949
- }, "Viewer"), /*#__PURE__*/React.createElement(Switch, Object.assign({
3950
- "data-testid": "switchMode"
3951
- }, props)), /*#__PURE__*/React.createElement(FormLabel, {
3952
- sx: styles.label
3953
- }, "Editor")));
3954
- };
3955
-
3956
- var TafAvatar = function TafAvatar(_ref) {
3957
- var editor = _ref.editor,
3958
- _ref$tooltipPlacement = _ref.tooltipPlacement,
3959
- tooltipPlacement = _ref$tooltipPlacement === void 0 ? 'bottom' : _ref$tooltipPlacement;
3960
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3961
- title: "Editor: ".concat(editor),
3962
- placement: tooltipPlacement
3963
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Avatar, {
3964
- size: "small"
3965
- }, getInitials(editor))));
3966
- };
3967
4019
 
3968
4020
  var noop = function noop() {};
3969
4021
 
@@ -3995,7 +4047,10 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
3995
4047
  _ref$fetchNewTafList = _ref.fetchNewTafList,
3996
4048
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
3997
4049
  return null;
3998
- } : _ref$fetchNewTafList;
4050
+ } : _ref$fetchNewTafList,
4051
+ _ref$previousTaf = _ref.previousTaf,
4052
+ previousTaf = _ref$previousTaf === void 0 ? null : _ref$previousTaf;
4053
+ var formRef = React__default.useRef();
3999
4054
  var originalTaf = tafFromBackend.taf,
4000
4055
  editor = tafFromBackend.editor;
4001
4056
 
@@ -4062,7 +4117,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4062
4117
  return confirmDialog({
4063
4118
  title: getConfirmationDialogTitle(action),
4064
4119
  description: getConfirmationDialogContent(action, function () {
4065
- return isTafAmendedCorrectedChanged(isFormDirty$1, originalTaf, convertTafValuesToObject(getValues()));
4120
+ return isTafAmendedCorrectedChanged( // If already saved as draft amd/cor then send over the previous taf
4121
+ originalTaf.status === 'DRAFT_AMENDED' || originalTaf.status === 'DRAFT_CORRECTED' ? previousTaf : originalTaf, convertTafValuesToObject(getValues()));
4066
4122
  }),
4067
4123
  confirmLabel: getConfirmationDialogButtonLabel(action)
4068
4124
  });
@@ -4259,14 +4315,37 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4259
4315
  resetFormState(null, true, convertTafValuesToObject(data));
4260
4316
  }
4261
4317
 
4262
- case 6:
4318
+ return _context3.abrupt("return", true);
4319
+
4320
+ case 7:
4263
4321
  case "end":
4264
4322
  return _context3.stop();
4265
4323
  }
4266
4324
  }
4267
4325
  }, _callee3);
4268
4326
  }));
4269
- })();
4327
+ })().then(function () {
4328
+ var hasFormErrors = Object.keys(errors).length;
4329
+ var formNodeRef = formRef.current;
4330
+
4331
+ if (hasFormErrors && formNodeRef) {
4332
+ var inputsWithError = formNodeRef.querySelectorAll('.Mui-error');
4333
+ var firstFormGroupWithError = inputsWithError.length ? inputsWithError[inputsWithError.length - 1].closest('.formRow') : null;
4334
+
4335
+ if (firstFormGroupWithError) {
4336
+ var _getFormRowPosition = getFormRowPosition(firstFormGroupWithError),
4337
+ top = _getFormRowPosition.top,
4338
+ left = _getFormRowPosition.left;
4339
+
4340
+ var tafModuleNode = formNodeRef.closest('#tafmodule');
4341
+ var newTop = top - (tafModuleNode === null || tafModuleNode === void 0 ? void 0 : tafModuleNode.getBoundingClientRect().top) || 0;
4342
+ setIsIssuesPaneOpen(true, {
4343
+ top: newTop,
4344
+ left: left
4345
+ });
4346
+ }
4347
+ }
4348
+ });
4270
4349
  break;
4271
4350
 
4272
4351
  default:
@@ -4452,7 +4531,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4452
4531
  editor: editor
4453
4532
  }))), /*#__PURE__*/React__default.createElement("form", {
4454
4533
  "data-testid": "taf-form",
4455
- onSubmit: handleSubmit(onSubmit)
4534
+ onSubmit: handleSubmit(onSubmit),
4535
+ ref: formRef
4456
4536
  }, /*#__PURE__*/React__default.createElement(TafFormRow, {
4457
4537
  disabled: isDisabled,
4458
4538
  onAddChangeGroupBelow: onAddRow,
@@ -4754,6 +4834,14 @@ var getNewTafLocationIndex = function getNewTafLocationIndex(tafLocations, previ
4754
4834
 
4755
4835
  return 0;
4756
4836
  };
4837
+ var getPreviousTaf = function getPreviousTaf(tafList, currentTaf) {
4838
+ var previousId = currentTaf.taf.previousId;
4839
+ if (!previousId) return null;
4840
+ var previousTaf = tafList.find(function (taf) {
4841
+ return taf.taf.uuid === previousId;
4842
+ });
4843
+ return previousTaf ? previousTaf.taf : null;
4844
+ };
4757
4845
 
4758
4846
  /* *
4759
4847
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -5592,7 +5680,10 @@ var TafPanel = function TafPanel(_ref) {
5592
5680
  _ref$fetchNewTafList = _ref.fetchNewTafList,
5593
5681
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
5594
5682
  return null;
5595
- } : _ref$fetchNewTafList;
5683
+ } : _ref$fetchNewTafList,
5684
+ _ref$previousTaf = _ref.previousTaf,
5685
+ previousTaf = _ref$previousTaf === void 0 ? null : _ref$previousTaf,
5686
+ tafAction = _ref.tafAction;
5596
5687
  var severity = isWarning(error) ? 'warning' : 'error';
5597
5688
 
5598
5689
  var onTafAction = function onTafAction(action, taf) {
@@ -5642,7 +5733,7 @@ var TafPanel = function TafPanel(_ref) {
5642
5733
  index: index,
5643
5734
  "data-testid": "taf-panel".concat(activeTafIndex === index ? '-active' : '')
5644
5735
  }, /*#__PURE__*/React__default.createElement(TafHeader, {
5645
- title: getTafStatusLabel(tafFromBackend.taf.status),
5736
+ title: getTafStatusLabel(tafFromBackend.taf.status, tafAction, isFormDisabled),
5646
5737
  sx: {
5647
5738
  marginBottom: '4px'
5648
5739
  }
@@ -5675,7 +5766,8 @@ var TafPanel = function TafPanel(_ref) {
5675
5766
  isDisabled: isFormDisabled,
5676
5767
  setIsDisabled: setIsFormDisabled,
5677
5768
  onSwitchEditor: patchTaf,
5678
- fetchNewTafList: fetchNewTafList
5769
+ fetchNewTafList: fetchNewTafList,
5770
+ previousTaf: previousTaf
5679
5771
  })));
5680
5772
  };
5681
5773
 
@@ -5786,7 +5878,7 @@ var getSnackbarMessage = function getSnackbarMessage(tafFromFrontEnd) {
5786
5878
  return 'Saved as draft';
5787
5879
 
5788
5880
  case 'DRAFT_AMENDED':
5789
- return 'Saved as draft amended';
5881
+ return 'Saved as draft amendment';
5790
5882
 
5791
5883
  case 'DRAFT_CORRECTED':
5792
5884
  return 'Saved as draft correction';
@@ -5827,7 +5919,8 @@ var TafLayout = function TafLayout(_ref2) {
5827
5919
  isIssuesPaneOpen = _useIssuesPane.isIssuesPaneOpen,
5828
5920
  onToggleIssuesPane = _useIssuesPane.onToggleIssuesPane,
5829
5921
  onCloseIssuesPane = _useIssuesPane.onCloseIssuesPane,
5830
- startPosition = _useIssuesPane.startPosition;
5922
+ startPosition = _useIssuesPane.startPosition,
5923
+ onUserHasDragged = _useIssuesPane.onUserHasDragged;
5831
5924
 
5832
5925
  var _usePostTafRequest = usePostTafRequest(api.postTaf),
5833
5926
  isLoading = _usePostTafRequest.isLoading,
@@ -6151,7 +6244,9 @@ var TafLayout = function TafLayout(_ref2) {
6151
6244
  patchTaf: patchTaf,
6152
6245
  isLoading: isLoading,
6153
6246
  error: error,
6154
- fetchNewTafList: onUpdateTaf
6247
+ fetchNewTafList: onUpdateTaf,
6248
+ previousTaf: getPreviousTaf(tafList, tafFromBackend),
6249
+ tafAction: tafAction
6155
6250
  });
6156
6251
  }))), /*#__PURE__*/React__default.createElement(Grid, {
6157
6252
  item: true,
@@ -6174,7 +6269,8 @@ var TafLayout = function TafLayout(_ref2) {
6174
6269
  })))))), /*#__PURE__*/React__default.createElement(IssuesPaneWrapper, {
6175
6270
  handleClose: onCloseIssuesPane,
6176
6271
  isOpen: isIssuesPaneOpen,
6177
- startPosition: startPosition
6272
+ startPosition: startPosition,
6273
+ onUserHasDragged: onUserHasDragged
6178
6274
  }));
6179
6275
  };
6180
6276
 
@@ -7191,15 +7287,21 @@ var fakeDraftAmendmentTaf = {
7191
7287
  }
7192
7288
  };
7193
7289
 
7290
+ var _a = fakeDraftAmendmentTaf.taf;
7291
+ _a.changeGroups;
7292
+ var fakeDraftAmendmentWithoutChangeGroups = __rest(_a, ["changeGroups"]); // Only use for display purposes in the list!
7293
+
7294
+
7194
7295
  ({
7195
7296
  creationDate: "2022-01-06T14:00:00Z",
7196
7297
  canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7197
7298
  editor: null,
7198
- taf: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf), {
7299
+ taf: Object.assign(Object.assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7199
7300
  location: 'EHRD',
7200
7301
  baseTime: "2022-01-06T12:00:00Z",
7201
7302
  validDateStart: "2022-01-06T14:00:00Z",
7202
7303
  validDateEnd: "2022-01-07T18:00:00Z",
7304
+ previousId: "previousIdOfPreviousTAF",
7203
7305
  previousValidDateStart: "2022-01-06T12:00:00Z",
7204
7306
  previousValidDateEnd: "2022-01-07T18:00:00Z",
7205
7307
  baseForecast: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
@@ -7207,8 +7309,32 @@ var fakeDraftAmendmentTaf = {
7207
7309
  start: "2022-01-06T14:00:00Z",
7208
7310
  end: "2022-01-07T18:00:00Z"
7209
7311
  }
7210
- }),
7211
- changeGroups: []
7312
+ })
7313
+ })
7314
+ }); // Use as the original previous TAF for TAF above
7315
+
7316
+ ({
7317
+ creationDate: "2022-01-06T14:00:00Z",
7318
+ canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7319
+ editor: null,
7320
+ taf: Object.assign(Object.assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7321
+ status: 'AMENDED',
7322
+ uuid: 'previousIdOfPreviousTAF',
7323
+ location: 'EHRD',
7324
+ baseTime: "2022-01-06T12:00:00Z",
7325
+ validDateStart: "2022-01-06T14:00:00Z",
7326
+ validDateEnd: "2022-01-07T18:00:00Z",
7327
+ baseForecast: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
7328
+ valid: {
7329
+ start: "2022-01-06T14:00:00Z",
7330
+ end: "2022-01-07T18:00:00Z"
7331
+ },
7332
+ wind: {
7333
+ direction: 344,
7334
+ speed: 90,
7335
+ unit: 'KT'
7336
+ }
7337
+ })
7212
7338
  })
7213
7339
  });
7214
7340
  var fakeAmendmentTaf = {