@opengeoweb/taf 2.4.1 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@mui/material'), require('react-hook-form'), require('react-sortablejs'), require('@opengeoweb/form-fields'), require('@opengeoweb/api'), require('@opengeoweb/shared'), require('moment'), require('lodash'), require('@mui/styles/makeStyles'), require('@mui/icons-material'), require('react-dom'), require('@mui/material/LinearProgress'), require('@mui/icons-material/DoDisturb'), require('@mui/material/Box')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'react', '@mui/material', 'react-hook-form', 'react-sortablejs', '@opengeoweb/form-fields', '@opengeoweb/api', '@opengeoweb/shared', 'moment', 'lodash', '@mui/styles/makeStyles', '@mui/icons-material', 'react-dom', '@mui/material/LinearProgress', '@mui/icons-material/DoDisturb', '@mui/material/Box'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Taf = {}, global.React, global.material, global.reactHookForm, global.reactSortablejs, global.formFields, global.api, global.shared, global.moment, global.lodash, global.makeStyles, global.iconsMaterial, global.ReactDOM, global.LinearProgress, global.DoDisturbIcon, global.Box));
5
- })(this, (function (exports, React, material, reactHookForm, reactSortablejs, formFields, api, shared, moment, lodash, makeStyles, iconsMaterial, ReactDOM, LinearProgress, DoDisturbIcon, Box) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@mui/material'), require('react-hook-form'), require('react-sortablejs'), require('@opengeoweb/form-fields'), require('@opengeoweb/shared'), require('lodash'), require('moment'), require('@mui/styles/makeStyles'), require('@mui/icons-material'), require('react-dom'), require('@opengeoweb/api'), require('@mui/material/LinearProgress'), require('@mui/icons-material/DoDisturb'), require('@mui/material/Box')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'react', '@mui/material', 'react-hook-form', 'react-sortablejs', '@opengeoweb/form-fields', '@opengeoweb/shared', 'lodash', 'moment', '@mui/styles/makeStyles', '@mui/icons-material', 'react-dom', '@opengeoweb/api', '@mui/material/LinearProgress', '@mui/icons-material/DoDisturb', '@mui/material/Box'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Taf = {}, global.React, global.material, global.reactHookForm, global.reactSortablejs, global.formFields, global.shared, global.lodash, global.moment, global.makeStyles, global.iconsMaterial, global.ReactDOM, global.api, global.LinearProgress, global.DoDisturbIcon, global.Box));
5
+ })(this, (function (exports, React, material, reactHookForm, reactSortablejs, formFields, shared, lodash, moment, makeStyles, iconsMaterial, ReactDOM, api, LinearProgress, DoDisturbIcon, Box) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -1994,6 +1994,22 @@
1994
1994
  return true;
1995
1995
  };
1996
1996
 
1997
+ var emptyBaseForecast = {
1998
+ wind: '',
1999
+ visibility: '',
2000
+ weather: {
2001
+ weather1: '',
2002
+ weather2: '',
2003
+ weather3: ''
2004
+ },
2005
+ cloud: {
2006
+ cloud1: '',
2007
+ cloud2: '',
2008
+ cloud3: '',
2009
+ cloud4: ''
2010
+ }
2011
+ }; // formatters
2012
+
1997
2013
  var formatIssueTime = function formatIssueTime(issueDate) {
1998
2014
  return issueDate ? moment__default["default"](issueDate).utc().format('DDHHmm') + "Z" : 'Not issued';
1999
2015
  };
@@ -2298,45 +2314,54 @@
2298
2314
  var TAC_MISSING_DATA = 'Missing data: no TAC can be generated';
2299
2315
  var TAC_NOT_AVAILABLE = 'No TAC available';
2300
2316
  var TAC_RETRIEVING_DATA = 'Retrieving TAC';
2301
- var useTACGenerator = function useTACGenerator(taf, requestTAC, standardTAC) {
2302
- if (standardTAC === void 0) {
2303
- standardTAC = '';
2304
- }
2305
-
2306
- var _a = __read(React__default["default"].useState(taf.status === 'NEW' ? TAC_NOT_AVAILABLE : TAC_RETRIEVING_DATA), 2),
2317
+ var TAC_FAILED = 'Failed to retrieve TAC';
2318
+ var tacHasError = function tacHasError(tac) {
2319
+ return tac === TAC_MISSING_DATA || tac === TAC_NOT_AVAILABLE || tac === TAC_RETRIEVING_DATA || tac === TAC_FAILED;
2320
+ };
2321
+ var useTACGenerator = function useTACGenerator(taf, requestTAC) {
2322
+ var _a = __read(React__default["default"].useState(!taf || taf.status === 'NEW' ? TAC_NOT_AVAILABLE : TAC_RETRIEVING_DATA), 2),
2307
2323
  TAC = _a[0],
2308
2324
  setTAC = _a[1];
2309
2325
 
2310
2326
  var isMounted = shared.useIsMounted().isMounted;
2327
+ var controller = React__default["default"].useRef(null);
2328
+
2329
+ var onSetTac = function onSetTac(newTAC) {
2330
+ if (controller.current) {
2331
+ controller.current.abort();
2332
+ }
2311
2333
 
2312
- var retrieveTAC = function retrieveTAC(tafToPost) {
2334
+ setTAC(newTAC);
2335
+ };
2336
+
2337
+ var retrieveTAC = React__default["default"].useCallback(function (tafToPost) {
2313
2338
  if (shouldRetrieveTAC(tafToPost)) {
2314
- requestTAC(tafToPost).then(function (result) {
2339
+ if (controller.current) {
2340
+ controller.current.abort();
2341
+ }
2342
+
2343
+ controller.current = new AbortController();
2344
+ setTAC(TAC_RETRIEVING_DATA);
2345
+ requestTAC(tafToPost, controller.current.signal).then(function (result) {
2315
2346
  if (isMounted.current) {
2316
2347
  setTAC(result.data);
2317
2348
  }
2318
- })["catch"](function () {
2319
- if (isMounted.current) {
2320
- setTAC('Failed to retrieve TAC');
2349
+ })["catch"](function (error) {
2350
+ if (isMounted && error.message !== 'canceled') {
2351
+ setTAC(TAC_FAILED);
2321
2352
  }
2322
2353
  });
2323
2354
  } else {
2324
2355
  setTAC(TAC_MISSING_DATA);
2325
2356
  }
2326
- };
2327
-
2357
+ }, [isMounted, requestTAC]);
2328
2358
  React__default["default"].useEffect(function () {
2329
- if (taf.status !== 'NEW' && !standardTAC) {
2359
+ if (taf && taf.status !== 'NEW') {
2330
2360
  retrieveTAC(taf);
2331
2361
  } // eslint-disable-next-line react-hooks/exhaustive-deps
2332
2362
 
2333
2363
  }, []);
2334
- React__default["default"].useEffect(function () {
2335
- if (standardTAC !== '') {
2336
- setTAC(standardTAC);
2337
- }
2338
- }, [standardTAC]);
2339
- return [TAC, retrieveTAC];
2364
+ return [TAC, retrieveTAC, onSetTac];
2340
2365
  };
2341
2366
  var useDragOrder = function useDragOrder(trigger, move, onFormBlur) {
2342
2367
  var _a = __read(React__default["default"].useState(null), 2),
@@ -2485,6 +2510,10 @@
2485
2510
  return 'AMD';
2486
2511
  }
2487
2512
 
2513
+ if (tafAction === 'CANCEL') {
2514
+ return 'CNL';
2515
+ }
2516
+
2488
2517
  return taf.messageType;
2489
2518
  }; // For corrections and amendment we need to add the previousValidStart and End for the TAC converter
2490
2519
 
@@ -2522,15 +2551,52 @@
2522
2551
 
2523
2552
 
2524
2553
  var taf = tafAction === 'AMEND' || tafAction === 'DRAFT_AMEND' || tafAction === 'CORRECT' || tafAction === 'DRAFT_CORRECT' ? getAmendedCorrectedTafTimes(_taf, tafAction) : _taf;
2554
+ var formattedBaseForecast = formatFormValues(taf.baseForecast);
2555
+
2556
+ var baseForecast = __assign(__assign(__assign({}, emptyBaseForecast), formattedBaseForecast), {
2557
+ weather: __assign(__assign({}, emptyBaseForecast.weather), formattedBaseForecast.weather),
2558
+ cloud: __assign(__assign({}, emptyBaseForecast.cloud), formattedBaseForecast.cloud)
2559
+ });
2560
+
2525
2561
  return __assign(__assign(__assign(__assign({}, taf), {
2526
2562
  messageType: getMessageType(taf, tafAction),
2527
- baseForecast: formatFormValues(taf.baseForecast)
2563
+ baseForecast: baseForecast
2528
2564
  }), taf.changeGroups && {
2529
2565
  changeGroups: taf.changeGroups.map(formatFormValues)
2530
2566
  }), addEmptyChangeGroup && {
2531
2567
  changeGroups: [emptyChangegroup]
2532
2568
  });
2533
2569
  };
2570
+ var getIsFormDefaultDisabled = function getIsFormDefaultDisabled(status) {
2571
+ return !(status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED');
2572
+ };
2573
+ var fromStatusToAction = function fromStatusToAction(tafStatus) {
2574
+ switch (tafStatus) {
2575
+ case 'DRAFT':
2576
+ return 'DRAFT';
2577
+
2578
+ case 'DRAFT_AMENDED':
2579
+ return 'DRAFT_AMEND';
2580
+
2581
+ case 'DRAFT_CORRECTED':
2582
+ return 'DRAFT_CORRECT';
2583
+
2584
+ case 'PUBLISHED':
2585
+ return 'PUBLISH';
2586
+
2587
+ case 'AMENDED':
2588
+ return 'AMEND';
2589
+
2590
+ case 'CORRECTED':
2591
+ return 'CORRECT';
2592
+
2593
+ case 'CANCELLED':
2594
+ return 'CANCEL';
2595
+
2596
+ default:
2597
+ return 'NEW';
2598
+ }
2599
+ };
2534
2600
 
2535
2601
  var textFieldStyle = function textFieldStyle(theme) {
2536
2602
  return {
@@ -2880,7 +2946,7 @@
2880
2946
  getValues = _g.getValues,
2881
2947
  trigger = _g.trigger;
2882
2948
 
2883
- var isNotRequiredForAction = shared.useDraftFormHelpers().isRequired; // cross-field required validation
2949
+ var isNotRequiredForAction = shared.useDraftFormHelpers(true).isRequired; // cross-field required validation
2884
2950
 
2885
2951
  var _h = __read(getRequiredCrossFields(fieldNames), 3),
2886
2952
  mainFields = _h[0],
@@ -3309,6 +3375,36 @@
3309
3375
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3310
3376
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
3311
3377
  * */
3378
+ var tafActionToDraftAction = function tafActionToDraftAction(tafAction) {
3379
+ switch (tafAction) {
3380
+ case 'AMEND':
3381
+ case 'DRAFT_AMEND':
3382
+ return 'DRAFT_AMEND';
3383
+
3384
+ case 'CORRECT':
3385
+ case 'DRAFT_CORRECT':
3386
+ return 'DRAFT_CORRECT';
3387
+
3388
+ default:
3389
+ return 'DRAFT';
3390
+ }
3391
+ };
3392
+
3393
+ var tafActionToPublishAction = function tafActionToPublishAction(tafAction) {
3394
+ switch (tafAction) {
3395
+ case 'AMEND':
3396
+ case 'DRAFT_AMEND':
3397
+ return 'AMEND';
3398
+
3399
+ case 'CORRECT':
3400
+ case 'DRAFT_CORRECT':
3401
+ return 'CORRECT';
3402
+
3403
+ default:
3404
+ return 'PUBLISH';
3405
+ }
3406
+ };
3407
+
3312
3408
  var buttonsStyle = {
3313
3409
  button: {
3314
3410
  minWidth: {
@@ -3338,7 +3434,7 @@
3338
3434
  return onTafViewModeButtonPress('CANCEL');
3339
3435
  }
3340
3436
  }, "Cancel"), canBe.includes('CORRECTED') && /*#__PURE__*/React__default["default"].createElement(material.Button, {
3341
- "data-testid": "correctaf",
3437
+ "data-testid": "correcttaf",
3342
3438
  variant: "tertiary",
3343
3439
  onClick: function onClick() {
3344
3440
  return onTafViewModeButtonPress('CORRECT');
@@ -3392,21 +3488,7 @@
3392
3488
  if action DRAFT_AMEND - new status will be DRAFT_AMENDED
3393
3489
  if action DRAFT_CORRECT - new status will be DRAFT_CORRECTED
3394
3490
  */
3395
- switch (tafAction) {
3396
- case 'AMEND':
3397
- case 'DRAFT_AMEND':
3398
- onTafEditModeButtonPress('DRAFT_AMEND');
3399
- break;
3400
-
3401
- case 'CORRECT':
3402
- case 'DRAFT_CORRECT':
3403
- onTafEditModeButtonPress('DRAFT_CORRECT');
3404
- break;
3405
-
3406
- default:
3407
- onTafEditModeButtonPress('DRAFT');
3408
- break;
3409
- }
3491
+ onTafEditModeButtonPress(tafActionToDraftAction(tafAction));
3410
3492
  }
3411
3493
  }, "Save"), /*#__PURE__*/React__default["default"].createElement(material.Button, {
3412
3494
  "data-testid": "publishtaf",
@@ -3419,21 +3501,7 @@
3419
3501
  if action DRAFT_AMEND - new status will be AMENDED
3420
3502
  if action DRAFT_CORRECT - new status will be CORRECTED
3421
3503
  */
3422
- switch (tafAction) {
3423
- case 'AMEND':
3424
- case 'DRAFT_AMEND':
3425
- onTafEditModeButtonPress('AMEND');
3426
- break;
3427
-
3428
- case 'CORRECT':
3429
- case 'DRAFT_CORRECT':
3430
- onTafEditModeButtonPress('CORRECT');
3431
- break;
3432
-
3433
- default:
3434
- onTafEditModeButtonPress('PUBLISH');
3435
- break;
3436
- }
3504
+ onTafEditModeButtonPress(tafActionToPublishAction(tafAction));
3437
3505
  }
3438
3506
  }, "Publish"))), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
3439
3507
  item: true,
@@ -3685,20 +3753,6 @@
3685
3753
  }
3686
3754
  };
3687
3755
 
3688
- var getErrorDefaultMessage = function getErrorDefaultMessage(error) {
3689
- switch (error.type) {
3690
- case 'required':
3691
- {
3692
- return 'this field is required';
3693
- }
3694
-
3695
- default:
3696
- {
3697
- return error.message;
3698
- }
3699
- }
3700
- };
3701
-
3702
3756
  var capitalizeWord = function capitalizeWord(_a) {
3703
3757
  var _b = __read(_a),
3704
3758
  firstLetter = _b[0],
@@ -3734,7 +3788,7 @@
3734
3788
  firstNamePart = _a[0];
3735
3789
 
3736
3790
  var fieldErrorTitle = humanizeErrorMessage(firstNamePart);
3737
- return index + 1 + ". " + fieldErrorTitle + ": " + getErrorDefaultMessage(error);
3791
+ return index + 1 + ". " + fieldErrorTitle + ": " + error.message;
3738
3792
  };
3739
3793
  var MODAL_DIALOG_ELEMENT = 'modal-dialog';
3740
3794
  var useIssuesPane = function useIssuesPane() {
@@ -3813,101 +3867,150 @@
3813
3867
  }))), rootElement);
3814
3868
  };
3815
3869
 
3816
- var fromStatusToAction = function fromStatusToAction(tafStatus) {
3817
- switch (tafStatus) {
3818
- case 'DRAFT':
3819
- return 'DRAFT';
3820
-
3821
- case 'DRAFT_AMENDED':
3822
- return 'DRAFT_AMEND';
3870
+ var TafModuleContext = /*#__PURE__*/React__namespace.createContext({
3871
+ onValidateForm: null,
3872
+ registerValidateForm: null,
3873
+ tafAction: null,
3874
+ setTafAction: null,
3875
+ isFormDirty: null,
3876
+ setIsFormDirty: null
3877
+ });
3878
+ var useTafModuleContext = function useTafModuleContext() {
3879
+ return React__namespace.useContext(TafModuleContext);
3880
+ };
3881
+ var useTafModuleState = function useTafModuleState(_a) {
3882
+ var onPreventCloseView = _a.onPreventCloseView;
3883
+ var api$1 = api.useApiContext().api;
3823
3884
 
3824
- case 'DRAFT_CORRECTED':
3825
- return 'DRAFT_CORRECT';
3885
+ var _b = __read(React__namespace.useState(function () {
3886
+ return new Promise(function () {
3887
+ return true;
3888
+ });
3889
+ }), 2),
3890
+ onValidateForm = _b[0],
3891
+ registerValidateForm = _b[1];
3826
3892
 
3827
- case 'PUBLISHED':
3828
- return 'PUBLISH';
3893
+ var _c = __read(React__namespace.useState(), 2),
3894
+ tafAction = _c[0],
3895
+ setTafAction = _c[1];
3829
3896
 
3830
- case 'AMENDED':
3831
- return 'AMEND';
3897
+ var _d = __read(React__namespace.useState(false), 2),
3898
+ isFormDirty = _d[0],
3899
+ setIsFormDirty = _d[1];
3832
3900
 
3833
- case 'CORRECTED':
3834
- return 'CORRECT';
3901
+ var _e = __read(useTACGenerator(undefined, api$1.getTAC), 3),
3902
+ TAC = _e[0],
3903
+ updateTAC = _e[1],
3904
+ setTAC = _e[2];
3835
3905
 
3836
- case 'CANCELLED':
3837
- return 'CANCEL';
3906
+ var onRegisterValidateForm = function onRegisterValidateForm(promiseToRegister) {
3907
+ registerValidateForm(function () {
3908
+ return promiseToRegister;
3909
+ });
3910
+ };
3838
3911
 
3839
- default:
3840
- return 'NEW';
3841
- }
3842
- }; // prevents default functionality
3912
+ var onChangeFormDirty = function onChangeFormDirty(isDirty) {
3913
+ if (isDirty !== isFormDirty) {
3914
+ setIsFormDirty(isDirty);
3915
+ onPreventCloseView(isDirty);
3916
+ }
3917
+ };
3843
3918
 
3919
+ return {
3920
+ onValidateForm: onValidateForm,
3921
+ registerValidateForm: onRegisterValidateForm,
3922
+ tafAction: tafAction,
3923
+ setTafAction: setTafAction,
3924
+ TAC: TAC,
3925
+ updateTAC: updateTAC,
3926
+ setTAC: setTAC,
3927
+ isFormDirty: isFormDirty,
3928
+ setIsFormDirty: onChangeFormDirty
3929
+ };
3930
+ };
3931
+ var TafModuleProvider = function TafModuleProvider(_a) {
3932
+ var children = _a.children,
3933
+ _b = _a.onPreventCloseView,
3934
+ onPreventCloseView = _b === void 0 ? function () {} : _b;
3935
+ var contextState = useTafModuleState({
3936
+ onPreventCloseView: onPreventCloseView
3937
+ });
3938
+ return /*#__PURE__*/React__namespace.createElement(TafModuleContext.Provider, {
3939
+ value: contextState
3940
+ }, children);
3941
+ };
3844
3942
 
3845
3943
  var noop = function noop() {};
3846
3944
 
3847
3945
  var TafForm = function TafForm(_a) {
3848
- var _b = _a.isDisabled,
3849
- isDefaultDisabled = _b === void 0 ? false : _b,
3850
- tafFromBackend = _a.tafFromBackend,
3851
- _c = _a.onFormAction,
3852
- onFormAction = _c === void 0 ? function () {
3946
+ var tafFromBackend = _a.tafFromBackend,
3947
+ _b = _a.onFormAction,
3948
+ onFormAction = _b === void 0 ? function () {
3853
3949
  return null;
3854
- } : _c,
3855
- _d = _a.onFormDirty,
3856
- onFormDirty = _d === void 0 ? function () {
3950
+ } : _b,
3951
+ _c = _a.isIssuesPaneOpen,
3952
+ isIssuesPaneOpen = _c === void 0 ? false : _c,
3953
+ _d = _a.setIsIssuesPaneOpen,
3954
+ setIsIssuesPaneOpen = _d === void 0 ? function () {
3857
3955
  return null;
3858
3956
  } : _d,
3859
- _e = _a.isIssuesPaneOpen,
3860
- isIssuesPaneOpen = _e === void 0 ? false : _e,
3861
- _f = _a.setIsIssuesPaneOpen,
3862
- setIsIssuesPaneOpen = _f === void 0 ? function () {
3957
+ _e = _a.isDisabled,
3958
+ isDisabled = _e === void 0 ? false : _e,
3959
+ _f = _a.setIsDisabled,
3960
+ setIsDisabled = _f === void 0 ? function () {
3863
3961
  return null;
3864
3962
  } : _f;
3865
3963
  var originalTaf = tafFromBackend.taf;
3866
- var defaultTafAction = fromStatusToAction(originalTaf.status);
3867
-
3868
- var _g = __read(React__default["default"].useState(defaultTafAction), 2),
3869
- tafAction = _g[0],
3870
- setTafAction = _g[1];
3871
-
3872
- var _h = __read(React__default["default"].useState(isDefaultDisabled), 2),
3873
- isDisabled = _h[0],
3874
- setIsDisabled = _h[1];
3875
-
3964
+ var isDefaultDisabled = getIsFormDefaultDisabled(tafFromBackend.taf.status);
3876
3965
  var confirmDialog = shared.useConfirmationDialog();
3877
3966
 
3878
- var _j = shared.useDraftFormHelpers(),
3879
- toggleIsDraft = _j.toggleIsDraft,
3880
- DraftFieldHelper = _j.DraftFieldHelper;
3967
+ var _g = shared.useDraftFormHelpers(true),
3968
+ toggleIsDraft = _g.toggleIsDraft,
3969
+ DraftFieldHelper = _g.DraftFieldHelper;
3970
+
3971
+ var _h = useTafModuleContext(),
3972
+ registerValidateForm = _h.registerValidateForm,
3973
+ tafAction = _h.tafAction,
3974
+ setIsFormDirty = _h.setIsFormDirty,
3975
+ setTafAction = _h.setTafAction,
3976
+ TAC = _h.TAC,
3977
+ updateTAC = _h.updateTAC,
3978
+ setTAC = _h.setTAC;
3881
3979
 
3882
- var api$1 = api.useApiContext().api;
3883
3980
  var isMounted = shared.useIsMounted().isMounted;
3884
3981
 
3885
- var _k = reactHookForm.useFormContext(),
3886
- control = _k.control,
3887
- handleSubmit = _k.handleSubmit,
3888
- trigger = _k.trigger,
3889
- formState = _k.formState,
3890
- getValues = _k.getValues,
3891
- setValue = _k.setValue,
3892
- reset = _k.reset;
3982
+ var _j = reactHookForm.useFormContext(),
3983
+ control = _j.control,
3984
+ handleSubmit = _j.handleSubmit,
3985
+ trigger = _j.trigger,
3986
+ formState = _j.formState,
3987
+ getValues = _j.getValues,
3988
+ setValue = _j.setValue,
3989
+ reset = _j.reset;
3893
3990
 
3894
3991
  var isFormDirty = formState.isDirty,
3895
3992
  errors = formState.errors;
3896
3993
  shared.usePreventBrowserClose(isFormDirty && !isDisabled);
3897
3994
  var hiddenInputFields = ['baseTime', 'issueDate', 'type', 'uuid', 'validDateStart', 'validDateEnd', 'status', 'previousId', 'previousValidDateStart', 'previousValidDateEnd'];
3898
3995
 
3899
- var _l = __read(React__default["default"].useState(getValues()), 2),
3900
- delayedFormValues = _l[0],
3901
- setDelayedFormValues = _l[1];
3902
-
3903
- var _m = __read(useTACGenerator(tafFromBackend.taf, api$1.getTAC), 2),
3904
- TAC = _m[0],
3905
- updateTAC = _m[1];
3996
+ var _k = __read(React__default["default"].useState(getValues()), 2),
3997
+ delayedFormValues = _k[0],
3998
+ setDelayedFormValues = _k[1];
3906
3999
 
3907
4000
  var hasErrors = Object.keys(errors).length;
3908
4001
 
3909
4002
  var onFormBlur = function onFormBlur() {
3910
- setDelayedFormValues(getValues());
4003
+ if (!lodash.isEqual(getValues(), delayedFormValues)) {
4004
+ setDelayedFormValues(getValues());
4005
+ }
4006
+ };
4007
+
4008
+ var resetTAC = function resetTAC() {
4009
+ if (originalTaf.status !== 'NEW') {
4010
+ updateTAC(originalTaf);
4011
+ } else {
4012
+ setTAC(TAC_NOT_AVAILABLE);
4013
+ }
3911
4014
  };
3912
4015
 
3913
4016
  React__default["default"].useEffect(function () {
@@ -3926,8 +4029,8 @@
3926
4029
  }, [hasErrors]); // Needed to be able to show a confirmation dialog on switching tabs when form is edited and not saved
3927
4030
 
3928
4031
  React__default["default"].useEffect(function () {
3929
- onFormDirty(isFormDirty);
3930
- }, [isFormDirty, onFormDirty]);
4032
+ setIsFormDirty(isFormDirty);
4033
+ }, [isFormDirty, setIsFormDirty]);
3931
4034
 
3932
4035
  var onSubmit = function onSubmit(data) {
3933
4036
  // eslint-disable-next-line no-console
@@ -3972,6 +4075,7 @@
3972
4075
  toggleIsDraft(true);
3973
4076
  handleSubmit(function (data) {
3974
4077
  onFormAction(action, convertTafValuesToObject(data));
4078
+ reset(getValues());
3975
4079
  })();
3976
4080
  break;
3977
4081
 
@@ -3979,6 +4083,7 @@
3979
4083
  if (isFormDirty) {
3980
4084
  showConfirmDialog(action).then(function () {
3981
4085
  resetForm(undefined, isDefaultDisabled);
4086
+ resetTAC();
3982
4087
  });
3983
4088
  } else {
3984
4089
  resetForm(undefined, isDefaultDisabled);
@@ -4035,7 +4140,7 @@
4035
4140
  switch (action) {
4036
4141
  case 'CANCEL':
4037
4142
  showConfirmDialog(action).then(function () {
4038
- onFormAction(action, tafFromBackend.taf);
4143
+ onFormAction(action, convertTafValuesToObject(prepareTafValues(tafFromBackend.taf, action)));
4039
4144
  });
4040
4145
  break;
4041
4146
 
@@ -4045,19 +4150,19 @@
4045
4150
  }
4046
4151
  };
4047
4152
 
4048
- var _o = reactHookForm.useFieldArray({
4153
+ var _l = reactHookForm.useFieldArray({
4049
4154
  control: control,
4050
4155
  name: 'changeGroups'
4051
4156
  }),
4052
- fields = _o.fields,
4053
- insert = _o.insert,
4054
- remove = _o.remove,
4055
- move = _o.move;
4157
+ fields = _l.fields,
4158
+ insert = _l.insert,
4159
+ remove = _l.remove,
4160
+ move = _l.move;
4056
4161
 
4057
- var _p = useDragOrder(trigger, move, onFormBlur),
4058
- onChangeOrder = _p.onChangeOrder,
4059
- onStartDrag = _p.onStartDrag,
4060
- activeDraggingIndex = _p.activeDraggingIndex;
4162
+ var _m = useDragOrder(trigger, move, onFormBlur),
4163
+ onChangeOrder = _m.onChangeOrder,
4164
+ onStartDrag = _m.onStartDrag,
4165
+ activeDraggingIndex = _m.activeDraggingIndex;
4061
4166
 
4062
4167
  var onRemoverow = function onRemoverow(index) {
4063
4168
  confirmDialog({
@@ -4138,20 +4243,46 @@
4138
4243
  });
4139
4244
  };
4140
4245
 
4141
- var _q = __read(React__default["default"].useState(false), 2),
4142
- shouldValidate = _q[0],
4143
- setShouldValidate = _q[1];
4246
+ var _o = __read(React__default["default"].useState(false), 2),
4247
+ shouldValidate = _o[0],
4248
+ setShouldValidate = _o[1];
4144
4249
 
4145
4250
  React__default["default"].useEffect(function () {
4146
- var defaultValues = prepareTafValues(tafFromBackend.taf, undefined, !isDisabled && !tafFromBackend.taf.changeGroups); // set initial form values
4251
+ setIsDisabled(isDefaultDisabled);
4252
+ var defaultValues = prepareTafValues(tafFromBackend.taf, undefined, !isDefaultDisabled && !tafFromBackend.taf.changeGroups); // set initial form values
4147
4253
 
4148
4254
  reset(defaultValues); // set validate flag to validate after the values have been set
4149
4255
 
4150
- setShouldValidate(true);
4256
+ setShouldValidate(true); // register validate method to use in parent components
4257
+
4258
+ var onValidateFormPromise = function onValidateFormPromise() {
4259
+ return new Promise(function (resolve, reject) {
4260
+ toggleIsDraft(true);
4261
+ handleSubmit(function (formData) {
4262
+ resolve(convertTafValuesToObject(formData));
4263
+ })().then(function (formData) {
4264
+ if (formData === undefined) {
4265
+ reject();
4266
+ }
4267
+
4268
+ resolve(formData);
4269
+ });
4270
+ });
4271
+ };
4272
+
4273
+ registerValidateForm(onValidateFormPromise); // set default taf action
4274
+
4275
+ setTafAction(fromStatusToAction(originalTaf.status));
4276
+ resetTAC();
4151
4277
  return function () {
4152
- reset();
4278
+ reset({});
4153
4279
  }; // eslint-disable-next-line react-hooks/exhaustive-deps
4154
4280
  }, []);
4281
+ React__default["default"].useEffect(function () {
4282
+ var newValues = prepareTafValues(tafFromBackend.taf, undefined, !isDefaultDisabled && !tafFromBackend.taf.changeGroups); // set new form values when tafFromBackend changed
4283
+
4284
+ reset(newValues); // eslint-disable-next-line react-hooks/exhaustive-deps
4285
+ }, [tafFromBackend]);
4155
4286
  React__default["default"].useEffect(function () {
4156
4287
  if (shouldValidate && !isDisabled) {
4157
4288
  // trigger validation on all changegroup validity times after initial load since they could be outside the new validity period
@@ -4443,6 +4574,20 @@
4443
4574
  'aria-controls': "simple-tabpanel-" + index
4444
4575
  };
4445
4576
  };
4577
+ var prepareTafExportValues = function prepareTafExportValues(tafToCopy, currentTaf) {
4578
+ var _a;
4579
+
4580
+ var convertedCopy = prepareTafValues(tafToCopy, undefined, false);
4581
+ var baseForecast = convertedCopy.baseForecast,
4582
+ _b = convertedCopy.changeGroups,
4583
+ changeGroups = _b === void 0 ? [] : _b;
4584
+ return __assign(__assign({}, currentTaf), {
4585
+ baseForecast: __assign(__assign({}, baseForecast), {
4586
+ valid: (_a = currentTaf === null || currentTaf === void 0 ? void 0 : currentTaf.baseForecast) === null || _a === void 0 ? void 0 : _a.valid
4587
+ }),
4588
+ changeGroups: changeGroups
4589
+ });
4590
+ };
4446
4591
 
4447
4592
  /* *
4448
4593
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -4533,6 +4678,38 @@
4533
4678
  }));
4534
4679
  };
4535
4680
 
4681
+ /* *
4682
+ * Licensed under the Apache License, Version 2.0 (the "License");
4683
+ * you may not use this file except in compliance with the License.
4684
+ * You may obtain a copy of the License at
4685
+ *
4686
+ * http://www.apache.org/licenses/LICENSE-2.0
4687
+ *
4688
+ * Unless required by applicable law or agreed to in writing, software
4689
+ * distributed under the License is distributed on an "AS IS" BASIS,
4690
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4691
+ * See the License for the specific language governing permissions and
4692
+ * limitations under the License.
4693
+ *
4694
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4695
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
4696
+ * */
4697
+ var ExportIcon = /*#__PURE__*/React__default["default"].createElement(material.SvgIcon, null, /*#__PURE__*/React__default["default"].createElement("path", {
4698
+ 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"
4699
+ }));
4700
+
4701
+ var ExportButton = function ExportButton(_a) {
4702
+ var onClick = _a.onClick,
4703
+ isHidden = _a.isHidden;
4704
+ return isHidden ? null : /*#__PURE__*/React__default["default"].createElement(material.Tooltip, {
4705
+ title: "Import TAC",
4706
+ placement: "left"
4707
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, /*#__PURE__*/React__default["default"].createElement(shared.ToolButton, {
4708
+ onClick: onClick,
4709
+ "data-testid": "export-tac-button"
4710
+ }, ExportIcon)));
4711
+ };
4712
+
4536
4713
  /* *
4537
4714
  * Licensed under the Apache License, Version 2.0 (the "License");
4538
4715
  * you may not use this file except in compliance with the License.
@@ -4553,18 +4730,43 @@
4553
4730
  var TacContainer = function TacContainer(_a) {
4554
4731
  var taf = _a.taf,
4555
4732
  _b = _a.isActive,
4556
- isActive = _b === void 0 ? false : _b;
4733
+ isActive = _b === void 0 ? false : _b,
4734
+ _c = _a.isFormDisabled,
4735
+ isFormDisabled = _c === void 0 ? false : _c;
4557
4736
  var api$1 = api.useApiContext().api;
4558
4737
 
4559
- var _c = __read(useTACGenerator(taf, api$1.getTAC), 2),
4560
- TAC = _c[0],
4561
- retrieveTAC = _c[1];
4738
+ var _d = __read(useTACGenerator(taf, api$1.getTAC), 2),
4739
+ TAC = _d[0],
4740
+ retrieveTAC = _d[1];
4562
4741
 
4563
4742
  var status = taf.status,
4564
4743
  location = taf.location,
4565
4744
  baseTime = taf.baseTime;
4566
4745
  var locationLabel = getLocationSetting(location).label;
4567
4746
  var timeSlot = getTafTimeSlot(baseTime, location, status);
4747
+
4748
+ var _e = reactHookForm.useFormContext(),
4749
+ getValues = _e.getValues,
4750
+ trigger = _e.trigger,
4751
+ setValue = _e.setValue;
4752
+
4753
+ var updateTAC = useTafModuleContext().updateTAC;
4754
+
4755
+ var handleExport = function handleExport() {
4756
+ var currentTaf = getValues();
4757
+ var newTaf = prepareTafExportValues(taf, currentTaf);
4758
+ setValue('baseForecast', newTaf.baseForecast, {
4759
+ shouldDirty: true
4760
+ });
4761
+ setValue('changeGroups', newTaf.changeGroups, {
4762
+ shouldDirty: true
4763
+ });
4764
+ setTimeout(function () {
4765
+ trigger(); // trigger all fields validation
4766
+ }, 0);
4767
+ updateTAC(convertTafValuesToObject(newTaf));
4768
+ };
4769
+
4568
4770
  React__default["default"].useEffect(function () {
4569
4771
  if (isActive) {
4570
4772
  retrieveTAC(taf);
@@ -4580,14 +4782,22 @@
4580
4782
  sx: {
4581
4783
  display: 'flex',
4582
4784
  alignItems: 'center',
4583
- marginBottom: '2px'
4785
+ justifyContent: 'space-between',
4786
+ height: 24
4584
4787
  }
4585
4788
  }, /*#__PURE__*/React__default["default"].createElement(material.Box, {
4586
4789
  sx: {
4587
- width: 20,
4588
- height: 20,
4589
4790
  display: 'flex',
4590
- marginRight: '6px'
4791
+ alignItems: 'center'
4792
+ }
4793
+ }, /*#__PURE__*/React__default["default"].createElement(material.Box, {
4794
+ sx: {
4795
+ width: 24,
4796
+ height: 24,
4797
+ display: 'flex',
4798
+ marginRight: '2px',
4799
+ alignItems: 'center',
4800
+ justifyContent: 'center'
4591
4801
  }
4592
4802
  }, /*#__PURE__*/React__default["default"].createElement(StatusIcon, {
4593
4803
  timeSlot: timeSlot,
@@ -4614,7 +4824,10 @@
4614
4824
  },
4615
4825
  "data-testid": "tafLocationLabel",
4616
4826
  component: "span"
4617
- }, locationLabel))), /*#__PURE__*/React__default["default"].createElement(material.Box, {
4827
+ }, locationLabel))), /*#__PURE__*/React__default["default"].createElement(ExportButton, {
4828
+ onClick: handleExport,
4829
+ isHidden: isFormDisabled || tacHasError(TAC)
4830
+ })), /*#__PURE__*/React__default["default"].createElement(material.Box, {
4618
4831
  sx: {
4619
4832
  fontSize: '12px',
4620
4833
  letterSpacing: '0.4px',
@@ -4650,11 +4863,13 @@
4650
4863
  _e = _a.hideTitle,
4651
4864
  hideTitle = _e === void 0 ? false : _e,
4652
4865
  _f = _a.activeTaf,
4653
- activeTaf = _f === void 0 ? null : _f;
4866
+ activeTaf = _f === void 0 ? null : _f,
4867
+ _g = _a.isFormDisabled,
4868
+ isFormDisabled = _g === void 0 ? false : _g;
4654
4869
 
4655
- var _g = __read(React__default["default"].useState(0), 2),
4656
- activeTab = _g[0],
4657
- setActiveTab = _g[1];
4870
+ var _h = __read(React__default["default"].useState(0), 2),
4871
+ activeTab = _h[0],
4872
+ setActiveTab = _h[1];
4658
4873
 
4659
4874
  var scrollRef = React__default["default"].useRef(null);
4660
4875
  var tabs = [{
@@ -4746,7 +4961,8 @@
4746
4961
  return /*#__PURE__*/React__default["default"].createElement(TacContainer, {
4747
4962
  key: taf.uuid,
4748
4963
  taf: taf,
4749
- isActive: isActiveLocation(taf.location)
4964
+ isActive: isActiveLocation(taf.location),
4965
+ isFormDisabled: isFormDisabled
4750
4966
  });
4751
4967
  }));
4752
4968
  })));
@@ -4980,84 +5196,72 @@
4980
5196
  }
4981
5197
  };
4982
5198
 
4983
- var TafPanel = function TafPanel(_a) {
4984
- var tafFromBackend = _a.tafFromBackend,
4985
- activeTafIndex = _a.activeTafIndex,
4986
- index = _a.index,
4987
- _b = _a.onPostTaf,
4988
- onPostTaf = _b === void 0 ? function () {} : _b,
4989
- _c = _a.onFormDirty,
4990
- onFormDirty = _c === void 0 ? function () {
4991
- return null;
4992
- } : _c,
4993
- _d = _a.isIssuesPaneOpen,
4994
- isIssuesPaneOpen = _d === void 0 ? false : _d,
4995
- _e = _a.setIsIssuesPaneOpen,
4996
- setIsIssuesPaneOpen = _e === void 0 ? function () {
4997
- return null;
4998
- } : _e;
4999
- var api$1 = api.useApiContext().api;
5199
+ var parseErrorMessage = function parseErrorMessage(error, params) {
5200
+ return params.changeStatusTo === 'CANCELLED' ? {
5201
+ type: 'CANCELLED',
5202
+ title: 'Cancelling this TAF failed, please try again'
5203
+ } : {
5204
+ type: 'SERVER',
5205
+ title: 'An error has occurred while saving, please try again',
5206
+ message: shared.isAxiosError(error) ? shared.getAxiosErrorMessage(error) : error.message
5207
+ };
5208
+ };
5000
5209
 
5001
- var _f = __read(React__default["default"].useState(false), 2),
5002
- isLoading = _f[0],
5003
- setLoading = _f[1];
5210
+ var usePostTafRequest = function usePostTafRequest(request, errorParser) {
5211
+ if (errorParser === void 0) {
5212
+ errorParser = parseErrorMessage;
5213
+ }
5004
5214
 
5005
- var _g = __read(React__default["default"].useState(null), 2),
5006
- error = _g[0],
5007
- setError = _g[1]; // removes cancelled error message
5215
+ var isMounted = shared.useIsMounted().isMounted;
5008
5216
 
5217
+ var _a = __read(React__default["default"].useState(false), 2),
5218
+ isLoading = _a[0],
5219
+ setLoading = _a[1];
5009
5220
 
5010
- React__default["default"].useEffect(function () {
5011
- var cancelErrorTimeout = error && error.type === 'CANCELLED' ? setTimeout(function () {
5012
- setError(null);
5013
- }, 10000) : null;
5014
- return function () {
5015
- if (cancelErrorTimeout !== null) {
5016
- clearTimeout(cancelErrorTimeout);
5017
- }
5018
- };
5019
- }, [error]);
5221
+ var _b = __read(React__default["default"].useState(null), 2),
5222
+ error = _b[0],
5223
+ setError = _b[1];
5020
5224
 
5021
- var postTaf = function postTaf(data) {
5225
+ var doRequest = function doRequest(params) {
5022
5226
  return __awaiter(void 0, void 0, void 0, function () {
5023
- var error_1, newError;
5227
+ var error_1, newErrorr;
5024
5228
  return __generator(this, function (_a) {
5025
5229
  switch (_a.label) {
5026
5230
  case 0:
5027
- _a.trys.push([0, 2,, 3]);
5028
-
5029
5231
  setLoading(true);
5232
+ setError(null);
5233
+ _a.label = 1;
5234
+
5235
+ case 1:
5236
+ _a.trys.push([1, 3,, 4]);
5237
+
5030
5238
  return [4
5031
5239
  /*yield*/
5032
- , api$1.postTaf(data)];
5240
+ , request(params)];
5033
5241
 
5034
- case 1:
5242
+ case 2:
5035
5243
  _a.sent();
5036
5244
 
5245
+ if (!isMounted.current) return [2
5246
+ /*return*/
5247
+ ];
5037
5248
  setLoading(false);
5038
5249
  setError(null);
5039
- onFormDirty(false); // callback
5040
-
5041
- onPostTaf();
5042
5250
  return [3
5043
5251
  /*break*/
5044
- , 3];
5252
+ , 4];
5045
5253
 
5046
- case 2:
5254
+ case 3:
5047
5255
  error_1 = _a.sent();
5048
- newError = data.changeStatusTo === 'CANCELLED' ? {
5049
- type: 'CANCELLED',
5050
- title: 'Cancelling this TAF failed, please try again'
5051
- } : {
5052
- type: 'SERVER',
5053
- title: 'An error has occurred while saving, please try again',
5054
- message: shared.getAxiosErrorMessage(error_1)
5055
- };
5056
- setError(newError);
5256
+ if (!isMounted.current) return [2
5257
+ /*return*/
5258
+ ];
5259
+ newErrorr = errorParser ? errorParser(error_1, params) : error_1;
5057
5260
  setLoading(false);
5058
- throw error_1;
5261
+ setError(newErrorr);
5262
+ throw newErrorr;
5059
5263
 
5060
- case 3:
5264
+ case 4:
5061
5265
  return [2
5062
5266
  /*return*/
5063
5267
  ];
@@ -5066,9 +5270,37 @@
5066
5270
  });
5067
5271
  };
5068
5272
 
5069
- var getViewMode = function getViewMode(status) {
5070
- return status === 'NEW' || status === 'DRAFT' || status === 'DRAFT_AMENDED' || status === 'DRAFT_CORRECTED' ? 'edit' : 'view';
5273
+ return {
5274
+ isLoading: isLoading,
5275
+ error: error,
5276
+ setError: setError,
5277
+ doRequest: doRequest
5071
5278
  };
5279
+ };
5280
+
5281
+ var TafPanel = function TafPanel(_a) {
5282
+ var tafFromBackend = _a.tafFromBackend,
5283
+ activeTafIndex = _a.activeTafIndex,
5284
+ index = _a.index,
5285
+ _b = _a.isLoading,
5286
+ isLoading = _b === void 0 ? false : _b,
5287
+ _c = _a.postTaf,
5288
+ postTaf = _c === void 0 ? function () {
5289
+ return null;
5290
+ } : _c,
5291
+ _d = _a.isIssuesPaneOpen,
5292
+ isIssuesPaneOpen = _d === void 0 ? false : _d,
5293
+ _e = _a.setIsIssuesPaneOpen,
5294
+ setIsIssuesPaneOpen = _e === void 0 ? function () {
5295
+ return null;
5296
+ } : _e,
5297
+ _f = _a.isFormDisabled,
5298
+ isFormDisabled = _f === void 0 ? false : _f,
5299
+ _g = _a.setIsFormDisabled,
5300
+ setIsFormDisabled = _g === void 0 ? function () {
5301
+ return null;
5302
+ } : _g,
5303
+ error = _a.error;
5072
5304
 
5073
5305
  var onTafAction = function onTafAction(action, taf) {
5074
5306
  return __awaiter(void 0, void 0, void 0, function () {
@@ -5181,15 +5413,21 @@
5181
5413
  severity: "error",
5182
5414
  title: error.title,
5183
5415
  info: error.message,
5184
- dataTestId: "taf-error"
5185
- }), /*#__PURE__*/React__default["default"].createElement(TafForm, {
5186
- isDisabled: getViewMode(tafFromBackend.taf.status) === 'view',
5416
+ dataTestId: "taf-error",
5417
+ shouldClose: true
5418
+ }), /*#__PURE__*/React__default["default"].createElement(material.Box, {
5419
+ sx: {
5420
+ marginTop: '10px',
5421
+ padding: 1
5422
+ }
5423
+ }, /*#__PURE__*/React__default["default"].createElement(TafForm, {
5187
5424
  tafFromBackend: tafFromBackend,
5188
5425
  onFormAction: onTafAction,
5189
- onFormDirty: onFormDirty,
5190
5426
  isIssuesPaneOpen: isIssuesPaneOpen,
5191
- setIsIssuesPaneOpen: setIsIssuesPaneOpen
5192
- }));
5427
+ setIsIssuesPaneOpen: setIsIssuesPaneOpen,
5428
+ isDisabled: isFormDisabled,
5429
+ setIsDisabled: setIsFormDisabled
5430
+ })));
5193
5431
  };
5194
5432
 
5195
5433
  var IssuesPaneWrapper = function IssuesPaneWrapper(props) {
@@ -5200,11 +5438,18 @@
5200
5438
  }, props));
5201
5439
  };
5202
5440
 
5441
+ var CONFIRM_DIALOG_OPTIONS = {
5442
+ title: 'Whoops',
5443
+ 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.",
5444
+ confirmLabel: 'Exit without saving'
5445
+ };
5446
+
5203
5447
  var TafLayout = function TafLayout(_a) {
5204
5448
  var _b = _a.tafList,
5205
5449
  tafList = _b === void 0 ? [] : _b,
5206
5450
  _c = _a.onPostTaf,
5207
5451
  onPostTaf = _c === void 0 ? function () {} : _c;
5452
+ var api$1 = api.useApiContext().api;
5208
5453
  var confirmDialog = shared.useConfirmationDialog();
5209
5454
 
5210
5455
  var _d = useIssuesPane(),
@@ -5213,44 +5458,127 @@
5213
5458
  onCloseIssuesPane = _d.onCloseIssuesPane,
5214
5459
  startPosition = _d.startPosition;
5215
5460
 
5216
- var _e = __read(React__default["default"].useState(sortTafTimeSlots(tafList)), 2),
5217
- _f = _e[0],
5218
- upcoming = _f.upcoming,
5219
- current = _f.current,
5220
- expired = _f.expired,
5221
- updateSortedTafs = _e[1];
5461
+ var _e = usePostTafRequest(api$1.postTaf),
5462
+ isLoading = _e.isLoading,
5463
+ postTafRequest = _e.doRequest,
5464
+ error = _e.error,
5465
+ setError = _e.setError;
5466
+
5467
+ var _f = useTafModuleContext(),
5468
+ onValidateForm = _f.onValidateForm,
5469
+ tafAction = _f.tafAction,
5470
+ isFormDirty = _f.isFormDirty;
5222
5471
 
5223
- var _g = __read(current.slice(-1), 1),
5224
- lastCurrentTaf = _g[0];
5472
+ var _g = __read(React__default["default"].useState(sortTafTimeSlots(tafList)), 2),
5473
+ _h = _g[0],
5474
+ upcoming = _h.upcoming,
5475
+ current = _h.current,
5476
+ expired = _h.expired,
5477
+ updateSortedTafs = _g[1];
5225
5478
 
5226
- var _h = __read(React__default["default"].useState('UPCOMING'), 2),
5227
- timeSlot = _h[0],
5228
- setTimeSlot = _h[1];
5479
+ var _j = __read(current.slice(-1), 1),
5480
+ lastCurrentTaf = _j[0];
5229
5481
 
5230
- var _j = __read(React__default["default"].useState(upcoming), 2),
5231
- locations = _j[0],
5232
- setLocations = _j[1];
5482
+ var _k = __read(React__default["default"].useState('UPCOMING'), 2),
5483
+ timeSlot = _k[0],
5484
+ setTimeSlot = _k[1];
5233
5485
 
5234
- var _k = __read(React__default["default"].useState(0), 2),
5235
- activeTafIndex = _k[0],
5236
- setActiveTafIndex = _k[1];
5486
+ var _l = __read(React__default["default"].useState(upcoming), 2),
5487
+ locations = _l[0],
5488
+ setLocations = _l[1];
5237
5489
 
5238
- var _l = __read(React__default["default"].useState(false), 2),
5239
- isFormDirty = _l[0],
5240
- setIsFormDirty = _l[1];
5490
+ var _m = __read(React__default["default"].useState(0), 2),
5491
+ activeTafIndex = _m[0],
5492
+ setActiveTafIndex = _m[1];
5493
+
5494
+ var _o = __read(React__default["default"].useState(false), 2),
5495
+ isFormDisabled = _o[0],
5496
+ setIsFormDisabled = _o[1];
5497
+
5498
+ var postTaf = function postTaf(data) {
5499
+ return __awaiter(void 0, void 0, void 0, function () {
5500
+ return __generator(this, function (_a) {
5501
+ switch (_a.label) {
5502
+ case 0:
5503
+ return [4
5504
+ /*yield*/
5505
+ , postTafRequest(data)];
5506
+
5507
+ case 1:
5508
+ _a.sent(); // callback
5509
+
5510
+
5511
+ onPostTaf();
5512
+ return [2
5513
+ /*return*/
5514
+ ];
5515
+ }
5516
+ });
5517
+ });
5518
+ };
5241
5519
 
5242
5520
  function onChangeTab(action, value) {
5243
- if (isFormDirty) {
5244
- confirmDialog({
5245
- title: 'Whoops',
5246
- description: 'Do you want to leave this open TAF without saving it? All changes will be lost.',
5247
- confirmLabel: 'Exit without saving'
5248
- }).then(function () {
5249
- action(value);
5521
+ return __awaiter(this, void 0, void 0, function () {
5522
+ var taf;
5523
+ return __generator(this, function (_a) {
5524
+ switch (_a.label) {
5525
+ case 0:
5526
+ if (!isFormDirty) return [3
5527
+ /*break*/
5528
+ , 6];
5529
+ _a.label = 1;
5530
+
5531
+ case 1:
5532
+ _a.trys.push([1, 4,, 5]);
5533
+
5534
+ return [4
5535
+ /*yield*/
5536
+ , onValidateForm()];
5537
+
5538
+ case 2:
5539
+ taf = _a.sent();
5540
+ return [4
5541
+ /*yield*/
5542
+ , postTaf({
5543
+ taf: taf,
5544
+ changeStatusTo: fromActionToStatus(tafActionToDraftAction(tafAction))
5545
+ })];
5546
+
5547
+ case 3:
5548
+ _a.sent();
5549
+
5550
+ action(value);
5551
+ return [3
5552
+ /*break*/
5553
+ , 5];
5554
+
5555
+ case 4:
5556
+ _a.sent();
5557
+ confirmDialog(CONFIRM_DIALOG_OPTIONS).then(function () {
5558
+ action(value);
5559
+ setError(null);
5560
+ });
5561
+ return [3
5562
+ /*break*/
5563
+ , 5];
5564
+
5565
+ case 5:
5566
+ return [3
5567
+ /*break*/
5568
+ , 7];
5569
+
5570
+ case 6:
5571
+ action(value);
5572
+ setError(null);
5573
+ _a.label = 7;
5574
+
5575
+ case 7:
5576
+ return [2
5577
+ /*return*/
5578
+ ];
5579
+ }
5250
5580
  });
5251
- } else {
5252
- action(value);
5253
- }
5581
+ });
5254
5582
  }
5255
5583
 
5256
5584
  var onChangeLocationTab = function onChangeLocationTab(index) {
@@ -5274,11 +5602,23 @@
5274
5602
  setLocations(updatedLocations); // update active index
5275
5603
 
5276
5604
  var newActiveIndex = updatedLocations.findIndex(function (location) {
5277
- return location.taf.previousId === locations[activeTafIndex].taf.uuid;
5605
+ var _a, _b, _c;
5606
+
5607
+ return ((_a = location === null || location === void 0 ? void 0 : location.taf) === null || _a === void 0 ? void 0 : _a.previousId) === ((_c = (_b = locations[activeTafIndex]) === null || _b === void 0 ? void 0 : _b.taf) === null || _c === void 0 ? void 0 : _c.uuid);
5278
5608
  });
5279
5609
  var newIndex = newActiveIndex !== -1 ? newActiveIndex : activeTafIndex;
5280
5610
  setActiveTafIndex(newIndex); // eslint-disable-next-line react-hooks/exhaustive-deps
5281
5611
  }, [tafList, setLocations]);
5612
+ React__default["default"].useEffect(function () {
5613
+ var cancelErrorTimeout = error && error.type === 'CANCELLED' ? setTimeout(function () {
5614
+ setError(null);
5615
+ }, 10000) : null;
5616
+ return function () {
5617
+ if (cancelErrorTimeout !== null) {
5618
+ clearTimeout(cancelErrorTimeout);
5619
+ }
5620
+ };
5621
+ }, [error, setError]);
5282
5622
 
5283
5623
  if (!tafList) {
5284
5624
  return null;
@@ -5353,10 +5693,9 @@
5353
5693
  }, /*#__PURE__*/React__default["default"].createElement(material.Card, {
5354
5694
  variant: "outlined",
5355
5695
  sx: {
5356
- padding: 1,
5357
- paddingTop: 0,
5358
5696
  marginBottom: '12px',
5359
- position: 'relative'
5697
+ position: 'relative',
5698
+ minHeight: locations.length * 62 + 32
5360
5699
  }
5361
5700
  }, /*#__PURE__*/React__default["default"].createElement(TacOverviewMobile, {
5362
5701
  upcomingTafs: upcoming,
@@ -5369,26 +5708,32 @@
5369
5708
  activeTafIndex: activeTafIndex,
5370
5709
  index: index,
5371
5710
  tafFromBackend: tafFromBackend,
5372
- onPostTaf: onPostTaf,
5373
- onFormDirty: setIsFormDirty,
5374
5711
  isIssuesPaneOpen: isIssuesPaneOpen,
5375
- setIsIssuesPaneOpen: onToggleIssuesPane
5712
+ setIsIssuesPaneOpen: onToggleIssuesPane,
5713
+ isFormDisabled: isFormDisabled,
5714
+ setIsFormDisabled: setIsFormDisabled,
5715
+ postTaf: postTaf,
5716
+ isLoading: isLoading,
5717
+ error: error
5376
5718
  });
5377
5719
  }))), /*#__PURE__*/React__default["default"].createElement(material.Grid, {
5378
5720
  item: true,
5379
- xs: 3,
5380
- sx: {
5381
- height: '100%'
5721
+ xs: 0,
5722
+ sm: 3,
5723
+ height: {
5724
+ xs: 0,
5725
+ sm: '100%'
5382
5726
  },
5383
- display: {
5384
- xs: 'none',
5385
- sm: 'block'
5727
+ width: {
5728
+ xs: 0,
5729
+ sm: '100%'
5386
5730
  }
5387
5731
  }, /*#__PURE__*/React__default["default"].createElement(TacOverview, {
5388
5732
  upcomingTafs: upcoming,
5389
5733
  currentTafs: current,
5390
5734
  expiredTafs: expired,
5391
- activeTaf: activeTaf
5735
+ activeTaf: activeTaf,
5736
+ isFormDisabled: isFormDisabled
5392
5737
  })))))), /*#__PURE__*/React__default["default"].createElement(IssuesPaneWrapper, {
5393
5738
  handleClose: onCloseIssuesPane,
5394
5739
  isOpen: isIssuesPaneOpen,
@@ -5396,96 +5741,37 @@
5396
5741
  }));
5397
5742
  };
5398
5743
 
5399
- /* *
5400
- * Licensed under the Apache License, Version 2.0 (the "License");
5401
- * you may not use this file except in compliance with the License.
5402
- * You may obtain a copy of the License at
5403
- *
5404
- * http://www.apache.org/licenses/LICENSE-2.0
5405
- *
5406
- * Unless required by applicable law or agreed to in writing, software
5407
- * distributed under the License is distributed on an "AS IS" BASIS,
5408
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5409
- * See the License for the specific language governing permissions and
5410
- * limitations under the License.
5411
- *
5412
- * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
5413
- * Copyright 2022 - Finnish Meteorological Institute (FMI)
5414
- * */
5415
-
5416
5744
  var TafWrapper = function TafWrapper(_a) {
5417
- var children = _a.children;
5418
- return /*#__PURE__*/React__namespace.createElement(shared.ConfirmationServiceProvider, null, /*#__PURE__*/React__namespace.createElement(formFields.ReactHookFormProvider, {
5745
+ var children = _a.children,
5746
+ props = __rest(_a, ["children"]);
5747
+
5748
+ return /*#__PURE__*/React__namespace.createElement(TafModuleProvider, __assign({}, props), /*#__PURE__*/React__namespace.createElement(shared.ConfirmationServiceProvider, null, /*#__PURE__*/React__namespace.createElement(formFields.ReactHookFormProvider, {
5419
5749
  options: {
5420
5750
  mode: 'onTouched',
5421
5751
  reValidateMode: 'onChange',
5422
5752
  criteriaMode: 'all'
5423
5753
  }
5424
- }, children));
5754
+ }, children)));
5425
5755
  };
5426
5756
 
5427
5757
  var TafModule = function TafModule() {
5428
5758
  var api$1 = api.useApiContext().api;
5429
5759
 
5430
- var _a = __read(React__namespace.useState(false), 2),
5431
- isLoading = _a[0],
5432
- setLoading = _a[1];
5433
-
5434
- var _b = api.useApi(api$1.getTafList),
5435
- getTafListError = _b.error,
5436
- isFetchingInitial = _b.isLoading,
5437
- tafList = _b.result,
5438
- fetchNewTafList = _b.fetchApiData;
5760
+ var _a = api.useApi(api$1.getTafList),
5761
+ getTafListError = _a.error,
5762
+ isLoading = _a.isLoading,
5763
+ tafList = _a.result,
5764
+ fetchNewTafList = _a.fetchApiData;
5439
5765
 
5440
5766
  shared.usePoller([tafList, getTafListError], function () {
5441
5767
  return fetchNewTafList({});
5442
5768
  });
5443
5769
 
5444
- var reFetchNewTafList = function reFetchNewTafList() {
5445
- return __awaiter(void 0, void 0, void 0, function () {
5446
- return __generator(this, function (_a) {
5447
- switch (_a.label) {
5448
- case 0:
5449
- _a.trys.push([0, 2,, 3]);
5450
-
5451
- setLoading(true);
5452
- return [4
5453
- /*yield*/
5454
- , fetchNewTafList({})];
5455
-
5456
- case 1:
5457
- _a.sent();
5458
-
5459
- setLoading(false);
5460
- return [3
5461
- /*break*/
5462
- , 3];
5463
-
5464
- case 2:
5465
- _a.sent();
5466
- setLoading(false);
5467
- return [3
5468
- /*break*/
5469
- , 3];
5470
-
5471
- case 3:
5472
- return [2
5473
- /*return*/
5474
- ];
5475
- }
5476
- });
5477
- });
5770
+ var onPostTaf = function onPostTaf() {
5771
+ fetchNewTafList({});
5478
5772
  };
5479
5773
 
5480
5774
  var hasTafListError = getTafListError !== null;
5481
-
5482
- if (isFetchingInitial) {
5483
- return /*#__PURE__*/React__namespace.createElement(LinearProgress__default["default"], {
5484
- color: "secondary",
5485
- "data-testid": "loading-bar"
5486
- });
5487
- }
5488
-
5489
5775
  return /*#__PURE__*/React__namespace.createElement(material.Box, {
5490
5776
  component: "div",
5491
5777
  id: "tafmodule",
@@ -5501,15 +5787,20 @@
5501
5787
  }), hasTafListError && /*#__PURE__*/React__namespace.createElement(shared.AlertBanner, {
5502
5788
  severity: "error",
5503
5789
  title: "An error has occurred while retrieving the list",
5504
- info: getTafListError.message
5790
+ info: getTafListError.message,
5791
+ dataTestId: "taf-list-error",
5792
+ actionButtonProps: {
5793
+ title: 'Try again',
5794
+ onClick: fetchNewTafList
5795
+ }
5505
5796
  }), /*#__PURE__*/React__namespace.createElement(TafLayout, {
5506
5797
  tafList: tafList,
5507
- onPostTaf: reFetchNewTafList
5798
+ onPostTaf: onPostTaf
5508
5799
  }));
5509
5800
  };
5510
5801
 
5511
- var Wrapper = function Wrapper() {
5512
- return /*#__PURE__*/React__namespace.createElement(TafWrapper, null, /*#__PURE__*/React__namespace.createElement(TafModule, null));
5802
+ var Wrapper = function Wrapper(props) {
5803
+ return /*#__PURE__*/React__namespace.createElement(TafWrapper, __assign({}, props), /*#__PURE__*/React__namespace.createElement(TafModule, null));
5513
5804
  };
5514
5805
 
5515
5806
  var createApi$1 = function createApi(url, appUrl, auth, setAuth, authTokenUrl, authClientId) {
@@ -5522,8 +5813,10 @@
5522
5813
  postTaf: function postTaf(formData) {
5523
5814
  return axiosInstance.post('/taf', __assign({}, formData));
5524
5815
  },
5525
- getTAC: function getTAC(tafData) {
5526
- return axiosInstance.post('/taf2tac', __assign({}, tafData));
5816
+ getTAC: function getTAC(tafData, signal) {
5817
+ return axiosInstance.post.apply(axiosInstance, __spreadArray(['/taf2tac'], __read(__spreadArray([__assign({}, tafData)], __read(signal ? [{
5818
+ signal: signal
5819
+ }] : [])))));
5527
5820
  }
5528
5821
  };
5529
5822
  };
@@ -6163,7 +6456,7 @@
6163
6456
  change: 'BECMG',
6164
6457
  valid: {
6165
6458
  start: currentDate + "T23:00:00Z",
6166
- end: tomorrowDate + "T00:00:00Z"
6459
+ end: tomorrowDate + "T01:00:00Z"
6167
6460
  },
6168
6461
  wind: {
6169
6462
  direction: 150,
@@ -6419,7 +6712,7 @@
6419
6712
  }
6420
6713
  }
6421
6714
  }
6422
- }; // Only use for display purposes in the list!
6715
+ };
6423
6716
 
6424
6717
  ({
6425
6718
  creationDate: "2022-01-06T14:00:00Z",
@@ -6443,13 +6736,21 @@
6443
6736
 
6444
6737
  var fakeTafTac = 'TAF EHAM 0812/0918 20020G35KT 0500 SN BKN040\nBECMG 0814/0816 0700 BKN001=';
6445
6738
 
6446
- var fakePromise = function fakePromise(withRandomError) {
6739
+ var fakePromise = function fakePromise(withRandomError, signal) {
6740
+ if (signal === void 0) {
6741
+ signal = null;
6742
+ }
6743
+
6447
6744
  return new Promise(function (resolve, reject) {
6448
- setTimeout(function () {
6745
+ var timer = setTimeout(function () {
6449
6746
  if (!withRandomError) return resolve();
6450
6747
  var randomError = Math.floor(Math.random() * 4) + 1;
6451
6748
  return randomError === 4 ? reject(new Error('something went wrong')) : resolve();
6452
6749
  }, 300);
6750
+ signal === null || signal === void 0 ? void 0 : signal.signal.addEventListener('abort', function () {
6751
+ clearTimeout(timer);
6752
+ reject(new Error('canceled'));
6753
+ });
6453
6754
  });
6454
6755
  };
6455
6756
 
@@ -6459,8 +6760,8 @@
6459
6760
  return fakePromise(false);
6460
6761
  },
6461
6762
  // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types
6462
- post: function post(_url, _params) {
6463
- return fakePromise(false);
6763
+ post: function post(_url, _params, _signal) {
6764
+ return fakePromise(false, _signal);
6464
6765
  }
6465
6766
  };
6466
6767
  var createApi = function createApi() {
@@ -6474,28 +6775,119 @@
6474
6775
  };
6475
6776
  });
6476
6777
  },
6477
- getTAC: function getTAC() {
6478
- // eslint-disable-next-line no-console
6479
- return fakeAxiosInstance.post('/taf2tac').then(function () {
6480
- return {
6481
- data: fakeTafTac
6482
- };
6483
- });
6484
- },
6485
6778
  postTaf: function postTaf(_postTaf) {
6486
6779
  // eslint-disable-next-line no-console
6487
6780
  console.log("The new status of the taf will be " + _postTaf.changeStatusTo); // eslint-disable-next-line no-console
6488
6781
 
6489
6782
  console.log('form has been posted with following values:', _postTaf.taf);
6490
6783
  return fakeAxiosInstance.post('/taf', _postTaf);
6784
+ },
6785
+ getTAC: function getTAC(tafData, signal) {
6786
+ return fakeAxiosInstance.post.apply(fakeAxiosInstance, __spreadArray(['/taf2tac'], __read(__spreadArray([__assign({}, tafData)], __read(signal ? [{
6787
+ signal: signal
6788
+ }] : []))))).then(function () {
6789
+ return {
6790
+ data: fakeTafTac
6791
+ };
6792
+ });
6491
6793
  }
6492
6794
  };
6493
6795
  };
6494
6796
 
6797
+ /* *
6798
+ * Licensed under the Apache License, Version 2.0 (the "License");
6799
+ * you may not use this file except in compliance with the License.
6800
+ * You may obtain a copy of the License at
6801
+ *
6802
+ * http://www.apache.org/licenses/LICENSE-2.0
6803
+ *
6804
+ * Unless required by applicable law or agreed to in writing, software
6805
+ * distributed under the License is distributed on an "AS IS" BASIS,
6806
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
6807
+ * See the License for the specific language governing permissions and
6808
+ * limitations under the License.
6809
+ *
6810
+ * Copyright 2022 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
6811
+ * Copyright 2022 - Finnish Meteorological Institute (FMI)
6812
+ * */
6813
+ var tafScreenPreset = {
6814
+ id: 'screenConfigTaf',
6815
+ title: 'TAF',
6816
+ views: {
6817
+ byId: {
6818
+ taf: {
6819
+ title: 'TAF',
6820
+ componentType: 'TafModule',
6821
+ initialProps: {}
6822
+ }
6823
+ },
6824
+ allIds: ['taf']
6825
+ },
6826
+ syncGroups: [],
6827
+ mosaicNode: 'taf'
6828
+ };
6829
+ var TafApiWrapper = function TafApiWrapper(_a) {
6830
+ var config = _a.config,
6831
+ auth = _a.auth,
6832
+ onSetAuth = _a.onSetAuth,
6833
+ onPreventCloseView = _a.onPreventCloseView;
6834
+ return config ? /*#__PURE__*/React__namespace.createElement(api.ApiProvider, {
6835
+ baseURL: config.baseUrl,
6836
+ appURL: config.appUrl,
6837
+ auth: auth,
6838
+ onSetAuth: onSetAuth,
6839
+ createApi: createApi$1,
6840
+ authTokenUrl: config.authTokenUrl,
6841
+ authClientId: config.authClientId
6842
+ }, /*#__PURE__*/React__namespace.createElement(shared.ErrorBoundary, null, /*#__PURE__*/React__namespace.createElement(Wrapper, {
6843
+ onPreventCloseView: onPreventCloseView
6844
+ }))) : null;
6845
+ };
6846
+ var componentsLookUp = function componentsLookUp(payload, _a, // TODO: find a good way to type this module without the apps complaining
6847
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
6848
+ ConnectedModuleWrapper) {
6849
+ var config = _a.config,
6850
+ auth = _a.auth,
6851
+ onSetAuth = _a.onSetAuth;
6852
+
6853
+ if (ConnectedModuleWrapper === void 0) {
6854
+ ConnectedModuleWrapper = null;
6855
+ }
6856
+
6857
+ var componentType = payload.componentType;
6858
+
6859
+ switch (componentType) {
6860
+ case 'TafModule':
6861
+ if (ConnectedModuleWrapper) {
6862
+ return /*#__PURE__*/React__namespace.createElement(ConnectedModuleWrapper, {
6863
+ component: TafApiWrapper,
6864
+ payload: payload,
6865
+ "data-testid": "tafmodule",
6866
+ config: config,
6867
+ auth: auth,
6868
+ onSetAuth: onSetAuth
6869
+ });
6870
+ }
6871
+
6872
+ return /*#__PURE__*/React__namespace.createElement(TafApiWrapper, {
6873
+ "data-testid": "tafmodule",
6874
+ config: config,
6875
+ auth: auth,
6876
+ onSetAuth: onSetAuth
6877
+ });
6878
+
6879
+ default:
6880
+ return null;
6881
+ }
6882
+ };
6883
+
6884
+ exports.TafApiWrapper = TafApiWrapper;
6495
6885
  exports.TafForm = TafForm;
6496
6886
  exports.TafModule = Wrapper;
6887
+ exports.componentsLookUp = componentsLookUp;
6497
6888
  exports.createApi = createApi$1;
6498
6889
  exports.createFakeApi = createApi;
6890
+ exports.tafScreenPreset = tafScreenPreset;
6499
6891
 
6500
6892
  Object.defineProperty(exports, '__esModule', { value: true });
6501
6893