@opengeoweb/taf 4.8.0 → 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,15 +2569,43 @@ 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);
2572
- return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, taf), {
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;
2576
+
2577
+ if (changeGroupsToAdd > 0) {
2578
+ Array.from(Array(changeGroupsToAdd)).map(function () {
2579
+ return changeGroups.push(emptyChangegroup);
2580
+ });
2581
+ }
2582
+ }
2583
+
2584
+ return Object.assign(Object.assign({
2585
+ issueDate: '',
2586
+ previousId: null,
2587
+ previousValidDateStart: null,
2588
+ previousValidDateEnd: null
2589
+ }, taf), _defineProperty({
2573
2590
  messageType: getMessageType(taf, tafAction),
2574
- baseForecast: baseForecast
2575
- }), changeGroups.length && {
2591
+ baseForecast: baseForecast,
2576
2592
  changeGroups: changeGroups
2577
- }), addEmptyChangeGroup && {
2578
- changeGroups: [emptyChangegroup]
2579
- }), _defineProperty({}, HIDDEN_INPUT_HELPER_IS_DRAFT, true));
2593
+ }, HIDDEN_INPUT_HELPER_IS_DRAFT, true));
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
+ });
2580
2609
  };
2581
2610
  var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2582
2611
  return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
@@ -3478,13 +3507,13 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3478
3507
  canBe: canBe,
3479
3508
  onTafViewModeButtonPress: onTafViewModeButtonPress
3480
3509
  }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Button, {
3481
- "data-testid": "discardtaf",
3510
+ "data-testid": "cleartaf",
3482
3511
  variant: "tertiary",
3483
3512
  onClick: function onClick() {
3484
3513
  // Simply discard the changes and close the dialog.
3485
- onTafEditModeButtonPress('DISCARD');
3514
+ onTafEditModeButtonPress('CLEAR');
3486
3515
  }
3487
- }, "Discard"), /*#__PURE__*/React__default.createElement(Button, {
3516
+ }, "Clear"), /*#__PURE__*/React__default.createElement(Button, {
3488
3517
  "data-testid": "savedrafttaf",
3489
3518
  variant: "tertiary",
3490
3519
  onClick: function onClick() {
@@ -3551,9 +3580,7 @@ var DragHandle = function DragHandle(_ref) {
3551
3580
  '&:hover': {
3552
3581
  backgroundColor: 'transparent'
3553
3582
  },
3554
- cursor: function cursor() {
3555
- return isSorting ? 'grabbing' : 'grab';
3556
- }
3583
+ cursor: isSorting ? 'grabbing' : 'grab'
3557
3584
  }
3558
3585
  }, /*#__PURE__*/React__default.createElement(DragHandle$1, null));
3559
3586
  };
@@ -4011,9 +4038,8 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4011
4038
  onStartDrag = _useDragOrder.onStartDrag,
4012
4039
  activeDraggingIndex = _useDragOrder.activeDraggingIndex;
4013
4040
 
4014
- var dirtyFields = formState.dirtyFields,
4041
+ var isFormDirty = formState.isDirty,
4015
4042
  errors = formState.errors;
4016
- var isFormDirty = Object.keys(dirtyFields).length > 0;
4017
4043
  usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4018
4044
 
4019
4045
  React__default.useEffect(function () {
@@ -4037,8 +4063,9 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4037
4063
  };
4038
4064
 
4039
4065
  var resetFormValues = function resetFormValues(formData) {
4066
+ var keepDirty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4040
4067
  reset(formData, {
4041
- keepDirty: false,
4068
+ keepDirty: keepDirty,
4042
4069
  keepDirtyValues: false
4043
4070
  });
4044
4071
  };
@@ -4047,7 +4074,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4047
4074
  var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined;
4048
4075
  var resetDisabled = arguments.length > 1 ? arguments[1] : undefined;
4049
4076
  var tafToReset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : originalTaf;
4050
- var shouldAddEmptyChangGroup = !(tafToReset && tafToReset.changeGroups) && !resetDisabled;
4077
+ var shouldAddEmptyChangGroup = !resetDisabled;
4051
4078
  var newTaf = prepareTafValues(tafToReset, action, shouldAddEmptyChangGroup);
4052
4079
  resetFormValues(newTaf);
4053
4080
  setIsDisabled(resetDisabled);
@@ -4185,15 +4212,18 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4185
4212
  })();
4186
4213
  break;
4187
4214
 
4188
- case 'DISCARD':
4189
- if (isFormDirty) {
4190
- showConfirmDialog(action).then(function () {
4191
- resetFormState(undefined, isDefaultDisabled);
4192
- });
4193
- } else {
4194
- resetFormState(undefined, isDefaultDisabled);
4195
- }
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
4196
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
+ });
4197
4227
  break;
4198
4228
 
4199
4229
  case 'AMEND':
@@ -4367,7 +4397,7 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4367
4397
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4368
4398
  }, []);
4369
4399
  React__default.useEffect(function () {
4370
- 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
4371
4401
 
4372
4402
  resetFormValues(newValues); // eslint-disable-next-line react-hooks/exhaustive-deps
4373
4403
  }, [originalTaf]);
@@ -4429,10 +4459,10 @@ var TafForm = /*#__PURE__*/React__default.memo(function (_ref) {
4429
4459
  handle: ".handle",
4430
4460
  direction: "vertical",
4431
4461
  // hover props
4432
- forceFallback: true,
4462
+ forceFallback: false,
4433
4463
  onStart: function onStart(event) {
4434
4464
  onStartDrag(event);
4435
- Sortable.ghost.style.opacity = '1';
4465
+ if (Sortable.ghost) Sortable.ghost.style.opacity = '1';
4436
4466
  }
4437
4467
  }, fields.map(function (item, index) {
4438
4468
  return /*#__PURE__*/React__default.createElement(TafFormRow, {
@@ -4739,69 +4769,72 @@ var IconWithTooltip = function IconWithTooltip(_ref) {
4739
4769
  children = _ref.children;
4740
4770
  return /*#__PURE__*/React.createElement(CustomTooltip, {
4741
4771
  title: title,
4742
- placement: "right"
4772
+ placement: "right",
4773
+ "data-testid": "statusIcon-tooltip"
4743
4774
  }, /*#__PURE__*/React.createElement(Box, {
4744
4775
  component: "span"
4745
4776
  }, children));
4746
4777
  };
4747
4778
 
4748
4779
  var StatusIcon = function StatusIcon(_ref2) {
4749
- var timeSlot = _ref2.timeSlot,
4750
- status = _ref2.status;
4780
+ var status = _ref2.status,
4781
+ timeSlot = _ref2.timeSlot;
4751
4782
 
4752
- if (status === 'NEW') {
4753
- return null;
4754
- }
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
+ }));
4755
4795
 
4756
- if (status === 'EXPIRED') {
4757
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4758
- title: "Expired"
4759
- }, /*#__PURE__*/React.createElement(Clock, {
4760
- "data-testid": "status-expired",
4761
- sx: {
4762
- transform: 'scaleX(-1)',
4763
- color: 'geowebColors.buttons.tertiary.disabled.color'
4764
- }
4765
- }));
4766
- }
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
+ }));
4767
4812
 
4768
- if (status === 'CANCELLED') {
4769
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4770
- title: "Cancelled"
4771
- }, /*#__PURE__*/React.createElement(Cancel, {
4772
- "data-testid": "status-cancelled",
4773
- sx: {
4774
- color: 'geowebColors.captions.captionError.rgba'
4775
- }
4776
- }));
4777
- }
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
+ }));
4778
4822
 
4779
- if (status === 'DRAFT' || status === 'DRAFT_CORRECTED' || status === 'DRAFT_AMENDED') {
4780
- return /*#__PURE__*/React.createElement(IconWithTooltip, {
4781
- title: "Draft"
4782
- }, /*#__PURE__*/React.createElement(Edit, {
4783
- "data-testid": "status-draft",
4784
- sx: {
4785
- color: 'geowebColors.buttons.tertiary.default.color'
4786
- }
4787
- }));
4788
- }
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
+ }));
4789
4833
 
4790
- return timeSlot === 'ACTIVE' ? /*#__PURE__*/React.createElement(IconWithTooltip, {
4791
- title: "Active"
4792
- }, /*#__PURE__*/React.createElement(Success, {
4793
- "data-testid": "status-active",
4794
- sx: {
4795
- color: 'geowebColors.functional.success'
4796
- }
4797
- })) : /*#__PURE__*/React.createElement(IconWithTooltip, {
4798
- title: "Upcoming"
4799
- }, /*#__PURE__*/React.createElement(Clock, {
4800
- "data-testid": "status-upcoming",
4801
- sx: {
4802
- color: 'geowebColors.functional.success'
4803
- }
4804
- }));
4834
+ case 'NEW':
4835
+ default:
4836
+ return null;
4837
+ }
4805
4838
  };
4806
4839
 
4807
4840
  /* *
@@ -4847,8 +4880,8 @@ var ExportButton = function ExportButton(_ref) {
4847
4880
  * See the License for the specific language governing permissions and
4848
4881
  * limitations under the License.
4849
4882
  *
4850
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4851
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
4883
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4884
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
4852
4885
  * */
4853
4886
  var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_ref) {
4854
4887
  var TAC = _ref.TAC,
@@ -4879,7 +4912,8 @@ var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_ref) {
4879
4912
  }, isActive && {
4880
4913
  backgroundColor: 'geowebColors.functional.warningHighlight.rgba'
4881
4914
  }), word.type === 'adverse' && {
4882
- color: 'geowebColors.captions.captionError.rgba'
4915
+ color: 'geowebColors.captions.captionError.rgba',
4916
+ fontWeight: 'bold'
4883
4917
  })
4884
4918
  }, word.text === '=' ? "".concat(word.text) : " ".concat(word.text));
4885
4919
  }));
@@ -5227,9 +5261,7 @@ var TopTabs = function TopTabs(_ref) {
5227
5261
  } : _ref$tafFromBackend;
5228
5262
 
5229
5263
  var _useFormContext = useFormContext(),
5230
- dirtyFields = _useFormContext.formState.dirtyFields;
5231
-
5232
- var isDirty = Object.keys(dirtyFields).length > 0;
5264
+ isDirty = _useFormContext.formState.isDirty;
5233
5265
 
5234
5266
  if (!tafFromBackend) {
5235
5267
  return null;
@@ -5297,9 +5329,8 @@ var LocationTabs = function LocationTabs(_ref) {
5297
5329
  timeSlot = _ref.timeSlot;
5298
5330
 
5299
5331
  var _useFormContext = useFormContext(),
5300
- dirtyFields = _useFormContext.formState.dirtyFields;
5332
+ isDirty = _useFormContext.formState.isDirty;
5301
5333
 
5302
- var isDirty = Object.keys(dirtyFields).length > 0;
5303
5334
  return /*#__PURE__*/React.createElement(MenuList, {
5304
5335
  "data-testid": "location-tabs",
5305
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,15 +2577,43 @@
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);
2580
- return __assign(__assign(__assign(__assign(__assign({}, taf), {
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;
2584
+
2585
+ if (changeGroupsToAdd > 0) {
2586
+ Array.from(Array(changeGroupsToAdd)).map(function () {
2587
+ return changeGroups.push(emptyChangegroup);
2588
+ });
2589
+ }
2590
+ }
2591
+
2592
+ return __assign(__assign({
2593
+ issueDate: '',
2594
+ previousId: null,
2595
+ previousValidDateStart: null,
2596
+ previousValidDateEnd: null
2597
+ }, taf), (_a = {
2581
2598
  messageType: getMessageType(taf, tafAction),
2582
- baseForecast: baseForecast
2583
- }), changeGroups.length && {
2599
+ baseForecast: baseForecast,
2584
2600
  changeGroups: changeGroups
2585
- }), addEmptyChangeGroup && {
2586
- changeGroups: [emptyChangegroup]
2587
- }), (_a = {}, _a[shared.HIDDEN_INPUT_HELPER_IS_DRAFT] = true, _a));
2601
+ }, _a[shared.HIDDEN_INPUT_HELPER_IS_DRAFT] = true, _a));
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
+ });
2588
2617
  };
2589
2618
  var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2590
2619
  return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
@@ -3482,13 +3511,13 @@
3482
3511
  canBe: canBe,
3483
3512
  onTafViewModeButtonPress: onTafViewModeButtonPress
3484
3513
  }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(material.Button, {
3485
- "data-testid": "discardtaf",
3514
+ "data-testid": "cleartaf",
3486
3515
  variant: "tertiary",
3487
3516
  onClick: function onClick() {
3488
3517
  // Simply discard the changes and close the dialog.
3489
- onTafEditModeButtonPress('DISCARD');
3518
+ onTafEditModeButtonPress('CLEAR');
3490
3519
  }
3491
- }, "Discard"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3520
+ }, "Clear"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3492
3521
  "data-testid": "savedrafttaf",
3493
3522
  variant: "tertiary",
3494
3523
  onClick: function onClick() {
@@ -3555,9 +3584,7 @@
3555
3584
  '&:hover': {
3556
3585
  backgroundColor: 'transparent'
3557
3586
  },
3558
- cursor: function cursor() {
3559
- return isSorting ? 'grabbing' : 'grab';
3560
- }
3587
+ cursor: isSorting ? 'grabbing' : 'grab'
3561
3588
  }
3562
3589
  }, /*#__PURE__*/React__default["default"].createElement(theme.DragHandle, null));
3563
3590
  };
@@ -4013,9 +4040,8 @@
4013
4040
  onStartDrag = _o.onStartDrag,
4014
4041
  activeDraggingIndex = _o.activeDraggingIndex;
4015
4042
 
4016
- var dirtyFields = formState.dirtyFields,
4043
+ var isFormDirty = formState.isDirty,
4017
4044
  errors = formState.errors;
4018
- var isFormDirty = Object.keys(dirtyFields).length > 0;
4019
4045
  shared.usePreventBrowserClose(isFormDirty && !isDisabled); // Needed to be able to show a confirmation dialog on closing parent view
4020
4046
 
4021
4047
  React__default["default"].useEffect(function () {
@@ -4038,9 +4064,13 @@
4038
4064
  });
4039
4065
  };
4040
4066
 
4041
- var resetFormValues = function resetFormValues(formData) {
4067
+ var resetFormValues = function resetFormValues(formData, keepDirty) {
4068
+ if (keepDirty === void 0) {
4069
+ keepDirty = false;
4070
+ }
4071
+
4042
4072
  reset(formData, {
4043
- keepDirty: false,
4073
+ keepDirty: keepDirty,
4044
4074
  keepDirtyValues: false
4045
4075
  });
4046
4076
  };
@@ -4054,7 +4084,7 @@
4054
4084
  tafToReset = originalTaf;
4055
4085
  }
4056
4086
 
4057
- var shouldAddEmptyChangGroup = !(tafToReset && tafToReset.changeGroups) && !resetDisabled;
4087
+ var shouldAddEmptyChangGroup = !resetDisabled;
4058
4088
  var newTaf = prepareTafValues(tafToReset, action, shouldAddEmptyChangGroup);
4059
4089
  resetFormValues(newTaf);
4060
4090
  setIsDisabled(resetDisabled);
@@ -4189,15 +4219,18 @@
4189
4219
  })();
4190
4220
  break;
4191
4221
 
4192
- case 'DISCARD':
4193
- if (isFormDirty) {
4194
- showConfirmDialog(action).then(function () {
4195
- resetFormState(undefined, isDefaultDisabled);
4196
- });
4197
- } else {
4198
- resetFormState(undefined, isDefaultDisabled);
4199
- }
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
4200
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
+ });
4201
4234
  break;
4202
4235
 
4203
4236
  case 'AMEND':
@@ -4386,7 +4419,7 @@
4386
4419
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4387
4420
  }, []);
4388
4421
  React__default["default"].useEffect(function () {
4389
- 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
4390
4423
 
4391
4424
  resetFormValues(newValues); // eslint-disable-next-line react-hooks/exhaustive-deps
4392
4425
  }, [originalTaf]);
@@ -4448,10 +4481,10 @@
4448
4481
  handle: ".handle",
4449
4482
  direction: "vertical",
4450
4483
  // hover props
4451
- forceFallback: true,
4484
+ forceFallback: false,
4452
4485
  onStart: function onStart(event) {
4453
4486
  onStartDrag(event);
4454
- Sortable__default["default"].ghost.style.opacity = '1';
4487
+ if (Sortable__default["default"].ghost) Sortable__default["default"].ghost.style.opacity = '1';
4455
4488
  }
4456
4489
  }, fields.map(function (item, index) {
4457
4490
  return /*#__PURE__*/React__default["default"].createElement(TafFormRow, {
@@ -4753,69 +4786,72 @@
4753
4786
  children = _a.children;
4754
4787
  return /*#__PURE__*/React__namespace.createElement(shared.CustomTooltip, {
4755
4788
  title: title,
4756
- placement: "right"
4789
+ placement: "right",
4790
+ "data-testid": "statusIcon-tooltip"
4757
4791
  }, /*#__PURE__*/React__namespace.createElement(material.Box, {
4758
4792
  component: "span"
4759
4793
  }, children));
4760
4794
  };
4761
4795
 
4762
4796
  var StatusIcon = function StatusIcon(_a) {
4763
- var timeSlot = _a.timeSlot,
4764
- status = _a.status;
4797
+ var status = _a.status,
4798
+ timeSlot = _a.timeSlot;
4765
4799
 
4766
- if (status === 'NEW') {
4767
- return null;
4768
- }
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
+ }));
4769
4812
 
4770
- if (status === 'EXPIRED') {
4771
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4772
- title: "Expired"
4773
- }, /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4774
- "data-testid": "status-expired",
4775
- sx: {
4776
- transform: 'scaleX(-1)',
4777
- color: 'geowebColors.buttons.tertiary.disabled.color'
4778
- }
4779
- }));
4780
- }
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
+ }));
4781
4829
 
4782
- if (status === 'CANCELLED') {
4783
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4784
- title: "Cancelled"
4785
- }, /*#__PURE__*/React__namespace.createElement(theme.Cancel, {
4786
- "data-testid": "status-cancelled",
4787
- sx: {
4788
- color: 'geowebColors.captions.captionError.rgba'
4789
- }
4790
- }));
4791
- }
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
+ }));
4792
4839
 
4793
- if (status === 'DRAFT' || status === 'DRAFT_CORRECTED' || status === 'DRAFT_AMENDED') {
4794
- return /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4795
- title: "Draft"
4796
- }, /*#__PURE__*/React__namespace.createElement(theme.Edit, {
4797
- "data-testid": "status-draft",
4798
- sx: {
4799
- color: 'geowebColors.buttons.tertiary.default.color'
4800
- }
4801
- }));
4802
- }
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
+ }));
4803
4850
 
4804
- return timeSlot === 'ACTIVE' ? /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4805
- title: "Active"
4806
- }, /*#__PURE__*/React__namespace.createElement(theme.Success, {
4807
- "data-testid": "status-active",
4808
- sx: {
4809
- color: 'geowebColors.functional.success'
4810
- }
4811
- })) : /*#__PURE__*/React__namespace.createElement(IconWithTooltip, {
4812
- title: "Upcoming"
4813
- }, /*#__PURE__*/React__namespace.createElement(theme.Clock, {
4814
- "data-testid": "status-upcoming",
4815
- sx: {
4816
- color: 'geowebColors.functional.success'
4817
- }
4818
- }));
4851
+ case 'NEW':
4852
+ default:
4853
+ return null;
4854
+ }
4819
4855
  };
4820
4856
 
4821
4857
  /* *
@@ -4861,8 +4897,8 @@
4861
4897
  * See the License for the specific language governing permissions and
4862
4898
  * limitations under the License.
4863
4899
  *
4864
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4865
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
4900
+ * Copyright 2023 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4901
+ * Copyright 2023 - Finnish Meteorological Institute (FMI)
4866
4902
  * */
4867
4903
  var AdverseWeatherTACMessage = function AdverseWeatherTACMessage(_a) {
4868
4904
  var TAC = _a.TAC,
@@ -4893,7 +4929,8 @@
4893
4929
  }, isActive && {
4894
4930
  backgroundColor: 'geowebColors.functional.warningHighlight.rgba'
4895
4931
  }), word.type === 'adverse' && {
4896
- color: 'geowebColors.captions.captionError.rgba'
4932
+ color: 'geowebColors.captions.captionError.rgba',
4933
+ fontWeight: 'bold'
4897
4934
  })
4898
4935
  }, word.text === '=' ? "" + word.text : " " + word.text);
4899
4936
  }));
@@ -5233,8 +5270,7 @@
5233
5270
  location: 'EHAM'
5234
5271
  }
5235
5272
  } : _c;
5236
- var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5237
- var isDirty = Object.keys(dirtyFields).length > 0;
5273
+ var isDirty = reactHookForm.useFormContext().formState.isDirty;
5238
5274
 
5239
5275
  if (!tafFromBackend) {
5240
5276
  return null;
@@ -5300,8 +5336,7 @@
5300
5336
  _c = _a.onChangeTab,
5301
5337
  onChangeTab = _c === void 0 ? function () {} : _c,
5302
5338
  timeSlot = _a.timeSlot;
5303
- var dirtyFields = reactHookForm.useFormContext().formState.dirtyFields;
5304
- var isDirty = Object.keys(dirtyFields).length > 0;
5339
+ var isDirty = reactHookForm.useFormContext().formState.isDirty;
5305
5340
  return /*#__PURE__*/React__namespace.createElement(material.MenuList, {
5306
5341
  "data-testid": "location-tabs",
5307
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.8.0",
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.8.0",
15
+ "@opengeoweb/api": "4.10.0",
16
16
  "react": "^17.0.2",
17
- "@opengeoweb/shared": "4.8.0",
17
+ "axios": "^0.25.0",
18
+ "@opengeoweb/shared": "4.10.0",
18
19
  "@mui/material": "^5.10.8",
19
- "@opengeoweb/theme": "4.8.0",
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.8.0",
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.8.0",
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.8.0",
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.8.0",
49
+ "@opengeoweb/authentication": "4.10.0",
50
50
  "react-router-dom": "^6.4.2",
51
51
  "query-string": "^6.13.7"
52
52
  }