@opengeoweb/taf 4.11.0 → 4.13.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.
Files changed (123) hide show
  1. package/README.md +0 -0
  2. package/index.d.ts +0 -0
  3. package/index.esm.js +1390 -1240
  4. package/index.umd.js +1416 -1270
  5. package/lib/TafDemo.stories.d.ts +0 -0
  6. package/lib/components/ComponentsLookUp/ComponentsLookUp.d.ts +0 -0
  7. package/lib/components/ComponentsLookUp/ComponentsLookUp.spec.d.ts +0 -0
  8. package/lib/components/ComponentsLookUp/index.d.ts +0 -0
  9. package/lib/components/IssuesPane/IssuesButton.d.ts +0 -0
  10. package/lib/components/IssuesPane/IssuesButton.spec.d.ts +0 -0
  11. package/lib/components/IssuesPane/IssuesPane.d.ts +1 -0
  12. package/lib/components/IssuesPane/IssuesPane.spec.d.ts +0 -0
  13. package/lib/components/IssuesPane/IssuesPane.stories.d.ts +0 -0
  14. package/lib/components/IssuesPane/IssuesPaneWrapper.d.ts +0 -0
  15. package/lib/components/IssuesPane/IssuesPaneWrapper.spec.d.ts +0 -0
  16. package/lib/components/IssuesPane/index.d.ts +0 -0
  17. package/lib/components/IssuesPane/types.d.ts +1 -0
  18. package/lib/components/IssuesPane/utils.d.ts +0 -0
  19. package/lib/components/IssuesPane/utils.spec.d.ts +0 -0
  20. package/lib/components/Providers/Providers.d.ts +0 -0
  21. package/lib/components/Providers/index.d.ts +0 -0
  22. package/lib/components/Spinner/Spinner.d.ts +0 -0
  23. package/lib/components/Spinner/Spinner.spec.d.ts +0 -0
  24. package/lib/components/Spinner/Spinner.stories.d.ts +0 -0
  25. package/lib/components/StatusIcon/StatusIcon.d.ts +0 -0
  26. package/lib/components/StatusIcon/StatusIcon.spec.d.ts +0 -0
  27. package/lib/components/SwitchButton/SwitchButton.d.ts +0 -0
  28. package/lib/components/SwitchButton/SwitchButton.spec.d.ts +0 -0
  29. package/lib/components/SwitchButton/index.d.ts +0 -0
  30. package/lib/components/TabPanel/TabPanel.d.ts +0 -0
  31. package/lib/components/TabPanel/TabPanel.spec.d.ts +0 -0
  32. package/lib/components/TabPanel/index.d.ts +0 -0
  33. package/lib/components/TafAvatar/TafAvatar.d.ts +0 -0
  34. package/lib/components/TafAvatar/index.d.ts +0 -0
  35. package/lib/components/TafForm/TafForm.d.ts +2 -1
  36. package/lib/components/TafForm/TafForm.spec.d.ts +0 -0
  37. package/lib/components/TafForm/TafForm.statusChanges.spec.d.ts +0 -0
  38. package/lib/components/TafForm/TafForm.stories.d.ts +0 -0
  39. package/lib/components/TafForm/TafFormButtons/TafFormButtons.d.ts +0 -0
  40. package/lib/components/TafForm/TafFormButtons/TafFormButtons.spec.d.ts +0 -0
  41. package/lib/components/TafForm/TafFormButtons/TafFormOptionsButton.d.ts +0 -0
  42. package/lib/components/TafForm/TafFormButtons/TafFormOptionsButton.spec.d.ts +0 -0
  43. package/lib/components/TafForm/TafFormRow/DragHandle.d.ts +0 -0
  44. package/lib/components/TafForm/TafFormRow/DragHandle.spec.d.ts +0 -0
  45. package/lib/components/TafForm/TafFormRow/TafFormRow.d.ts +0 -0
  46. package/lib/components/TafForm/TafFormRow/TafFormRow.spec.d.ts +0 -0
  47. package/lib/components/TafForm/TafFormRow/TafFormTextField.d.ts +5 -1
  48. package/lib/components/TafForm/TafFormRow/TafFormTextField.spec.d.ts +0 -0
  49. package/lib/components/TafForm/TafFormRow/types.d.ts +0 -0
  50. package/lib/components/TafForm/TafFormRow/validations/change.d.ts +0 -0
  51. package/lib/components/TafForm/TafFormRow/validations/change.spec.d.ts +0 -0
  52. package/lib/components/TafForm/TafFormRow/validations/clouds.d.ts +3 -3
  53. package/lib/components/TafForm/TafFormRow/validations/clouds.spec.d.ts +0 -0
  54. package/lib/components/TafForm/TafFormRow/validations/probability.d.ts +0 -0
  55. package/lib/components/TafForm/TafFormRow/validations/probability.spec.d.ts +0 -0
  56. package/lib/components/TafForm/TafFormRow/validations/utils.d.ts +1 -0
  57. package/lib/components/TafForm/TafFormRow/validations/utils.spec.d.ts +0 -0
  58. package/lib/components/TafForm/TafFormRow/validations/validField.d.ts +0 -0
  59. package/lib/components/TafForm/TafFormRow/validations/validField.spec.d.ts +0 -0
  60. package/lib/components/TafForm/TafFormRow/validations/visibility.d.ts +0 -0
  61. package/lib/components/TafForm/TafFormRow/validations/visibility.spec.d.ts +0 -0
  62. package/lib/components/TafForm/TafFormRow/validations/weather.d.ts +3 -3
  63. package/lib/components/TafForm/TafFormRow/validations/weather.spec.d.ts +0 -0
  64. package/lib/components/TafForm/TafFormRow/validations/wind.d.ts +0 -0
  65. package/lib/components/TafForm/TafFormRow/validations/wind.spec.d.ts +0 -0
  66. package/lib/components/TafForm/index.d.ts +0 -0
  67. package/lib/components/TafForm/utils.d.ts +4 -2
  68. package/lib/components/TafForm/utils.spec.d.ts +0 -0
  69. package/lib/components/TafHeader/TafHeader.d.ts +0 -0
  70. package/lib/components/TafHeader/TafHeader.spec.d.ts +0 -0
  71. package/lib/components/TafLayout/LastUpdateTime/LastUpdateTime.d.ts +0 -0
  72. package/lib/components/TafLayout/LastUpdateTime/LastUpdateTime.spec.d.ts +0 -0
  73. package/lib/components/TafLayout/LastUpdateTime/LastUpdateTime.stories.d.ts +0 -0
  74. package/lib/components/TafLayout/LastUpdateTime/index.d.ts +0 -0
  75. package/lib/components/TafLayout/LocationTabs/LocationTabs.d.ts +0 -0
  76. package/lib/components/TafLayout/LocationTabs/LocationTabs.spec.d.ts +0 -0
  77. package/lib/components/TafLayout/LocationTabs/LocationTabs.stories.d.ts +0 -0
  78. package/lib/components/TafLayout/LocationTabs/index.d.ts +0 -0
  79. package/lib/components/TafLayout/TacOverview/AdverseWeatherTacMessage.d.ts +0 -0
  80. package/lib/components/TafLayout/TacOverview/AdverseWeatherTacMessage.spec.d.ts +0 -0
  81. package/lib/components/TafLayout/TacOverview/AdverseWeatherTacMessage.stories.d.ts +0 -0
  82. package/lib/components/TafLayout/TacOverview/ExportButton.d.ts +0 -0
  83. package/lib/components/TafLayout/TacOverview/ExportButton.spec.d.ts +0 -0
  84. package/lib/components/TafLayout/TacOverview/TacContainer.d.ts +0 -0
  85. package/lib/components/TafLayout/TacOverview/TacContainer.spec.d.ts +0 -0
  86. package/lib/components/TafLayout/TacOverview/TacOverview.d.ts +0 -0
  87. package/lib/components/TafLayout/TacOverview/TacOverview.spec.d.ts +0 -0
  88. package/lib/components/TafLayout/TacOverview/TacOverview.stories.d.ts +0 -0
  89. package/lib/components/TafLayout/TacOverview/TacOverviewMobile.d.ts +0 -0
  90. package/lib/components/TafLayout/TacOverview/TacOverviewMobile.spec.d.ts +0 -0
  91. package/lib/components/TafLayout/TacOverview/TacOverviewMobile.stories.d.ts +0 -0
  92. package/lib/components/TafLayout/TacOverview/index.d.ts +0 -0
  93. package/lib/components/TafLayout/TafLayout.d.ts +0 -0
  94. package/lib/components/TafLayout/TafLayout.spec.d.ts +0 -0
  95. package/lib/components/TafLayout/TafLayout.stories.d.ts +0 -0
  96. package/lib/components/TafLayout/TafPanel/TafPanel.d.ts +3 -1
  97. package/lib/components/TafLayout/TafPanel/TafPanel.spec.d.ts +0 -0
  98. package/lib/components/TafLayout/TafPanel/TafPanel.stories.d.ts +0 -0
  99. package/lib/components/TafLayout/TafPanel/index.d.ts +0 -0
  100. package/lib/components/TafLayout/TopTabs/TopTabs.d.ts +0 -0
  101. package/lib/components/TafLayout/TopTabs/TopTabs.spec.d.ts +0 -0
  102. package/lib/components/TafLayout/TopTabs/TopTabs.stories.d.ts +0 -0
  103. package/lib/components/TafLayout/TopTabs/index.d.ts +0 -0
  104. package/lib/components/TafLayout/utils.d.ts +1 -0
  105. package/lib/components/TafLayout/utils.spec.d.ts +0 -0
  106. package/lib/components/TafModule/TafModule.d.ts +0 -0
  107. package/lib/components/TafModule/TafModule.spec.d.ts +0 -0
  108. package/lib/components/TafModule/TafModule.stories.d.ts +0 -0
  109. package/lib/components/TafModule/TafModuleProvider.d.ts +0 -0
  110. package/lib/components/TafModule/index.d.ts +0 -0
  111. package/lib/components/TafWrapper/TafWrapper.d.ts +0 -0
  112. package/lib/components/TafWrapper/TafWrapper.spec.d.ts +0 -0
  113. package/lib/components/TafWrapper/index.d.ts +0 -0
  114. package/lib/storyshots/Storyshots.spec.d.ts +0 -0
  115. package/lib/types.d.ts +0 -0
  116. package/lib/utils/__mocks__/api.d.ts +0 -0
  117. package/lib/utils/api.d.ts +0 -0
  118. package/lib/utils/api.spec.d.ts +0 -0
  119. package/lib/utils/fakeApi.d.ts +0 -0
  120. package/lib/utils/fakeApi.spec.d.ts +0 -0
  121. package/lib/utils/mockdata/fakeTafList.d.ts +1 -0
  122. package/lib/utils/weatherPhenomena.d.ts +0 -0
  123. package/package.json +12 -11
package/index.esm.js CHANGED
@@ -1,18 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import React__default from 'react';
3
- import { TextField, Grid, Box, Button, IconButton, Chip, Typography, FormLabel, Switch, Card, Tabs, Tab, Dialog, MenuList, MenuItem, Backdrop, CircularProgress } from '@mui/material';
3
+ import { Grid, Button, IconButton, Chip, Box, Typography, FormLabel, Switch, TextField, Card, Tabs, Tab, Dialog, MenuList, MenuItem, Backdrop, CircularProgress } from '@mui/material';
4
4
  import { useFormContext, Controller, useFieldArray } from 'react-hook-form';
5
5
  import { useDispatch } from 'react-redux';
6
6
  import { ReactSortable } from 'react-sortablejs';
7
7
  import Sortable from 'sortablejs';
8
8
  import { useAuthenticationContext } from '@opengeoweb/authentication';
9
9
  import { getDeepProperty, ReactHookFormHiddenInput, ReactHookFormProvider } from '@opengeoweb/form-fields';
10
- import { HIDDEN_INPUT_HELPER_IS_DRAFT, useIsMounted, ToggleMenu, CustomTooltip, ToolContainerDraggable, Avatar, getInitials, useConfirmationDialog, useDraftFormHelpers, usePreventBrowserClose, ToolButton, ToolHeader, AlertBanner, getErrorMessage as getErrorMessage$1, getWarningMessage, ConfirmationServiceProvider, usePoller, ErrorBoundary } from '@opengeoweb/shared';
10
+ import { HIDDEN_INPUT_HELPER_IS_DRAFT, useIsMounted, CustomTooltip, ToolContainerDraggable, Avatar, getInitials, ToggleMenu, useConfirmationDialog, useDraftFormHelpers, usePreventBrowserClose, ToolButton, ToolHeader, AlertBanner, getErrorMessage as getErrorMessage$1, getWarningMessage, ConfirmationServiceProvider, usePoller, ErrorBoundary } from '@opengeoweb/shared';
11
11
  import { snackbarActions } from '@opengeoweb/core';
12
12
  import moment from 'moment';
13
13
  import { isEqual } from 'lodash';
14
- import { Add, Delete, Close, DragHandle as DragHandle$1, ThumbsUp, Clock, Cancel, Success, Edit, Export, ListItem, Cached } from '@opengeoweb/theme';
14
+ import { DragHandle as DragHandle$1, ThumbsUp, Add, Delete, Close, Clock, Cancel, Success, Edit, Export, ListItem, Cached } from '@opengeoweb/theme';
15
15
  import ReactDOM from 'react-dom';
16
+ import { useTheme } from '@emotion/react';
16
17
  import { useApiContext, createApiInstance, createFakeApiInstance, ApiProvider } from '@opengeoweb/api';
17
18
  import LinearProgress from '@mui/material/LinearProgress';
18
19
  import Box$1 from '@mui/material/Box';
@@ -173,6 +174,184 @@ function __awaiter(thisArg, _arguments, P, generator) {
173
174
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
174
175
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
175
176
  * */
177
+ var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
178
+ switch (tafAction) {
179
+ case 'AMEND':
180
+ case 'DRAFT_AMEND':
181
+ return 'DRAFT_AMEND';
182
+
183
+ case 'CORRECT':
184
+ case 'DRAFT_CORRECT':
185
+ return 'DRAFT_CORRECT';
186
+
187
+ default:
188
+ return 'DRAFT';
189
+ }
190
+ };
191
+
192
+ var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
193
+ switch (tafAction) {
194
+ case 'AMEND':
195
+ case 'DRAFT_AMEND':
196
+ return 'AMEND';
197
+
198
+ case 'CORRECT':
199
+ case 'DRAFT_CORRECT':
200
+ return 'CORRECT';
201
+
202
+ default:
203
+ return 'PUBLISH';
204
+ }
205
+ };
206
+
207
+ var buttonsStyle = {
208
+ button: {
209
+ minWidth: {
210
+ xs: '56px',
211
+ sm: '64px'
212
+ },
213
+ width: {
214
+ xs: '56px',
215
+ sm: '64px'
216
+ },
217
+ marginLeft: {
218
+ xs: 0.5,
219
+ sm: 1
220
+ },
221
+ marginTop: 3,
222
+ marginBottom: 3
223
+ }
224
+ };
225
+
226
+ var ViewModeButtons = function ViewModeButtons(_ref) {
227
+ var canBe = _ref.canBe,
228
+ onTafViewModeButtonPress = _ref.onTafViewModeButtonPress;
229
+ return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default.createElement(Button, {
230
+ "data-testid": "canceltaf",
231
+ variant: "tertiary",
232
+ onClick: function onClick() {
233
+ return onTafViewModeButtonPress('CANCEL');
234
+ }
235
+ }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
236
+ "data-testid": "correcttaf",
237
+ variant: "tertiary",
238
+ onClick: function onClick() {
239
+ return onTafViewModeButtonPress('CORRECT');
240
+ }
241
+ }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default.createElement(Button, {
242
+ "data-testid": "amendtaf",
243
+ variant: "tertiary",
244
+ onClick: function onClick() {
245
+ return onTafViewModeButtonPress('AMEND');
246
+ }
247
+ }, "Amend"));
248
+ };
249
+
250
+ var TafFormButtons = function TafFormButtons(_ref2) {
251
+ var _ref2$isFormDisabled = _ref2.isFormDisabled,
252
+ isFormDisabled = _ref2$isFormDisabled === void 0 ? false : _ref2$isFormDisabled,
253
+ tafAction = _ref2.tafAction,
254
+ _ref2$canBe = _ref2.canBe,
255
+ canBe = _ref2$canBe === void 0 ? [] : _ref2$canBe,
256
+ onTafEditModeButtonPress = _ref2.onTafEditModeButtonPress,
257
+ onTafViewModeButtonPress = _ref2.onTafViewModeButtonPress;
258
+ return /*#__PURE__*/React__default.createElement(Grid, {
259
+ container: true,
260
+ justifyContent: "flex-end",
261
+ sx: buttonsStyle,
262
+ columns: 24
263
+ }, /*#__PURE__*/React__default.createElement(Grid, {
264
+ item: true,
265
+ container: true,
266
+ justifyContent: "flex-end",
267
+ columns: 24,
268
+ xs: 24,
269
+ sm: 23
270
+ }, isFormDisabled ? /*#__PURE__*/React__default.createElement(ViewModeButtons, {
271
+ canBe: canBe,
272
+ onTafViewModeButtonPress: onTafViewModeButtonPress
273
+ }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
274
+ "data-testid": "cleartaf",
275
+ variant: "tertiary",
276
+ onClick: function onClick() {
277
+ // Simply discard the changes and close the dialog.
278
+ onTafEditModeButtonPress('CLEAR');
279
+ }
280
+ }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
281
+ "data-testid": "savedrafttaf",
282
+ variant: "tertiary",
283
+ onClick: function onClick() {
284
+ /* Save the TAF as draft:
285
+ if action NEW or DRAFT - new status will be DRAFT -- default
286
+ if action AMEND - new status will be DRAFT_AMENDED
287
+ if action CORRECT - new status will be DRAFT_CORRECTED
288
+ if action DRAFT_AMEND - new status will be DRAFT_AMENDED
289
+ if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
290
+ */
291
+ onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
292
+ }
293
+ }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
294
+ "data-testid": "publishtaf",
295
+ variant: "tertiary",
296
+ onClick: function onClick() {
297
+ /* Publish the TAF:
298
+ if action NEW or DRAFT - new status will be PUBLISHED -- default
299
+ if action AMEND - new status will be AMENDED
300
+ if action CORRECT - new status will be CORRECTED
301
+ if action DRAFT_AMEND - new status will be AMENDED
302
+ if action DRAFT_CORRECT - new status will be CORRECTED
303
+ */
304
+ onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
305
+ }
306
+ }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
307
+ item: true,
308
+ columns: 24,
309
+ sm: 1
310
+ }));
311
+ };
312
+
313
+ /* *
314
+ * Licensed under the Apache License, Version 2.0 (the "License");
315
+ * you may not use this file except in compliance with the License.
316
+ * You may obtain a copy of the License at
317
+ *
318
+ * http://www.apache.org/licenses/LICENSE-2.0
319
+ *
320
+ * Unless required by applicable law or agreed to in writing, software
321
+ * distributed under the License is distributed on an "AS IS" BASIS,
322
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
323
+ * See the License for the specific language governing permissions and
324
+ * limitations under the License.
325
+ *
326
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
327
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
328
+ * */
329
+ var prependZeroes = function prependZeroes(value, totalDigits) {
330
+ var valueAsString = value.toString();
331
+ return _toConsumableArray(Array(totalDigits - valueAsString.length)).reduce(function (newVal) {
332
+ return "0".concat(newVal);
333
+ }, valueAsString);
334
+ };
335
+ var getFieldValue = function getFieldValue(fieldValue) {
336
+ return fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.trim().toUpperCase();
337
+ };
338
+
339
+ /* *
340
+ * Licensed under the Apache License, Version 2.0 (the "License");
341
+ * you may not use this file except in compliance with the License.
342
+ * You may obtain a copy of the License at
343
+ *
344
+ * http://www.apache.org/licenses/LICENSE-2.0
345
+ *
346
+ * Unless required by applicable law or agreed to in writing, software
347
+ * distributed under the License is distributed on an "AS IS" BASIS,
348
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
349
+ * See the License for the specific language governing permissions and
350
+ * limitations under the License.
351
+ *
352
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
353
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
354
+ * */
176
355
  var FORMAT_DAYS_HOURS = 'DDHH';
177
356
  var FORMAT_DAYS_HOURS_MINUTES = 'DDHHmm'; // formatters
178
357
 
@@ -305,7 +484,7 @@ var validateIsValidDates = function validateIsValidDates(value, tafStart, tafEnd
305
484
 
306
485
 
307
486
  var validateValidField = function validateValidField(value, tafStart, tafEnd) {
308
- var trimmedValue = value.trim();
487
+ var trimmedValue = getFieldValue(value);
309
488
 
310
489
  if (!trimmedValue.length) {
311
490
  return true;
@@ -328,9 +507,9 @@ var validateValidField = function validateValidField(value, tafStart, tafEnd) {
328
507
  return true;
329
508
  };
330
509
  var validateValidChangeGroupInterField = function validateValidChangeGroupInterField(value, valueChange, valueProb, tafStart, tafEnd) {
331
- var trimmedValue = value.trim();
332
- var trimmedValueChange = valueChange.trim();
333
- var trimmedValueProb = valueProb.trim();
510
+ var trimmedValue = getFieldValue(value);
511
+ var trimmedValueChange = getFieldValue(valueChange);
512
+ var trimmedValueProb = getFieldValue(valueProb);
334
513
 
335
514
  if (!trimmedValue.length) {
336
515
  return true;
@@ -380,16 +559,12 @@ var invalidPreviousChangeGroupOrderMessage = "When valid times are equal, the ch
380
559
  var invalidPreviousChangeGroupHasSameValue = "When valid times are equal, probability/change can't have the same value as previous row value";
381
560
  var validatePreviousChangeGroup = function validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, tafStart, tafEnd) {
382
561
  // extract the needed values from changeGroups
383
- var valid = currentChangeGroup.valid,
384
- _currentChangeGroup$c = currentChangeGroup.change,
385
- change = _currentChangeGroup$c === void 0 ? '' : _currentChangeGroup$c,
386
- _currentChangeGroup$p = currentChangeGroup.probability,
387
- probability = _currentChangeGroup$p === void 0 ? '' : _currentChangeGroup$p;
388
- var previousValid = previousChangeGroup.valid,
389
- _previousChangeGroup$ = previousChangeGroup.change,
390
- previousChange = _previousChangeGroup$ === void 0 ? '' : _previousChangeGroup$,
391
- _previousChangeGroup$2 = previousChangeGroup.probability,
392
- previousProbability = _previousChangeGroup$2 === void 0 ? '' : _previousChangeGroup$2; // get the parsed values
562
+ var valid = getFieldValue(currentChangeGroup.valid);
563
+ var change = getFieldValue(currentChangeGroup.change || '');
564
+ var probability = getFieldValue(currentChangeGroup.probability || '');
565
+ var previousValid = getFieldValue(previousChangeGroup.valid);
566
+ var previousChange = getFieldValue(previousChangeGroup.change || '');
567
+ var previousProbability = getFieldValue(previousChangeGroup.probability || ''); // get the parsed values
393
568
 
394
569
  var validValue = parseValidToObject(valid, tafStart, tafEnd);
395
570
  var previousValidValue = parseValidToObject(previousValid, tafStart, tafEnd);
@@ -426,12 +601,12 @@ var validatePreviousChangeGroup = function validatePreviousChangeGroup(currentCh
426
601
  }; // validate overlapping validity when one of the following changegroups is FM
427
602
 
428
603
  var validateOverlapWithFM = function validateOverlapWithFM(currentChangeGroup, nextChangeGroups, tafStart, tafEnd) {
429
- var valid = currentChangeGroup.valid;
604
+ var valid = getFieldValue(currentChangeGroup.valid);
430
605
  if (!valid || !nextChangeGroups.length) return true;
431
606
  var validValue = parseValidToObject(valid, tafStart, tafEnd);
432
607
  var currentRowEndTime = moment(validValue.end);
433
608
  var firstFMChangeGroup = nextChangeGroups.find(function (nextChangeGroup) {
434
- return nextChangeGroup.change.trim() === 'FM';
609
+ return getFieldValue(nextChangeGroup.change) === 'FM';
435
610
  });
436
611
 
437
612
  if (firstFMChangeGroup && firstFMChangeGroup.valid) {
@@ -446,29 +621,6 @@ var validateOverlapWithFM = function validateOverlapWithFM(currentChangeGroup, n
446
621
  return true;
447
622
  };
448
623
 
449
- /* *
450
- * Licensed under the Apache License, Version 2.0 (the "License");
451
- * you may not use this file except in compliance with the License.
452
- * You may obtain a copy of the License at
453
- *
454
- * http://www.apache.org/licenses/LICENSE-2.0
455
- *
456
- * Unless required by applicable law or agreed to in writing, software
457
- * distributed under the License is distributed on an "AS IS" BASIS,
458
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
459
- * See the License for the specific language governing permissions and
460
- * limitations under the License.
461
- *
462
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
463
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
464
- * */
465
- var prependZeroes = function prependZeroes(value, totalDigits) {
466
- var valueAsString = value.toString();
467
- return _toConsumableArray(Array(totalDigits - valueAsString.length)).reduce(function (newVal) {
468
- return "0".concat(newVal);
469
- }, valueAsString);
470
- };
471
-
472
624
  var config$1 = [{
473
625
  key: 'range',
474
626
  size: 4
@@ -498,7 +650,7 @@ var formatVisibilityToString = function formatVisibilityToString(value) {
498
650
  // returns object with validity if passed numbers - returns object with cavOK: true if passed CAVOK
499
651
 
500
652
  var parseVisibilityToObject = function parseVisibilityToObject(value) {
501
- var trimmedValue = value.trim();
653
+ var trimmedValue = getFieldValue(value);
502
654
 
503
655
  if (trimmedValue === 'CAVOK') {
504
656
  return {
@@ -546,7 +698,7 @@ var validateRange = function validateRange(value) {
546
698
 
547
699
 
548
700
  var validateVisibilityField = function validateVisibilityField(value) {
549
- var trimmedValue = value.trim();
701
+ var trimmedValue = getFieldValue(value);
550
702
 
551
703
  if (!trimmedValue.length) {
552
704
  return true;
@@ -559,7 +711,7 @@ var validateVisibilityField = function validateVisibilityField(value) {
559
711
 
560
712
 
561
713
  if (!trimmedValue.match(/^[0-9]+$/)) {
562
- return value === 'CAVOK' || invalidVisibilityMessage;
714
+ return trimmedValue === 'CAVOK' || invalidVisibilityMessage;
563
715
  } // validate range
564
716
 
565
717
 
@@ -1025,9 +1177,10 @@ var invalidWeatherBRVisibility = 'Invalid weather input, weather code BR needs t
1025
1177
  var invalidWeatherFGVisibility = 'Invalid weather input, weather code FG needs to be combined with a visibility below 1000m'; // validations
1026
1178
 
1027
1179
  var WeatherVisibilityBelow5000 = [WeatherPhenomena.FU, WeatherPhenomena.DU, WeatherPhenomena.HZ, WeatherPhenomena.DRDU, WeatherPhenomena.BLDU];
1028
- var validateWeatherField = function validateWeatherField(value, visibilityValue) {
1180
+ var validateWeatherField = function validateWeatherField(value, visibilityFieldValue) {
1029
1181
  var NSWAllowed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
1030
- var trimmedValue = value.trim(); // if empty, validate as true
1182
+ var trimmedValue = getFieldValue(value);
1183
+ var visibilityValue = getFieldValue(visibilityFieldValue); // if empty, validate as true
1031
1184
 
1032
1185
  if (trimmedValue === '') {
1033
1186
  return true;
@@ -1066,14 +1219,15 @@ var validateWeatherField = function validateWeatherField(value, visibilityValue)
1066
1219
 
1067
1220
  return true;
1068
1221
  };
1069
- var validateSecondWeatherField = function validateSecondWeatherField(weather1Value, weather2Value, visibilityValue) {
1070
- var trimmedWeather2Value = weather2Value.trim(); // Field can be left empty
1222
+ var validateSecondWeatherField = function validateSecondWeatherField(weather1Value, weather2Value, visibilityFieldValue) {
1223
+ var trimmedWeather2Value = getFieldValue(weather2Value);
1224
+ var visibilityValue = getFieldValue(visibilityFieldValue); // Field can be left empty
1071
1225
 
1072
1226
  if (!trimmedWeather2Value.length) {
1073
1227
  return true;
1074
1228
  }
1075
1229
 
1076
- var trimmedWeather1Value = weather1Value.trim(); // If weather1 is NSW weather2 should be empty
1230
+ var trimmedWeather1Value = getFieldValue(weather1Value); // If weather1 is NSW weather2 should be empty
1077
1231
 
1078
1232
  if (trimmedWeather1Value === 'NSW' && trimmedWeather2Value !== '') {
1079
1233
  return invalidWeatherNonEmptyNSWGroups;
@@ -1091,15 +1245,16 @@ var validateSecondWeatherField = function validateSecondWeatherField(weather1Val
1091
1245
 
1092
1246
  return validateWeatherField(weather2Value, visibilityValue, false);
1093
1247
  };
1094
- var validateThirdWeatherField = function validateThirdWeatherField(weather1Value, weather2Value, weather3Value, visibilityValue) {
1095
- var trimmedWeather3Value = weather3Value.trim(); // Field can be left empty
1248
+ var validateThirdWeatherField = function validateThirdWeatherField(weather1Value, weather2Value, weather3Value, visibilityFieldValue) {
1249
+ var trimmedWeather3Value = getFieldValue(weather3Value);
1250
+ var visibilityValue = getFieldValue(visibilityFieldValue); // Field can be left empty
1096
1251
 
1097
1252
  if (!trimmedWeather3Value.length) {
1098
1253
  return true;
1099
1254
  }
1100
1255
 
1101
- var trimmedWeather1Value = weather1Value.trim();
1102
- var trimmedWeather2Value = weather2Value.trim(); // If weather1 is NSW weather3 should be empty
1256
+ var trimmedWeather1Value = getFieldValue(weather1Value);
1257
+ var trimmedWeather2Value = getFieldValue(weather2Value); // If weather1 is NSW weather3 should be empty
1103
1258
 
1104
1259
  if (trimmedWeather1Value === 'NSW' && trimmedWeather3Value !== '') {
1105
1260
  return invalidWeatherNonEmptyNSWGroups;
@@ -1462,10 +1617,10 @@ var validateWindInterSection = function validateWindInterSection(speed, gust, di
1462
1617
 
1463
1618
 
1464
1619
  var validateWindField = function validateWindField(value, weatherfield1, weatherfield2, weatherfield3) {
1465
- var trimmedWindValue = value.trim();
1466
- var trimmedWeather1Value = weatherfield1.trim();
1467
- var trimmedWeather2Value = weatherfield2.trim();
1468
- var trimmedWeather3Value = weatherfield3.trim();
1620
+ var trimmedWindValue = getFieldValue(value);
1621
+ var trimmedWeather1Value = getFieldValue(weatherfield1);
1622
+ var trimmedWeather2Value = getFieldValue(weatherfield2);
1623
+ var trimmedWeather3Value = getFieldValue(weatherfield3);
1469
1624
 
1470
1625
  if (!trimmedWindValue.length) {
1471
1626
  return true;
@@ -1732,11 +1887,11 @@ var sharedCloudValidations = function sharedCloudValidations(_ref) {
1732
1887
  };
1733
1888
 
1734
1889
  var validateFirstCloud = function validateFirstCloud(value, visibilityValue, weatherfield1, weatherfield2, weatherfield3) {
1735
- var trimmedValueFirstCloud = value.trim();
1736
- var trimmedValueVisibility = visibilityValue.trim();
1737
- var trimmedWeather1Value = weatherfield1.trim();
1738
- var trimmedWeather2Value = weatherfield2.trim();
1739
- var trimmedWeather3Value = weatherfield3.trim(); // Field can be left empty
1890
+ var trimmedValueFirstCloud = getFieldValue(value);
1891
+ var trimmedValueVisibility = getFieldValue(visibilityValue);
1892
+ var trimmedWeather1Value = getFieldValue(weatherfield1);
1893
+ var trimmedWeather2Value = getFieldValue(weatherfield2);
1894
+ var trimmedWeather3Value = getFieldValue(weatherfield3); // Field can be left empty
1740
1895
 
1741
1896
  if (!trimmedValueFirstCloud.length) {
1742
1897
  return true;
@@ -1772,9 +1927,10 @@ var validateFirstCloud = function validateFirstCloud(value, visibilityValue, wea
1772
1927
 
1773
1928
  return errorMessages.length ? errorMessages[0] : true;
1774
1929
  };
1775
- var validateSecondCloud = function validateSecondCloud(firstCloudValue, secondCloudValue, visibilityValue) {
1776
- var trimmedValueFirstCloud = firstCloudValue.trim();
1777
- var trimmedValueSecondCloud = secondCloudValue.trim(); // Field can be left empty
1930
+ var validateSecondCloud = function validateSecondCloud(firstCloudValue, secondCloudValue, visibilityFieldValue) {
1931
+ var trimmedValueFirstCloud = getFieldValue(firstCloudValue);
1932
+ var trimmedValueSecondCloud = getFieldValue(secondCloudValue);
1933
+ var visibilityValue = getFieldValue(visibilityFieldValue); // Field can be left empty
1778
1934
 
1779
1935
  if (!trimmedValueSecondCloud.length) {
1780
1936
  return true;
@@ -1841,10 +1997,11 @@ var validateSecondCloud = function validateSecondCloud(firstCloudValue, secondCl
1841
1997
 
1842
1998
  return true;
1843
1999
  };
1844
- var validateThirdCloud = function validateThirdCloud(firstCloudValue, secondCloudValue, thirdCloudValue, visibilityValue) {
1845
- var trimmedValueFirstCloud = firstCloudValue.trim();
1846
- var trimmedValueSecondCloud = secondCloudValue.trim();
1847
- var trimmedValueThirdCloud = thirdCloudValue.trim(); // Field can be left empty
2000
+ var validateThirdCloud = function validateThirdCloud(firstCloudValue, secondCloudValue, thirdCloudValue, visibilityFieldValue) {
2001
+ var trimmedValueFirstCloud = getFieldValue(firstCloudValue);
2002
+ var trimmedValueSecondCloud = getFieldValue(secondCloudValue);
2003
+ var trimmedValueThirdCloud = getFieldValue(thirdCloudValue);
2004
+ var visibilityValue = getFieldValue(visibilityFieldValue); // Field can be left empty
1848
2005
 
1849
2006
  if (!trimmedValueThirdCloud.length) {
1850
2007
  return true;
@@ -1919,11 +2076,12 @@ var validateThirdCloud = function validateThirdCloud(firstCloudValue, secondClou
1919
2076
 
1920
2077
  return true;
1921
2078
  };
1922
- var validateFourthCloud = function validateFourthCloud(firstCloudValue, secondCloudValue, thirdCloudValue, fourthCloudValue, visibilityValue) {
1923
- var trimmedValueFirstCloud = firstCloudValue.trim();
1924
- var trimmedValueSecondCloud = secondCloudValue.trim();
1925
- var trimmedValueThirdCloud = thirdCloudValue.trim();
1926
- var trimmedValueFourthCloud = fourthCloudValue.trim(); // Field can be left empty
2079
+ var validateFourthCloud = function validateFourthCloud(firstCloudValue, secondCloudValue, thirdCloudValue, fourthCloudValue, visibilityFieldValue) {
2080
+ var trimmedValueFirstCloud = getFieldValue(firstCloudValue);
2081
+ var trimmedValueSecondCloud = getFieldValue(secondCloudValue);
2082
+ var trimmedValueThirdCloud = getFieldValue(thirdCloudValue);
2083
+ var trimmedValueFourthCloud = getFieldValue(fourthCloudValue);
2084
+ var visibilityValue = getFieldValue(visibilityFieldValue); // Field can be left empty
1927
2085
 
1928
2086
  if (!trimmedValueFourthCloud.length) {
1929
2087
  return true;
@@ -2431,7 +2589,8 @@ var getConfirmationDialogTitle = function getConfirmationDialogTitle(action) {
2431
2589
  }; // Check if the amended/corrected TAF has been changed. Only compare the fields users are able to fill in
2432
2590
  // (i.e. exclude baseforecast valid time as that gets updated when doing an amendment automatically outside of the users influence)
2433
2591
 
2434
- var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormDirty, originalTaf, currentTaf) {
2592
+ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(originalTaf, currentTaf) {
2593
+ if (originalTaf === null || currentTaf === null) return false;
2435
2594
  var originalBaseF = originalTaf.baseForecast,
2436
2595
  originalChG = originalTaf.changeGroups;
2437
2596
  var currentBaseF = currentTaf.baseForecast,
@@ -2443,7 +2602,7 @@ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormD
2443
2602
  currentBaseF.valid;
2444
2603
  var currentNoValid = __rest(currentBaseF, ["valid"]);
2445
2604
 
2446
- return isFormDirty && (!isEqual(originalNoValid, currentNoValid) || !isEqual(originalChG, currentChG));
2605
+ return !isEqual(originalNoValid, currentNoValid) || !isEqual(originalChG, currentChG);
2447
2606
  };
2448
2607
  var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
2449
2608
  switch (action) {
@@ -2495,13 +2654,30 @@ var emptyChangegroup = {
2495
2654
  change: '',
2496
2655
  probability: ''
2497
2656
  };
2498
- var getTafStatusLabel = function getTafStatusLabel(status) {
2657
+ var getTafStatusLabel = function getTafStatusLabel(status, action, isFormDisabled) {
2658
+ // See if we need to base status label on action if form is not disabled and action passed
2659
+ var baseOnAction = isFormDisabled !== undefined && !isFormDisabled && action;
2660
+
2661
+ if (baseOnAction && action === 'AMEND' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2662
+ return 'new amendment';
2663
+ }
2664
+
2665
+ if (baseOnAction && action === 'CORRECT' && (status === 'PUBLISHED' || status === 'AMENDED' || status === 'CORRECTED')) {
2666
+ return 'new correction';
2667
+ }
2668
+
2499
2669
  switch (status) {
2500
2670
  case 'DRAFT_AMENDED':
2501
- return 'draft amended';
2671
+ return 'draft amendment';
2502
2672
 
2503
2673
  case 'DRAFT_CORRECTED':
2504
- return 'draft corrected';
2674
+ return 'draft correction';
2675
+
2676
+ case 'AMENDED':
2677
+ return 'published amendment';
2678
+
2679
+ case 'CORRECTED':
2680
+ return 'published correction';
2505
2681
 
2506
2682
  default:
2507
2683
  return status.toLocaleLowerCase();
@@ -2640,193 +2816,18 @@ var fromStatusToAction = function fromStatusToAction(tafStatus) {
2640
2816
  var isFormDirty = function isFormDirty(dirtyFields) {
2641
2817
  return Object.keys(dirtyFields).length > 0;
2642
2818
  };
2819
+ var getFormRowPosition = function getFormRowPosition(formRow) {
2820
+ var _formRow$getBoundingC = formRow.getBoundingClientRect(),
2821
+ top = _formRow$getBoundingC.top,
2822
+ left = _formRow$getBoundingC.left,
2823
+ height = _formRow$getBoundingC.height;
2643
2824
 
2644
- var textFieldStyle = function textFieldStyle(theme) {
2825
+ var newTop = top + height;
2645
2826
  return {
2646
- // input
2647
- marginRight: '2px',
2648
- marginBottom: '4px',
2649
- width: 56,
2650
- height: 46,
2651
- input: {
2652
- textAlign: 'center',
2653
- fontSize: 10,
2654
- fontWeight: 500,
2655
- paddingLeft: 0,
2656
- paddingRight: 0,
2657
- '&.Mui-disabled': {
2658
- color: 'geowebColors.typographyAndIcons.text',
2659
- WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
2660
- },
2661
- // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
2662
- '&:-webkit-autofill': {
2663
- WebkitTransitionDelay: '86400s' // 1 day delay
2664
-
2665
- }
2666
- },
2667
- label: {
2668
- transformOrigin: 'center top',
2669
- right: 0,
2670
- textAlign: 'center',
2671
- fontSize: '10px',
2672
- '&.Mui-disabled': {
2673
- color: 'geowebColors.captions.captionStatus.rgba'
2674
- },
2675
- whiteSpace: 'nowrap',
2676
- maxWidth: '100%',
2677
- transform: 'translate(0px, 16px) scale(1)'
2678
- },
2679
- // shrink
2680
- ' .MuiInputLabel-shrink': {
2681
- transform: 'translate(2px, 10px) scale(0.75) !important',
2682
- letterSpacing: '0.33px',
2683
- textAlign: 'left'
2684
- },
2685
- // root
2686
- '&': {
2687
- '.Mui-error.MuiFilledInput-root': {
2688
- backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
2689
- },
2690
- '.Mui-disabled:before': {
2691
- borderColor: 'transparent'
2692
- }
2693
- }
2694
- };
2695
- };
2696
-
2697
- var getTafErrors = function getTafErrors(name, errors) {
2698
- var nameAsArray = name.split('.');
2699
-
2700
- if (nameAsArray[0].includes('changeGroups')) {
2701
- if (errors.changeGroups) {
2702
- var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
2703
- var restArray = nameAsArray.slice(1);
2704
- return getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
2705
- } // No changegroup errors
2706
-
2707
-
2708
- return null;
2709
- }
2710
-
2711
- return getDeepProperty(nameAsArray, errors);
2712
- };
2713
-
2714
- var getDisplayValue = function getDisplayValue(value, disabled) {
2715
- return disabled && !value ? '-' : value;
2716
- };
2717
- var BaseTextField = /*#__PURE__*/React__default.memo(function (props) {
2718
- return /*#__PURE__*/React__default.createElement(TextField, Object.assign({
2719
- type: "text",
2720
- variant: "filled",
2721
- sx: textFieldStyle
2722
- }, props));
2723
- }, function (prevProps, nextProps) {
2724
- return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
2725
- });
2726
-
2727
- var TafFormTextField = function TafFormTextField(_ref) {
2728
- var label = _ref.label,
2729
- _ref$disabled = _ref.disabled,
2730
- disabled = _ref$disabled === void 0 ? false : _ref$disabled,
2731
- _ref$name = _ref.name,
2732
- name = _ref$name === void 0 ? '' : _ref$name,
2733
- _ref$onChange = _ref.onChange,
2734
- onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
2735
- _ref$onBlur = _ref.onBlur,
2736
- onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
2737
- _ref$defaultValue = _ref.defaultValue,
2738
- defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
2739
- _ref$formatter = _ref.formatter,
2740
- formatter = _ref$formatter === void 0 ? null : _ref$formatter,
2741
- rules = _ref.rules,
2742
- _ref$autoComplete = _ref.autoComplete,
2743
- autoComplete = _ref$autoComplete === void 0 ? [] : _ref$autoComplete,
2744
- _ref$autoFocus = _ref.autoFocus,
2745
- autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus;
2746
-
2747
- var _useFormContext = useFormContext(),
2748
- control = _useFormContext.control,
2749
- setValue = _useFormContext.setValue,
2750
- errors = _useFormContext.formState.errors;
2751
-
2752
- var fieldErrors = getTafErrors(name, errors);
2753
-
2754
- var _React$useState = React__default.useState(null),
2755
- _React$useState2 = _slicedToArray(_React$useState, 2),
2756
- maxLength = _React$useState2[0],
2757
- setMaxLength = _React$useState2[1];
2758
-
2759
- var onKeyDown = React__default.useCallback(function (event) {
2760
- var target = event.target;
2761
- var currentValue = target.value,
2762
- selectionStart = target.selectionStart,
2763
- selectionEnd = target.selectionEnd;
2764
- var textSelection = currentValue.substring(selectionStart, selectionEnd);
2765
-
2766
- if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
2767
- var pressedKey = event.key.toString().toUpperCase();
2768
- var foundValue = autoComplete.find(function (el) {
2769
- return el.key === pressedKey;
2770
- }) || null;
2771
-
2772
- if (foundValue) {
2773
- setValue(name, foundValue.value, {
2774
- shouldDirty: true
2775
- });
2776
- setMaxLength(foundValue.value.length);
2777
- event.preventDefault();
2778
- }
2779
- }
2780
- }, [name, autoComplete, setValue]);
2781
- var onChangeField = React__default.useCallback(function (event, callback) {
2782
- var valueUppercase = event.currentTarget.value.toUpperCase();
2783
-
2784
- if (autoComplete) {
2785
- var exist = autoComplete.find(function (e) {
2786
- return e.value === valueUppercase;
2787
- });
2788
- var newMaxLength = exist ? valueUppercase.length : null;
2789
- setMaxLength(newMaxLength);
2790
- }
2791
-
2792
- callback(valueUppercase);
2793
- onChange(valueUppercase);
2794
- }, [onChange, autoComplete]);
2795
- var onBlurField = React__default.useCallback(function (callback) {
2796
- callback();
2797
- onBlur();
2798
- }, [onBlur]);
2799
- var hasError = !!fieldErrors;
2800
- return /*#__PURE__*/React__default.createElement(Controller, {
2801
- render: function render(_ref2) {
2802
- var field = _ref2.field;
2803
- var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
2804
- return /*#__PURE__*/React__default.createElement(BaseTextField, {
2805
- label: label,
2806
- disabled: disabled,
2807
- name: name,
2808
- value: displayValue,
2809
- inputRef: field.ref,
2810
- onChange: function onChange(e) {
2811
- return onChangeField(e, field.onChange);
2812
- },
2813
- onKeyDown: onKeyDown,
2814
- error: hasError,
2815
- onBlur: function onBlur() {
2816
- return onBlurField(field.onBlur);
2817
- },
2818
- inputProps: {
2819
- maxLength: maxLength
2820
- },
2821
- autoFocus: autoFocus
2822
- });
2823
- },
2824
- name: name,
2825
- control: control,
2826
- defaultValue: defaultValue,
2827
- rules: rules
2828
- });
2829
- };
2827
+ top: newTop,
2828
+ left: left
2829
+ };
2830
+ };
2830
2831
 
2831
2832
  /* *
2832
2833
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -2844,24 +2845,27 @@ var TafFormTextField = function TafFormTextField(_ref) {
2844
2845
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2845
2846
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
2846
2847
  * */
2847
- // messages
2848
- var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
2849
- var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
2850
-
2851
- var validateChangeField = function validateChangeField(value) {
2852
- var trimmedValue = value.trim();
2853
- var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
2854
- return isValid ? true : invalidChangeMessage;
2855
- };
2856
- var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
2857
- var trimmedProbValue = valueProb.trim();
2858
- var trimmedValue = value.trim();
2859
-
2860
- if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
2861
- return invalidChangeProbCombinationMessage;
2862
- }
2863
2848
 
2864
- return true;
2849
+ var DragHandle = function DragHandle(_ref) {
2850
+ var _ref$isSorting = _ref.isSorting,
2851
+ isSorting = _ref$isSorting === void 0 ? false : _ref$isSorting,
2852
+ _ref$isDisabled = _ref.isDisabled,
2853
+ isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
2854
+ index = _ref.index;
2855
+ return /*#__PURE__*/React__default.createElement(IconButton, {
2856
+ className: "handle",
2857
+ "data-testid": "dragHandle-".concat(index),
2858
+ disableRipple: true,
2859
+ disabled: isDisabled,
2860
+ size: "large",
2861
+ sx: {
2862
+ backgroundColor: 'transparent',
2863
+ '&:hover': {
2864
+ backgroundColor: 'transparent'
2865
+ },
2866
+ cursor: isSorting ? 'grabbing' : 'grab'
2867
+ }
2868
+ }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
2865
2869
  };
2866
2870
 
2867
2871
  /* *
@@ -2877,16 +2881,77 @@ var validateChangeFieldInterField = function validateChangeFieldInterField(value
2877
2881
  * See the License for the specific language governing permissions and
2878
2882
  * limitations under the License.
2879
2883
  *
2880
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2881
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2884
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2885
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
2882
2886
  * */
2883
- // messages
2884
- var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
2887
+ var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
2888
+ return Object.assign(Object.assign({}, error), {
2889
+ isChangeGroup: isChangeGroup,
2890
+ rowIndex: rowIndex
2891
+ });
2892
+ };
2893
+ var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
2894
+ switch (sumOfErrors) {
2895
+ case 0:
2896
+ return '0 issues';
2885
2897
 
2886
- var validateProbabilityField = function validateProbabilityField(value) {
2887
- var trimmedValue = value.trim();
2888
- var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
2889
- return isValid ? true : invalidProbabilityMessage;
2898
+ case 1:
2899
+ return '1 issue';
2900
+
2901
+ default:
2902
+ return "".concat(sumOfErrors, " issues");
2903
+ }
2904
+ };
2905
+ var getErrorValues = function getErrorValues(fieldErrors) {
2906
+ var isChangeGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2907
+ var rowIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
2908
+ if (!fieldErrors) return [];
2909
+ return Object.keys(fieldErrors).reduce(function (list, key) {
2910
+ var error = Object.assign({}, fieldErrors[key]);
2911
+
2912
+ if (error.ref) {
2913
+ return list.concat(getCustomError(error, isChangeGroup, rowIndex));
2914
+ }
2915
+
2916
+ return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
2917
+ }, []);
2918
+ };
2919
+ var filterDuplicateErrors = function filterDuplicateErrors(errors) {
2920
+ return errors.reduce(function (list, error) {
2921
+ // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
2922
+ if (error.type === 'validateRequiredSub') {
2923
+ var exist = list.find(function (e) {
2924
+ return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
2925
+ });
2926
+ return exist ? list : list.concat(error);
2927
+ }
2928
+
2929
+ if (error.type === 'validateRequiredMainOptional') {
2930
+ var _exist = list.find(function (e) {
2931
+ return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
2932
+ });
2933
+
2934
+ return _exist ? list : list.concat(error);
2935
+ }
2936
+
2937
+ return list.concat(error);
2938
+ }, []);
2939
+ };
2940
+ var getErrors = function getErrors(errors) {
2941
+ var errorList = Object.keys(errors).reduce(function (list, key) {
2942
+ var errorValue = errors[key]; // changeGroups
2943
+
2944
+ if (Array.isArray(errorValue)) {
2945
+ var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
2946
+ return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
2947
+ }, []);
2948
+ return list.concat.apply(list, _toConsumableArray(errorValues));
2949
+ } // baseForecast
2950
+
2951
+
2952
+ return list.concat(getErrorValues(errorValue, false, -1));
2953
+ }, []);
2954
+ return errorList;
2890
2955
  };
2891
2956
 
2892
2957
  /* *
@@ -2902,502 +2967,505 @@ var validateProbabilityField = function validateProbabilityField(value) {
2902
2967
  * See the License for the specific language governing permissions and
2903
2968
  * limitations under the License.
2904
2969
  *
2905
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2906
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
2970
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2971
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
2907
2972
  * */
2908
2973
 
2909
- var TafFormOptionsButton = function TafFormOptionsButton(_ref) {
2910
- var isChangeGroup = _ref.isChangeGroup,
2911
- addChangeGroupBelow = _ref.addChangeGroupBelow,
2912
- addChangeGroupAbove = _ref.addChangeGroupAbove,
2913
- removeChangeGroup = _ref.removeChangeGroup,
2914
- clearRow = _ref.clearRow,
2915
- index = _ref.index;
2916
- var insertAbove = {
2917
- text: 'Insert 1 row above',
2918
- icon: /*#__PURE__*/React.createElement(Add, null),
2919
- action: addChangeGroupAbove
2920
- };
2921
- var insertBelow = {
2922
- text: 'Insert 1 row below',
2923
- icon: /*#__PURE__*/React.createElement(Add, null),
2924
- action: addChangeGroupBelow
2925
- };
2926
- var deleteRow = {
2927
- text: 'Delete row',
2928
- icon: /*#__PURE__*/React.createElement(Delete, null),
2929
- action: removeChangeGroup
2930
- };
2931
- var clear = {
2932
- text: 'Clear row',
2933
- icon: /*#__PURE__*/React.createElement(Close, null),
2934
- action: clearRow
2935
- };
2936
- var menuItemsBaseForecast = [insertBelow, clear];
2937
- var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
2938
- return /*#__PURE__*/React.createElement(ToggleMenu, {
2939
- buttonTestId: "tafFormOptions[".concat(index, "]"),
2940
- buttonSx: {
2941
- marginTop: '10px',
2942
- marginLeft: '4px'
2943
- },
2944
- menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
2945
- });
2946
- };
2947
-
2948
- var getDefaultValue = function getDefaultValue(fieldName, data) {
2949
- if (!data) {
2950
- return '';
2951
- }
2952
-
2953
- return getDeepProperty(fieldName.split('.'), data) || '';
2954
- };
2955
-
2956
- var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
2957
- return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
2958
- ];
2959
- };
2960
-
2961
- var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2962
- var isNotRequiredForAction = _a.isNotRequiredForAction,
2963
- _a$isChangeGroup = _a.isChangeGroup,
2964
- isChangeGroup = _a$isChangeGroup === void 0 ? false : _a$isChangeGroup,
2965
- _a$disabled = _a.disabled,
2966
- disabled = _a$disabled === void 0 ? false : _a$disabled,
2967
- _a$index = _a.index,
2968
- index = _a$index === void 0 ? -1 : _a$index,
2969
- onRemoveChangeGroup = _a.onRemoveChangeGroup,
2970
- _a$field = _a.field,
2971
- field = _a$field === void 0 ? null : _a$field,
2972
- _a$dragHandle = _a.dragHandle,
2973
- dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
2974
- onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
2975
- onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
2976
- onClearRow = _a.onClearRow,
2977
- props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
2978
-
2979
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
2980
- var fieldNames = getFieldNames(isChangeGroup, index);
2981
-
2982
- var _useFormContext = useFormContext(),
2983
- getValues = _useFormContext.getValues,
2984
- trigger = _useFormContext.trigger; // cross-field required validation
2985
-
2986
-
2987
- var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
2988
- _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
2989
- mainFields = _getRequiredCrossFiel2[0],
2990
- mainOptionalFields = _getRequiredCrossFiel2[1],
2991
- subFields = _getRequiredCrossFiel2[2];
2992
-
2993
- var hasFieldsValue = function hasFieldsValue(fields) {
2994
- return fields.map(getValues).find(function (field) {
2995
- return !!field;
2996
- });
2997
- }; // Used to validate the required field for change groups: Valid
2974
+ var IssuesButton = function IssuesButton(_ref) {
2975
+ var _ref$errors = _ref.errors,
2976
+ errors = _ref$errors === void 0 ? {} : _ref$errors,
2977
+ _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
2978
+ isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
2979
+ _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
2980
+ setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
2981
+ return null;
2982
+ } : _ref$setIsIssuesPaneO;
2983
+ var errorList = filterDuplicateErrors(getErrors(errors));
2984
+ var totalErrors = errorList.length;
2985
+ var errorStatus = totalErrors > 0 ? 'error' : 'success';
2986
+ var buttonColor = "geowebColors.functional.".concat(errorStatus);
2998
2987
 
2988
+ var toggleIssuesPane = function toggleIssuesPane(newPosition) {
2989
+ return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
2990
+ };
2999
2991
 
3000
- var validateRequiredMain = function validateRequiredMain(value) {
3001
- return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3002
- }; // Used to ensure either probability or change is entered, or both
2992
+ var onClickButton = function onClickButton(event) {
2993
+ var _a;
3003
2994
 
2995
+ var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
2996
+ left = _event$currentTarget$.left,
2997
+ top = _event$currentTarget$.top;
3004
2998
 
3005
- var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3006
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3007
- }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
2999
+ var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3000
+ top: 0,
3001
+ left: 0
3002
+ };
3003
+ var newPosition = {
3004
+ left: left - parentOffset.left + 100,
3005
+ top: top - parentOffset.top
3006
+ };
3007
+ toggleIssuesPane(newPosition);
3008
+ };
3008
3009
 
3010
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3011
+ title: "View details"
3012
+ }, /*#__PURE__*/React.createElement(Chip, {
3013
+ "data-testid": "issuesButton",
3014
+ className: "status-".concat(errorStatus),
3015
+ size: "small",
3016
+ label: getIssuesLabel(totalErrors),
3017
+ onClick: onClickButton,
3018
+ sx: {
3019
+ width: '74px',
3020
+ color: '#ffffff',
3021
+ backgroundColor: buttonColor,
3022
+ '&:hover': {
3023
+ backgroundColor: buttonColor
3024
+ },
3025
+ '&:focus': {
3026
+ backgroundColor: buttonColor
3027
+ },
3028
+ fontSize: 12
3029
+ }
3030
+ }));
3031
+ };
3009
3032
 
3010
- var validateRequiredSub = function validateRequiredSub(value) {
3011
- return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3012
- }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3033
+ var getPaneTitle = function getPaneTitle(sumOfErrors) {
3034
+ switch (sumOfErrors) {
3035
+ case 0:
3036
+ return 'Looks good';
3013
3037
 
3038
+ case 1:
3039
+ return 'There is an issue to address';
3014
3040
 
3015
- var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3016
- var changeField = getValues("".concat(namePrefix, ".change"));
3017
- var visibilityField = getValues("".concat(namePrefix, ".visibility"));
3018
- var isFM = changeField && changeField.trim() === 'FM';
3019
- var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3041
+ default:
3042
+ return 'There are a few issues to address';
3043
+ }
3044
+ };
3020
3045
 
3021
- if (isNotRequiredForAction(value) !== true && !value.length) {
3022
- if (isChangeGroup && isFM || !isChangeGroup) {
3023
- // exception for CavOK
3024
- if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3025
- return true;
3026
- } // exception for visibility > 5000
3046
+ var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3047
+ if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3048
+ // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3049
+ var fieldNumber = fieldNumberedValue + 1;
3050
+ return "".concat(errorTitle, " ").concat(fieldNumber);
3051
+ }
3027
3052
 
3053
+ return errorTitle;
3054
+ };
3055
+ var getErrorMessage = function getErrorMessage(error, index) {
3056
+ var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3057
+ var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3058
+ return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(error.message);
3059
+ };
3060
+ var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3061
+ var useIssuesPane = function useIssuesPane() {
3062
+ var _React$useState = React.useState(false),
3063
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3064
+ isIssuesPaneOpen = _React$useState2[0],
3065
+ setIsIssuesPaneOpen = _React$useState2[1];
3028
3066
 
3029
- if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3030
- return true;
3031
- }
3067
+ var _React$useState3 = React.useState(null),
3068
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3069
+ startPosition = _React$useState4[0],
3070
+ setStartPosition = _React$useState4[1];
3032
3071
 
3033
- return "".concat(fieldName, " is required");
3034
- }
3035
- }
3072
+ var _React$useState5 = React.useState(false),
3073
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
3074
+ hasUserDragged = _React$useState6[0],
3075
+ setHasUserDragged = _React$useState6[1];
3036
3076
 
3037
- return true;
3077
+ var onUserHasDragged = function onUserHasDragged() {
3078
+ return setHasUserDragged(true);
3038
3079
  };
3039
3080
 
3040
- var validatePreviousRow = React__default.useCallback(function () {
3041
- if (isChangeGroup && index > 0) {
3042
- var _getValues = getValues(),
3043
- validDateEnd = _getValues.validDateEnd,
3044
- validDateStart = _getValues.validDateStart,
3045
- changeGroups = _getValues.changeGroups;
3046
-
3047
- var currentChangeGroup = changeGroups[index];
3048
- var previousChangeGroup = changeGroups[index - 1];
3049
- return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3081
+ var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3082
+ if (!hasUserDragged) {
3083
+ setStartPosition(newPosition);
3050
3084
  }
3051
3085
 
3052
- return true;
3053
- }, [index, isChangeGroup, getValues]);
3054
-
3055
- var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3056
- var indexedFieldName = "changeGroups[".concat(rowIndex, "].").concat(fieldname);
3057
- var rowValue = getValues(indexedFieldName);
3058
- return rowValue ? [indexedFieldName] : [];
3086
+ setIsIssuesPaneOpen(isOpen);
3059
3087
  };
3060
3088
 
3061
- var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3062
- return getFieldFromRow('valid', index + 1);
3089
+ var onCloseIssuesPane = function onCloseIssuesPane() {
3090
+ return setIsIssuesPaneOpen(false);
3063
3091
  };
3064
3092
 
3065
- var validateNextRows = React__default.useCallback(function () {
3066
- if (isChangeGroup) {
3067
- var _getValues2 = getValues(),
3068
- validDateEnd = _getValues2.validDateEnd,
3069
- validDateStart = _getValues2.validDateStart,
3070
- changeGroups = _getValues2.changeGroups;
3071
-
3072
- var currentChangeGroup = changeGroups[index];
3073
- var nextChangeGroups = changeGroups.slice(index + 1);
3074
- return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3075
- }
3076
-
3077
- return true;
3078
- }, [index, isChangeGroup, getValues]);
3079
-
3080
- var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3081
- var _getValues3 = getValues(),
3082
- changeGroups = _getValues3.changeGroups;
3083
-
3084
- var previousChangeGroups = changeGroups.slice(0, rowIndex);
3085
- var validFields = previousChangeGroups.map(function (_element, index) {
3086
- return getFieldFromRow('valid', index)[0];
3087
- });
3088
- return validFields;
3093
+ return {
3094
+ isIssuesPaneOpen: isIssuesPaneOpen,
3095
+ startPosition: startPosition,
3096
+ onToggleIssuesPane: onToggleIssuesPane,
3097
+ onCloseIssuesPane: onCloseIssuesPane,
3098
+ onUserHasDragged: onUserHasDragged
3089
3099
  };
3100
+ };
3090
3101
 
3091
- var addChangeGroupBelow = React__default.useCallback(function () {
3092
- onAddChangeGroupBelow(index);
3093
- }, [onAddChangeGroupBelow, index]);
3094
- var addChangeGroupAbove = React__default.useCallback(function () {
3095
- onAddChangeGroupAbove(index);
3096
- }, [onAddChangeGroupAbove, index]);
3097
- var clearRow = React__default.useCallback(function () {
3098
- onClearRow(index);
3099
- }, [onClearRow, index]);
3100
- return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
3101
- sx: {
3102
- marginTop: '8px',
3103
- backgroundColor: 'geowebColors.cards.cardContainer',
3104
- position: 'relative',
3105
- '&.sortable-chosen': {
3106
- boxShadow: 1
3107
- },
3108
- '&.sortable-ghost': {
3109
- opacity: 0.5
3102
+ var IssuesPane = function IssuesPane(_ref) {
3103
+ var _ref$errorList = _ref.errorList,
3104
+ errorList = _ref$errorList === void 0 ? [] : _ref$errorList,
3105
+ isOpen = _ref.isOpen,
3106
+ handleClose = _ref.handleClose,
3107
+ _ref$startPosition = _ref.startPosition,
3108
+ startPosition = _ref$startPosition === void 0 ? {
3109
+ left: 20,
3110
+ top: 50
3111
+ } : _ref$startPosition,
3112
+ _ref$onUserHasDragged = _ref.onUserHasDragged,
3113
+ onUserHasDragged = _ref$onUserHasDragged === void 0 ? function () {} : _ref$onUserHasDragged;
3114
+ var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3115
+ return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3116
+ startSize: {
3117
+ width: '577px',
3118
+ height: '200px'
3119
+ },
3120
+ startPosition: startPosition,
3121
+ minWidth: 300,
3122
+ onClose: handleClose,
3123
+ title: getPaneTitle(errorList.length),
3124
+ headerSize: "xs",
3125
+ isOpen: isOpen,
3126
+ "data-testid": "moveable-issues-pane",
3127
+ bounds: "parent",
3128
+ onDragEnd: function onDragEnd(event) {
3129
+ if (event.x !== 0 && event.y !== 0) {
3130
+ onUserHasDragged();
3110
3131
  }
3132
+ }
3133
+ }, /*#__PURE__*/React.createElement(Box, {
3134
+ component: "div",
3135
+ sx: {
3136
+ marginTop: '16px',
3137
+ marginLeft: '24px'
3138
+ }
3139
+ }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3140
+ component: "div",
3141
+ sx: {
3142
+ fontSize: '4rem'
3111
3143
  },
3112
- justifyContent: "flex-start",
3113
- "data-testid": "row-".concat(namePrefix),
3114
- container: true,
3115
- ref: ref
3116
- }, props), /*#__PURE__*/React__default.createElement(Grid, {
3117
- columns: 24,
3118
- item: true,
3119
- container: true,
3120
- justifyContent: "flex-end",
3121
- xs: 24,
3122
- sm: 23
3123
- }, !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
3124
- label: "Type",
3125
- name: fieldNames.messageType,
3126
- disabled: true
3127
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3128
- label: "Location",
3129
- name: "location",
3130
- disabled: true
3131
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3132
- formatter: formatIssueTime,
3133
- label: "Issue time",
3134
- name: "issueDate",
3135
- disabled: true
3136
- })), isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box, {
3144
+ "data-testid": "zeroIssuesImage"
3145
+ }, /*#__PURE__*/React.createElement(ThumbsUp, {
3137
3146
  sx: {
3138
- width: 56,
3139
- marginRight: '2px'
3147
+ height: '69px',
3148
+ width: '58px'
3140
3149
  }
3141
- }, !disabled && dragHandle), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3142
- label: "Prob",
3143
- name: fieldNames.probability,
3144
- disabled: disabled,
3145
- defaultValue: getDefaultValue('probability', field),
3146
- rules: {
3147
- validate: {
3148
- validateRequiredMainOptional: validateRequiredMainOptional,
3149
- validateProbabilityField: validateProbabilityField
3150
+ })), errorList.length > 0 && errorList.map(function (error, index) {
3151
+ return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3152
+ , {
3153
+ // eslint-disable-next-line react/no-array-index-key
3154
+ key: "message-".concat(index),
3155
+ variant: "body1",
3156
+ "data-testid": "errorMessage"
3157
+ }, getErrorMessage(error, index));
3158
+ }))), rootElement);
3159
+ };
3160
+
3161
+ var TafModuleContext = /*#__PURE__*/React.createContext({
3162
+ onValidateForm: null,
3163
+ registerValidateForm: null,
3164
+ tafAction: null,
3165
+ setTafAction: null,
3166
+ onPreventCloseView: null
3167
+ });
3168
+ var useTafModuleContext = function useTafModuleContext() {
3169
+ return React.useContext(TafModuleContext);
3170
+ };
3171
+ var useTafModuleState = function useTafModuleState(_ref) {
3172
+ var onPreventCloseView = _ref.onPreventCloseView;
3173
+
3174
+ var _React$useState = React.useState(function () {
3175
+ return new Promise(function () {
3176
+ return true;
3177
+ });
3178
+ }),
3179
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3180
+ onValidateForm = _React$useState2[0],
3181
+ registerValidateForm = _React$useState2[1];
3182
+
3183
+ var _React$useState3 = React.useState(),
3184
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3185
+ tafAction = _React$useState4[0],
3186
+ setTafAction = _React$useState4[1];
3187
+
3188
+ var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3189
+ registerValidateForm(function () {
3190
+ return promiseToRegister;
3191
+ });
3192
+ };
3193
+
3194
+ return {
3195
+ onValidateForm: onValidateForm,
3196
+ registerValidateForm: onRegisterValidateForm,
3197
+ tafAction: tafAction,
3198
+ setTafAction: setTafAction,
3199
+ onPreventCloseView: onPreventCloseView
3200
+ };
3201
+ };
3202
+ var TafModuleProvider = function TafModuleProvider(_ref2) {
3203
+ var children = _ref2.children,
3204
+ _ref2$onPreventCloseV = _ref2.onPreventCloseView,
3205
+ onPreventCloseView = _ref2$onPreventCloseV === void 0 ? function () {} : _ref2$onPreventCloseV;
3206
+ var contextState = useTafModuleState({
3207
+ onPreventCloseView: onPreventCloseView
3208
+ });
3209
+ return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3210
+ value: contextState
3211
+ }, children);
3212
+ };
3213
+
3214
+ /* *
3215
+ * Licensed under the Apache License, Version 2.0 (the "License");
3216
+ * you may not use this file except in compliance with the License.
3217
+ * You may obtain a copy of the License at
3218
+ *
3219
+ * http://www.apache.org/licenses/LICENSE-2.0
3220
+ *
3221
+ * Unless required by applicable law or agreed to in writing, software
3222
+ * distributed under the License is distributed on an "AS IS" BASIS,
3223
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3224
+ * See the License for the specific language governing permissions and
3225
+ * limitations under the License.
3226
+ *
3227
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3228
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
3229
+ * */
3230
+ var styles = {
3231
+ label: {
3232
+ color: 'geowebColors.buttons.tertiary.default.color',
3233
+ opacity: 1,
3234
+ fontSize: '12px',
3235
+ fontWeight: 500
3236
+ }
3237
+ };
3238
+
3239
+ var SwitchButton = function SwitchButton(props) {
3240
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3241
+ title: "Switch mode"
3242
+ }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(FormLabel, {
3243
+ sx: styles.label
3244
+ }, "Viewer"), /*#__PURE__*/React.createElement(Switch, Object.assign({
3245
+ "data-testid": "switchMode"
3246
+ }, props)), /*#__PURE__*/React.createElement(FormLabel, {
3247
+ sx: styles.label
3248
+ }, "Editor")));
3249
+ };
3250
+
3251
+ var TafAvatar = function TafAvatar(_ref) {
3252
+ var editor = _ref.editor,
3253
+ _ref$tooltipPlacement = _ref.tooltipPlacement,
3254
+ tooltipPlacement = _ref$tooltipPlacement === void 0 ? 'bottom' : _ref$tooltipPlacement;
3255
+ return /*#__PURE__*/React.createElement(CustomTooltip, {
3256
+ title: "Editor: ".concat(editor),
3257
+ placement: tooltipPlacement
3258
+ }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Avatar, {
3259
+ size: "small"
3260
+ }, getInitials(editor))));
3261
+ };
3262
+
3263
+ var textFieldStyle = function textFieldStyle(theme, shouldPreventUppercase) {
3264
+ return {
3265
+ // input
3266
+ marginRight: '2px',
3267
+ marginBottom: '4px',
3268
+ width: 56,
3269
+ height: 46,
3270
+ input: {
3271
+ textAlign: 'center',
3272
+ textTransform: shouldPreventUppercase ? 'none' : 'uppercase',
3273
+ fontSize: 10,
3274
+ fontWeight: 500,
3275
+ paddingLeft: 0,
3276
+ paddingRight: 0,
3277
+ '&.Mui-disabled': {
3278
+ color: 'geowebColors.typographyAndIcons.text',
3279
+ WebkitTextFillColor: theme.palette.geowebColors.typographyAndIcons.text
3280
+ },
3281
+ // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/1995 disables the default autofill styling, should be a better fix
3282
+ '&:-webkit-autofill': {
3283
+ WebkitTransitionDelay: '86400s' // 1 day delay
3284
+
3150
3285
  }
3151
3286
  },
3152
- autoComplete: [{
3153
- key: '3',
3154
- value: 'PROB30'
3155
- }, {
3156
- key: '4',
3157
- value: 'PROB40'
3158
- }],
3159
- onBlur: function onBlur() {
3160
- if (isChangeGroup) {
3161
- var nextValidFieldName = getValidFieldFromNextRow();
3162
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
3287
+ label: {
3288
+ transformOrigin: 'center top',
3289
+ right: 0,
3290
+ textAlign: 'center',
3291
+ fontSize: '10px',
3292
+ '&.Mui-disabled': {
3293
+ color: 'geowebColors.captions.captionStatus.rgba'
3294
+ },
3295
+ whiteSpace: 'nowrap',
3296
+ maxWidth: '100%',
3297
+ transform: 'translate(0px, 16px) scale(1)'
3298
+ },
3299
+ // shrink
3300
+ ' .MuiInputLabel-shrink': {
3301
+ transform: 'translate(2px, 10px) scale(0.75) !important',
3302
+ letterSpacing: '0.33px',
3303
+ textAlign: 'left'
3304
+ },
3305
+ // root
3306
+ '&': {
3307
+ '.Mui-error.MuiFilledInput-root': {
3308
+ backgroundColor: 'geowebColors.captions.captionErrorBackground.rgba'
3309
+ },
3310
+ '.Mui-disabled:before': {
3311
+ borderColor: 'transparent'
3163
3312
  }
3164
3313
  }
3165
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3166
- label: "Change",
3167
- name: fieldNames.change,
3168
- disabled: disabled,
3169
- defaultValue: getDefaultValue('change', field),
3170
- rules: {
3171
- validate: {
3172
- validateRequiredMainOptional: validateRequiredMainOptional,
3173
- validateChangeField: validateChangeField,
3174
- validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3175
- return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3176
- }
3177
- }
3178
- },
3179
- autoComplete: [{
3180
- key: 'T',
3181
- value: 'TEMPO'
3182
- }, {
3183
- key: 'B',
3184
- value: 'BECMG'
3185
- }, {
3186
- key: 'F',
3187
- value: 'FM'
3188
- }],
3189
- onBlur: function onBlur() {
3190
- if (isChangeGroup) {
3191
- var nextValidFieldName = getValidFieldFromNextRow();
3192
- var previousValidFieldNames = getPreviousValidFields(index);
3193
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3314
+ };
3315
+ };
3316
+
3317
+ var getTafErrors = function getTafErrors(name, errors) {
3318
+ var nameAsArray = name.split('.');
3319
+
3320
+ if (nameAsArray[0].includes('changeGroups')) {
3321
+ if (errors.changeGroups) {
3322
+ var changeGroupNum = nameAsArray[0].slice(13, nameAsArray[0].length - 1);
3323
+ var restArray = nameAsArray.slice(1);
3324
+ return getDeepProperty(restArray, errors.changeGroups[changeGroupNum]);
3325
+ } // No changegroup errors
3326
+
3327
+
3328
+ return null;
3329
+ }
3330
+
3331
+ return getDeepProperty(nameAsArray, errors);
3332
+ };
3333
+
3334
+ var getDisplayValue = function getDisplayValue(value, disabled) {
3335
+ return disabled && !value ? '-' : value;
3336
+ };
3337
+ var BaseTextField = /*#__PURE__*/React__default.memo(function (_a) {
3338
+ var _a$shouldPreventUpper = _a.shouldPreventUppercase,
3339
+ shouldPreventUppercase = _a$shouldPreventUpper === void 0 ? false : _a$shouldPreventUpper,
3340
+ props = __rest(_a, ["shouldPreventUppercase"]);
3341
+
3342
+ var theme = useTheme();
3343
+ var styling = textFieldStyle(theme, shouldPreventUppercase);
3344
+ return /*#__PURE__*/React__default.createElement(TextField, Object.assign({
3345
+ type: "text",
3346
+ variant: "filled",
3347
+ sx: styling
3348
+ }, props));
3349
+ }, function (prevProps, nextProps) {
3350
+ return prevProps.value === nextProps.value && prevProps.error === nextProps.error && prevProps.name === nextProps.name && prevProps.disabled === nextProps.disabled;
3351
+ });
3352
+
3353
+ var TafFormTextField = function TafFormTextField(_ref) {
3354
+ var label = _ref.label,
3355
+ _ref$disabled = _ref.disabled,
3356
+ disabled = _ref$disabled === void 0 ? false : _ref$disabled,
3357
+ _ref$name = _ref.name,
3358
+ name = _ref$name === void 0 ? '' : _ref$name,
3359
+ _ref$onChange = _ref.onChange,
3360
+ onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
3361
+ _ref$onBlur = _ref.onBlur,
3362
+ onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur,
3363
+ _ref$defaultValue = _ref.defaultValue,
3364
+ defaultValue = _ref$defaultValue === void 0 ? '' : _ref$defaultValue,
3365
+ _ref$formatter = _ref.formatter,
3366
+ formatter = _ref$formatter === void 0 ? null : _ref$formatter,
3367
+ rules = _ref.rules,
3368
+ _ref$autoComplete = _ref.autoComplete,
3369
+ autoComplete = _ref$autoComplete === void 0 ? [] : _ref$autoComplete,
3370
+ _ref$autoFocus = _ref.autoFocus,
3371
+ autoFocus = _ref$autoFocus === void 0 ? false : _ref$autoFocus,
3372
+ _ref$shouldPreventUpp = _ref.shouldPreventUppercase,
3373
+ shouldPreventUppercase = _ref$shouldPreventUpp === void 0 ? false : _ref$shouldPreventUpp;
3374
+
3375
+ var _useFormContext = useFormContext(),
3376
+ control = _useFormContext.control,
3377
+ setValue = _useFormContext.setValue,
3378
+ errors = _useFormContext.formState.errors;
3379
+
3380
+ var fieldErrors = getTafErrors(name, errors);
3381
+
3382
+ var _React$useState = React__default.useState(null),
3383
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3384
+ maxLength = _React$useState2[0],
3385
+ setMaxLength = _React$useState2[1];
3386
+
3387
+ var onKeyDown = React__default.useCallback(function (event) {
3388
+ var target = event.target;
3389
+ var currentValue = target.value,
3390
+ selectionStart = target.selectionStart,
3391
+ selectionEnd = target.selectionEnd;
3392
+ var textSelection = currentValue.substring(selectionStart, selectionEnd);
3393
+
3394
+ if (autoComplete && !currentValue.length || textSelection.length && currentValue.length && textSelection === currentValue) {
3395
+ var pressedKey = event.key.toString().toUpperCase();
3396
+ var foundValue = autoComplete.find(function (el) {
3397
+ return el.key === pressedKey;
3398
+ }) || null;
3399
+
3400
+ if (foundValue) {
3401
+ setValue(name, foundValue.value, {
3402
+ shouldDirty: true
3403
+ });
3404
+ setMaxLength(foundValue.value.length);
3405
+ event.preventDefault();
3194
3406
  }
3195
3407
  }
3196
- })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3197
- label: "Valid",
3198
- name: fieldNames.valid,
3199
- // always disabled for baseforecast row
3200
- disabled: !isChangeGroup ? true : disabled,
3201
- defaultValue: getDefaultValue('valid', field),
3202
- rules: {
3203
- validate: {
3204
- validateRequiredMain: validateRequiredMain,
3205
- validateValidField: function validateValidField$1(value) {
3206
- return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3207
- },
3208
- validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3209
- return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3210
- },
3211
- validatePreviousRow: validatePreviousRow,
3212
- validateNextRows: validateNextRows
3213
- }
3214
- },
3215
- onBlur: function onBlur() {
3216
- if (isChangeGroup) {
3217
- var nextValidFieldName = getValidFieldFromNextRow();
3218
- var previousValidFieldNames = getPreviousValidFields(index);
3219
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3220
- }
3408
+ }, [name, autoComplete, setValue]);
3409
+ var onChangeField = React__default.useCallback(function (event, callback) {
3410
+ var value = event.currentTarget.value;
3411
+
3412
+ if (autoComplete) {
3413
+ var valueUppercase = value.toUpperCase();
3414
+ var exist = autoComplete.find(function (e) {
3415
+ return e.value === valueUppercase;
3416
+ });
3417
+ var newMaxLength = exist ? valueUppercase.length : null;
3418
+ setMaxLength(newMaxLength);
3221
3419
  }
3222
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3223
- label: "Wind",
3224
- name: fieldNames.wind,
3225
- disabled: disabled,
3226
- defaultValue: getDefaultValue('wind', field),
3227
- rules: {
3228
- validate: {
3229
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3230
- return _validateRequiredMainFields(value, 'Wind');
3420
+
3421
+ callback(value);
3422
+ onChange(value);
3423
+ }, [onChange, autoComplete]);
3424
+ var onBlurField = React__default.useCallback(function (event, callback) {
3425
+ var value = event.target.value;
3426
+ var valueUppercase = value.toUpperCase();
3427
+
3428
+ if (value !== valueUppercase && !shouldPreventUppercase) {
3429
+ setValue(name, valueUppercase, {
3430
+ shouldValidate: true
3431
+ });
3432
+ }
3433
+
3434
+ callback();
3435
+ onBlur();
3436
+ }, [onBlur, name, setValue, shouldPreventUppercase]);
3437
+ var hasError = !!fieldErrors;
3438
+ return /*#__PURE__*/React__default.createElement(Controller, {
3439
+ render: function render(_ref2) {
3440
+ var field = _ref2.field;
3441
+ var displayValue = formatter ? formatter(field.value) : getDisplayValue(field.value, disabled);
3442
+ return /*#__PURE__*/React__default.createElement(BaseTextField, {
3443
+ label: label,
3444
+ disabled: disabled,
3445
+ name: name,
3446
+ value: displayValue,
3447
+ inputRef: field.ref,
3448
+ onChange: function onChange(event) {
3449
+ return onChangeField(event, field.onChange);
3231
3450
  },
3232
- validateRequiredSub: validateRequiredSub,
3233
- validateWindField: function validateWindField$1(value) {
3234
- return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3235
- }
3236
- }
3237
- },
3238
- onBlur: function onBlur() {
3239
- if (isChangeGroup) {
3240
- trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
3241
- }
3242
- },
3243
- autoFocus: !isChangeGroup
3244
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3245
- label: "Visibility",
3246
- name: fieldNames.visibility,
3247
- disabled: disabled,
3248
- defaultValue: getDefaultValue('visibility', field),
3249
- rules: {
3250
- validate: {
3251
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3252
- return _validateRequiredMainFields(value, 'Visibility');
3451
+ onKeyDown: onKeyDown,
3452
+ error: hasError,
3453
+ onBlur: function onBlur(event) {
3454
+ return onBlurField(event, field.onBlur);
3253
3455
  },
3254
- validateRequiredSub: validateRequiredSub,
3255
- validateVisibilityField: validateVisibilityField
3256
- }
3257
- },
3258
- autoComplete: [{
3259
- key: 'C',
3260
- value: 'CAVOK'
3261
- }],
3262
- onBlur: function onBlur() {
3263
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3264
- trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3265
- }
3266
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3267
- label: "Weather",
3268
- name: fieldNames.weather1,
3269
- disabled: disabled,
3270
- defaultValue: getDefaultValue('weather.weather1', field),
3271
- rules: {
3272
- validate: {
3273
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3274
- return _validateRequiredMainFields(value, 'Weather');
3456
+ inputProps: {
3457
+ maxLength: maxLength
3275
3458
  },
3276
- validateRequiredSub: validateRequiredSub,
3277
- validateWeatherField: function validateWeatherField$1(value) {
3278
- return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3279
- }
3280
- }
3281
- },
3282
- onBlur: function onBlur() {
3283
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3284
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3285
- }
3286
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3287
- label: "Weather",
3288
- name: fieldNames.weather2,
3289
- disabled: disabled,
3290
- defaultValue: getDefaultValue('weather.weather2', field),
3291
- rules: {
3292
- validate: {
3293
- validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3294
- return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3295
- }
3296
- }
3297
- },
3298
- onBlur: function onBlur() {
3299
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3300
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3301
- }
3302
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3303
- label: "Weather",
3304
- name: fieldNames.weather3,
3305
- disabled: disabled,
3306
- defaultValue: getDefaultValue('weather.weather3', field),
3307
- rules: {
3308
- validate: {
3309
- validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3310
- return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3311
- }
3312
- }
3459
+ autoFocus: autoFocus,
3460
+ shouldPreventUppercase: shouldPreventUppercase
3461
+ });
3313
3462
  },
3314
- onBlur: function onBlur() {
3315
- return trigger([fieldNames.wind, fieldNames.cloud1]);
3316
- }
3317
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3318
- label: "Cloud",
3319
- name: fieldNames.cloud1,
3320
- disabled: disabled,
3321
- defaultValue: getDefaultValue('cloud.cloud1', field),
3322
- rules: {
3323
- validate: {
3324
- validateRequiredMainFields: function validateRequiredMainFields(value) {
3325
- return _validateRequiredMainFields(value, 'Clouds');
3326
- },
3327
- validateRequiredSub: validateRequiredSub,
3328
- validateFirstCloud: function validateFirstCloud$1(value) {
3329
- return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3330
- }
3331
- }
3332
- },
3333
- onBlur: function onBlur() {
3334
- var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3335
- return trigger([].concat(_toConsumableArray(fields), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3336
- }
3337
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3338
- label: "Cloud",
3339
- name: fieldNames.cloud2,
3340
- disabled: disabled,
3341
- defaultValue: getDefaultValue('cloud.cloud2', field),
3342
- rules: {
3343
- validate: {
3344
- validateSecondCloud: function validateSecondCloud$1(value) {
3345
- return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3346
- }
3347
- }
3348
- },
3349
- onBlur: function onBlur() {
3350
- return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3351
- }
3352
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3353
- label: "Cloud",
3354
- name: fieldNames.cloud3,
3355
- disabled: disabled,
3356
- defaultValue: getDefaultValue('cloud.cloud3', field),
3357
- rules: {
3358
- validate: {
3359
- validateThirdCloud: function validateThirdCloud$1(value) {
3360
- return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
3361
- }
3362
- }
3363
- },
3364
- onBlur: function onBlur() {
3365
- return trigger(fieldNames.cloud4);
3366
- }
3367
- }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3368
- label: "Cloud",
3369
- name: fieldNames.cloud4,
3370
- disabled: disabled,
3371
- defaultValue: getDefaultValue('cloud.cloud4', field),
3372
- rules: {
3373
- validate: {
3374
- validateFourthCloud: function validateFourthCloud$1(value) {
3375
- return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
3376
- }
3377
- }
3378
- }
3379
- })), !disabled && /*#__PURE__*/React__default.createElement(Grid, {
3380
- item: true,
3381
- container: true,
3382
- justifyContent: "flex-end",
3383
- alignItems: "flex-end",
3384
- xs: 24,
3385
- sm: 1,
3386
- sx: {
3387
- marginBottom: '16px'
3388
- },
3389
- columns: 24
3390
- }, /*#__PURE__*/React__default.createElement(TafFormOptionsButton, {
3391
- isChangeGroup: isChangeGroup,
3392
- addChangeGroupBelow: addChangeGroupBelow,
3393
- addChangeGroupAbove: addChangeGroupAbove,
3394
- removeChangeGroup: function removeChangeGroup() {
3395
- return onRemoveChangeGroup(index);
3396
- },
3397
- clearRow: clearRow,
3398
- index: index
3399
- })));
3400
- });
3463
+ name: name,
3464
+ control: control,
3465
+ defaultValue: defaultValue,
3466
+ rules: rules
3467
+ });
3468
+ };
3401
3469
 
3402
3470
  /* *
3403
3471
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -3412,143 +3480,27 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3412
3480
  * See the License for the specific language governing permissions and
3413
3481
  * limitations under the License.
3414
3482
  *
3415
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3416
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3483
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3484
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3417
3485
  * */
3418
- var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3419
- switch (tafAction) {
3420
- case 'AMEND':
3421
- case 'DRAFT_AMEND':
3422
- return 'DRAFT_AMEND';
3423
-
3424
- case 'CORRECT':
3425
- case 'DRAFT_CORRECT':
3426
- return 'DRAFT_CORRECT';
3427
-
3428
- default:
3429
- return 'DRAFT';
3430
- }
3431
- };
3432
3486
 
3433
- var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3434
- switch (tafAction) {
3435
- case 'AMEND':
3436
- case 'DRAFT_AMEND':
3437
- return 'AMEND';
3438
-
3439
- case 'CORRECT':
3440
- case 'DRAFT_CORRECT':
3441
- return 'CORRECT';
3487
+ var invalidChangeMessage = 'Invalid Change input, only BECMG, TEMPO or FM are allowed';
3488
+ var invalidChangeProbCombinationMessage = 'A probability is only allowed in combination with TEMPO or an empty Change input'; // validations
3442
3489
 
3443
- default:
3444
- return 'PUBLISH';
3445
- }
3490
+ var validateChangeField = function validateChangeField(value) {
3491
+ var trimmedValue = getFieldValue(value);
3492
+ var isValid = trimmedValue === '' || trimmedValue === 'FM' || trimmedValue === 'TEMPO' || trimmedValue === 'BECMG';
3493
+ return isValid ? true : invalidChangeMessage;
3446
3494
  };
3495
+ var validateChangeFieldInterField = function validateChangeFieldInterField(value, valueProb) {
3496
+ var trimmedProbValue = getFieldValue(valueProb);
3497
+ var trimmedValue = getFieldValue(value);
3447
3498
 
3448
- var buttonsStyle = {
3449
- button: {
3450
- minWidth: {
3451
- xs: '56px',
3452
- sm: '64px'
3453
- },
3454
- width: {
3455
- xs: '56px',
3456
- sm: '64px'
3457
- },
3458
- marginLeft: {
3459
- xs: 0.5,
3460
- sm: 1
3461
- },
3462
- marginTop: 3,
3463
- marginBottom: 3
3499
+ if (trimmedProbValue !== '' && trimmedValue !== '' && trimmedValue !== 'TEMPO') {
3500
+ return invalidChangeProbCombinationMessage;
3464
3501
  }
3465
- };
3466
-
3467
- var ViewModeButtons = function ViewModeButtons(_ref) {
3468
- var canBe = _ref.canBe,
3469
- onTafViewModeButtonPress = _ref.onTafViewModeButtonPress;
3470
- return !canBe.includes('CANCELLED') && !canBe.includes('CORRECTED') && !canBe.includes('AMENDED') ? null : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, canBe.includes('CANCELLED') && /*#__PURE__*/React__default.createElement(Button, {
3471
- "data-testid": "canceltaf",
3472
- variant: "tertiary",
3473
- onClick: function onClick() {
3474
- return onTafViewModeButtonPress('CANCEL');
3475
- }
3476
- }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
3477
- "data-testid": "correcttaf",
3478
- variant: "tertiary",
3479
- onClick: function onClick() {
3480
- return onTafViewModeButtonPress('CORRECT');
3481
- }
3482
- }, "Correct"), canBe.includes('AMENDED') && /*#__PURE__*/React__default.createElement(Button, {
3483
- "data-testid": "amendtaf",
3484
- variant: "tertiary",
3485
- onClick: function onClick() {
3486
- return onTafViewModeButtonPress('AMEND');
3487
- }
3488
- }, "Amend"));
3489
- };
3490
3502
 
3491
- var TafFormButtons = function TafFormButtons(_ref2) {
3492
- var _ref2$isFormDisabled = _ref2.isFormDisabled,
3493
- isFormDisabled = _ref2$isFormDisabled === void 0 ? false : _ref2$isFormDisabled,
3494
- tafAction = _ref2.tafAction,
3495
- _ref2$canBe = _ref2.canBe,
3496
- canBe = _ref2$canBe === void 0 ? [] : _ref2$canBe,
3497
- onTafEditModeButtonPress = _ref2.onTafEditModeButtonPress,
3498
- onTafViewModeButtonPress = _ref2.onTafViewModeButtonPress;
3499
- return /*#__PURE__*/React__default.createElement(Grid, {
3500
- container: true,
3501
- justifyContent: "flex-end",
3502
- sx: buttonsStyle,
3503
- columns: 24
3504
- }, /*#__PURE__*/React__default.createElement(Grid, {
3505
- item: true,
3506
- container: true,
3507
- justifyContent: "flex-end",
3508
- columns: 24,
3509
- xs: 24,
3510
- sm: 23
3511
- }, isFormDisabled ? /*#__PURE__*/React__default.createElement(ViewModeButtons, {
3512
- canBe: canBe,
3513
- onTafViewModeButtonPress: onTafViewModeButtonPress
3514
- }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
3515
- "data-testid": "cleartaf",
3516
- variant: "tertiary",
3517
- onClick: function onClick() {
3518
- // Simply discard the changes and close the dialog.
3519
- onTafEditModeButtonPress('CLEAR');
3520
- }
3521
- }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
3522
- "data-testid": "savedrafttaf",
3523
- variant: "tertiary",
3524
- onClick: function onClick() {
3525
- /* Save the TAF as draft:
3526
- if action NEW or DRAFT - new status will be DRAFT -- default
3527
- if action AMEND - new status will be DRAFT_AMENDED
3528
- if action CORRECT - new status will be DRAFT_CORRECTED
3529
- if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3530
- if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3531
- */
3532
- onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
3533
- }
3534
- }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
3535
- "data-testid": "publishtaf",
3536
- variant: "tertiary",
3537
- onClick: function onClick() {
3538
- /* Publish the TAF:
3539
- if action NEW or DRAFT - new status will be PUBLISHED -- default
3540
- if action AMEND - new status will be AMENDED
3541
- if action CORRECT - new status will be CORRECTED
3542
- if action DRAFT_AMEND - new status will be AMENDED
3543
- if action DRAFT_CORRECT - new status will be CORRECTED
3544
- */
3545
- onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
3546
- }
3547
- }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
3548
- item: true,
3549
- columns: 24,
3550
- sm: 1
3551
- }));
3503
+ return true;
3552
3504
  };
3553
3505
 
3554
3506
  /* *
@@ -3564,30 +3516,16 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3564
3516
  * See the License for the specific language governing permissions and
3565
3517
  * limitations under the License.
3566
3518
  *
3567
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3568
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3519
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3520
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
3569
3521
  * */
3570
3522
 
3571
- var DragHandle = function DragHandle(_ref) {
3572
- var _ref$isSorting = _ref.isSorting,
3573
- isSorting = _ref$isSorting === void 0 ? false : _ref$isSorting,
3574
- _ref$isDisabled = _ref.isDisabled,
3575
- isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
3576
- index = _ref.index;
3577
- return /*#__PURE__*/React__default.createElement(IconButton, {
3578
- className: "handle",
3579
- "data-testid": "dragHandle-".concat(index),
3580
- disableRipple: true,
3581
- disabled: isDisabled,
3582
- size: "large",
3583
- sx: {
3584
- backgroundColor: 'transparent',
3585
- '&:hover': {
3586
- backgroundColor: 'transparent'
3587
- },
3588
- cursor: isSorting ? 'grabbing' : 'grab'
3589
- }
3590
- }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
3523
+ var invalidProbabilityMessage = 'Invalid Probability input, only PROB30 or PROB40 are allowed'; // validations
3524
+
3525
+ var validateProbabilityField = function validateProbabilityField(value) {
3526
+ var trimmedValue = getFieldValue(value);
3527
+ var isValid = trimmedValue === '' || trimmedValue === 'PROB30' || trimmedValue === 'PROB40';
3528
+ return isValid ? true : invalidProbabilityMessage;
3591
3529
  };
3592
3530
 
3593
3531
  /* *
@@ -3606,364 +3544,502 @@ var DragHandle = function DragHandle(_ref) {
3606
3544
  * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3607
3545
  * Copyright 2022 - Finnish Meteorological Institute (FMI)
3608
3546
  * */
3609
- var getCustomError = function getCustomError(error, isChangeGroup, rowIndex) {
3610
- return Object.assign(Object.assign({}, error), {
3611
- isChangeGroup: isChangeGroup,
3612
- rowIndex: rowIndex
3547
+
3548
+ var TafFormOptionsButton = function TafFormOptionsButton(_ref) {
3549
+ var isChangeGroup = _ref.isChangeGroup,
3550
+ addChangeGroupBelow = _ref.addChangeGroupBelow,
3551
+ addChangeGroupAbove = _ref.addChangeGroupAbove,
3552
+ removeChangeGroup = _ref.removeChangeGroup,
3553
+ clearRow = _ref.clearRow,
3554
+ index = _ref.index;
3555
+ var insertAbove = {
3556
+ text: 'Insert 1 row above',
3557
+ icon: /*#__PURE__*/React.createElement(Add, null),
3558
+ action: addChangeGroupAbove
3559
+ };
3560
+ var insertBelow = {
3561
+ text: 'Insert 1 row below',
3562
+ icon: /*#__PURE__*/React.createElement(Add, null),
3563
+ action: addChangeGroupBelow
3564
+ };
3565
+ var deleteRow = {
3566
+ text: 'Delete row',
3567
+ icon: /*#__PURE__*/React.createElement(Delete, null),
3568
+ action: removeChangeGroup
3569
+ };
3570
+ var clear = {
3571
+ text: 'Clear row',
3572
+ icon: /*#__PURE__*/React.createElement(Close, null),
3573
+ action: clearRow
3574
+ };
3575
+ var menuItemsBaseForecast = [insertBelow, clear];
3576
+ var menuItemsChangeGroup = [insertAbove, insertBelow, deleteRow, clear];
3577
+ return /*#__PURE__*/React.createElement(ToggleMenu, {
3578
+ buttonTestId: "tafFormOptions[".concat(index, "]"),
3579
+ buttonSx: {
3580
+ marginTop: '10px',
3581
+ marginLeft: '4px'
3582
+ },
3583
+ menuItems: isChangeGroup ? menuItemsChangeGroup : menuItemsBaseForecast
3613
3584
  });
3614
3585
  };
3615
- var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
3616
- switch (sumOfErrors) {
3617
- case 0:
3618
- return '0 issues';
3619
-
3620
- case 1:
3621
- return '1 issue';
3622
3586
 
3623
- default:
3624
- return "".concat(sumOfErrors, " issues");
3587
+ var getDefaultValue = function getDefaultValue(fieldName, data) {
3588
+ if (!data) {
3589
+ return '';
3625
3590
  }
3626
- };
3627
- var getErrorValues = function getErrorValues(fieldErrors) {
3628
- var isChangeGroup = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
3629
- var rowIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -1;
3630
- if (!fieldErrors) return [];
3631
- return Object.keys(fieldErrors).reduce(function (list, key) {
3632
- var error = Object.assign({}, fieldErrors[key]);
3633
-
3634
- if (error.ref) {
3635
- return list.concat(getCustomError(error, isChangeGroup, rowIndex));
3636
- }
3637
3591
 
3638
- return list.concat(getErrorValues(error, isChangeGroup, rowIndex));
3639
- }, []);
3592
+ return getDeepProperty(fieldName.split('.'), data) || '';
3640
3593
  };
3641
- var filterDuplicateErrors = function filterDuplicateErrors(errors) {
3642
- return errors.reduce(function (list, error) {
3643
- // check on type validateRequiredSub and validateRequiredMainOptional since these are giving 'duplicates'
3644
- if (error.type === 'validateRequiredSub') {
3645
- var exist = list.find(function (e) {
3646
- return e.type === 'validateRequiredSub' && e.rowIndex === error.rowIndex;
3647
- });
3648
- return exist ? list : list.concat(error);
3649
- }
3650
-
3651
- if (error.type === 'validateRequiredMainOptional') {
3652
- var _exist = list.find(function (e) {
3653
- return e.type === 'validateRequiredMainOptional' && e.rowIndex === error.rowIndex;
3654
- });
3655
-
3656
- return _exist ? list : list.concat(error);
3657
- }
3658
3594
 
3659
- return list.concat(error);
3660
- }, []);
3595
+ var getRequiredCrossFields = function getRequiredCrossFields(fieldNames) {
3596
+ return [[fieldNames.valid], [fieldNames.change, fieldNames.probability], [fieldNames.wind, fieldNames.visibility, fieldNames.weather1, fieldNames.cloud1] // sub fields
3597
+ ];
3661
3598
  };
3662
- var getErrors = function getErrors(errors) {
3663
- var errorList = Object.keys(errors).reduce(function (list, key) {
3664
- var errorValue = errors[key]; // changeGroups
3665
3599
 
3666
- if (Array.isArray(errorValue)) {
3667
- var errorValues = errorValue.reduce(function (changeGroupErrors, changeGroupError, index) {
3668
- return changeGroupErrors.concat(getErrorValues(changeGroupError, true, index));
3669
- }, []);
3670
- return list.concat.apply(list, _toConsumableArray(errorValues));
3671
- } // baseForecast
3600
+ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3601
+ var isNotRequiredForAction = _a.isNotRequiredForAction,
3602
+ _a$isChangeGroup = _a.isChangeGroup,
3603
+ isChangeGroup = _a$isChangeGroup === void 0 ? false : _a$isChangeGroup,
3604
+ _a$disabled = _a.disabled,
3605
+ disabled = _a$disabled === void 0 ? false : _a$disabled,
3606
+ _a$index = _a.index,
3607
+ index = _a$index === void 0 ? -1 : _a$index,
3608
+ onRemoveChangeGroup = _a.onRemoveChangeGroup,
3609
+ _a$field = _a.field,
3610
+ field = _a$field === void 0 ? null : _a$field,
3611
+ _a$dragHandle = _a.dragHandle,
3612
+ dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
3613
+ onAddChangeGroupBelow = _a.onAddChangeGroupBelow,
3614
+ onAddChangeGroupAbove = _a.onAddChangeGroupAbove,
3615
+ onClearRow = _a.onClearRow,
3616
+ props = __rest(_a, ["isNotRequiredForAction", "isChangeGroup", "disabled", "index", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroupBelow", "onAddChangeGroupAbove", "onClearRow"]);
3672
3617
 
3618
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
3619
+ var fieldNames = getFieldNames(isChangeGroup, index);
3673
3620
 
3674
- return list.concat(getErrorValues(errorValue, false, -1));
3675
- }, []);
3676
- return errorList;
3677
- };
3621
+ var _useFormContext = useFormContext(),
3622
+ getValues = _useFormContext.getValues,
3623
+ trigger = _useFormContext.trigger; // cross-field required validation
3678
3624
 
3679
- /* *
3680
- * Licensed under the Apache License, Version 2.0 (the "License");
3681
- * you may not use this file except in compliance with the License.
3682
- * You may obtain a copy of the License at
3683
- *
3684
- * http://www.apache.org/licenses/LICENSE-2.0
3685
- *
3686
- * Unless required by applicable law or agreed to in writing, software
3687
- * distributed under the License is distributed on an "AS IS" BASIS,
3688
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3689
- * See the License for the specific language governing permissions and
3690
- * limitations under the License.
3691
- *
3692
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3693
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3694
- * */
3695
3625
 
3696
- var IssuesButton = function IssuesButton(_ref) {
3697
- var _ref$errors = _ref.errors,
3698
- errors = _ref$errors === void 0 ? {} : _ref$errors,
3699
- _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
3700
- isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
3701
- _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
3702
- setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
3703
- return null;
3704
- } : _ref$setIsIssuesPaneO;
3705
- var errorList = filterDuplicateErrors(getErrors(errors));
3706
- var totalErrors = errorList.length;
3707
- var errorStatus = totalErrors > 0 ? 'error' : 'success';
3708
- var buttonColor = "geowebColors.functional.".concat(errorStatus);
3626
+ var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
3627
+ _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
3628
+ mainFields = _getRequiredCrossFiel2[0],
3629
+ mainOptionalFields = _getRequiredCrossFiel2[1],
3630
+ subFields = _getRequiredCrossFiel2[2];
3709
3631
 
3710
- var toggleIssuesPane = function toggleIssuesPane(newPosition) {
3711
- return setIsIssuesPaneOpen(!isIssuesPaneOpen, newPosition);
3712
- };
3632
+ var hasFieldsValue = function hasFieldsValue(fields) {
3633
+ return fields.map(getValues).find(function (field) {
3634
+ return !!field;
3635
+ });
3636
+ }; // Used to validate the required field for change groups: Valid
3713
3637
 
3714
- var onClickButton = function onClickButton(event) {
3715
- var _a;
3716
3638
 
3717
- var _event$currentTarget$ = event.currentTarget.getBoundingClientRect(),
3718
- left = _event$currentTarget$.left,
3719
- top = _event$currentTarget$.top;
3639
+ var validateRequiredMain = function validateRequiredMain(value) {
3640
+ return isNotRequiredForAction(value) !== true && isChangeGroup && !value.length && (hasFieldsValue(subFields) || hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) ? 'Valid is required' : true;
3641
+ }; // Used to ensure either probability or change is entered, or both
3720
3642
 
3721
- var parentOffset = ((_a = document.getElementById('tafmodule')) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
3722
- top: 0,
3723
- left: 0
3724
- };
3725
- var newPosition = {
3726
- left: left - parentOffset.left + 100,
3727
- top: top - parentOffset.top
3728
- };
3729
- toggleIssuesPane(newPosition);
3730
- };
3731
3643
 
3732
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3733
- title: "View details"
3734
- }, /*#__PURE__*/React.createElement(Chip, {
3735
- "data-testid": "issuesButton",
3736
- className: "status-".concat(errorStatus),
3737
- size: "small",
3738
- label: getIssuesLabel(totalErrors),
3739
- onClick: onClickButton,
3740
- sx: {
3741
- width: '74px',
3742
- color: '#ffffff',
3743
- backgroundColor: buttonColor,
3744
- '&:hover': {
3745
- backgroundColor: buttonColor
3746
- },
3747
- '&:focus': {
3748
- backgroundColor: buttonColor
3749
- },
3750
- fontSize: 12
3751
- }
3752
- }));
3753
- };
3644
+ var validateRequiredMainOptional = function validateRequiredMainOptional(value) {
3645
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(subFields)) && !hasFieldsValue(mainOptionalFields) ? 'Probability or change is required' : true;
3646
+ }; // Used to ensure one wind, visibility, weather or cloud is entered when start editing a changegroup and all of these are empty
3754
3647
 
3755
- var getPaneTitle = function getPaneTitle(sumOfErrors) {
3756
- switch (sumOfErrors) {
3757
- case 0:
3758
- return 'Looks good';
3759
3648
 
3760
- case 1:
3761
- return 'There is an issue to address';
3649
+ var validateRequiredSub = function validateRequiredSub(value) {
3650
+ return isNotRequiredForAction(value) !== true && isChangeGroup && (hasFieldsValue(mainFields) || hasFieldsValue(mainOptionalFields)) && !hasFieldsValue(subFields) ? 'Wind, visibility, weather or cloud is required' : true;
3651
+ }; // Used to validate the combination of change group and wind, visibility, weather and/or cloud data entered
3762
3652
 
3763
- default:
3764
- return 'There are a few issues to address';
3765
- }
3766
- };
3767
3653
 
3768
- var humanizeErrorMessage = function humanizeErrorMessage(errorTitle, fieldNumberedValue) {
3769
- if (fieldNumberedValue !== undefined && fieldNumberedValue >= 0) {
3770
- // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3771
- var fieldNumber = fieldNumberedValue + 1;
3772
- return "".concat(errorTitle, " ").concat(fieldNumber);
3773
- }
3654
+ var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
3655
+ var changeField = getValues("".concat(namePrefix, ".change"));
3656
+ var visibilityField = getValues("".concat(namePrefix, ".visibility"));
3657
+ var isFM = changeField && changeField.trim() === 'FM';
3658
+ var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
3774
3659
 
3775
- return errorTitle;
3776
- };
3777
- var getErrorMessage = function getErrorMessage(error, index) {
3778
- var errorTitleCategory = error.isChangeGroup ? 'Changegroups' : 'Baseforecast';
3779
- var fieldErrorTitle = humanizeErrorMessage(errorTitleCategory, error.rowIndex);
3780
- return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(error.message);
3781
- };
3782
- var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3783
- var useIssuesPane = function useIssuesPane() {
3784
- var _React$useState = React.useState(false),
3785
- _React$useState2 = _slicedToArray(_React$useState, 2),
3786
- isIssuesPaneOpen = _React$useState2[0],
3787
- setIsIssuesPaneOpen = _React$useState2[1];
3660
+ if (isNotRequiredForAction(value) !== true && !value.length) {
3661
+ if (isChangeGroup && isFM || !isChangeGroup) {
3662
+ // exception for CavOK
3663
+ if (isCAVOK && (fieldName === 'Clouds' || fieldName === 'Weather')) {
3664
+ return true;
3665
+ } // exception for visibility > 5000
3788
3666
 
3789
- var _React$useState3 = React.useState(null),
3790
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3791
- startPosition = _React$useState4[0],
3792
- setStartPosition = _React$useState4[1];
3793
3667
 
3794
- var onToggleIssuesPane = function onToggleIssuesPane(isOpen, newPosition) {
3795
- if (!startPosition) {
3796
- setStartPosition(newPosition);
3668
+ if (visibilityField && parseInt(visibilityField.trim(), 10) >= 5000 && fieldName === 'Weather') {
3669
+ return true;
3670
+ }
3671
+
3672
+ return "".concat(fieldName, " is required");
3673
+ }
3674
+ }
3675
+
3676
+ return true;
3677
+ };
3678
+
3679
+ var validatePreviousRow = React__default.useCallback(function () {
3680
+ if (isChangeGroup && index > 0) {
3681
+ var _getValues = getValues(),
3682
+ validDateEnd = _getValues.validDateEnd,
3683
+ validDateStart = _getValues.validDateStart,
3684
+ changeGroups = _getValues.changeGroups;
3685
+
3686
+ var currentChangeGroup = changeGroups[index];
3687
+ var previousChangeGroup = changeGroups[index - 1];
3688
+ return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
3689
+ }
3690
+
3691
+ return true;
3692
+ }, [index, isChangeGroup, getValues]);
3693
+
3694
+ var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
3695
+ var indexedFieldName = "changeGroups[".concat(rowIndex, "].").concat(fieldname);
3696
+ var rowValue = getValues(indexedFieldName);
3697
+ return rowValue ? [indexedFieldName] : [];
3698
+ };
3699
+
3700
+ var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
3701
+ return getFieldFromRow('valid', index + 1);
3702
+ };
3703
+
3704
+ var validateNextRows = React__default.useCallback(function () {
3705
+ if (isChangeGroup) {
3706
+ var _getValues2 = getValues(),
3707
+ validDateEnd = _getValues2.validDateEnd,
3708
+ validDateStart = _getValues2.validDateStart,
3709
+ changeGroups = _getValues2.changeGroups;
3710
+
3711
+ var currentChangeGroup = changeGroups[index];
3712
+ var nextChangeGroups = changeGroups.slice(index + 1);
3713
+ return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
3714
+ }
3715
+
3716
+ return true;
3717
+ }, [index, isChangeGroup, getValues]);
3718
+
3719
+ var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
3720
+ var _getValues3 = getValues(),
3721
+ changeGroups = _getValues3.changeGroups;
3722
+
3723
+ var previousChangeGroups = changeGroups.slice(0, rowIndex);
3724
+ var validFields = previousChangeGroups.map(function (_element, index) {
3725
+ return getFieldFromRow('valid', index)[0];
3726
+ });
3727
+ return validFields;
3728
+ };
3729
+
3730
+ var addChangeGroupBelow = React__default.useCallback(function () {
3731
+ onAddChangeGroupBelow(index);
3732
+ }, [onAddChangeGroupBelow, index]);
3733
+ var addChangeGroupAbove = React__default.useCallback(function () {
3734
+ onAddChangeGroupAbove(index);
3735
+ }, [onAddChangeGroupAbove, index]);
3736
+ var clearRow = React__default.useCallback(function () {
3737
+ onClearRow(index);
3738
+ }, [onClearRow, index]);
3739
+ return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
3740
+ sx: {
3741
+ marginTop: '8px',
3742
+ backgroundColor: 'geowebColors.cards.cardContainer',
3743
+ position: 'relative',
3744
+ '&.sortable-chosen': {
3745
+ boxShadow: 1
3746
+ },
3747
+ '&.sortable-ghost': {
3748
+ opacity: 0.5
3749
+ }
3750
+ },
3751
+ justifyContent: "flex-start",
3752
+ "data-testid": "row-".concat(namePrefix),
3753
+ container: true,
3754
+ ref: ref
3755
+ }, props, {
3756
+ className: "formRow"
3757
+ }), /*#__PURE__*/React__default.createElement(Grid, {
3758
+ columns: 24,
3759
+ item: true,
3760
+ container: true,
3761
+ justifyContent: "flex-end",
3762
+ xs: 24,
3763
+ sm: 23
3764
+ }, !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
3765
+ label: "Type",
3766
+ name: fieldNames.messageType,
3767
+ disabled: true
3768
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3769
+ label: "Location",
3770
+ name: "location",
3771
+ disabled: true
3772
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3773
+ formatter: formatIssueTime,
3774
+ label: "Issue time",
3775
+ name: "issueDate",
3776
+ disabled: true,
3777
+ shouldPreventUppercase: true
3778
+ })), isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Box, {
3779
+ sx: {
3780
+ width: 56,
3781
+ marginRight: '2px'
3782
+ }
3783
+ }, !disabled && dragHandle), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3784
+ label: "Prob",
3785
+ name: fieldNames.probability,
3786
+ disabled: disabled,
3787
+ defaultValue: getDefaultValue('probability', field),
3788
+ rules: {
3789
+ validate: {
3790
+ validateRequiredMainOptional: validateRequiredMainOptional,
3791
+ validateProbabilityField: validateProbabilityField
3792
+ }
3793
+ },
3794
+ autoComplete: [{
3795
+ key: '3',
3796
+ value: 'PROB30'
3797
+ }, {
3798
+ key: '4',
3799
+ value: 'PROB40'
3800
+ }],
3801
+ onBlur: function onBlur() {
3802
+ if (isChangeGroup) {
3803
+ var nextValidFieldName = getValidFieldFromNextRow();
3804
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
3805
+ }
3806
+ }
3807
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3808
+ label: "Change",
3809
+ name: fieldNames.change,
3810
+ disabled: disabled,
3811
+ defaultValue: getDefaultValue('change', field),
3812
+ rules: {
3813
+ validate: {
3814
+ validateRequiredMainOptional: validateRequiredMainOptional,
3815
+ validateChangeField: validateChangeField,
3816
+ validateChangeFieldInterField: function validateChangeFieldInterField$1(value) {
3817
+ return validateChangeFieldInterField(value, getValues(fieldNames.probability));
3818
+ }
3819
+ }
3820
+ },
3821
+ autoComplete: [{
3822
+ key: 'T',
3823
+ value: 'TEMPO'
3824
+ }, {
3825
+ key: 'B',
3826
+ value: 'BECMG'
3827
+ }, {
3828
+ key: 'F',
3829
+ value: 'FM'
3830
+ }],
3831
+ onBlur: function onBlur() {
3832
+ if (isChangeGroup) {
3833
+ var nextValidFieldName = getValidFieldFromNextRow();
3834
+ var previousValidFieldNames = getPreviousValidFields(index);
3835
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3836
+ }
3837
+ }
3838
+ })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3839
+ label: "Valid",
3840
+ name: fieldNames.valid,
3841
+ // always disabled for baseforecast row
3842
+ disabled: !isChangeGroup ? true : disabled,
3843
+ defaultValue: getDefaultValue('valid', field),
3844
+ rules: {
3845
+ validate: {
3846
+ validateRequiredMain: validateRequiredMain,
3847
+ validateValidField: function validateValidField$1(value) {
3848
+ return isChangeGroup ? validateValidField(value, getValues('validDateStart'), getValues('validDateEnd')) : true;
3849
+ },
3850
+ validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
3851
+ return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues(fieldNames.probability), getValues('validDateStart'), getValues('validDateEnd')) : true;
3852
+ },
3853
+ validatePreviousRow: validatePreviousRow,
3854
+ validateNextRows: validateNextRows
3855
+ }
3856
+ },
3857
+ onBlur: function onBlur() {
3858
+ if (isChangeGroup) {
3859
+ var nextValidFieldName = getValidFieldFromNextRow();
3860
+ var previousValidFieldNames = getPreviousValidFields(index);
3861
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName), _toConsumableArray(previousValidFieldNames)));
3862
+ }
3863
+ }
3864
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3865
+ label: "Wind",
3866
+ name: fieldNames.wind,
3867
+ disabled: disabled,
3868
+ defaultValue: getDefaultValue('wind', field),
3869
+ rules: {
3870
+ validate: {
3871
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3872
+ return _validateRequiredMainFields(value, 'Wind');
3873
+ },
3874
+ validateRequiredSub: validateRequiredSub,
3875
+ validateWindField: function validateWindField$1(value) {
3876
+ return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3877
+ }
3878
+ }
3879
+ },
3880
+ onBlur: function onBlur() {
3881
+ if (isChangeGroup) {
3882
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
3883
+ }
3884
+ },
3885
+ autoFocus: !isChangeGroup
3886
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3887
+ label: "Visibility",
3888
+ name: fieldNames.visibility,
3889
+ disabled: disabled,
3890
+ defaultValue: getDefaultValue('visibility', field),
3891
+ rules: {
3892
+ validate: {
3893
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3894
+ return _validateRequiredMainFields(value, 'Visibility');
3895
+ },
3896
+ validateRequiredSub: validateRequiredSub,
3897
+ validateVisibilityField: validateVisibilityField
3898
+ }
3899
+ },
3900
+ autoComplete: [{
3901
+ key: 'C',
3902
+ value: 'CAVOK'
3903
+ }],
3904
+ onBlur: function onBlur() {
3905
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3906
+ trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3907
+ }
3908
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3909
+ label: "Weather",
3910
+ name: fieldNames.weather1,
3911
+ disabled: disabled,
3912
+ defaultValue: getDefaultValue('weather.weather1', field),
3913
+ rules: {
3914
+ validate: {
3915
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3916
+ return _validateRequiredMainFields(value, 'Weather');
3917
+ },
3918
+ validateRequiredSub: validateRequiredSub,
3919
+ validateWeatherField: function validateWeatherField$1(value) {
3920
+ return validateWeatherField(value, getValues(fieldNames.visibility), !!isChangeGroup);
3921
+ }
3922
+ }
3923
+ },
3924
+ onBlur: function onBlur() {
3925
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3926
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3927
+ }
3928
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3929
+ label: "Weather",
3930
+ name: fieldNames.weather2,
3931
+ disabled: disabled,
3932
+ defaultValue: getDefaultValue('weather.weather2', field),
3933
+ rules: {
3934
+ validate: {
3935
+ validateSecondWeatherField: function validateSecondWeatherField$1(value) {
3936
+ return validateSecondWeatherField(getValues(fieldNames.weather1), value, getValues(fieldNames.visibility));
3937
+ }
3938
+ }
3939
+ },
3940
+ onBlur: function onBlur() {
3941
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3942
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
3943
+ }
3944
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3945
+ label: "Weather",
3946
+ name: fieldNames.weather3,
3947
+ disabled: disabled,
3948
+ defaultValue: getDefaultValue('weather.weather3', field),
3949
+ rules: {
3950
+ validate: {
3951
+ validateThirdWeatherField: function validateThirdWeatherField$1(value) {
3952
+ return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
3953
+ }
3954
+ }
3955
+ },
3956
+ onBlur: function onBlur() {
3957
+ return trigger([fieldNames.wind, fieldNames.cloud1]);
3958
+ }
3959
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3960
+ label: "Cloud",
3961
+ name: fieldNames.cloud1,
3962
+ disabled: disabled,
3963
+ defaultValue: getDefaultValue('cloud.cloud1', field),
3964
+ rules: {
3965
+ validate: {
3966
+ validateRequiredMainFields: function validateRequiredMainFields(value) {
3967
+ return _validateRequiredMainFields(value, 'Clouds');
3968
+ },
3969
+ validateRequiredSub: validateRequiredSub,
3970
+ validateFirstCloud: function validateFirstCloud$1(value) {
3971
+ return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
3972
+ }
3973
+ }
3974
+ },
3975
+ onBlur: function onBlur() {
3976
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3977
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3797
3978
  }
3798
-
3799
- setIsIssuesPaneOpen(isOpen);
3800
- };
3801
-
3802
- var onCloseIssuesPane = function onCloseIssuesPane() {
3803
- return setIsIssuesPaneOpen(false);
3804
- };
3805
-
3806
- return {
3807
- isIssuesPaneOpen: isIssuesPaneOpen,
3808
- startPosition: startPosition,
3809
- onToggleIssuesPane: onToggleIssuesPane,
3810
- onCloseIssuesPane: onCloseIssuesPane
3811
- };
3812
- };
3813
-
3814
- var IssuesPane = function IssuesPane(_ref) {
3815
- var _ref$errorList = _ref.errorList,
3816
- errorList = _ref$errorList === void 0 ? [] : _ref$errorList,
3817
- isOpen = _ref.isOpen,
3818
- handleClose = _ref.handleClose,
3819
- _ref$startPosition = _ref.startPosition,
3820
- startPosition = _ref$startPosition === void 0 ? {
3821
- left: 20,
3822
- top: 50
3823
- } : _ref$startPosition;
3824
- var rootElement = document.getElementById(MODAL_DIALOG_ELEMENT) || document.body;
3825
- return /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3826
- startSize: {
3827
- width: '577px',
3828
- height: '200px'
3979
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3980
+ label: "Cloud",
3981
+ name: fieldNames.cloud2,
3982
+ disabled: disabled,
3983
+ defaultValue: getDefaultValue('cloud.cloud2', field),
3984
+ rules: {
3985
+ validate: {
3986
+ validateSecondCloud: function validateSecondCloud$1(value) {
3987
+ return validateSecondCloud(getValues(fieldNames.cloud1), value, getValues(fieldNames.visibility));
3988
+ }
3989
+ }
3829
3990
  },
3830
- startPosition: startPosition,
3831
- minWidth: 300,
3832
- onClose: handleClose,
3833
- title: getPaneTitle(errorList.length),
3834
- headerSize: "xs",
3835
- isOpen: isOpen,
3836
- "data-testid": "moveable-issues-pane",
3837
- bounds: "parent"
3838
- }, /*#__PURE__*/React.createElement(Box, {
3839
- component: "div",
3840
- sx: {
3841
- marginTop: '16px',
3842
- marginLeft: '24px'
3991
+ onBlur: function onBlur() {
3992
+ return trigger([fieldNames.cloud3, fieldNames.cloud4]);
3843
3993
  }
3844
- }, errorList.length === 0 && /*#__PURE__*/React.createElement(Box, {
3845
- component: "div",
3846
- sx: {
3847
- fontSize: '4rem'
3994
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
3995
+ label: "Cloud",
3996
+ name: fieldNames.cloud3,
3997
+ disabled: disabled,
3998
+ defaultValue: getDefaultValue('cloud.cloud3', field),
3999
+ rules: {
4000
+ validate: {
4001
+ validateThirdCloud: function validateThirdCloud$1(value) {
4002
+ return validateThirdCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), value, getValues(fieldNames.visibility));
4003
+ }
4004
+ }
3848
4005
  },
3849
- "data-testid": "zeroIssuesImage"
3850
- }, /*#__PURE__*/React.createElement(ThumbsUp, {
3851
- sx: {
3852
- height: '69px',
3853
- width: '58px'
4006
+ onBlur: function onBlur() {
4007
+ return trigger(fieldNames.cloud4);
3854
4008
  }
3855
- })), errorList.length > 0 && errorList.map(function (error, index) {
3856
- return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3857
- , {
3858
- // eslint-disable-next-line react/no-array-index-key
3859
- key: "message-".concat(index),
3860
- variant: "body1",
3861
- "data-testid": "errorMessage"
3862
- }, getErrorMessage(error, index));
3863
- }))), rootElement);
3864
- };
3865
-
3866
- var TafModuleContext = /*#__PURE__*/React.createContext({
3867
- onValidateForm: null,
3868
- registerValidateForm: null,
3869
- tafAction: null,
3870
- setTafAction: null,
3871
- onPreventCloseView: null
4009
+ }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
4010
+ label: "Cloud",
4011
+ name: fieldNames.cloud4,
4012
+ disabled: disabled,
4013
+ defaultValue: getDefaultValue('cloud.cloud4', field),
4014
+ rules: {
4015
+ validate: {
4016
+ validateFourthCloud: function validateFourthCloud$1(value) {
4017
+ return validateFourthCloud(getValues(fieldNames.cloud1), getValues(fieldNames.cloud2), getValues(fieldNames.cloud3), value, getValues(fieldNames.visibility));
4018
+ }
4019
+ }
4020
+ }
4021
+ })), !disabled && /*#__PURE__*/React__default.createElement(Grid, {
4022
+ item: true,
4023
+ container: true,
4024
+ justifyContent: "flex-end",
4025
+ alignItems: "flex-end",
4026
+ xs: 24,
4027
+ sm: 1,
4028
+ sx: {
4029
+ marginBottom: '16px'
4030
+ },
4031
+ columns: 24
4032
+ }, /*#__PURE__*/React__default.createElement(TafFormOptionsButton, {
4033
+ isChangeGroup: isChangeGroup,
4034
+ addChangeGroupBelow: addChangeGroupBelow,
4035
+ addChangeGroupAbove: addChangeGroupAbove,
4036
+ removeChangeGroup: function removeChangeGroup() {
4037
+ return onRemoveChangeGroup(index);
4038
+ },
4039
+ clearRow: clearRow,
4040
+ index: index
4041
+ })));
3872
4042
  });
3873
- var useTafModuleContext = function useTafModuleContext() {
3874
- return React.useContext(TafModuleContext);
3875
- };
3876
- var useTafModuleState = function useTafModuleState(_ref) {
3877
- var onPreventCloseView = _ref.onPreventCloseView;
3878
-
3879
- var _React$useState = React.useState(function () {
3880
- return new Promise(function () {
3881
- return true;
3882
- });
3883
- }),
3884
- _React$useState2 = _slicedToArray(_React$useState, 2),
3885
- onValidateForm = _React$useState2[0],
3886
- registerValidateForm = _React$useState2[1];
3887
-
3888
- var _React$useState3 = React.useState(),
3889
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3890
- tafAction = _React$useState4[0],
3891
- setTafAction = _React$useState4[1];
3892
-
3893
- var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3894
- registerValidateForm(function () {
3895
- return promiseToRegister;
3896
- });
3897
- };
3898
-
3899
- return {
3900
- onValidateForm: onValidateForm,
3901
- registerValidateForm: onRegisterValidateForm,
3902
- tafAction: tafAction,
3903
- setTafAction: setTafAction,
3904
- onPreventCloseView: onPreventCloseView
3905
- };
3906
- };
3907
- var TafModuleProvider = function TafModuleProvider(_ref2) {
3908
- var children = _ref2.children,
3909
- _ref2$onPreventCloseV = _ref2.onPreventCloseView,
3910
- onPreventCloseView = _ref2$onPreventCloseV === void 0 ? function () {} : _ref2$onPreventCloseV;
3911
- var contextState = useTafModuleState({
3912
- onPreventCloseView: onPreventCloseView
3913
- });
3914
- return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3915
- value: contextState
3916
- }, children);
3917
- };
3918
-
3919
- /* *
3920
- * Licensed under the Apache License, Version 2.0 (the "License");
3921
- * you may not use this file except in compliance with the License.
3922
- * You may obtain a copy of the License at
3923
- *
3924
- * http://www.apache.org/licenses/LICENSE-2.0
3925
- *
3926
- * Unless required by applicable law or agreed to in writing, software
3927
- * distributed under the License is distributed on an "AS IS" BASIS,
3928
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3929
- * See the License for the specific language governing permissions and
3930
- * limitations under the License.
3931
- *
3932
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3933
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
3934
- * */
3935
- var styles = {
3936
- label: {
3937
- color: 'geowebColors.buttons.tertiary.default.color',
3938
- opacity: 1,
3939
- fontSize: '12px',
3940
- fontWeight: 500
3941
- }
3942
- };
3943
-
3944
- var SwitchButton = function SwitchButton(props) {
3945
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3946
- title: "Switch mode"
3947
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(FormLabel, {
3948
- sx: styles.label
3949
- }, "Viewer"), /*#__PURE__*/React.createElement(Switch, Object.assign({
3950
- "data-testid": "switchMode"
3951
- }, props)), /*#__PURE__*/React.createElement(FormLabel, {
3952
- sx: styles.label
3953
- }, "Editor")));
3954
- };
3955
-
3956
- var TafAvatar = function TafAvatar(_ref) {
3957
- var editor = _ref.editor,
3958
- _ref$tooltipPlacement = _ref.tooltipPlacement,
3959
- tooltipPlacement = _ref$tooltipPlacement === void 0 ? 'bottom' : _ref$tooltipPlacement;
3960
- return /*#__PURE__*/React.createElement(CustomTooltip, {
3961
- title: "Editor: ".concat(editor),
3962
- placement: tooltipPlacement
3963
- }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Avatar, {
3964
- size: "small"
3965
- }, getInitials(editor))));
3966
- };
3967
4043
 
3968
4044
  var noop = function noop() {};
3969
4045
 
@@ -3995,7 +4071,10 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
3995
4071
  _ref$fetchNewTafList = _ref.fetchNewTafList,
3996
4072
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
3997
4073
  return null;
3998
- } : _ref$fetchNewTafList;
4074
+ } : _ref$fetchNewTafList,
4075
+ _ref$previousTaf = _ref.previousTaf,
4076
+ previousTaf = _ref$previousTaf === void 0 ? null : _ref$previousTaf;
4077
+ var formRef = React__default.useRef();
3999
4078
  var originalTaf = tafFromBackend.taf,
4000
4079
  editor = tafFromBackend.editor;
4001
4080
 
@@ -4062,7 +4141,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4062
4141
  return confirmDialog({
4063
4142
  title: getConfirmationDialogTitle(action),
4064
4143
  description: getConfirmationDialogContent(action, function () {
4065
- return isTafAmendedCorrectedChanged(isFormDirty$1, originalTaf, convertTafValuesToObject(getValues()));
4144
+ return isTafAmendedCorrectedChanged( // If already saved as draft amd/cor then send over the previous taf
4145
+ originalTaf.status === 'DRAFT_AMENDED' || originalTaf.status === 'DRAFT_CORRECTED' ? previousTaf : originalTaf, convertTafValuesToObject(getValues()));
4066
4146
  }),
4067
4147
  confirmLabel: getConfirmationDialogButtonLabel(action)
4068
4148
  });
@@ -4259,14 +4339,37 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4259
4339
  resetFormState(null, true, convertTafValuesToObject(data));
4260
4340
  }
4261
4341
 
4262
- case 6:
4342
+ return _context3.abrupt("return", true);
4343
+
4344
+ case 7:
4263
4345
  case "end":
4264
4346
  return _context3.stop();
4265
4347
  }
4266
4348
  }
4267
4349
  }, _callee3);
4268
4350
  }));
4269
- })();
4351
+ })().then(function () {
4352
+ var hasFormErrors = Object.keys(errors).length;
4353
+ var formNodeRef = formRef.current;
4354
+
4355
+ if (hasFormErrors && formNodeRef) {
4356
+ var inputsWithError = formNodeRef.querySelectorAll('.Mui-error');
4357
+ var firstFormGroupWithError = inputsWithError.length ? inputsWithError[inputsWithError.length - 1].closest('.formRow') : null;
4358
+
4359
+ if (firstFormGroupWithError) {
4360
+ var _getFormRowPosition = getFormRowPosition(firstFormGroupWithError),
4361
+ top = _getFormRowPosition.top,
4362
+ left = _getFormRowPosition.left;
4363
+
4364
+ var tafModuleNode = formNodeRef.closest('#tafmodule');
4365
+ var newTop = top - (tafModuleNode === null || tafModuleNode === void 0 ? void 0 : tafModuleNode.getBoundingClientRect().top) || 0;
4366
+ setIsIssuesPaneOpen(true, {
4367
+ top: newTop,
4368
+ left: left
4369
+ });
4370
+ }
4371
+ }
4372
+ });
4270
4373
  break;
4271
4374
 
4272
4375
  default:
@@ -4452,7 +4555,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4452
4555
  editor: editor
4453
4556
  }))), /*#__PURE__*/React__default.createElement("form", {
4454
4557
  "data-testid": "taf-form",
4455
- onSubmit: handleSubmit(onSubmit)
4558
+ onSubmit: handleSubmit(onSubmit),
4559
+ ref: formRef
4456
4560
  }, /*#__PURE__*/React__default.createElement(TafFormRow, {
4457
4561
  disabled: isDisabled,
4458
4562
  onAddChangeGroupBelow: onAddRow,
@@ -4754,6 +4858,14 @@ var getNewTafLocationIndex = function getNewTafLocationIndex(tafLocations, previ
4754
4858
 
4755
4859
  return 0;
4756
4860
  };
4861
+ var getPreviousTaf = function getPreviousTaf(tafList, currentTaf) {
4862
+ var previousId = currentTaf.taf.previousId;
4863
+ if (!previousId) return null;
4864
+ var previousTaf = tafList.find(function (taf) {
4865
+ return taf.taf.uuid === previousId;
4866
+ });
4867
+ return previousTaf ? previousTaf.taf : null;
4868
+ };
4757
4869
 
4758
4870
  /* *
4759
4871
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -5592,7 +5704,10 @@ var TafPanel = function TafPanel(_ref) {
5592
5704
  _ref$fetchNewTafList = _ref.fetchNewTafList,
5593
5705
  fetchNewTafList = _ref$fetchNewTafList === void 0 ? function () {
5594
5706
  return null;
5595
- } : _ref$fetchNewTafList;
5707
+ } : _ref$fetchNewTafList,
5708
+ _ref$previousTaf = _ref.previousTaf,
5709
+ previousTaf = _ref$previousTaf === void 0 ? null : _ref$previousTaf,
5710
+ tafAction = _ref.tafAction;
5596
5711
  var severity = isWarning(error) ? 'warning' : 'error';
5597
5712
 
5598
5713
  var onTafAction = function onTafAction(action, taf) {
@@ -5642,7 +5757,7 @@ var TafPanel = function TafPanel(_ref) {
5642
5757
  index: index,
5643
5758
  "data-testid": "taf-panel".concat(activeTafIndex === index ? '-active' : '')
5644
5759
  }, /*#__PURE__*/React__default.createElement(TafHeader, {
5645
- title: getTafStatusLabel(tafFromBackend.taf.status),
5760
+ title: getTafStatusLabel(tafFromBackend.taf.status, tafAction, isFormDisabled),
5646
5761
  sx: {
5647
5762
  marginBottom: '4px'
5648
5763
  }
@@ -5675,7 +5790,8 @@ var TafPanel = function TafPanel(_ref) {
5675
5790
  isDisabled: isFormDisabled,
5676
5791
  setIsDisabled: setIsFormDisabled,
5677
5792
  onSwitchEditor: patchTaf,
5678
- fetchNewTafList: fetchNewTafList
5793
+ fetchNewTafList: fetchNewTafList,
5794
+ previousTaf: previousTaf
5679
5795
  })));
5680
5796
  };
5681
5797
 
@@ -5786,7 +5902,7 @@ var getSnackbarMessage = function getSnackbarMessage(tafFromFrontEnd) {
5786
5902
  return 'Saved as draft';
5787
5903
 
5788
5904
  case 'DRAFT_AMENDED':
5789
- return 'Saved as draft amended';
5905
+ return 'Saved as draft amendment';
5790
5906
 
5791
5907
  case 'DRAFT_CORRECTED':
5792
5908
  return 'Saved as draft correction';
@@ -5827,7 +5943,8 @@ var TafLayout = function TafLayout(_ref2) {
5827
5943
  isIssuesPaneOpen = _useIssuesPane.isIssuesPaneOpen,
5828
5944
  onToggleIssuesPane = _useIssuesPane.onToggleIssuesPane,
5829
5945
  onCloseIssuesPane = _useIssuesPane.onCloseIssuesPane,
5830
- startPosition = _useIssuesPane.startPosition;
5946
+ startPosition = _useIssuesPane.startPosition,
5947
+ onUserHasDragged = _useIssuesPane.onUserHasDragged;
5831
5948
 
5832
5949
  var _usePostTafRequest = usePostTafRequest(api.postTaf),
5833
5950
  isLoading = _usePostTafRequest.isLoading,
@@ -6151,7 +6268,9 @@ var TafLayout = function TafLayout(_ref2) {
6151
6268
  patchTaf: patchTaf,
6152
6269
  isLoading: isLoading,
6153
6270
  error: error,
6154
- fetchNewTafList: onUpdateTaf
6271
+ fetchNewTafList: onUpdateTaf,
6272
+ previousTaf: getPreviousTaf(tafList, tafFromBackend),
6273
+ tafAction: tafAction
6155
6274
  });
6156
6275
  }))), /*#__PURE__*/React__default.createElement(Grid, {
6157
6276
  item: true,
@@ -6174,7 +6293,8 @@ var TafLayout = function TafLayout(_ref2) {
6174
6293
  })))))), /*#__PURE__*/React__default.createElement(IssuesPaneWrapper, {
6175
6294
  handleClose: onCloseIssuesPane,
6176
6295
  isOpen: isIssuesPaneOpen,
6177
- startPosition: startPosition
6296
+ startPosition: startPosition,
6297
+ onUserHasDragged: onUserHasDragged
6178
6298
  }));
6179
6299
  };
6180
6300
 
@@ -7191,15 +7311,21 @@ var fakeDraftAmendmentTaf = {
7191
7311
  }
7192
7312
  };
7193
7313
 
7314
+ var _a = fakeDraftAmendmentTaf.taf;
7315
+ _a.changeGroups;
7316
+ var fakeDraftAmendmentWithoutChangeGroups = __rest(_a, ["changeGroups"]); // Only use for display purposes in the list!
7317
+
7318
+
7194
7319
  ({
7195
7320
  creationDate: "2022-01-06T14:00:00Z",
7196
7321
  canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7197
7322
  editor: null,
7198
- taf: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf), {
7323
+ taf: Object.assign(Object.assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7199
7324
  location: 'EHRD',
7200
7325
  baseTime: "2022-01-06T12:00:00Z",
7201
7326
  validDateStart: "2022-01-06T14:00:00Z",
7202
7327
  validDateEnd: "2022-01-07T18:00:00Z",
7328
+ previousId: "previousIdOfPreviousTAF",
7203
7329
  previousValidDateStart: "2022-01-06T12:00:00Z",
7204
7330
  previousValidDateEnd: "2022-01-07T18:00:00Z",
7205
7331
  baseForecast: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
@@ -7207,8 +7333,32 @@ var fakeDraftAmendmentTaf = {
7207
7333
  start: "2022-01-06T14:00:00Z",
7208
7334
  end: "2022-01-07T18:00:00Z"
7209
7335
  }
7210
- }),
7211
- changeGroups: []
7336
+ })
7337
+ })
7338
+ }); // Use as the original previous TAF for TAF above
7339
+
7340
+ ({
7341
+ creationDate: "2022-01-06T14:00:00Z",
7342
+ canbe: ['DRAFTED', 'DISCARDED', 'PUBLISHED'],
7343
+ editor: null,
7344
+ taf: Object.assign(Object.assign({}, fakeDraftAmendmentWithoutChangeGroups), {
7345
+ status: 'AMENDED',
7346
+ uuid: 'previousIdOfPreviousTAF',
7347
+ location: 'EHRD',
7348
+ baseTime: "2022-01-06T12:00:00Z",
7349
+ validDateStart: "2022-01-06T14:00:00Z",
7350
+ validDateEnd: "2022-01-07T18:00:00Z",
7351
+ baseForecast: Object.assign(Object.assign({}, fakeDraftAmendmentTaf.taf.baseForecast), {
7352
+ valid: {
7353
+ start: "2022-01-06T14:00:00Z",
7354
+ end: "2022-01-07T18:00:00Z"
7355
+ },
7356
+ wind: {
7357
+ direction: 344,
7358
+ speed: 90,
7359
+ unit: 'KT'
7360
+ }
7361
+ })
7212
7362
  })
7213
7363
  });
7214
7364
  var fakeAmendmentTaf = {