nox-validation 1.5.9 → 1.6.1
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/helpers.js +69 -0
- package/lib/validate.js +79 -23
- package/package.json +1 -1
package/lib/helpers.js
CHANGED
|
@@ -1456,6 +1456,74 @@ const getSelectedNodes = ({
|
|
|
1456
1456
|
return result;
|
|
1457
1457
|
};
|
|
1458
1458
|
|
|
1459
|
+
const getParts = (date, timeZone) => {
|
|
1460
|
+
const formatter = new Intl.DateTimeFormat("en-US", {
|
|
1461
|
+
timeZone,
|
|
1462
|
+
year: "numeric",
|
|
1463
|
+
month: "2-digit",
|
|
1464
|
+
day: "2-digit",
|
|
1465
|
+
hour: "2-digit",
|
|
1466
|
+
minute: "2-digit",
|
|
1467
|
+
second: "2-digit",
|
|
1468
|
+
hour12: true,
|
|
1469
|
+
});
|
|
1470
|
+
|
|
1471
|
+
const parts = {};
|
|
1472
|
+
formatter.formatToParts(new Date(date)).forEach(({ type, value }) => {
|
|
1473
|
+
parts[type] = value;
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
return {
|
|
1477
|
+
year: parts.year,
|
|
1478
|
+
month: parts.month,
|
|
1479
|
+
day: parts.day,
|
|
1480
|
+
hour: parts.hour,
|
|
1481
|
+
minute: parts.minute,
|
|
1482
|
+
second: parts.second,
|
|
1483
|
+
dayPeriod: parts.dayPeriod, // AM/PM
|
|
1484
|
+
};
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
const formatDate = ({
|
|
1488
|
+
date,
|
|
1489
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
1490
|
+
format,
|
|
1491
|
+
}) => {
|
|
1492
|
+
const formats = [
|
|
1493
|
+
"MM/DD/YYYY h:mm A",
|
|
1494
|
+
"M/D/YYYY h:mm A",
|
|
1495
|
+
"YYYY-MM-DD HH:mm",
|
|
1496
|
+
"DD/MM/YYYY HH:mm",
|
|
1497
|
+
"DD-MM-YYYY HH:mm",
|
|
1498
|
+
"MM/DD/YYYY h:mm:ss A",
|
|
1499
|
+
"DD/MM/YYYY HH:mm:ss",
|
|
1500
|
+
"DD-MM-YYYY HH:mm:ss",
|
|
1501
|
+
"YYYY-MM-DD HH:mm:ss",
|
|
1502
|
+
"YYYY.MM.DD HH:mm:ss",
|
|
1503
|
+
];
|
|
1504
|
+
|
|
1505
|
+
if (!formats.includes(format)) format = formats[0];
|
|
1506
|
+
|
|
1507
|
+
const { year, month, day, hour, minute, second, dayPeriod } = getParts(
|
|
1508
|
+
date,
|
|
1509
|
+
timeZone
|
|
1510
|
+
);
|
|
1511
|
+
|
|
1512
|
+
let hour24 = Number(hour);
|
|
1513
|
+
if (dayPeriod === "PM" && hour24 !== 12) hour24 += 12;
|
|
1514
|
+
if (dayPeriod === "AM" && hour24 === 12) hour24 = 0;
|
|
1515
|
+
|
|
1516
|
+
return format
|
|
1517
|
+
.replace("YYYY", year)
|
|
1518
|
+
.replace("MM", month)
|
|
1519
|
+
.replace("DD", day)
|
|
1520
|
+
.replace("HH", String(hour24).padStart(2, "0"))
|
|
1521
|
+
.replace("h", String(hour24 % 12 || 12))
|
|
1522
|
+
.replace("mm", minute)
|
|
1523
|
+
.replace("ss", second)
|
|
1524
|
+
.replace("A", dayPeriod);
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1459
1527
|
module.exports = {
|
|
1460
1528
|
generateModifiedRules,
|
|
1461
1529
|
getFieldsGroupBySchemaId,
|
|
@@ -1478,4 +1546,5 @@ module.exports = {
|
|
|
1478
1546
|
getM2AItemParentPath,
|
|
1479
1547
|
getSelectedNodes,
|
|
1480
1548
|
remainingItems,
|
|
1549
|
+
formatDate,
|
|
1481
1550
|
};
|
package/lib/validate.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
getM2AItemParentPath,
|
|
13
13
|
getSelectedNodes,
|
|
14
14
|
remainingItems,
|
|
15
|
+
formatDate,
|
|
15
16
|
} = require("./helpers");
|
|
16
17
|
|
|
17
18
|
const choices = ["radio", "checkboxes", "dropdown_multiple", "dropdown"];
|
|
@@ -59,9 +60,20 @@ const typeChecks = {
|
|
|
59
60
|
}
|
|
60
61
|
return false;
|
|
61
62
|
},
|
|
62
|
-
[constants.types.TIME]: (val) =>
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
[constants.types.TIME]: (val, data) => {
|
|
64
|
+
if (val instanceof Date && !isNaN(val)) return true;
|
|
65
|
+
if (typeof val === "string") {
|
|
66
|
+
if (/^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/.test(val)) return true;
|
|
67
|
+
const parsed = Date.parse(val);
|
|
68
|
+
if (!isNaN(parsed)) {
|
|
69
|
+
if (data && data?.key && data?.updateValue) {
|
|
70
|
+
data.updateValue(data.key, new Date(val));
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
},
|
|
65
77
|
[constants.types.TIMESTAMP]: (val, data) => {
|
|
66
78
|
if (val instanceof Date && !isNaN(val)) return true;
|
|
67
79
|
if (typeof val === "string" && !isNaN(Date.parse(val))) {
|
|
@@ -410,6 +422,7 @@ const validateMetaRules = (
|
|
|
410
422
|
if (
|
|
411
423
|
(isEmpty(fieldValue) &&
|
|
412
424
|
required &&
|
|
425
|
+
!field?.meta?.hidden &&
|
|
413
426
|
![
|
|
414
427
|
constants.interfaces.FILES,
|
|
415
428
|
constants.interfaces.FILE,
|
|
@@ -422,11 +435,13 @@ const validateMetaRules = (
|
|
|
422
435
|
"none",
|
|
423
436
|
].includes(field?.meta?.interface)) ||
|
|
424
437
|
(field?.meta?.interface === constants.interfaces.TRANSLATIONS &&
|
|
438
|
+
!field?.meta?.hidden &&
|
|
425
439
|
language_codes?.length &&
|
|
426
440
|
!onlyFormFields) ||
|
|
427
441
|
([constants.interfaces.OBJECT, constants.interfaces.ITEMS].includes(
|
|
428
442
|
field?.meta?.interface
|
|
429
443
|
) &&
|
|
444
|
+
!field?.meta?.hidden &&
|
|
430
445
|
!onlyFormFields &&
|
|
431
446
|
getNodes)
|
|
432
447
|
) {
|
|
@@ -455,6 +470,7 @@ const validateMetaRules = (
|
|
|
455
470
|
const message = error_messages.REQUIRED.replace("{field}", label);
|
|
456
471
|
|
|
457
472
|
const buildError = (path, translated) => {
|
|
473
|
+
if (!isEmpty(getValue(formData, path))) return;
|
|
458
474
|
let obj = {
|
|
459
475
|
label,
|
|
460
476
|
fieldPath: path,
|
|
@@ -625,10 +641,6 @@ const handleRegexValidation = (
|
|
|
625
641
|
message = message
|
|
626
642
|
?.replace(`{field}`, fieldLabel)
|
|
627
643
|
?.replace(`{value}`, rule.value[0]);
|
|
628
|
-
console.log(
|
|
629
|
-
"[handleRegexValidation] Validation failed. Adding error. Message:",
|
|
630
|
-
message
|
|
631
|
-
);
|
|
632
644
|
addError(
|
|
633
645
|
currentPath,
|
|
634
646
|
{ label: fieldLabel, fieldPath: currentPath, description: "", message },
|
|
@@ -645,7 +657,8 @@ const validateOperatorRule = (
|
|
|
645
657
|
currentPath,
|
|
646
658
|
formData,
|
|
647
659
|
error_messages,
|
|
648
|
-
custom_message
|
|
660
|
+
custom_message,
|
|
661
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
649
662
|
) => {
|
|
650
663
|
const { isFieldCompare = false } = rule?.options ?? {};
|
|
651
664
|
let valid = false;
|
|
@@ -658,10 +671,40 @@ const validateOperatorRule = (
|
|
|
658
671
|
const isTime = field.type === constants.types.TIME;
|
|
659
672
|
const isArray = field.type === constants.types.ARRAY;
|
|
660
673
|
|
|
661
|
-
const parseTime = (
|
|
662
|
-
if (!
|
|
663
|
-
|
|
664
|
-
|
|
674
|
+
const parseTime = (value) => {
|
|
675
|
+
if (!value) return null;
|
|
676
|
+
|
|
677
|
+
const toSeconds = (str) => {
|
|
678
|
+
const [hh = 0, mm = 0, ss = 0] = str.split(":").map(Number);
|
|
679
|
+
return hh * 3600 + mm * 60 + ss;
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
if (value instanceof Date && !isNaN(value)) {
|
|
683
|
+
const timePart = formatDate({
|
|
684
|
+
date: value,
|
|
685
|
+
format: "DD/MM/YYYY HH:mm:ss",
|
|
686
|
+
timeZone,
|
|
687
|
+
}).split(" ")[1];
|
|
688
|
+
const totalSeconds = toSeconds(timePart);
|
|
689
|
+
return totalSeconds || null;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (typeof value === "string") {
|
|
693
|
+
if (/^\d{1,2}:\d{2}:\d{2}$/.test(value)) {
|
|
694
|
+
return toSeconds(value);
|
|
695
|
+
}
|
|
696
|
+
if (!isNaN(Date.parse(value))) {
|
|
697
|
+
const timePart = formatDate({
|
|
698
|
+
date: value,
|
|
699
|
+
format: "DD/MM/YYYY HH:mm:ss",
|
|
700
|
+
timeZone,
|
|
701
|
+
}).split(" ")[1];
|
|
702
|
+
const totalSeconds = toSeconds(timePart);
|
|
703
|
+
return totalSeconds || null;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
return null;
|
|
665
708
|
};
|
|
666
709
|
|
|
667
710
|
// Helper to parse date string to UTC midnight timestamp
|
|
@@ -698,7 +741,8 @@ const validateOperatorRule = (
|
|
|
698
741
|
}
|
|
699
742
|
if (isDateTime) {
|
|
700
743
|
if (forMessage) {
|
|
701
|
-
|
|
744
|
+
const format = field?.meta?.options?.format;
|
|
745
|
+
return formatDate({ date: value, format, timeZone });
|
|
702
746
|
}
|
|
703
747
|
// Return UTC timestamp for comparison
|
|
704
748
|
return parseDateTimeToUTC(value);
|
|
@@ -889,7 +933,8 @@ const handleRule = (
|
|
|
889
933
|
addError,
|
|
890
934
|
currentPath,
|
|
891
935
|
formData,
|
|
892
|
-
error_messages
|
|
936
|
+
error_messages,
|
|
937
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
893
938
|
) => {
|
|
894
939
|
const ruleValue = rule?.value;
|
|
895
940
|
let messageValue = Array.isArray(ruleValue)
|
|
@@ -990,7 +1035,8 @@ const handleRule = (
|
|
|
990
1035
|
currentPath,
|
|
991
1036
|
formData,
|
|
992
1037
|
error_messages,
|
|
993
|
-
custom_message
|
|
1038
|
+
custom_message,
|
|
1039
|
+
timeZone
|
|
994
1040
|
);
|
|
995
1041
|
break;
|
|
996
1042
|
default:
|
|
@@ -1011,7 +1057,8 @@ const validateField = (
|
|
|
1011
1057
|
fieldOptions,
|
|
1012
1058
|
language_codes,
|
|
1013
1059
|
existingForm,
|
|
1014
|
-
getNodes = true
|
|
1060
|
+
getNodes = true,
|
|
1061
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1015
1062
|
) => {
|
|
1016
1063
|
if (onlyFormFields == true && value === undefined) return;
|
|
1017
1064
|
|
|
@@ -1073,7 +1120,8 @@ const validateField = (
|
|
|
1073
1120
|
fieldOptions,
|
|
1074
1121
|
language_codes,
|
|
1075
1122
|
existingForm,
|
|
1076
|
-
false
|
|
1123
|
+
false,
|
|
1124
|
+
timeZone
|
|
1077
1125
|
)
|
|
1078
1126
|
);
|
|
1079
1127
|
} else if (field.type === constants.types.ARRAY && Array.isArray(value)) {
|
|
@@ -1093,7 +1141,8 @@ const validateField = (
|
|
|
1093
1141
|
addError,
|
|
1094
1142
|
itemPath,
|
|
1095
1143
|
formData,
|
|
1096
|
-
error_messages
|
|
1144
|
+
error_messages,
|
|
1145
|
+
timeZone
|
|
1097
1146
|
);
|
|
1098
1147
|
}
|
|
1099
1148
|
|
|
@@ -1130,7 +1179,8 @@ const validateField = (
|
|
|
1130
1179
|
fieldOptions,
|
|
1131
1180
|
language_codes,
|
|
1132
1181
|
existingForm,
|
|
1133
|
-
false
|
|
1182
|
+
false,
|
|
1183
|
+
timeZone
|
|
1134
1184
|
)
|
|
1135
1185
|
);
|
|
1136
1186
|
});
|
|
@@ -1143,7 +1193,8 @@ const validateField = (
|
|
|
1143
1193
|
addError,
|
|
1144
1194
|
currentPath,
|
|
1145
1195
|
formData,
|
|
1146
|
-
error_messages
|
|
1196
|
+
error_messages,
|
|
1197
|
+
timeZone
|
|
1147
1198
|
)
|
|
1148
1199
|
) {
|
|
1149
1200
|
addError(
|
|
@@ -1166,7 +1217,8 @@ const applyValidations = (
|
|
|
1166
1217
|
addError,
|
|
1167
1218
|
currentPath,
|
|
1168
1219
|
formData,
|
|
1169
|
-
error_messages
|
|
1220
|
+
error_messages,
|
|
1221
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1170
1222
|
) => {
|
|
1171
1223
|
if (
|
|
1172
1224
|
!field.validations ||
|
|
@@ -1185,7 +1237,8 @@ const applyValidations = (
|
|
|
1185
1237
|
addError,
|
|
1186
1238
|
currentPath,
|
|
1187
1239
|
formData,
|
|
1188
|
-
error_messages
|
|
1240
|
+
error_messages,
|
|
1241
|
+
timeZone
|
|
1189
1242
|
) === false
|
|
1190
1243
|
);
|
|
1191
1244
|
};
|
|
@@ -1213,6 +1266,7 @@ const schema = {
|
|
|
1213
1266
|
type: constants.types.ARRAY,
|
|
1214
1267
|
array_type: constants.types.OBJECT_ID,
|
|
1215
1268
|
},
|
|
1269
|
+
timeZone: { type: constants.types.STRING, array_type: null },
|
|
1216
1270
|
};
|
|
1217
1271
|
|
|
1218
1272
|
const validate = (data) => {
|
|
@@ -1239,6 +1293,7 @@ const validate = (data) => {
|
|
|
1239
1293
|
maxLevel,
|
|
1240
1294
|
onlyFormFields,
|
|
1241
1295
|
existingForm = {},
|
|
1296
|
+
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
1242
1297
|
} = data;
|
|
1243
1298
|
|
|
1244
1299
|
const error_messages =
|
|
@@ -1499,7 +1554,8 @@ const validate = (data) => {
|
|
|
1499
1554
|
apiVersion,
|
|
1500
1555
|
fieldOptions,
|
|
1501
1556
|
data.language_codes,
|
|
1502
|
-
existingForm
|
|
1557
|
+
existingForm,
|
|
1558
|
+
timeZone
|
|
1503
1559
|
);
|
|
1504
1560
|
});
|
|
1505
1561
|
return result;
|