@opengeoweb/taf 1.2.5 → 2.1.2

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/taf.esm.js CHANGED
@@ -3,8 +3,8 @@ import React__default from 'react';
3
3
  import { makeStyles, Grid, TextField, IconButton, Tooltip, Chip, SvgIcon, Typography, Button, Dialog, DialogTitle, DialogContent, Card, Accordion, AccordionSummary, AccordionDetails, Backdrop, CircularProgress } from '@material-ui/core';
4
4
  import { Skeleton } from '@material-ui/lab';
5
5
  import moment from 'moment';
6
- import { useDraftFormHelpers, ToolContainerDraggable, useConfirmationDialog, useIsMounted, usePreventBrowserClose, StatusTag, AlertBanner, ConfirmationServiceProvider, usePoller, isAxiosError, getAxiosErrorMessage } from '@opengeoweb/shared';
7
- import { Delete, DragIndicator, Add, Close, InfoOutlined, Create, CheckCircle, Schedule, OpenInNew, ExpandMore } from '@material-ui/icons';
6
+ import { useIsMounted, useDraftFormHelpers, ToolContainerDraggable, useConfirmationDialog, usePreventBrowserClose, StatusTag, AlertBanner, ConfirmationServiceProvider, usePoller, isAxiosError, getAxiosErrorMessage } from '@opengeoweb/shared';
7
+ import { Add, Delete, DragIndicator, Close, InfoOutlined, Create, CheckCircle, Schedule, OpenInNew, ExpandMore } from '@material-ui/icons';
8
8
  import { useApiContext, useApi, createApiInstance } from '@opengeoweb/api';
9
9
  import { getDeepProperty, ReactHookFormHiddenInput, ReactHookFormProvider } from '@opengeoweb/form-fields';
10
10
  import { useFormContext, Controller, useFieldArray } from 'react-hook-form';
@@ -26,6 +26,72 @@ function _typeof(obj) {
26
26
  return _typeof(obj);
27
27
  }
28
28
 
29
+ function _defineProperty(obj, key, value) {
30
+ if (key in obj) {
31
+ Object.defineProperty(obj, key, {
32
+ value: value,
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true
36
+ });
37
+ } else {
38
+ obj[key] = value;
39
+ }
40
+
41
+ return obj;
42
+ }
43
+
44
+ function _slicedToArray(arr, i) {
45
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
46
+ }
47
+
48
+ function _toArray(arr) {
49
+ return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest();
50
+ }
51
+
52
+ function _toConsumableArray(arr) {
53
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
54
+ }
55
+
56
+ function _arrayWithoutHoles(arr) {
57
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
58
+ }
59
+
60
+ function _arrayWithHoles(arr) {
61
+ if (Array.isArray(arr)) return arr;
62
+ }
63
+
64
+ function _iterableToArray(iter) {
65
+ if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
66
+ }
67
+
68
+ function _iterableToArrayLimit(arr, i) {
69
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
70
+ var _arr = [];
71
+ var _n = true;
72
+ var _d = false;
73
+ var _e = undefined;
74
+
75
+ try {
76
+ for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
77
+ _arr.push(_s.value);
78
+
79
+ if (i && _arr.length === i) break;
80
+ }
81
+ } catch (err) {
82
+ _d = true;
83
+ _e = err;
84
+ } finally {
85
+ try {
86
+ if (!_n && _i["return"] != null) _i["return"]();
87
+ } finally {
88
+ if (_d) throw _e;
89
+ }
90
+ }
91
+
92
+ return _arr;
93
+ }
94
+
29
95
  function _unsupportedIterableToArray(o, minLen) {
30
96
  if (!o) return;
31
97
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
@@ -43,29 +109,69 @@ function _arrayLikeToArray(arr, len) {
43
109
  return arr2;
44
110
  }
45
111
 
46
- function _createForOfIteratorHelperLoose(o, allowArrayLike) {
112
+ function _nonIterableSpread() {
113
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
114
+ }
115
+
116
+ function _nonIterableRest() {
117
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
118
+ }
119
+
120
+ function _createForOfIteratorHelper(o, allowArrayLike) {
47
121
  var it;
48
122
 
49
123
  if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
50
124
  if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
51
125
  if (it) o = it;
52
126
  var i = 0;
53
- return function () {
54
- if (i >= o.length) return {
55
- done: true
56
- };
57
- return {
58
- done: false,
59
- value: o[i++]
60
- };
127
+
128
+ var F = function () {};
129
+
130
+ return {
131
+ s: F,
132
+ n: function () {
133
+ if (i >= o.length) return {
134
+ done: true
135
+ };
136
+ return {
137
+ done: false,
138
+ value: o[i++]
139
+ };
140
+ },
141
+ e: function (e) {
142
+ throw e;
143
+ },
144
+ f: F
61
145
  };
62
146
  }
63
147
 
64
148
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
65
149
  }
66
150
 
67
- it = o[Symbol.iterator]();
68
- return it.next.bind(it);
151
+ var normalCompletion = true,
152
+ didErr = false,
153
+ err;
154
+ return {
155
+ s: function () {
156
+ it = o[Symbol.iterator]();
157
+ },
158
+ n: function () {
159
+ var step = it.next();
160
+ normalCompletion = step.done;
161
+ return step;
162
+ },
163
+ e: function (e) {
164
+ didErr = true;
165
+ err = e;
166
+ },
167
+ f: function () {
168
+ try {
169
+ if (!normalCompletion && it.return != null) it.return();
170
+ } finally {
171
+ if (didErr) throw err;
172
+ }
173
+ }
174
+ };
69
175
  }
70
176
 
71
177
  /* *
@@ -177,19 +283,21 @@ function __awaiter(thisArg, _arguments, P, generator) {
177
283
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
178
284
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
179
285
  * */
286
+ var FORMAT_DAYS_HOURS = 'DDHH';
287
+ var FORMAT_DAYS_HOURS_MINUTS = 'DDHHmm'; // formatters
180
288
 
181
289
  var formatValidToString = function formatValidToString(valid) {
182
290
  // Ensure end of valid period if midnight is shown as 24 and not 00
183
291
  var endHours = moment.utc(valid.end).format('kk');
184
292
  var endDate = endHours === '24' ? moment.utc(valid.end).add(-1, 'day').format('DD') : moment.utc(valid.end).format('DD');
185
- return valid.end ? moment.utc(valid.start).format('DDHH') + "/" + endDate + endHours : moment.utc(valid.start).format('DDHHmm');
293
+ return valid.end ? "".concat(moment.utc(valid.start).format(FORMAT_DAYS_HOURS), "/").concat(endDate).concat(endHours) : moment.utc(valid.start).format(FORMAT_DAYS_HOURS_MINUTS);
186
294
  };
187
295
 
188
296
  var getSections = function getSections(value, format) {
189
297
  return {
190
298
  day: parseInt(value.substring(0, 2), 10),
191
299
  hour: parseInt(value.substring(2, 4), 10),
192
- min: format === 'DDHHmm' ? parseInt(value.substring(4), 10) : 0
300
+ min: format === FORMAT_DAYS_HOURS_MINUTS ? parseInt(value.substring(4), 10) : 0
193
301
  };
194
302
  };
195
303
 
@@ -219,7 +327,7 @@ var parseValidToObject = function parseValidToObject(value, tafStart, tafEnd) {
219
327
  var tafStartMoment = moment.utc(tafStart);
220
328
  var tafEndMoment = moment.utc(tafEnd);
221
329
  var startEnd = trimmedValue.split('/');
222
- var format = trimmedValue.indexOf('/') === -1 ? 'DDHHmm' : 'DDHH';
330
+ var format = trimmedValue.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTS : FORMAT_DAYS_HOURS;
223
331
  var startSections = getSections(startEnd[0], format);
224
332
  var start = getValidityTimeStamp('start', startSections, tafStartMoment, tafEndMoment).format('YYYY-MM-DDTHH:mm:ss[Z]'); // If we only have start value - return that otherwise, also get end time
225
333
 
@@ -229,7 +337,7 @@ var parseValidToObject = function parseValidToObject(value, tafStart, tafEnd) {
229
337
  };
230
338
  }
231
339
 
232
- var endSections = getSections(startEnd[1], 'DDHH');
340
+ var endSections = getSections(startEnd[1], FORMAT_DAYS_HOURS);
233
341
  var end = getValidityTimeStamp('end', endSections, tafStartMoment, tafEndMoment).format('YYYY-MM-DDTHH:mm:ss[Z]');
234
342
  return {
235
343
  start: start,
@@ -268,7 +376,7 @@ var validateIsValidDates = function validateIsValidDates(value, tafStart, tafEnd
268
376
  var tafStartMoment = moment.utc(tafStart);
269
377
  var tafEndMoment = moment.utc(tafEnd);
270
378
  var startEnd = value.split('/');
271
- var format = value.indexOf('/') === -1 ? 'DDHHmm' : 'DDHH';
379
+ var format = value.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTS : FORMAT_DAYS_HOURS;
272
380
  var validateMsg = []; // Validate start time
273
381
 
274
382
  var startSections = getSections(startEnd[0], format); // Validate individual sections for start
@@ -284,7 +392,7 @@ var validateIsValidDates = function validateIsValidDates(value, tafStart, tafEnd
284
392
 
285
393
 
286
394
  if (startEnd.length > 1) {
287
- var endSections = getSections(startEnd[1], 'DDHH'); // Validate individual sections for end
395
+ var endSections = getSections(startEnd[1], FORMAT_DAYS_HOURS); // Validate individual sections for end
288
396
 
289
397
  var sectionValidationEnd = validateValidSections(endSections, 'end'); // If invalid end - return with errors
290
398
 
@@ -346,11 +454,11 @@ var validateValidChangeGroupInterField = function validateValidChangeGroupInterF
346
454
  var tafStartMoment = moment.utc(tafStart);
347
455
  var tafEndMoment = moment.utc(tafEnd);
348
456
  var startEnd = trimmedValue.split('/');
349
- var format = trimmedValue.indexOf('/') === -1 ? 'DDHHmm' : 'DDHH'; // Validate start time
457
+ var format = trimmedValue.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTS : FORMAT_DAYS_HOURS; // Validate start time
350
458
 
351
459
  var startSections = getSections(startEnd[0], format);
352
460
  var startTimestamp = getValidityTimeStamp('start', startSections, tafStartMoment, tafEndMoment);
353
- var endSections = getSections(startEnd[1], 'DDHH');
461
+ var endSections = getSections(startEnd[1], FORMAT_DAYS_HOURS);
354
462
  var endTimestamp = getValidityTimeStamp('end', endSections, tafStartMoment, tafEndMoment);
355
463
  var timeDifference = endTimestamp.diff(startTimestamp, 'hours');
356
464
 
@@ -359,6 +467,57 @@ var validateValidChangeGroupInterField = function validateValidChangeGroupInterF
359
467
  }
360
468
  }
361
469
 
470
+ return true;
471
+ }; // validate previous changeGroup
472
+
473
+ var validProbChangeOrder = ['FM', 'BECMG', 'TEMPO', 'PROB40', 'PROB30', 'PROB40 TEMPO', 'PROB30 TEMPO'];
474
+ var invalidPreviousChangeGroupIsBeforeMessage = 'Valid time should be after previous valid time';
475
+ var invalidPreviousChangeGroupOrderMessage = "When valid times are equal, the change/probability order should be: ".concat(validProbChangeOrder.join(', '));
476
+ var invalidPreviousChangeGroupHasSameValue = "When valid times are equal, probability/change can't have the same value as previous row value";
477
+ var validatePreviousChangeGroup = function validatePreviousChangeGroup(currentChangeGroup, nextChangeGroup, tafStart, tafEnd) {
478
+ // extract the needed values from changeGroups
479
+ var valid = currentChangeGroup.valid,
480
+ _currentChangeGroup$c = currentChangeGroup.change,
481
+ change = _currentChangeGroup$c === void 0 ? '' : _currentChangeGroup$c,
482
+ _currentChangeGroup$p = currentChangeGroup.probability,
483
+ probability = _currentChangeGroup$p === void 0 ? '' : _currentChangeGroup$p;
484
+ var previousValid = nextChangeGroup.valid,
485
+ _nextChangeGroup$chan = nextChangeGroup.change,
486
+ previousChange = _nextChangeGroup$chan === void 0 ? '' : _nextChangeGroup$chan,
487
+ _nextChangeGroup$prob = nextChangeGroup.probability,
488
+ previousProbability = _nextChangeGroup$prob === void 0 ? '' : _nextChangeGroup$prob; // get the parsed values
489
+
490
+ var validValue = parseValidToObject(valid, tafStart, tafEnd);
491
+ var previousValidValue = parseValidToObject(previousValid, tafStart, tafEnd);
492
+
493
+ if (!validValue || !previousValidValue || !change.length && !probability.length) {
494
+ return true;
495
+ } // validate is valid time before
496
+
497
+
498
+ var currentStartTime = moment(validValue.start);
499
+ var previousRowStartTime = moment(previousValidValue.start);
500
+
501
+ if (currentStartTime.isBefore(previousRowStartTime)) {
502
+ return invalidPreviousChangeGroupIsBeforeMessage;
503
+ } // validate same valid time
504
+
505
+
506
+ if (currentStartTime.isSame(previousRowStartTime)) {
507
+ // validate change/probability order
508
+ var currentProbChangeValue = "".concat(probability, " ").concat(change).trim();
509
+ var previousProbChangeValue = "".concat(previousProbability, " ").concat(previousChange).trim();
510
+
511
+ if (validProbChangeOrder.indexOf(currentProbChangeValue) < validProbChangeOrder.indexOf(previousProbChangeValue)) {
512
+ return invalidPreviousChangeGroupOrderMessage;
513
+ } // validate same valid + change/probability value
514
+
515
+
516
+ if (currentProbChangeValue === previousProbChangeValue) {
517
+ return invalidPreviousChangeGroupHasSameValue;
518
+ }
519
+ }
520
+
362
521
  return true;
363
522
  };
364
523
 
@@ -380,8 +539,8 @@ var validateValidChangeGroupInterField = function validateValidChangeGroupInterF
380
539
  * */
381
540
  var prependZeroes = function prependZeroes(value, totalDigits) {
382
541
  var valueAsString = value.toString();
383
- return [].concat(Array(totalDigits - valueAsString.length)).reduce(function (newVal) {
384
- return "0" + newVal;
542
+ return _toConsumableArray(Array(totalDigits - valueAsString.length)).reduce(function (newVal) {
543
+ return "0".concat(newVal);
385
544
  }, valueAsString);
386
545
  };
387
546
 
@@ -393,9 +552,7 @@ var config$1 = [{
393
552
  size: 1
394
553
  }];
395
554
  var configAsObject$1 = Object.assign(config$1).reduce(function (list, item) {
396
- var _Object$assign;
397
-
398
- return Object.assign(Object.assign({}, list), (_Object$assign = {}, _Object$assign[item.key] = item, _Object$assign));
555
+ return Object.assign(Object.assign({}, list), _defineProperty({}, item.key, item));
399
556
  }, {}); // formatters
400
557
  // if passed true - visibility is CAVOK, if passed a number - prepend zeroes to size 4
401
558
 
@@ -943,11 +1100,8 @@ var invalidWeatherBRVisibility = 'Invalid weather input, weather code BR needs t
943
1100
  var invalidWeatherFGVisibility = 'Invalid weather input, weather code FG needs to be combined with a visibility below 1000m'; // validations
944
1101
 
945
1102
  var WeatherVisibilityBelow5000 = [WeatherPhenomena.FU, WeatherPhenomena.DU, WeatherPhenomena.HZ, WeatherPhenomena.DRDU, WeatherPhenomena.BLDU];
946
- var validateWeatherField = function validateWeatherField(value, visibilityValue, NSWAllowed) {
947
- if (NSWAllowed === void 0) {
948
- NSWAllowed = true;
949
- }
950
-
1103
+ var validateWeatherField = function validateWeatherField(value, visibilityValue) {
1104
+ var NSWAllowed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
951
1105
  var trimmedValue = value.trim(); // if empty, validate as true
952
1106
 
953
1107
  if (trimmedValue === '') {
@@ -1045,9 +1199,7 @@ function parseWeatherToObject(value) {
1045
1199
  var trimmedWeather = Object.keys(value).reduce(function (obj, key) {
1046
1200
  // only parse it if it has a value
1047
1201
  if (value[key] && value[key].trim()) {
1048
- var _Object$assign;
1049
-
1050
- return Object.assign(Object.assign({}, obj), (_Object$assign = {}, _Object$assign[key] = obj[key].trim(), _Object$assign));
1202
+ return Object.assign(Object.assign({}, obj), _defineProperty({}, key, obj[key].trim()));
1051
1203
  } // if it doesn't have a value, remove it from the list
1052
1204
 
1053
1205
 
@@ -1079,9 +1231,7 @@ var config = [{
1079
1231
  size: 2
1080
1232
  }];
1081
1233
  var configAsObject = Object.assign(config).reduce(function (list, item) {
1082
- var _Object$assign;
1083
-
1084
- return Object.assign(Object.assign({}, list), (_Object$assign = {}, _Object$assign[item.key] = item, _Object$assign));
1234
+ return Object.assign(Object.assign({}, list), _defineProperty({}, item.key, item));
1085
1235
  }, {}); // wind formatters:
1086
1236
 
1087
1237
  var formatWindValues = function formatWindValues(key, value) {
@@ -1117,7 +1267,7 @@ var formatWindValues = function formatWindValues(key, value) {
1117
1267
 
1118
1268
  var _size2 = configAsObject[key].size;
1119
1269
  var newValue = prependZeroes(value, _size2);
1120
- return "G" + newValue.toString();
1270
+ return "G".concat(newValue.toString());
1121
1271
  }
1122
1272
 
1123
1273
  case 'unit':
@@ -1144,11 +1294,8 @@ var formatWindToString = function formatWindToString(value) {
1144
1294
  }, '');
1145
1295
  };
1146
1296
 
1147
- var extractValidateWindSections = function extractValidateWindSections(value, validation) {
1148
- if (validation === void 0) {
1149
- validation = false;
1150
- }
1151
-
1297
+ var extractValidateWindSections = function extractValidateWindSections(value) {
1298
+ var validation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1152
1299
  return config.reduce(function (obj, item) {
1153
1300
  var key = item.key,
1154
1301
  size = item.size;
@@ -1299,8 +1446,11 @@ var invalidWindDirectionMinMaxMessage = 'Invalid wind direction, the direction m
1299
1446
  var invalidWindDirectionStepMessage = 'Invalid wind direction, the direction must be rounded to the nearest step of 10 degrees';
1300
1447
  var invalidWindSpeedMessage = 'Invalid wind speed, expected a speed equal to 2 digits or P99';
1301
1448
  var invalidWindGustsMessage = 'Invalid wind gusts, expected gusts equal to 2 digits or P99';
1302
- var invalidWindGustSpeedCombinationMessage = 'Invalid wind, wind gusts must at least be 10 knots greater than the wind speed';
1303
- var invalidGustForWindP99Message = 'Invalid wind speed and gust combination, if wind is P99, gusts can only be empty or P99'; // validations
1449
+ var invalidWindGustSpeedCombinationMessage = 'Invalid wind gusts, gusts must at least be 10 knots greater than the wind speed';
1450
+ var invalidWindGustSpeedBelow15Message = 'Invalid wind gusts, gusts are only allowed for a minimum wind speed of 15 knots';
1451
+ var invalidGustForWindP99Message = 'Invalid wind speed and gust combination, if wind is P99, gusts can only be empty or P99';
1452
+ var invalidWindSpeedForDirectionZeroMessage = 'Invalid wind speed, if direction is 000, speed can only be 00';
1453
+ var invalidWindSpeedForDirectionNonZeroMessage = 'Invalid wind speed, if direction is not 000, speed can not be 00'; // validations
1304
1454
 
1305
1455
  var validateDirection = function validateDirection(value) {
1306
1456
  // if not a number
@@ -1348,8 +1498,16 @@ var validateUnit = function validateUnit(value) {
1348
1498
  return value === 'KT' || value === '' || invalidWindMessage;
1349
1499
  };
1350
1500
 
1351
- var validateWindInterSection = function validateWindInterSection(speed, gust) {
1352
- if (gust === '' || gust === 'P99') {
1501
+ var validateWindInterSection = function validateWindInterSection(speed, gust, direction) {
1502
+ if (direction === '000' && speed !== '00') {
1503
+ return invalidWindSpeedForDirectionZeroMessage;
1504
+ }
1505
+
1506
+ if (direction !== '000' && speed === '00') {
1507
+ return invalidWindSpeedForDirectionNonZeroMessage;
1508
+ }
1509
+
1510
+ if (gust === '') {
1353
1511
  return true;
1354
1512
  }
1355
1513
 
@@ -1357,7 +1515,15 @@ var validateWindInterSection = function validateWindInterSection(speed, gust) {
1357
1515
  return invalidGustForWindP99Message;
1358
1516
  }
1359
1517
 
1360
- return parseInt(gust, 10) - parseInt(speed, 10) >= 10 || invalidWindGustSpeedCombinationMessage;
1518
+ if (parseInt(speed, 10) < 15) {
1519
+ return invalidWindGustSpeedBelow15Message;
1520
+ }
1521
+
1522
+ if (gust !== 'P99' && parseInt(gust, 10) - parseInt(speed, 10) < 10) {
1523
+ return invalidWindGustSpeedCombinationMessage;
1524
+ }
1525
+
1526
+ return true;
1361
1527
  }; // Main validation function
1362
1528
 
1363
1529
 
@@ -1383,12 +1549,12 @@ var validateWindField = function validateWindField(value) {
1383
1549
  } // Then do any intersection validation
1384
1550
 
1385
1551
 
1386
- return validateWindInterSection(windValidationIndv.speed, windValidationIndv.gust);
1552
+ return validateWindInterSection(windValidationIndv.speed, windValidationIndv.gust, windValidationIndv.direction);
1387
1553
  };
1388
1554
 
1389
1555
  var formatSingleCloud = function formatSingleCloud(value) {
1390
1556
  if (!value) return null;
1391
- return value.type ? "" + value.coverage + prependZeroes(value.height, 3) + value.type : "" + value.coverage + prependZeroes(value.height, 3);
1557
+ return value.type ? "".concat(value.coverage).concat(prependZeroes(value.height, 3)).concat(value.type) : "".concat(value.coverage).concat(prependZeroes(value.height, 3));
1392
1558
  }; // TODO: clouds type = Clouds, but couldn't get it to work properly https://gitlab.com/opengeoweb/opengeoweb/-/issues/119
1393
1559
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
1394
1560
 
@@ -1401,32 +1567,24 @@ var formatCloudsToString = function formatCloudsToString(clouds) {
1401
1567
  switch (key) {
1402
1568
  case 'cloud1':
1403
1569
  {
1404
- var _Object$assign3;
1405
-
1406
1570
  if (clouds[key].verticalVisibility !== undefined) {
1407
- var _Object$assign;
1408
-
1409
1571
  // Format Vertical Visibility
1410
- return Object.assign(Object.assign({}, list), (_Object$assign = {}, _Object$assign[key] = "VV" + prependZeroes(clouds[key].verticalVisibility, 3), _Object$assign));
1572
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, "VV".concat(prependZeroes(clouds[key].verticalVisibility, 3))));
1411
1573
  }
1412
1574
 
1413
1575
  if (clouds[key].coverage) {
1414
- var _Object$assign2;
1415
-
1416
1576
  // Format Cloud
1417
- return Object.assign(Object.assign({}, list), (_Object$assign2 = {}, _Object$assign2[key] = formatSingleCloud(clouds[key]), _Object$assign2));
1577
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, formatSingleCloud(clouds[key])));
1418
1578
  } // Format No Significant Clouds
1419
1579
 
1420
1580
 
1421
- return Object.assign(Object.assign({}, list), (_Object$assign3 = {}, _Object$assign3[key] = clouds[key], _Object$assign3));
1581
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, clouds[key]));
1422
1582
  }
1423
1583
 
1424
1584
  default:
1425
1585
  {
1426
- var _Object$assign4;
1427
-
1428
1586
  // Other cloud keys can only contain a cloud
1429
- return Object.assign(Object.assign({}, list), (_Object$assign4 = {}, _Object$assign4[key] = formatSingleCloud(clouds[key]), _Object$assign4));
1587
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, formatSingleCloud(clouds[key])));
1430
1588
  }
1431
1589
  }
1432
1590
  }
@@ -1457,34 +1615,26 @@ var parseCloudsToObject = function parseCloudsToObject(clouds) {
1457
1615
  switch (key) {
1458
1616
  case 'cloud1':
1459
1617
  {
1460
- var _Object$assign7;
1461
-
1462
1618
  if (isVerticalVisibility(clouds[key])) {
1463
- var _Object$assign5;
1464
-
1465
1619
  // Parse Vertical Visibility
1466
- return Object.assign(Object.assign({}, list), (_Object$assign5 = {}, _Object$assign5[key] = {
1620
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, {
1467
1621
  verticalVisibility: parseInt(clouds[key].substr(2, 3), 10)
1468
- }, _Object$assign5));
1622
+ }));
1469
1623
  }
1470
1624
 
1471
1625
  if (clouds[key] === 'NSC') {
1472
- var _Object$assign6;
1473
-
1474
1626
  // Parse No Significant Clouds
1475
- return Object.assign(Object.assign({}, list), (_Object$assign6 = {}, _Object$assign6[key] = clouds[key], _Object$assign6));
1627
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, clouds[key]));
1476
1628
  } // Parse Cloud
1477
1629
 
1478
1630
 
1479
- return Object.assign(Object.assign({}, list), (_Object$assign7 = {}, _Object$assign7[key] = parseSingleCloud(clouds[key]), _Object$assign7));
1631
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, parseSingleCloud(clouds[key])));
1480
1632
  }
1481
1633
 
1482
1634
  default:
1483
1635
  {
1484
- var _Object$assign8;
1485
-
1486
1636
  // Other cloud keys can only contain a cloud
1487
- return Object.assign(Object.assign({}, list), (_Object$assign8 = {}, _Object$assign8[key] = parseSingleCloud(clouds[key]), _Object$assign8));
1637
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, parseSingleCloud(clouds[key])));
1488
1638
  }
1489
1639
  }
1490
1640
  } // if it doesn't have a value, remove it from the list
@@ -1868,7 +2018,7 @@ var validateFourthCloud = function validateFourthCloud(firstCloudValue, secondCl
1868
2018
  };
1869
2019
 
1870
2020
  var formatIssueTime = function formatIssueTime(issueDate) {
1871
- return issueDate ? moment(issueDate).utc().format('DDHHmm') + "Z" : 'Not issued';
2021
+ return issueDate ? "".concat(moment(issueDate).utc().format('DDHHmm'), "Z") : 'Not issued';
1872
2022
  };
1873
2023
  function formatFormValues(row) {
1874
2024
  return Object.keys(row).reduce(function (list, key) {
@@ -1920,6 +2070,8 @@ function formatFormValues(row) {
1920
2070
 
1921
2071
  function reduceRowValues(row, tafStart, tafEnd) {
1922
2072
  return Object.keys(row).reduce(function (list, key) {
2073
+ var _a;
2074
+
1923
2075
  switch (key) {
1924
2076
  case 'valid':
1925
2077
  {
@@ -1958,9 +2110,7 @@ function reduceRowValues(row, tafStart, tafEnd) {
1958
2110
  case 'change':
1959
2111
  case 'probability':
1960
2112
  {
1961
- var _Object$assign;
1962
-
1963
- return Object.assign(Object.assign({}, list), (_Object$assign = {}, _Object$assign[key] = list[key].trim(), _Object$assign));
2113
+ return Object.assign(Object.assign({}, list), _defineProperty({}, key, (_a = list[key]) === null || _a === void 0 ? void 0 : _a.trim()));
1964
2114
  }
1965
2115
 
1966
2116
  default:
@@ -2132,8 +2282,7 @@ var convertTafValuesToObject = function convertTafValuesToObject(formData) {
2132
2282
  }
2133
2283
  }
2134
2284
  }, parsedFormValues);
2135
- };
2136
- var noTAC = 'Missing data: no TAC can be generated'; // Ensure we have enough data to retrieve a TAC - we only need to check for wind and visibility/ cavok as those are the only ones required in all cases
2285
+ }; // Ensure we have enough data to retrieve a TAC - we only need to check for wind and visibility/ cavok as those are the only ones required in all cases
2137
2286
 
2138
2287
  var shouldRetrieveTAC = function shouldRetrieveTAC(product) {
2139
2288
  if (product && product.baseForecast && product.baseForecast.wind && 'speed' in product.baseForecast.wind && product.baseForecast.wind.speed !== '' && (product.baseForecast.visibility && 'range' in product.baseForecast.visibility && product.baseForecast.visibility.range !== '' || product.baseForecast.cavOK)) {
@@ -2143,46 +2292,55 @@ var shouldRetrieveTAC = function shouldRetrieveTAC(product) {
2143
2292
  return false;
2144
2293
  };
2145
2294
  var getFieldNames = function getFieldNames(isChangeGroup, index) {
2146
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[" + index + "]";
2295
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
2147
2296
  return Object.assign(Object.assign(Object.assign({}, !isChangeGroup && {
2148
2297
  messageType: 'messageType',
2149
2298
  location: 'location',
2150
2299
  issueDate: 'issueDate'
2151
2300
  }), isChangeGroup && {
2152
- probability: namePrefix + ".probability",
2153
- change: namePrefix + ".change"
2301
+ probability: "".concat(namePrefix, ".probability"),
2302
+ change: "".concat(namePrefix, ".change")
2154
2303
  }), {
2155
- valid: namePrefix + ".valid",
2156
- wind: namePrefix + ".wind",
2157
- visibility: namePrefix + ".visibility",
2158
- weather1: namePrefix + ".weather.weather1",
2159
- weather2: namePrefix + ".weather.weather2",
2160
- weather3: namePrefix + ".weather.weather3",
2161
- cloud1: namePrefix + ".cloud.cloud1",
2162
- cloud2: namePrefix + ".cloud.cloud2",
2163
- cloud3: namePrefix + ".cloud.cloud3",
2164
- cloud4: namePrefix + ".cloud.cloud4"
2304
+ valid: "".concat(namePrefix, ".valid"),
2305
+ wind: "".concat(namePrefix, ".wind"),
2306
+ visibility: "".concat(namePrefix, ".visibility"),
2307
+ weather1: "".concat(namePrefix, ".weather.weather1"),
2308
+ weather2: "".concat(namePrefix, ".weather.weather2"),
2309
+ weather3: "".concat(namePrefix, ".weather.weather3"),
2310
+ cloud1: "".concat(namePrefix, ".cloud.cloud1"),
2311
+ cloud2: "".concat(namePrefix, ".cloud.cloud2"),
2312
+ cloud3: "".concat(namePrefix, ".cloud.cloud3"),
2313
+ cloud4: "".concat(namePrefix, ".cloud.cloud4")
2165
2314
  });
2166
2315
  };
2167
- var useTACGenerator = function useTACGenerator(taf, requestTAC, standardTAC) {
2168
- if (standardTAC === void 0) {
2169
- standardTAC = '';
2170
- }
2316
+ var TAC_MISSING_DATA = 'Missing data: no TAC can be generated';
2317
+ var TAC_NOT_AVAILABLE = 'No TAC available';
2318
+ var TAC_RETRIEVING_DATA = 'Retrieving TAC';
2319
+ var useTACGenerator = function useTACGenerator(taf, requestTAC) {
2320
+ var standardTAC = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
2171
2321
 
2172
- var _React$useState = React__default.useState(taf.status === 'NEW' ? 'No TAC available' : 'Retrieving TAC'),
2173
- TAC = _React$useState[0],
2174
- setTAC = _React$useState[1];
2322
+ var _React$useState = React__default.useState(taf.status === 'NEW' ? TAC_NOT_AVAILABLE : TAC_RETRIEVING_DATA),
2323
+ _React$useState2 = _slicedToArray(_React$useState, 2),
2324
+ TAC = _React$useState2[0],
2325
+ setTAC = _React$useState2[1];
2326
+
2327
+ var _useIsMounted = useIsMounted(),
2328
+ isMounted = _useIsMounted.isMounted;
2175
2329
 
2176
2330
  var retrieveTAC = function retrieveTAC(tafToPost) {
2177
2331
  if (shouldRetrieveTAC(tafToPost)) {
2178
2332
  requestTAC(tafToPost).then(function (result) {
2179
- setTAC(result.data);
2333
+ if (isMounted.current) {
2334
+ setTAC(result.data);
2335
+ }
2180
2336
  })["catch"](function () {
2181
- setTAC('Failed to retrieve TAC');
2337
+ if (isMounted.current) {
2338
+ setTAC('Failed to retrieve TAC');
2339
+ }
2182
2340
  });
2341
+ } else {
2342
+ setTAC(TAC_MISSING_DATA);
2183
2343
  }
2184
-
2185
- setTAC(noTAC);
2186
2344
  };
2187
2345
 
2188
2346
  React__default.useEffect(function () {
@@ -2198,22 +2356,16 @@ var useTACGenerator = function useTACGenerator(taf, requestTAC, standardTAC) {
2198
2356
  }, [standardTAC]);
2199
2357
  return [TAC, retrieveTAC];
2200
2358
  };
2201
- var getRange = function getRange(min, max) {
2202
- return Array.from({
2203
- length: max - min + 1
2204
- }, function (_, i) {
2205
- return min + i;
2206
- });
2207
- };
2208
- var useDragOrder = function useDragOrder(trigger, move, fields, onFormBlur) {
2209
- // create simple ordered list with hover (chosen) state
2210
- var _React$useState2 = React__default.useState([]),
2211
- sortedFields = _React$useState2[0],
2212
- setSortedFields = _React$useState2[1];
2359
+ var useDragOrder = function useDragOrder(trigger, move, onFormBlur) {
2360
+ var _React$useState3 = React__default.useState(null),
2361
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
2362
+ activeDraggingIndex = _React$useState4[0],
2363
+ setIsDragging = _React$useState4[1];
2213
2364
 
2214
- var _React$useState3 = React__default.useState([null, null]),
2215
- lastDragOrder = _React$useState3[0],
2216
- onUpdatelastDragOrder = _React$useState3[1];
2365
+ var _React$useState5 = React__default.useState([null, null]),
2366
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
2367
+ lastDragOrder = _React$useState6[0],
2368
+ onUpdatelastDragOrder = _React$useState6[1];
2217
2369
 
2218
2370
  var onChangeOrder = function onChangeOrder(_ref) {
2219
2371
  var oldIndex = _ref.oldIndex,
@@ -2221,45 +2373,30 @@ var useDragOrder = function useDragOrder(trigger, move, fields, onFormBlur) {
2221
2373
  if (oldIndex === undefined || newIndex === undefined) return;
2222
2374
  move(oldIndex, newIndex);
2223
2375
  onUpdatelastDragOrder([oldIndex, newIndex]);
2376
+ setIsDragging(false);
2224
2377
  };
2225
2378
 
2226
- React__default.useEffect(function () {
2227
- setSortedFields(fields.map(function (_ref2) {
2228
- var id = _ref2.id;
2229
- return {
2230
- id: id,
2231
- chosen: false
2232
- };
2233
- }));
2234
- }, [fields]); // triggers validation AFTER render of new sorted elements
2379
+ var onStartDrag = function onStartDrag(_ref2) {
2380
+ var oldIndex = _ref2.oldIndex;
2381
+ return setIsDragging(oldIndex);
2382
+ }; // triggers validation AFTER render of new sorted elements
2383
+
2235
2384
 
2236
2385
  React__default.useEffect(function () {
2237
- var oldIndex = lastDragOrder[0],
2238
- newIndex = lastDragOrder[1];
2386
+ var _lastDragOrder = _slicedToArray(lastDragOrder, 2),
2387
+ oldIndex = _lastDragOrder[0],
2388
+ newIndex = _lastDragOrder[1];
2239
2389
 
2240
2390
  if (oldIndex !== null && newIndex !== null) {
2241
- // trigger validation of moved rows
2242
- var _sort = [oldIndex, newIndex].sort(function (a, b) {
2243
- return a - b;
2244
- }),
2245
- start = _sort[0],
2246
- end = _sort[1];
2247
-
2248
- var changedRows = getRange(start, end);
2249
- var fieldsToValidate = changedRows.reduce(function (list, rowIndex) {
2250
- var fieldsDict = getFieldNames(true, rowIndex);
2251
- var fields = Object.keys(fieldsDict).map(function (key) {
2252
- return fieldsDict[key];
2253
- });
2254
- return list.concat(fields);
2255
- }, []);
2256
- trigger(fieldsToValidate);
2391
+ // trigger validation of all fields
2392
+ trigger();
2257
2393
  }
2258
2394
  }, [lastDragOrder, trigger]); // trigger onFormBlur AFTER render of new sorted elements so the TAC gets updated
2259
2395
 
2260
2396
  React__default.useEffect(function () {
2261
- var oldIndex = lastDragOrder[0],
2262
- newIndex = lastDragOrder[1];
2397
+ var _lastDragOrder2 = _slicedToArray(lastDragOrder, 2),
2398
+ oldIndex = _lastDragOrder2[0],
2399
+ newIndex = _lastDragOrder2[1];
2263
2400
 
2264
2401
  if (oldIndex !== null && newIndex !== null) {
2265
2402
  onFormBlur();
@@ -2268,8 +2405,8 @@ var useDragOrder = function useDragOrder(trigger, move, fields, onFormBlur) {
2268
2405
  }, [lastDragOrder]);
2269
2406
  return {
2270
2407
  onChangeOrder: onChangeOrder,
2271
- sortedFields: sortedFields,
2272
- setSortedFields: setSortedFields
2408
+ activeDraggingIndex: activeDraggingIndex,
2409
+ onStartDrag: onStartDrag
2273
2410
  };
2274
2411
  }; // dialog utils
2275
2412
 
@@ -2281,11 +2418,22 @@ var getConfirmationDialogTitle = function getConfirmationDialogTitle(action) {
2281
2418
  return 'Cancel TAF';
2282
2419
  };
2283
2420
  var getConfirmationDialogContent = function getConfirmationDialogContent(action) {
2284
- if (action === 'DISCARD') return 'Are you sure you would like to discard this TAF? Any changes made will be lost';
2285
- if (action === 'PUBLISH') return 'Are you sure you want to publish this TAF?';
2286
- if (action === 'AMEND') return 'Do you want to publish it?';
2287
- if (action === 'CORRECT') return 'Do you want to publish it?';
2288
- return 'Are you sure you want to cancel this TAF?';
2421
+ var isFormDirty = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
2422
+
2423
+ switch (action) {
2424
+ case 'DISCARD':
2425
+ return 'Are you sure you would like to discard this TAF? Any changes made will be lost';
2426
+
2427
+ case 'PUBLISH':
2428
+ return 'Are you sure you want to publish this TAF?';
2429
+
2430
+ case 'AMEND':
2431
+ case 'CORRECT':
2432
+ return isFormDirty ? 'Do you want to publish it?' : 'Are you sure you want to publish the TAF? You did not make any changes!';
2433
+
2434
+ default:
2435
+ return 'Are you sure you want to cancel this TAF?';
2436
+ }
2289
2437
  };
2290
2438
  var getConfirmationDialogButtonLabel = function getConfirmationDialogButtonLabel(action) {
2291
2439
  switch (action) {
@@ -2362,7 +2510,7 @@ var useStyles$9 = makeStyles(function (theme) {
2362
2510
  borderRadius: '3px'
2363
2511
  },
2364
2512
  addButton: {
2365
- marginRight: '38px'
2513
+ marginRight: '48px'
2366
2514
  },
2367
2515
  lifecycleButtons: {
2368
2516
  marginTop: '40px',
@@ -2377,27 +2525,13 @@ var useStyles$9 = makeStyles(function (theme) {
2377
2525
  backdrop: {
2378
2526
  zIndex: 1500,
2379
2527
  color: '#fff'
2528
+ },
2529
+ emptyButtonContainer: {
2530
+ minWidth: 96
2380
2531
  }
2381
2532
  };
2382
2533
  });
2383
2534
 
2384
- /* *
2385
- * Licensed under the Apache License, Version 2.0 (the "License");
2386
- * you may not use this file except in compliance with the License.
2387
- * You may obtain a copy of the License at
2388
- *
2389
- * http://www.apache.org/licenses/LICENSE-2.0
2390
- *
2391
- * Unless required by applicable law or agreed to in writing, software
2392
- * distributed under the License is distributed on an "AS IS" BASIS,
2393
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2394
- * See the License for the specific language governing permissions and
2395
- * limitations under the License.
2396
- *
2397
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
2398
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
2399
- * */
2400
-
2401
2535
  var getTafErrors = function getTafErrors(name, errors) {
2402
2536
  var nameAsArray = name.split('.');
2403
2537
 
@@ -2470,8 +2604,9 @@ var TafFormTextField = function TafFormTextField(_ref) {
2470
2604
  var fieldErrors = getTafErrors(name, errors);
2471
2605
 
2472
2606
  var _React$useState = React__default.useState(null),
2473
- maxLength = _React$useState[0],
2474
- setMaxLength = _React$useState[1];
2607
+ _React$useState2 = _slicedToArray(_React$useState, 2),
2608
+ maxLength = _React$useState2[0],
2609
+ setMaxLength = _React$useState2[1];
2475
2610
 
2476
2611
  var onKeyDown = React__default.useCallback(function (event) {
2477
2612
  var currentValue = getValues(name).toString();
@@ -2637,9 +2772,11 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2637
2772
  field = _a$field === void 0 ? null : _a$field,
2638
2773
  _a$dragHandle = _a.dragHandle,
2639
2774
  dragHandle = _a$dragHandle === void 0 ? null : _a$dragHandle,
2640
- props = __rest(_a, ["isChangeGroup", "disabled", "index", "lastRow", "onRemoveChangeGroup", "field", "dragHandle"]);
2775
+ onAddChangeGroup = _a.onAddChangeGroup,
2776
+ props = __rest(_a, ["isChangeGroup", "disabled", "index", "lastRow", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroup"]);
2641
2777
 
2642
- var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[" + index + "]";
2778
+ var classes = useStyles$9();
2779
+ var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[".concat(index, "]");
2643
2780
  var fieldNames = getFieldNames(isChangeGroup, index);
2644
2781
 
2645
2782
  var _useFormContext = useFormContext(),
@@ -2651,9 +2788,10 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2651
2788
 
2652
2789
 
2653
2790
  var _getRequiredCrossFiel = getRequiredCrossFields(fieldNames),
2654
- mainFields = _getRequiredCrossFiel[0],
2655
- mainOptionalFields = _getRequiredCrossFiel[1],
2656
- subFields = _getRequiredCrossFiel[2];
2791
+ _getRequiredCrossFiel2 = _slicedToArray(_getRequiredCrossFiel, 3),
2792
+ mainFields = _getRequiredCrossFiel2[0],
2793
+ mainOptionalFields = _getRequiredCrossFiel2[1],
2794
+ subFields = _getRequiredCrossFiel2[2];
2657
2795
 
2658
2796
  var hasFieldsValue = function hasFieldsValue(fields) {
2659
2797
  return fields.map(getValues).find(function (field) {
@@ -2678,8 +2816,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2678
2816
 
2679
2817
 
2680
2818
  var _validateRequiredMainFields = function validateRequiredMainFields(value, fieldName) {
2681
- var changeField = getValues(namePrefix + ".change");
2682
- var visibilityField = getValues(namePrefix + ".visibility");
2819
+ var changeField = getValues("".concat(namePrefix, ".change"));
2820
+ var visibilityField = getValues("".concat(namePrefix, ".visibility"));
2683
2821
  var isFM = changeField && changeField.trim() === 'FM';
2684
2822
  var isCAVOK = visibilityField && visibilityField.trim() === 'CAVOK';
2685
2823
 
@@ -2695,15 +2833,40 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2695
2833
  return true;
2696
2834
  }
2697
2835
 
2698
- return fieldName + " is required";
2836
+ return "".concat(fieldName, " is required");
2699
2837
  }
2700
2838
  }
2701
2839
 
2702
2840
  return true;
2703
2841
  };
2704
2842
 
2843
+ var validatePreviousRow = React__default.useCallback(function () {
2844
+ if (isChangeGroup && index > 0) {
2845
+ var _getValues = getValues(),
2846
+ validDateEnd = _getValues.validDateEnd,
2847
+ validDateStart = _getValues.validDateStart,
2848
+ changeGroups = _getValues.changeGroups;
2849
+
2850
+ var currentChangeGroup = changeGroups[index];
2851
+ var previousChangeGroup = changeGroups[index - 1];
2852
+ return validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, validDateStart, validDateEnd);
2853
+ }
2854
+
2855
+ return true;
2856
+ }, [index, isChangeGroup, getValues]);
2857
+
2858
+ var getFieldFromNextRow = function getFieldFromNextRow() {
2859
+ var fieldname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'valid';
2860
+ var nextValidFieldName = "changeGroups[".concat(index + 1, "].").concat(fieldname);
2861
+ var nextRowValidValue = getValues(nextValidFieldName);
2862
+ return nextRowValidValue ? [nextValidFieldName] : [];
2863
+ };
2864
+
2865
+ var addChangeGroup = React__default.useCallback(function () {
2866
+ onAddChangeGroup(index);
2867
+ }, [onAddChangeGroup, index]);
2705
2868
  return /*#__PURE__*/React__default.createElement(Grid, Object.assign({
2706
- "data-testid": "row-" + namePrefix,
2869
+ "data-testid": "row-".concat(namePrefix),
2707
2870
  container: true,
2708
2871
  ref: ref
2709
2872
  }, props), !isChangeGroup && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(TafFormTextField, {
@@ -2745,7 +2908,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2745
2908
  }],
2746
2909
  onBlur: function onBlur() {
2747
2910
  if (isChangeGroup) {
2748
- trigger([].concat(subFields, mainOptionalFields, mainFields));
2911
+ var nextValidFieldName = getFieldFromNextRow();
2912
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
2749
2913
  }
2750
2914
  }
2751
2915
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
@@ -2774,7 +2938,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2774
2938
  }],
2775
2939
  onBlur: function onBlur() {
2776
2940
  if (isChangeGroup) {
2777
- trigger([].concat(subFields, mainOptionalFields, mainFields));
2941
+ var nextValidFieldName = getFieldFromNextRow();
2942
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
2778
2943
  }
2779
2944
  }
2780
2945
  })), /*#__PURE__*/React__default.createElement(TafFormTextField, {
@@ -2791,12 +2956,14 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2791
2956
  },
2792
2957
  validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
2793
2958
  return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues('validDateStart'), getValues('validDateEnd')) : true;
2794
- }
2959
+ },
2960
+ validatePreviousRow: validatePreviousRow
2795
2961
  }
2796
2962
  },
2797
2963
  onBlur: function onBlur() {
2798
2964
  if (isChangeGroup) {
2799
- trigger([].concat(subFields, mainOptionalFields, mainFields));
2965
+ var nextValidFieldName = getFieldFromNextRow();
2966
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainOptionalFields), _toConsumableArray(mainFields), _toConsumableArray(nextValidFieldName)));
2800
2967
  }
2801
2968
  }
2802
2969
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
@@ -2815,7 +2982,7 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2815
2982
  },
2816
2983
  onBlur: function onBlur() {
2817
2984
  if (isChangeGroup) {
2818
- trigger([].concat(subFields, mainFields));
2985
+ trigger([].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)));
2819
2986
  }
2820
2987
  },
2821
2988
  autoFocus: !isChangeGroup
@@ -2838,8 +3005,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2838
3005
  value: 'CAVOK'
2839
3006
  }],
2840
3007
  onBlur: function onBlur() {
2841
- var fields = isChangeGroup ? [].concat(subFields, mainFields) : subFields;
2842
- trigger([].concat(fields, [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
3008
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : subFields;
3009
+ trigger([].concat(_toConsumableArray(fields), [fieldNames.weather1, fieldNames.weather2, fieldNames.weather3]));
2843
3010
  }
2844
3011
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
2845
3012
  label: "Weather",
@@ -2858,8 +3025,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2858
3025
  }
2859
3026
  },
2860
3027
  onBlur: function onBlur() {
2861
- var fields = isChangeGroup ? [].concat(subFields, mainFields) : [];
2862
- return trigger([].concat(fields, [fieldNames.weather2, fieldNames.weather3]));
3028
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3029
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather2, fieldNames.weather3]));
2863
3030
  }
2864
3031
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
2865
3032
  label: "Weather",
@@ -2874,8 +3041,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2874
3041
  }
2875
3042
  },
2876
3043
  onBlur: function onBlur() {
2877
- var fields = isChangeGroup ? [].concat(subFields, mainFields) : [];
2878
- return trigger([].concat(fields, [fieldNames.weather3]));
3044
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3045
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.weather3]));
2879
3046
  }
2880
3047
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
2881
3048
  label: "Weather",
@@ -2906,8 +3073,8 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2906
3073
  }
2907
3074
  },
2908
3075
  onBlur: function onBlur() {
2909
- var fields = isChangeGroup ? [].concat(subFields, mainFields) : [];
2910
- return trigger([].concat(fields, [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
3076
+ var fields = isChangeGroup ? [].concat(_toConsumableArray(subFields), _toConsumableArray(mainFields)) : [];
3077
+ return trigger([].concat(_toConsumableArray(fields), [fieldNames.cloud2, fieldNames.cloud3, fieldNames.cloud4]));
2911
3078
  }
2912
3079
  }), /*#__PURE__*/React__default.createElement(TafFormTextField, {
2913
3080
  label: "Cloud",
@@ -2952,12 +3119,20 @@ var TafFormRow = /*#__PURE__*/React__default.forwardRef(function (_a, ref) {
2952
3119
  }
2953
3120
  }
2954
3121
  }), (!isChangeGroup || disabled) && /*#__PURE__*/React__default.createElement(Grid, {
3122
+ className: classes.emptyButtonContainer,
2955
3123
  item: true,
2956
3124
  xs: true
2957
- }), isChangeGroup && !disabled && /*#__PURE__*/React__default.createElement(Grid, {
2958
- item: true,
2959
- xs: true
2960
- }, /*#__PURE__*/React__default.createElement(IconButton, Object.assign({
3125
+ }, !disabled && /*#__PURE__*/React__default.createElement(IconButton, {
3126
+ "aria-label": "add",
3127
+ "data-testid": "add-changeGroup",
3128
+ onClick: addChangeGroup
3129
+ }, /*#__PURE__*/React__default.createElement(Add, null))), isChangeGroup && !disabled && /*#__PURE__*/React__default.createElement(Grid, {
3130
+ item: true
3131
+ }, /*#__PURE__*/React__default.createElement(IconButton, {
3132
+ "aria-label": "add",
3133
+ "data-testid": "add-changeGroup",
3134
+ onClick: addChangeGroup
3135
+ }, /*#__PURE__*/React__default.createElement(Add, null)), /*#__PURE__*/React__default.createElement(IconButton, Object.assign({
2961
3136
  "aria-label": "delete",
2962
3137
  "data-testid": "remove-changeGroup",
2963
3138
  onClick: function onClick() {
@@ -2994,7 +3169,7 @@ var getIssuesLabel = function getIssuesLabel(sumOfErrors) {
2994
3169
  return '1 issue';
2995
3170
 
2996
3171
  default:
2997
- return sumOfErrors + " issues";
3172
+ return "".concat(sumOfErrors, " issues");
2998
3173
  }
2999
3174
  };
3000
3175
 
@@ -3096,23 +3271,6 @@ var useStyles$8 = makeStyles({
3096
3271
  }
3097
3272
  });
3098
3273
 
3099
- /* *
3100
- * Licensed under the Apache License, Version 2.0 (the "License");
3101
- * you may not use this file except in compliance with the License.
3102
- * You may obtain a copy of the License at
3103
- *
3104
- * http://www.apache.org/licenses/LICENSE-2.0
3105
- *
3106
- * Unless required by applicable law or agreed to in writing, software
3107
- * distributed under the License is distributed on an "AS IS" BASIS,
3108
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3109
- * See the License for the specific language governing permissions and
3110
- * limitations under the License.
3111
- *
3112
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3113
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3114
- * */
3115
-
3116
3274
  var getPaneTitle = function getPaneTitle(sumOfErrors) {
3117
3275
  switch (sumOfErrors) {
3118
3276
  case 0:
@@ -3141,8 +3299,9 @@ var getErrorDefaultMessage = function getErrorDefaultMessage(error) {
3141
3299
  };
3142
3300
 
3143
3301
  var capitalizeWord = function capitalizeWord(_ref) {
3144
- var firstLetter = _ref[0],
3145
- restOfWord = _ref.slice(1);
3302
+ var _ref2 = _toArray(_ref),
3303
+ firstLetter = _ref2[0],
3304
+ restOfWord = _ref2.slice(1);
3146
3305
 
3147
3306
  return firstLetter.toUpperCase() + restOfWord.join('');
3148
3307
  };
@@ -3151,19 +3310,19 @@ var humanizeErrorMessage = function humanizeErrorMessage(nameAsString) {
3151
3310
  var nameLowerCase = nameWithoutBrackets.toLowerCase();
3152
3311
 
3153
3312
  var _nameLowerCase$split$ = nameLowerCase.split(/([0-9]+)/) // split numbers from field and build array
3154
- . // split numbers from field and build array
3155
- filter(function (s) {
3313
+ .filter(function (s) {
3156
3314
  return s.length;
3157
3315
  }),
3158
- fieldName = _nameLowerCase$split$[0],
3159
- fieldNumberedValue = _nameLowerCase$split$[1];
3316
+ _nameLowerCase$split$2 = _slicedToArray(_nameLowerCase$split$, 2),
3317
+ fieldName = _nameLowerCase$split$2[0],
3318
+ fieldNumberedValue = _nameLowerCase$split$2[1];
3160
3319
 
3161
3320
  var nameCapitalized = capitalizeWord(fieldName);
3162
3321
 
3163
3322
  if (fieldNumberedValue) {
3164
3323
  // when name contains a number we assume it's a formgroup and we add a index +1 for human readability
3165
3324
  var fieldNumber = parseInt(fieldNumberedValue, 10) + 1;
3166
- return nameCapitalized + " " + fieldNumber;
3325
+ return "".concat(nameCapitalized, " ").concat(fieldNumber);
3167
3326
  }
3168
3327
 
3169
3328
  return nameCapitalized;
@@ -3172,17 +3331,18 @@ var getErrorMessage = function getErrorMessage(error, index) {
3172
3331
  var name = error.ref.name;
3173
3332
 
3174
3333
  var _name$split = name.split('.'),
3175
- firstNamePart = _name$split[0];
3334
+ _name$split2 = _slicedToArray(_name$split, 1),
3335
+ firstNamePart = _name$split2[0];
3176
3336
 
3177
3337
  var fieldErrorTitle = humanizeErrorMessage(firstNamePart);
3178
- return index + 1 + ". " + fieldErrorTitle + ": " + getErrorDefaultMessage(error);
3338
+ return "".concat(index + 1, ". ").concat(fieldErrorTitle, ": ").concat(getErrorDefaultMessage(error));
3179
3339
  };
3180
3340
 
3181
- var IssuesPane = function IssuesPane(_ref2) {
3182
- var isOpen = _ref2.isOpen,
3183
- handleClose = _ref2.handleClose,
3184
- _ref2$errorList = _ref2.errorList,
3185
- errorList = _ref2$errorList === void 0 ? [] : _ref2$errorList;
3341
+ var IssuesPane = function IssuesPane(_ref3) {
3342
+ var isOpen = _ref3.isOpen,
3343
+ handleClose = _ref3.handleClose,
3344
+ _ref3$errorList = _ref3.errorList,
3345
+ errorList = _ref3$errorList === void 0 ? [] : _ref3$errorList;
3186
3346
  var classes = useStyles$8();
3187
3347
  return /*#__PURE__*/React.createElement(ToolContainerDraggable, {
3188
3348
  startSize: {
@@ -3209,29 +3369,13 @@ var IssuesPane = function IssuesPane(_ref2) {
3209
3369
  return /*#__PURE__*/React.createElement(Typography // eslint-disable-next-line react/no-array-index-key
3210
3370
  , {
3211
3371
  // eslint-disable-next-line react/no-array-index-key
3212
- key: "message-" + index,
3372
+ key: "message-".concat(index),
3213
3373
  variant: "body1",
3214
3374
  "data-testid": "errorMessage"
3215
3375
  }, getErrorMessage(error, index));
3216
3376
  })));
3217
3377
  };
3218
3378
 
3219
- /* *
3220
- * Licensed under the Apache License, Version 2.0 (the "License");
3221
- * you may not use this file except in compliance with the License.
3222
- * You may obtain a copy of the License at
3223
- *
3224
- * http://www.apache.org/licenses/LICENSE-2.0
3225
- *
3226
- * Unless required by applicable law or agreed to in writing, software
3227
- * distributed under the License is distributed on an "AS IS" BASIS,
3228
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3229
- * See the License for the specific language governing permissions and
3230
- * limitations under the License.
3231
- *
3232
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3233
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3234
- * */
3235
3379
  var getCustomError = function getCustomError(error) {
3236
3380
  var name = error.ref.name;
3237
3381
  var isChangeGroup = name.includes('changeGroups');
@@ -3264,7 +3408,7 @@ var getErrors = function getErrors(errors) {
3264
3408
  var errorValues = errorValue.reduce(function (l, i) {
3265
3409
  return l.concat(getErrorValues(i));
3266
3410
  }, []);
3267
- return list.concat.apply(list, errorValues);
3411
+ return list.concat.apply(list, _toConsumableArray(errorValues));
3268
3412
  }
3269
3413
 
3270
3414
  return list.concat(getErrorValues(errorValue));
@@ -3305,8 +3449,9 @@ var TafFormButtons = function TafFormButtons(_ref) {
3305
3449
  var errorList = filterDuplicateErrors(getErrors(errors));
3306
3450
 
3307
3451
  var _React$useState = React__default.useState(false),
3308
- isIssuesPaneOpen = _React$useState[0],
3309
- setIsIssuesPaneOpen = _React$useState[1];
3452
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3453
+ isIssuesPaneOpen = _React$useState2[0],
3454
+ setIsIssuesPaneOpen = _React$useState2[1];
3310
3455
 
3311
3456
  var toggleIssuesPane = function toggleIssuesPane() {
3312
3457
  return setIsIssuesPaneOpen(!isIssuesPaneOpen);
@@ -3439,30 +3584,16 @@ var DragHandle = function DragHandle(_ref) {
3439
3584
  index = _ref.index;
3440
3585
  var classes = useStyles$7(isSorting);
3441
3586
  return /*#__PURE__*/React__default.createElement(IconButton, {
3442
- className: classes.dragHandle + " handle",
3443
- "data-testid": "dragHandle-" + index,
3587
+ className: "".concat(classes.dragHandle, " handle"),
3588
+ "data-testid": "dragHandle-".concat(index),
3444
3589
  disableRipple: true,
3445
3590
  disabled: isDisabled
3446
3591
  }, /*#__PURE__*/React__default.createElement(DragIndicator, null));
3447
3592
  };
3448
3593
 
3449
- /* *
3450
- * Licensed under the Apache License, Version 2.0 (the "License");
3451
- * you may not use this file except in compliance with the License.
3452
- * You may obtain a copy of the License at
3453
- *
3454
- * http://www.apache.org/licenses/LICENSE-2.0
3455
- *
3456
- * Unless required by applicable law or agreed to in writing, software
3457
- * distributed under the License is distributed on an "AS IS" BASIS,
3458
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3459
- * See the License for the specific language governing permissions and
3460
- * limitations under the License.
3461
- *
3462
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3463
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
3464
- * */
3465
- var emptyRow = {
3594
+ var noop = function noop() {};
3595
+
3596
+ var emptyChangegroup = {
3466
3597
  valid: '',
3467
3598
  wind: '',
3468
3599
  visibility: '',
@@ -3482,8 +3613,7 @@ var emptyRow = {
3482
3613
  };
3483
3614
 
3484
3615
  var TafForm = function TafForm(_ref) {
3485
- var mode = _ref.mode,
3486
- changeGroups = _ref.changeGroups,
3616
+ var isDisabled = _ref.isDisabled,
3487
3617
  tafAction = _ref.tafAction,
3488
3618
  _ref$staticTAC = _ref.staticTAC,
3489
3619
  staticTAC = _ref$staticTAC === void 0 ? '' : _ref$staticTAC,
@@ -3504,55 +3634,49 @@ var TafForm = function TafForm(_ref) {
3504
3634
  var _useIsMounted = useIsMounted(),
3505
3635
  isMounted = _useIsMounted.isMounted;
3506
3636
 
3507
- var isDisabled = mode === 'view';
3508
-
3509
3637
  var _useFormContext = useFormContext(),
3510
3638
  control = _useFormContext.control,
3511
3639
  handleSubmit = _useFormContext.handleSubmit,
3512
3640
  watch = _useFormContext.watch,
3513
- getValues = _useFormContext.getValues,
3514
- errors = _useFormContext.errors,
3515
- trigger = _useFormContext.trigger;
3641
+ trigger = _useFormContext.trigger,
3642
+ formState = _useFormContext.formState,
3643
+ getValues = _useFormContext.getValues;
3516
3644
 
3645
+ var isFormDirty = formState.isDirty,
3646
+ errors = formState.errors;
3647
+ usePreventBrowserClose(isFormDirty && !isDisabled);
3517
3648
  var hiddenInputFields = ['baseTime', 'issueDate', 'type', 'uuid', 'validDateStart', 'validDateEnd', 'status', 'previousId', 'previousValidDateStart', 'previousValidDateEnd'];
3518
3649
 
3519
3650
  var _React$useState = React__default.useState(watch()),
3520
- delayedFormValues = _React$useState[0],
3521
- setDelayedFormValues = _React$useState[1];
3651
+ _React$useState2 = _slicedToArray(_React$useState, 2),
3652
+ delayedFormValues = _React$useState2[0],
3653
+ setDelayedFormValues = _React$useState2[1];
3522
3654
 
3523
3655
  var _useTACGenerator = useTACGenerator(convertTafValuesToObject(delayedFormValues), api.getTAC, staticTAC),
3524
- TAC = _useTACGenerator[0],
3525
- updateTAC = _useTACGenerator[1];
3656
+ _useTACGenerator2 = _slicedToArray(_useTACGenerator, 2),
3657
+ TAC = _useTACGenerator2[0],
3658
+ updateTAC = _useTACGenerator2[1];
3526
3659
 
3527
- React__default.useEffect(function () {
3528
- if (!Object.keys(errors).length && staticTAC === '' && isMounted.current) {
3529
- updateTAC(convertTafValuesToObject(delayedFormValues));
3530
- } // eslint-disable-next-line react-hooks/exhaustive-deps
3531
-
3532
- }, [delayedFormValues]);
3660
+ var hasErrors = Object.keys(errors).length;
3533
3661
 
3534
3662
  var onFormBlur = function onFormBlur() {
3535
3663
  setDelayedFormValues(getValues());
3536
3664
  };
3537
3665
 
3538
- var _React$useState2 = React__default.useState(false),
3539
- isFormDirty = _React$useState2[0],
3540
- setFormDirty = _React$useState2[1];
3541
-
3542
- var onFormChange = function onFormChange() {
3543
- return !isFormDirty ? setFormDirty(true) : null;
3544
- };
3666
+ React__default.useEffect(function () {
3667
+ if (staticTAC === '' && isMounted.current && isFormDirty) {
3668
+ var newTAC = hasErrors ? null : convertTafValuesToObject(delayedFormValues);
3669
+ updateTAC(newTAC);
3670
+ } // eslint-disable-next-line react-hooks/exhaustive-deps
3545
3671
 
3546
- usePreventBrowserClose(isFormDirty && !isDisabled);
3672
+ }, [delayedFormValues]);
3673
+ React__default.useEffect(function () {
3674
+ // prevent updating an error while typing
3675
+ if (!hasErrors && isFormDirty && document.activeElement.tagName !== 'INPUT') {
3676
+ updateTAC(convertTafValuesToObject(delayedFormValues));
3677
+ } // eslint-disable-next-line react-hooks/exhaustive-deps
3547
3678
 
3548
- var _useFieldArray = useFieldArray({
3549
- control: control,
3550
- name: 'changeGroups'
3551
- }),
3552
- fields = _useFieldArray.fields,
3553
- append = _useFieldArray.append,
3554
- remove = _useFieldArray.remove,
3555
- move = _useFieldArray.move;
3679
+ }, [hasErrors]);
3556
3680
 
3557
3681
  var onSubmit = function onSubmit(data) {
3558
3682
  // eslint-disable-next-line no-console
@@ -3562,7 +3686,7 @@ var TafForm = function TafForm(_ref) {
3562
3686
  var showConfirmDialog = function showConfirmDialog(action) {
3563
3687
  return confirmDialog({
3564
3688
  title: getConfirmationDialogTitle(action),
3565
- description: getConfirmationDialogContent(action),
3689
+ description: getConfirmationDialogContent(action, isFormDirty),
3566
3690
  confirmLabel: getConfirmationDialogButtonLabel(action)
3567
3691
  });
3568
3692
  };
@@ -3606,38 +3730,65 @@ var TafForm = function TafForm(_ref) {
3606
3730
  }
3607
3731
  };
3608
3732
 
3733
+ var _useFieldArray = useFieldArray({
3734
+ control: control,
3735
+ name: 'changeGroups'
3736
+ }),
3737
+ fields = _useFieldArray.fields,
3738
+ insert = _useFieldArray.insert,
3739
+ remove = _useFieldArray.remove,
3740
+ move = _useFieldArray.move;
3741
+
3742
+ var _useDragOrder = useDragOrder(trigger, move, onFormBlur),
3743
+ onChangeOrder = _useDragOrder.onChangeOrder,
3744
+ onStartDrag = _useDragOrder.onStartDrag,
3745
+ activeDraggingIndex = _useDragOrder.activeDraggingIndex;
3746
+
3747
+ var onRemoverow = function onRemoverow(index) {
3748
+ confirmDialog({
3749
+ title: 'Delete row',
3750
+ description: 'Are you sure you want to delete this row?',
3751
+ confirmLabel: 'Yes'
3752
+ }).then(function () {
3753
+ remove(index);
3754
+ trigger(); // trigger all fields validation
3755
+
3756
+ onFormBlur();
3757
+ });
3758
+ }; // TODO: https://gitlab.com/opengeoweb/opengeoweb/-/issues/726 insert (react-hook-form) does not work well with focus (only last row will get focus), so added this dirty solution. This can be fixed in a better way in react-hook-form v7
3759
+
3760
+
3761
+ var focusFirstInput = function focusFirstInput(rowIndex) {
3762
+ var nextRowFirstInput = document.querySelector("[name=\"changeGroups[".concat(rowIndex, "].probability\"]"));
3763
+
3764
+ if (nextRowFirstInput) {
3765
+ nextRowFirstInput.focus();
3766
+ }
3767
+ };
3768
+
3609
3769
  var onAddRow = function onAddRow() {
3610
- append(emptyRow);
3770
+ var rowIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : -1;
3771
+ var newRowIndex = rowIndex + 1;
3772
+ insert(newRowIndex, emptyChangegroup, false); // adding rows and validation don't work well combined, with always skipping validation of fields of rows above the one the inserted row. A setTimeout prevents this issue
3773
+
3774
+ setTimeout(function () {
3775
+ focusFirstInput(newRowIndex);
3776
+ trigger(); // trigger all fields validation
3777
+ }, 0);
3611
3778
  };
3612
3779
 
3613
3780
  React__default.useEffect(function () {
3614
- // set changegroups on mount (if no changegroups - add empty one by default)
3615
- if (changeGroups.length > 0) {
3616
- changeGroups.forEach(function (group) {
3617
- append(group, false);
3781
+ if (!isDisabled) {
3782
+ // trigger validation on all changegroup validity times after initial load since they could be outside the new validity period
3783
+ var validFields = fields.map(function (_field, index) {
3784
+ return "changeGroups[".concat(index, "].valid");
3618
3785
  });
3619
- } else if (!isDisabled) {
3620
- append(emptyRow, false);
3786
+ trigger(validFields);
3621
3787
  } // eslint-disable-next-line react-hooks/exhaustive-deps
3622
3788
 
3623
3789
  }, []);
3624
-
3625
- var _useDragOrder = useDragOrder(trigger, move, fields, onFormBlur),
3626
- onChangeOrder = _useDragOrder.onChangeOrder,
3627
- sortedFields = _useDragOrder.sortedFields,
3628
- setSortedFields = _useDragOrder.setSortedFields;
3629
-
3630
- var onRemoverow = function onRemoverow(index) {
3631
- remove(index);
3632
- var newList = fields.length > 1 ? fields.filter(function (_, fieldIndex) {
3633
- return fieldIndex === index;
3634
- }) : [];
3635
- setSortedFields(newList);
3636
- };
3637
-
3638
3790
  return /*#__PURE__*/React__default.createElement("form", {
3639
3791
  onSubmit: handleSubmit(onSubmit),
3640
- onChange: onFormChange,
3641
3792
  onBlur: onFormBlur
3642
3793
  }, /*#__PURE__*/React__default.createElement(Typography, {
3643
3794
  className: classes.tacTitle
@@ -3651,23 +3802,23 @@ var TafForm = function TafForm(_ref) {
3651
3802
  "data-testid": "tafform-tac-message-line"
3652
3803
  }, line);
3653
3804
  })), /*#__PURE__*/React__default.createElement(TafFormRow, {
3654
- disabled: isDisabled
3805
+ disabled: isDisabled,
3806
+ onAddChangeGroup: onAddRow
3655
3807
  }), /*#__PURE__*/React__default.createElement(ReactSortable, {
3656
3808
  tag: "div",
3657
- list: sortedFields,
3658
- setList: setSortedFields,
3809
+ list: fields,
3810
+ setList: noop,
3659
3811
  animation: 200,
3660
3812
  onSort: onChangeOrder,
3661
3813
  handle: ".handle",
3662
3814
  direction: "vertical",
3663
3815
  // hover props
3664
3816
  forceFallback: true,
3665
- onStart: function onStart() {
3817
+ onStart: function onStart(event) {
3818
+ onStartDrag(event);
3666
3819
  Sortable.ghost.style.opacity = '1';
3667
3820
  }
3668
- }, sortedFields.map(function (_ref2, index) {
3669
- var chosen = _ref2.chosen;
3670
- var item = fields[index];
3821
+ }, fields.map(function (item, index) {
3671
3822
  return /*#__PURE__*/React__default.createElement(TafFormRow, {
3672
3823
  field: item,
3673
3824
  className: classes.formRow,
@@ -3676,27 +3827,18 @@ var TafForm = function TafForm(_ref) {
3676
3827
  lastRow: fields.length === index + 1,
3677
3828
  disabled: isDisabled,
3678
3829
  onRemoveChangeGroup: onRemoverow,
3830
+ onAddChangeGroup: onAddRow,
3679
3831
  isChangeGroup: true,
3680
3832
  dragHandle: /*#__PURE__*/React__default.createElement(DragHandle, {
3681
- isDisabled: sortedFields.length === 1 || isDisabled,
3682
- isSorting: chosen,
3833
+ isDisabled: fields.length === 1 || isDisabled,
3834
+ isSorting: activeDraggingIndex === index,
3683
3835
  index: index
3684
3836
  })
3685
3837
  });
3686
- })), !isDisabled && /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Grid, {
3687
- container: true,
3688
- item: true,
3689
- xs: 12,
3690
- justify: "flex-end"
3691
- }, /*#__PURE__*/React__default.createElement(IconButton, {
3692
- "aria-label": "add",
3693
- "data-testid": "add-changeGroup",
3694
- onClick: onAddRow,
3695
- className: classes.addButton
3696
- }, /*#__PURE__*/React__default.createElement(Add, null))), /*#__PURE__*/React__default.createElement(TafFormButtons, {
3838
+ })), !isDisabled && /*#__PURE__*/React__default.createElement(TafFormButtons, {
3697
3839
  tafAction: tafAction,
3698
3840
  onTafFormButtonPress: onTafButtonPress
3699
- })), hiddenInputFields.map(function (field) {
3841
+ }), hiddenInputFields.map(function (field) {
3700
3842
  return /*#__PURE__*/React__default.createElement(ReactHookFormHiddenInput, {
3701
3843
  name: field,
3702
3844
  key: field
@@ -3704,6 +3846,22 @@ var TafForm = function TafForm(_ref) {
3704
3846
  }), /*#__PURE__*/React__default.createElement(DraftFieldHelper, null));
3705
3847
  };
3706
3848
 
3849
+ /* *
3850
+ * Licensed under the Apache License, Version 2.0 (the "License");
3851
+ * you may not use this file except in compliance with the License.
3852
+ * You may obtain a copy of the License at
3853
+ *
3854
+ * http://www.apache.org/licenses/LICENSE-2.0
3855
+ *
3856
+ * Unless required by applicable law or agreed to in writing, software
3857
+ * distributed under the License is distributed on an "AS IS" BASIS,
3858
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3859
+ * See the License for the specific language governing permissions and
3860
+ * limitations under the License.
3861
+ *
3862
+ * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
3863
+ * Copyright 2021 - Finnish Meteorological Institute (FMI)
3864
+ * */
3707
3865
  var getMessageType = function getMessageType(taf, tafAction) {
3708
3866
  if (tafAction === 'CORRECT') {
3709
3867
  return 'COR';
@@ -3743,14 +3901,17 @@ var getAmendedCorrectedTafTimes = function getAmendedCorrectedTafTimes(taf, tafA
3743
3901
  });
3744
3902
  };
3745
3903
  var prepareTafValues = function prepareTafValues(_taf, tafAction) {
3904
+ var addEmptyChangeGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
3746
3905
  // If action is AMEND/CORRECT/DRAFT_AMEND/DRAFT_CORRECTION - add previous valid start and end
3747
3906
  // If action is AMEND/DRAFT_AMEND - update validity start time to current time
3748
3907
  var taf = tafAction === 'AMEND' || tafAction === 'DRAFT_AMEND' || tafAction === 'CORRECT' || tafAction === 'DRAFT_CORRECT' ? getAmendedCorrectedTafTimes(_taf, tafAction) : _taf;
3749
- return Object.assign(Object.assign(Object.assign({}, taf), {
3908
+ return Object.assign(Object.assign(Object.assign(Object.assign({}, taf), {
3750
3909
  messageType: getMessageType(taf, tafAction),
3751
3910
  baseForecast: formatFormValues(taf.baseForecast)
3752
3911
  }), taf.changeGroups && {
3753
3912
  changeGroups: taf.changeGroups.map(formatFormValues)
3913
+ }), addEmptyChangeGroup && {
3914
+ changeGroups: [emptyChangegroup]
3754
3915
  });
3755
3916
  };
3756
3917
 
@@ -3761,13 +3922,9 @@ var TafFormWrapper = function TafFormWrapper(_ref) {
3761
3922
  _ref$TAC = _ref.TAC,
3762
3923
  TAC = _ref$TAC === void 0 ? '' : _ref$TAC,
3763
3924
  onFormAction = _ref.onFormAction;
3764
- var taf = tafFromBackend.taf; // react-hook-form doesn't work well when setting defaultValues on dynamic list, that's why it's send seperate, and build up in the mount effect
3765
-
3766
- var _a = prepareTafValues(taf, tafAction),
3767
- _a$changeGroups = _a.changeGroups,
3768
- changeGroups = _a$changeGroups === void 0 ? [] : _a$changeGroups,
3769
- defaultValues = __rest(_a, ["changeGroups"]);
3770
-
3925
+ var taf = tafFromBackend.taf;
3926
+ var isDisabled = mode === 'view';
3927
+ var defaultValues = prepareTafValues(taf, tafAction, !isDisabled && !taf.changeGroups);
3771
3928
  var options = {
3772
3929
  defaultValues: defaultValues,
3773
3930
  mode: 'onTouched',
@@ -3777,8 +3934,7 @@ var TafFormWrapper = function TafFormWrapper(_ref) {
3777
3934
  return /*#__PURE__*/React__default.createElement(ReactHookFormProvider, {
3778
3935
  options: options
3779
3936
  }, /*#__PURE__*/React__default.createElement(TafForm, {
3780
- mode: mode,
3781
- changeGroups: changeGroups,
3937
+ isDisabled: isDisabled,
3782
3938
  tafAction: tafAction,
3783
3939
  staticTAC: TAC,
3784
3940
  onFormAction: onFormAction
@@ -4184,22 +4340,6 @@ var TafListButtons = function TafListButtons(_ref) {
4184
4340
  }, "Amend")));
4185
4341
  };
4186
4342
 
4187
- /* *
4188
- * Licensed under the Apache License, Version 2.0 (the "License");
4189
- * you may not use this file except in compliance with the License.
4190
- * You may obtain a copy of the License at
4191
- *
4192
- * http://www.apache.org/licenses/LICENSE-2.0
4193
- *
4194
- * Unless required by applicable law or agreed to in writing, software
4195
- * distributed under the License is distributed on an "AS IS" BASIS,
4196
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4197
- * See the License for the specific language governing permissions and
4198
- * limitations under the License.
4199
- *
4200
- * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4201
- * Copyright 2021 - Finnish Meteorological Institute (FMI)
4202
- * */
4203
4343
  var useStyles$3 = makeStyles({
4204
4344
  accordion: {
4205
4345
  marginBottom: '5px'
@@ -4238,8 +4378,9 @@ var TafListAccordion = function TafListAccordion(_ref) {
4238
4378
  api = _useApiContext.api;
4239
4379
 
4240
4380
  var _useTACGenerator = useTACGenerator(tafListItem.taf, api.getTAC),
4241
- TAC = _useTACGenerator[0],
4242
- requestTAC = _useTACGenerator[1];
4381
+ _useTACGenerator2 = _slicedToArray(_useTACGenerator, 2),
4382
+ TAC = _useTACGenerator2[0],
4383
+ requestTAC = _useTACGenerator2[1];
4243
4384
 
4244
4385
  React__default.useEffect(function () {
4245
4386
  // only re-retrieve TAC if draft state
@@ -4344,10 +4485,10 @@ var TafListSection = function TafListSection(_ref) {
4344
4485
  variant: "subtitle2",
4345
4486
  className: classes.listHeaders
4346
4487
  }, title), /*#__PURE__*/React__default.createElement("div", {
4347
- "data-testid": "tafList" + listType
4488
+ "data-testid": "tafList".concat(listType)
4348
4489
  }, tafList.map(function (tafListItem) {
4349
4490
  return /*#__PURE__*/React__default.createElement(TafListAccordion, {
4350
- key: tafListItem.taf.uuid + "-" + tafListItem.taf.status,
4491
+ key: "".concat(tafListItem.taf.uuid, "-").concat(tafListItem.taf.status),
4351
4492
  tafListItem: tafListItem,
4352
4493
  listType: listType,
4353
4494
  errorCancelTaf: errorCancelTaf,
@@ -4386,20 +4527,29 @@ var TafList = function TafList(_ref) {
4386
4527
  var expiredTafs = [];
4387
4528
 
4388
4529
  if (tafList) {
4389
- for (var _iterator = _createForOfIteratorHelperLoose(tafList), _step; !(_step = _iterator()).done;) {
4390
- var taf = _step.value;
4391
- var now = moment.utc();
4392
- var baseTime = moment.utc(taf.taf.baseTime);
4393
- var activityPeriod = locationSettings[taf.taf.location].activity_period;
4394
- var nextBaseTime = moment.utc(taf.taf.baseTime).add(activityPeriod, 'hours');
4395
-
4396
- if (taf.taf.status === 'EXPIRED') {
4397
- expiredTafs.push(taf);
4398
- } else if (baseTime < now && nextBaseTime > now) {
4399
- currentTafs.push(taf);
4400
- } else {
4401
- upcomingTafs.push(taf);
4530
+ var _iterator = _createForOfIteratorHelper(tafList),
4531
+ _step;
4532
+
4533
+ try {
4534
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
4535
+ var taf = _step.value;
4536
+ var now = moment.utc();
4537
+ var baseTime = moment.utc(taf.taf.baseTime);
4538
+ var activityPeriod = locationSettings[taf.taf.location].activity_period;
4539
+ var nextBaseTime = moment.utc(taf.taf.baseTime).add(activityPeriod, 'hours');
4540
+
4541
+ if (taf.taf.status === 'EXPIRED') {
4542
+ expiredTafs.push(taf);
4543
+ } else if (baseTime < now && nextBaseTime > now) {
4544
+ currentTafs.push(taf);
4545
+ } else {
4546
+ upcomingTafs.push(taf);
4547
+ }
4402
4548
  }
4549
+ } catch (err) {
4550
+ _iterator.e(err);
4551
+ } finally {
4552
+ _iterator.f();
4403
4553
  }
4404
4554
  }
4405
4555
 
@@ -4474,14 +4624,13 @@ var Spinner = function Spinner() {
4474
4624
  }));
4475
4625
  };
4476
4626
 
4477
- var useTimeoutCancelError = function useTimeoutCancelError(pollingInterval) {
4478
- if (pollingInterval === void 0) {
4479
- pollingInterval = 10000;
4480
- }
4627
+ var useTimeoutCancelError = function useTimeoutCancelError() {
4628
+ var pollingInterval = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10000;
4481
4629
 
4482
4630
  var _React$useState = React__default.useState([]),
4483
- errorCancelTaf = _React$useState[0],
4484
- setErrorCancelTaf = _React$useState[1];
4631
+ _React$useState2 = _slicedToArray(_React$useState, 2),
4632
+ errorCancelTaf = _React$useState2[0],
4633
+ setErrorCancelTaf = _React$useState2[1];
4485
4634
 
4486
4635
  React__default.useEffect(function () {
4487
4636
  var cancelErrorMessageHandler = errorCancelTaf.length > 0 ? setTimeout(function () {
@@ -4510,34 +4659,41 @@ var TafWrapper = function TafWrapper() {
4510
4659
 
4511
4660
  var confirmDialog = useConfirmationDialog();
4512
4661
 
4513
- var _React$useState2 = React__default.useState(false),
4514
- isTafDialogOpen = _React$useState2[0],
4515
- setTafDialogOpen = _React$useState2[1];
4662
+ var _React$useState3 = React__default.useState(false),
4663
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
4664
+ isTafDialogOpen = _React$useState4[0],
4665
+ setTafDialogOpen = _React$useState4[1];
4516
4666
 
4517
- var _React$useState3 = React__default.useState(null),
4518
- selectedTafId = _React$useState3[0],
4519
- setselectedTafId = _React$useState3[1];
4667
+ var _React$useState5 = React__default.useState(null),
4668
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
4669
+ selectedTafId = _React$useState6[0],
4670
+ setselectedTafId = _React$useState6[1];
4520
4671
 
4521
- var _React$useState4 = React__default.useState(null),
4522
- tafDialogAction = _React$useState4[0],
4523
- setTafDialogAction = _React$useState4[1];
4672
+ var _React$useState7 = React__default.useState(null),
4673
+ _React$useState8 = _slicedToArray(_React$useState7, 2),
4674
+ tafDialogAction = _React$useState8[0],
4675
+ setTafDialogAction = _React$useState8[1];
4524
4676
 
4525
- var _React$useState5 = React__default.useState(false),
4526
- errorPostMessage = _React$useState5[0],
4527
- setErrorPostMessage = _React$useState5[1];
4677
+ var _React$useState9 = React__default.useState(false),
4678
+ _React$useState10 = _slicedToArray(_React$useState9, 2),
4679
+ errorPostMessage = _React$useState10[0],
4680
+ setErrorPostMessage = _React$useState10[1];
4528
4681
 
4529
- var _React$useState6 = React__default.useState(''),
4530
- errorPostMessageText = _React$useState6[0],
4531
- setErrorPostMessageText = _React$useState6[1];
4682
+ var _React$useState11 = React__default.useState(''),
4683
+ _React$useState12 = _slicedToArray(_React$useState11, 2),
4684
+ errorPostMessageText = _React$useState12[0],
4685
+ setErrorPostMessageText = _React$useState12[1];
4532
4686
 
4533
- var _React$useState7 = React__default.useState(false),
4534
- showSpinner = _React$useState7[0],
4535
- setSpinner = _React$useState7[1]; // clear error message for cancel after 10 seconds
4687
+ var _React$useState13 = React__default.useState(false),
4688
+ _React$useState14 = _slicedToArray(_React$useState13, 2),
4689
+ showSpinner = _React$useState14[0],
4690
+ setSpinner = _React$useState14[1]; // clear error message for cancel after 10 seconds
4536
4691
 
4537
4692
 
4538
4693
  var _useTimeoutCancelErro = useTimeoutCancelError(),
4539
- errorCancelTaf = _useTimeoutCancelErro[0],
4540
- setErrorCancelTaf = _useTimeoutCancelErro[1]; // Retrieve list of tafs
4694
+ _useTimeoutCancelErro2 = _slicedToArray(_useTimeoutCancelErro, 2),
4695
+ errorCancelTaf = _useTimeoutCancelErro2[0],
4696
+ setErrorCancelTaf = _useTimeoutCancelErro2[1]; // Retrieve list of tafs
4541
4697
 
4542
4698
 
4543
4699
  var _useApi = useApi(api.getTafList),
@@ -4618,7 +4774,7 @@ var TafWrapper = function TafWrapper() {
4618
4774
  _context.t0 = _context["catch"](1);
4619
4775
 
4620
4776
  if (data.changeStatusTo === 'CANCELLED') {
4621
- setErrorCancelTaf([].concat(errorCancelTaf, [data.taf.uuid]));
4777
+ setErrorCancelTaf([].concat(_toConsumableArray(errorCancelTaf), [data.taf.uuid]));
4622
4778
  } else {
4623
4779
  setErrorPostMessage(true);
4624
4780
 
@@ -4747,8 +4903,8 @@ var ConfirmationWrapper = function ConfirmationWrapper() {
4747
4903
  * Copyright 2021 - Koninklijk Nederlands Meteorologisch Instituut (KNMI)
4748
4904
  * Copyright 2021 - Finnish Meteorological Institute (FMI)
4749
4905
  * */
4750
- var createApi = function createApi(url, appUrl, auth, setAuth, authTokenUrl) {
4751
- var axiosInstance = createApiInstance(url, appUrl, auth, setAuth, authTokenUrl);
4906
+ var createApi = function createApi(url, appUrl, auth, setAuth, authTokenUrl, authClientId) {
4907
+ var axiosInstance = createApiInstance(url, appUrl, auth, setAuth, authTokenUrl, authClientId);
4752
4908
  return {
4753
4909
  // api data
4754
4910
  getTafList: function getTafList() {