@opengeoweb/taf 4.10.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();
@@ -2637,190 +2810,59 @@ var fromStatusToAction = function fromStatusToAction(tafStatus) {
2637
2810
  return 'NEW';
2638
2811
  }
2639
2812
  };
2813
+ var isFormDirty = function isFormDirty(dirtyFields) {
2814
+ return Object.keys(dirtyFields).length > 0;
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;
2640
2821
 
2641
- var textFieldStyle = function textFieldStyle(theme) {
2822
+ var newTop = top + height;
2642
2823
  return {
2643
- // input
2644
- marginRight: '2px',
2645
- marginBottom: '4px',
2646
- width: 56,
2647
- height: 46,
2648
- input: {
2649
- textAlign: 'center',
2650
- fontSize: 10,
2651
- fontWeight: 500,
2652
- paddingLeft: 0,
2653
- paddingRight: 0,
2654
- '&.Mui-disabled': {
2655
- color: 'geowebColors.typographyAndIcons.text',
2656
- WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
2657
- },
2658
- // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
2659
- '&:-webkit-autofill': {
2660
- WebkitTransitionDelay: '86400s' // 1 day delay
2824
+ top: newTop,
2825
+ left: left
2826
+ };
2827
+ };
2661
2828
 
2662
- }
2663
- },
2664
- label: {
2665
- transformOrigin: 'center top',
2666
- right: 0,
2667
- textAlign: 'center',
2668
- fontSize: '10px',
2669
- '&.Mui-disabled': {
2670
- color: 'geowebColors.captions.captionStatus.rgba'
2671
- },
2672
- whiteSpace: 'nowrap',
2673
- maxWidth: '100%',
2674
- transform: 'translate(0px, 16px) scale(1)'
2675
- },
2676
- // shrink
2677
- ' .MuiInputLabel-shrink': {
2678
- transform: 'translate(2px, 10px) scale(0.75) !important',
2679
- letterSpacing: '0.33px',
2680
- textAlign: 'left'
2681
- },
2682
- // root
2683
- '&': {
2684
- '.Mui-error.MuiFilledInput-root': {
2685
- 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'
2686
2862
  },
2687
- '.Mui-disabled:before': {
2688
- borderColor: 'transparent'
2689
- }
2863
+ cursor: isSorting ? 'grabbing' : 'grab'
2690
2864
  }
2691
- };
2692
- };
2693
-
2694
- var getTafErrors = function getTafErrors(name, errors) {
2695
- var nameAsArray = name.split('.');
2696
-
2697
- if (nameAsArray[0].includes('changeGroups')) {
2698
- if (errors.changeGroups) {
2699
- var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
2700
- var restArray = nameAsArray.slice(1);
2701
- return getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
2702
- } // No changegroup errors
2703
-
2704
-
2705
- return null;
2706
- }
2707
-
2708
- return getDeepProperty(nameAsArray, errors);
2709
- };
2710
-
2711
- var getDisplayValue = function getDisplayValue(value, disabled) {
2712
- return disabled && !value ? '-' : value;
2713
- };
2714
- var BaseTextField = /*#__PURE__*/React__default.memo(function (props) {
2715
- return /*#__PURE__*/React__default.createElement(TextField, Object.assign({
2716
- type: "text",
2717
- variant: "filled",
2718
- sx: textFieldStyle
2719
- }, props));
2720
- }, function (prevProps, nextProps) {
2721
- return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
2722
- });
2723
-
2724
- var TafFormTextField = function TafFormTextField(_ref) {
2725
- var label = _ref.label,
2726
- _ref$disabled = _ref.disabled,
2727
- disabled = _ref$disabled === void 0 ? false : _ref$disabled,
2728
- _ref$name = _ref.name,
2729
- name = _ref$name === void 0 ? '' : _ref$name,
2730
- _ref$onChange = _ref.onChange,
2731
- onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
2732
- _ref$onBlur = _ref.onBlur,
2733
- onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
2734
- _ref$defaultValue = _ref.defaultValue,
2735
- defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
2736
- _ref$formatter = _ref.formatter,
2737
- formatter = _ref$formatter === void 0 ? null : _ref$formatter,
2738
- rules = _ref.rules,
2739
- _ref$autoComplete = _ref.autoComplete,
2740
- autoComplete = _ref$autoComplete === void 0 ? [] : _ref$autoComplete,
2741
- _ref$autoFocus = _ref.autoFocus,
2742
- autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus;
2743
-
2744
- var _useFormContext = useFormContext(),
2745
- control = _useFormContext.control,
2746
- setValue = _useFormContext.setValue,
2747
- errors = _useFormContext.formState.errors;
2748
-
2749
- var fieldErrors = getTafErrors(name, errors);
2750
-
2751
- var _React$useState = React__default.useState(null),
2752
- _React$useState2 = _slicedToArray(_React$useState, 2),
2753
- maxLength = _React$useState2[0],
2754
- setMaxLength = _React$useState2[1];
2755
-
2756
- var onKeyDown = React__default.useCallback(function (event) {
2757
- var target = event.target;
2758
- var currentValue = target.value,
2759
- selectionStart = target.selectionStart,
2760
- selectionEnd = target.selectionEnd;
2761
- var textSelection = currentValue.substring(selectionStart, selectionEnd);
2762
-
2763
- if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
2764
- var pressedKey = event.key.toString().toUpperCase();
2765
- var foundValue = autoComplete.find(function (el) {
2766
- return el.key === pressedKey;
2767
- }) || null;
2768
-
2769
- if (foundValue) {
2770
- setValue(name, foundValue.value);
2771
- setMaxLength(foundValue.value.length);
2772
- event.preventDefault();
2773
- }
2774
- }
2775
- }, [name, autoComplete, setValue]);
2776
- var onChangeField = React__default.useCallback(function (event, callback) {
2777
- var valueUppercase = event.currentTarget.value.toUpperCase();
2778
-
2779
- if (autoComplete) {
2780
- var exist = autoComplete.find(function (e) {
2781
- return e.value === valueUppercase;
2782
- });
2783
- var newMaxLength = exist ? valueUppercase.length : null;
2784
- setMaxLength(newMaxLength);
2785
- }
2786
-
2787
- callback(valueUppercase);
2788
- onChange(valueUppercase);
2789
- }, [onChange, autoComplete]);
2790
- var onBlurField = React__default.useCallback(function (callback) {
2791
- callback();
2792
- onBlur();
2793
- }, [onBlur]);
2794
- var hasError = !!fieldErrors;
2795
- return /*#__PURE__*/React__default.createElement(Controller, {
2796
- render: function render(_ref2) {
2797
- var field = _ref2.field;
2798
- var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
2799
- return /*#__PURE__*/React__default.createElement(BaseTextField, {
2800
- label: label,
2801
- disabled: disabled,
2802
- name: name,
2803
- value: displayValue,
2804
- inputRef: field.ref,
2805
- onChange: function onChange(e) {
2806
- return onChangeField(e, field.onChange);
2807
- },
2808
- onKeyDown: onKeyDown,
2809
- error: hasError,
2810
- onBlur: function onBlur() {
2811
- return onBlurField(field.onBlur);
2812
- },
2813
- inputProps: {
2814
- maxLength: maxLength
2815
- },
2816
- autoFocus: autoFocus
2817
- });
2818
- },
2819
- name: name,
2820
- control: control,
2821
- defaultValue: defaultValue,
2822
- rules: rules
2823
- });
2865
+ }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
2824
2866
  };
2825
2867
 
2826
2868
  /* *
@@ -2836,52 +2878,77 @@ var TafFormTextField = function TafFormTextField(_ref) {
2836
2878
  * See the License for the specific language governing permissions and
2837
2879
  * limitations under the License.
2838
2880
  *
2839
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2840
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2881
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2882
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
2841
2883
  * */
2842
- // messages
2843
- var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
2844
- var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
2845
-
2846
- var validateChangeField = function validateChangeField(value) {
2847
- var trimmedValue = value.trim();
2848
- var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
2849
- 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
+ });
2850
2889
  };
2851
- var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
2852
- var trimmedProbValue = valueProb.trim();
2853
- var trimmedValue = value.trim();
2890
+ var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
2891
+ switch (sumOfErrors) {
2892
+ case 0:
2893
+ return '0 issues';
2854
2894
 
2855
- if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
2856
- return invalidChangeProbCombinationMessage;
2895
+ case 1:
2896
+ return '1 issue';
2897
+
2898
+ default:
2899
+ return "".concat(sumOfErrors, " issues");
2857
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]);
2858
2908
 
2859
- 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
+ }, []);
2860
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
+ }
2861
2925
 
2862
- /* *
2863
- * Licensed under the Apache License, Version 2.0 (the "License");
2864
- * you may not use this file except in compliance with the License.
2865
- * You may obtain a copy of the License at
2866
- *
2867
- * http://www.apache.org/licenses/LICENSE-2.0
2868
- *
2869
- * Unless required by applicable law or agreed to in writing, software
2870
- * distributed under the License is distributed on an "AS IS" BASIS,
2871
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2872
- * See the License for the specific language governing permissions and
2873
- * limitations under the License.
2874
- *
2875
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2876
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2877
- * */
2878
- // messages
2879
- var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
2926
+ if (error.type === 'validateRequiredMainOptional') {
2927
+ var _exist = list.find(function (e) {
2928
+ return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
2929
+ });
2880
2930
 
2881
- var validateProbabilityField = function validateProbabilityField(value) {
2882
- var trimmedValue = value.trim();
2883
- var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
2884
- return isValid ? true : invalidProbabilityMessage;
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;
2885
2952
  };
2886
2953
 
2887
2954
  /* *
@@ -2897,502 +2964,249 @@ var validateProbabilityField = function validateProbabilityField(value) {
2897
2964
  * See the License for the specific language governing permissions and
2898
2965
  * limitations under the License.
2899
2966
  *
2900
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2901
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
2967
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2968
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
2902
2969
  * */
2903
2970
 
2904
- var TafFormOptionsButton = function TafFormOptionsButton(_ref) {
2905
- var isChangeGroup = _ref.isChangeGroup,
2906
- addChangeGroupBelow = _ref.addChangeGroupBelow,
2907
- addChangeGroupAbove = _ref.addChangeGroupAbove,
2908
- removeChangeGroup = _ref.removeChangeGroup,
2909
- clearRow = _ref.clearRow,
2910
- index = _ref.index;
2911
- var insertAbove = {
2912
- text: 'Insert 1 row above',
2913
- icon: /*#__PURE__*/React.createElement(Add, null),
2914
- action: addChangeGroupAbove
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);
2984
+
2985
+ var toggleIssuesPane = function toggleIssuesPane(newPosition) {
2986
+ return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
2915
2987
  };
2916
- var insertBelow = {
2917
- text: 'Insert 1 row below',
2918
- icon: /*#__PURE__*/React.createElement(Add, null),
2919
- action: addChangeGroupBelow
2920
- };
2921
- var deleteRow = {
2922
- text: 'Delete row',
2923
- icon: /*#__PURE__*/React.createElement(Delete, null),
2924
- action: removeChangeGroup
2925
- };
2926
- var clear = {
2927
- text: 'Clear row',
2928
- icon: /*#__PURE__*/React.createElement(Close, null),
2929
- action: clearRow
2930
- };
2931
- var menuItemsBaseForecast = [insertBelow, clear];
2932
- var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
2933
- return /*#__PURE__*/React.createElement(ToggleMenu, {
2934
- buttonTestId: "tafFormOptions[".concat(index, "]"),
2935
- buttonSx: {
2936
- marginTop: '10px',
2937
- marginLeft: '4px'
2938
- },
2939
- menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
2940
- });
2941
- };
2942
-
2943
- var getDefaultValue = function getDefaultValue(fieldName, data) {
2944
- if (!data) {
2945
- return '';
2946
- }
2947
-
2948
- return getDeepProperty(fieldName.split('.'), data) || '';
2949
- };
2950
-
2951
- var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
2952
- return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
2953
- ];
2954
- };
2955
-
2956
- var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2957
- var isNotRequiredForAction = _a.isNotRequiredForAction,
2958
- _a$isChangeGroup = _a.isChangeGroup,
2959
- isChangeGroup = _a$isChangeGroup === void 0 ? false : _a$isChangeGroup,
2960
- _a$disabled = _a.disabled,
2961
- disabled = _a$disabled === void 0 ? false : _a$disabled,
2962
- _a$index = _a.index,
2963
- index = _a$index === void 0 ? -1 : _a$index,
2964
- onRemoveChangeGroup = _a.onRemoveChangeGroup,
2965
- _a$field = _a.field,
2966
- field = _a$field === void 0 ? null : _a$field,
2967
- _a$dragHandle = _a.dragHandle,
2968
- dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
2969
- onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
2970
- onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
2971
- onClearRow = _a.onClearRow,
2972
- props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
2973
-
2974
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
2975
- var fieldNames = getFieldNames(isChangeGroup, index);
2976
-
2977
- var _useFormContext = useFormContext(),
2978
- getValues = _useFormContext.getValues,
2979
- trigger = _useFormContext.trigger; // cross-field required validation
2980
-
2981
2988
 
2982
- var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
2983
- _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
2984
- mainFields = _getRequiredCrossFiel2[0],
2985
- mainOptionalFields = _getRequiredCrossFiel2[1],
2986
- subFields = _getRequiredCrossFiel2[2];
2987
-
2988
- var hasFieldsValue = function hasFieldsValue(fields) {
2989
- return fields.map(getValues).find(function (field) {
2990
- return !!field;
2991
- });
2992
- }; // Used to validate the required field for change groups: Valid
2993
-
2994
-
2995
- var validateRequiredMain = function validateRequiredMain(value) {
2996
- return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
2997
- }; // Used to ensure either probability or change is entered, or both
2989
+ var onClickButton = function onClickButton(event) {
2990
+ var _a;
2998
2991
 
2992
+ var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
2993
+ left = _event$currentTarget$.left,
2994
+ top = _event$currentTarget$.top;
2999
2995
 
3000
- var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3001
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3002
- }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
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
+ };
3003
3006
 
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
+ }));
3028
+ };
3004
3029
 
3005
- var validateRequiredSub = function validateRequiredSub(value) {
3006
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3007
- }; // 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';
3008
3034
 
3035
+ case 1:
3036
+ return 'There is an issue to address';
3009
3037
 
3010
- var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3011
- var changeField = getValues("".concat(namePrefix, ".change"));
3012
- var visibilityField = getValues("".concat(namePrefix, ".visibility"));
3013
- var isFM = changeField && changeField.trim() === 'FM';
3014
- var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3038
+ default:
3039
+ return 'There are a few issues to address';
3040
+ }
3041
+ };
3015
3042
 
3016
- if (isNotRequiredForAction(value) !== true && !value.length) {
3017
- if (isChangeGroup && isFM || !isChangeGroup) {
3018
- // exception for CavOK
3019
- if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3020
- return true;
3021
- } // 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
+ }
3022
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];
3023
3063
 
3024
- if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3025
- return true;
3026
- }
3064
+ var _React$useState3 = React.useState(null),
3065
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3066
+ startPosition = _React$useState4[0],
3067
+ setStartPosition = _React$useState4[1];
3027
3068
 
3028
- return "".concat(fieldName, " is required");
3029
- }
3030
- }
3069
+ var _React$useState5 = React.useState(false),
3070
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
3071
+ hasUserDragged = _React$useState6[0],
3072
+ setHasUserDragged = _React$useState6[1];
3031
3073
 
3032
- return true;
3074
+ var onUserHasDragged = function onUserHasDragged() {
3075
+ return setHasUserDragged(true);
3033
3076
  };
3034
3077
 
3035
- var validatePreviousRow = React__default.useCallback(function () {
3036
- if (isChangeGroup && index > 0) {
3037
- var _getValues = getValues(),
3038
- validDateEnd = _getValues.validDateEnd,
3039
- validDateStart = _getValues.validDateStart,
3040
- changeGroups = _getValues.changeGroups;
3041
-
3042
- var currentChangeGroup = changeGroups[index];
3043
- var previousChangeGroup = changeGroups[index - 1];
3044
- return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3078
+ var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3079
+ if (!hasUserDragged) {
3080
+ setStartPosition(newPosition);
3045
3081
  }
3046
3082
 
3047
- return true;
3048
- }, [index, isChangeGroup, getValues]);
3049
-
3050
- var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3051
- var indexedFieldName = "changeGroups[".concat(rowIndex, "].").concat(fieldname);
3052
- var rowValue = getValues(indexedFieldName);
3053
- return rowValue ? [indexedFieldName] : [];
3083
+ setIsIssuesPaneOpen(isOpen);
3054
3084
  };
3055
3085
 
3056
- var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3057
- return getFieldFromRow('valid', index + 1);
3086
+ var onCloseIssuesPane = function onCloseIssuesPane() {
3087
+ return setIsIssuesPaneOpen(false);
3058
3088
  };
3059
3089
 
3060
- var validateNextRows = React__default.useCallback(function () {
3061
- if (isChangeGroup) {
3062
- var _getValues2 = getValues(),
3063
- validDateEnd = _getValues2.validDateEnd,
3064
- validDateStart = _getValues2.validDateStart,
3065
- changeGroups = _getValues2.changeGroups;
3066
-
3067
- var currentChangeGroup = changeGroups[index];
3068
- var nextChangeGroups = changeGroups.slice(index + 1);
3069
- return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3070
- }
3071
-
3072
- return true;
3073
- }, [index, isChangeGroup, getValues]);
3074
-
3075
- var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3076
- var _getValues3 = getValues(),
3077
- changeGroups = _getValues3.changeGroups;
3078
-
3079
- var previousChangeGroups = changeGroups.slice(0, rowIndex);
3080
- var validFields = previousChangeGroups.map(function (_element, index) {
3081
- return getFieldFromRow('valid', index)[0];
3082
- });
3083
- return validFields;
3090
+ return {
3091
+ isIssuesPaneOpen: isIssuesPaneOpen,
3092
+ startPosition: startPosition,
3093
+ onToggleIssuesPane: onToggleIssuesPane,
3094
+ onCloseIssuesPane: onCloseIssuesPane,
3095
+ onUserHasDragged: onUserHasDragged
3084
3096
  };
3097
+ };
3085
3098
 
3086
- var addChangeGroupBelow = React__default.useCallback(function () {
3087
- onAddChangeGroupBelow(index);
3088
- }, [onAddChangeGroupBelow, index]);
3089
- var addChangeGroupAbove = React__default.useCallback(function () {
3090
- onAddChangeGroupAbove(index);
3091
- }, [onAddChangeGroupAbove, index]);
3092
- var clearRow = React__default.useCallback(function () {
3093
- onClearRow(index);
3094
- }, [onClearRow, index]);
3095
- return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
3096
- sx: {
3097
- marginTop: '8px',
3098
- backgroundColor: 'geowebColors.cards.cardContainer',
3099
- position: 'relative',
3100
- '&.sortable-chosen': {
3101
- boxShadow: 1
3102
- },
3103
- '&.sortable-ghost': {
3104
- opacity: 0.5
3105
- }
3106
- },
3107
- justifyContent: "flex-start",
3108
- "data-testid": "row-".concat(namePrefix),
3109
- container: true,
3110
- ref: ref
3111
- }, props), /*#__PURE__*/React__default.createElement(Grid, {
3112
- columns: 24,
3113
- item: true,
3114
- container: true,
3115
- justifyContent: "flex-end",
3116
- xs: 24,
3117
- sm: 23
3118
- }, !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
3119
- label: "Type",
3120
- name: fieldNames.messageType,
3121
- disabled: true
3122
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3123
- label: "Location",
3124
- name: "location",
3125
- disabled: true
3126
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3127
- formatter: formatIssueTime,
3128
- label: "Issue time",
3129
- name: "issueDate",
3130
- disabled: true
3131
- })), isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box, {
3132
- sx: {
3133
- width: 56,
3134
- marginRight: '2px'
3135
- }
3136
- }, !disabled && dragHandle), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3137
- label: "Prob",
3138
- name: fieldNames.probability,
3139
- disabled: disabled,
3140
- defaultValue: getDefaultValue('probability', field),
3141
- rules: {
3142
- validate: {
3143
- validateRequiredMainOptional: validateRequiredMainOptional,
3144
- validateProbabilityField: validateProbabilityField
3145
- }
3146
- },
3147
- autoComplete: [{
3148
- key: '3',
3149
- value: 'PROB30'
3150
- }, {
3151
- key: '4',
3152
- value: 'PROB40'
3153
- }],
3154
- onBlur: function onBlur() {
3155
- if (isChangeGroup) {
3156
- var nextValidFieldName = getValidFieldFromNextRow();
3157
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
3158
- }
3159
- }
3160
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3161
- label: "Change",
3162
- name: fieldNames.change,
3163
- disabled: disabled,
3164
- defaultValue: getDefaultValue('change', field),
3165
- rules: {
3166
- validate: {
3167
- validateRequiredMainOptional: validateRequiredMainOptional,
3168
- validateChangeField: validateChangeField,
3169
- validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3170
- return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3171
- }
3172
- }
3173
- },
3174
- autoComplete: [{
3175
- key: 'T',
3176
- value: 'TEMPO'
3177
- }, {
3178
- key: 'B',
3179
- value: 'BECMG'
3180
- }, {
3181
- key: 'F',
3182
- value: 'FM'
3183
- }],
3184
- onBlur: function onBlur() {
3185
- if (isChangeGroup) {
3186
- var nextValidFieldName = getValidFieldFromNextRow();
3187
- var previousValidFieldNames = getPreviousValidFields(index);
3188
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3189
- }
3190
- }
3191
- })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3192
- label: "Valid",
3193
- name: fieldNames.valid,
3194
- // always disabled for baseforecast row
3195
- disabled: !isChangeGroup ? true : disabled,
3196
- defaultValue: getDefaultValue('valid', field),
3197
- rules: {
3198
- validate: {
3199
- validateRequiredMain: validateRequiredMain,
3200
- validateValidField: function validateValidField$1(value) {
3201
- return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3202
- },
3203
- validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3204
- return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3205
- },
3206
- validatePreviousRow: validatePreviousRow,
3207
- validateNextRows: validateNextRows
3208
- }
3209
- },
3210
- onBlur: function onBlur() {
3211
- if (isChangeGroup) {
3212
- var nextValidFieldName = getValidFieldFromNextRow();
3213
- var previousValidFieldNames = getPreviousValidFields(index);
3214
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3215
- }
3216
- }
3217
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3218
- label: "Wind",
3219
- name: fieldNames.wind,
3220
- disabled: disabled,
3221
- defaultValue: getDefaultValue('wind', field),
3222
- rules: {
3223
- validate: {
3224
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3225
- return _validateRequiredMainFields(value, 'Wind');
3226
- },
3227
- validateRequiredSub: validateRequiredSub,
3228
- validateWindField: function validateWindField$1(value) {
3229
- return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3230
- }
3231
- }
3232
- },
3233
- onBlur: function onBlur() {
3234
- if (isChangeGroup) {
3235
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
3236
- }
3237
- },
3238
- autoFocus: !isChangeGroup
3239
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3240
- label: "Visibility",
3241
- name: fieldNames.visibility,
3242
- disabled: disabled,
3243
- defaultValue: getDefaultValue('visibility', field),
3244
- rules: {
3245
- validate: {
3246
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3247
- return _validateRequiredMainFields(value, 'Visibility');
3248
- },
3249
- validateRequiredSub: validateRequiredSub,
3250
- validateVisibilityField: validateVisibilityField
3251
- }
3252
- },
3253
- autoComplete: [{
3254
- key: 'C',
3255
- value: 'CAVOK'
3256
- }],
3257
- onBlur: function onBlur() {
3258
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3259
- trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3260
- }
3261
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3262
- label: "Weather",
3263
- name: fieldNames.weather1,
3264
- disabled: disabled,
3265
- defaultValue: getDefaultValue('weather.weather1', field),
3266
- rules: {
3267
- validate: {
3268
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3269
- return _validateRequiredMainFields(value, 'Weather');
3270
- },
3271
- validateRequiredSub: validateRequiredSub,
3272
- validateWeatherField: function validateWeatherField$1(value) {
3273
- return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3274
- }
3275
- }
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'
3276
3116
  },
3277
- onBlur: function onBlur() {
3278
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3279
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3280
- }
3281
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3282
- label: "Weather",
3283
- name: fieldNames.weather2,
3284
- disabled: disabled,
3285
- defaultValue: getDefaultValue('weather.weather2', field),
3286
- rules: {
3287
- validate: {
3288
- validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3289
- return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3290
- }
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();
3291
3128
  }
3292
- },
3293
- onBlur: function onBlur() {
3294
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3295
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3296
3129
  }
3297
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3298
- label: "Weather",
3299
- name: fieldNames.weather3,
3300
- disabled: disabled,
3301
- defaultValue: getDefaultValue('weather.weather3', field),
3302
- rules: {
3303
- validate: {
3304
- validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3305
- return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3306
- }
3307
- }
3308
- },
3309
- onBlur: function onBlur() {
3310
- return trigger([fieldNames.wind, fieldNames.cloud1]);
3130
+ }, /*#__PURE__*/React.createElement(Box, {
3131
+ component: "div",
3132
+ sx: {
3133
+ marginTop: '16px',
3134
+ marginLeft: '24px'
3311
3135
  }
3312
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3313
- label: "Cloud",
3314
- name: fieldNames.cloud1,
3315
- disabled: disabled,
3316
- defaultValue: getDefaultValue('cloud.cloud1', field),
3317
- rules: {
3318
- validate: {
3319
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3320
- return _validateRequiredMainFields(value, 'Clouds');
3321
- },
3322
- validateRequiredSub: validateRequiredSub,
3323
- validateFirstCloud: function validateFirstCloud$1(value) {
3324
- return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3325
- }
3326
- }
3136
+ }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3137
+ component: "div",
3138
+ sx: {
3139
+ fontSize: '4rem'
3327
3140
  },
3328
- onBlur: function onBlur() {
3329
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3330
- 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'
3331
3146
  }
3332
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3333
- label: "Cloud",
3334
- name: fieldNames.cloud2,
3335
- disabled: disabled,
3336
- defaultValue: getDefaultValue('cloud.cloud2', field),
3337
- rules: {
3338
- validate: {
3339
- validateSecondCloud: function validateSecondCloud$1(value) {
3340
- return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3341
- }
3342
- }
3343
- },
3344
- onBlur: function onBlur() {
3345
- return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3346
- }
3347
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3348
- label: "Cloud",
3349
- name: fieldNames.cloud3,
3350
- disabled: disabled,
3351
- defaultValue: getDefaultValue('cloud.cloud3', field),
3352
- rules: {
3353
- validate: {
3354
- validateThirdCloud: function validateThirdCloud$1(value) {
3355
- return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3356
- }
3357
- }
3358
- },
3359
- onBlur: function onBlur() {
3360
- return trigger(fieldNames.cloud4);
3361
- }
3362
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3363
- label: "Cloud",
3364
- name: fieldNames.cloud4,
3365
- disabled: disabled,
3366
- defaultValue: getDefaultValue('cloud.cloud4', field),
3367
- rules: {
3368
- validate: {
3369
- validateFourthCloud: function validateFourthCloud$1(value) {
3370
- return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3371
- }
3372
- }
3373
- }
3374
- })), !disabled && /*#__PURE__*/React__default.createElement(Grid, {
3375
- item: true,
3376
- container: true,
3377
- justifyContent: "flex-end",
3378
- alignItems: "flex-end",
3379
- xs: 24,
3380
- sm: 1,
3381
- sx: {
3382
- marginBottom: '16px'
3383
- },
3384
- columns: 24
3385
- }, /*#__PURE__*/React__default.createElement(TafFormOptionsButton, {
3386
- isChangeGroup: isChangeGroup,
3387
- addChangeGroupBelow: addChangeGroupBelow,
3388
- addChangeGroupAbove: addChangeGroupAbove,
3389
- removeChangeGroup: function removeChangeGroup() {
3390
- return onRemoveChangeGroup(index);
3391
- },
3392
- clearRow: clearRow,
3393
- index: index
3394
- })));
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
3395
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
+ };
3396
3210
 
3397
3211
  /* *
3398
3212
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -3407,143 +3221,227 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3407
3221
  * See the License for the specific language governing permissions and
3408
3222
  * limitations under the License.
3409
3223
  *
3410
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3411
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3224
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3225
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3412
3226
  * */
3413
- var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3414
- switch (tafAction) {
3415
- case 'AMEND':
3416
- case 'DRAFT_AMEND':
3417
- return 'DRAFT_AMEND';
3418
-
3419
- case 'CORRECT':
3420
- case 'DRAFT_CORRECT':
3421
- return 'DRAFT_CORRECT';
3422
-
3423
- default:
3424
- return 'DRAFT';
3227
+ var styles = {
3228
+ label: {
3229
+ color: 'geowebColors.buttons.tertiary.default.color',
3230
+ opacity: 1,
3231
+ fontSize: '12px',
3232
+ fontWeight: 500
3425
3233
  }
3426
3234
  };
3427
3235
 
3428
- var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3429
- switch (tafAction) {
3430
- case 'AMEND':
3431
- case 'DRAFT_AMEND':
3432
- return 'AMEND';
3433
-
3434
- case 'CORRECT':
3435
- case 'DRAFT_CORRECT':
3436
- 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
+ };
3437
3247
 
3438
- default:
3439
- return 'PUBLISH';
3440
- }
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))));
3441
3258
  };
3442
3259
 
3443
- var buttonsStyle = {
3444
- button: {
3445
- minWidth: {
3446
- xs: '56px',
3447
- 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
+ }
3448
3282
  },
3449
- width: {
3450
- xs: '56px',
3451
- 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)'
3452
3294
  },
3453
- marginLeft: {
3454
- xs: 0.5,
3455
- sm: 1
3295
+ // shrink
3296
+ ' .MuiInputLabel-shrink': {
3297
+ transform: 'translate(2px, 10px) scale(0.75) !important',
3298
+ letterSpacing: '0.33px',
3299
+ textAlign: 'left'
3456
3300
  },
3457
- marginTop: 3,
3458
- marginBottom: 3
3459
- }
3460
- };
3461
-
3462
- var ViewModeButtons = function ViewModeButtons(_ref) {
3463
- var canBe = _ref.canBe,
3464
- onTafViewModeButtonPress = _ref.onTafViewModeButtonPress;
3465
- 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, {
3466
- "data-testid": "canceltaf",
3467
- variant: "tertiary",
3468
- onClick: function onClick() {
3469
- return onTafViewModeButtonPress('CANCEL');
3470
- }
3471
- }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
3472
- "data-testid": "correcttaf",
3473
- variant: "tertiary",
3474
- onClick: function onClick() {
3475
- return onTafViewModeButtonPress('CORRECT');
3476
- }
3477
- }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default.createElement(Button, {
3478
- "data-testid": "amendtaf",
3479
- variant: "tertiary",
3480
- onClick: function onClick() {
3481
- 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
+ }
3482
3309
  }
3483
- }, "Amend"));
3310
+ };
3484
3311
  };
3485
3312
 
3486
- var TafFormButtons = function TafFormButtons(_ref2) {
3487
- var _ref2$isFormDisabled = _ref2.isFormDisabled,
3488
- isFormDisabled = _ref2$isFormDisabled === void 0 ? false : _ref2$isFormDisabled,
3489
- tafAction = _ref2.tafAction,
3490
- _ref2$canBe = _ref2.canBe,
3491
- canBe = _ref2$canBe === void 0 ? [] : _ref2$canBe,
3492
- onTafEditModeButtonPress = _ref2.onTafEditModeButtonPress,
3493
- onTafViewModeButtonPress = _ref2.onTafViewModeButtonPress;
3494
- return /*#__PURE__*/React__default.createElement(Grid, {
3495
- container: true,
3496
- justifyContent: "flex-end",
3497
- sx: buttonsStyle,
3498
- columns: 24
3499
- }, /*#__PURE__*/React__default.createElement(Grid, {
3500
- item: true,
3501
- container: true,
3502
- justifyContent: "flex-end",
3503
- columns: 24,
3504
- xs: 24,
3505
- sm: 23
3506
- }, isFormDisabled ? /*#__PURE__*/React__default.createElement(ViewModeButtons, {
3507
- canBe: canBe,
3508
- onTafViewModeButtonPress: onTafViewModeButtonPress
3509
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
3510
- "data-testid": "cleartaf",
3511
- variant: "tertiary",
3512
- onClick: function onClick() {
3513
- // Simply discard the changes and close the dialog.
3514
- onTafEditModeButtonPress('CLEAR');
3515
- }
3516
- }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
3517
- "data-testid": "savedrafttaf",
3518
- variant: "tertiary",
3519
- onClick: function onClick() {
3520
- /* Save the TAF as draft:
3521
- if action NEW or DRAFT - new status will be DRAFT -- default
3522
- if action AMEND - new status will be DRAFT_AMENDED
3523
- if action CORRECT - new status will be DRAFT_CORRECTED
3524
- if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3525
- if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3526
- */
3527
- 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
+ }
3528
3395
  }
3529
- }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
3530
- "data-testid": "publishtaf",
3531
- variant: "tertiary",
3532
- onClick: function onClick() {
3533
- /* Publish the TAF:
3534
- if action NEW or DRAFT - new status will be PUBLISHED -- default
3535
- if action AMEND - new status will be AMENDED
3536
- if action CORRECT - new status will be CORRECTED
3537
- if action DRAFT_AMEND - new status will be AMENDED
3538
- if action DRAFT_CORRECT - new status will be CORRECTED
3539
- */
3540
- 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);
3541
3406
  }
3542
- }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
3543
- item: true,
3544
- columns: 24,
3545
- sm: 1
3546
- }));
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
+ });
3547
3445
  };
3548
3446
 
3549
3447
  /* *
@@ -3559,30 +3457,27 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3559
3457
  * See the License for the specific language governing permissions and
3560
3458
  * limitations under the License.
3561
3459
  *
3562
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3563
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3460
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3461
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3564
3462
  * */
3565
3463
 
3566
- var DragHandle = function DragHandle(_ref) {
3567
- var _ref$isSorting = _ref.isSorting,
3568
- isSorting = _ref$isSorting === void 0 ? false : _ref$isSorting,
3569
- _ref$isDisabled = _ref.isDisabled,
3570
- isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
3571
- index = _ref.index;
3572
- return /*#__PURE__*/React__default.createElement(IconButton, {
3573
- className: "handle",
3574
- "data-testid": "dragHandle-".concat(index),
3575
- disableRipple: true,
3576
- disabled: isDisabled,
3577
- size: "large",
3578
- sx: {
3579
- backgroundColor: 'transparent',
3580
- '&:hover': {
3581
- backgroundColor: 'transparent'
3582
- },
3583
- cursor: isSorting ? 'grabbing' : 'grab'
3584
- }
3585
- }, /*#__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;
3586
3481
  };
3587
3482
 
3588
3483
  /* *
@@ -3598,77 +3493,16 @@ var DragHandle = function DragHandle(_ref) {
3598
3493
  * See the License for the specific language governing permissions and
3599
3494
  * limitations under the License.
3600
3495
  *
3601
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3602
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3496
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3497
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3603
3498
  * */
3604
- var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
3605
- return Object.assign(Object.assign({}, error), {
3606
- isChangeGroup: isChangeGroup,
3607
- rowIndex: rowIndex
3608
- });
3609
- };
3610
- var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
3611
- switch (sumOfErrors) {
3612
- case 0:
3613
- return '0 issues';
3614
3499
 
3615
- case 1:
3616
- return '1 issue';
3500
+ var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
3617
3501
 
3618
- default:
3619
- return "".concat(sumOfErrors, " issues");
3620
- }
3621
- };
3622
- var getErrorValues = function getErrorValues(fieldErrors) {
3623
- var isChangeGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
3624
- var rowIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
3625
- if (!fieldErrors) return [];
3626
- return Object.keys(fieldErrors).reduce(function (list, key) {
3627
- var error = Object.assign({}, fieldErrors[key]);
3628
-
3629
- if (error.ref) {
3630
- return list.concat(getCustomError(error, isChangeGroup, rowIndex));
3631
- }
3632
-
3633
- return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
3634
- }, []);
3635
- };
3636
- var filterDuplicateErrors = function filterDuplicateErrors(errors) {
3637
- return errors.reduce(function (list, error) {
3638
- // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
3639
- if (error.type === 'validateRequiredSub') {
3640
- var exist = list.find(function (e) {
3641
- return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
3642
- });
3643
- return exist ? list : list.concat(error);
3644
- }
3645
-
3646
- if (error.type === 'validateRequiredMainOptional') {
3647
- var _exist = list.find(function (e) {
3648
- return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
3649
- });
3650
-
3651
- return _exist ? list : list.concat(error);
3652
- }
3653
-
3654
- return list.concat(error);
3655
- }, []);
3656
- };
3657
- var getErrors = function getErrors(errors) {
3658
- var errorList = Object.keys(errors).reduce(function (list, key) {
3659
- var errorValue = errors[key]; // changeGroups
3660
-
3661
- if (Array.isArray(errorValue)) {
3662
- var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
3663
- return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
3664
- }, []);
3665
- return list.concat.apply(list, _toConsumableArray(errorValues));
3666
- } // baseForecast
3667
-
3668
-
3669
- return list.concat(getErrorValues(errorValue, false, -1));
3670
- }, []);
3671
- 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;
3672
3506
  };
3673
3507
 
3674
3508
  /* *
@@ -3684,281 +3518,504 @@ var getErrors = function getErrors(errors) {
3684
3518
  * See the License for the specific language governing permissions and
3685
3519
  * limitations under the License.
3686
3520
  *
3687
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3688
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3521
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3522
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3689
3523
  * */
3690
3524
 
3691
- var IssuesButton = function IssuesButton(_ref) {
3692
- var _ref$errors = _ref.errors,
3693
- errors = _ref$errors === void 0 ? {} : _ref$errors,
3694
- _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
3695
- isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
3696
- _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
3697
- setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
3698
- return null;
3699
- } : _ref$setIsIssuesPaneO;
3700
- var errorList = filterDuplicateErrors(getErrors(errors));
3701
- var totalErrors = errorList.length;
3702
- var errorStatus = totalErrors > 0 ? 'error' : 'success';
3703
- var buttonColor = "geowebColors.functional.".concat(errorStatus);
3704
-
3705
- var toggleIssuesPane = function toggleIssuesPane(newPosition) {
3706
- 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
3707
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
+ };
3708
3563
 
3709
- var onClickButton = function onClickButton(event) {
3710
- var _a;
3711
-
3712
- var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
3713
- left = _event$currentTarget$.left,
3714
- top = _event$currentTarget$.top;
3564
+ var getDefaultValue = function getDefaultValue(fieldName, data) {
3565
+ if (!data) {
3566
+ return '';
3567
+ }
3715
3568
 
3716
- var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3717
- top: 0,
3718
- left: 0
3719
- };
3720
- var newPosition = {
3721
- left: left - parentOffset.left + 100,
3722
- top: top - parentOffset.top
3723
- };
3724
- toggleIssuesPane(newPosition);
3725
- };
3569
+ return getDeepProperty(fieldName.split('.'), data) || '';
3570
+ };
3726
3571
 
3727
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3728
- title: "View details"
3729
- }, /*#__PURE__*/React.createElement(Chip, {
3730
- "data-testid": "issuesButton",
3731
- className: "status-".concat(errorStatus),
3732
- size: "small",
3733
- label: getIssuesLabel(totalErrors),
3734
- onClick: onClickButton,
3735
- sx: {
3736
- width: '74px',
3737
- color: '#ffffff',
3738
- backgroundColor: buttonColor,
3739
- '&:hover': {
3740
- backgroundColor: buttonColor
3741
- },
3742
- '&:focus': {
3743
- backgroundColor: buttonColor
3744
- },
3745
- fontSize: 12
3746
- }
3747
- }));
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
+ ];
3748
3575
  };
3749
3576
 
3750
- var getPaneTitle = function getPaneTitle(sumOfErrors) {
3751
- switch (sumOfErrors) {
3752
- case 0:
3753
- 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"]);
3754
3594
 
3755
- case 1:
3756
- return 'There is an issue to address';
3595
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
3596
+ var fieldNames = getFieldNames(isChangeGroup, index);
3757
3597
 
3758
- default:
3759
- return 'There are a few issues to address';
3760
- }
3761
- };
3598
+ var _useFormContext = useFormContext(),
3599
+ getValues = _useFormContext.getValues,
3600
+ trigger = _useFormContext.trigger; // cross-field required validation
3762
3601
 
3763
- var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3764
- if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3765
- // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3766
- var fieldNumber = fieldNumberedValue + 1;
3767
- return "".concat(errorTitle, " ").concat(fieldNumber);
3768
- }
3769
3602
 
3770
- return errorTitle;
3771
- };
3772
- var getErrorMessage = function getErrorMessage(error, index) {
3773
- var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3774
- var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3775
- return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(error.message);
3776
- };
3777
- var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3778
- var useIssuesPane = function useIssuesPane() {
3779
- var _React$useState = React.useState(false),
3780
- _React$useState2 = _slicedToArray(_React$useState, 2),
3781
- isIssuesPaneOpen = _React$useState2[0],
3782
- 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];
3783
3608
 
3784
- var _React$useState3 = React.useState(null),
3785
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3786
- startPosition = _React$useState4[0],
3787
- 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
3788
3614
 
3789
- var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3790
- if (!startPosition) {
3791
- 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]));
3954
+ }
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
+ }
3966
+ },
3967
+ onBlur: function onBlur() {
3968
+ return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3792
3969
  }
3793
-
3794
- setIsIssuesPaneOpen(isOpen);
3795
- };
3796
-
3797
- var onCloseIssuesPane = function onCloseIssuesPane() {
3798
- return setIsIssuesPaneOpen(false);
3799
- };
3800
-
3801
- return {
3802
- isIssuesPaneOpen: isIssuesPaneOpen,
3803
- startPosition: startPosition,
3804
- onToggleIssuesPane: onToggleIssuesPane,
3805
- onCloseIssuesPane: onCloseIssuesPane
3806
- };
3807
- };
3808
-
3809
- var IssuesPane = function IssuesPane(_ref) {
3810
- var _ref$errorList = _ref.errorList,
3811
- errorList = _ref$errorList === void 0 ? [] : _ref$errorList,
3812
- isOpen = _ref.isOpen,
3813
- handleClose = _ref.handleClose,
3814
- _ref$startPosition = _ref.startPosition,
3815
- startPosition = _ref$startPosition === void 0 ? {
3816
- left: 20,
3817
- top: 50
3818
- } : _ref$startPosition;
3819
- var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3820
- return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3821
- startSize: {
3822
- width: '577px',
3823
- height: '200px'
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
+ }
3824
3981
  },
3825
- startPosition: startPosition,
3826
- minWidth: 300,
3827
- onClose: handleClose,
3828
- title: getPaneTitle(errorList.length),
3829
- headerSize: "xs",
3830
- isOpen: isOpen,
3831
- "data-testid": "moveable-issues-pane",
3832
- bounds: "parent"
3833
- }, /*#__PURE__*/React.createElement(Box, {
3834
- component: "div",
3835
- sx: {
3836
- marginTop: '16px',
3837
- marginLeft: '24px'
3982
+ onBlur: function onBlur() {
3983
+ return trigger(fieldNames.cloud4);
3838
3984
  }
3839
- }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3840
- component: "div",
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,
3841
4004
  sx: {
3842
- fontSize: '4rem'
4005
+ marginBottom: '16px'
3843
4006
  },
3844
- "data-testid": "zeroIssuesImage"
3845
- }, /*#__PURE__*/React.createElement(ThumbsUp, {
3846
- sx: {
3847
- height: '69px',
3848
- width: '58px'
3849
- }
3850
- })), errorList.length > 0 && errorList.map(function (error, index) {
3851
- return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3852
- , {
3853
- // eslint-disable-next-line react/no-array-index-key
3854
- key: "message-".concat(index),
3855
- variant: "body1",
3856
- "data-testid": "errorMessage"
3857
- }, getErrorMessage(error, index));
3858
- }))), rootElement);
3859
- };
3860
-
3861
- var TafModuleContext = /*#__PURE__*/React.createContext({
3862
- onValidateForm: null,
3863
- registerValidateForm: null,
3864
- tafAction: null,
3865
- setTafAction: null,
3866
- onPreventCloseView: null
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
+ })));
3867
4018
  });
3868
- var useTafModuleContext = function useTafModuleContext() {
3869
- return React.useContext(TafModuleContext);
3870
- };
3871
- var useTafModuleState = function useTafModuleState(_ref) {
3872
- var onPreventCloseView = _ref.onPreventCloseView;
3873
-
3874
- var _React$useState = React.useState(function () {
3875
- return new Promise(function () {
3876
- return true;
3877
- });
3878
- }),
3879
- _React$useState2 = _slicedToArray(_React$useState, 2),
3880
- onValidateForm = _React$useState2[0],
3881
- registerValidateForm = _React$useState2[1];
3882
-
3883
- var _React$useState3 = React.useState(),
3884
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3885
- tafAction = _React$useState4[0],
3886
- setTafAction = _React$useState4[1];
3887
-
3888
- var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3889
- registerValidateForm(function () {
3890
- return promiseToRegister;
3891
- });
3892
- };
3893
-
3894
- return {
3895
- onValidateForm: onValidateForm,
3896
- registerValidateForm: onRegisterValidateForm,
3897
- tafAction: tafAction,
3898
- setTafAction: setTafAction,
3899
- onPreventCloseView: onPreventCloseView
3900
- };
3901
- };
3902
- var TafModuleProvider = function TafModuleProvider(_ref2) {
3903
- var children = _ref2.children,
3904
- _ref2$onPreventCloseV = _ref2.onPreventCloseView,
3905
- onPreventCloseView = _ref2$onPreventCloseV === void 0 ? function () {} : _ref2$onPreventCloseV;
3906
- var contextState = useTafModuleState({
3907
- onPreventCloseView: onPreventCloseView
3908
- });
3909
- return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3910
- value: contextState
3911
- }, children);
3912
- };
3913
-
3914
- /* *
3915
- * Licensed under the Apache License, Version 2.0 (the "License");
3916
- * you may not use this file except in compliance with the License.
3917
- * You may obtain a copy of the License at
3918
- *
3919
- * http://www.apache.org/licenses/LICENSE-2.0
3920
- *
3921
- * Unless required by applicable law or agreed to in writing, software
3922
- * distributed under the License is distributed on an "AS IS" BASIS,
3923
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3924
- * See the License for the specific language governing permissions and
3925
- * limitations under the License.
3926
- *
3927
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3928
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3929
- * */
3930
- var styles = {
3931
- label: {
3932
- color: 'geowebColors.buttons.tertiary.default.color',
3933
- opacity: 1,
3934
- fontSize: '12px',
3935
- fontWeight: 500
3936
- }
3937
- };
3938
-
3939
- var SwitchButton = function SwitchButton(props) {
3940
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3941
- title: "Switch mode"
3942
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(FormLabel, {
3943
- sx: styles.label
3944
- }, "Viewer"), /*#__PURE__*/React.createElement(Switch, Object.assign({
3945
- "data-testid": "switchMode"
3946
- }, props)), /*#__PURE__*/React.createElement(FormLabel, {
3947
- sx: styles.label
3948
- }, "Editor")));
3949
- };
3950
-
3951
- var TafAvatar = function TafAvatar(_ref) {
3952
- var editor = _ref.editor,
3953
- _ref$tooltipPlacement = _ref.tooltipPlacement,
3954
- tooltipPlacement = _ref$tooltipPlacement === void 0 ? 'bottom' : _ref$tooltipPlacement;
3955
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3956
- title: "Editor: ".concat(editor),
3957
- placement: tooltipPlacement
3958
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Avatar, {
3959
- size: "small"
3960
- }, getInitials(editor))));
3961
- };
3962
4019
 
3963
4020
  var noop = function noop() {};
3964
4021
 
@@ -3990,7 +4047,10 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
3990
4047
  _ref$fetchNewTafList = _ref.fetchNewTafList,
3991
4048
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
3992
4049
  return null;
3993
- } : _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();
3994
4054
  var originalTaf = tafFromBackend.taf,
3995
4055
  editor = tafFromBackend.editor;
3996
4056
 
@@ -4019,7 +4079,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4019
4079
  formState = _useFormContext.formState,
4020
4080
  getValues = _useFormContext.getValues,
4021
4081
  setValue = _useFormContext.setValue,
4022
- reset = _useFormContext.reset; // added this ignore as the build is failing otherwise on: Type instantiation is excessively deep and possibly infinite.
4082
+ resetField = _useFormContext.resetField; // added this ignore as the build is failing otherwise on: Type instantiation is excessively deep and possibly infinite.
4023
4083
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4024
4084
  // @ts-ignore
4025
4085
 
@@ -4038,13 +4098,14 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4038
4098
  onStartDrag = _useDragOrder.onStartDrag,
4039
4099
  activeDraggingIndex = _useDragOrder.activeDraggingIndex;
4040
4100
 
4041
- var isFormDirty = formState.isDirty,
4101
+ var dirtyFields = formState.dirtyFields,
4042
4102
  errors = formState.errors;
4043
- usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4103
+ var isFormDirty$1 = isFormDirty(dirtyFields);
4104
+ usePreventBrowserClose(isFormDirty$1 && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4044
4105
 
4045
4106
  React__default.useEffect(function () {
4046
- onPreventCloseView(isFormDirty); // eslint-disable-next-line react-hooks/exhaustive-deps
4047
- }, [isFormDirty]);
4107
+ onPreventCloseView(isFormDirty$1); // eslint-disable-next-line react-hooks/exhaustive-deps
4108
+ }, [isFormDirty$1]);
4048
4109
  var hiddenInputFields = ['baseTime', 'issueDate', 'uuid', 'validDateStart', 'validDateEnd', 'status', 'previousId', 'previousValidDateStart', 'previousValidDateEnd', HIDDEN_INPUT_HELPER_IS_DRAFT];
4049
4110
 
4050
4111
  var onSubmit = function onSubmit(data) {
@@ -4056,7 +4117,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4056
4117
  return confirmDialog({
4057
4118
  title: getConfirmationDialogTitle(action),
4058
4119
  description: getConfirmationDialogContent(action, function () {
4059
- return isTafAmendedCorrectedChanged(isFormDirty, 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()));
4060
4122
  }),
4061
4123
  confirmLabel: getConfirmationDialogButtonLabel(action)
4062
4124
  });
@@ -4064,9 +4126,17 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4064
4126
 
4065
4127
  var resetFormValues = function resetFormValues(formData) {
4066
4128
  var keepDirty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4067
- reset(formData, {
4068
- keepDirty: keepDirty,
4069
- keepDirtyValues: false
4129
+ Object.keys(formData).forEach(function (key) {
4130
+ if (!keepDirty || key === 'changeGroups') {
4131
+ resetField(key, {
4132
+ keepDirty: keepDirty,
4133
+ defaultValue: formData[key]
4134
+ });
4135
+ }
4136
+
4137
+ setValue(key, formData[key], {
4138
+ shouldDirty: keepDirty
4139
+ });
4070
4140
  });
4071
4141
  };
4072
4142
 
@@ -4165,7 +4235,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4165
4235
  var onSwitchMode = function onSwitchMode(event) {
4166
4236
  var checked = event.target.checked;
4167
4237
 
4168
- if (!checked && isFormDirty) {
4238
+ if (!checked && isFormDirty$1) {
4169
4239
  confirmDialog({
4170
4240
  title: 'Whoops',
4171
4241
  description: 'Are you sure you want to switch to viewer mode? Your unsaved changes will be lost.',
@@ -4214,13 +4284,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4214
4284
 
4215
4285
  case 'CLEAR':
4216
4286
  showConfirmDialog(action).then(function () {
4217
- var emptiedForm = clearTafFormData(getValues()); // Trigger an invisible change to dirty the form
4218
- // This is needed to trigger the autosave on changing location/time
4219
-
4220
- var baseForecastFields = getFieldNames(false, -1);
4221
- setValue(baseForecastFields.wind, ' ', {
4222
- shouldDirty: true
4223
- });
4287
+ var emptiedForm = clearTafFormData(getValues());
4224
4288
  resetFormValues(emptiedForm, true);
4225
4289
  showSnackbar('TAF has been cleared');
4226
4290
  });
@@ -4251,14 +4315,37 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4251
4315
  resetFormState(null, true, convertTafValuesToObject(data));
4252
4316
  }
4253
4317
 
4254
- case 6:
4318
+ return _context3.abrupt("return", true);
4319
+
4320
+ case 7:
4255
4321
  case "end":
4256
4322
  return _context3.stop();
4257
4323
  }
4258
4324
  }
4259
4325
  }, _callee3);
4260
4326
  }));
4261
- })();
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
+ });
4262
4349
  break;
4263
4350
 
4264
4351
  default:
@@ -4444,7 +4531,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4444
4531
  editor: editor
4445
4532
  }))), /*#__PURE__*/React__default.createElement("form", {
4446
4533
  "data-testid": "taf-form",
4447
- onSubmit: handleSubmit(onSubmit)
4534
+ onSubmit: handleSubmit(onSubmit),
4535
+ ref: formRef
4448
4536
  }, /*#__PURE__*/React__default.createElement(TafFormRow, {
4449
4537
  disabled: isDisabled,
4450
4538
  onAddChangeGroupBelow: onAddRow,
@@ -4746,6 +4834,14 @@ var getNewTafLocationIndex = function getNewTafLocationIndex(tafLocations, previ
4746
4834
 
4747
4835
  return 0;
4748
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
+ };
4749
4845
 
4750
4846
  /* *
4751
4847
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -5261,7 +5357,9 @@ var TopTabs = function TopTabs(_ref) {
5261
5357
  } : _ref$tafFromBackend;
5262
5358
 
5263
5359
  var _useFormContext = useFormContext(),
5264
- isDirty = _useFormContext.formState.isDirty;
5360
+ dirtyFields = _useFormContext.formState.dirtyFields;
5361
+
5362
+ var isDirty = isFormDirty(dirtyFields);
5265
5363
 
5266
5364
  if (!tafFromBackend) {
5267
5365
  return null;
@@ -5329,8 +5427,9 @@ var LocationTabs = function LocationTabs(_ref) {
5329
5427
  timeSlot = _ref.timeSlot;
5330
5428
 
5331
5429
  var _useFormContext = useFormContext(),
5332
- isDirty = _useFormContext.formState.isDirty;
5430
+ dirtyFields = _useFormContext.formState.dirtyFields;
5333
5431
 
5432
+ var isDirty = isFormDirty(dirtyFields);
5334
5433
  return /*#__PURE__*/React.createElement(MenuList, {
5335
5434
  "data-testid": "location-tabs",
5336
5435
  sx: {
@@ -5581,7 +5680,10 @@ var TafPanel = function TafPanel(_ref) {
5581
5680
  _ref$fetchNewTafList = _ref.fetchNewTafList,
5582
5681
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
5583
5682
  return null;
5584
- } : _ref$fetchNewTafList;
5683
+ } : _ref$fetchNewTafList,
5684
+ _ref$previousTaf = _ref.previousTaf,
5685
+ previousTaf = _ref$previousTaf === void 0 ? null : _ref$previousTaf,
5686
+ tafAction = _ref.tafAction;
5585
5687
  var severity = isWarning(error) ? 'warning' : 'error';
5586
5688
 
5587
5689
  var onTafAction = function onTafAction(action, taf) {
@@ -5631,7 +5733,7 @@ var TafPanel = function TafPanel(_ref) {
5631
5733
  index: index,
5632
5734
  "data-testid": "taf-panel".concat(activeTafIndex === index ? '-active' : '')
5633
5735
  }, /*#__PURE__*/React__default.createElement(TafHeader, {
5634
- title: getTafStatusLabel(tafFromBackend.taf.status),
5736
+ title: getTafStatusLabel(tafFromBackend.taf.status, tafAction, isFormDisabled),
5635
5737
  sx: {
5636
5738
  marginBottom: '4px'
5637
5739
  }
@@ -5664,7 +5766,8 @@ var TafPanel = function TafPanel(_ref) {
5664
5766
  isDisabled: isFormDisabled,
5665
5767
  setIsDisabled: setIsFormDisabled,
5666
5768
  onSwitchEditor: patchTaf,
5667
- fetchNewTafList: fetchNewTafList
5769
+ fetchNewTafList: fetchNewTafList,
5770
+ previousTaf: previousTaf
5668
5771
  })));
5669
5772
  };
5670
5773
 
@@ -5775,7 +5878,7 @@ var getSnackbarMessage = function getSnackbarMessage(tafFromFrontEnd) {
5775
5878
  return 'Saved as draft';
5776
5879
 
5777
5880
  case 'DRAFT_AMENDED':
5778
- return 'Saved as draft amended';
5881
+ return 'Saved as draft amendment';
5779
5882
 
5780
5883
  case 'DRAFT_CORRECTED':
5781
5884
  return 'Saved as draft correction';
@@ -5816,7 +5919,8 @@ var TafLayout = function TafLayout(_ref2) {
5816
5919
  isIssuesPaneOpen = _useIssuesPane.isIssuesPaneOpen,
5817
5920
  onToggleIssuesPane = _useIssuesPane.onToggleIssuesPane,
5818
5921
  onCloseIssuesPane = _useIssuesPane.onCloseIssuesPane,
5819
- startPosition = _useIssuesPane.startPosition;
5922
+ startPosition = _useIssuesPane.startPosition,
5923
+ onUserHasDragged = _useIssuesPane.onUserHasDragged;
5820
5924
 
5821
5925
  var _usePostTafRequest = usePostTafRequest(api.postTaf),
5822
5926
  isLoading = _usePostTafRequest.isLoading,
@@ -6140,7 +6244,9 @@ var TafLayout = function TafLayout(_ref2) {
6140
6244
  patchTaf: patchTaf,
6141
6245
  isLoading: isLoading,
6142
6246
  error: error,
6143
- fetchNewTafList: onUpdateTaf
6247
+ fetchNewTafList: onUpdateTaf,
6248
+ previousTaf: getPreviousTaf(tafList, tafFromBackend),
6249
+ tafAction: tafAction
6144
6250
  });
6145
6251
  }))), /*#__PURE__*/React__default.createElement(Grid, {
6146
6252
  item: true,
@@ -6163,7 +6269,8 @@ var TafLayout = function TafLayout(_ref2) {
6163
6269
  })))))), /*#__PURE__*/React__default.createElement(IssuesPaneWrapper, {
6164
6270
  handleClose: onCloseIssuesPane,
6165
6271
  isOpen: isIssuesPaneOpen,
6166
- startPosition: startPosition
6272
+ startPosition: startPosition,
6273
+ onUserHasDragged: onUserHasDragged
6167
6274
  }));
6168
6275
  };
6169
6276
 
@@ -7180,15 +7287,21 @@ var fakeDraftAmendmentTaf = {
7180
7287
  }
7181
7288
  };
7182
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
+
7183
7295
  ({
7184
7296
  creationDate: "2022-01-06T14:00:00Z",
7185
7297
  canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7186
7298
  editor: null,
7187
- taf: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf), {
7299
+ taf: Object.assign(Object.assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7188
7300
  location: 'EHRD',
7189
7301
  baseTime: "2022-01-06T12:00:00Z",
7190
7302
  validDateStart: "2022-01-06T14:00:00Z",
7191
7303
  validDateEnd: "2022-01-07T18:00:00Z",
7304
+ previousId: "previousIdOfPreviousTAF",
7192
7305
  previousValidDateStart: "2022-01-06T12:00:00Z",
7193
7306
  previousValidDateEnd: "2022-01-07T18:00:00Z",
7194
7307
  baseForecast: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
@@ -7196,8 +7309,32 @@ var fakeDraftAmendmentTaf = {
7196
7309
  start: "2022-01-06T14:00:00Z",
7197
7310
  end: "2022-01-07T18:00:00Z"
7198
7311
  }
7199
- }),
7200
- 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
+ })
7201
7338
  })
7202
7339
  });
7203
7340
  var fakeAmendmentTaf = {