@opengeoweb/taf 2.4.1 → 2.5.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
@@ -5,7 +5,7 @@ import { useFormContext, Controller, useFieldArray } from 'react-hook-form';
5
5
  import { ReactSortable, Sortable } from 'react-sortablejs';
6
6
  import { getDeepProperty, ReactHookFormHiddenInput, ReactHookFormProvider } from '@opengeoweb/form-fields';
7
7
  import { useApiContext, useApi, createApiInstance } from '@opengeoweb/api';
8
- import { useIsMounted, ToggleMenu, useDraftFormHelpers, ToolContainerDraggable, useConfirmationDialog, usePreventBrowserClose, ToolButton, ToolHeader, AlertBanner, getAxiosErrorMessage, ConfirmationServiceProvider, usePoller } from '@opengeoweb/shared';
8
+ import { useIsMounted, ToggleMenu, useDraftFormHelpers, ToolContainerDraggable, useConfirmationDialog, usePreventBrowserClose, ToolButton, ToolHeader, getAxiosErrorMessage, AlertBanner, ConfirmationServiceProvider, usePoller } from '@opengeoweb/shared';
9
9
  import moment from 'moment';
10
10
  import { isEqual } from 'lodash';
11
11
  import makeStyles from '@mui/styles/makeStyles';
@@ -2294,6 +2294,10 @@ var getFieldNames = function getFieldNames(isChangeGroup, index) {
2294
2294
  var TAC_MISSING_DATA = 'Missing data: no TAC can be generated';
2295
2295
  var TAC_NOT_AVAILABLE = 'No TAC available';
2296
2296
  var TAC_RETRIEVING_DATA = 'Retrieving TAC';
2297
+ var TAC_FAILED = 'Failed to retrieve TAC';
2298
+ var tacHasError = function tacHasError(tac) {
2299
+ return tac === TAC_MISSING_DATA || tac === TAC_NOT_AVAILABLE || tac === TAC_RETRIEVING_DATA || tac === TAC_FAILED;
2300
+ };
2297
2301
  var useTACGenerator = function useTACGenerator(taf, requestTAC) {
2298
2302
  var standardTAC = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
2299
2303
 
@@ -2305,7 +2309,7 @@ var useTACGenerator = function useTACGenerator(taf, requestTAC) {
2305
2309
  var _useIsMounted = useIsMounted(),
2306
2310
  isMounted = _useIsMounted.isMounted;
2307
2311
 
2308
- var retrieveTAC = function retrieveTAC(tafToPost) {
2312
+ var retrieveTAC = React__default.useCallback(function (tafToPost) {
2309
2313
  if (shouldRetrieveTAC(tafToPost)) {
2310
2314
  requestTAC(tafToPost).then(function (result) {
2311
2315
  if (isMounted.current) {
@@ -2313,14 +2317,13 @@ var useTACGenerator = function useTACGenerator(taf, requestTAC) {
2313
2317
  }
2314
2318
  })["catch"](function () {
2315
2319
  if (isMounted.current) {
2316
- setTAC('Failed to retrieve TAC');
2320
+ setTAC(TAC_FAILED);
2317
2321
  }
2318
2322
  });
2319
2323
  } else {
2320
2324
  setTAC(TAC_MISSING_DATA);
2321
2325
  }
2322
- };
2323
-
2326
+ }, [isMounted, requestTAC]);
2324
2327
  React__default.useEffect(function () {
2325
2328
  if (taf.status !== 'NEW' && !standardTAC) {
2326
2329
  retrieveTAC(taf);
@@ -2483,6 +2486,10 @@ var getMessageType = function getMessageType(taf, tafAction) {
2483
2486
  return 'AMD';
2484
2487
  }
2485
2488
 
2489
+ if (tafAction === 'CANCEL') {
2490
+ return 'CNL';
2491
+ }
2492
+
2486
2493
  return taf.messageType;
2487
2494
  }; // For corrections and amendment we need to add the previousValidStart and End for the TAC converter
2488
2495
 
@@ -2526,6 +2533,36 @@ var prepareTafValues = function prepareTafValues(_taf, tafAction) {
2526
2533
  changeGroups: [emptyChangegroup]
2527
2534
  });
2528
2535
  };
2536
+ var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2537
+ return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
2538
+ };
2539
+ var fromStatusToAction = function fromStatusToAction(tafStatus) {
2540
+ switch (tafStatus) {
2541
+ case 'DRAFT':
2542
+ return 'DRAFT';
2543
+
2544
+ case 'DRAFT_AMENDED':
2545
+ return 'DRAFT_AMEND';
2546
+
2547
+ case 'DRAFT_CORRECTED':
2548
+ return 'DRAFT_CORRECT';
2549
+
2550
+ case 'PUBLISHED':
2551
+ return 'PUBLISH';
2552
+
2553
+ case 'AMENDED':
2554
+ return 'AMEND';
2555
+
2556
+ case 'CORRECTED':
2557
+ return 'CORRECT';
2558
+
2559
+ case 'CANCELLED':
2560
+ return 'CANCEL';
2561
+
2562
+ default:
2563
+ return 'NEW';
2564
+ }
2565
+ };
2529
2566
 
2530
2567
  var textFieldStyle = function textFieldStyle(theme) {
2531
2568
  return {
@@ -3310,6 +3347,36 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
3310
3347
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3311
3348
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
3312
3349
  * */
3350
+ var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3351
+ switch (tafAction) {
3352
+ case 'AMEND':
3353
+ case 'DRAFT_AMEND':
3354
+ return 'DRAFT_AMEND';
3355
+
3356
+ case 'CORRECT':
3357
+ case 'DRAFT_CORRECT':
3358
+ return 'DRAFT_CORRECT';
3359
+
3360
+ default:
3361
+ return 'DRAFT';
3362
+ }
3363
+ };
3364
+
3365
+ var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3366
+ switch (tafAction) {
3367
+ case 'AMEND':
3368
+ case 'DRAFT_AMEND':
3369
+ return 'AMEND';
3370
+
3371
+ case 'CORRECT':
3372
+ case 'DRAFT_CORRECT':
3373
+ return 'CORRECT';
3374
+
3375
+ default:
3376
+ return 'PUBLISH';
3377
+ }
3378
+ };
3379
+
3313
3380
  var buttonsStyle = {
3314
3381
  button: {
3315
3382
  minWidth: {
@@ -3339,7 +3406,7 @@ var ViewModeButtons = function ViewModeButtons(_ref) {
3339
3406
  return onTafViewModeButtonPress('CANCEL');
3340
3407
  }
3341
3408
  }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default.createElement(Button, {
3342
- "data-testid": "correctaf",
3409
+ "data-testid": "correcttaf",
3343
3410
  variant: "tertiary",
3344
3411
  onClick: function onClick() {
3345
3412
  return onTafViewModeButtonPress('CORRECT');
@@ -3393,21 +3460,7 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3393
3460
  if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3394
3461
  if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3395
3462
  */
3396
- switch (tafAction) {
3397
- case 'AMEND':
3398
- case 'DRAFT_AMEND':
3399
- onTafEditModeButtonPress('DRAFT_AMEND');
3400
- break;
3401
-
3402
- case 'CORRECT':
3403
- case 'DRAFT_CORRECT':
3404
- onTafEditModeButtonPress('DRAFT_CORRECT');
3405
- break;
3406
-
3407
- default:
3408
- onTafEditModeButtonPress('DRAFT');
3409
- break;
3410
- }
3463
+ onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
3411
3464
  }
3412
3465
  }, "Save"), /*#__PURE__*/React__default.createElement(Button, {
3413
3466
  "data-testid": "publishtaf",
@@ -3420,21 +3473,7 @@ var TafFormButtons = function TafFormButtons(_ref2) {
3420
3473
  if action DRAFT_AMEND - new status will be AMENDED
3421
3474
  if action DRAFT_CORRECT - new status will be CORRECTED
3422
3475
  */
3423
- switch (tafAction) {
3424
- case 'AMEND':
3425
- case 'DRAFT_AMEND':
3426
- onTafEditModeButtonPress('AMEND');
3427
- break;
3428
-
3429
- case 'CORRECT':
3430
- case 'DRAFT_CORRECT':
3431
- onTafEditModeButtonPress('CORRECT');
3432
- break;
3433
-
3434
- default:
3435
- onTafEditModeButtonPress('PUBLISH');
3436
- break;
3437
- }
3476
+ onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
3438
3477
  }
3439
3478
  }, "Publish"))), /*#__PURE__*/React__default.createElement(Grid, {
3440
3479
  item: true,
@@ -3835,41 +3874,55 @@ var IssuesPane = function IssuesPane(_ref3) {
3835
3874
  }))), rootElement);
3836
3875
  };
3837
3876
 
3838
- var fromStatusToAction = function fromStatusToAction(tafStatus) {
3839
- switch (tafStatus) {
3840
- case 'DRAFT':
3841
- return 'DRAFT';
3842
-
3843
- case 'DRAFT_AMENDED':
3844
- return 'DRAFT_AMEND';
3845
-
3846
- case 'DRAFT_CORRECTED':
3847
- return 'DRAFT_CORRECT';
3848
-
3849
- case 'PUBLISHED':
3850
- return 'PUBLISH';
3851
-
3852
- case 'AMENDED':
3853
- return 'AMEND';
3854
-
3855
- case 'CORRECTED':
3856
- return 'CORRECT';
3877
+ var TafModuleContext = /*#__PURE__*/React.createContext({
3878
+ onValidateForm: null,
3879
+ registerValidateForm: null,
3880
+ tafAction: null,
3881
+ setTafAction: null
3882
+ });
3883
+ var useTafModuleContext = function useTafModuleContext() {
3884
+ return React.useContext(TafModuleContext);
3885
+ };
3886
+ var useTafModuleState = function useTafModuleState() {
3887
+ var _React$useState = React.useState(function () {
3888
+ return new Promise(function () {
3889
+ return true;
3890
+ });
3891
+ }),
3892
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3893
+ onValidateForm = _React$useState2[0],
3894
+ registerValidateForm = _React$useState2[1];
3857
3895
 
3858
- case 'CANCELLED':
3859
- return 'CANCEL';
3896
+ var _React$useState3 = React.useState(),
3897
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
3898
+ tafAction = _React$useState4[0],
3899
+ setTafAction = _React$useState4[1];
3860
3900
 
3861
- default:
3862
- return 'NEW';
3863
- }
3864
- }; // prevents default functionality
3901
+ var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3902
+ registerValidateForm(function () {
3903
+ return promiseToRegister;
3904
+ });
3905
+ };
3865
3906
 
3907
+ return {
3908
+ onValidateForm: onValidateForm,
3909
+ registerValidateForm: onRegisterValidateForm,
3910
+ tafAction: tafAction,
3911
+ setTafAction: setTafAction
3912
+ };
3913
+ };
3914
+ var TafModuleProvider = function TafModuleProvider(_ref) {
3915
+ var children = _ref.children;
3916
+ var contextState = useTafModuleState();
3917
+ return /*#__PURE__*/React.createElement(TafModuleContext.Provider, {
3918
+ value: contextState
3919
+ }, children);
3920
+ };
3866
3921
 
3867
3922
  var noop = function noop() {};
3868
3923
 
3869
3924
  var TafForm = function TafForm(_ref) {
3870
- var _ref$isDisabled = _ref.isDisabled,
3871
- isDefaultDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
3872
- tafFromBackend = _ref.tafFromBackend,
3925
+ var tafFromBackend = _ref.tafFromBackend,
3873
3926
  _ref$onFormAction = _ref.onFormAction,
3874
3927
  onFormAction = _ref$onFormAction === void 0 ? function () {
3875
3928
  return null;
@@ -3883,26 +3936,26 @@ var TafForm = function TafForm(_ref) {
3883
3936
  _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
3884
3937
  setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
3885
3938
  return null;
3886
- } : _ref$setIsIssuesPaneO;
3939
+ } : _ref$setIsIssuesPaneO,
3940
+ _ref$isDisabled = _ref.isDisabled,
3941
+ isDisabled = _ref$isDisabled === void 0 ? false : _ref$isDisabled,
3942
+ _ref$setIsDisabled = _ref.setIsDisabled,
3943
+ setIsDisabled = _ref$setIsDisabled === void 0 ? function () {
3944
+ return null;
3945
+ } : _ref$setIsDisabled;
3887
3946
  var originalTaf = tafFromBackend.taf;
3888
- var defaultTafAction = fromStatusToAction(originalTaf.status);
3889
-
3890
- var _React$useState = React__default.useState(defaultTafAction),
3891
- _React$useState2 = _slicedToArray(_React$useState, 2),
3892
- tafAction = _React$useState2[0],
3893
- setTafAction = _React$useState2[1];
3894
-
3895
- var _React$useState3 = React__default.useState(isDefaultDisabled),
3896
- _React$useState4 = _slicedToArray(_React$useState3, 2),
3897
- isDisabled = _React$useState4[0],
3898
- setIsDisabled = _React$useState4[1];
3899
-
3947
+ var isDefaultDisabled = getIsFormDefaultDisabled(tafFromBackend.taf.status);
3900
3948
  var confirmDialog = useConfirmationDialog();
3901
3949
 
3902
3950
  var _useDraftFormHelpers = useDraftFormHelpers(),
3903
3951
  toggleIsDraft = _useDraftFormHelpers.toggleIsDraft,
3904
3952
  DraftFieldHelper = _useDraftFormHelpers.DraftFieldHelper;
3905
3953
 
3954
+ var _useTafModuleContext = useTafModuleContext(),
3955
+ registerValidateForm = _useTafModuleContext.registerValidateForm,
3956
+ tafAction = _useTafModuleContext.tafAction,
3957
+ setTafAction = _useTafModuleContext.setTafAction;
3958
+
3906
3959
  var _useApiContext = useApiContext(),
3907
3960
  api = _useApiContext.api;
3908
3961
 
@@ -3923,10 +3976,10 @@ var TafForm = function TafForm(_ref) {
3923
3976
  usePreventBrowserClose(isFormDirty && !isDisabled);
3924
3977
  var hiddenInputFields = ['baseTime', 'issueDate', 'type', 'uuid', 'validDateStart', 'validDateEnd', 'status', 'previousId', 'previousValidDateStart', 'previousValidDateEnd'];
3925
3978
 
3926
- var _React$useState5 = React__default.useState(getValues()),
3927
- _React$useState6 = _slicedToArray(_React$useState5, 2),
3928
- delayedFormValues = _React$useState6[0],
3929
- setDelayedFormValues = _React$useState6[1];
3979
+ var _React$useState = React__default.useState(getValues()),
3980
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3981
+ delayedFormValues = _React$useState2[0],
3982
+ setDelayedFormValues = _React$useState2[1];
3930
3983
 
3931
3984
  var _useTACGenerator = useTACGenerator(tafFromBackend.taf, api.getTAC),
3932
3985
  _useTACGenerator2 = _slicedToArray(_useTACGenerator, 2),
@@ -3997,6 +4050,7 @@ var TafForm = function TafForm(_ref) {
3997
4050
  toggleIsDraft(true);
3998
4051
  handleSubmit(function (data) {
3999
4052
  onFormAction(action, convertTafValuesToObject(data));
4053
+ reset(getValues());
4000
4054
  })();
4001
4055
  break;
4002
4056
 
@@ -4058,7 +4112,7 @@ var TafForm = function TafForm(_ref) {
4058
4112
  switch (action) {
4059
4113
  case 'CANCEL':
4060
4114
  showConfirmDialog(action).then(function () {
4061
- onFormAction(action, tafFromBackend.taf);
4115
+ onFormAction(action, convertTafValuesToObject(prepareTafValues(tafFromBackend.taf, action)));
4062
4116
  });
4063
4117
  break;
4064
4118
 
@@ -4149,19 +4203,39 @@ var TafForm = function TafForm(_ref) {
4149
4203
  });
4150
4204
  };
4151
4205
 
4152
- var _React$useState7 = React__default.useState(false),
4153
- _React$useState8 = _slicedToArray(_React$useState7, 2),
4154
- shouldValidate = _React$useState8[0],
4155
- setShouldValidate = _React$useState8[1];
4206
+ var _React$useState3 = React__default.useState(false),
4207
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
4208
+ shouldValidate = _React$useState4[0],
4209
+ setShouldValidate = _React$useState4[1];
4156
4210
 
4157
4211
  React__default.useEffect(function () {
4158
- var defaultValues = prepareTafValues(tafFromBackend.taf, undefined, !isDisabled && !tafFromBackend.taf.changeGroups); // set initial form values
4212
+ setIsDisabled(isDefaultDisabled);
4213
+ var defaultValues = prepareTafValues(tafFromBackend.taf, undefined, !isDefaultDisabled && !tafFromBackend.taf.changeGroups); // set initial form values
4159
4214
 
4160
4215
  reset(defaultValues); // set validate flag to validate after the values have been set
4161
4216
 
4162
- setShouldValidate(true);
4217
+ setShouldValidate(true); // register validate method to use in parent components
4218
+
4219
+ var onValidateFormPromise = function onValidateFormPromise() {
4220
+ return new Promise(function (resolve, reject) {
4221
+ toggleIsDraft(true);
4222
+ handleSubmit(function (formData) {
4223
+ resolve(convertTafValuesToObject(formData));
4224
+ })().then(function (formData) {
4225
+ if (formData === undefined) {
4226
+ reject();
4227
+ }
4228
+
4229
+ resolve(formData);
4230
+ });
4231
+ });
4232
+ };
4233
+
4234
+ registerValidateForm(onValidateFormPromise); // set default taf action
4235
+
4236
+ setTafAction(fromStatusToAction(originalTaf.status));
4163
4237
  return function () {
4164
- reset();
4238
+ reset({});
4165
4239
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4166
4240
  }, []);
4167
4241
  React__default.useEffect(function () {
@@ -4449,6 +4523,35 @@ var muiTabA11yProps = function muiTabA11yProps(index) {
4449
4523
  'aria-controls': "simple-tabpanel-".concat(index)
4450
4524
  };
4451
4525
  };
4526
+ var emptyBaseForecast = {
4527
+ wind: '',
4528
+ visibility: '',
4529
+ weather: {
4530
+ weather1: '',
4531
+ weather2: '',
4532
+ weather3: ''
4533
+ },
4534
+ cloud: {
4535
+ cloud1: '',
4536
+ cloud2: '',
4537
+ cloud3: '',
4538
+ cloud4: ''
4539
+ }
4540
+ };
4541
+ var prepareTafExportValues = function prepareTafExportValues(tafToCopy, currentTaf) {
4542
+ var _a;
4543
+
4544
+ var convertedCopy = prepareTafValues(tafToCopy, undefined, false);
4545
+ var baseForecast = convertedCopy.baseForecast,
4546
+ _convertedCopy$change = convertedCopy.changeGroups,
4547
+ changeGroups = _convertedCopy$change === void 0 ? [] : _convertedCopy$change;
4548
+ return Object.assign(Object.assign({}, currentTaf), {
4549
+ baseForecast: Object.assign(Object.assign(Object.assign({}, emptyBaseForecast), baseForecast), {
4550
+ valid: (_a = currentTaf === null || currentTaf === void 0 ? void 0 : currentTaf.baseForecast) === null || _a === void 0 ? void 0 : _a.valid
4551
+ }),
4552
+ changeGroups: changeGroups
4553
+ });
4554
+ };
4452
4555
 
4453
4556
  /* *
4454
4557
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -4539,10 +4642,44 @@ var StatusIcon = function StatusIcon(_ref) {
4539
4642
  }));
4540
4643
  };
4541
4644
 
4645
+ /* *
4646
+ * Licensed under the Apache License, Version 2.0 (the "License");
4647
+ * you may not use this file except in compliance with the License.
4648
+ * You may obtain a copy of the License at
4649
+ *
4650
+ * http://www.apache.org/licenses/LICENSE-2.0
4651
+ *
4652
+ * Unless required by applicable law or agreed to in writing, software
4653
+ * distributed under the License is distributed on an "AS IS" BASIS,
4654
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4655
+ * See the License for the specific language governing permissions and
4656
+ * limitations under the License.
4657
+ *
4658
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4659
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
4660
+ * */
4661
+ var ExportIcon = /*#__PURE__*/React__default.createElement(SvgIcon, null, /*#__PURE__*/React__default.createElement("path", {
4662
+ d: "M14.744 5.476a1.252 1.252 0 1 0 0 2.504h2.752v9.516H6.48v-1.753a1.251 1.251 0 1 0-2.504 0v3.004c0 .693.561 1.253 1.252 1.253h13.52C19.44 20 20 19.44 20 18.747V6.727c0-.69-.56-1.251-1.252-1.251zM9.133 2.385a1.252 1.252 0 0 0-1.77 0L1.773 7.974l5.54 5.54c.49.49 1.281.49 1.77 0l.022-.026a1.25 1.25 0 0 0-.021-1.745L6.568 9.225h1.371c.914 0 2.756.618 4.045 2.763 1.29 2.145.352 2.526.653 2.526.301 0 1.943-1.798.721-4.295-1.71-3.498-4.6-3.498-5.346-3.498H6.568l2.565-2.565a1.253 1.253 0 0 0 0-1.771z"
4663
+ }));
4664
+
4665
+ var ExportButton = function ExportButton(_ref) {
4666
+ var onClick = _ref.onClick,
4667
+ isHidden = _ref.isHidden;
4668
+ return isHidden ? null : /*#__PURE__*/React__default.createElement(Tooltip, {
4669
+ title: "Import TAC",
4670
+ placement: "left"
4671
+ }, /*#__PURE__*/React__default.createElement("span", null, /*#__PURE__*/React__default.createElement(ToolButton, {
4672
+ onClick: onClick,
4673
+ "data-testid": "export-tac-button"
4674
+ }, ExportIcon)));
4675
+ };
4676
+
4542
4677
  var TacContainer = function TacContainer(_ref) {
4543
4678
  var taf = _ref.taf,
4544
4679
  _ref$isActive = _ref.isActive,
4545
- isActive = _ref$isActive === void 0 ? false : _ref$isActive;
4680
+ isActive = _ref$isActive === void 0 ? false : _ref$isActive,
4681
+ _ref$isFormDisabled = _ref.isFormDisabled,
4682
+ isFormDisabled = _ref$isFormDisabled === void 0 ? false : _ref$isFormDisabled;
4546
4683
 
4547
4684
  var _useApiContext = useApiContext(),
4548
4685
  api = _useApiContext.api;
@@ -4557,6 +4694,26 @@ var TacContainer = function TacContainer(_ref) {
4557
4694
  baseTime = taf.baseTime;
4558
4695
  var locationLabel = getLocationSetting(location).label;
4559
4696
  var timeSlot = getTafTimeSlot(baseTime, location, status);
4697
+
4698
+ var _useFormContext = useFormContext(),
4699
+ getValues = _useFormContext.getValues,
4700
+ trigger = _useFormContext.trigger,
4701
+ setValue = _useFormContext.setValue;
4702
+
4703
+ var handleExport = function handleExport() {
4704
+ var currentTaf = getValues();
4705
+ var newTaf = prepareTafExportValues(taf, currentTaf);
4706
+ setValue('baseForecast', newTaf.baseForecast, {
4707
+ shouldDirty: true
4708
+ });
4709
+ setValue('changeGroups', newTaf.changeGroups, {
4710
+ shouldDirty: true
4711
+ });
4712
+ setTimeout(function () {
4713
+ trigger(); // trigger all fields validation
4714
+ }, 0);
4715
+ };
4716
+
4560
4717
  React__default.useEffect(function () {
4561
4718
  if (isActive) {
4562
4719
  retrieveTAC(taf);
@@ -4572,14 +4729,22 @@ var TacContainer = function TacContainer(_ref) {
4572
4729
  sx: {
4573
4730
  display: 'flex',
4574
4731
  alignItems: 'center',
4575
- marginBottom: '2px'
4732
+ justifyContent: 'space-between',
4733
+ height: 24
4734
+ }
4735
+ }, /*#__PURE__*/React__default.createElement(Box, {
4736
+ sx: {
4737
+ display: 'flex',
4738
+ alignItems: 'center'
4576
4739
  }
4577
4740
  }, /*#__PURE__*/React__default.createElement(Box, {
4578
4741
  sx: {
4579
- width: 20,
4580
- height: 20,
4742
+ width: 24,
4743
+ height: 24,
4581
4744
  display: 'flex',
4582
- marginRight: '6px'
4745
+ marginRight: '2px',
4746
+ alignItems: 'center',
4747
+ justifyContent: 'center'
4583
4748
  }
4584
4749
  }, /*#__PURE__*/React__default.createElement(StatusIcon, {
4585
4750
  timeSlot: timeSlot,
@@ -4606,7 +4771,10 @@ var TacContainer = function TacContainer(_ref) {
4606
4771
  },
4607
4772
  "data-testid": "tafLocationLabel",
4608
4773
  component: "span"
4609
- }, locationLabel))), /*#__PURE__*/React__default.createElement(Box, {
4774
+ }, locationLabel))), /*#__PURE__*/React__default.createElement(ExportButton, {
4775
+ onClick: handleExport,
4776
+ isHidden: isFormDisabled || tacHasError(TAC)
4777
+ })), /*#__PURE__*/React__default.createElement(Box, {
4610
4778
  sx: {
4611
4779
  fontSize: '12px',
4612
4780
  letterSpacing: '0.4px',
@@ -4642,7 +4810,9 @@ var TacOverview = function TacOverview(_ref) {
4642
4810
  _ref$hideTitle = _ref.hideTitle,
4643
4811
  hideTitle = _ref$hideTitle === void 0 ? false : _ref$hideTitle,
4644
4812
  _ref$activeTaf = _ref.activeTaf,
4645
- activeTaf = _ref$activeTaf === void 0 ? null : _ref$activeTaf;
4813
+ activeTaf = _ref$activeTaf === void 0 ? null : _ref$activeTaf,
4814
+ _ref$isFormDisabled = _ref.isFormDisabled,
4815
+ isFormDisabled = _ref$isFormDisabled === void 0 ? false : _ref$isFormDisabled;
4646
4816
 
4647
4817
  var _React$useState = React__default.useState(0),
4648
4818
  _React$useState2 = _slicedToArray(_React$useState, 2),
@@ -4739,7 +4909,8 @@ var TacOverview = function TacOverview(_ref) {
4739
4909
  return /*#__PURE__*/React__default.createElement(TacContainer, {
4740
4910
  key: taf.uuid,
4741
4911
  taf: taf,
4742
- isActive: isActiveLocation(taf.location)
4912
+ isActive: isActiveLocation(taf.location),
4913
+ isFormDisabled: isFormDisabled
4743
4914
  });
4744
4915
  }));
4745
4916
  })));
@@ -5008,25 +5179,22 @@ var fromActionToStatus = function fromActionToStatus(tafAction) {
5008
5179
  }
5009
5180
  };
5010
5181
 
5011
- var TafPanel = function TafPanel(_ref) {
5012
- var tafFromBackend = _ref.tafFromBackend,
5013
- activeTafIndex = _ref.activeTafIndex,
5014
- index = _ref.index,
5015
- _ref$onPostTaf = _ref.onPostTaf,
5016
- onPostTaf = _ref$onPostTaf === void 0 ? function () {} : _ref$onPostTaf,
5017
- _ref$onFormDirty = _ref.onFormDirty,
5018
- onFormDirty = _ref$onFormDirty === void 0 ? function () {
5019
- return null;
5020
- } : _ref$onFormDirty,
5021
- _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
5022
- isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
5023
- _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
5024
- setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
5025
- return null;
5026
- } : _ref$setIsIssuesPaneO;
5182
+ var parseErrorMessage = function parseErrorMessage(error, params) {
5183
+ return params.changeStatusTo === 'CANCELLED' ? {
5184
+ type: 'CANCELLED',
5185
+ title: 'Cancelling this TAF failed, please try again'
5186
+ } : {
5187
+ type: 'SERVER',
5188
+ title: 'An error has occurred while saving, please try again',
5189
+ message: getAxiosErrorMessage(error)
5190
+ };
5191
+ };
5027
5192
 
5028
- var _useApiContext = useApiContext(),
5029
- api = _useApiContext.api;
5193
+ var usePostTafRequest = function usePostTafRequest(request) {
5194
+ var errorParser = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : parseErrorMessage;
5195
+
5196
+ var _useIsMounted = useIsMounted(),
5197
+ isMounted = _useIsMounted.isMounted;
5030
5198
 
5031
5199
  var _React$useState = React__default.useState(false),
5032
5200
  _React$useState2 = _slicedToArray(_React$useState, 2),
@@ -5036,68 +5204,95 @@ var TafPanel = function TafPanel(_ref) {
5036
5204
  var _React$useState3 = React__default.useState(null),
5037
5205
  _React$useState4 = _slicedToArray(_React$useState3, 2),
5038
5206
  error = _React$useState4[0],
5039
- setError = _React$useState4[1]; // removes cancelled error message
5040
-
5041
-
5042
- React__default.useEffect(function () {
5043
- var cancelErrorTimeout = error && error.type === 'CANCELLED' ? setTimeout(function () {
5044
- setError(null);
5045
- }, 10000) : null;
5046
- return function () {
5047
- if (cancelErrorTimeout !== null) {
5048
- clearTimeout(cancelErrorTimeout);
5049
- }
5050
- };
5051
- }, [error]);
5207
+ setError = _React$useState4[1];
5052
5208
 
5053
- var postTaf = function postTaf(data) {
5209
+ var doRequest = function doRequest(params) {
5054
5210
  return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
5055
- var newError;
5211
+ var newErrorr;
5056
5212
  return regeneratorRuntime.wrap(function _callee$(_context) {
5057
5213
  while (1) {
5058
5214
  switch (_context.prev = _context.next) {
5059
5215
  case 0:
5060
- _context.prev = 0;
5061
5216
  setLoading(true);
5217
+ _context.prev = 1;
5062
5218
  _context.next = 4;
5063
- return api.postTaf(data);
5219
+ return request(params);
5064
5220
 
5065
5221
  case 4:
5222
+ if (isMounted.current) {
5223
+ _context.next = 6;
5224
+ break;
5225
+ }
5226
+
5227
+ return _context.abrupt("return");
5228
+
5229
+ case 6:
5066
5230
  setLoading(false);
5067
5231
  setError(null);
5068
- onFormDirty(false); // callback
5069
-
5070
- onPostTaf();
5071
- _context.next = 16;
5232
+ _context.next = 18;
5072
5233
  break;
5073
5234
 
5074
5235
  case 10:
5075
5236
  _context.prev = 10;
5076
- _context.t0 = _context["catch"](0);
5077
- newError = data.changeStatusTo === 'CANCELLED' ? {
5078
- type: 'CANCELLED',
5079
- title: 'Cancelling this TAF failed, please try again'
5080
- } : {
5081
- type: 'SERVER',
5082
- title: 'An error has occurred while saving, please try again',
5083
- message: getAxiosErrorMessage(_context.t0)
5084
- };
5085
- setError(newError);
5237
+ _context.t0 = _context["catch"](1);
5238
+
5239
+ if (isMounted.current) {
5240
+ _context.next = 14;
5241
+ break;
5242
+ }
5243
+
5244
+ return _context.abrupt("return");
5245
+
5246
+ case 14:
5247
+ newErrorr = errorParser ? errorParser(_context.t0, params) : _context.t0;
5086
5248
  setLoading(false);
5087
- throw _context.t0;
5249
+ setError(newErrorr);
5250
+ throw newErrorr;
5088
5251
 
5089
- case 16:
5252
+ case 18:
5090
5253
  case "end":
5091
5254
  return _context.stop();
5092
5255
  }
5093
5256
  }
5094
- }, _callee, null, [[0, 10]]);
5257
+ }, _callee, null, [[1, 10]]);
5095
5258
  }));
5096
5259
  };
5097
5260
 
5098
- var getViewMode = function getViewMode(status) {
5099
- return status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED' ? 'edit' : 'view';
5261
+ return {
5262
+ isLoading: isLoading,
5263
+ error: error,
5264
+ setError: setError,
5265
+ doRequest: doRequest
5100
5266
  };
5267
+ };
5268
+
5269
+ var TafPanel = function TafPanel(_ref) {
5270
+ var tafFromBackend = _ref.tafFromBackend,
5271
+ activeTafIndex = _ref.activeTafIndex,
5272
+ index = _ref.index,
5273
+ _ref$isLoading = _ref.isLoading,
5274
+ isLoading = _ref$isLoading === void 0 ? false : _ref$isLoading,
5275
+ _ref$postTaf = _ref.postTaf,
5276
+ postTaf = _ref$postTaf === void 0 ? function () {
5277
+ return null;
5278
+ } : _ref$postTaf,
5279
+ _ref$onFormDirty = _ref.onFormDirty,
5280
+ onFormDirty = _ref$onFormDirty === void 0 ? function () {
5281
+ return null;
5282
+ } : _ref$onFormDirty,
5283
+ _ref$isIssuesPaneOpen = _ref.isIssuesPaneOpen,
5284
+ isIssuesPaneOpen = _ref$isIssuesPaneOpen === void 0 ? false : _ref$isIssuesPaneOpen,
5285
+ _ref$setIsIssuesPaneO = _ref.setIsIssuesPaneOpen,
5286
+ setIsIssuesPaneOpen = _ref$setIsIssuesPaneO === void 0 ? function () {
5287
+ return null;
5288
+ } : _ref$setIsIssuesPaneO,
5289
+ _ref$isFormDisabled = _ref.isFormDisabled,
5290
+ isFormDisabled = _ref$isFormDisabled === void 0 ? false : _ref$isFormDisabled,
5291
+ _ref$setIsFormDisable = _ref.setIsFormDisabled,
5292
+ setIsFormDisabled = _ref$setIsFormDisable === void 0 ? function () {
5293
+ return null;
5294
+ } : _ref$setIsFormDisable,
5295
+ error = _ref.error;
5101
5296
 
5102
5297
  var onTafAction = function onTafAction(action, taf) {
5103
5298
  return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
@@ -5160,12 +5355,13 @@ var TafPanel = function TafPanel(_ref) {
5160
5355
  info: error.message,
5161
5356
  dataTestId: "taf-error"
5162
5357
  }), /*#__PURE__*/React__default.createElement(TafForm, {
5163
- isDisabled: getViewMode(tafFromBackend.taf.status) === 'view',
5164
5358
  tafFromBackend: tafFromBackend,
5165
5359
  onFormAction: onTafAction,
5166
5360
  onFormDirty: onFormDirty,
5167
5361
  isIssuesPaneOpen: isIssuesPaneOpen,
5168
- setIsIssuesPaneOpen: setIsIssuesPaneOpen
5362
+ setIsIssuesPaneOpen: setIsIssuesPaneOpen,
5363
+ isDisabled: isFormDisabled,
5364
+ setIsDisabled: setIsFormDisabled
5169
5365
  }));
5170
5366
  };
5171
5367
 
@@ -5196,11 +5392,21 @@ var IssuesPaneWrapper = function IssuesPaneWrapper(props) {
5196
5392
  }, props));
5197
5393
  };
5198
5394
 
5395
+ var CONFIRM_DIALOG_OPTIONS = {
5396
+ title: 'Whoops',
5397
+ description: "It's not possible to autosave this TAF due to the presence of issue(s). Are you sure you want to close this TAF? Any changes made will be lost.",
5398
+ confirmLabel: 'Exit without saving'
5399
+ };
5400
+
5199
5401
  var TafLayout = function TafLayout(_ref) {
5200
5402
  var _ref$tafList = _ref.tafList,
5201
5403
  tafList = _ref$tafList === void 0 ? [] : _ref$tafList,
5202
5404
  _ref$onPostTaf = _ref.onPostTaf,
5203
5405
  onPostTaf = _ref$onPostTaf === void 0 ? function () {} : _ref$onPostTaf;
5406
+
5407
+ var _useApiContext = useApiContext(),
5408
+ api = _useApiContext.api;
5409
+
5204
5410
  var confirmDialog = useConfirmationDialog();
5205
5411
 
5206
5412
  var _useIssuesPane = useIssuesPane(),
@@ -5209,6 +5415,16 @@ var TafLayout = function TafLayout(_ref) {
5209
5415
  onCloseIssuesPane = _useIssuesPane.onCloseIssuesPane,
5210
5416
  startPosition = _useIssuesPane.startPosition;
5211
5417
 
5418
+ var _usePostTafRequest = usePostTafRequest(api.postTaf),
5419
+ isLoading = _usePostTafRequest.isLoading,
5420
+ postTafRequest = _usePostTafRequest.doRequest,
5421
+ error = _usePostTafRequest.error,
5422
+ setError = _usePostTafRequest.setError;
5423
+
5424
+ var _useTafModuleContext = useTafModuleContext(),
5425
+ onValidateForm = _useTafModuleContext.onValidateForm,
5426
+ tafAction = _useTafModuleContext.tafAction;
5427
+
5212
5428
  var _React$useState = React__default.useState(sortTafTimeSlots(tafList)),
5213
5429
  _React$useState2 = _slicedToArray(_React$useState, 2),
5214
5430
  _React$useState2$ = _React$useState2[0],
@@ -5241,18 +5457,83 @@ var TafLayout = function TafLayout(_ref) {
5241
5457
  isFormDirty = _React$useState10[0],
5242
5458
  setIsFormDirty = _React$useState10[1];
5243
5459
 
5460
+ var _React$useState11 = React__default.useState(false),
5461
+ _React$useState12 = _slicedToArray(_React$useState11, 2),
5462
+ isFormDisabled = _React$useState12[0],
5463
+ setIsFormDisabled = _React$useState12[1];
5464
+
5465
+ var postTaf = function postTaf(data) {
5466
+ return __awaiter(void 0, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
5467
+ return regeneratorRuntime.wrap(function _callee$(_context) {
5468
+ while (1) {
5469
+ switch (_context.prev = _context.next) {
5470
+ case 0:
5471
+ _context.next = 2;
5472
+ return postTafRequest(data);
5473
+
5474
+ case 2:
5475
+ // callback
5476
+ onPostTaf();
5477
+
5478
+ case 3:
5479
+ case "end":
5480
+ return _context.stop();
5481
+ }
5482
+ }
5483
+ }, _callee);
5484
+ }));
5485
+ };
5486
+
5244
5487
  function onChangeTab(action, value) {
5245
- if (isFormDirty) {
5246
- confirmDialog({
5247
- title: 'Whoops',
5248
- description: 'Do you want to leave this open TAF without saving it? All changes will be lost.',
5249
- confirmLabel: 'Exit without saving'
5250
- }).then(function () {
5251
- action(value);
5252
- });
5253
- } else {
5254
- action(value);
5255
- }
5488
+ return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
5489
+ var taf;
5490
+ return regeneratorRuntime.wrap(function _callee2$(_context2) {
5491
+ while (1) {
5492
+ switch (_context2.prev = _context2.next) {
5493
+ case 0:
5494
+ if (!isFormDirty) {
5495
+ _context2.next = 15;
5496
+ break;
5497
+ }
5498
+
5499
+ _context2.prev = 1;
5500
+ _context2.next = 4;
5501
+ return onValidateForm();
5502
+
5503
+ case 4:
5504
+ taf = _context2.sent;
5505
+ _context2.next = 7;
5506
+ return postTaf({
5507
+ taf: taf,
5508
+ changeStatusTo: fromActionToStatus(tafActionToDraftAction(tafAction))
5509
+ });
5510
+
5511
+ case 7:
5512
+ action(value);
5513
+ _context2.next = 13;
5514
+ break;
5515
+
5516
+ case 10:
5517
+ _context2.prev = 10;
5518
+ _context2.t0 = _context2["catch"](1);
5519
+ confirmDialog(CONFIRM_DIALOG_OPTIONS).then(function () {
5520
+ action(value);
5521
+ });
5522
+
5523
+ case 13:
5524
+ _context2.next = 16;
5525
+ break;
5526
+
5527
+ case 15:
5528
+ action(value);
5529
+
5530
+ case 16:
5531
+ case "end":
5532
+ return _context2.stop();
5533
+ }
5534
+ }
5535
+ }, _callee2, null, [[1, 10]]);
5536
+ }));
5256
5537
  }
5257
5538
 
5258
5539
  var onChangeLocationTab = function onChangeLocationTab(index) {
@@ -5281,6 +5562,16 @@ var TafLayout = function TafLayout(_ref) {
5281
5562
  var newIndex = newActiveIndex !== -1 ? newActiveIndex : activeTafIndex;
5282
5563
  setActiveTafIndex(newIndex); // eslint-disable-next-line react-hooks/exhaustive-deps
5283
5564
  }, [tafList, setLocations]);
5565
+ React__default.useEffect(function () {
5566
+ var cancelErrorTimeout = error && error.type === 'CANCELLED' ? setTimeout(function () {
5567
+ setError(null);
5568
+ }, 10000) : null;
5569
+ return function () {
5570
+ if (cancelErrorTimeout !== null) {
5571
+ clearTimeout(cancelErrorTimeout);
5572
+ }
5573
+ };
5574
+ }, [error, setError]);
5284
5575
 
5285
5576
  if (!tafList) {
5286
5577
  return null;
@@ -5371,10 +5662,14 @@ var TafLayout = function TafLayout(_ref) {
5371
5662
  activeTafIndex: activeTafIndex,
5372
5663
  index: index,
5373
5664
  tafFromBackend: tafFromBackend,
5374
- onPostTaf: onPostTaf,
5375
5665
  onFormDirty: setIsFormDirty,
5376
5666
  isIssuesPaneOpen: isIssuesPaneOpen,
5377
- setIsIssuesPaneOpen: onToggleIssuesPane
5667
+ setIsIssuesPaneOpen: onToggleIssuesPane,
5668
+ isFormDisabled: isFormDisabled,
5669
+ setIsFormDisabled: setIsFormDisabled,
5670
+ postTaf: postTaf,
5671
+ isLoading: isLoading,
5672
+ error: error
5378
5673
  });
5379
5674
  }))), /*#__PURE__*/React__default.createElement(Grid, {
5380
5675
  item: true,
@@ -5390,7 +5685,8 @@ var TafLayout = function TafLayout(_ref) {
5390
5685
  upcomingTafs: upcoming,
5391
5686
  currentTafs: current,
5392
5687
  expiredTafs: expired,
5393
- activeTaf: activeTaf
5688
+ activeTaf: activeTaf,
5689
+ isFormDisabled: isFormDisabled
5394
5690
  })))))), /*#__PURE__*/React__default.createElement(IssuesPaneWrapper, {
5395
5691
  handleClose: onCloseIssuesPane,
5396
5692
  isOpen: isIssuesPaneOpen,
@@ -5417,13 +5713,13 @@ var TafLayout = function TafLayout(_ref) {
5417
5713
 
5418
5714
  var TafWrapper = function TafWrapper(_ref) {
5419
5715
  var children = _ref.children;
5420
- return /*#__PURE__*/React.createElement(ConfirmationServiceProvider, null, /*#__PURE__*/React.createElement(ReactHookFormProvider, {
5716
+ return /*#__PURE__*/React.createElement(TafModuleProvider, null, /*#__PURE__*/React.createElement(ConfirmationServiceProvider, null, /*#__PURE__*/React.createElement(ReactHookFormProvider, {
5421
5717
  options: {
5422
5718
  mode: 'onTouched',
5423
5719
  reValidateMode: 'onChange',
5424
5720
  criteriaMode: 'all'
5425
5721
  }
5426
- }, children));
5722
+ }, children)));
5427
5723
  };
5428
5724
 
5429
5725
  var TafModule = function TafModule() {
@@ -6180,7 +6476,7 @@ var fakePublishedTaf = {
6180
6476
  change: 'BECMG',
6181
6477
  valid: {
6182
6478
  start: "".concat(currentDate, "T23:00:00Z"),
6183
- end: "".concat(tomorrowDate, "T00:00:00Z")
6479
+ end: "".concat(tomorrowDate, "T01:00:00Z")
6184
6480
  },
6185
6481
  wind: {
6186
6482
  direction: 150,
@@ -6436,7 +6732,7 @@ var fakeAmendmentTaf = {
6436
6732
  }
6437
6733
  }
6438
6734
  }
6439
- }; // Only use for display purposes in the list!
6735
+ };
6440
6736
 
6441
6737
  ({
6442
6738
  creationDate: "2022-01-06T14:00:00Z",