@opengeoweb/taf 4.9.1 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -11,7 +11,7 @@ import { HIDDEN_INPUT_HELPER_IS_DRAFT, useIsMounted, ToggleMenu, CustomTooltip,
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, Edit, Success, Export, ListItem, Cached } from '@opengeoweb/theme';
14
+ import { Add, Delete, Close, DragHandle as DragHandle$1, ThumbsUp, Clock, Cancel, Success, Edit, Export, ListItem, Cached } from '@opengeoweb/theme';
15
15
  import ReactDOM from 'react-dom';
16
16
  import { useApiContext, createApiInstance, createFakeApiInstance, ApiProvider } from '@opengeoweb/api';
17
17
  import LinearProgress from '@mui/material/LinearProgress';
@@ -2014,7 +2014,8 @@ var emptyBaseForecast = {
2014
2014
  cloud3: '',
2015
2015
  cloud4: ''
2016
2016
  }
2017
- }; // formatters
2017
+ };
2018
+ var MIN_NUMBER_CHANGE_GROUP = 5; // formatters
2018
2019
 
2019
2020
  var formatIssueTime = function formatIssueTime(issueDate) {
2020
2021
  return issueDate ? "".concat(moment(issueDate).utc().format('DDHHmm'), "Z") : 'Not issued';
@@ -2421,7 +2422,7 @@ var useDragOrder = function useDragOrder(trigger, move) {
2421
2422
  }; // dialog utils
2422
2423
 
2423
2424
  var getConfirmationDialogTitle = function getConfirmationDialogTitle(action) {
2424
- if (action === 'DISCARD') return 'Discard TAF';
2425
+ if (action === 'CLEAR') return 'Clear TAF';
2425
2426
  if (action === 'PUBLISH') return 'Publish';
2426
2427
  if (action === 'AMEND') return 'This TAF is an amendment';
2427
2428
  if (action === 'CORRECT') return 'This TAF is a correction';
@@ -2446,8 +2447,8 @@ var isTafAmendedCorrectedChanged = function isTafAmendedCorrectedChanged(isFormD
2446
2447
  };
2447
2448
  var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
2448
2449
  switch (action) {
2449
- case 'DISCARD':
2450
- return 'Are you sure you would like to discard this TAF? Any changes made will be lost';
2450
+ case 'CLEAR':
2451
+ return 'Are you sure you would like to clear this TAF? All content will be lost';
2451
2452
 
2452
2453
  case 'PUBLISH':
2453
2454
  return 'Are you sure you want to publish this TAF?';
@@ -2462,9 +2463,9 @@ var getConfirmationDialogContent = function getConfirmationDialogContent(action,
2462
2463
  };
2463
2464
  var getConfirmationDialogButtonLabel = function getConfirmationDialogButtonLabel(action) {
2464
2465
  switch (action) {
2465
- case 'DISCARD':
2466
+ case 'CLEAR':
2466
2467
  {
2467
- return 'Discard';
2468
+ return 'Clear';
2468
2469
  }
2469
2470
 
2470
2471
  case 'CANCEL':
@@ -2555,7 +2556,7 @@ var createChangeGroup = function createChangeGroup(changeGroup) {
2555
2556
  });
2556
2557
  };
2557
2558
  var prepareTafValues = function prepareTafValues(_taf, tafAction) {
2558
- var addEmptyChangeGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
2559
+ var addEmptyChangeGroups = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
2559
2560
 
2560
2561
  var _a; // If action is AMEND/CORRECT/DRAFT_AMEND/DRAFT_CORRECTION - add previous valid start and end
2561
2562
  // If action is AMEND/DRAFT_AMEND - update validity start time to current time
@@ -2568,18 +2569,44 @@ var prepareTafValues = function prepareTafValues(_taf, tafAction) {
2568
2569
  cloud: Object.assign(Object.assign({}, emptyBaseForecast.cloud), formattedBaseForecast.cloud)
2569
2570
  });
2570
2571
  var formattedChangeGroups = ((_a = taf.changeGroups) === null || _a === void 0 ? void 0 : _a.map(formatFormValues)) || [];
2571
- var changeGroups = formattedChangeGroups.map(createChangeGroup); // Add empty changegroup if set tot true
2572
+ var changeGroups = formattedChangeGroups.map(createChangeGroup); // If addEmptyChangeGroups is true - ensure there are at least MIN_NUMBER_CHANGE_GROUP changegroups
2573
+
2574
+ if (addEmptyChangeGroups) {
2575
+ var changeGroupsToAdd = MIN_NUMBER_CHANGE_GROUP - changeGroups.length;
2572
2576
 
2573
- if (addEmptyChangeGroup) {
2574
- changeGroups.push(emptyChangegroup);
2577
+ if (changeGroupsToAdd > 0) {
2578
+ Array.from(Array(changeGroupsToAdd)).map(function () {
2579
+ return changeGroups.push(emptyChangegroup);
2580
+ });
2581
+ }
2575
2582
  }
2576
2583
 
2577
- return Object.assign(Object.assign({}, taf), _defineProperty({
2584
+ return Object.assign(Object.assign({
2585
+ issueDate: '',
2586
+ previousId: null,
2587
+ previousValidDateStart: null,
2588
+ previousValidDateEnd: null
2589
+ }, taf), _defineProperty({
2578
2590
  messageType: getMessageType(taf, tafAction),
2579
2591
  baseForecast: baseForecast,
2580
2592
  changeGroups: changeGroups
2581
2593
  }, HIDDEN_INPUT_HELPER_IS_DRAFT, true));
2582
2594
  };
2595
+ var clearTafFormData = function clearTafFormData(tafFormValues) {
2596
+ // Remove all except for the validity times
2597
+ var baseForecast = {
2598
+ valid: tafFormValues.baseForecast.valid
2599
+ };
2600
+ var emptyChangeGroups = [];
2601
+ Array.from(Array(MIN_NUMBER_CHANGE_GROUP)).map(function () {
2602
+ return emptyChangeGroups.push(emptyChangegroup);
2603
+ });
2604
+ return Object.assign(Object.assign({}, tafFormValues), {
2605
+ baseForecast: Object.assign(Object.assign({}, emptyBaseForecast), baseForecast),
2606
+ // Add empty change groups
2607
+ changeGroups: emptyChangeGroups
2608
+ });
2609
+ };
2583
2610
  var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2584
2611
  return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
2585
2612
  };
@@ -3480,13 +3507,13 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3480
3507
  canBe: canBe,
3481
3508
  onTafViewModeButtonPress: onTafViewModeButtonPress
3482
3509
  }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
3483
- "data-testid": "discardtaf",
3510
+ "data-testid": "cleartaf",
3484
3511
  variant: "tertiary",
3485
3512
  onClick: function onClick() {
3486
3513
  // Simply discard the changes and close the dialog.
3487
- onTafEditModeButtonPress('DISCARD');
3514
+ onTafEditModeButtonPress('CLEAR');
3488
3515
  }
3489
- }, "Discard"), /*#__PURE__*/React__default.createElement(Button, {
3516
+ }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
3490
3517
  "data-testid": "savedrafttaf",
3491
3518
  variant: "tertiary",
3492
3519
  onClick: function onClick() {
@@ -3553,9 +3580,7 @@ var DragHandle = function DragHandle(_ref) {
3553
3580
  '&:hover': {
3554
3581
  backgroundColor: 'transparent'
3555
3582
  },
3556
- cursor: function cursor() {
3557
- return isSorting ? 'grabbing' : 'grab';
3558
- }
3583
+ cursor: isSorting ? 'grabbing' : 'grab'
3559
3584
  }
3560
3585
  }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
3561
3586
  };
@@ -4013,9 +4038,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4013
4038
  onStartDrag = _useDragOrder.onStartDrag,
4014
4039
  activeDraggingIndex = _useDragOrder.activeDraggingIndex;
4015
4040
 
4016
- var dirtyFields = formState.dirtyFields,
4041
+ var isFormDirty = formState.isDirty,
4017
4042
  errors = formState.errors;
4018
- var isFormDirty = Object.keys(dirtyFields).length > 0;
4019
4043
  usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4020
4044
 
4021
4045
  React__default.useEffect(function () {
@@ -4039,8 +4063,9 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4039
4063
  };
4040
4064
 
4041
4065
  var resetFormValues = function resetFormValues(formData) {
4066
+ var keepDirty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4042
4067
  reset(formData, {
4043
- keepDirty: false,
4068
+ keepDirty: keepDirty,
4044
4069
  keepDirtyValues: false
4045
4070
  });
4046
4071
  };
@@ -4049,7 +4074,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4049
4074
  var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
4050
4075
  var resetDisabled = arguments.length > 1 ? arguments[1] : undefined;
4051
4076
  var tafToReset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : originalTaf;
4052
- var shouldAddEmptyChangGroup = !(tafToReset && tafToReset.changeGroups) && !resetDisabled;
4077
+ var shouldAddEmptyChangGroup = !resetDisabled;
4053
4078
  var newTaf = prepareTafValues(tafToReset, action, shouldAddEmptyChangGroup);
4054
4079
  resetFormValues(newTaf);
4055
4080
  setIsDisabled(resetDisabled);
@@ -4187,15 +4212,18 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4187
4212
  })();
4188
4213
  break;
4189
4214
 
4190
- case 'DISCARD':
4191
- if (isFormDirty) {
4192
- showConfirmDialog(action).then(function () {
4193
- resetFormState(undefined, isDefaultDisabled);
4194
- });
4195
- } else {
4196
- resetFormState(undefined, isDefaultDisabled);
4197
- }
4215
+ case 'CLEAR':
4216
+ showConfirmDialog(action).then(function () {
4217
+ var emptiedForm = clearTafFormData(getValues()); // Trigger an invisible change to dirty the form
4218
+ // This is needed to trigger the autosave on changing location/time
4198
4219
 
4220
+ var baseForecastFields = getFieldNames(false, -1);
4221
+ setValue(baseForecastFields.wind, ' ', {
4222
+ shouldDirty: true
4223
+ });
4224
+ resetFormValues(emptiedForm, true);
4225
+ showSnackbar('TAF has been cleared');
4226
+ });
4199
4227
  break;
4200
4228
 
4201
4229
  case 'AMEND':
@@ -4369,7 +4397,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4369
4397
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4370
4398
  }, []);
4371
4399
  React__default.useEffect(function () {
4372
- var newValues = prepareTafValues(originalTaf, undefined, !isDefaultDisabled && !originalTaf.changeGroups); // set new form values when taf values changed
4400
+ var newValues = prepareTafValues(originalTaf, undefined, !isDefaultDisabled); // set new form values when taf values changed
4373
4401
 
4374
4402
  resetFormValues(newValues); // eslint-disable-next-line react-hooks/exhaustive-deps
4375
4403
  }, [originalTaf]);
@@ -4431,10 +4459,10 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4431
4459
  handle: ".handle",
4432
4460
  direction: "vertical",
4433
4461
  // hover props
4434
- forceFallback: true,
4462
+ forceFallback: false,
4435
4463
  onStart: function onStart(event) {
4436
4464
  onStartDrag(event);
4437
- Sortable.ghost.style.opacity = '1';
4465
+ if (Sortable.ghost) Sortable.ghost.style.opacity = '1';
4438
4466
  }
4439
4467
  }, fields.map(function (item, index) {
4440
4468
  return /*#__PURE__*/React__default.createElement(TafFormRow, {
@@ -4741,69 +4769,72 @@ var IconWithTooltip = function IconWithTooltip(_ref) {
4741
4769
  children = _ref.children;
4742
4770
  return /*#__PURE__*/React.createElement(CustomTooltip, {
4743
4771
  title: title,
4744
- placement: "right"
4772
+ placement: "right",
4773
+ "data-testid": "statusIcon-tooltip"
4745
4774
  }, /*#__PURE__*/React.createElement(Box, {
4746
4775
  component: "span"
4747
4776
  }, children));
4748
4777
  };
4749
4778
 
4750
4779
  var StatusIcon = function StatusIcon(_ref2) {
4751
- var timeSlot = _ref2.timeSlot,
4752
- status = _ref2.status;
4780
+ var status = _ref2.status,
4781
+ timeSlot = _ref2.timeSlot;
4753
4782
 
4754
- if (status === 'NEW') {
4755
- return null;
4756
- }
4783
+ switch (status) {
4784
+ case 'DRAFT':
4785
+ case 'DRAFT_AMENDED':
4786
+ case 'DRAFT_CORRECTED':
4787
+ return /*#__PURE__*/React.createElement(IconWithTooltip, {
4788
+ title: getTafStatusLabel(status)
4789
+ }, /*#__PURE__*/React.createElement(Edit, {
4790
+ "data-testid": "status-draft",
4791
+ sx: {
4792
+ color: 'geowebColors.buttons.tertiary.default.color'
4793
+ }
4794
+ }));
4757
4795
 
4758
- if (status === 'EXPIRED') {
4759
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4760
- title: "Expired"
4761
- }, /*#__PURE__*/React.createElement(Clock, {
4762
- "data-testid": "status-expired",
4763
- sx: {
4764
- transform: 'scaleX(-1)',
4765
- color: 'geowebColors.buttons.tertiary.disabled.color'
4766
- }
4767
- }));
4768
- }
4796
+ case 'PUBLISHED':
4797
+ case 'CORRECTED':
4798
+ case 'AMENDED':
4799
+ return /*#__PURE__*/React.createElement(IconWithTooltip, {
4800
+ title: getTafStatusLabel(status)
4801
+ }, timeSlot === 'ACTIVE' ? /*#__PURE__*/React.createElement(Success, {
4802
+ "data-testid": "status-active",
4803
+ sx: {
4804
+ color: 'geowebColors.functional.success'
4805
+ }
4806
+ }) : /*#__PURE__*/React.createElement(Clock, {
4807
+ "data-testid": "status-upcoming",
4808
+ sx: {
4809
+ color: 'geowebColors.functional.success'
4810
+ }
4811
+ }));
4769
4812
 
4770
- if (status === 'CANCELLED') {
4771
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4772
- title: "Cancelled"
4773
- }, /*#__PURE__*/React.createElement(Cancel, {
4774
- "data-testid": "status-cancelled",
4775
- sx: {
4776
- color: 'geowebColors.captions.captionError.rgba'
4777
- }
4778
- }));
4779
- }
4813
+ case 'CANCELLED':
4814
+ return /*#__PURE__*/React.createElement(IconWithTooltip, {
4815
+ title: getTafStatusLabel(status)
4816
+ }, /*#__PURE__*/React.createElement(Cancel, {
4817
+ "data-testid": "status-cancelled",
4818
+ sx: {
4819
+ color: 'geowebColors.captions.captionError.rgba'
4820
+ }
4821
+ }));
4780
4822
 
4781
- if (status === 'DRAFT' || status === 'DRAFT_CORRECTED' || status === 'DRAFT_AMENDED') {
4782
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4783
- title: "Draft"
4784
- }, /*#__PURE__*/React.createElement(Edit, {
4785
- "data-testid": "status-draft",
4786
- sx: {
4787
- color: 'geowebColors.buttons.tertiary.default.color'
4788
- }
4789
- }));
4790
- }
4823
+ case 'EXPIRED':
4824
+ return /*#__PURE__*/React.createElement(IconWithTooltip, {
4825
+ title: getTafStatusLabel(status)
4826
+ }, /*#__PURE__*/React.createElement(Clock, {
4827
+ "data-testid": "status-expired",
4828
+ sx: {
4829
+ transform: 'scaleX(-1)',
4830
+ color: 'geowebColors.buttons.tertiary.disabled.color'
4831
+ }
4832
+ }));
4791
4833
 
4792
- return timeSlot === 'ACTIVE' ? /*#__PURE__*/React.createElement(IconWithTooltip, {
4793
- title: "Active"
4794
- }, /*#__PURE__*/React.createElement(Success, {
4795
- "data-testid": "status-active",
4796
- sx: {
4797
- color: 'geowebColors.functional.success'
4798
- }
4799
- })) : /*#__PURE__*/React.createElement(IconWithTooltip, {
4800
- title: "Upcoming"
4801
- }, /*#__PURE__*/React.createElement(Clock, {
4802
- "data-testid": "status-upcoming",
4803
- sx: {
4804
- color: 'geowebColors.functional.success'
4805
- }
4806
- }));
4834
+ case 'NEW':
4835
+ default:
4836
+ return null;
4837
+ }
4807
4838
  };
4808
4839
 
4809
4840
  /* *
@@ -4849,8 +4880,8 @@ var ExportButton = function ExportButton(_ref) {
4849
4880
  * See the License for the specific language governing permissions and
4850
4881
  * limitations under the License.
4851
4882
  *
4852
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4853
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
4883
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4884
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
4854
4885
  * */
4855
4886
  var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_ref) {
4856
4887
  var TAC = _ref.TAC,
@@ -4881,7 +4912,8 @@ var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_ref) {
4881
4912
  }, isActive && {
4882
4913
  backgroundColor: 'geowebColors.functional.warningHighlight.rgba'
4883
4914
  }), word.type === 'adverse' && {
4884
- color: 'geowebColors.captions.captionError.rgba'
4915
+ color: 'geowebColors.captions.captionError.rgba',
4916
+ fontWeight: 'bold'
4885
4917
  })
4886
4918
  }, word.text === '=' ? "".concat(word.text) : " ".concat(word.text));
4887
4919
  }));
@@ -5229,9 +5261,7 @@ var TopTabs = function TopTabs(_ref) {
5229
5261
  } : _ref$tafFromBackend;
5230
5262
 
5231
5263
  var _useFormContext = useFormContext(),
5232
- dirtyFields = _useFormContext.formState.dirtyFields;
5233
-
5234
- var isDirty = Object.keys(dirtyFields).length > 0;
5264
+ isDirty = _useFormContext.formState.isDirty;
5235
5265
 
5236
5266
  if (!tafFromBackend) {
5237
5267
  return null;
@@ -5299,9 +5329,8 @@ var LocationTabs = function LocationTabs(_ref) {
5299
5329
  timeSlot = _ref.timeSlot;
5300
5330
 
5301
5331
  var _useFormContext = useFormContext(),
5302
- dirtyFields = _useFormContext.formState.dirtyFields;
5332
+ isDirty = _useFormContext.formState.isDirty;
5303
5333
 
5304
- var isDirty = Object.keys(dirtyFields).length > 0;
5305
5334
  return /*#__PURE__*/React.createElement(MenuList, {
5306
5335
  "data-testid": "location-tabs",
5307
5336
  sx: {
package/index.umd.js CHANGED
@@ -2015,7 +2015,8 @@
2015
2015
  cloud3: '',
2016
2016
  cloud4: ''
2017
2017
  }
2018
- }; // formatters
2018
+ };
2019
+ var MIN_NUMBER_CHANGE_GROUP = 5; // formatters
2019
2020
 
2020
2021
  var formatIssueTime = function formatIssueTime(issueDate) {
2021
2022
  return issueDate ? moment__default["default"](issueDate).utc().format('DDHHmm') + "Z" : 'Not issued';
@@ -2423,7 +2424,7 @@
2423
2424
  }; // dialog utils
2424
2425
 
2425
2426
  var getConfirmationDialogTitle = function getConfirmationDialogTitle(action) {
2426
- if (action === 'DISCARD') return 'Discard TAF';
2427
+ if (action === 'CLEAR') return 'Clear TAF';
2427
2428
  if (action === 'PUBLISH') return 'Publish';
2428
2429
  if (action === 'AMEND') return 'This TAF is an amendment';
2429
2430
  if (action === 'CORRECT') return 'This TAF is a correction';
@@ -2448,8 +2449,8 @@
2448
2449
  };
2449
2450
  var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
2450
2451
  switch (action) {
2451
- case 'DISCARD':
2452
- return 'Are you sure you would like to discard this TAF? Any changes made will be lost';
2452
+ case 'CLEAR':
2453
+ return 'Are you sure you would like to clear this TAF? All content will be lost';
2453
2454
 
2454
2455
  case 'PUBLISH':
2455
2456
  return 'Are you sure you want to publish this TAF?';
@@ -2464,9 +2465,9 @@
2464
2465
  };
2465
2466
  var getConfirmationDialogButtonLabel = function getConfirmationDialogButtonLabel(action) {
2466
2467
  switch (action) {
2467
- case 'DISCARD':
2468
+ case 'CLEAR':
2468
2469
  {
2469
- return 'Discard';
2470
+ return 'Clear';
2470
2471
  }
2471
2472
 
2472
2473
  case 'CANCEL':
@@ -2556,13 +2557,13 @@
2556
2557
  cloud: __assign(__assign({}, emptyChangegroup.cloud), changeGroup.cloud)
2557
2558
  });
2558
2559
  };
2559
- var prepareTafValues = function prepareTafValues(_taf, tafAction, addEmptyChangeGroup) {
2560
+ var prepareTafValues = function prepareTafValues(_taf, tafAction, addEmptyChangeGroups) {
2560
2561
  var _a;
2561
2562
 
2562
2563
  var _b;
2563
2564
 
2564
- if (addEmptyChangeGroup === void 0) {
2565
- addEmptyChangeGroup = false;
2565
+ if (addEmptyChangeGroups === void 0) {
2566
+ addEmptyChangeGroups = false;
2566
2567
  } // If action is AMEND/CORRECT/DRAFT_AMEND/DRAFT_CORRECTION - add previous valid start and end
2567
2568
  // If action is AMEND/DRAFT_AMEND - update validity start time to current time
2568
2569
 
@@ -2576,18 +2577,44 @@
2576
2577
  });
2577
2578
 
2578
2579
  var formattedChangeGroups = ((_b = taf.changeGroups) === null || _b === void 0 ? void 0 : _b.map(formatFormValues)) || [];
2579
- var changeGroups = formattedChangeGroups.map(createChangeGroup); // Add empty changegroup if set tot true
2580
+ var changeGroups = formattedChangeGroups.map(createChangeGroup); // If addEmptyChangeGroups is true - ensure there are at least MIN_NUMBER_CHANGE_GROUP changegroups
2581
+
2582
+ if (addEmptyChangeGroups) {
2583
+ var changeGroupsToAdd = MIN_NUMBER_CHANGE_GROUP - changeGroups.length;
2580
2584
 
2581
- if (addEmptyChangeGroup) {
2582
- changeGroups.push(emptyChangegroup);
2585
+ if (changeGroupsToAdd > 0) {
2586
+ Array.from(Array(changeGroupsToAdd)).map(function () {
2587
+ return changeGroups.push(emptyChangegroup);
2588
+ });
2589
+ }
2583
2590
  }
2584
2591
 
2585
- return __assign(__assign({}, taf), (_a = {
2592
+ return __assign(__assign({
2593
+ issueDate: '',
2594
+ previousId: null,
2595
+ previousValidDateStart: null,
2596
+ previousValidDateEnd: null
2597
+ }, taf), (_a = {
2586
2598
  messageType: getMessageType(taf, tafAction),
2587
2599
  baseForecast: baseForecast,
2588
2600
  changeGroups: changeGroups
2589
2601
  }, _a[shared.HIDDEN_INPUT_HELPER_IS_DRAFT] = true, _a));
2590
2602
  };
2603
+ var clearTafFormData = function clearTafFormData(tafFormValues) {
2604
+ // Remove all except for the validity times
2605
+ var baseForecast = {
2606
+ valid: tafFormValues.baseForecast.valid
2607
+ };
2608
+ var emptyChangeGroups = [];
2609
+ Array.from(Array(MIN_NUMBER_CHANGE_GROUP)).map(function () {
2610
+ return emptyChangeGroups.push(emptyChangegroup);
2611
+ });
2612
+ return __assign(__assign({}, tafFormValues), {
2613
+ baseForecast: __assign(__assign({}, emptyBaseForecast), baseForecast),
2614
+ // Add empty change groups
2615
+ changeGroups: emptyChangeGroups
2616
+ });
2617
+ };
2591
2618
  var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2592
2619
  return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
2593
2620
  };
@@ -3484,13 +3511,13 @@
3484
3511
  canBe: canBe,
3485
3512
  onTafViewModeButtonPress: onTafViewModeButtonPress
3486
3513
  }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Button, {
3487
- "data-testid": "discardtaf",
3514
+ "data-testid": "cleartaf",
3488
3515
  variant: "tertiary",
3489
3516
  onClick: function onClick() {
3490
3517
  // Simply discard the changes and close the dialog.
3491
- onTafEditModeButtonPress('DISCARD');
3518
+ onTafEditModeButtonPress('CLEAR');
3492
3519
  }
3493
- }, "Discard"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3520
+ }, "Clear"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3494
3521
  "data-testid": "savedrafttaf",
3495
3522
  variant: "tertiary",
3496
3523
  onClick: function onClick() {
@@ -3557,9 +3584,7 @@
3557
3584
  '&:hover': {
3558
3585
  backgroundColor: 'transparent'
3559
3586
  },
3560
- cursor: function cursor() {
3561
- return isSorting ? 'grabbing' : 'grab';
3562
- }
3587
+ cursor: isSorting ? 'grabbing' : 'grab'
3563
3588
  }
3564
3589
  }, /*#__PURE__*/React__default["default"].createElement(theme.DragHandle, null));
3565
3590
  };
@@ -4015,9 +4040,8 @@
4015
4040
  onStartDrag = _o.onStartDrag,
4016
4041
  activeDraggingIndex = _o.activeDraggingIndex;
4017
4042
 
4018
- var dirtyFields = formState.dirtyFields,
4043
+ var isFormDirty = formState.isDirty,
4019
4044
  errors = formState.errors;
4020
- var isFormDirty = Object.keys(dirtyFields).length > 0;
4021
4045
  shared.usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4022
4046
 
4023
4047
  React__default["default"].useEffect(function () {
@@ -4040,9 +4064,13 @@
4040
4064
  });
4041
4065
  };
4042
4066
 
4043
- var resetFormValues = function resetFormValues(formData) {
4067
+ var resetFormValues = function resetFormValues(formData, keepDirty) {
4068
+ if (keepDirty === void 0) {
4069
+ keepDirty = false;
4070
+ }
4071
+
4044
4072
  reset(formData, {
4045
- keepDirty: false,
4073
+ keepDirty: keepDirty,
4046
4074
  keepDirtyValues: false
4047
4075
  });
4048
4076
  };
@@ -4056,7 +4084,7 @@
4056
4084
  tafToReset = originalTaf;
4057
4085
  }
4058
4086
 
4059
- var shouldAddEmptyChangGroup = !(tafToReset && tafToReset.changeGroups) && !resetDisabled;
4087
+ var shouldAddEmptyChangGroup = !resetDisabled;
4060
4088
  var newTaf = prepareTafValues(tafToReset, action, shouldAddEmptyChangGroup);
4061
4089
  resetFormValues(newTaf);
4062
4090
  setIsDisabled(resetDisabled);
@@ -4191,15 +4219,18 @@
4191
4219
  })();
4192
4220
  break;
4193
4221
 
4194
- case 'DISCARD':
4195
- if (isFormDirty) {
4196
- showConfirmDialog(action).then(function () {
4197
- resetFormState(undefined, isDefaultDisabled);
4198
- });
4199
- } else {
4200
- resetFormState(undefined, isDefaultDisabled);
4201
- }
4222
+ case 'CLEAR':
4223
+ showConfirmDialog(action).then(function () {
4224
+ var emptiedForm = clearTafFormData(getValues()); // Trigger an invisible change to dirty the form
4225
+ // This is needed to trigger the autosave on changing location/time
4202
4226
 
4227
+ var baseForecastFields = getFieldNames(false, -1);
4228
+ setValue(baseForecastFields.wind, ' ', {
4229
+ shouldDirty: true
4230
+ });
4231
+ resetFormValues(emptiedForm, true);
4232
+ showSnackbar('TAF has been cleared');
4233
+ });
4203
4234
  break;
4204
4235
 
4205
4236
  case 'AMEND':
@@ -4388,7 +4419,7 @@
4388
4419
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4389
4420
  }, []);
4390
4421
  React__default["default"].useEffect(function () {
4391
- var newValues = prepareTafValues(originalTaf, undefined, !isDefaultDisabled && !originalTaf.changeGroups); // set new form values when taf values changed
4422
+ var newValues = prepareTafValues(originalTaf, undefined, !isDefaultDisabled); // set new form values when taf values changed
4392
4423
 
4393
4424
  resetFormValues(newValues); // eslint-disable-next-line react-hooks/exhaustive-deps
4394
4425
  }, [originalTaf]);
@@ -4450,10 +4481,10 @@
4450
4481
  handle: ".handle",
4451
4482
  direction: "vertical",
4452
4483
  // hover props
4453
- forceFallback: true,
4484
+ forceFallback: false,
4454
4485
  onStart: function onStart(event) {
4455
4486
  onStartDrag(event);
4456
- Sortable__default["default"].ghost.style.opacity = '1';
4487
+ if (Sortable__default["default"].ghost) Sortable__default["default"].ghost.style.opacity = '1';
4457
4488
  }
4458
4489
  }, fields.map(function (item, index) {
4459
4490
  return /*#__PURE__*/React__default["default"].createElement(TafFormRow, {
@@ -4755,69 +4786,72 @@
4755
4786
  children = _a.children;
4756
4787
  return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
4757
4788
  title: title,
4758
- placement: "right"
4789
+ placement: "right",
4790
+ "data-testid": "statusIcon-tooltip"
4759
4791
  }, /*#__PURE__*/React__namespace.createElement(material.Box, {
4760
4792
  component: "span"
4761
4793
  }, children));
4762
4794
  };
4763
4795
 
4764
4796
  var StatusIcon = function StatusIcon(_a) {
4765
- var timeSlot = _a.timeSlot,
4766
- status = _a.status;
4797
+ var status = _a.status,
4798
+ timeSlot = _a.timeSlot;
4767
4799
 
4768
- if (status === 'NEW') {
4769
- return null;
4770
- }
4800
+ switch (status) {
4801
+ case 'DRAFT':
4802
+ case 'DRAFT_AMENDED':
4803
+ case 'DRAFT_CORRECTED':
4804
+ return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4805
+ title: getTafStatusLabel(status)
4806
+ }, /*#__PURE__*/React__namespace.createElement(theme.Edit, {
4807
+ "data-testid": "status-draft",
4808
+ sx: {
4809
+ color: 'geowebColors.buttons.tertiary.default.color'
4810
+ }
4811
+ }));
4771
4812
 
4772
- if (status === 'EXPIRED') {
4773
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4774
- title: "Expired"
4775
- }, /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4776
- "data-testid": "status-expired",
4777
- sx: {
4778
- transform: 'scaleX(-1)',
4779
- color: 'geowebColors.buttons.tertiary.disabled.color'
4780
- }
4781
- }));
4782
- }
4813
+ case 'PUBLISHED':
4814
+ case 'CORRECTED':
4815
+ case 'AMENDED':
4816
+ return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4817
+ title: getTafStatusLabel(status)
4818
+ }, timeSlot === 'ACTIVE' ? /*#__PURE__*/React__namespace.createElement(theme.Success, {
4819
+ "data-testid": "status-active",
4820
+ sx: {
4821
+ color: 'geowebColors.functional.success'
4822
+ }
4823
+ }) : /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4824
+ "data-testid": "status-upcoming",
4825
+ sx: {
4826
+ color: 'geowebColors.functional.success'
4827
+ }
4828
+ }));
4783
4829
 
4784
- if (status === 'CANCELLED') {
4785
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4786
- title: "Cancelled"
4787
- }, /*#__PURE__*/React__namespace.createElement(theme.Cancel, {
4788
- "data-testid": "status-cancelled",
4789
- sx: {
4790
- color: 'geowebColors.captions.captionError.rgba'
4791
- }
4792
- }));
4793
- }
4830
+ case 'CANCELLED':
4831
+ return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4832
+ title: getTafStatusLabel(status)
4833
+ }, /*#__PURE__*/React__namespace.createElement(theme.Cancel, {
4834
+ "data-testid": "status-cancelled",
4835
+ sx: {
4836
+ color: 'geowebColors.captions.captionError.rgba'
4837
+ }
4838
+ }));
4794
4839
 
4795
- if (status === 'DRAFT' || status === 'DRAFT_CORRECTED' || status === 'DRAFT_AMENDED') {
4796
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4797
- title: "Draft"
4798
- }, /*#__PURE__*/React__namespace.createElement(theme.Edit, {
4799
- "data-testid": "status-draft",
4800
- sx: {
4801
- color: 'geowebColors.buttons.tertiary.default.color'
4802
- }
4803
- }));
4804
- }
4840
+ case 'EXPIRED':
4841
+ return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4842
+ title: getTafStatusLabel(status)
4843
+ }, /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4844
+ "data-testid": "status-expired",
4845
+ sx: {
4846
+ transform: 'scaleX(-1)',
4847
+ color: 'geowebColors.buttons.tertiary.disabled.color'
4848
+ }
4849
+ }));
4805
4850
 
4806
- return timeSlot === 'ACTIVE' ? /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4807
- title: "Active"
4808
- }, /*#__PURE__*/React__namespace.createElement(theme.Success, {
4809
- "data-testid": "status-active",
4810
- sx: {
4811
- color: 'geowebColors.functional.success'
4812
- }
4813
- })) : /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4814
- title: "Upcoming"
4815
- }, /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4816
- "data-testid": "status-upcoming",
4817
- sx: {
4818
- color: 'geowebColors.functional.success'
4819
- }
4820
- }));
4851
+ case 'NEW':
4852
+ default:
4853
+ return null;
4854
+ }
4821
4855
  };
4822
4856
 
4823
4857
  /* *
@@ -4863,8 +4897,8 @@
4863
4897
  * See the License for the specific language governing permissions and
4864
4898
  * limitations under the License.
4865
4899
  *
4866
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4867
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
4900
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4901
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
4868
4902
  * */
4869
4903
  var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_a) {
4870
4904
  var TAC = _a.TAC,
@@ -4895,7 +4929,8 @@
4895
4929
  }, isActive && {
4896
4930
  backgroundColor: 'geowebColors.functional.warningHighlight.rgba'
4897
4931
  }), word.type === 'adverse' && {
4898
- color: 'geowebColors.captions.captionError.rgba'
4932
+ color: 'geowebColors.captions.captionError.rgba',
4933
+ fontWeight: 'bold'
4899
4934
  })
4900
4935
  }, word.text === '=' ? "" + word.text : " " + word.text);
4901
4936
  }));
@@ -5235,8 +5270,7 @@
5235
5270
  location: 'EHAM'
5236
5271
  }
5237
5272
  } : _c;
5238
- var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5239
- var isDirty = Object.keys(dirtyFields).length > 0;
5273
+ var isDirty = reactHookForm.useFormContext().formState.isDirty;
5240
5274
 
5241
5275
  if (!tafFromBackend) {
5242
5276
  return null;
@@ -5302,8 +5336,7 @@
5302
5336
  _c = _a.onChangeTab,
5303
5337
  onChangeTab = _c === void 0 ? function () {} : _c,
5304
5338
  timeSlot = _a.timeSlot;
5305
- var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5306
- var isDirty = Object.keys(dirtyFields).length > 0;
5339
+ var isDirty = reactHookForm.useFormContext().formState.isDirty;
5307
5340
  return /*#__PURE__*/React__namespace.createElement(material.MenuList, {
5308
5341
  "data-testid": "location-tabs",
5309
5342
  sx: {
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { TafStatus, TimeSlot } from '../../types';
3
3
  interface StatusIconProps {
4
- timeSlot: TimeSlot;
5
4
  status: TafStatus;
5
+ timeSlot: TimeSlot;
6
6
  }
7
7
  declare const StatusIcon: React.FC<StatusIconProps>;
8
8
  export default StatusIcon;
@@ -16,6 +16,7 @@ export declare const emptyBaseForecast: {
16
16
  cloud4: string;
17
17
  };
18
18
  };
19
+ export declare const MIN_NUMBER_CHANGE_GROUP = 5;
19
20
  export declare const formatIssueTime: (issueDate: string) => string;
20
21
  declare type BaseForecastOrChangeGroupFormData<T extends BaseForecast | ChangeGroup> = T extends ChangeGroup ? ChangeGroupFormData : BaseForecastFormData;
21
22
  export declare function formatFormValues<T extends BaseForecast | ChangeGroup>(row: T): BaseForecastOrChangeGroupFormData<T>;
@@ -67,7 +68,8 @@ export declare const getTafStatusLabel: (status: TafStatus) => string;
67
68
  export declare const getMessageType: (taf: Taf, tafAction: TafActions) => string;
68
69
  export declare const getAmendedCorrectedTafTimes: (taf: Taf, tafAction: TafActions) => Taf;
69
70
  export declare const createChangeGroup: (changeGroup: ChangeGroupFormData) => ChangeGroupFormData;
70
- export declare const prepareTafValues: (_taf: Taf, tafAction: TafActions, addEmptyChangeGroup?: boolean) => TafFormData;
71
+ export declare const prepareTafValues: (_taf: Taf, tafAction: TafActions, addEmptyChangeGroups?: boolean) => TafFormData;
72
+ export declare const clearTafFormData: (tafFormValues: TafFormData) => TafFormData;
71
73
  export declare const getIsFormDefaultDisabled: (status: TafStatus) => boolean;
72
74
  export declare const fromStatusToAction: (tafStatus: TafStatus) => TafActions;
73
75
  export {};
package/lib/types.d.ts CHANGED
@@ -67,7 +67,7 @@ export interface BaseTaf {
67
67
  issueDate?: TafDate;
68
68
  }
69
69
  export declare type TafStatus = 'NEW' | 'DRAFT' | 'DRAFT_AMENDED' | 'DRAFT_CORRECTED' | 'PUBLISHED' | 'CORRECTED' | 'AMENDED' | 'CANCELLED' | 'EXPIRED';
70
- export declare type TafActions = 'NEW' | 'DRAFT' | 'DRAFT_AMEND' | 'DRAFT_CORRECT' | 'PUBLISH' | 'CANCEL' | 'CORRECT' | 'AMEND' | 'CLOSE' | 'DISCARD';
70
+ export declare type TafActions = 'NEW' | 'DRAFT' | 'DRAFT_AMEND' | 'DRAFT_CORRECT' | 'PUBLISH' | 'CANCEL' | 'CORRECT' | 'AMEND' | 'CLOSE' | 'CLEAR';
71
71
  export declare type TafCanbe = 'DRAFTED' | 'DISCARDED' | 'PUBLISHED' | 'CANCELLED' | 'AMENDED' | 'CORRECTED';
72
72
  export interface Taf extends BaseTaf {
73
73
  status: TafStatus;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeoweb/taf",
3
- "version": "4.9.1",
3
+ "version": "4.10.0",
4
4
  "description": "GeoWeb TAF library for the opengeoweb project",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -12,32 +12,32 @@
12
12
  "typings": "./index.d.ts",
13
13
  "dependencies": {},
14
14
  "peerDependencies": {
15
- "@opengeoweb/core": "4.9.1",
15
+ "@opengeoweb/api": "4.10.0",
16
16
  "react": "^17.0.2",
17
- "@opengeoweb/shared": "4.9.1",
17
+ "axios": "^0.25.0",
18
+ "@opengeoweb/shared": "4.10.0",
18
19
  "@mui/material": "^5.10.8",
19
- "@opengeoweb/theme": "4.9.1",
20
+ "@opengeoweb/theme": "4.10.0",
20
21
  "react-draggable": "^4.4.5",
21
22
  "re-resizable": "^6.9.0",
22
23
  "@redux-eggs/core": "^2.2.0",
23
24
  "react-redux": "^8.0.4",
24
- "@opengeoweb/form-fields": "4.9.1",
25
+ "@opengeoweb/form-fields": "4.10.0",
25
26
  "react-hook-form": "^7.41.5",
26
27
  "moment": "^2.29.0",
27
28
  "moment-timezone": "^0.5.31",
28
29
  "@mui/x-date-pickers": "^5.0.4",
29
30
  "lodash": "^4.17.20",
30
- "axios": "^0.25.0",
31
31
  "date-fns": "^2.29.3",
32
- "@opengeoweb/webmap": "4.9.1",
32
+ "@opengeoweb/core": "4.10.0",
33
+ "@opengeoweb/webmap": "4.10.0",
33
34
  "throttle-debounce": "^3.0.1",
34
35
  "proj4": "^2.6.2",
35
- "@opengeoweb/api": "4.9.1",
36
36
  "react-intl": "^5.17.5",
37
37
  "react-sortablejs": "^6.1.4",
38
38
  "sortablejs": "^1.15.0",
39
- "react-window": "^1.8.7",
40
39
  "immer": "^9.0.15",
40
+ "react-window": "^1.8.7",
41
41
  "@reduxjs/toolkit": "^1.8.3",
42
42
  "lodash.clonedeep": "^4.5.0",
43
43
  "@turf/turf": "^5.1.6",
@@ -46,7 +46,7 @@
46
46
  "@redux-eggs/redux-toolkit": "^2.2.0",
47
47
  "@redux-eggs/saga-extension": "^2.2.0",
48
48
  "react-dom": "^17.0.2",
49
- "@opengeoweb/authentication": "4.9.1",
49
+ "@opengeoweb/authentication": "4.10.0",
50
50
  "react-router-dom": "^6.4.2",
51
51
  "query-string": "^6.13.7"
52
52
  }