@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.umd.js CHANGED
@@ -135,6 +135,158 @@
135
135
  return to.concat(ar || Array.prototype.slice.call(from));
136
136
  }
137
137
 
138
+ /* *
139
+ * Licensed under the Apache License, Version 2.0 (the "License");
140
+ * you may not use this file except in compliance with the License.
141
+ * You may obtain a copy of the License at
142
+ *
143
+ * http://www.apache.org/licenses/LICENSE-2.0
144
+ *
145
+ * Unless required by applicable law or agreed to in writing, software
146
+ * distributed under the License is distributed on an "AS IS" BASIS,
147
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148
+ * See the License for the specific language governing permissions and
149
+ * limitations under the License.
150
+ *
151
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
152
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
153
+ * */
154
+ var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
155
+ switch (tafAction) {
156
+ case 'AMEND':
157
+ case 'DRAFT_AMEND':
158
+ return 'DRAFT_AMEND';
159
+
160
+ case 'CORRECT':
161
+ case 'DRAFT_CORRECT':
162
+ return 'DRAFT_CORRECT';
163
+
164
+ default:
165
+ return 'DRAFT';
166
+ }
167
+ };
168
+
169
+ var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
170
+ switch (tafAction) {
171
+ case 'AMEND':
172
+ case 'DRAFT_AMEND':
173
+ return 'AMEND';
174
+
175
+ case 'CORRECT':
176
+ case 'DRAFT_CORRECT':
177
+ return 'CORRECT';
178
+
179
+ default:
180
+ return 'PUBLISH';
181
+ }
182
+ };
183
+
184
+ var buttonsStyle = {
185
+ button: {
186
+ minWidth: {
187
+ xs: '56px',
188
+ sm: '64px'
189
+ },
190
+ width: {
191
+ xs: '56px',
192
+ sm: '64px'
193
+ },
194
+ marginLeft: {
195
+ xs: 0.5,
196
+ sm: 1
197
+ },
198
+ marginTop: 3,
199
+ marginBottom: 3
200
+ }
201
+ };
202
+
203
+ var ViewModeButtons = function ViewModeButtons(_a) {
204
+ var canBe = _a.canBe,
205
+ onTafViewModeButtonPress = _a.onTafViewModeButtonPress;
206
+ return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
207
+ "data-testid": "canceltaf",
208
+ variant: "tertiary",
209
+ onClick: function onClick() {
210
+ return onTafViewModeButtonPress('CANCEL');
211
+ }
212
+ }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
213
+ "data-testid": "correcttaf",
214
+ variant: "tertiary",
215
+ onClick: function onClick() {
216
+ return onTafViewModeButtonPress('CORRECT');
217
+ }
218
+ }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
219
+ "data-testid": "amendtaf",
220
+ variant: "tertiary",
221
+ onClick: function onClick() {
222
+ return onTafViewModeButtonPress('AMEND');
223
+ }
224
+ }, "Amend"));
225
+ };
226
+
227
+ var TafFormButtons = function TafFormButtons(_a) {
228
+ var _b = _a.isFormDisabled,
229
+ isFormDisabled = _b === void 0 ? false : _b,
230
+ tafAction = _a.tafAction,
231
+ _c = _a.canBe,
232
+ canBe = _c === void 0 ? [] : _c,
233
+ onTafEditModeButtonPress = _a.onTafEditModeButtonPress,
234
+ onTafViewModeButtonPress = _a.onTafViewModeButtonPress;
235
+ return /*#__PURE__*/React__default["default"].createElement(material.Grid, {
236
+ container: true,
237
+ justifyContent: "flex-end",
238
+ sx: buttonsStyle,
239
+ columns: 24
240
+ }, /*#__PURE__*/React__default["default"].createElement(material.Grid, {
241
+ item: true,
242
+ container: true,
243
+ justifyContent: "flex-end",
244
+ columns: 24,
245
+ xs: 24,
246
+ sm: 23
247
+ }, isFormDisabled ? /*#__PURE__*/React__default["default"].createElement(ViewModeButtons, {
248
+ canBe: canBe,
249
+ onTafViewModeButtonPress: onTafViewModeButtonPress
250
+ }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Button, {
251
+ "data-testid": "cleartaf",
252
+ variant: "tertiary",
253
+ onClick: function onClick() {
254
+ // Simply discard the changes and close the dialog.
255
+ onTafEditModeButtonPress('CLEAR');
256
+ }
257
+ }, "Clear"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
258
+ "data-testid": "savedrafttaf",
259
+ variant: "tertiary",
260
+ onClick: function onClick() {
261
+ /* Save the TAF as draft:
262
+ if action NEW or DRAFT - new status will be DRAFT -- default
263
+ if action AMEND - new status will be DRAFT_AMENDED
264
+ if action CORRECT - new status will be DRAFT_CORRECTED
265
+ if action DRAFT_AMEND - new status will be DRAFT_AMENDED
266
+ if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
267
+ */
268
+ onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
269
+ }
270
+ }, "Save"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
271
+ "data-testid": "publishtaf",
272
+ variant: "tertiary",
273
+ onClick: function onClick() {
274
+ /* Publish the TAF:
275
+ if action NEW or DRAFT - new status will be PUBLISHED -- default
276
+ if action AMEND - new status will be AMENDED
277
+ if action CORRECT - new status will be CORRECTED
278
+ if action DRAFT_AMEND - new status will be AMENDED
279
+ if action DRAFT_CORRECT - new status will be CORRECTED
280
+ */
281
+ onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
282
+ }
283
+ }, "Publish"))), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
284
+ item: true,
285
+ columns: 24,
286
+ sm: 1
287
+ }));
288
+ };
289
+
138
290
  function _typeof(obj) {
139
291
  "@babel/helpers - typeof";
140
292
 
@@ -453,8 +605,8 @@
453
605
  * See the License for the specific language governing permissions and
454
606
  * limitations under the License.
455
607
  *
456
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
457
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
608
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
609
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
458
610
  * */
459
611
 
460
612
  var prependZeroes = function prependZeroes(value, totalDigits) {
@@ -463,6 +615,9 @@
463
615
  return "0" + newVal;
464
616
  }, valueAsString);
465
617
  };
618
+ var getFieldValue = function getFieldValue(fieldValue) {
619
+ return fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.trim().toUpperCase();
620
+ };
466
621
 
467
622
  var config$1 = [{
468
623
  key: 'range',
@@ -2433,7 +2588,8 @@
2433
2588
  }; // Check if the amended/corrected TAF has been changed. Only compare the fields users are able to fill in
2434
2589
  // (i.e. exclude baseforecast valid time as that gets updated when doing an amendment automatically outside of the users influence)
2435
2590
 
2436
- var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormDirty, originalTaf, currentTaf) {
2591
+ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(originalTaf, currentTaf) {
2592
+ if (originalTaf === null || currentTaf === null) return false;
2437
2593
  var originalBaseF = originalTaf.baseForecast,
2438
2594
  originalChG = originalTaf.changeGroups;
2439
2595
  var currentBaseF = currentTaf.baseForecast,
@@ -2445,7 +2601,7 @@
2445
2601
  currentBaseF.valid;
2446
2602
  var currentNoValid = __rest(currentBaseF, ["valid"]);
2447
2603
 
2448
- return isFormDirty && (!lodash.isEqual(originalNoValid, currentNoValid) || !lodash.isEqual(originalChG, currentChG));
2604
+ return !lodash.isEqual(originalNoValid, currentNoValid) || !lodash.isEqual(originalChG, currentChG);
2449
2605
  };
2450
2606
  var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
2451
2607
  switch (action) {
@@ -2497,13 +2653,30 @@
2497
2653
  change: '',
2498
2654
  probability: ''
2499
2655
  };
2500
- var getTafStatusLabel = function getTafStatusLabel(status) {
2656
+ var getTafStatusLabel = function getTafStatusLabel(status, action, isFormDisabled) {
2657
+ // See if we need to base status label on action if form is not disabled and action passed
2658
+ var baseOnAction = isFormDisabled !== undefined && !isFormDisabled && action;
2659
+
2660
+ if (baseOnAction && action === 'AMEND' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2661
+ return 'new amendment';
2662
+ }
2663
+
2664
+ if (baseOnAction && action === 'CORRECT' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2665
+ return 'new correction';
2666
+ }
2667
+
2501
2668
  switch (status) {
2502
2669
  case 'DRAFT_AMENDED':
2503
- return 'draft amended';
2670
+ return 'draft amendment';
2504
2671
 
2505
2672
  case 'DRAFT_CORRECTED':
2506
- return 'draft corrected';
2673
+ return 'draft correction';
2674
+
2675
+ case 'AMENDED':
2676
+ return 'published amendment';
2677
+
2678
+ case 'CORRECTED':
2679
+ return 'published correction';
2507
2680
 
2508
2681
  default:
2509
2682
  return status.toLocaleLowerCase();
@@ -2645,189 +2818,59 @@
2645
2818
  return 'NEW';
2646
2819
  }
2647
2820
  };
2821
+ var isFormDirty = function isFormDirty(dirtyFields) {
2822
+ return Object.keys(dirtyFields).length > 0;
2823
+ };
2824
+ var getFormRowPosition = function getFormRowPosition(formRow) {
2825
+ var _a = formRow.getBoundingClientRect(),
2826
+ top = _a.top,
2827
+ left = _a.left,
2828
+ height = _a.height;
2648
2829
 
2649
- var textFieldStyle = function textFieldStyle(theme) {
2830
+ var newTop = top + height;
2650
2831
  return {
2651
- // input
2652
- marginRight: '2px',
2653
- marginBottom: '4px',
2654
- width: 56,
2655
- height: 46,
2656
- input: {
2657
- textAlign: 'center',
2658
- fontSize: 10,
2659
- fontWeight: 500,
2660
- paddingLeft: 0,
2661
- paddingRight: 0,
2662
- '&.Mui-disabled': {
2663
- color: 'geowebColors.typographyAndIcons.text',
2664
- WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
2665
- },
2666
- // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
2667
- '&:-webkit-autofill': {
2668
- WebkitTransitionDelay: '86400s' // 1 day delay
2832
+ top: newTop,
2833
+ left: left
2834
+ };
2835
+ };
2669
2836
 
2670
- }
2671
- },
2672
- label: {
2673
- transformOrigin: 'center top',
2674
- right: 0,
2675
- textAlign: 'center',
2676
- fontSize: '10px',
2677
- '&.Mui-disabled': {
2678
- color: 'geowebColors.captions.captionStatus.rgba'
2679
- },
2680
- whiteSpace: 'nowrap',
2681
- maxWidth: '100%',
2682
- transform: 'translate(0px, 16px) scale(1)'
2683
- },
2684
- // shrink
2685
- ' .MuiInputLabel-shrink': {
2686
- transform: 'translate(2px, 10px) scale(0.75) !important',
2687
- letterSpacing: '0.33px',
2688
- textAlign: 'left'
2689
- },
2690
- // root
2691
- '&': {
2692
- '.Mui-error.MuiFilledInput-root': {
2693
- backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
2837
+ /* *
2838
+ * Licensed under the Apache License, Version 2.0 (the "License");
2839
+ * you may not use this file except in compliance with the License.
2840
+ * You may obtain a copy of the License at
2841
+ *
2842
+ * http://www.apache.org/licenses/LICENSE-2.0
2843
+ *
2844
+ * Unless required by applicable law or agreed to in writing, software
2845
+ * distributed under the License is distributed on an "AS IS" BASIS,
2846
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2847
+ * See the License for the specific language governing permissions and
2848
+ * limitations under the License.
2849
+ *
2850
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2851
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
2852
+ * */
2853
+
2854
+ var DragHandle = function DragHandle(_a) {
2855
+ var _b = _a.isSorting,
2856
+ isSorting = _b === void 0 ? false : _b,
2857
+ _c = _a.isDisabled,
2858
+ isDisabled = _c === void 0 ? false : _c,
2859
+ index = _a.index;
2860
+ return /*#__PURE__*/React__default["default"].createElement(material.IconButton, {
2861
+ className: "handle",
2862
+ "data-testid": "dragHandle-" + index,
2863
+ disableRipple: true,
2864
+ disabled: isDisabled,
2865
+ size: "large",
2866
+ sx: {
2867
+ backgroundColor: 'transparent',
2868
+ '&:hover': {
2869
+ backgroundColor: 'transparent'
2694
2870
  },
2695
- '.Mui-disabled:before': {
2696
- borderColor: 'transparent'
2697
- }
2871
+ cursor: isSorting ? 'grabbing' : 'grab'
2698
2872
  }
2699
- };
2700
- };
2701
-
2702
- var getTafErrors = function getTafErrors(name, errors) {
2703
- var nameAsArray = name.split('.');
2704
-
2705
- if (nameAsArray[0].includes('changeGroups')) {
2706
- if (errors.changeGroups) {
2707
- var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
2708
- var restArray = nameAsArray.slice(1);
2709
- return formFields.getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
2710
- } // No changegroup errors
2711
-
2712
-
2713
- return null;
2714
- }
2715
-
2716
- return formFields.getDeepProperty(nameAsArray, errors);
2717
- };
2718
-
2719
- var getDisplayValue = function getDisplayValue(value, disabled) {
2720
- return disabled && !value ? '-' : value;
2721
- };
2722
- var BaseTextField = /*#__PURE__*/React__default["default"].memo(function (props) {
2723
- return /*#__PURE__*/React__default["default"].createElement(material.TextField, __assign({
2724
- type: "text",
2725
- variant: "filled",
2726
- sx: textFieldStyle
2727
- }, props));
2728
- }, function (prevProps, nextProps) {
2729
- return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
2730
- });
2731
-
2732
- var TafFormTextField = function TafFormTextField(_a) {
2733
- var label = _a.label,
2734
- _b = _a.disabled,
2735
- disabled = _b === void 0 ? false : _b,
2736
- _c = _a.name,
2737
- name = _c === void 0 ? '' : _c,
2738
- _d = _a.onChange,
2739
- onChange = _d === void 0 ? function () {} : _d,
2740
- _e = _a.onBlur,
2741
- onBlur = _e === void 0 ? function () {} : _e,
2742
- _f = _a.defaultValue,
2743
- defaultValue = _f === void 0 ? '' : _f,
2744
- _g = _a.formatter,
2745
- formatter = _g === void 0 ? null : _g,
2746
- rules = _a.rules,
2747
- _h = _a.autoComplete,
2748
- autoComplete = _h === void 0 ? [] : _h,
2749
- _j = _a.autoFocus,
2750
- autoFocus = _j === void 0 ? false : _j;
2751
-
2752
- var _k = reactHookForm.useFormContext(),
2753
- control = _k.control,
2754
- setValue = _k.setValue,
2755
- errors = _k.formState.errors;
2756
-
2757
- var fieldErrors = getTafErrors(name, errors);
2758
-
2759
- var _l = __read(React__default["default"].useState(null), 2),
2760
- maxLength = _l[0],
2761
- setMaxLength = _l[1];
2762
-
2763
- var onKeyDown = React__default["default"].useCallback(function (event) {
2764
- var target = event.target;
2765
- var currentValue = target.value,
2766
- selectionStart = target.selectionStart,
2767
- selectionEnd = target.selectionEnd;
2768
- var textSelection = currentValue.substring(selectionStart, selectionEnd);
2769
-
2770
- if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
2771
- var pressedKey_1 = event.key.toString().toUpperCase();
2772
- var foundValue = autoComplete.find(function (el) {
2773
- return el.key === pressedKey_1;
2774
- }) || null;
2775
-
2776
- if (foundValue) {
2777
- setValue(name, foundValue.value);
2778
- setMaxLength(foundValue.value.length);
2779
- event.preventDefault();
2780
- }
2781
- }
2782
- }, [name, autoComplete, setValue]);
2783
- var onChangeField = React__default["default"].useCallback(function (event, callback) {
2784
- var valueUppercase = event.currentTarget.value.toUpperCase();
2785
-
2786
- if (autoComplete) {
2787
- var exist = autoComplete.find(function (e) {
2788
- return e.value === valueUppercase;
2789
- });
2790
- var newMaxLength = exist ? valueUppercase.length : null;
2791
- setMaxLength(newMaxLength);
2792
- }
2793
-
2794
- callback(valueUppercase);
2795
- onChange(valueUppercase);
2796
- }, [onChange, autoComplete]);
2797
- var onBlurField = React__default["default"].useCallback(function (callback) {
2798
- callback();
2799
- onBlur();
2800
- }, [onBlur]);
2801
- var hasError = !!fieldErrors;
2802
- return /*#__PURE__*/React__default["default"].createElement(reactHookForm.Controller, {
2803
- render: function render(_a) {
2804
- var field = _a.field;
2805
- var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
2806
- return /*#__PURE__*/React__default["default"].createElement(BaseTextField, {
2807
- label: label,
2808
- disabled: disabled,
2809
- name: name,
2810
- value: displayValue,
2811
- inputRef: field.ref,
2812
- onChange: function onChange(e) {
2813
- return onChangeField(e, field.onChange);
2814
- },
2815
- onKeyDown: onKeyDown,
2816
- error: hasError,
2817
- onBlur: function onBlur() {
2818
- return onBlurField(field.onBlur);
2819
- },
2820
- inputProps: {
2821
- maxLength: maxLength
2822
- },
2823
- autoFocus: autoFocus
2824
- });
2825
- },
2826
- name: name,
2827
- control: control,
2828
- defaultValue: defaultValue,
2829
- rules: rules
2830
- });
2873
+ }, /*#__PURE__*/React__default["default"].createElement(theme.DragHandle, null));
2831
2874
  };
2832
2875
 
2833
2876
  /* *
@@ -2843,27 +2886,82 @@
2843
2886
  * See the License for the specific language governing permissions and
2844
2887
  * limitations under the License.
2845
2888
  *
2846
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2847
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2889
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2890
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
2848
2891
  * */
2849
- // messages
2850
- var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
2851
- var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
2892
+ var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
2893
+ return __assign(__assign({}, error), {
2894
+ isChangeGroup: isChangeGroup,
2895
+ rowIndex: rowIndex
2896
+ });
2897
+ };
2898
+ var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
2899
+ switch (sumOfErrors) {
2900
+ case 0:
2901
+ return '0 issues';
2852
2902
 
2853
- var validateChangeField = function validateChangeField(value) {
2854
- var trimmedValue = value.trim();
2855
- var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
2856
- return isValid ? true : invalidChangeMessage;
2903
+ case 1:
2904
+ return '1 issue';
2905
+
2906
+ default:
2907
+ return sumOfErrors + " issues";
2908
+ }
2857
2909
  };
2858
- var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
2859
- var trimmedProbValue = valueProb.trim();
2860
- var trimmedValue = value.trim();
2910
+ var getErrorValues = function getErrorValues(fieldErrors, isChangeGroup, rowIndex) {
2911
+ if (isChangeGroup === void 0) {
2912
+ isChangeGroup = false;
2913
+ }
2861
2914
 
2862
- if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
2863
- return invalidChangeProbCombinationMessage;
2915
+ if (rowIndex === void 0) {
2916
+ rowIndex = -1;
2864
2917
  }
2865
2918
 
2866
- return true;
2919
+ if (!fieldErrors) return [];
2920
+ return Object.keys(fieldErrors).reduce(function (list, key) {
2921
+ var error = __assign({}, fieldErrors[key]);
2922
+
2923
+ if (error.ref) {
2924
+ return list.concat(getCustomError(error, isChangeGroup, rowIndex));
2925
+ }
2926
+
2927
+ return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
2928
+ }, []);
2929
+ };
2930
+ var filterDuplicateErrors = function filterDuplicateErrors(errors) {
2931
+ return errors.reduce(function (list, error) {
2932
+ // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
2933
+ if (error.type === 'validateRequiredSub') {
2934
+ var exist = list.find(function (e) {
2935
+ return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
2936
+ });
2937
+ return exist ? list : list.concat(error);
2938
+ }
2939
+
2940
+ if (error.type === 'validateRequiredMainOptional') {
2941
+ var exist = list.find(function (e) {
2942
+ return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
2943
+ });
2944
+ return exist ? list : list.concat(error);
2945
+ }
2946
+
2947
+ return list.concat(error);
2948
+ }, []);
2949
+ };
2950
+ var getErrors = function getErrors(errors) {
2951
+ var errorList = Object.keys(errors).reduce(function (list, key) {
2952
+ var errorValue = errors[key]; // changeGroups
2953
+
2954
+ if (Array.isArray(errorValue)) {
2955
+ var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
2956
+ return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
2957
+ }, []);
2958
+ return list.concat.apply(list, __spreadArray([], __read(errorValues)));
2959
+ } // baseForecast
2960
+
2961
+
2962
+ return list.concat(getErrorValues(errorValue, false, -1));
2963
+ }, []);
2964
+ return errorList;
2867
2965
  };
2868
2966
 
2869
2967
  /* *
@@ -2882,672 +2980,475 @@
2882
2980
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2883
2981
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
2884
2982
  * */
2885
- // messages
2886
- var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
2887
2983
 
2888
- var validateProbabilityField = function validateProbabilityField(value) {
2889
- var trimmedValue = value.trim();
2890
- var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
2891
- return isValid ? true : invalidProbabilityMessage;
2892
- };
2984
+ var IssuesButton = function IssuesButton(_a) {
2985
+ var _b = _a.errors,
2986
+ errors = _b === void 0 ? {} : _b,
2987
+ _c = _a.isIssuesPaneOpen,
2988
+ isIssuesPaneOpen = _c === void 0 ? false : _c,
2989
+ _d = _a.setIsIssuesPaneOpen,
2990
+ setIsIssuesPaneOpen = _d === void 0 ? function () {
2991
+ return null;
2992
+ } : _d;
2993
+ var errorList = filterDuplicateErrors(getErrors(errors));
2994
+ var totalErrors = errorList.length;
2995
+ var errorStatus = totalErrors > 0 ? 'error' : 'success';
2996
+ var buttonColor = "geowebColors.functional." + errorStatus;
2893
2997
 
2894
- /* *
2895
- * Licensed under the Apache License, Version 2.0 (the "License");
2896
- * you may not use this file except in compliance with the License.
2897
- * You may obtain a copy of the License at
2898
- *
2899
- * http://www.apache.org/licenses/LICENSE-2.0
2900
- *
2901
- * Unless required by applicable law or agreed to in writing, software
2902
- * distributed under the License is distributed on an "AS IS" BASIS,
2903
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2904
- * See the License for the specific language governing permissions and
2905
- * limitations under the License.
2906
- *
2907
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2908
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
2909
- * */
2998
+ var toggleIssuesPane = function toggleIssuesPane(newPosition) {
2999
+ return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
3000
+ };
2910
3001
 
2911
- var TafFormOptionsButton = function TafFormOptionsButton(_a) {
2912
- var isChangeGroup = _a.isChangeGroup,
2913
- addChangeGroupBelow = _a.addChangeGroupBelow,
2914
- addChangeGroupAbove = _a.addChangeGroupAbove,
2915
- removeChangeGroup = _a.removeChangeGroup,
2916
- clearRow = _a.clearRow,
2917
- index = _a.index;
2918
- var insertAbove = {
2919
- text: 'Insert 1 row above',
2920
- icon: /*#__PURE__*/React__namespace.createElement(theme.Add, null),
2921
- action: addChangeGroupAbove
2922
- };
2923
- var insertBelow = {
2924
- text: 'Insert 1 row below',
2925
- icon: /*#__PURE__*/React__namespace.createElement(theme.Add, null),
2926
- action: addChangeGroupBelow
2927
- };
2928
- var deleteRow = {
2929
- text: 'Delete row',
2930
- icon: /*#__PURE__*/React__namespace.createElement(theme.Delete, null),
2931
- action: removeChangeGroup
2932
- };
2933
- var clear = {
2934
- text: 'Clear row',
2935
- icon: /*#__PURE__*/React__namespace.createElement(theme.Close, null),
2936
- action: clearRow
2937
- };
2938
- var menuItemsBaseForecast = [insertBelow, clear];
2939
- var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
2940
- return /*#__PURE__*/React__namespace.createElement(shared.ToggleMenu, {
2941
- buttonTestId: "tafFormOptions[" + index + "]",
2942
- buttonSx: {
2943
- marginTop: '10px',
2944
- marginLeft: '4px'
2945
- },
2946
- menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
2947
- });
2948
- };
3002
+ var onClickButton = function onClickButton(event) {
3003
+ var _a;
2949
3004
 
2950
- var getDefaultValue = function getDefaultValue(fieldName, data) {
2951
- if (!data) {
2952
- return '';
2953
- }
3005
+ var _b = event.currentTarget.getBoundingClientRect(),
3006
+ left = _b.left,
3007
+ top = _b.top;
2954
3008
 
2955
- return formFields.getDeepProperty(fieldName.split('.'), data) || '';
2956
- };
3009
+ var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3010
+ top: 0,
3011
+ left: 0
3012
+ };
3013
+ var newPosition = {
3014
+ left: left - parentOffset.left + 100,
3015
+ top: top - parentOffset.top
3016
+ };
3017
+ toggleIssuesPane(newPosition);
3018
+ };
2957
3019
 
2958
- var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
2959
- return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
2960
- ];
3020
+ return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3021
+ title: "View details"
3022
+ }, /*#__PURE__*/React__namespace.createElement(material.Chip, {
3023
+ "data-testid": "issuesButton",
3024
+ className: "status-" + errorStatus,
3025
+ size: "small",
3026
+ label: getIssuesLabel(totalErrors),
3027
+ onClick: onClickButton,
3028
+ sx: {
3029
+ width: '74px',
3030
+ color: '#ffffff',
3031
+ backgroundColor: buttonColor,
3032
+ '&:hover': {
3033
+ backgroundColor: buttonColor
3034
+ },
3035
+ '&:focus': {
3036
+ backgroundColor: buttonColor
3037
+ },
3038
+ fontSize: 12
3039
+ }
3040
+ }));
2961
3041
  };
2962
3042
 
2963
- var TafFormRow = /*#__PURE__*/React__default["default"].forwardRef(function (_a, ref) {
2964
- var isNotRequiredForAction = _a.isNotRequiredForAction,
2965
- _b = _a.isChangeGroup,
2966
- isChangeGroup = _b === void 0 ? false : _b,
2967
- _c = _a.disabled,
2968
- disabled = _c === void 0 ? false : _c,
2969
- _d = _a.index,
2970
- index = _d === void 0 ? -1 : _d,
2971
- onRemoveChangeGroup = _a.onRemoveChangeGroup,
2972
- _e = _a.field,
2973
- field = _e === void 0 ? null : _e,
2974
- _f = _a.dragHandle,
2975
- dragHandle = _f === void 0 ? null : _f,
2976
- onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
2977
- onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
2978
- onClearRow = _a.onClearRow,
2979
- props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
2980
-
2981
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[" + index + "]";
2982
- var fieldNames = getFieldNames(isChangeGroup, index);
2983
-
2984
- var _g = reactHookForm.useFormContext(),
2985
- getValues = _g.getValues,
2986
- trigger = _g.trigger; // cross-field required validation
2987
-
2988
-
2989
- var _h = __read(getRequiredCrossFields(fieldNames), 3),
2990
- mainFields = _h[0],
2991
- mainOptionalFields = _h[1],
2992
- subFields = _h[2];
2993
-
2994
- var hasFieldsValue = function hasFieldsValue(fields) {
2995
- return fields.map(getValues).find(function (field) {
2996
- return !!field;
2997
- });
2998
- }; // Used to validate the required field for change groups: Valid
2999
-
3000
-
3001
- var validateRequiredMain = function validateRequiredMain(value) {
3002
- return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3003
- }; // Used to ensure either probability or change is entered, or both
3004
-
3005
-
3006
- var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3007
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3008
- }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
3009
-
3010
-
3011
- var validateRequiredSub = function validateRequiredSub(value) {
3012
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3013
- }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3043
+ var getPaneTitle = function getPaneTitle(sumOfErrors) {
3044
+ switch (sumOfErrors) {
3045
+ case 0:
3046
+ return 'Looks good';
3014
3047
 
3048
+ case 1:
3049
+ return 'There is an issue to address';
3015
3050
 
3016
- var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3017
- var changeField = getValues(namePrefix + ".change");
3018
- var visibilityField = getValues(namePrefix + ".visibility");
3019
- var isFM = changeField && changeField.trim() === 'FM';
3020
- var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3051
+ default:
3052
+ return 'There are a few issues to address';
3053
+ }
3054
+ };
3021
3055
 
3022
- if (isNotRequiredForAction(value) !== true && !value.length) {
3023
- if (isChangeGroup && isFM || !isChangeGroup) {
3024
- // exception for CavOK
3025
- if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3026
- return true;
3027
- } // exception for visibility > 5000
3056
+ var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3057
+ if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3058
+ // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3059
+ var fieldNumber = fieldNumberedValue + 1;
3060
+ return errorTitle + " " + fieldNumber;
3061
+ }
3028
3062
 
3063
+ return errorTitle;
3064
+ };
3065
+ var getErrorMessage = function getErrorMessage(error, index) {
3066
+ var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3067
+ var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3068
+ return index + 1 + ". " + fieldErrorTitle + ": " + error.message;
3069
+ };
3070
+ var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3071
+ var useIssuesPane = function useIssuesPane() {
3072
+ var _a = __read(React__namespace.useState(false), 2),
3073
+ isIssuesPaneOpen = _a[0],
3074
+ setIsIssuesPaneOpen = _a[1];
3029
3075
 
3030
- if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3031
- return true;
3032
- }
3076
+ var _b = __read(React__namespace.useState(null), 2),
3077
+ startPosition = _b[0],
3078
+ setStartPosition = _b[1];
3033
3079
 
3034
- return fieldName + " is required";
3035
- }
3036
- }
3080
+ var _c = __read(React__namespace.useState(false), 2),
3081
+ hasUserDragged = _c[0],
3082
+ setHasUserDragged = _c[1];
3037
3083
 
3038
- return true;
3084
+ var onUserHasDragged = function onUserHasDragged() {
3085
+ return setHasUserDragged(true);
3039
3086
  };
3040
3087
 
3041
- var validatePreviousRow = React__default["default"].useCallback(function () {
3042
- if (isChangeGroup && index > 0) {
3043
- var _a = getValues(),
3044
- validDateEnd = _a.validDateEnd,
3045
- validDateStart = _a.validDateStart,
3046
- changeGroups = _a.changeGroups;
3047
-
3048
- var currentChangeGroup = changeGroups[index];
3049
- var previousChangeGroup = changeGroups[index - 1];
3050
- return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3088
+ var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3089
+ if (!hasUserDragged) {
3090
+ setStartPosition(newPosition);
3051
3091
  }
3052
3092
 
3053
- return true;
3054
- }, [index, isChangeGroup, getValues]);
3055
-
3056
- var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3057
- var indexedFieldName = "changeGroups[" + rowIndex + "]." + fieldname;
3058
- var rowValue = getValues(indexedFieldName);
3059
- return rowValue ? [indexedFieldName] : [];
3093
+ setIsIssuesPaneOpen(isOpen);
3060
3094
  };
3061
3095
 
3062
- var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3063
- return getFieldFromRow('valid', index + 1);
3096
+ var onCloseIssuesPane = function onCloseIssuesPane() {
3097
+ return setIsIssuesPaneOpen(false);
3064
3098
  };
3065
3099
 
3066
- var validateNextRows = React__default["default"].useCallback(function () {
3067
- if (isChangeGroup) {
3068
- var _a = getValues(),
3069
- validDateEnd = _a.validDateEnd,
3070
- validDateStart = _a.validDateStart,
3071
- changeGroups = _a.changeGroups;
3072
-
3073
- var currentChangeGroup = changeGroups[index];
3074
- var nextChangeGroups = changeGroups.slice(index + 1);
3075
- return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3076
- }
3077
-
3078
- return true;
3079
- }, [index, isChangeGroup, getValues]);
3080
-
3081
- var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3082
- var changeGroups = getValues().changeGroups;
3083
- var previousChangeGroups = changeGroups.slice(0, rowIndex);
3084
- var validFields = previousChangeGroups.map(function (_element, index) {
3085
- return getFieldFromRow('valid', index)[0];
3086
- });
3087
- return validFields;
3100
+ return {
3101
+ isIssuesPaneOpen: isIssuesPaneOpen,
3102
+ startPosition: startPosition,
3103
+ onToggleIssuesPane: onToggleIssuesPane,
3104
+ onCloseIssuesPane: onCloseIssuesPane,
3105
+ onUserHasDragged: onUserHasDragged
3088
3106
  };
3107
+ };
3089
3108
 
3090
- var addChangeGroupBelow = React__default["default"].useCallback(function () {
3091
- onAddChangeGroupBelow(index);
3092
- }, [onAddChangeGroupBelow, index]);
3093
- var addChangeGroupAbove = React__default["default"].useCallback(function () {
3094
- onAddChangeGroupAbove(index);
3095
- }, [onAddChangeGroupAbove, index]);
3096
- var clearRow = React__default["default"].useCallback(function () {
3097
- onClearRow(index);
3098
- }, [onClearRow, index]);
3099
- return /*#__PURE__*/React__default["default"].createElement(material.Grid, __assign({
3100
- sx: {
3101
- marginTop: '8px',
3102
- backgroundColor: 'geowebColors.cards.cardContainer',
3103
- position: 'relative',
3104
- '&.sortable-chosen': {
3105
- boxShadow: 1
3106
- },
3107
- '&.sortable-ghost': {
3108
- opacity: 0.5
3109
- }
3110
- },
3111
- justifyContent: "flex-start",
3112
- "data-testid": "row-" + namePrefix,
3113
- container: true,
3114
- ref: ref
3115
- }, props), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3116
- columns: 24,
3117
- item: true,
3118
- container: true,
3119
- justifyContent: "flex-end",
3120
- xs: 24,
3121
- sm: 23
3122
- }, !isChangeGroup && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3123
- label: "Type",
3124
- name: fieldNames.messageType,
3125
- disabled: true
3126
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3127
- label: "Location",
3128
- name: "location",
3129
- disabled: true
3130
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3131
- formatter: formatIssueTime,
3132
- label: "Issue time",
3133
- name: "issueDate",
3134
- disabled: true
3135
- })), isChangeGroup && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Box, {
3136
- sx: {
3137
- width: 56,
3138
- marginRight: '2px'
3139
- }
3140
- }, !disabled && dragHandle), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3141
- label: "Prob",
3142
- name: fieldNames.probability,
3143
- disabled: disabled,
3144
- defaultValue: getDefaultValue('probability', field),
3145
- rules: {
3146
- validate: {
3147
- validateRequiredMainOptional: validateRequiredMainOptional,
3148
- validateProbabilityField: validateProbabilityField
3149
- }
3109
+ var IssuesPane = function IssuesPane(_a) {
3110
+ var _b = _a.errorList,
3111
+ errorList = _b === void 0 ? [] : _b,
3112
+ isOpen = _a.isOpen,
3113
+ handleClose = _a.handleClose,
3114
+ _c = _a.startPosition,
3115
+ startPosition = _c === void 0 ? {
3116
+ left: 20,
3117
+ top: 50
3118
+ } : _c,
3119
+ _d = _a.onUserHasDragged,
3120
+ onUserHasDragged = _d === void 0 ? function () {} : _d;
3121
+ var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3122
+ return /*#__PURE__*/ReactDOM__default["default"].createPortal( /*#__PURE__*/React__namespace.createElement(shared.ToolContainerDraggable, {
3123
+ startSize: {
3124
+ width: '577px',
3125
+ height: '200px'
3150
3126
  },
3151
- autoComplete: [{
3152
- key: '3',
3153
- value: 'PROB30'
3154
- }, {
3155
- key: '4',
3156
- value: 'PROB40'
3157
- }],
3158
- onBlur: function onBlur() {
3159
- if (isChangeGroup) {
3160
- var nextValidFieldName = getValidFieldFromNextRow();
3161
- trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)));
3127
+ startPosition: startPosition,
3128
+ minWidth: 300,
3129
+ onClose: handleClose,
3130
+ title: getPaneTitle(errorList.length),
3131
+ headerSize: "xs",
3132
+ isOpen: isOpen,
3133
+ "data-testid": "moveable-issues-pane",
3134
+ bounds: "parent",
3135
+ onDragEnd: function onDragEnd(event) {
3136
+ if (event.x !== 0 && event.y !== 0) {
3137
+ onUserHasDragged();
3162
3138
  }
3163
3139
  }
3164
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3165
- label: "Change",
3166
- name: fieldNames.change,
3167
- disabled: disabled,
3168
- defaultValue: getDefaultValue('change', field),
3169
- rules: {
3170
- validate: {
3171
- validateRequiredMainOptional: validateRequiredMainOptional,
3172
- validateChangeField: validateChangeField,
3173
- validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3174
- return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3175
- }
3176
- }
3140
+ }, /*#__PURE__*/React__namespace.createElement(material.Box, {
3141
+ component: "div",
3142
+ sx: {
3143
+ marginTop: '16px',
3144
+ marginLeft: '24px'
3145
+ }
3146
+ }, errorList.length === 0 && /*#__PURE__*/React__namespace.createElement(material.Box, {
3147
+ component: "div",
3148
+ sx: {
3149
+ fontSize: '4rem'
3177
3150
  },
3178
- autoComplete: [{
3179
- key: 'T',
3180
- value: 'TEMPO'
3181
- }, {
3182
- key: 'B',
3183
- value: 'BECMG'
3184
- }, {
3185
- key: 'F',
3186
- value: 'FM'
3187
- }],
3188
- onBlur: function onBlur() {
3189
- if (isChangeGroup) {
3190
- var nextValidFieldName = getValidFieldFromNextRow();
3191
- var previousValidFieldNames = getPreviousValidFields(index);
3192
- trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
3193
- }
3151
+ "data-testid": "zeroIssuesImage"
3152
+ }, /*#__PURE__*/React__namespace.createElement(theme.ThumbsUp, {
3153
+ sx: {
3154
+ height: '69px',
3155
+ width: '58px'
3194
3156
  }
3195
- })), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3196
- label: "Valid",
3197
- name: fieldNames.valid,
3198
- // always disabled for baseforecast row
3199
- disabled: !isChangeGroup ? true : disabled,
3200
- defaultValue: getDefaultValue('valid', field),
3201
- rules: {
3202
- validate: {
3203
- validateRequiredMain: validateRequiredMain,
3204
- validateValidField: function validateValidField$1(value) {
3205
- return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3206
- },
3207
- validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3208
- return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3209
- },
3210
- validatePreviousRow: validatePreviousRow,
3211
- validateNextRows: validateNextRows
3157
+ })), errorList.length > 0 && errorList.map(function (error, index) {
3158
+ return /*#__PURE__*/React__namespace.createElement(material.Typography // eslint-disable-next-line react/no-array-index-key
3159
+ , {
3160
+ // eslint-disable-next-line react/no-array-index-key
3161
+ key: "message-" + index,
3162
+ variant: "body1",
3163
+ "data-testid": "errorMessage"
3164
+ }, getErrorMessage(error, index));
3165
+ }))), rootElement);
3166
+ };
3167
+
3168
+ /* *
3169
+ * Licensed under the Apache License, Version 2.0 (the "License");
3170
+ * you may not use this file except in compliance with the License.
3171
+ * You may obtain a copy of the License at
3172
+ *
3173
+ * http://www.apache.org/licenses/LICENSE-2.0
3174
+ *
3175
+ * Unless required by applicable law or agreed to in writing, software
3176
+ * distributed under the License is distributed on an "AS IS" BASIS,
3177
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3178
+ * See the License for the specific language governing permissions and
3179
+ * limitations under the License.
3180
+ *
3181
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3182
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3183
+ * */
3184
+ var TafModuleContext = /*#__PURE__*/React__namespace.createContext({
3185
+ onValidateForm: null,
3186
+ registerValidateForm: null,
3187
+ tafAction: null,
3188
+ setTafAction: null,
3189
+ onPreventCloseView: null
3190
+ });
3191
+ var useTafModuleContext = function useTafModuleContext() {
3192
+ return React__namespace.useContext(TafModuleContext);
3193
+ };
3194
+ var useTafModuleState = function useTafModuleState(_a) {
3195
+ var onPreventCloseView = _a.onPreventCloseView;
3196
+
3197
+ var _b = __read(React__namespace.useState(function () {
3198
+ return new Promise(function () {
3199
+ return true;
3200
+ });
3201
+ }), 2),
3202
+ onValidateForm = _b[0],
3203
+ registerValidateForm = _b[1];
3204
+
3205
+ var _c = __read(React__namespace.useState(), 2),
3206
+ tafAction = _c[0],
3207
+ setTafAction = _c[1];
3208
+
3209
+ var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3210
+ registerValidateForm(function () {
3211
+ return promiseToRegister;
3212
+ });
3213
+ };
3214
+
3215
+ return {
3216
+ onValidateForm: onValidateForm,
3217
+ registerValidateForm: onRegisterValidateForm,
3218
+ tafAction: tafAction,
3219
+ setTafAction: setTafAction,
3220
+ onPreventCloseView: onPreventCloseView
3221
+ };
3222
+ };
3223
+ var TafModuleProvider = function TafModuleProvider(_a) {
3224
+ var children = _a.children,
3225
+ _b = _a.onPreventCloseView,
3226
+ onPreventCloseView = _b === void 0 ? function () {} : _b;
3227
+ var contextState = useTafModuleState({
3228
+ onPreventCloseView: onPreventCloseView
3229
+ });
3230
+ return /*#__PURE__*/React__namespace.createElement(TafModuleContext.Provider, {
3231
+ value: contextState
3232
+ }, children);
3233
+ };
3234
+
3235
+ var styles = {
3236
+ label: {
3237
+ color: 'geowebColors.buttons.tertiary.default.color',
3238
+ opacity: 1,
3239
+ fontSize: '12px',
3240
+ fontWeight: 500
3241
+ }
3242
+ };
3243
+
3244
+ var SwitchButton = function SwitchButton(props) {
3245
+ return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3246
+ title: "Switch mode"
3247
+ }, /*#__PURE__*/React__namespace.createElement("span", null, /*#__PURE__*/React__namespace.createElement(material.FormLabel, {
3248
+ sx: styles.label
3249
+ }, "Viewer"), /*#__PURE__*/React__namespace.createElement(material.Switch, __assign({
3250
+ "data-testid": "switchMode"
3251
+ }, props)), /*#__PURE__*/React__namespace.createElement(material.FormLabel, {
3252
+ sx: styles.label
3253
+ }, "Editor")));
3254
+ };
3255
+
3256
+ var TafAvatar = function TafAvatar(_a) {
3257
+ var editor = _a.editor,
3258
+ _b = _a.tooltipPlacement,
3259
+ tooltipPlacement = _b === void 0 ? 'bottom' : _b;
3260
+ return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3261
+ title: "Editor: " + editor,
3262
+ placement: tooltipPlacement
3263
+ }, /*#__PURE__*/React__namespace.createElement("span", null, /*#__PURE__*/React__namespace.createElement(shared.Avatar, {
3264
+ size: "small"
3265
+ }, shared.getInitials(editor))));
3266
+ };
3267
+
3268
+ var textFieldStyle = function textFieldStyle(theme) {
3269
+ return {
3270
+ // input
3271
+ marginRight: '2px',
3272
+ marginBottom: '4px',
3273
+ width: 56,
3274
+ height: 46,
3275
+ input: {
3276
+ textAlign: 'center',
3277
+ fontSize: 10,
3278
+ fontWeight: 500,
3279
+ paddingLeft: 0,
3280
+ paddingRight: 0,
3281
+ '&.Mui-disabled': {
3282
+ color: 'geowebColors.typographyAndIcons.text',
3283
+ WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
3284
+ },
3285
+ // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
3286
+ '&:-webkit-autofill': {
3287
+ WebkitTransitionDelay: '86400s' // 1 day delay
3288
+
3212
3289
  }
3213
3290
  },
3214
- onBlur: function onBlur() {
3215
- if (isChangeGroup) {
3216
- var nextValidFieldName = getValidFieldFromNextRow();
3217
- var previousValidFieldNames = getPreviousValidFields(index);
3218
- trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
3219
- }
3220
- }
3221
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3222
- label: "Wind",
3223
- name: fieldNames.wind,
3224
- disabled: disabled,
3225
- defaultValue: getDefaultValue('wind', field),
3226
- rules: {
3227
- validate: {
3228
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3229
- return _validateRequiredMainFields(value, 'Wind');
3230
- },
3231
- validateRequiredSub: validateRequiredSub,
3232
- validateWindField: function validateWindField$1(value) {
3233
- return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3234
- }
3235
- }
3236
- },
3237
- onBlur: function onBlur() {
3238
- if (isChangeGroup) {
3239
- trigger(__spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)));
3240
- }
3241
- },
3242
- autoFocus: !isChangeGroup
3243
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3244
- label: "Visibility",
3245
- name: fieldNames.visibility,
3246
- disabled: disabled,
3247
- defaultValue: getDefaultValue('visibility', field),
3248
- rules: {
3249
- validate: {
3250
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3251
- return _validateRequiredMainFields(value, 'Visibility');
3252
- },
3253
- validateRequiredSub: validateRequiredSub,
3254
- validateVisibilityField: validateVisibilityField
3255
- }
3256
- },
3257
- autoComplete: [{
3258
- key: 'C',
3259
- value: 'CAVOK'
3260
- }],
3261
- onBlur: function onBlur() {
3262
- var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : subFields;
3263
- trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3264
- }
3265
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3266
- label: "Weather",
3267
- name: fieldNames.weather1,
3268
- disabled: disabled,
3269
- defaultValue: getDefaultValue('weather.weather1', field),
3270
- rules: {
3271
- validate: {
3272
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3273
- return _validateRequiredMainFields(value, 'Weather');
3274
- },
3275
- validateRequiredSub: validateRequiredSub,
3276
- validateWeatherField: function validateWeatherField$1(value) {
3277
- return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3278
- }
3279
- }
3280
- },
3281
- onBlur: function onBlur() {
3282
- var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3283
- return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3284
- }
3285
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3286
- label: "Weather",
3287
- name: fieldNames.weather2,
3288
- disabled: disabled,
3289
- defaultValue: getDefaultValue('weather.weather2', field),
3290
- rules: {
3291
- validate: {
3292
- validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3293
- return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3294
- }
3295
- }
3296
- },
3297
- onBlur: function onBlur() {
3298
- var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3299
- return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3300
- }
3301
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3302
- label: "Weather",
3303
- name: fieldNames.weather3,
3304
- disabled: disabled,
3305
- defaultValue: getDefaultValue('weather.weather3', field),
3306
- rules: {
3307
- validate: {
3308
- validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3309
- return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3310
- }
3311
- }
3312
- },
3313
- onBlur: function onBlur() {
3314
- return trigger([fieldNames.wind, fieldNames.cloud1]);
3315
- }
3316
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3317
- label: "Cloud",
3318
- name: fieldNames.cloud1,
3319
- disabled: disabled,
3320
- defaultValue: getDefaultValue('cloud.cloud1', field),
3321
- rules: {
3322
- validate: {
3323
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3324
- return _validateRequiredMainFields(value, 'Clouds');
3325
- },
3326
- validateRequiredSub: validateRequiredSub,
3327
- validateFirstCloud: function validateFirstCloud$1(value) {
3328
- return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3329
- }
3330
- }
3331
- },
3332
- onBlur: function onBlur() {
3333
- var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3334
- return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3335
- }
3336
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3337
- label: "Cloud",
3338
- name: fieldNames.cloud2,
3339
- disabled: disabled,
3340
- defaultValue: getDefaultValue('cloud.cloud2', field),
3341
- rules: {
3342
- validate: {
3343
- validateSecondCloud: function validateSecondCloud$1(value) {
3344
- return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3345
- }
3346
- }
3291
+ label: {
3292
+ transformOrigin: 'center top',
3293
+ right: 0,
3294
+ textAlign: 'center',
3295
+ fontSize: '10px',
3296
+ '&.Mui-disabled': {
3297
+ color: 'geowebColors.captions.captionStatus.rgba'
3298
+ },
3299
+ whiteSpace: 'nowrap',
3300
+ maxWidth: '100%',
3301
+ transform: 'translate(0px, 16px) scale(1)'
3347
3302
  },
3348
- onBlur: function onBlur() {
3349
- return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3350
- }
3351
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3352
- label: "Cloud",
3353
- name: fieldNames.cloud3,
3354
- disabled: disabled,
3355
- defaultValue: getDefaultValue('cloud.cloud3', field),
3356
- rules: {
3357
- validate: {
3358
- validateThirdCloud: function validateThirdCloud$1(value) {
3359
- return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3360
- }
3361
- }
3303
+ // shrink
3304
+ ' .MuiInputLabel-shrink': {
3305
+ transform: 'translate(2px, 10px) scale(0.75) !important',
3306
+ letterSpacing: '0.33px',
3307
+ textAlign: 'left'
3362
3308
  },
3363
- onBlur: function onBlur() {
3364
- return trigger(fieldNames.cloud4);
3365
- }
3366
- }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3367
- label: "Cloud",
3368
- name: fieldNames.cloud4,
3369
- disabled: disabled,
3370
- defaultValue: getDefaultValue('cloud.cloud4', field),
3371
- rules: {
3372
- validate: {
3373
- validateFourthCloud: function validateFourthCloud$1(value) {
3374
- return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3375
- }
3309
+ // root
3310
+ '&': {
3311
+ '.Mui-error.MuiFilledInput-root': {
3312
+ backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
3313
+ },
3314
+ '.Mui-disabled:before': {
3315
+ borderColor: 'transparent'
3376
3316
  }
3377
3317
  }
3378
- })), !disabled && /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3379
- item: true,
3380
- container: true,
3381
- justifyContent: "flex-end",
3382
- alignItems: "flex-end",
3383
- xs: 24,
3384
- sm: 1,
3385
- sx: {
3386
- marginBottom: '16px'
3387
- },
3388
- columns: 24
3389
- }, /*#__PURE__*/React__default["default"].createElement(TafFormOptionsButton, {
3390
- isChangeGroup: isChangeGroup,
3391
- addChangeGroupBelow: addChangeGroupBelow,
3392
- addChangeGroupAbove: addChangeGroupAbove,
3393
- removeChangeGroup: function removeChangeGroup() {
3394
- return onRemoveChangeGroup(index);
3395
- },
3396
- clearRow: clearRow,
3397
- index: index
3398
- })));
3399
- });
3400
-
3401
- /* *
3402
- * Licensed under the Apache License, Version 2.0 (the "License");
3403
- * you may not use this file except in compliance with the License.
3404
- * You may obtain a copy of the License at
3405
- *
3406
- * http://www.apache.org/licenses/LICENSE-2.0
3407
- *
3408
- * Unless required by applicable law or agreed to in writing, software
3409
- * distributed under the License is distributed on an "AS IS" BASIS,
3410
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3411
- * See the License for the specific language governing permissions and
3412
- * limitations under the License.
3413
- *
3414
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3415
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3416
- * */
3417
- var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3418
- switch (tafAction) {
3419
- case 'AMEND':
3420
- case 'DRAFT_AMEND':
3421
- return 'DRAFT_AMEND';
3422
-
3423
- case 'CORRECT':
3424
- case 'DRAFT_CORRECT':
3425
- return 'DRAFT_CORRECT';
3426
-
3427
- default:
3428
- return 'DRAFT';
3429
- }
3318
+ };
3430
3319
  };
3431
3320
 
3432
- var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3433
- switch (tafAction) {
3434
- case 'AMEND':
3435
- case 'DRAFT_AMEND':
3436
- return 'AMEND';
3321
+ var getTafErrors = function getTafErrors(name, errors) {
3322
+ var nameAsArray = name.split('.');
3437
3323
 
3438
- case 'CORRECT':
3439
- case 'DRAFT_CORRECT':
3440
- return 'CORRECT';
3324
+ if (nameAsArray[0].includes('changeGroups')) {
3325
+ if (errors.changeGroups) {
3326
+ var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
3327
+ var restArray = nameAsArray.slice(1);
3328
+ return formFields.getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
3329
+ } // No changegroup errors
3441
3330
 
3442
- default:
3443
- return 'PUBLISH';
3331
+
3332
+ return null;
3444
3333
  }
3334
+
3335
+ return formFields.getDeepProperty(nameAsArray, errors);
3445
3336
  };
3446
3337
 
3447
- var buttonsStyle = {
3448
- button: {
3449
- minWidth: {
3450
- xs: '56px',
3451
- sm: '64px'
3452
- },
3453
- width: {
3454
- xs: '56px',
3455
- sm: '64px'
3456
- },
3457
- marginLeft: {
3458
- xs: 0.5,
3459
- sm: 1
3460
- },
3461
- marginTop: 3,
3462
- marginBottom: 3
3463
- }
3338
+ var getDisplayValue = function getDisplayValue(value, disabled) {
3339
+ return disabled && !value ? '-' : value;
3464
3340
  };
3341
+ var BaseTextField = /*#__PURE__*/React__default["default"].memo(function (props) {
3342
+ return /*#__PURE__*/React__default["default"].createElement(material.TextField, __assign({
3343
+ type: "text",
3344
+ variant: "filled",
3345
+ sx: textFieldStyle
3346
+ }, props));
3347
+ }, function (prevProps, nextProps) {
3348
+ return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
3349
+ });
3465
3350
 
3466
- var ViewModeButtons = function ViewModeButtons(_a) {
3467
- var canBe = _a.canBe,
3468
- onTafViewModeButtonPress = _a.onTafViewModeButtonPress;
3469
- return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
3470
- "data-testid": "canceltaf",
3471
- variant: "tertiary",
3472
- onClick: function onClick() {
3473
- return onTafViewModeButtonPress('CANCEL');
3474
- }
3475
- }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
3476
- "data-testid": "correcttaf",
3477
- variant: "tertiary",
3478
- onClick: function onClick() {
3479
- return onTafViewModeButtonPress('CORRECT');
3480
- }
3481
- }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
3482
- "data-testid": "amendtaf",
3483
- variant: "tertiary",
3484
- onClick: function onClick() {
3485
- return onTafViewModeButtonPress('AMEND');
3486
- }
3487
- }, "Amend"));
3488
- };
3351
+ var TafFormTextField = function TafFormTextField(_a) {
3352
+ var label = _a.label,
3353
+ _b = _a.disabled,
3354
+ disabled = _b === void 0 ? false : _b,
3355
+ _c = _a.name,
3356
+ name = _c === void 0 ? '' : _c,
3357
+ _d = _a.onChange,
3358
+ onChange = _d === void 0 ? function () {} : _d,
3359
+ _e = _a.onBlur,
3360
+ onBlur = _e === void 0 ? function () {} : _e,
3361
+ _f = _a.defaultValue,
3362
+ defaultValue = _f === void 0 ? '' : _f,
3363
+ _g = _a.formatter,
3364
+ formatter = _g === void 0 ? null : _g,
3365
+ rules = _a.rules,
3366
+ _h = _a.autoComplete,
3367
+ autoComplete = _h === void 0 ? [] : _h,
3368
+ _j = _a.autoFocus,
3369
+ autoFocus = _j === void 0 ? false : _j;
3489
3370
 
3490
- var TafFormButtons = function TafFormButtons(_a) {
3491
- var _b = _a.isFormDisabled,
3492
- isFormDisabled = _b === void 0 ? false : _b,
3493
- tafAction = _a.tafAction,
3494
- _c = _a.canBe,
3495
- canBe = _c === void 0 ? [] : _c,
3496
- onTafEditModeButtonPress = _a.onTafEditModeButtonPress,
3497
- onTafViewModeButtonPress = _a.onTafViewModeButtonPress;
3498
- return /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3499
- container: true,
3500
- justifyContent: "flex-end",
3501
- sx: buttonsStyle,
3502
- columns: 24
3503
- }, /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3504
- item: true,
3505
- container: true,
3506
- justifyContent: "flex-end",
3507
- columns: 24,
3508
- xs: 24,
3509
- sm: 23
3510
- }, isFormDisabled ? /*#__PURE__*/React__default["default"].createElement(ViewModeButtons, {
3511
- canBe: canBe,
3512
- onTafViewModeButtonPress: onTafViewModeButtonPress
3513
- }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Button, {
3514
- "data-testid": "cleartaf",
3515
- variant: "tertiary",
3516
- onClick: function onClick() {
3517
- // Simply discard the changes and close the dialog.
3518
- onTafEditModeButtonPress('CLEAR');
3519
- }
3520
- }, "Clear"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3521
- "data-testid": "savedrafttaf",
3522
- variant: "tertiary",
3523
- onClick: function onClick() {
3524
- /* Save the TAF as draft:
3525
- if action NEW or DRAFT - new status will be DRAFT -- default
3526
- if action AMEND - new status will be DRAFT_AMENDED
3527
- if action CORRECT - new status will be DRAFT_CORRECTED
3528
- if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3529
- if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3530
- */
3531
- onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
3371
+ var _k = reactHookForm.useFormContext(),
3372
+ control = _k.control,
3373
+ setValue = _k.setValue,
3374
+ errors = _k.formState.errors;
3375
+
3376
+ var fieldErrors = getTafErrors(name, errors);
3377
+
3378
+ var _l = __read(React__default["default"].useState(null), 2),
3379
+ maxLength = _l[0],
3380
+ setMaxLength = _l[1];
3381
+
3382
+ var onKeyDown = React__default["default"].useCallback(function (event) {
3383
+ var target = event.target;
3384
+ var currentValue = target.value,
3385
+ selectionStart = target.selectionStart,
3386
+ selectionEnd = target.selectionEnd;
3387
+ var textSelection = currentValue.substring(selectionStart, selectionEnd);
3388
+
3389
+ if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
3390
+ var pressedKey_1 = event.key.toString().toUpperCase();
3391
+ var foundValue = autoComplete.find(function (el) {
3392
+ return el.key === pressedKey_1;
3393
+ }) || null;
3394
+
3395
+ if (foundValue) {
3396
+ setValue(name, foundValue.value, {
3397
+ shouldDirty: true
3398
+ });
3399
+ setMaxLength(foundValue.value.length);
3400
+ event.preventDefault();
3401
+ }
3532
3402
  }
3533
- }, "Save"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3534
- "data-testid": "publishtaf",
3535
- variant: "tertiary",
3536
- onClick: function onClick() {
3537
- /* Publish the TAF:
3538
- if action NEW or DRAFT - new status will be PUBLISHED -- default
3539
- if action AMEND - new status will be AMENDED
3540
- if action CORRECT - new status will be CORRECTED
3541
- if action DRAFT_AMEND - new status will be AMENDED
3542
- if action DRAFT_CORRECT - new status will be CORRECTED
3543
- */
3544
- onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
3403
+ }, [name, autoComplete, setValue]);
3404
+ var onChangeField = React__default["default"].useCallback(function (event, callback) {
3405
+ var valueUppercase = event.currentTarget.value.toUpperCase();
3406
+
3407
+ if (autoComplete) {
3408
+ var exist = autoComplete.find(function (e) {
3409
+ return e.value === valueUppercase;
3410
+ });
3411
+ var newMaxLength = exist ? valueUppercase.length : null;
3412
+ setMaxLength(newMaxLength);
3545
3413
  }
3546
- }, "Publish"))), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3547
- item: true,
3548
- columns: 24,
3549
- sm: 1
3550
- }));
3414
+
3415
+ callback(valueUppercase);
3416
+ onChange(valueUppercase);
3417
+ }, [onChange, autoComplete]);
3418
+ var onBlurField = React__default["default"].useCallback(function (callback) {
3419
+ callback();
3420
+ onBlur();
3421
+ }, [onBlur]);
3422
+ var hasError = !!fieldErrors;
3423
+ return /*#__PURE__*/React__default["default"].createElement(reactHookForm.Controller, {
3424
+ render: function render(_a) {
3425
+ var field = _a.field;
3426
+ var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
3427
+ return /*#__PURE__*/React__default["default"].createElement(BaseTextField, {
3428
+ label: label,
3429
+ disabled: disabled,
3430
+ name: name,
3431
+ value: displayValue,
3432
+ inputRef: field.ref,
3433
+ onChange: function onChange(e) {
3434
+ return onChangeField(e, field.onChange);
3435
+ },
3436
+ onKeyDown: onKeyDown,
3437
+ error: hasError,
3438
+ onBlur: function onBlur() {
3439
+ return onBlurField(field.onBlur);
3440
+ },
3441
+ inputProps: {
3442
+ maxLength: maxLength
3443
+ },
3444
+ autoFocus: autoFocus
3445
+ });
3446
+ },
3447
+ name: name,
3448
+ control: control,
3449
+ defaultValue: defaultValue,
3450
+ rules: rules
3451
+ });
3551
3452
  };
3552
3453
 
3553
3454
  /* *
@@ -3563,30 +3464,27 @@
3563
3464
  * See the License for the specific language governing permissions and
3564
3465
  * limitations under the License.
3565
3466
  *
3566
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3567
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3467
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3468
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3568
3469
  * */
3569
3470
 
3570
- var DragHandle = function DragHandle(_a) {
3571
- var _b = _a.isSorting,
3572
- isSorting = _b === void 0 ? false : _b,
3573
- _c = _a.isDisabled,
3574
- isDisabled = _c === void 0 ? false : _c,
3575
- index = _a.index;
3576
- return /*#__PURE__*/React__default["default"].createElement(material.IconButton, {
3577
- className: "handle",
3578
- "data-testid": "dragHandle-" + index,
3579
- disableRipple: true,
3580
- disabled: isDisabled,
3581
- size: "large",
3582
- sx: {
3583
- backgroundColor: 'transparent',
3584
- '&:hover': {
3585
- backgroundColor: 'transparent'
3586
- },
3587
- cursor: isSorting ? 'grabbing' : 'grab'
3588
- }
3589
- }, /*#__PURE__*/React__default["default"].createElement(theme.DragHandle, null));
3471
+ var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
3472
+ var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
3473
+
3474
+ var validateChangeField = function validateChangeField(value) {
3475
+ var trimmedValue = getFieldValue(value);
3476
+ var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
3477
+ return isValid ? true : invalidChangeMessage;
3478
+ };
3479
+ var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
3480
+ var trimmedProbValue = getFieldValue(valueProb);
3481
+ var trimmedValue = getFieldValue(value);
3482
+
3483
+ if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
3484
+ return invalidChangeProbCombinationMessage;
3485
+ }
3486
+
3487
+ return true;
3590
3488
  };
3591
3489
 
3592
3490
  /* *
@@ -3602,82 +3500,16 @@
3602
3500
  * See the License for the specific language governing permissions and
3603
3501
  * limitations under the License.
3604
3502
  *
3605
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3606
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3503
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3504
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3607
3505
  * */
3608
- var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
3609
- return __assign(__assign({}, error), {
3610
- isChangeGroup: isChangeGroup,
3611
- rowIndex: rowIndex
3612
- });
3613
- };
3614
- var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
3615
- switch (sumOfErrors) {
3616
- case 0:
3617
- return '0 issues';
3618
-
3619
- case 1:
3620
- return '1 issue';
3621
-
3622
- default:
3623
- return sumOfErrors + " issues";
3624
- }
3625
- };
3626
- var getErrorValues = function getErrorValues(fieldErrors, isChangeGroup, rowIndex) {
3627
- if (isChangeGroup === void 0) {
3628
- isChangeGroup = false;
3629
- }
3630
-
3631
- if (rowIndex === void 0) {
3632
- rowIndex = -1;
3633
- }
3634
-
3635
- if (!fieldErrors) return [];
3636
- return Object.keys(fieldErrors).reduce(function (list, key) {
3637
- var error = __assign({}, fieldErrors[key]);
3638
-
3639
- if (error.ref) {
3640
- return list.concat(getCustomError(error, isChangeGroup, rowIndex));
3641
- }
3642
-
3643
- return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
3644
- }, []);
3645
- };
3646
- var filterDuplicateErrors = function filterDuplicateErrors(errors) {
3647
- return errors.reduce(function (list, error) {
3648
- // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
3649
- if (error.type === 'validateRequiredSub') {
3650
- var exist = list.find(function (e) {
3651
- return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
3652
- });
3653
- return exist ? list : list.concat(error);
3654
- }
3655
-
3656
- if (error.type === 'validateRequiredMainOptional') {
3657
- var exist = list.find(function (e) {
3658
- return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
3659
- });
3660
- return exist ? list : list.concat(error);
3661
- }
3662
-
3663
- return list.concat(error);
3664
- }, []);
3665
- };
3666
- var getErrors = function getErrors(errors) {
3667
- var errorList = Object.keys(errors).reduce(function (list, key) {
3668
- var errorValue = errors[key]; // changeGroups
3669
-
3670
- if (Array.isArray(errorValue)) {
3671
- var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
3672
- return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
3673
- }, []);
3674
- return list.concat.apply(list, __spreadArray([], __read(errorValues)));
3675
- } // baseForecast
3676
3506
 
3507
+ var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
3677
3508
 
3678
- return list.concat(getErrorValues(errorValue, false, -1));
3679
- }, []);
3680
- return errorList;
3509
+ var validateProbabilityField = function validateProbabilityField(value) {
3510
+ var trimmedValue = getFieldValue(value);
3511
+ var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
3512
+ return isValid ? true : invalidProbabilityMessage;
3681
3513
  };
3682
3514
 
3683
3515
  /* *
@@ -3693,277 +3525,501 @@
3693
3525
  * See the License for the specific language governing permissions and
3694
3526
  * limitations under the License.
3695
3527
  *
3696
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3697
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3528
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3529
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3698
3530
  * */
3699
3531
 
3700
- var IssuesButton = function IssuesButton(_a) {
3701
- var _b = _a.errors,
3702
- errors = _b === void 0 ? {} : _b,
3703
- _c = _a.isIssuesPaneOpen,
3704
- isIssuesPaneOpen = _c === void 0 ? false : _c,
3705
- _d = _a.setIsIssuesPaneOpen,
3706
- setIsIssuesPaneOpen = _d === void 0 ? function () {
3707
- return null;
3708
- } : _d;
3709
- var errorList = filterDuplicateErrors(getErrors(errors));
3710
- var totalErrors = errorList.length;
3711
- var errorStatus = totalErrors > 0 ? 'error' : 'success';
3712
- var buttonColor = "geowebColors.functional." + errorStatus;
3713
-
3714
- var toggleIssuesPane = function toggleIssuesPane(newPosition) {
3715
- return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
3532
+ var TafFormOptionsButton = function TafFormOptionsButton(_a) {
3533
+ var isChangeGroup = _a.isChangeGroup,
3534
+ addChangeGroupBelow = _a.addChangeGroupBelow,
3535
+ addChangeGroupAbove = _a.addChangeGroupAbove,
3536
+ removeChangeGroup = _a.removeChangeGroup,
3537
+ clearRow = _a.clearRow,
3538
+ index = _a.index;
3539
+ var insertAbove = {
3540
+ text: 'Insert 1 row above',
3541
+ icon: /*#__PURE__*/React__namespace.createElement(theme.Add, null),
3542
+ action: addChangeGroupAbove
3716
3543
  };
3544
+ var insertBelow = {
3545
+ text: 'Insert 1 row below',
3546
+ icon: /*#__PURE__*/React__namespace.createElement(theme.Add, null),
3547
+ action: addChangeGroupBelow
3548
+ };
3549
+ var deleteRow = {
3550
+ text: 'Delete row',
3551
+ icon: /*#__PURE__*/React__namespace.createElement(theme.Delete, null),
3552
+ action: removeChangeGroup
3553
+ };
3554
+ var clear = {
3555
+ text: 'Clear row',
3556
+ icon: /*#__PURE__*/React__namespace.createElement(theme.Close, null),
3557
+ action: clearRow
3558
+ };
3559
+ var menuItemsBaseForecast = [insertBelow, clear];
3560
+ var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
3561
+ return /*#__PURE__*/React__namespace.createElement(shared.ToggleMenu, {
3562
+ buttonTestId: "tafFormOptions[" + index + "]",
3563
+ buttonSx: {
3564
+ marginTop: '10px',
3565
+ marginLeft: '4px'
3566
+ },
3567
+ menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
3568
+ });
3569
+ };
3717
3570
 
3718
- var onClickButton = function onClickButton(event) {
3719
- var _a;
3720
-
3721
- var _b = event.currentTarget.getBoundingClientRect(),
3722
- left = _b.left,
3723
- top = _b.top;
3571
+ var getDefaultValue = function getDefaultValue(fieldName, data) {
3572
+ if (!data) {
3573
+ return '';
3574
+ }
3724
3575
 
3725
- var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3726
- top: 0,
3727
- left: 0
3728
- };
3729
- var newPosition = {
3730
- left: left - parentOffset.left + 100,
3731
- top: top - parentOffset.top
3732
- };
3733
- toggleIssuesPane(newPosition);
3734
- };
3576
+ return formFields.getDeepProperty(fieldName.split('.'), data) || '';
3577
+ };
3735
3578
 
3736
- return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3737
- title: "View details"
3738
- }, /*#__PURE__*/React__namespace.createElement(material.Chip, {
3739
- "data-testid": "issuesButton",
3740
- className: "status-" + errorStatus,
3741
- size: "small",
3742
- label: getIssuesLabel(totalErrors),
3743
- onClick: onClickButton,
3744
- sx: {
3745
- width: '74px',
3746
- color: '#ffffff',
3747
- backgroundColor: buttonColor,
3748
- '&:hover': {
3749
- backgroundColor: buttonColor
3750
- },
3751
- '&:focus': {
3752
- backgroundColor: buttonColor
3753
- },
3754
- fontSize: 12
3755
- }
3756
- }));
3579
+ var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
3580
+ return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
3581
+ ];
3757
3582
  };
3758
3583
 
3759
- var getPaneTitle = function getPaneTitle(sumOfErrors) {
3760
- switch (sumOfErrors) {
3761
- case 0:
3762
- return 'Looks good';
3584
+ var TafFormRow = /*#__PURE__*/React__default["default"].forwardRef(function (_a, ref) {
3585
+ var isNotRequiredForAction = _a.isNotRequiredForAction,
3586
+ _b = _a.isChangeGroup,
3587
+ isChangeGroup = _b === void 0 ? false : _b,
3588
+ _c = _a.disabled,
3589
+ disabled = _c === void 0 ? false : _c,
3590
+ _d = _a.index,
3591
+ index = _d === void 0 ? -1 : _d,
3592
+ onRemoveChangeGroup = _a.onRemoveChangeGroup,
3593
+ _e = _a.field,
3594
+ field = _e === void 0 ? null : _e,
3595
+ _f = _a.dragHandle,
3596
+ dragHandle = _f === void 0 ? null : _f,
3597
+ onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
3598
+ onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
3599
+ onClearRow = _a.onClearRow,
3600
+ props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
3763
3601
 
3764
- case 1:
3765
- return 'There is an issue to address';
3602
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[" + index + "]";
3603
+ var fieldNames = getFieldNames(isChangeGroup, index);
3766
3604
 
3767
- default:
3768
- return 'There are a few issues to address';
3769
- }
3770
- };
3605
+ var _g = reactHookForm.useFormContext(),
3606
+ getValues = _g.getValues,
3607
+ trigger = _g.trigger; // cross-field required validation
3771
3608
 
3772
- var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3773
- if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3774
- // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3775
- var fieldNumber = fieldNumberedValue + 1;
3776
- return errorTitle + " " + fieldNumber;
3777
- }
3778
3609
 
3779
- return errorTitle;
3780
- };
3781
- var getErrorMessage = function getErrorMessage(error, index) {
3782
- var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3783
- var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3784
- return index + 1 + ". " + fieldErrorTitle + ": " + error.message;
3785
- };
3786
- var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3787
- var useIssuesPane = function useIssuesPane() {
3788
- var _a = __read(React__namespace.useState(false), 2),
3789
- isIssuesPaneOpen = _a[0],
3790
- setIsIssuesPaneOpen = _a[1];
3610
+ var _h = __read(getRequiredCrossFields(fieldNames), 3),
3611
+ mainFields = _h[0],
3612
+ mainOptionalFields = _h[1],
3613
+ subFields = _h[2];
3791
3614
 
3792
- var _b = __read(React__namespace.useState(null), 2),
3793
- startPosition = _b[0],
3794
- setStartPosition = _b[1];
3615
+ var hasFieldsValue = function hasFieldsValue(fields) {
3616
+ return fields.map(getValues).find(function (field) {
3617
+ return !!field;
3618
+ });
3619
+ }; // Used to validate the required field for change groups: Valid
3795
3620
 
3796
- var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3797
- if (!startPosition) {
3798
- setStartPosition(newPosition);
3621
+
3622
+ var validateRequiredMain = function validateRequiredMain(value) {
3623
+ return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3624
+ }; // Used to ensure either probability or change is entered, or both
3625
+
3626
+
3627
+ var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3628
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3629
+ }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
3630
+
3631
+
3632
+ var validateRequiredSub = function validateRequiredSub(value) {
3633
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3634
+ }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3635
+
3636
+
3637
+ var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3638
+ var changeField = getValues(namePrefix + ".change");
3639
+ var visibilityField = getValues(namePrefix + ".visibility");
3640
+ var isFM = changeField && changeField.trim() === 'FM';
3641
+ var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3642
+
3643
+ if (isNotRequiredForAction(value) !== true && !value.length) {
3644
+ if (isChangeGroup && isFM || !isChangeGroup) {
3645
+ // exception for CavOK
3646
+ if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3647
+ return true;
3648
+ } // exception for visibility > 5000
3649
+
3650
+
3651
+ if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3652
+ return true;
3653
+ }
3654
+
3655
+ return fieldName + " is required";
3656
+ }
3657
+ }
3658
+
3659
+ return true;
3660
+ };
3661
+
3662
+ var validatePreviousRow = React__default["default"].useCallback(function () {
3663
+ if (isChangeGroup && index > 0) {
3664
+ var _a = getValues(),
3665
+ validDateEnd = _a.validDateEnd,
3666
+ validDateStart = _a.validDateStart,
3667
+ changeGroups = _a.changeGroups;
3668
+
3669
+ var currentChangeGroup = changeGroups[index];
3670
+ var previousChangeGroup = changeGroups[index - 1];
3671
+ return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3672
+ }
3673
+
3674
+ return true;
3675
+ }, [index, isChangeGroup, getValues]);
3676
+
3677
+ var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3678
+ var indexedFieldName = "changeGroups[" + rowIndex + "]." + fieldname;
3679
+ var rowValue = getValues(indexedFieldName);
3680
+ return rowValue ? [indexedFieldName] : [];
3681
+ };
3682
+
3683
+ var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3684
+ return getFieldFromRow('valid', index + 1);
3685
+ };
3686
+
3687
+ var validateNextRows = React__default["default"].useCallback(function () {
3688
+ if (isChangeGroup) {
3689
+ var _a = getValues(),
3690
+ validDateEnd = _a.validDateEnd,
3691
+ validDateStart = _a.validDateStart,
3692
+ changeGroups = _a.changeGroups;
3693
+
3694
+ var currentChangeGroup = changeGroups[index];
3695
+ var nextChangeGroups = changeGroups.slice(index + 1);
3696
+ return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3697
+ }
3698
+
3699
+ return true;
3700
+ }, [index, isChangeGroup, getValues]);
3701
+
3702
+ var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3703
+ var changeGroups = getValues().changeGroups;
3704
+ var previousChangeGroups = changeGroups.slice(0, rowIndex);
3705
+ var validFields = previousChangeGroups.map(function (_element, index) {
3706
+ return getFieldFromRow('valid', index)[0];
3707
+ });
3708
+ return validFields;
3709
+ };
3710
+
3711
+ var addChangeGroupBelow = React__default["default"].useCallback(function () {
3712
+ onAddChangeGroupBelow(index);
3713
+ }, [onAddChangeGroupBelow, index]);
3714
+ var addChangeGroupAbove = React__default["default"].useCallback(function () {
3715
+ onAddChangeGroupAbove(index);
3716
+ }, [onAddChangeGroupAbove, index]);
3717
+ var clearRow = React__default["default"].useCallback(function () {
3718
+ onClearRow(index);
3719
+ }, [onClearRow, index]);
3720
+ return /*#__PURE__*/React__default["default"].createElement(material.Grid, __assign({
3721
+ sx: {
3722
+ marginTop: '8px',
3723
+ backgroundColor: 'geowebColors.cards.cardContainer',
3724
+ position: 'relative',
3725
+ '&.sortable-chosen': {
3726
+ boxShadow: 1
3727
+ },
3728
+ '&.sortable-ghost': {
3729
+ opacity: 0.5
3730
+ }
3731
+ },
3732
+ justifyContent: "flex-start",
3733
+ "data-testid": "row-" + namePrefix,
3734
+ container: true,
3735
+ ref: ref
3736
+ }, props, {
3737
+ className: "formRow"
3738
+ }), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3739
+ columns: 24,
3740
+ item: true,
3741
+ container: true,
3742
+ justifyContent: "flex-end",
3743
+ xs: 24,
3744
+ sm: 23
3745
+ }, !isChangeGroup && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3746
+ label: "Type",
3747
+ name: fieldNames.messageType,
3748
+ disabled: true
3749
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3750
+ label: "Location",
3751
+ name: "location",
3752
+ disabled: true
3753
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3754
+ formatter: formatIssueTime,
3755
+ label: "Issue time",
3756
+ name: "issueDate",
3757
+ disabled: true
3758
+ })), isChangeGroup && /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Box, {
3759
+ sx: {
3760
+ width: 56,
3761
+ marginRight: '2px'
3762
+ }
3763
+ }, !disabled && dragHandle), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3764
+ label: "Prob",
3765
+ name: fieldNames.probability,
3766
+ disabled: disabled,
3767
+ defaultValue: getDefaultValue('probability', field),
3768
+ rules: {
3769
+ validate: {
3770
+ validateRequiredMainOptional: validateRequiredMainOptional,
3771
+ validateProbabilityField: validateProbabilityField
3772
+ }
3773
+ },
3774
+ autoComplete: [{
3775
+ key: '3',
3776
+ value: 'PROB30'
3777
+ }, {
3778
+ key: '4',
3779
+ value: 'PROB40'
3780
+ }],
3781
+ onBlur: function onBlur() {
3782
+ if (isChangeGroup) {
3783
+ var nextValidFieldName = getValidFieldFromNextRow();
3784
+ trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)));
3785
+ }
3786
+ }
3787
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3788
+ label: "Change",
3789
+ name: fieldNames.change,
3790
+ disabled: disabled,
3791
+ defaultValue: getDefaultValue('change', field),
3792
+ rules: {
3793
+ validate: {
3794
+ validateRequiredMainOptional: validateRequiredMainOptional,
3795
+ validateChangeField: validateChangeField,
3796
+ validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3797
+ return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3798
+ }
3799
+ }
3800
+ },
3801
+ autoComplete: [{
3802
+ key: 'T',
3803
+ value: 'TEMPO'
3804
+ }, {
3805
+ key: 'B',
3806
+ value: 'BECMG'
3807
+ }, {
3808
+ key: 'F',
3809
+ value: 'FM'
3810
+ }],
3811
+ onBlur: function onBlur() {
3812
+ if (isChangeGroup) {
3813
+ var nextValidFieldName = getValidFieldFromNextRow();
3814
+ var previousValidFieldNames = getPreviousValidFields(index);
3815
+ trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
3816
+ }
3817
+ }
3818
+ })), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3819
+ label: "Valid",
3820
+ name: fieldNames.valid,
3821
+ // always disabled for baseforecast row
3822
+ disabled: !isChangeGroup ? true : disabled,
3823
+ defaultValue: getDefaultValue('valid', field),
3824
+ rules: {
3825
+ validate: {
3826
+ validateRequiredMain: validateRequiredMain,
3827
+ validateValidField: function validateValidField$1(value) {
3828
+ return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3829
+ },
3830
+ validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3831
+ return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3832
+ },
3833
+ validatePreviousRow: validatePreviousRow,
3834
+ validateNextRows: validateNextRows
3835
+ }
3836
+ },
3837
+ onBlur: function onBlur() {
3838
+ if (isChangeGroup) {
3839
+ var nextValidFieldName = getValidFieldFromNextRow();
3840
+ var previousValidFieldNames = getPreviousValidFields(index);
3841
+ trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
3842
+ }
3843
+ }
3844
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3845
+ label: "Wind",
3846
+ name: fieldNames.wind,
3847
+ disabled: disabled,
3848
+ defaultValue: getDefaultValue('wind', field),
3849
+ rules: {
3850
+ validate: {
3851
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3852
+ return _validateRequiredMainFields(value, 'Wind');
3853
+ },
3854
+ validateRequiredSub: validateRequiredSub,
3855
+ validateWindField: function validateWindField$1(value) {
3856
+ return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3857
+ }
3858
+ }
3859
+ },
3860
+ onBlur: function onBlur() {
3861
+ if (isChangeGroup) {
3862
+ trigger(__spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)));
3863
+ }
3864
+ },
3865
+ autoFocus: !isChangeGroup
3866
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3867
+ label: "Visibility",
3868
+ name: fieldNames.visibility,
3869
+ disabled: disabled,
3870
+ defaultValue: getDefaultValue('visibility', field),
3871
+ rules: {
3872
+ validate: {
3873
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3874
+ return _validateRequiredMainFields(value, 'Visibility');
3875
+ },
3876
+ validateRequiredSub: validateRequiredSub,
3877
+ validateVisibilityField: validateVisibilityField
3878
+ }
3879
+ },
3880
+ autoComplete: [{
3881
+ key: 'C',
3882
+ value: 'CAVOK'
3883
+ }],
3884
+ onBlur: function onBlur() {
3885
+ var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : subFields;
3886
+ trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3887
+ }
3888
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3889
+ label: "Weather",
3890
+ name: fieldNames.weather1,
3891
+ disabled: disabled,
3892
+ defaultValue: getDefaultValue('weather.weather1', field),
3893
+ rules: {
3894
+ validate: {
3895
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3896
+ return _validateRequiredMainFields(value, 'Weather');
3897
+ },
3898
+ validateRequiredSub: validateRequiredSub,
3899
+ validateWeatherField: function validateWeatherField$1(value) {
3900
+ return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3901
+ }
3902
+ }
3903
+ },
3904
+ onBlur: function onBlur() {
3905
+ var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3906
+ return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3907
+ }
3908
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3909
+ label: "Weather",
3910
+ name: fieldNames.weather2,
3911
+ disabled: disabled,
3912
+ defaultValue: getDefaultValue('weather.weather2', field),
3913
+ rules: {
3914
+ validate: {
3915
+ validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3916
+ return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3917
+ }
3918
+ }
3919
+ },
3920
+ onBlur: function onBlur() {
3921
+ var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3922
+ return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3923
+ }
3924
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3925
+ label: "Weather",
3926
+ name: fieldNames.weather3,
3927
+ disabled: disabled,
3928
+ defaultValue: getDefaultValue('weather.weather3', field),
3929
+ rules: {
3930
+ validate: {
3931
+ validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3932
+ return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3933
+ }
3934
+ }
3935
+ },
3936
+ onBlur: function onBlur() {
3937
+ return trigger([fieldNames.wind, fieldNames.cloud1]);
3938
+ }
3939
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3940
+ label: "Cloud",
3941
+ name: fieldNames.cloud1,
3942
+ disabled: disabled,
3943
+ defaultValue: getDefaultValue('cloud.cloud1', field),
3944
+ rules: {
3945
+ validate: {
3946
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3947
+ return _validateRequiredMainFields(value, 'Clouds');
3948
+ },
3949
+ validateRequiredSub: validateRequiredSub,
3950
+ validateFirstCloud: function validateFirstCloud$1(value) {
3951
+ return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3952
+ }
3953
+ }
3954
+ },
3955
+ onBlur: function onBlur() {
3956
+ var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
3957
+ return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3958
+ }
3959
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3960
+ label: "Cloud",
3961
+ name: fieldNames.cloud2,
3962
+ disabled: disabled,
3963
+ defaultValue: getDefaultValue('cloud.cloud2', field),
3964
+ rules: {
3965
+ validate: {
3966
+ validateSecondCloud: function validateSecondCloud$1(value) {
3967
+ return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3968
+ }
3969
+ }
3970
+ },
3971
+ onBlur: function onBlur() {
3972
+ return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3799
3973
  }
3800
-
3801
- setIsIssuesPaneOpen(isOpen);
3802
- };
3803
-
3804
- var onCloseIssuesPane = function onCloseIssuesPane() {
3805
- return setIsIssuesPaneOpen(false);
3806
- };
3807
-
3808
- return {
3809
- isIssuesPaneOpen: isIssuesPaneOpen,
3810
- startPosition: startPosition,
3811
- onToggleIssuesPane: onToggleIssuesPane,
3812
- onCloseIssuesPane: onCloseIssuesPane
3813
- };
3814
- };
3815
-
3816
- var IssuesPane = function IssuesPane(_a) {
3817
- var _b = _a.errorList,
3818
- errorList = _b === void 0 ? [] : _b,
3819
- isOpen = _a.isOpen,
3820
- handleClose = _a.handleClose,
3821
- _c = _a.startPosition,
3822
- startPosition = _c === void 0 ? {
3823
- left: 20,
3824
- top: 50
3825
- } : _c;
3826
- var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3827
- return /*#__PURE__*/ReactDOM__default["default"].createPortal( /*#__PURE__*/React__namespace.createElement(shared.ToolContainerDraggable, {
3828
- startSize: {
3829
- width: '577px',
3830
- height: '200px'
3974
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3975
+ label: "Cloud",
3976
+ name: fieldNames.cloud3,
3977
+ disabled: disabled,
3978
+ defaultValue: getDefaultValue('cloud.cloud3', field),
3979
+ rules: {
3980
+ validate: {
3981
+ validateThirdCloud: function validateThirdCloud$1(value) {
3982
+ return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3983
+ }
3984
+ }
3831
3985
  },
3832
- startPosition: startPosition,
3833
- minWidth: 300,
3834
- onClose: handleClose,
3835
- title: getPaneTitle(errorList.length),
3836
- headerSize: "xs",
3837
- isOpen: isOpen,
3838
- "data-testid": "moveable-issues-pane",
3839
- bounds: "parent"
3840
- }, /*#__PURE__*/React__namespace.createElement(material.Box, {
3841
- component: "div",
3842
- sx: {
3843
- marginTop: '16px',
3844
- marginLeft: '24px'
3986
+ onBlur: function onBlur() {
3987
+ return trigger(fieldNames.cloud4);
3845
3988
  }
3846
- }, errorList.length === 0 && /*#__PURE__*/React__namespace.createElement(material.Box, {
3847
- component: "div",
3989
+ }), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
3990
+ label: "Cloud",
3991
+ name: fieldNames.cloud4,
3992
+ disabled: disabled,
3993
+ defaultValue: getDefaultValue('cloud.cloud4', field),
3994
+ rules: {
3995
+ validate: {
3996
+ validateFourthCloud: function validateFourthCloud$1(value) {
3997
+ return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3998
+ }
3999
+ }
4000
+ }
4001
+ })), !disabled && /*#__PURE__*/React__default["default"].createElement(material.Grid, {
4002
+ item: true,
4003
+ container: true,
4004
+ justifyContent: "flex-end",
4005
+ alignItems: "flex-end",
4006
+ xs: 24,
4007
+ sm: 1,
3848
4008
  sx: {
3849
- fontSize: '4rem'
4009
+ marginBottom: '16px'
3850
4010
  },
3851
- "data-testid": "zeroIssuesImage"
3852
- }, /*#__PURE__*/React__namespace.createElement(theme.ThumbsUp, {
3853
- sx: {
3854
- height: '69px',
3855
- width: '58px'
3856
- }
3857
- })), errorList.length > 0 && errorList.map(function (error, index) {
3858
- return /*#__PURE__*/React__namespace.createElement(material.Typography // eslint-disable-next-line react/no-array-index-key
3859
- , {
3860
- // eslint-disable-next-line react/no-array-index-key
3861
- key: "message-" + index,
3862
- variant: "body1",
3863
- "data-testid": "errorMessage"
3864
- }, getErrorMessage(error, index));
3865
- }))), rootElement);
3866
- };
3867
-
3868
- /* *
3869
- * Licensed under the Apache License, Version 2.0 (the "License");
3870
- * you may not use this file except in compliance with the License.
3871
- * You may obtain a copy of the License at
3872
- *
3873
- * http://www.apache.org/licenses/LICENSE-2.0
3874
- *
3875
- * Unless required by applicable law or agreed to in writing, software
3876
- * distributed under the License is distributed on an "AS IS" BASIS,
3877
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3878
- * See the License for the specific language governing permissions and
3879
- * limitations under the License.
3880
- *
3881
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3882
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3883
- * */
3884
- var TafModuleContext = /*#__PURE__*/React__namespace.createContext({
3885
- onValidateForm: null,
3886
- registerValidateForm: null,
3887
- tafAction: null,
3888
- setTafAction: null,
3889
- onPreventCloseView: null
4011
+ columns: 24
4012
+ }, /*#__PURE__*/React__default["default"].createElement(TafFormOptionsButton, {
4013
+ isChangeGroup: isChangeGroup,
4014
+ addChangeGroupBelow: addChangeGroupBelow,
4015
+ addChangeGroupAbove: addChangeGroupAbove,
4016
+ removeChangeGroup: function removeChangeGroup() {
4017
+ return onRemoveChangeGroup(index);
4018
+ },
4019
+ clearRow: clearRow,
4020
+ index: index
4021
+ })));
3890
4022
  });
3891
- var useTafModuleContext = function useTafModuleContext() {
3892
- return React__namespace.useContext(TafModuleContext);
3893
- };
3894
- var useTafModuleState = function useTafModuleState(_a) {
3895
- var onPreventCloseView = _a.onPreventCloseView;
3896
-
3897
- var _b = __read(React__namespace.useState(function () {
3898
- return new Promise(function () {
3899
- return true;
3900
- });
3901
- }), 2),
3902
- onValidateForm = _b[0],
3903
- registerValidateForm = _b[1];
3904
-
3905
- var _c = __read(React__namespace.useState(), 2),
3906
- tafAction = _c[0],
3907
- setTafAction = _c[1];
3908
-
3909
- var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3910
- registerValidateForm(function () {
3911
- return promiseToRegister;
3912
- });
3913
- };
3914
-
3915
- return {
3916
- onValidateForm: onValidateForm,
3917
- registerValidateForm: onRegisterValidateForm,
3918
- tafAction: tafAction,
3919
- setTafAction: setTafAction,
3920
- onPreventCloseView: onPreventCloseView
3921
- };
3922
- };
3923
- var TafModuleProvider = function TafModuleProvider(_a) {
3924
- var children = _a.children,
3925
- _b = _a.onPreventCloseView,
3926
- onPreventCloseView = _b === void 0 ? function () {} : _b;
3927
- var contextState = useTafModuleState({
3928
- onPreventCloseView: onPreventCloseView
3929
- });
3930
- return /*#__PURE__*/React__namespace.createElement(TafModuleContext.Provider, {
3931
- value: contextState
3932
- }, children);
3933
- };
3934
-
3935
- var styles = {
3936
- label: {
3937
- color: 'geowebColors.buttons.tertiary.default.color',
3938
- opacity: 1,
3939
- fontSize: '12px',
3940
- fontWeight: 500
3941
- }
3942
- };
3943
-
3944
- var SwitchButton = function SwitchButton(props) {
3945
- return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3946
- title: "Switch mode"
3947
- }, /*#__PURE__*/React__namespace.createElement("span", null, /*#__PURE__*/React__namespace.createElement(material.FormLabel, {
3948
- sx: styles.label
3949
- }, "Viewer"), /*#__PURE__*/React__namespace.createElement(material.Switch, __assign({
3950
- "data-testid": "switchMode"
3951
- }, props)), /*#__PURE__*/React__namespace.createElement(material.FormLabel, {
3952
- sx: styles.label
3953
- }, "Editor")));
3954
- };
3955
-
3956
- var TafAvatar = function TafAvatar(_a) {
3957
- var editor = _a.editor,
3958
- _b = _a.tooltipPlacement,
3959
- tooltipPlacement = _b === void 0 ? 'bottom' : _b;
3960
- return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
3961
- title: "Editor: " + editor,
3962
- placement: tooltipPlacement
3963
- }, /*#__PURE__*/React__namespace.createElement("span", null, /*#__PURE__*/React__namespace.createElement(shared.Avatar, {
3964
- size: "small"
3965
- }, shared.getInitials(editor))));
3966
- };
3967
4023
 
3968
4024
  var noop = function noop() {};
3969
4025
 
@@ -3995,7 +4051,10 @@
3995
4051
  _h = _a.fetchNewTafList,
3996
4052
  fetchNewTafList = _h === void 0 ? function () {
3997
4053
  return null;
3998
- } : _h;
4054
+ } : _h,
4055
+ _j = _a.previousTaf,
4056
+ previousTaf = _j === void 0 ? null : _j;
4057
+ var formRef = React__default["default"].useRef();
3999
4058
  var originalTaf = tafFromBackend.taf,
4000
4059
  editor = tafFromBackend.editor;
4001
4060
  var auth = authentication.useAuthenticationContext().auth;
@@ -4004,49 +4063,50 @@
4004
4063
  var isDefaultDisabled = getIsFormDefaultDisabled(originalTaf.status);
4005
4064
  var confirmDialog = shared.useConfirmationDialog();
4006
4065
 
4007
- var _j = shared.useDraftFormHelpers(),
4008
- toggleIsDraft = _j.toggleIsDraft,
4009
- isNotRequiredForAction = _j.isRequired;
4010
-
4011
- var _k = useTafModuleContext(),
4012
- registerValidateForm = _k.registerValidateForm,
4013
- tafAction = _k.tafAction,
4014
- setTafAction = _k.setTafAction,
4015
- onPreventCloseView = _k.onPreventCloseView;
4016
-
4017
- var _l = reactHookForm.useFormContext(),
4018
- control = _l.control,
4019
- handleSubmit = _l.handleSubmit,
4020
- trigger = _l.trigger,
4021
- formState = _l.formState,
4022
- getValues = _l.getValues,
4023
- setValue = _l.setValue,
4024
- reset = _l.reset; // added this ignore as the build is failing otherwise on: Type instantiation is excessively deep and possibly infinite.
4066
+ var _k = shared.useDraftFormHelpers(),
4067
+ toggleIsDraft = _k.toggleIsDraft,
4068
+ isNotRequiredForAction = _k.isRequired;
4069
+
4070
+ var _l = useTafModuleContext(),
4071
+ registerValidateForm = _l.registerValidateForm,
4072
+ tafAction = _l.tafAction,
4073
+ setTafAction = _l.setTafAction,
4074
+ onPreventCloseView = _l.onPreventCloseView;
4075
+
4076
+ var _m = reactHookForm.useFormContext(),
4077
+ control = _m.control,
4078
+ handleSubmit = _m.handleSubmit,
4079
+ trigger = _m.trigger,
4080
+ formState = _m.formState,
4081
+ getValues = _m.getValues,
4082
+ setValue = _m.setValue,
4083
+ resetField = _m.resetField; // added this ignore as the build is failing otherwise on: Type instantiation is excessively deep and possibly infinite.
4025
4084
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4026
4085
  // @ts-ignore
4027
4086
 
4028
4087
 
4029
- var _m = reactHookForm.useFieldArray({
4088
+ var _o = reactHookForm.useFieldArray({
4030
4089
  control: control,
4031
4090
  name: 'changeGroups'
4032
4091
  }),
4033
- fields = _m.fields,
4034
- insert = _m.insert,
4035
- remove = _m.remove,
4036
- move = _m.move;
4092
+ fields = _o.fields,
4093
+ insert = _o.insert,
4094
+ remove = _o.remove,
4095
+ move = _o.move;
4037
4096
 
4038
- var _o = useDragOrder(trigger, move),
4039
- onChangeOrder = _o.onChangeOrder,
4040
- onStartDrag = _o.onStartDrag,
4041
- activeDraggingIndex = _o.activeDraggingIndex;
4097
+ var _p = useDragOrder(trigger, move),
4098
+ onChangeOrder = _p.onChangeOrder,
4099
+ onStartDrag = _p.onStartDrag,
4100
+ activeDraggingIndex = _p.activeDraggingIndex;
4042
4101
 
4043
- var isFormDirty = formState.isDirty,
4102
+ var dirtyFields = formState.dirtyFields,
4044
4103
  errors = formState.errors;
4045
- shared.usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4104
+ var isFormDirty$1 = isFormDirty(dirtyFields);
4105
+ shared.usePreventBrowserClose(isFormDirty$1 && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4046
4106
 
4047
4107
  React__default["default"].useEffect(function () {
4048
- onPreventCloseView(isFormDirty); // eslint-disable-next-line react-hooks/exhaustive-deps
4049
- }, [isFormDirty]);
4108
+ onPreventCloseView(isFormDirty$1); // eslint-disable-next-line react-hooks/exhaustive-deps
4109
+ }, [isFormDirty$1]);
4050
4110
  var hiddenInputFields = ['baseTime', 'issueDate', 'uuid', 'validDateStart', 'validDateEnd', 'status', 'previousId', 'previousValidDateStart', 'previousValidDateEnd', shared.HIDDEN_INPUT_HELPER_IS_DRAFT];
4051
4111
 
4052
4112
  var onSubmit = function onSubmit(data) {
@@ -4058,7 +4118,8 @@
4058
4118
  return confirmDialog({
4059
4119
  title: getConfirmationDialogTitle(action),
4060
4120
  description: getConfirmationDialogContent(action, function () {
4061
- return isTafAmendedCorrectedChanged(isFormDirty, originalTaf, convertTafValuesToObject(getValues()));
4121
+ return isTafAmendedCorrectedChanged( // If already saved as draft amd/cor then send over the previous taf
4122
+ originalTaf.status === 'DRAFT_AMENDED' || originalTaf.status === 'DRAFT_CORRECTED' ? previousTaf : originalTaf, convertTafValuesToObject(getValues()));
4062
4123
  }),
4063
4124
  confirmLabel: getConfirmationDialogButtonLabel(action)
4064
4125
  });
@@ -4069,9 +4130,17 @@
4069
4130
  keepDirty = false;
4070
4131
  }
4071
4132
 
4072
- reset(formData, {
4073
- keepDirty: keepDirty,
4074
- keepDirtyValues: false
4133
+ Object.keys(formData).forEach(function (key) {
4134
+ if (!keepDirty || key === 'changeGroups') {
4135
+ resetField(key, {
4136
+ keepDirty: keepDirty,
4137
+ defaultValue: formData[key]
4138
+ });
4139
+ }
4140
+
4141
+ setValue(key, formData[key], {
4142
+ shouldDirty: keepDirty
4143
+ });
4075
4144
  });
4076
4145
  };
4077
4146
 
@@ -4173,7 +4242,7 @@
4173
4242
  var onSwitchMode = function onSwitchMode(event) {
4174
4243
  var checked = event.target.checked;
4175
4244
 
4176
- if (!checked && isFormDirty) {
4245
+ if (!checked && isFormDirty$1) {
4177
4246
  confirmDialog({
4178
4247
  title: 'Whoops',
4179
4248
  description: 'Are you sure you want to switch to viewer mode? Your unsaved changes will be lost.',
@@ -4221,13 +4290,7 @@
4221
4290
 
4222
4291
  case 'CLEAR':
4223
4292
  showConfirmDialog(action).then(function () {
4224
- var emptiedForm = clearTafFormData(getValues()); // Trigger an invisible change to dirty the form
4225
- // This is needed to trigger the autosave on changing location/time
4226
-
4227
- var baseForecastFields = getFieldNames(false, -1);
4228
- setValue(baseForecastFields.wind, ' ', {
4229
- shouldDirty: true
4230
- });
4293
+ var emptiedForm = clearTafFormData(getValues());
4231
4294
  resetFormValues(emptiedForm, true);
4232
4295
  showSnackbar('TAF has been cleared');
4233
4296
  });
@@ -4263,11 +4326,32 @@
4263
4326
 
4264
4327
  return [2
4265
4328
  /*return*/
4266
- ];
4329
+ , true];
4267
4330
  }
4268
4331
  });
4269
4332
  });
4270
- })();
4333
+ })().then(function () {
4334
+ var hasFormErrors = Object.keys(errors).length;
4335
+ var formNodeRef = formRef.current;
4336
+
4337
+ if (hasFormErrors && formNodeRef) {
4338
+ var inputsWithError = formNodeRef.querySelectorAll('.Mui-error');
4339
+ var firstFormGroupWithError = inputsWithError.length ? inputsWithError[inputsWithError.length - 1].closest('.formRow') : null;
4340
+
4341
+ if (firstFormGroupWithError) {
4342
+ var _a = getFormRowPosition(firstFormGroupWithError),
4343
+ top_1 = _a.top,
4344
+ left = _a.left;
4345
+
4346
+ var tafModuleNode = formNodeRef.closest('#tafmodule');
4347
+ var newTop = top_1 - (tafModuleNode === null || tafModuleNode === void 0 ? void 0 : tafModuleNode.getBoundingClientRect().top) || 0;
4348
+ setIsIssuesPaneOpen(true, {
4349
+ top: newTop,
4350
+ left: left
4351
+ });
4352
+ }
4353
+ }
4354
+ });
4271
4355
  break;
4272
4356
 
4273
4357
  default:
@@ -4387,9 +4471,9 @@
4387
4471
  });
4388
4472
  };
4389
4473
 
4390
- var _p = __read(React__default["default"].useState(false), 2),
4391
- shouldValidate = _p[0],
4392
- setShouldValidate = _p[1];
4474
+ var _q = __read(React__default["default"].useState(false), 2),
4475
+ shouldValidate = _q[0],
4476
+ setShouldValidate = _q[1];
4393
4477
 
4394
4478
  React__default["default"].useEffect(function () {
4395
4479
  setIsDisabled(!isEditor || isDefaultDisabled); // set validate flag to validate after the values have been set
@@ -4466,7 +4550,8 @@
4466
4550
  editor: editor
4467
4551
  }))), /*#__PURE__*/React__default["default"].createElement("form", {
4468
4552
  "data-testid": "taf-form",
4469
- onSubmit: handleSubmit(onSubmit)
4553
+ onSubmit: handleSubmit(onSubmit),
4554
+ ref: formRef
4470
4555
  }, /*#__PURE__*/React__default["default"].createElement(TafFormRow, {
4471
4556
  disabled: isDisabled,
4472
4557
  onAddChangeGroupBelow: onAddRow,
@@ -4763,6 +4848,14 @@
4763
4848
 
4764
4849
  return 0;
4765
4850
  };
4851
+ var getPreviousTaf = function getPreviousTaf(tafList, currentTaf) {
4852
+ var previousId = currentTaf.taf.previousId;
4853
+ if (!previousId) return null;
4854
+ var previousTaf = tafList.find(function (taf) {
4855
+ return taf.taf.uuid === previousId;
4856
+ });
4857
+ return previousTaf ? previousTaf.taf : null;
4858
+ };
4766
4859
 
4767
4860
  /* *
4768
4861
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -5270,7 +5363,8 @@
5270
5363
  location: 'EHAM'
5271
5364
  }
5272
5365
  } : _c;
5273
- var isDirty = reactHookForm.useFormContext().formState.isDirty;
5366
+ var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5367
+ var isDirty = isFormDirty(dirtyFields);
5274
5368
 
5275
5369
  if (!tafFromBackend) {
5276
5370
  return null;
@@ -5336,7 +5430,8 @@
5336
5430
  _c = _a.onChangeTab,
5337
5431
  onChangeTab = _c === void 0 ? function () {} : _c,
5338
5432
  timeSlot = _a.timeSlot;
5339
- var isDirty = reactHookForm.useFormContext().formState.isDirty;
5433
+ var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5434
+ var isDirty = isFormDirty(dirtyFields);
5340
5435
  return /*#__PURE__*/React__namespace.createElement(material.MenuList, {
5341
5436
  "data-testid": "location-tabs",
5342
5437
  sx: {
@@ -5564,7 +5659,10 @@
5564
5659
  _j = _a.fetchNewTafList,
5565
5660
  fetchNewTafList = _j === void 0 ? function () {
5566
5661
  return null;
5567
- } : _j;
5662
+ } : _j,
5663
+ _k = _a.previousTaf,
5664
+ previousTaf = _k === void 0 ? null : _k,
5665
+ tafAction = _a.tafAction;
5568
5666
  var severity = isWarning(error) ? 'warning' : 'error';
5569
5667
 
5570
5668
  var onTafAction = function onTafAction(action, taf) {
@@ -5666,7 +5764,7 @@
5666
5764
  index: index,
5667
5765
  "data-testid": "taf-panel" + (activeTafIndex === index ? '-active' : '')
5668
5766
  }, /*#__PURE__*/React__default["default"].createElement(TafHeader, {
5669
- title: getTafStatusLabel(tafFromBackend.taf.status),
5767
+ title: getTafStatusLabel(tafFromBackend.taf.status, tafAction, isFormDisabled),
5670
5768
  sx: {
5671
5769
  marginBottom: '4px'
5672
5770
  }
@@ -5699,7 +5797,8 @@
5699
5797
  isDisabled: isFormDisabled,
5700
5798
  setIsDisabled: setIsFormDisabled,
5701
5799
  onSwitchEditor: patchTaf,
5702
- fetchNewTafList: fetchNewTafList
5800
+ fetchNewTafList: fetchNewTafList,
5801
+ previousTaf: previousTaf
5703
5802
  })));
5704
5803
  };
5705
5804
 
@@ -5794,7 +5893,7 @@
5794
5893
  return 'Saved as draft';
5795
5894
 
5796
5895
  case 'DRAFT_AMENDED':
5797
- return 'Saved as draft amended';
5896
+ return 'Saved as draft amendment';
5798
5897
 
5799
5898
  case 'DRAFT_CORRECTED':
5800
5899
  return 'Saved as draft correction';
@@ -5832,7 +5931,8 @@
5832
5931
  isIssuesPaneOpen = _d.isIssuesPaneOpen,
5833
5932
  onToggleIssuesPane = _d.onToggleIssuesPane,
5834
5933
  onCloseIssuesPane = _d.onCloseIssuesPane,
5835
- startPosition = _d.startPosition;
5934
+ startPosition = _d.startPosition,
5935
+ onUserHasDragged = _d.onUserHasDragged;
5836
5936
 
5837
5937
  var _e = usePostTafRequest(api$1.postTaf),
5838
5938
  isLoading = _e.isLoading,
@@ -6172,7 +6272,9 @@
6172
6272
  patchTaf: patchTaf,
6173
6273
  isLoading: isLoading,
6174
6274
  error: error,
6175
- fetchNewTafList: onUpdateTaf
6275
+ fetchNewTafList: onUpdateTaf,
6276
+ previousTaf: getPreviousTaf(tafList, tafFromBackend),
6277
+ tafAction: tafAction
6176
6278
  });
6177
6279
  }))), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
6178
6280
  item: true,
@@ -6195,7 +6297,8 @@
6195
6297
  })))))), /*#__PURE__*/React__default["default"].createElement(IssuesPaneWrapper, {
6196
6298
  handleClose: onCloseIssuesPane,
6197
6299
  isOpen: isIssuesPaneOpen,
6198
- startPosition: startPosition
6300
+ startPosition: startPosition,
6301
+ onUserHasDragged: onUserHasDragged
6199
6302
  }));
6200
6303
  };
6201
6304
 
@@ -7187,15 +7290,21 @@
7187
7290
  }
7188
7291
  };
7189
7292
 
7293
+ var _d = fakeDraftAmendmentTaf.taf;
7294
+ _d.changeGroups;
7295
+ var fakeDraftAmendmentWithoutChangeGroups = __rest(_d, ["changeGroups"]); // Only use for display purposes in the list!
7296
+
7297
+
7190
7298
  ({
7191
7299
  creationDate: "2022-01-06T14:00:00Z",
7192
7300
  canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7193
7301
  editor: null,
7194
- taf: __assign(__assign({}, fakeDraftAmendmentTaf.taf), {
7302
+ taf: __assign(__assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7195
7303
  location: 'EHRD',
7196
7304
  baseTime: "2022-01-06T12:00:00Z",
7197
7305
  validDateStart: "2022-01-06T14:00:00Z",
7198
7306
  validDateEnd: "2022-01-07T18:00:00Z",
7307
+ previousId: "previousIdOfPreviousTAF",
7199
7308
  previousValidDateStart: "2022-01-06T12:00:00Z",
7200
7309
  previousValidDateEnd: "2022-01-07T18:00:00Z",
7201
7310
  baseForecast: __assign(__assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
@@ -7203,8 +7312,32 @@
7203
7312
  start: "2022-01-06T14:00:00Z",
7204
7313
  end: "2022-01-07T18:00:00Z"
7205
7314
  }
7206
- }),
7207
- changeGroups: []
7315
+ })
7316
+ })
7317
+ }); // Use as the original previous TAF for TAF above
7318
+
7319
+ ({
7320
+ creationDate: "2022-01-06T14:00:00Z",
7321
+ canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7322
+ editor: null,
7323
+ taf: __assign(__assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7324
+ status: 'AMENDED',
7325
+ uuid: 'previousIdOfPreviousTAF',
7326
+ location: 'EHRD',
7327
+ baseTime: "2022-01-06T12:00:00Z",
7328
+ validDateStart: "2022-01-06T14:00:00Z",
7329
+ validDateEnd: "2022-01-07T18:00:00Z",
7330
+ baseForecast: __assign(__assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
7331
+ valid: {
7332
+ start: "2022-01-06T14:00:00Z",
7333
+ end: "2022-01-07T18:00:00Z"
7334
+ },
7335
+ wind: {
7336
+ direction: 344,
7337
+ speed: 90,
7338
+ unit: 'KT'
7339
+ }
7340
+ })
7208
7341
  })
7209
7342
  });
7210
7343
  var fakeAmendmentTaf = {