@opengeoweb/taf 1.3.0 → 2.1.3
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/lib/components/TafForm/TafForm.styles.d.ts +1 -1
- package/lib/components/TafForm/TafFormRow/clouds.d.ts +8 -5
- package/lib/components/TafForm/TafFormRow/types.d.ts +1 -0
- package/lib/components/TafForm/TafFormRow/validField.d.ts +4 -2
- package/lib/components/TafForm/TafFormRow/wind.d.ts +6 -2
- package/lib/components/TafForm/TafFormWrapper.stories.d.ts +20 -4
- package/lib/components/TafForm/utils.d.ts +1 -1
- package/lib/components/TafList/TafListSection.stories.d.ts +12 -0
- package/lib/storyshots/Storyshots.spec.d.ts +1 -0
- package/lib/utils/api.d.ts +1 -1
- package/lib/utils/mockdata/fakeTafList.d.ts +8 -0
- package/lib/utils/testUtils.d.ts +6 -0
- package/package.json +7 -7
- package/taf.esm.js +372 -186
- package/taf.umd.js +371 -185
package/taf.umd.js
CHANGED
|
@@ -228,20 +228,20 @@
|
|
|
228
228
|
* Copyright 2021 - Finnish Meteorological Institute (FMI)
|
|
229
229
|
* */
|
|
230
230
|
var FORMAT_DAYS_HOURS = 'DDHH';
|
|
231
|
-
var
|
|
231
|
+
var FORMAT_DAYS_HOURS_MINUTES = 'DDHHmm'; // formatters
|
|
232
232
|
|
|
233
233
|
var formatValidToString = function formatValidToString(valid) {
|
|
234
234
|
// Ensure end of valid period if midnight is shown as 24 and not 00
|
|
235
235
|
var endHours = moment__default["default"].utc(valid.end).format('kk');
|
|
236
236
|
var endDate = endHours === '24' ? moment__default["default"].utc(valid.end).add(-1, 'day').format('DD') : moment__default["default"].utc(valid.end).format('DD');
|
|
237
|
-
return valid.end ? moment__default["default"].utc(valid.start).format(FORMAT_DAYS_HOURS) + "/" + endDate + endHours : moment__default["default"].utc(valid.start).format(
|
|
237
|
+
return valid.end ? moment__default["default"].utc(valid.start).format(FORMAT_DAYS_HOURS) + "/" + endDate + endHours : moment__default["default"].utc(valid.start).format(FORMAT_DAYS_HOURS_MINUTES);
|
|
238
238
|
};
|
|
239
239
|
|
|
240
240
|
var getSections = function getSections(value, format) {
|
|
241
241
|
return {
|
|
242
242
|
day: parseInt(value.substring(0, 2), 10),
|
|
243
243
|
hour: parseInt(value.substring(2, 4), 10),
|
|
244
|
-
min: format ===
|
|
244
|
+
min: format === FORMAT_DAYS_HOURS_MINUTES ? parseInt(value.substring(4), 10) : 0
|
|
245
245
|
};
|
|
246
246
|
};
|
|
247
247
|
|
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
var tafStartMoment = moment__default["default"].utc(tafStart);
|
|
272
272
|
var tafEndMoment = moment__default["default"].utc(tafEnd);
|
|
273
273
|
var startEnd = trimmedValue.split('/');
|
|
274
|
-
var format = trimmedValue.indexOf('/') === -1 ?
|
|
274
|
+
var format = trimmedValue.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTES : FORMAT_DAYS_HOURS;
|
|
275
275
|
var startSections = getSections(startEnd[0], format);
|
|
276
276
|
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
|
|
277
277
|
|
|
@@ -296,7 +296,8 @@
|
|
|
296
296
|
var invalidValidityPeriodMessage = 'Invalid validity period, validity end time has to be after validity start time';
|
|
297
297
|
var invalidValidityEndTimeMessage = 'Invalid validity end time, change group validity must lie within the TAF validity period';
|
|
298
298
|
var invalidChangeValidInterFieldMessage = 'Invalid validity period, expected DDHH/DDHH for BECMG and TEMPO or DDHHmm for FM';
|
|
299
|
-
var invalidBECMGDurationValidInterFieldMessage = 'Invalid validity period, for BECMG only validity periods with a duration of 1, 2, 3 or 4 hours are allowed';
|
|
299
|
+
var invalidBECMGDurationValidInterFieldMessage = 'Invalid validity period, for BECMG only validity periods with a duration of 1, 2, 3 or 4 hours are allowed';
|
|
300
|
+
var invalidChangeGroupOverlapsWithFM = 'The valid time of a change group cannot overlap with the valid time of a following FM group. This change group should end before or at the hour of the start of the FM group'; // Validations
|
|
300
301
|
// Ensure all individual sections are correct (DD HH mm etc)
|
|
301
302
|
|
|
302
303
|
var validateValidSections = function validateValidSections(sections, isStartEnd) {
|
|
@@ -320,7 +321,7 @@
|
|
|
320
321
|
var tafStartMoment = moment__default["default"].utc(tafStart);
|
|
321
322
|
var tafEndMoment = moment__default["default"].utc(tafEnd);
|
|
322
323
|
var startEnd = value.split('/');
|
|
323
|
-
var format = value.indexOf('/') === -1 ?
|
|
324
|
+
var format = value.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTES : FORMAT_DAYS_HOURS;
|
|
324
325
|
var validateMsg = []; // Validate start time
|
|
325
326
|
|
|
326
327
|
var startSections = getSections(startEnd[0], format); // Validate individual sections for start
|
|
@@ -398,7 +399,7 @@
|
|
|
398
399
|
var tafStartMoment = moment__default["default"].utc(tafStart);
|
|
399
400
|
var tafEndMoment = moment__default["default"].utc(tafEnd);
|
|
400
401
|
var startEnd = trimmedValue.split('/');
|
|
401
|
-
var format = trimmedValue.indexOf('/') === -1 ?
|
|
402
|
+
var format = trimmedValue.indexOf('/') === -1 ? FORMAT_DAYS_HOURS_MINUTES : FORMAT_DAYS_HOURS; // Validate start time
|
|
402
403
|
|
|
403
404
|
var startSections = getSections(startEnd[0], format);
|
|
404
405
|
var startTimestamp = getValidityTimeStamp('start', startSections, tafStartMoment, tafEndMoment);
|
|
@@ -418,17 +419,17 @@
|
|
|
418
419
|
var invalidPreviousChangeGroupIsBeforeMessage = 'Valid time should be after previous valid time';
|
|
419
420
|
var invalidPreviousChangeGroupOrderMessage = "When valid times are equal, the change/probability order should be: " + validProbChangeOrder.join(', ');
|
|
420
421
|
var invalidPreviousChangeGroupHasSameValue = "When valid times are equal, probability/change can't have the same value as previous row value";
|
|
421
|
-
var validatePreviousChangeGroup = function validatePreviousChangeGroup(currentChangeGroup,
|
|
422
|
+
var validatePreviousChangeGroup = function validatePreviousChangeGroup(currentChangeGroup, previousChangeGroup, tafStart, tafEnd) {
|
|
422
423
|
// extract the needed values from changeGroups
|
|
423
424
|
var valid = currentChangeGroup.valid,
|
|
424
425
|
_a = currentChangeGroup.change,
|
|
425
426
|
change = _a === void 0 ? '' : _a,
|
|
426
427
|
_b = currentChangeGroup.probability,
|
|
427
428
|
probability = _b === void 0 ? '' : _b;
|
|
428
|
-
var previousValid =
|
|
429
|
-
_c =
|
|
429
|
+
var previousValid = previousChangeGroup.valid,
|
|
430
|
+
_c = previousChangeGroup.change,
|
|
430
431
|
previousChange = _c === void 0 ? '' : _c,
|
|
431
|
-
_d =
|
|
432
|
+
_d = previousChangeGroup.probability,
|
|
432
433
|
previousProbability = _d === void 0 ? '' : _d; // get the parsed values
|
|
433
434
|
|
|
434
435
|
var validValue = parseValidToObject(valid, tafStart, tafEnd);
|
|
@@ -462,6 +463,27 @@
|
|
|
462
463
|
}
|
|
463
464
|
}
|
|
464
465
|
|
|
466
|
+
return true;
|
|
467
|
+
}; // validate overlapping validity when one of the following changegroups is FM
|
|
468
|
+
|
|
469
|
+
var validateOverlapWithFM = function validateOverlapWithFM(currentChangeGroup, nextChangeGroups, tafStart, tafEnd) {
|
|
470
|
+
var valid = currentChangeGroup.valid;
|
|
471
|
+
if (!valid || !nextChangeGroups.length) return true;
|
|
472
|
+
var validValue = parseValidToObject(valid, tafStart, tafEnd);
|
|
473
|
+
var currentRowEndTime = moment__default["default"](validValue.end);
|
|
474
|
+
var firstFMChangeGroup = nextChangeGroups.find(function (nextChangeGroup) {
|
|
475
|
+
return nextChangeGroup.change.trim() === 'FM';
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
if (firstFMChangeGroup && firstFMChangeGroup.valid) {
|
|
479
|
+
var FMValidValue = parseValidToObject(firstFMChangeGroup.valid, tafStart, tafEnd);
|
|
480
|
+
var FMStartTime = moment__default["default"](FMValidValue.start);
|
|
481
|
+
|
|
482
|
+
if (currentRowEndTime.isAfter(FMStartTime)) {
|
|
483
|
+
return invalidChangeGroupOverlapsWithFM;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
465
487
|
return true;
|
|
466
488
|
};
|
|
467
489
|
|
|
@@ -1395,8 +1417,12 @@
|
|
|
1395
1417
|
var invalidWindDirectionStepMessage = 'Invalid wind direction, the direction must be rounded to the nearest step of 10 degrees';
|
|
1396
1418
|
var invalidWindSpeedMessage = 'Invalid wind speed, expected a speed equal to 2 digits or P99';
|
|
1397
1419
|
var invalidWindGustsMessage = 'Invalid wind gusts, expected gusts equal to 2 digits or P99';
|
|
1398
|
-
var invalidWindGustSpeedCombinationMessage = 'Invalid wind,
|
|
1399
|
-
var
|
|
1420
|
+
var invalidWindGustSpeedCombinationMessage = 'Invalid wind gusts, gusts must at least be 10 knots greater than the wind speed';
|
|
1421
|
+
var invalidWindGustSpeedBelow15Message = 'Invalid wind gusts, gusts are only allowed for a minimum wind speed of 15 knots';
|
|
1422
|
+
var invalidGustForWindP99Message = 'Invalid wind speed and gust combination, if wind is P99, gusts can only be empty or P99';
|
|
1423
|
+
var invalidWindSpeedForDirectionZeroMessage = 'Invalid wind speed, if direction is 000, speed can only be 00';
|
|
1424
|
+
var invalidWindSpeedForDirectionNonZeroMessage = 'Invalid wind speed, if direction is not 000, speed can not be 00';
|
|
1425
|
+
var invalidWindVRBWindDirectionMessage = 'Invalid wind direction, VRB can only be used in combination with windspeeds smaller than 4 or in combination with gusts and showers'; // validations
|
|
1400
1426
|
|
|
1401
1427
|
var validateDirection = function validateDirection(value) {
|
|
1402
1428
|
// if not a number
|
|
@@ -1444,8 +1470,29 @@
|
|
|
1444
1470
|
return value === 'KT' || value === '' || invalidWindMessage;
|
|
1445
1471
|
};
|
|
1446
1472
|
|
|
1447
|
-
var validateWindInterSection = function validateWindInterSection(speed, gust) {
|
|
1448
|
-
if (
|
|
1473
|
+
var validateWindInterSection = function validateWindInterSection(speed, gust, direction, weather1Value, weather2Value, weather3Value) {
|
|
1474
|
+
if (direction === '000' && speed !== '00') {
|
|
1475
|
+
return invalidWindSpeedForDirectionZeroMessage;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
if (direction !== '000' && speed === '00') {
|
|
1479
|
+
return invalidWindSpeedForDirectionNonZeroMessage;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
if (direction === 'VRB' && (speed === 'P99' || parseInt(speed, 10) > 3)) {
|
|
1483
|
+
// Only allow VRB for speeds smaller than 4 or in combination with gusts and showers (SH, TS, SQ)
|
|
1484
|
+
var allowedWeatherPhenom = ['SH', 'TS', 'SQ'];
|
|
1485
|
+
if (gust === '' || !allowedWeatherPhenom.some(function (allowedPhenom) {
|
|
1486
|
+
return weather1Value.includes(allowedPhenom);
|
|
1487
|
+
}) && !allowedWeatherPhenom.some(function (allowedPhenom) {
|
|
1488
|
+
return weather2Value.includes(allowedPhenom);
|
|
1489
|
+
}) && !allowedWeatherPhenom.some(function (allowedPhenom) {
|
|
1490
|
+
return weather3Value.includes(allowedPhenom);
|
|
1491
|
+
})) return invalidWindVRBWindDirectionMessage;
|
|
1492
|
+
} // Validate gust
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
if (gust === '') {
|
|
1449
1496
|
return true;
|
|
1450
1497
|
}
|
|
1451
1498
|
|
|
@@ -1453,24 +1500,35 @@
|
|
|
1453
1500
|
return invalidGustForWindP99Message;
|
|
1454
1501
|
}
|
|
1455
1502
|
|
|
1456
|
-
|
|
1503
|
+
if (parseInt(speed, 10) < 15) {
|
|
1504
|
+
return invalidWindGustSpeedBelow15Message;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
if (gust !== 'P99' && parseInt(gust, 10) - parseInt(speed, 10) < 10) {
|
|
1508
|
+
return invalidWindGustSpeedCombinationMessage;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
return true;
|
|
1457
1512
|
}; // Main validation function
|
|
1458
1513
|
|
|
1459
1514
|
|
|
1460
|
-
var validateWindField = function validateWindField(value) {
|
|
1461
|
-
var
|
|
1515
|
+
var validateWindField = function validateWindField(value, weatherfield1, weatherfield2, weatherfield3) {
|
|
1516
|
+
var trimmedWindValue = value.trim();
|
|
1517
|
+
var trimmedWeather1Value = weatherfield1.trim();
|
|
1518
|
+
var trimmedWeather2Value = weatherfield2.trim();
|
|
1519
|
+
var trimmedWeather3Value = weatherfield3.trim();
|
|
1462
1520
|
|
|
1463
|
-
if (!
|
|
1521
|
+
if (!trimmedWindValue.length) {
|
|
1464
1522
|
return true;
|
|
1465
1523
|
} // Validate length and ensure it doesn't contain any other characters than numbers and VRB P KT and G
|
|
1466
1524
|
|
|
1467
1525
|
|
|
1468
|
-
if (
|
|
1526
|
+
if (trimmedWindValue.length < 5 || trimmedWindValue.length > 12 || !trimmedWindValue.match(/^[0-9VRBPGKT]+$/)) {
|
|
1469
1527
|
return invalidWindMessage;
|
|
1470
1528
|
} // First validate individual sections
|
|
1471
1529
|
|
|
1472
1530
|
|
|
1473
|
-
var windValidationIndv = extractValidateWindSections(
|
|
1531
|
+
var windValidationIndv = extractValidateWindSections(trimmedWindValue, true);
|
|
1474
1532
|
|
|
1475
1533
|
if (windValidationIndv.validations.length !== 0) {
|
|
1476
1534
|
return windValidationIndv.validations.find(function (error) {
|
|
@@ -1479,7 +1537,7 @@
|
|
|
1479
1537
|
} // Then do any intersection validation
|
|
1480
1538
|
|
|
1481
1539
|
|
|
1482
|
-
return validateWindInterSection(windValidationIndv.speed, windValidationIndv.gust);
|
|
1540
|
+
return validateWindInterSection(windValidationIndv.speed, windValidationIndv.gust, windValidationIndv.direction, trimmedWeather1Value, trimmedWeather2Value, trimmedWeather3Value);
|
|
1483
1541
|
};
|
|
1484
1542
|
|
|
1485
1543
|
var formatSingleCloud = function formatSingleCloud(value) {
|
|
@@ -1528,10 +1586,10 @@
|
|
|
1528
1586
|
var parseSingleCloud = function parseSingleCloud(value) {
|
|
1529
1587
|
if (!value) return null;
|
|
1530
1588
|
var trimmedCloud = value.trim();
|
|
1531
|
-
var cloudType = trimmedCloud.
|
|
1589
|
+
var cloudType = trimmedCloud.substring(6, 9);
|
|
1532
1590
|
return __assign({
|
|
1533
|
-
coverage: trimmedCloud.
|
|
1534
|
-
height: parseInt(trimmedCloud.
|
|
1591
|
+
coverage: trimmedCloud.substring(0, 3),
|
|
1592
|
+
height: parseInt(trimmedCloud.substring(3, 6), 10)
|
|
1535
1593
|
}, cloudType && {
|
|
1536
1594
|
type: cloudType
|
|
1537
1595
|
});
|
|
@@ -1549,20 +1607,22 @@
|
|
|
1549
1607
|
switch (key) {
|
|
1550
1608
|
case 'cloud1':
|
|
1551
1609
|
{
|
|
1552
|
-
|
|
1610
|
+
var trimmedValue = clouds[key].trim();
|
|
1611
|
+
|
|
1612
|
+
if (isVerticalVisibility(trimmedValue)) {
|
|
1553
1613
|
// Parse Vertical Visibility
|
|
1554
1614
|
return __assign(__assign({}, list), (_a = {}, _a[key] = {
|
|
1555
|
-
verticalVisibility: parseInt(
|
|
1615
|
+
verticalVisibility: parseInt(trimmedValue.substring(2, 5), 10)
|
|
1556
1616
|
}, _a));
|
|
1557
1617
|
}
|
|
1558
1618
|
|
|
1559
|
-
if (
|
|
1619
|
+
if (trimmedValue === 'NSC') {
|
|
1560
1620
|
// Parse No Significant Clouds
|
|
1561
|
-
return __assign(__assign({}, list), (_b = {}, _b[key] =
|
|
1621
|
+
return __assign(__assign({}, list), (_b = {}, _b[key] = trimmedValue, _b));
|
|
1562
1622
|
} // Parse Cloud
|
|
1563
1623
|
|
|
1564
1624
|
|
|
1565
|
-
return __assign(__assign({}, list), (_c = {}, _c[key] = parseSingleCloud(
|
|
1625
|
+
return __assign(__assign({}, list), (_c = {}, _c[key] = parseSingleCloud(trimmedValue), _c));
|
|
1566
1626
|
}
|
|
1567
1627
|
|
|
1568
1628
|
default:
|
|
@@ -1590,16 +1650,19 @@
|
|
|
1590
1650
|
var invalidCloudHeightStepsMessage = 'Invalid cloud height, a height above 050 must be rounded to the nearest 1000ft';
|
|
1591
1651
|
var invalidCLoudTypeMessage = 'Invalid cloud type, expected CB or TCU';
|
|
1592
1652
|
var invalidHeightTypeCombinationMessage = 'Invalid cloud input, when cloud height is 050 or higher, CB or TCU is required';
|
|
1593
|
-
var invalidVerticalVisibilityMessage = 'Invalid vertical visibility, expected VV<value> with value consisting of 3 digits
|
|
1653
|
+
var invalidVerticalVisibilityMessage = 'Invalid vertical visibility, expected VV<value> with value consisting of 3 digits';
|
|
1654
|
+
var invalidVerticalVisibilityHeightMessage = 'Invalid vertical visibility, visibility should lie between 001 and 010';
|
|
1655
|
+
var invalidVerticalVisibilityHeightFGMessage = 'Invalid vertical visibility, in case of fog visibility should lie between 001 and 005';
|
|
1594
1656
|
var invalidCloudHeightComparedToPreviousMessage = 'Invalid cloud height, height must be greater than previous cloud group height';
|
|
1595
|
-
var invalidCloud2CoverageTypeCombinationMessage = 'Invalid cloud input, cloud
|
|
1657
|
+
var invalidCloud2CoverageTypeCombinationMessage = 'Invalid cloud input, for the second cloud group (excluding any significant convective cloud groups with CB/TCU) a coverage of FEW is not allowed';
|
|
1596
1658
|
var invalidCloud2WithVerticalVisibilityMessage = 'Invalid cloud input, cloud type is required when Vertical Visibility is given';
|
|
1597
|
-
var invalidCloud3CoverageTypeCombinationMessage = 'Invalid cloud input, cloud
|
|
1659
|
+
var invalidCloud3CoverageTypeCombinationMessage = 'Invalid cloud input, for the third cloud group (excluding any significant convective cloud groups with CB/TCU) a coverage of FEW or SCT is not allowed';
|
|
1598
1660
|
var invalidCloudWithVerticalVisibilityMessage = 'Invalid cloud input, third or fourth cloud group is not allowed when Vertical Visibility is given';
|
|
1599
1661
|
var invalidCloudWithPreviousEmptyCloud = 'Invalid cloud input, value is not allowed when previous cloud group is empty';
|
|
1600
1662
|
var invalidCloudWithNSCMessage = 'Invalid cloud input, other cloud groups are not allowed when No Significant Clouds is given';
|
|
1601
|
-
var
|
|
1602
|
-
var invalidCloudCAVOKMessage = 'Invalid cloud input, when CAVOK is used, cloud groups must be empty';
|
|
1663
|
+
var invalidCloudWithPreviousType = 'Invalid cloud input, only one significant convective cloud group with CB/TCU is allowed';
|
|
1664
|
+
var invalidCloudCAVOKMessage = 'Invalid cloud input, when CAVOK is used, cloud groups must be empty';
|
|
1665
|
+
var invalidCloud4TypeMissingMessage = 'Invalid cloud input for fourth group, CB or TCU required if no other significant convective cloud group present'; // validations
|
|
1603
1666
|
|
|
1604
1667
|
var isLengthValid = function isLengthValid(value) {
|
|
1605
1668
|
var onlyDigitsOrSpecificLetters = RegExp(/^[0-9FEWSCTBKNOVU]+$/);
|
|
@@ -1646,25 +1709,32 @@
|
|
|
1646
1709
|
};
|
|
1647
1710
|
|
|
1648
1711
|
var isVerticalVisibility = function isVerticalVisibility(value) {
|
|
1649
|
-
return value.
|
|
1712
|
+
return value.substring(0, 2) === 'VV';
|
|
1650
1713
|
};
|
|
1651
1714
|
|
|
1652
|
-
var isVerticalVisibilityValid = function isVerticalVisibilityValid(value) {
|
|
1715
|
+
var isVerticalVisibilityValid = function isVerticalVisibilityValid(value, weather1, weather2, weather3) {
|
|
1653
1716
|
// validate if its a number
|
|
1654
1717
|
if (!value.match(/^[0-9]+$/)) {
|
|
1655
|
-
return
|
|
1718
|
+
return invalidVerticalVisibilityMessage;
|
|
1656
1719
|
} // check if its 3 digits
|
|
1657
1720
|
|
|
1658
1721
|
|
|
1659
1722
|
if (value.length !== 3) {
|
|
1660
|
-
return
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1723
|
+
return invalidVerticalVisibilityMessage;
|
|
1724
|
+
}
|
|
1663
1725
|
|
|
1664
1726
|
var intValue = parseInt(value, 10);
|
|
1665
1727
|
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1728
|
+
if (weather1 !== 'FG' && weather2 !== 'FG' && weather3 !== 'FG') {
|
|
1729
|
+
// value should not be above 10
|
|
1730
|
+
if (intValue < 1 || intValue > 10) {
|
|
1731
|
+
return invalidVerticalVisibilityHeightMessage;
|
|
1732
|
+
}
|
|
1733
|
+
} else if (intValue < 1 || intValue > 5) {
|
|
1734
|
+
// Apply Dutch rule as national exception
|
|
1735
|
+
// In case of fog (FG) the vertical visibility can only be between VV001 up to and including VV005
|
|
1736
|
+
// HEIGHT_VV is: (001-(1)-005). Deze maxima zijn officiële Nederlandse afwijkingen van de WMO/ICAO regelgeving
|
|
1737
|
+
return invalidVerticalVisibilityHeightFGMessage;
|
|
1668
1738
|
}
|
|
1669
1739
|
|
|
1670
1740
|
return true;
|
|
@@ -1681,14 +1751,14 @@
|
|
|
1681
1751
|
} // Validate coverage
|
|
1682
1752
|
|
|
1683
1753
|
|
|
1684
|
-
var coverage = value.
|
|
1754
|
+
var coverage = value.substring(0, 3);
|
|
1685
1755
|
|
|
1686
1756
|
if (!isCoverageValid(coverage)) {
|
|
1687
1757
|
errorMessages.push(invalidCloudCoverageMessage);
|
|
1688
1758
|
} // Validate height
|
|
1689
1759
|
|
|
1690
1760
|
|
|
1691
|
-
var height = value.
|
|
1761
|
+
var height = value.substring(3, 6);
|
|
1692
1762
|
var isValidHeight = isHeightValid(height);
|
|
1693
1763
|
|
|
1694
1764
|
if (isValidHeight !== true) {
|
|
@@ -1697,7 +1767,7 @@
|
|
|
1697
1767
|
} // Validate type
|
|
1698
1768
|
|
|
1699
1769
|
|
|
1700
|
-
var type = value.
|
|
1770
|
+
var type = value.substring(6, 9);
|
|
1701
1771
|
|
|
1702
1772
|
if (!isTypeValid(type)) {
|
|
1703
1773
|
errorMessages.push(invalidCLoudTypeMessage);
|
|
@@ -1716,56 +1786,66 @@
|
|
|
1716
1786
|
};
|
|
1717
1787
|
};
|
|
1718
1788
|
|
|
1719
|
-
var validateFirstCloud = function validateFirstCloud(value, visibilityValue) {
|
|
1720
|
-
var
|
|
1789
|
+
var validateFirstCloud = function validateFirstCloud(value, visibilityValue, weatherfield1, weatherfield2, weatherfield3) {
|
|
1790
|
+
var trimmedValueFirstCloud = value.trim();
|
|
1791
|
+
var trimmedValueVisibility = visibilityValue.trim();
|
|
1792
|
+
var trimmedWeather1Value = weatherfield1.trim();
|
|
1793
|
+
var trimmedWeather2Value = weatherfield2.trim();
|
|
1794
|
+
var trimmedWeather3Value = weatherfield3.trim(); // Field can be left empty
|
|
1721
1795
|
|
|
1722
|
-
if (!
|
|
1796
|
+
if (!trimmedValueFirstCloud.length) {
|
|
1723
1797
|
return true;
|
|
1724
1798
|
}
|
|
1725
1799
|
|
|
1726
|
-
if (
|
|
1800
|
+
if (trimmedValueFirstCloud && trimmedValueVisibility === 'CAVOK') {
|
|
1727
1801
|
return invalidCloudCAVOKMessage;
|
|
1728
1802
|
} // Check for No Signicant Clouds
|
|
1729
1803
|
|
|
1730
1804
|
|
|
1731
|
-
if (
|
|
1805
|
+
if (trimmedValueFirstCloud === 'NSC') {
|
|
1732
1806
|
return true;
|
|
1733
1807
|
} // Validate Vertical Visibility
|
|
1734
1808
|
|
|
1735
1809
|
|
|
1736
|
-
if (isVerticalVisibility(
|
|
1810
|
+
if (isVerticalVisibility(trimmedValueFirstCloud)) {
|
|
1737
1811
|
if ( // Validate length of 5
|
|
1738
|
-
|
|
1739
|
-
!
|
|
1812
|
+
trimmedValueFirstCloud.length !== 5 || // Ensure it only contains digits or VV
|
|
1813
|
+
!trimmedValueFirstCloud.match(/^[0-9V]+$/)) {
|
|
1740
1814
|
return invalidVerticalVisibilityMessage;
|
|
1741
1815
|
}
|
|
1742
1816
|
|
|
1743
|
-
var verticalVisibilityValue =
|
|
1744
|
-
|
|
1745
|
-
if (!isVerticalVisibilityValid(verticalVisibilityValue)) {
|
|
1746
|
-
return invalidVerticalVisibilityMessage;
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
|
-
return true;
|
|
1817
|
+
var verticalVisibilityValue = trimmedValueFirstCloud.substring(2, 5);
|
|
1818
|
+
return isVerticalVisibilityValid(verticalVisibilityValue, trimmedWeather1Value, trimmedWeather2Value, trimmedWeather3Value);
|
|
1750
1819
|
}
|
|
1751
1820
|
|
|
1752
1821
|
var errorMessages = sharedCloudValidations({
|
|
1753
|
-
value:
|
|
1822
|
+
value: trimmedValueFirstCloud,
|
|
1754
1823
|
canBeNSC: true
|
|
1755
1824
|
}).errorMessages; // Return first error if any
|
|
1756
1825
|
|
|
1757
1826
|
return errorMessages.length ? errorMessages[0] : true;
|
|
1758
1827
|
};
|
|
1759
1828
|
var validateSecondCloud = function validateSecondCloud(firstCloudValue, secondCloudValue, visibilityValue) {
|
|
1760
|
-
var
|
|
1829
|
+
var trimmedValueFirstCloud = firstCloudValue.trim();
|
|
1830
|
+
var trimmedValueSecondCloud = secondCloudValue.trim(); // Field can be left empty
|
|
1761
1831
|
|
|
1762
|
-
if (!
|
|
1832
|
+
if (!trimmedValueSecondCloud.length) {
|
|
1763
1833
|
return true;
|
|
1834
|
+
} // If Cloud1 is NSC, Cloud2 has to be empty
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
if (trimmedValueFirstCloud === 'NSC' && trimmedValueSecondCloud !== '') {
|
|
1838
|
+
return invalidCloudWithNSCMessage;
|
|
1839
|
+
} // If Cloud1 is empty Cloud2 should be empty
|
|
1840
|
+
|
|
1841
|
+
|
|
1842
|
+
if (trimmedValueFirstCloud === '') {
|
|
1843
|
+
return invalidCloudWithPreviousEmptyCloud;
|
|
1764
1844
|
} // Generic validations
|
|
1765
1845
|
|
|
1766
1846
|
|
|
1767
1847
|
var _a = sharedCloudValidations({
|
|
1768
|
-
value:
|
|
1848
|
+
value: trimmedValueSecondCloud
|
|
1769
1849
|
}),
|
|
1770
1850
|
coverage = _a.coverage,
|
|
1771
1851
|
height = _a.height,
|
|
@@ -1775,32 +1855,32 @@
|
|
|
1775
1855
|
|
|
1776
1856
|
if (errorMessages.length) {
|
|
1777
1857
|
return errorMessages[0];
|
|
1778
|
-
} // Cloud2 specific validations
|
|
1779
|
-
// Without type, coverage can not be FEW
|
|
1858
|
+
} // Cloud2 specific validations - only to be applied when cloud1 does not contain type CB/TCU
|
|
1780
1859
|
|
|
1781
1860
|
|
|
1782
|
-
|
|
1783
|
-
|
|
1861
|
+
var typeCloud1 = trimmedValueFirstCloud.substring(6, 9);
|
|
1862
|
+
|
|
1863
|
+
if (typeCloud1 !== 'CB' && typeCloud1 !== 'TCU') {
|
|
1864
|
+
// Without a type specified in cloud group 1, this group counts as #2 and coverage can not be FEW
|
|
1865
|
+
if (type === '' && coverage === 'FEW') {
|
|
1866
|
+
return invalidCloud2CoverageTypeCombinationMessage;
|
|
1867
|
+
}
|
|
1784
1868
|
} // If Cloud1 is not valid, skip further validation of Cloud2
|
|
1869
|
+
// No need to pass the weatherfields as their content does not influence what happens below
|
|
1785
1870
|
|
|
1786
1871
|
|
|
1787
|
-
if (validateFirstCloud(
|
|
1872
|
+
if (validateFirstCloud(trimmedValueFirstCloud, visibilityValue, '', '', '') !== true) {
|
|
1788
1873
|
return true;
|
|
1789
|
-
} // If Cloud1
|
|
1790
|
-
|
|
1874
|
+
} // If Cloud1 contains a type, Cloud2 cannot contain a type
|
|
1791
1875
|
|
|
1792
|
-
if (firstCloudValue === 'NSC' && trimmedValue !== '') {
|
|
1793
|
-
return invalidCloudWithNSCMessage;
|
|
1794
|
-
} // If Cloud1 is empty Cloud2 should be empty
|
|
1795
1876
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
return invalidCloudWithPreviousEmptyCloud;
|
|
1877
|
+
if (type !== '' && typeCloud1 !== '') {
|
|
1878
|
+
return invalidCloudWithPreviousType;
|
|
1799
1879
|
} // Cloud2 height has to be greater than Cloud1 height
|
|
1800
1880
|
|
|
1801
1881
|
|
|
1802
|
-
if (!isVerticalVisibility(
|
|
1803
|
-
var cloud1Height =
|
|
1882
|
+
if (!isVerticalVisibility(trimmedValueFirstCloud)) {
|
|
1883
|
+
var cloud1Height = trimmedValueFirstCloud.substring(3, 6);
|
|
1804
1884
|
|
|
1805
1885
|
if (height <= cloud1Height) {
|
|
1806
1886
|
return invalidCloudHeightComparedToPreviousMessage;
|
|
@@ -1808,22 +1888,34 @@
|
|
|
1808
1888
|
} // If Cloud1 contains Vertical Visibility then Cloud2 type is required
|
|
1809
1889
|
|
|
1810
1890
|
|
|
1811
|
-
if (isVerticalVisibility(
|
|
1891
|
+
if (isVerticalVisibility(trimmedValueFirstCloud) && type === '') {
|
|
1812
1892
|
return invalidCloud2WithVerticalVisibilityMessage;
|
|
1813
1893
|
}
|
|
1814
1894
|
|
|
1815
1895
|
return true;
|
|
1816
1896
|
};
|
|
1817
1897
|
var validateThirdCloud = function validateThirdCloud(firstCloudValue, secondCloudValue, thirdCloudValue, visibilityValue) {
|
|
1818
|
-
var
|
|
1898
|
+
var trimmedValueFirstCloud = firstCloudValue.trim();
|
|
1899
|
+
var trimmedValueSecondCloud = secondCloudValue.trim();
|
|
1900
|
+
var trimmedValueThirdCloud = thirdCloudValue.trim(); // Field can be left empty
|
|
1819
1901
|
|
|
1820
|
-
if (!
|
|
1902
|
+
if (!trimmedValueThirdCloud.length) {
|
|
1821
1903
|
return true;
|
|
1904
|
+
} // If Cloud1 is NSC, Cloud3 has to be empty
|
|
1905
|
+
|
|
1906
|
+
|
|
1907
|
+
if (trimmedValueFirstCloud === 'NSC' && trimmedValueThirdCloud !== '') {
|
|
1908
|
+
return invalidCloudWithNSCMessage;
|
|
1909
|
+
} // If Cloud1 or Cloud2 is empty Cloud3 should be empty
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
if (trimmedValueFirstCloud === '' || trimmedValueSecondCloud === '') {
|
|
1913
|
+
return invalidCloudWithPreviousEmptyCloud;
|
|
1822
1914
|
} // Generic validations
|
|
1823
1915
|
|
|
1824
1916
|
|
|
1825
1917
|
var _a = sharedCloudValidations({
|
|
1826
|
-
value:
|
|
1918
|
+
value: trimmedValueThirdCloud
|
|
1827
1919
|
}),
|
|
1828
1920
|
coverage = _a.coverage,
|
|
1829
1921
|
height = _a.height,
|
|
@@ -1834,45 +1926,45 @@
|
|
|
1834
1926
|
if (errorMessages.length) {
|
|
1835
1927
|
return errorMessages[0];
|
|
1836
1928
|
} // Cloud3 specific validations
|
|
1837
|
-
// Without type, coverage can not be FEW or SCT
|
|
1929
|
+
// Without a type specified in cloud group 1 or 2, this group counts as #3 and coverage can not be FEW or SCT
|
|
1838
1930
|
|
|
1839
1931
|
|
|
1840
|
-
|
|
1841
|
-
|
|
1932
|
+
var typeCloud1 = trimmedValueFirstCloud.substring(6, 9);
|
|
1933
|
+
var typeCloud2 = trimmedValueSecondCloud.substring(6, 9);
|
|
1934
|
+
|
|
1935
|
+
if (typeCloud1 !== 'CB' && typeCloud1 !== 'TCU' && typeCloud2 !== 'CB' && typeCloud2 !== 'TCU') {
|
|
1936
|
+
if (type === '' && (coverage === 'FEW' || coverage === 'SCT')) {
|
|
1937
|
+
return invalidCloud3CoverageTypeCombinationMessage;
|
|
1938
|
+
}
|
|
1939
|
+
} else if (type === '' && coverage === 'FEW') {
|
|
1940
|
+
// In case we do have a CB/TCU group in one of the previous clouf groups. This cloudgroup should be evaluated as if it was the second group
|
|
1941
|
+
return invalidCloud2CoverageTypeCombinationMessage;
|
|
1842
1942
|
} // If Cloud1 is not valid, skip further validation of Cloud3
|
|
1943
|
+
// No need to pass the weatherfields as their content does not influence what happens below
|
|
1944
|
+
// Since in case of VV the third field should be empty anyways
|
|
1843
1945
|
|
|
1844
1946
|
|
|
1845
|
-
if (validateFirstCloud(
|
|
1947
|
+
if (validateFirstCloud(trimmedValueFirstCloud, visibilityValue, '', '', '') !== true) {
|
|
1846
1948
|
return true;
|
|
1847
|
-
} // If Cloud1 is empty Cloud3 should be empty
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
if (firstCloudValue === '') {
|
|
1851
|
-
return invalidCloudWithPreviousEmptyCloud;
|
|
1852
1949
|
} // If Cloud1 contains Vertical Visibility then Cloud3 should be empty
|
|
1853
1950
|
|
|
1854
1951
|
|
|
1855
|
-
if (isVerticalVisibility(
|
|
1952
|
+
if (isVerticalVisibility(trimmedValueFirstCloud)) {
|
|
1856
1953
|
return invalidCloudWithVerticalVisibilityMessage;
|
|
1857
|
-
} // If Cloud1 is NSC, Cloud3 has to be empty
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
if (firstCloudValue === 'NSC' && trimmedValue !== '') {
|
|
1861
|
-
return invalidCloudWithNSCMessage;
|
|
1862
1954
|
} // If Cloud2 is not valid, skip further validation of Cloud3
|
|
1863
1955
|
|
|
1864
1956
|
|
|
1865
|
-
if (validateSecondCloud(
|
|
1957
|
+
if (validateSecondCloud(trimmedValueFirstCloud, trimmedValueSecondCloud, visibilityValue) !== true) {
|
|
1866
1958
|
return true;
|
|
1867
|
-
} // If
|
|
1959
|
+
} // If one of the previous groups contains a type, Cloud3 cannot contain a type
|
|
1868
1960
|
|
|
1869
1961
|
|
|
1870
|
-
if (
|
|
1871
|
-
return
|
|
1962
|
+
if (type !== '' && (typeCloud1 !== '' || typeCloud2 !== '')) {
|
|
1963
|
+
return invalidCloudWithPreviousType;
|
|
1872
1964
|
} // Cloud3 height has to be greater than Cloud2 height
|
|
1873
1965
|
|
|
1874
1966
|
|
|
1875
|
-
var cloud2Height =
|
|
1967
|
+
var cloud2Height = trimmedValueSecondCloud.substring(3, 6);
|
|
1876
1968
|
|
|
1877
1969
|
if (height <= cloud2Height) {
|
|
1878
1970
|
return invalidCloudHeightComparedToPreviousMessage;
|
|
@@ -1881,17 +1973,31 @@
|
|
|
1881
1973
|
return true;
|
|
1882
1974
|
};
|
|
1883
1975
|
var validateFourthCloud = function validateFourthCloud(firstCloudValue, secondCloudValue, thirdCloudValue, fourthCloudValue, visibilityValue) {
|
|
1884
|
-
var
|
|
1976
|
+
var trimmedValueFirstCloud = firstCloudValue.trim();
|
|
1977
|
+
var trimmedValueSecondCloud = secondCloudValue.trim();
|
|
1978
|
+
var trimmedValueThirdCloud = thirdCloudValue.trim();
|
|
1979
|
+
var trimmedValueFourthCloud = fourthCloudValue.trim(); // Field can be left empty
|
|
1885
1980
|
|
|
1886
|
-
if (!
|
|
1981
|
+
if (!trimmedValueFourthCloud.length) {
|
|
1887
1982
|
return true;
|
|
1983
|
+
} // If Cloud1 is NSC, Cloud4 has to be empty
|
|
1984
|
+
|
|
1985
|
+
|
|
1986
|
+
if (trimmedValueFirstCloud === 'NSC' && trimmedValueFourthCloud !== '') {
|
|
1987
|
+
return invalidCloudWithNSCMessage;
|
|
1988
|
+
} // If Cloud 1, 2 or 3 is empty Cloud4 should be empty
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
if (trimmedValueFirstCloud === '' || trimmedValueSecondCloud === '' || trimmedValueThirdCloud === '') {
|
|
1992
|
+
return invalidCloudWithPreviousEmptyCloud;
|
|
1888
1993
|
} // Generic validations
|
|
1889
1994
|
|
|
1890
1995
|
|
|
1891
1996
|
var _a = sharedCloudValidations({
|
|
1892
|
-
value:
|
|
1997
|
+
value: trimmedValueFourthCloud
|
|
1893
1998
|
}),
|
|
1894
1999
|
height = _a.height,
|
|
2000
|
+
coverage = _a.coverage,
|
|
1895
2001
|
type = _a.type,
|
|
1896
2002
|
errorMessages = _a.errorMessages; // Return generic errors if any
|
|
1897
2003
|
|
|
@@ -1899,50 +2005,48 @@
|
|
|
1899
2005
|
if (errorMessages.length) {
|
|
1900
2006
|
return errorMessages[0];
|
|
1901
2007
|
} // Cloud4 specific validations
|
|
1902
|
-
//
|
|
2008
|
+
// If none of the previous cloud groups contains a type, the fourth group must contain a type if not empty
|
|
2009
|
+
|
|
1903
2010
|
|
|
2011
|
+
var typeCloud1 = trimmedValueFirstCloud.substring(6, 9);
|
|
2012
|
+
var typeCloud2 = trimmedValueSecondCloud.substring(6, 9);
|
|
2013
|
+
var typeCloud3 = trimmedValueThirdCloud.substring(6, 9);
|
|
1904
2014
|
|
|
1905
|
-
if (
|
|
1906
|
-
|
|
2015
|
+
if (typeCloud1 !== 'CB' && typeCloud1 !== 'TCU' && typeCloud2 !== 'CB' && typeCloud2 !== 'TCU' && typeCloud3 !== 'CB' && typeCloud3 !== 'TCU') {
|
|
2016
|
+
if (type === '') {
|
|
2017
|
+
return invalidCloud4TypeMissingMessage;
|
|
2018
|
+
}
|
|
2019
|
+
} else if (coverage === 'FEW' || coverage === 'SCT') {
|
|
2020
|
+
// We have a CB/TCU group in one of the previous cloud groups. This group should be evaluated as if it was the third group
|
|
2021
|
+
return invalidCloud3CoverageTypeCombinationMessage;
|
|
1907
2022
|
} // If Cloud1 is not valid, skip further validation of Cloud4
|
|
2023
|
+
// No need to pass the weatherfields as their content does not influence what happens below
|
|
2024
|
+
// Since in case of VV the fourth field should be empty anyways
|
|
1908
2025
|
|
|
1909
2026
|
|
|
1910
|
-
if (validateFirstCloud(
|
|
2027
|
+
if (validateFirstCloud(trimmedValueFirstCloud, visibilityValue, '', '', '') !== true) {
|
|
1911
2028
|
return true;
|
|
1912
2029
|
} // If Cloud1 contains Vertical Visibility then Cloud4 should be empty
|
|
1913
2030
|
|
|
1914
2031
|
|
|
1915
|
-
if (isVerticalVisibility(
|
|
2032
|
+
if (isVerticalVisibility(trimmedValueFirstCloud)) {
|
|
1916
2033
|
return invalidCloudWithVerticalVisibilityMessage;
|
|
1917
|
-
} // If Cloud1 is NSC, Cloud4 has to be empty
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
if (firstCloudValue === 'NSC' && trimmedValue !== '') {
|
|
1921
|
-
return invalidCloudWithNSCMessage;
|
|
1922
|
-
} // If Cloud 1, 2 or 3 is empty Cloud4 should be empty
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (firstCloudValue === '' || secondCloudValue === '' || thirdCloudValue === '') {
|
|
1926
|
-
return invalidCloudWithPreviousEmptyCloud;
|
|
1927
2034
|
} // If Cloud3 is not valid, skip further validation of Cloud4
|
|
1928
2035
|
|
|
1929
2036
|
|
|
1930
|
-
if (validateThirdCloud(
|
|
2037
|
+
if (validateThirdCloud(trimmedValueFirstCloud, trimmedValueSecondCloud, trimmedValueThirdCloud, visibilityValue) !== true) {
|
|
1931
2038
|
return true;
|
|
1932
|
-
} // If
|
|
2039
|
+
} // If one of the previous groups contains a type, Cloud4 cannot contain a type
|
|
1933
2040
|
|
|
1934
2041
|
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
if (cloud3Type !== '') {
|
|
1938
|
-
return invalidCloud4WithPreviousType;
|
|
2042
|
+
if (type !== '' && (typeCloud1 !== '' || typeCloud2 !== '' || typeCloud3 !== '')) {
|
|
2043
|
+
return invalidCloudWithPreviousType;
|
|
1939
2044
|
} // Cloud4 height has to be greater than Cloud3 height
|
|
1940
2045
|
|
|
1941
2046
|
|
|
1942
|
-
var cloud3Height =
|
|
2047
|
+
var cloud3Height = trimmedValueThirdCloud.substring(3, 6);
|
|
1943
2048
|
|
|
1944
2049
|
if (height <= cloud3Height) {
|
|
1945
|
-
// Because of the type validations this is automatically enforced for Cloud4, so impossible to end up here but leaving the check in just in case
|
|
1946
2050
|
return invalidCloudHeightComparedToPreviousMessage;
|
|
1947
2051
|
}
|
|
1948
2052
|
|
|
@@ -2351,12 +2455,25 @@
|
|
|
2351
2455
|
if (action === 'CORRECT') return 'This TAF is a correction';
|
|
2352
2456
|
return 'Cancel TAF';
|
|
2353
2457
|
};
|
|
2354
|
-
var getConfirmationDialogContent = function getConfirmationDialogContent(action) {
|
|
2355
|
-
if (
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2458
|
+
var getConfirmationDialogContent = function getConfirmationDialogContent(action, isFormDirty) {
|
|
2459
|
+
if (isFormDirty === void 0) {
|
|
2460
|
+
isFormDirty = true;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
switch (action) {
|
|
2464
|
+
case 'DISCARD':
|
|
2465
|
+
return 'Are you sure you would like to discard this TAF? Any changes made will be lost';
|
|
2466
|
+
|
|
2467
|
+
case 'PUBLISH':
|
|
2468
|
+
return 'Are you sure you want to publish this TAF?';
|
|
2469
|
+
|
|
2470
|
+
case 'AMEND':
|
|
2471
|
+
case 'CORRECT':
|
|
2472
|
+
return isFormDirty ? 'Do you want to publish it?' : 'Are you sure you want to publish the TAF? You did not make any changes!';
|
|
2473
|
+
|
|
2474
|
+
default:
|
|
2475
|
+
return 'Are you sure you want to cancel this TAF?';
|
|
2476
|
+
}
|
|
2360
2477
|
};
|
|
2361
2478
|
var getConfirmationDialogButtonLabel = function getConfirmationDialogButtonLabel(action) {
|
|
2362
2479
|
switch (action) {
|
|
@@ -2433,7 +2550,7 @@
|
|
|
2433
2550
|
borderRadius: '3px'
|
|
2434
2551
|
},
|
|
2435
2552
|
addButton: {
|
|
2436
|
-
marginRight: '
|
|
2553
|
+
marginRight: '48px'
|
|
2437
2554
|
},
|
|
2438
2555
|
lifecycleButtons: {
|
|
2439
2556
|
marginTop: '40px',
|
|
@@ -2448,6 +2565,9 @@
|
|
|
2448
2565
|
backdrop: {
|
|
2449
2566
|
zIndex: 1500,
|
|
2450
2567
|
color: '#fff'
|
|
2568
|
+
},
|
|
2569
|
+
emptyButtonContainer: {
|
|
2570
|
+
minWidth: 96
|
|
2451
2571
|
}
|
|
2452
2572
|
};
|
|
2453
2573
|
});
|
|
@@ -2691,8 +2811,10 @@
|
|
|
2691
2811
|
field = _f === void 0 ? null : _f,
|
|
2692
2812
|
_g = _a.dragHandle,
|
|
2693
2813
|
dragHandle = _g === void 0 ? null : _g,
|
|
2694
|
-
|
|
2814
|
+
onAddChangeGroup = _a.onAddChangeGroup,
|
|
2815
|
+
props = __rest(_a, ["isChangeGroup", "disabled", "index", "lastRow", "onRemoveChangeGroup", "field", "dragHandle", "onAddChangeGroup"]);
|
|
2695
2816
|
|
|
2817
|
+
var classes = useStyles$9();
|
|
2696
2818
|
var namePrefix = !isChangeGroup ? 'baseForecast' : "changeGroups[" + index + "]";
|
|
2697
2819
|
var fieldNames = getFieldNames(isChangeGroup, index);
|
|
2698
2820
|
|
|
@@ -2769,16 +2891,43 @@
|
|
|
2769
2891
|
return true;
|
|
2770
2892
|
}, [index, isChangeGroup, getValues]);
|
|
2771
2893
|
|
|
2772
|
-
var
|
|
2773
|
-
|
|
2774
|
-
|
|
2894
|
+
var getFieldFromRow = function getFieldFromRow(fieldname, rowIndex) {
|
|
2895
|
+
var indexedFieldName = "changeGroups[" + rowIndex + "]." + fieldname;
|
|
2896
|
+
var rowValue = getValues(indexedFieldName);
|
|
2897
|
+
return rowValue ? [indexedFieldName] : [];
|
|
2898
|
+
};
|
|
2899
|
+
|
|
2900
|
+
var getValidFieldFromNextRow = function getValidFieldFromNextRow() {
|
|
2901
|
+
return getFieldFromRow('valid', index + 1);
|
|
2902
|
+
};
|
|
2903
|
+
|
|
2904
|
+
var validateNextRows = React__default["default"].useCallback(function () {
|
|
2905
|
+
if (isChangeGroup) {
|
|
2906
|
+
var _a = getValues(),
|
|
2907
|
+
validDateEnd = _a.validDateEnd,
|
|
2908
|
+
validDateStart = _a.validDateStart,
|
|
2909
|
+
changeGroups = _a.changeGroups;
|
|
2910
|
+
|
|
2911
|
+
var currentChangeGroup = changeGroups[index];
|
|
2912
|
+
var nextChangeGroups = changeGroups.slice(index + 1);
|
|
2913
|
+
return validateOverlapWithFM(currentChangeGroup, nextChangeGroups, validDateStart, validDateEnd);
|
|
2775
2914
|
}
|
|
2776
2915
|
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2916
|
+
return true;
|
|
2917
|
+
}, [index, isChangeGroup, getValues]);
|
|
2918
|
+
|
|
2919
|
+
var getPreviousValidFields = function getPreviousValidFields(rowIndex) {
|
|
2920
|
+
var changeGroups = getValues().changeGroups;
|
|
2921
|
+
var previousChangeGroups = changeGroups.slice(0, rowIndex);
|
|
2922
|
+
var validFields = previousChangeGroups.map(function (_element, index) {
|
|
2923
|
+
return getFieldFromRow('valid', index)[0];
|
|
2924
|
+
});
|
|
2925
|
+
return validFields;
|
|
2780
2926
|
};
|
|
2781
2927
|
|
|
2928
|
+
var addChangeGroup = React__default["default"].useCallback(function () {
|
|
2929
|
+
onAddChangeGroup(index);
|
|
2930
|
+
}, [onAddChangeGroup, index]);
|
|
2782
2931
|
return /*#__PURE__*/React__default["default"].createElement(core.Grid, __assign({
|
|
2783
2932
|
"data-testid": "row-" + namePrefix,
|
|
2784
2933
|
container: true,
|
|
@@ -2822,7 +2971,7 @@
|
|
|
2822
2971
|
}],
|
|
2823
2972
|
onBlur: function onBlur() {
|
|
2824
2973
|
if (isChangeGroup) {
|
|
2825
|
-
var nextValidFieldName =
|
|
2974
|
+
var nextValidFieldName = getValidFieldFromNextRow();
|
|
2826
2975
|
trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)));
|
|
2827
2976
|
}
|
|
2828
2977
|
}
|
|
@@ -2852,8 +3001,9 @@
|
|
|
2852
3001
|
}],
|
|
2853
3002
|
onBlur: function onBlur() {
|
|
2854
3003
|
if (isChangeGroup) {
|
|
2855
|
-
var nextValidFieldName =
|
|
2856
|
-
|
|
3004
|
+
var nextValidFieldName = getValidFieldFromNextRow();
|
|
3005
|
+
var previousValidFieldNames = getPreviousValidFields(index);
|
|
3006
|
+
trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
|
|
2857
3007
|
}
|
|
2858
3008
|
}
|
|
2859
3009
|
})), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
|
|
@@ -2871,13 +3021,15 @@
|
|
|
2871
3021
|
validateValidChangeGroupInterField: function validateValidChangeGroupInterField$1(value) {
|
|
2872
3022
|
return isChangeGroup ? validateValidChangeGroupInterField(value, getValues(fieldNames.change), getValues('validDateStart'), getValues('validDateEnd')) : true;
|
|
2873
3023
|
},
|
|
2874
|
-
validatePreviousRow: validatePreviousRow
|
|
3024
|
+
validatePreviousRow: validatePreviousRow,
|
|
3025
|
+
validateNextRows: validateNextRows
|
|
2875
3026
|
}
|
|
2876
3027
|
},
|
|
2877
3028
|
onBlur: function onBlur() {
|
|
2878
3029
|
if (isChangeGroup) {
|
|
2879
|
-
var nextValidFieldName =
|
|
2880
|
-
|
|
3030
|
+
var nextValidFieldName = getValidFieldFromNextRow();
|
|
3031
|
+
var previousValidFieldNames = getPreviousValidFields(index);
|
|
3032
|
+
trigger(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], __read(subFields)), __read(mainOptionalFields)), __read(mainFields)), __read(nextValidFieldName)), __read(previousValidFieldNames)));
|
|
2881
3033
|
}
|
|
2882
3034
|
}
|
|
2883
3035
|
}), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
|
|
@@ -2891,7 +3043,9 @@
|
|
|
2891
3043
|
return _validateRequiredMainFields(value, 'Wind');
|
|
2892
3044
|
},
|
|
2893
3045
|
validateRequiredSub: validateRequiredSub,
|
|
2894
|
-
validateWindField: validateWindField
|
|
3046
|
+
validateWindField: function validateWindField$1(value) {
|
|
3047
|
+
return validateWindField(value, getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
|
|
3048
|
+
}
|
|
2895
3049
|
}
|
|
2896
3050
|
},
|
|
2897
3051
|
onBlur: function onBlur() {
|
|
@@ -2940,7 +3094,7 @@
|
|
|
2940
3094
|
},
|
|
2941
3095
|
onBlur: function onBlur() {
|
|
2942
3096
|
var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
|
|
2943
|
-
return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather2, fieldNames.weather3]));
|
|
3097
|
+
return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather2, fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
|
|
2944
3098
|
}
|
|
2945
3099
|
}), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
|
|
2946
3100
|
label: "Weather",
|
|
@@ -2956,7 +3110,7 @@
|
|
|
2956
3110
|
},
|
|
2957
3111
|
onBlur: function onBlur() {
|
|
2958
3112
|
var fields = isChangeGroup ? __spreadArray(__spreadArray([], __read(subFields)), __read(mainFields)) : [];
|
|
2959
|
-
return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather3]));
|
|
3113
|
+
return trigger(__spreadArray(__spreadArray([], __read(fields)), [fieldNames.weather3, fieldNames.wind, fieldNames.cloud1]));
|
|
2960
3114
|
}
|
|
2961
3115
|
}), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
|
|
2962
3116
|
label: "Weather",
|
|
@@ -2969,6 +3123,9 @@
|
|
|
2969
3123
|
return validateThirdWeatherField(getValues(fieldNames.weather1), getValues(fieldNames.weather2), value, getValues(fieldNames.visibility));
|
|
2970
3124
|
}
|
|
2971
3125
|
}
|
|
3126
|
+
},
|
|
3127
|
+
onBlur: function onBlur() {
|
|
3128
|
+
return trigger([fieldNames.wind, fieldNames.cloud1]);
|
|
2972
3129
|
}
|
|
2973
3130
|
}), /*#__PURE__*/React__default["default"].createElement(TafFormTextField, {
|
|
2974
3131
|
label: "Cloud",
|
|
@@ -2982,7 +3139,7 @@
|
|
|
2982
3139
|
},
|
|
2983
3140
|
validateRequiredSub: validateRequiredSub,
|
|
2984
3141
|
validateFirstCloud: function validateFirstCloud$1(value) {
|
|
2985
|
-
return validateFirstCloud(value, getValues(fieldNames.visibility));
|
|
3142
|
+
return validateFirstCloud(value, getValues(fieldNames.visibility), getValues(fieldNames.weather1), getValues(fieldNames.weather2), getValues(fieldNames.weather3));
|
|
2986
3143
|
}
|
|
2987
3144
|
}
|
|
2988
3145
|
},
|
|
@@ -3033,19 +3190,27 @@
|
|
|
3033
3190
|
}
|
|
3034
3191
|
}
|
|
3035
3192
|
}), (!isChangeGroup || disabled) && /*#__PURE__*/React__default["default"].createElement(core.Grid, {
|
|
3193
|
+
className: classes.emptyButtonContainer,
|
|
3036
3194
|
item: true,
|
|
3037
3195
|
xs: true
|
|
3038
|
-
}
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3196
|
+
}, !disabled && /*#__PURE__*/React__default["default"].createElement(core.IconButton, {
|
|
3197
|
+
"aria-label": "add",
|
|
3198
|
+
"data-testid": "add-changeGroup",
|
|
3199
|
+
onClick: addChangeGroup
|
|
3200
|
+
}, /*#__PURE__*/React__default["default"].createElement(icons.Add, null))), isChangeGroup && !disabled && /*#__PURE__*/React__default["default"].createElement(core.Grid, {
|
|
3201
|
+
item: true
|
|
3202
|
+
}, /*#__PURE__*/React__default["default"].createElement(core.IconButton, {
|
|
3203
|
+
"aria-label": "add",
|
|
3204
|
+
"data-testid": "add-changeGroup",
|
|
3205
|
+
onClick: addChangeGroup
|
|
3206
|
+
}, /*#__PURE__*/React__default["default"].createElement(icons.Add, null)), /*#__PURE__*/React__default["default"].createElement(core.IconButton, __assign({
|
|
3042
3207
|
"aria-label": "delete",
|
|
3043
3208
|
"data-testid": "remove-changeGroup",
|
|
3044
3209
|
onClick: function onClick() {
|
|
3045
3210
|
return onRemoveChangeGroup(index);
|
|
3046
3211
|
}
|
|
3047
3212
|
}, lastRow ? {
|
|
3048
|
-
tabIndex:
|
|
3213
|
+
tabIndex: -1
|
|
3049
3214
|
} : {}), /*#__PURE__*/React__default["default"].createElement(icons.Delete, null))));
|
|
3050
3215
|
});
|
|
3051
3216
|
|
|
@@ -3547,7 +3712,7 @@
|
|
|
3547
3712
|
var showConfirmDialog = function showConfirmDialog(action) {
|
|
3548
3713
|
return confirmDialog({
|
|
3549
3714
|
title: getConfirmationDialogTitle(action),
|
|
3550
|
-
description: getConfirmationDialogContent(action),
|
|
3715
|
+
description: getConfirmationDialogContent(action, isFormDirty),
|
|
3551
3716
|
confirmLabel: getConfirmationDialogButtonLabel(action)
|
|
3552
3717
|
});
|
|
3553
3718
|
};
|
|
@@ -3596,32 +3761,61 @@
|
|
|
3596
3761
|
name: 'changeGroups'
|
|
3597
3762
|
}),
|
|
3598
3763
|
fields = _h.fields,
|
|
3599
|
-
|
|
3764
|
+
insert = _h.insert,
|
|
3600
3765
|
remove = _h.remove,
|
|
3601
3766
|
move = _h.move;
|
|
3602
3767
|
|
|
3603
|
-
var lastTotalFields = shared.usePrevious(fields.length);
|
|
3604
|
-
|
|
3605
3768
|
var _j = useDragOrder(trigger, move, onFormBlur),
|
|
3606
3769
|
onChangeOrder = _j.onChangeOrder,
|
|
3607
3770
|
onStartDrag = _j.onStartDrag,
|
|
3608
3771
|
activeDraggingIndex = _j.activeDraggingIndex;
|
|
3609
3772
|
|
|
3610
3773
|
var onRemoverow = function onRemoverow(index) {
|
|
3611
|
-
|
|
3774
|
+
confirmDialog({
|
|
3775
|
+
title: 'Delete row',
|
|
3776
|
+
description: 'Are you sure you want to delete this row?',
|
|
3777
|
+
confirmLabel: 'Yes'
|
|
3778
|
+
}).then(function () {
|
|
3779
|
+
remove(index);
|
|
3780
|
+
trigger(); // trigger all fields validation
|
|
3781
|
+
|
|
3782
|
+
onFormBlur();
|
|
3783
|
+
});
|
|
3784
|
+
}; // 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
|
|
3785
|
+
|
|
3786
|
+
|
|
3787
|
+
var focusFirstInput = function focusFirstInput(rowIndex) {
|
|
3788
|
+
var nextRowFirstInput = document.querySelector("[name=\"changeGroups[" + rowIndex + "].probability\"]");
|
|
3789
|
+
|
|
3790
|
+
if (nextRowFirstInput) {
|
|
3791
|
+
nextRowFirstInput.focus();
|
|
3792
|
+
}
|
|
3612
3793
|
};
|
|
3613
3794
|
|
|
3614
|
-
var onAddRow = function onAddRow() {
|
|
3615
|
-
|
|
3795
|
+
var onAddRow = function onAddRow(rowIndex) {
|
|
3796
|
+
if (rowIndex === void 0) {
|
|
3797
|
+
rowIndex = -1;
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
var newRowIndex = rowIndex + 1;
|
|
3801
|
+
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
|
|
3802
|
+
|
|
3803
|
+
setTimeout(function () {
|
|
3804
|
+
focusFirstInput(newRowIndex);
|
|
3805
|
+
trigger(); // trigger all fields validation
|
|
3806
|
+
}, 0);
|
|
3616
3807
|
};
|
|
3617
3808
|
|
|
3618
3809
|
React__default["default"].useEffect(function () {
|
|
3619
|
-
if (
|
|
3620
|
-
|
|
3621
|
-
|
|
3810
|
+
if (!isDisabled) {
|
|
3811
|
+
// trigger validation on all changegroup validity times after initial load since they could be outside the new validity period
|
|
3812
|
+
var validFields = fields.map(function (_field, index) {
|
|
3813
|
+
return "changeGroups[" + index + "].valid";
|
|
3814
|
+
});
|
|
3815
|
+
trigger(validFields);
|
|
3622
3816
|
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3623
3817
|
|
|
3624
|
-
}, [
|
|
3818
|
+
}, []);
|
|
3625
3819
|
return /*#__PURE__*/React__default["default"].createElement("form", {
|
|
3626
3820
|
onSubmit: handleSubmit(onSubmit),
|
|
3627
3821
|
onBlur: onFormBlur
|
|
@@ -3637,7 +3831,8 @@
|
|
|
3637
3831
|
"data-testid": "tafform-tac-message-line"
|
|
3638
3832
|
}, line);
|
|
3639
3833
|
})), /*#__PURE__*/React__default["default"].createElement(TafFormRow, {
|
|
3640
|
-
disabled: isDisabled
|
|
3834
|
+
disabled: isDisabled,
|
|
3835
|
+
onAddChangeGroup: onAddRow
|
|
3641
3836
|
}), /*#__PURE__*/React__default["default"].createElement(reactSortablejs.ReactSortable, {
|
|
3642
3837
|
tag: "div",
|
|
3643
3838
|
list: fields,
|
|
@@ -3661,6 +3856,7 @@
|
|
|
3661
3856
|
lastRow: fields.length === index + 1,
|
|
3662
3857
|
disabled: isDisabled,
|
|
3663
3858
|
onRemoveChangeGroup: onRemoverow,
|
|
3859
|
+
onAddChangeGroup: onAddRow,
|
|
3664
3860
|
isChangeGroup: true,
|
|
3665
3861
|
dragHandle: /*#__PURE__*/React__default["default"].createElement(DragHandle, {
|
|
3666
3862
|
isDisabled: fields.length === 1 || isDisabled,
|
|
@@ -3668,20 +3864,10 @@
|
|
|
3668
3864
|
index: index
|
|
3669
3865
|
})
|
|
3670
3866
|
});
|
|
3671
|
-
})), !isDisabled && /*#__PURE__*/React__default["default"].createElement(
|
|
3672
|
-
container: true,
|
|
3673
|
-
item: true,
|
|
3674
|
-
xs: 12,
|
|
3675
|
-
justify: "flex-end"
|
|
3676
|
-
}, /*#__PURE__*/React__default["default"].createElement(core.IconButton, {
|
|
3677
|
-
"aria-label": "add",
|
|
3678
|
-
"data-testid": "add-changeGroup",
|
|
3679
|
-
onClick: onAddRow,
|
|
3680
|
-
className: classes.addButton
|
|
3681
|
-
}, /*#__PURE__*/React__default["default"].createElement(icons.Add, null))), /*#__PURE__*/React__default["default"].createElement(TafFormButtons, {
|
|
3867
|
+
})), !isDisabled && /*#__PURE__*/React__default["default"].createElement(TafFormButtons, {
|
|
3682
3868
|
tafAction: tafAction,
|
|
3683
3869
|
onTafFormButtonPress: onTafButtonPress
|
|
3684
|
-
})
|
|
3870
|
+
}), hiddenInputFields.map(function (field) {
|
|
3685
3871
|
return /*#__PURE__*/React__default["default"].createElement(formFields.ReactHookFormHiddenInput, {
|
|
3686
3872
|
name: field,
|
|
3687
3873
|
key: field
|
|
@@ -4713,8 +4899,8 @@
|
|
|
4713
4899
|
return /*#__PURE__*/React__default["default"].createElement(shared.ConfirmationServiceProvider, null, /*#__PURE__*/React__default["default"].createElement(TafWrapper, null));
|
|
4714
4900
|
};
|
|
4715
4901
|
|
|
4716
|
-
var createApi = function createApi(url, appUrl, auth, setAuth, authTokenUrl) {
|
|
4717
|
-
var axiosInstance = api.createApiInstance(url, appUrl, auth, setAuth, authTokenUrl);
|
|
4902
|
+
var createApi = function createApi(url, appUrl, auth, setAuth, authTokenUrl, authClientId) {
|
|
4903
|
+
var axiosInstance = api.createApiInstance(url, appUrl, auth, setAuth, authTokenUrl, authClientId);
|
|
4718
4904
|
return {
|
|
4719
4905
|
// api data
|
|
4720
4906
|
getTafList: function getTafList() {
|