@visns-studio/visns-components 5.15.10 → 5.15.11

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/package.json CHANGED
@@ -94,7 +94,7 @@
94
94
  "react-dom": "^17.0.0 || ^18.0.0"
95
95
  },
96
96
  "name": "@visns-studio/visns-components",
97
- "version": "5.15.10",
97
+ "version": "5.15.11",
98
98
  "description": "Various packages to assist in the development of our Custom Applications.",
99
99
  "main": "src/index.js",
100
100
  "files": [
@@ -70,9 +70,13 @@ function Breadcrumb({ data, page }) {
70
70
 
71
71
  return (
72
72
  <h1>
73
- {page?.parentTitle && page?.parentUrl && (
73
+ {page?.parentTitle && (
74
74
  <>
75
- <Link to={page.parentUrl}>{parse(page.parentTitle)}</Link>
75
+ {page?.parentUrl ? (
76
+ <Link to={page.parentUrl}>{parse(page.parentTitle)}</Link>
77
+ ) : (
78
+ <span>{parse(page.parentTitle)}</span>
79
+ )}
76
80
  <ChevronRight strokeWidth={2} size={18} />
77
81
  </>
78
82
  )}
@@ -92,15 +96,19 @@ function Breadcrumb({ data, page }) {
92
96
  page &&
93
97
  page.title && (
94
98
  <>
95
- <Link
96
- to={`${page.previousUrl}${
97
- page.previousUrlKey && data[page.previousUrlKey]
98
- ? '/' + data[page.previousUrlKey]
99
- : ''
100
- }`}
101
- >
102
- {parse(page.title)}
103
- </Link>
99
+ {page.previousUrl ? (
100
+ <Link
101
+ to={`${page.previousUrl}${
102
+ page.previousUrlKey && data[page.previousUrlKey]
103
+ ? '/' + data[page.previousUrlKey]
104
+ : ''
105
+ }`}
106
+ >
107
+ {parse(page.title)}
108
+ </Link>
109
+ ) : (
110
+ <span>{parse(page.title)}</span>
111
+ )}
104
112
  </>
105
113
  )
106
114
  )}
@@ -323,7 +323,12 @@ function Form({
323
323
  updateFormData({ [id]: inputValue });
324
324
 
325
325
  // Batch update version
326
- const excludedKeys = new Set(['id', 'label', 'description']);
326
+ const excludedKeys = new Set([
327
+ 'id',
328
+ 'label',
329
+ 'description',
330
+ 'name',
331
+ ]);
327
332
  const updates = {};
328
333
 
329
334
  for (const key in inputValue) {
@@ -571,7 +576,7 @@ function Form({
571
576
  const handleChangeJsonTable = (event, rowIndex, columnId, fieldType) => {
572
577
  const fieldId = event.target.getAttribute('data-id');
573
578
  let value = event.target.value;
574
-
579
+
575
580
  // Handle different field types
576
581
  if (fieldType === 'checkbox' || fieldType === 'toggle') {
577
582
  value = event.target.checked;
@@ -579,9 +584,9 @@ function Form({
579
584
  value = parseFloat(value) || 0;
580
585
  }
581
586
 
582
- setFormData(prevData => {
587
+ setFormData((prevData) => {
583
588
  const newData = { ...prevData };
584
-
589
+
585
590
  // Get the current JSON value for this field
586
591
  let currentValue = newData[fieldId];
587
592
  if (typeof currentValue === 'string') {
@@ -595,13 +600,17 @@ function Form({
595
600
  // Find field configuration from form settings
596
601
  let fieldConfig = null;
597
602
  if (formSettings && formSettings.fields) {
598
- fieldConfig = formSettings.fields.find(f => f.id === fieldId);
603
+ fieldConfig = formSettings.fields.find((f) => f.id === fieldId);
599
604
  }
600
605
 
601
606
  // Handle nested JSON path (e.g., intervals within galvanizing_intervals)
602
607
  let tableData;
603
-
604
- if (fieldConfig && fieldConfig.jsonPath && currentValue[fieldConfig.jsonPath]) {
608
+
609
+ if (
610
+ fieldConfig &&
611
+ fieldConfig.jsonPath &&
612
+ currentValue[fieldConfig.jsonPath]
613
+ ) {
605
614
  tableData = [...currentValue[fieldConfig.jsonPath]];
606
615
  } else if (Array.isArray(currentValue)) {
607
616
  tableData = [...currentValue];
@@ -613,7 +622,7 @@ function Form({
613
622
  if (tableData[rowIndex]) {
614
623
  tableData[rowIndex] = {
615
624
  ...tableData[rowIndex],
616
- [columnId]: value
625
+ [columnId]: value,
617
626
  };
618
627
  }
619
628
 
@@ -621,7 +630,7 @@ function Form({
621
630
  if (fieldConfig && fieldConfig.jsonPath) {
622
631
  newData[fieldId] = {
623
632
  ...currentValue,
624
- [fieldConfig.jsonPath]: tableData
633
+ [fieldConfig.jsonPath]: tableData,
625
634
  };
626
635
  } else {
627
636
  newData[fieldId] = tableData;
@@ -632,10 +641,10 @@ function Form({
632
641
  };
633
642
 
634
643
  const handleAddJsonTableRow = (fieldId, defaultRow = {}) => {
635
- setFormData(prevData => {
644
+ setFormData((prevData) => {
636
645
  const newData = { ...prevData };
637
646
  let currentValue = newData[fieldId];
638
-
647
+
639
648
  if (typeof currentValue === 'string') {
640
649
  try {
641
650
  currentValue = JSON.parse(currentValue);
@@ -647,12 +656,16 @@ function Form({
647
656
  // Find field configuration from form settings
648
657
  let fieldConfig = null;
649
658
  if (formSettings && formSettings.fields) {
650
- fieldConfig = formSettings.fields.find(f => f.id === fieldId);
659
+ fieldConfig = formSettings.fields.find((f) => f.id === fieldId);
651
660
  }
652
661
 
653
662
  let tableData;
654
-
655
- if (fieldConfig && fieldConfig.jsonPath && currentValue[fieldConfig.jsonPath]) {
663
+
664
+ if (
665
+ fieldConfig &&
666
+ fieldConfig.jsonPath &&
667
+ currentValue[fieldConfig.jsonPath]
668
+ ) {
656
669
  tableData = [...currentValue[fieldConfig.jsonPath]];
657
670
  } else if (Array.isArray(currentValue)) {
658
671
  tableData = [...currentValue];
@@ -663,7 +676,7 @@ function Form({
663
676
  // Add new row with auto-generated number
664
677
  const newRow = {
665
678
  ...defaultRow,
666
- number: tableData.length + 1
679
+ number: tableData.length + 1,
667
680
  };
668
681
  tableData.push(newRow);
669
682
 
@@ -671,7 +684,7 @@ function Form({
671
684
  if (fieldConfig && fieldConfig.jsonPath) {
672
685
  newData[fieldId] = {
673
686
  ...currentValue,
674
- [fieldConfig.jsonPath]: tableData
687
+ [fieldConfig.jsonPath]: tableData,
675
688
  };
676
689
  } else {
677
690
  newData[fieldId] = tableData;
@@ -689,10 +702,10 @@ function Form({
689
702
  {
690
703
  label: 'Yes',
691
704
  onClick: () => {
692
- setFormData(prevData => {
705
+ setFormData((prevData) => {
693
706
  const newData = { ...prevData };
694
707
  let currentValue = newData[fieldId];
695
-
708
+
696
709
  if (typeof currentValue === 'string') {
697
710
  try {
698
711
  currentValue = JSON.parse(currentValue);
@@ -704,13 +717,21 @@ function Form({
704
717
  // Find field configuration from form settings
705
718
  let fieldConfig = null;
706
719
  if (formSettings && formSettings.fields) {
707
- fieldConfig = formSettings.fields.find(f => f.id === fieldId);
720
+ fieldConfig = formSettings.fields.find(
721
+ (f) => f.id === fieldId
722
+ );
708
723
  }
709
724
 
710
725
  let tableData;
711
-
712
- if (fieldConfig && fieldConfig.jsonPath && currentValue[fieldConfig.jsonPath]) {
713
- tableData = [...currentValue[fieldConfig.jsonPath]];
726
+
727
+ if (
728
+ fieldConfig &&
729
+ fieldConfig.jsonPath &&
730
+ currentValue[fieldConfig.jsonPath]
731
+ ) {
732
+ tableData = [
733
+ ...currentValue[fieldConfig.jsonPath],
734
+ ];
714
735
  } else if (Array.isArray(currentValue)) {
715
736
  tableData = [...currentValue];
716
737
  } else {
@@ -729,7 +750,7 @@ function Form({
729
750
  if (fieldConfig && fieldConfig.jsonPath) {
730
751
  newData[fieldId] = {
731
752
  ...currentValue,
732
- [fieldConfig.jsonPath]: tableData
753
+ [fieldConfig.jsonPath]: tableData,
733
754
  };
734
755
  } else {
735
756
  newData[fieldId] = tableData;
@@ -737,15 +758,15 @@ function Form({
737
758
 
738
759
  return newData;
739
760
  });
740
- }
761
+ },
741
762
  },
742
763
  {
743
764
  label: 'No',
744
765
  onClick: () => {
745
766
  // User cancelled - do nothing
746
- }
747
- }
748
- ]
767
+ },
768
+ },
769
+ ],
749
770
  });
750
771
  };
751
772
 
@@ -1179,121 +1200,233 @@ function Form({
1179
1200
 
1180
1201
  // Custom validation for json-table fields
1181
1202
  fields.forEach((item) => {
1182
- if (item.type === 'json-table' && item.validation?.customValidation) {
1203
+ if (
1204
+ item.type === 'json-table' &&
1205
+ item.validation?.customValidation
1206
+ ) {
1183
1207
  try {
1184
1208
  let jsonTableData = [];
1185
1209
  const fieldValue = formData[item.id];
1186
-
1187
- if (fieldValue && fieldValue !== 'null' && fieldValue !== '') {
1188
- const parsedValue = typeof fieldValue === 'string' ? JSON.parse(fieldValue) : fieldValue;
1189
-
1210
+
1211
+ if (
1212
+ fieldValue &&
1213
+ fieldValue !== 'null' &&
1214
+ fieldValue !== ''
1215
+ ) {
1216
+ const parsedValue =
1217
+ typeof fieldValue === 'string'
1218
+ ? JSON.parse(fieldValue)
1219
+ : fieldValue;
1220
+
1190
1221
  // Handle jsonPath setting to extract nested data
1191
- if (item.jsonPath && parsedValue[item.jsonPath]) {
1192
- jsonTableData = Array.isArray(parsedValue[item.jsonPath])
1193
- ? parsedValue[item.jsonPath]
1222
+ if (
1223
+ item.jsonPath &&
1224
+ parsedValue[item.jsonPath]
1225
+ ) {
1226
+ jsonTableData = Array.isArray(
1227
+ parsedValue[item.jsonPath]
1228
+ )
1229
+ ? parsedValue[item.jsonPath]
1194
1230
  : [];
1195
1231
  } else if (Array.isArray(parsedValue)) {
1196
1232
  jsonTableData = parsedValue;
1197
- } else if (typeof parsedValue === 'object' && parsedValue !== null) {
1233
+ } else if (
1234
+ typeof parsedValue === 'object' &&
1235
+ parsedValue !== null
1236
+ ) {
1198
1237
  jsonTableData = [parsedValue];
1199
1238
  }
1200
1239
  }
1201
-
1240
+
1202
1241
  // Perform validation using the same logic as in Field.jsx
1203
- const validateJsonTable = (data, validationConfig) => {
1204
- if (!validationConfig || !validationConfig.customValidation) {
1242
+ const validateJsonTable = (
1243
+ data,
1244
+ validationConfig
1245
+ ) => {
1246
+ if (
1247
+ !validationConfig ||
1248
+ !validationConfig.customValidation
1249
+ ) {
1205
1250
  return { isValid: true, errors: [] };
1206
1251
  }
1207
- const { type, startTimeField, endTimeField, message } = validationConfig.customValidation;
1252
+ const {
1253
+ type,
1254
+ startTimeField,
1255
+ endTimeField,
1256
+ message,
1257
+ } = validationConfig.customValidation;
1208
1258
  const errors = [];
1209
-
1259
+
1210
1260
  if (type === '24hour_coverage') {
1211
1261
  // Convert time strings to minutes for easier calculation
1212
1262
  const timeToMinutes = (timeStr) => {
1213
1263
  if (!timeStr) return null;
1214
- const [hours, minutes] = timeStr.split(':').map(Number);
1264
+ const [hours, minutes] = timeStr
1265
+ .split(':')
1266
+ .map(Number);
1215
1267
  return hours * 60 + minutes;
1216
1268
  };
1217
-
1269
+
1218
1270
  // Sort intervals by start time
1219
- const sortedIntervals = [...data].sort((a, b) => {
1220
- const aStart = timeToMinutes(a[startTimeField]);
1221
- const bStart = timeToMinutes(b[startTimeField]);
1222
- return aStart - bStart;
1223
- });
1224
-
1271
+ const sortedIntervals = [...data].sort(
1272
+ (a, b) => {
1273
+ const aStart = timeToMinutes(
1274
+ a[startTimeField]
1275
+ );
1276
+ const bStart = timeToMinutes(
1277
+ b[startTimeField]
1278
+ );
1279
+ return aStart - bStart;
1280
+ }
1281
+ );
1282
+
1225
1283
  let totalCoverage = 0;
1226
1284
  let previousEnd = null;
1227
-
1228
- for (let i = 0; i < sortedIntervals.length; i++) {
1285
+
1286
+ for (
1287
+ let i = 0;
1288
+ i < sortedIntervals.length;
1289
+ i++
1290
+ ) {
1229
1291
  const interval = sortedIntervals[i];
1230
- const startMinutes = timeToMinutes(interval[startTimeField]);
1231
- const endMinutes = timeToMinutes(interval[endTimeField]);
1232
-
1233
- if (startMinutes === null || endMinutes === null) {
1234
- errors.push(`Interval ${i + 1}: Missing start or end time`);
1292
+ const startMinutes = timeToMinutes(
1293
+ interval[startTimeField]
1294
+ );
1295
+ const endMinutes = timeToMinutes(
1296
+ interval[endTimeField]
1297
+ );
1298
+
1299
+ if (
1300
+ startMinutes === null ||
1301
+ endMinutes === null
1302
+ ) {
1303
+ errors.push(
1304
+ `Interval ${
1305
+ i + 1
1306
+ }: Missing start or end time`
1307
+ );
1235
1308
  continue;
1236
1309
  }
1237
-
1310
+
1238
1311
  // Handle cross-midnight intervals (e.g., 18:00 to 06:00)
1239
1312
  let duration;
1240
1313
  if (endMinutes <= startMinutes) {
1241
- duration = (endMinutes + 1440) - startMinutes;
1314
+ duration =
1315
+ endMinutes +
1316
+ 1440 -
1317
+ startMinutes;
1242
1318
  } else {
1243
- duration = endMinutes - startMinutes;
1319
+ duration =
1320
+ endMinutes - startMinutes;
1244
1321
  }
1245
-
1322
+
1246
1323
  totalCoverage += duration;
1247
-
1324
+
1248
1325
  // Check for gaps (except for the first interval)
1249
- if (previousEnd !== null && startMinutes !== previousEnd) {
1250
- const gapSize = startMinutes > previousEnd
1251
- ? startMinutes - previousEnd
1252
- : (startMinutes + 1440) - previousEnd;
1253
-
1326
+ if (
1327
+ previousEnd !== null &&
1328
+ startMinutes !== previousEnd
1329
+ ) {
1330
+ const gapSize =
1331
+ startMinutes > previousEnd
1332
+ ? startMinutes - previousEnd
1333
+ : startMinutes +
1334
+ 1440 -
1335
+ previousEnd;
1336
+
1254
1337
  if (gapSize > 0 && gapSize < 1440) {
1255
- errors.push(`Gap detected between intervals: ${Math.floor(gapSize / 60)}h ${gapSize % 60}m`);
1338
+ errors.push(
1339
+ `Gap detected between intervals: ${Math.floor(
1340
+ gapSize / 60
1341
+ )}h ${gapSize % 60}m`
1342
+ );
1256
1343
  }
1257
1344
  }
1258
-
1345
+
1259
1346
  // Update previousEnd, handling cross-midnight
1260
- previousEnd = endMinutes <= startMinutes ? endMinutes + 1440 : endMinutes;
1261
- if (previousEnd >= 1440) previousEnd -= 1440;
1347
+ previousEnd =
1348
+ endMinutes <= startMinutes
1349
+ ? endMinutes + 1440
1350
+ : endMinutes;
1351
+ if (previousEnd >= 1440)
1352
+ previousEnd -= 1440;
1262
1353
  }
1263
-
1354
+
1264
1355
  // Check if total coverage equals 24 hours (1440 minutes)
1265
1356
  if (Math.abs(totalCoverage - 1440) > 1) {
1266
- errors.push(`Total coverage is ${Math.floor(totalCoverage / 60)}h ${totalCoverage % 60}m. Required: 24h 0m`);
1357
+ errors.push(
1358
+ `Total coverage is ${Math.floor(
1359
+ totalCoverage / 60
1360
+ )}h ${
1361
+ totalCoverage % 60
1362
+ }m. Required: 24h 0m`
1363
+ );
1267
1364
  }
1268
-
1365
+
1269
1366
  // Check for overlaps
1270
- for (let i = 0; i < sortedIntervals.length - 1; i++) {
1367
+ for (
1368
+ let i = 0;
1369
+ i < sortedIntervals.length - 1;
1370
+ i++
1371
+ ) {
1271
1372
  const current = sortedIntervals[i];
1272
1373
  const next = sortedIntervals[i + 1];
1273
-
1274
- const currentStart = timeToMinutes(current[startTimeField]);
1275
- const currentEnd = timeToMinutes(current[endTimeField]);
1276
- const nextStart = timeToMinutes(next[startTimeField]);
1277
-
1278
- const currentActualEnd = currentEnd <= currentStart ? currentEnd + 1440 : currentEnd;
1374
+
1375
+ const currentStart = timeToMinutes(
1376
+ current[startTimeField]
1377
+ );
1378
+ const currentEnd = timeToMinutes(
1379
+ current[endTimeField]
1380
+ );
1381
+ const nextStart = timeToMinutes(
1382
+ next[startTimeField]
1383
+ );
1384
+
1385
+ const currentActualEnd =
1386
+ currentEnd <= currentStart
1387
+ ? currentEnd + 1440
1388
+ : currentEnd;
1279
1389
  const nextActualStart = nextStart;
1280
-
1281
- if (currentActualEnd > nextActualStart && currentActualEnd < nextActualStart + 1440) {
1282
- const overlapMinutes = currentActualEnd - nextActualStart;
1283
- errors.push(`Overlap detected: ${Math.floor(overlapMinutes / 60)}h ${overlapMinutes % 60}m between intervals ${i + 1} and ${i + 2}`);
1390
+
1391
+ if (
1392
+ currentActualEnd >
1393
+ nextActualStart &&
1394
+ currentActualEnd <
1395
+ nextActualStart + 1440
1396
+ ) {
1397
+ const overlapMinutes =
1398
+ currentActualEnd -
1399
+ nextActualStart;
1400
+ errors.push(
1401
+ `Overlap detected: ${Math.floor(
1402
+ overlapMinutes / 60
1403
+ )}h ${
1404
+ overlapMinutes % 60
1405
+ }m between intervals ${
1406
+ i + 1
1407
+ } and ${i + 2}`
1408
+ );
1284
1409
  }
1285
1410
  }
1286
1411
  }
1287
-
1412
+
1288
1413
  return {
1289
1414
  isValid: errors.length === 0,
1290
- errors: errors.length > 0 ? [message, ...errors] : []
1415
+ errors:
1416
+ errors.length > 0
1417
+ ? [message, ...errors]
1418
+ : [],
1291
1419
  };
1292
1420
  };
1293
-
1294
- const validationResult = validateJsonTable(jsonTableData, item.validation);
1421
+
1422
+ const validationResult = validateJsonTable(
1423
+ jsonTableData,
1424
+ item.validation
1425
+ );
1295
1426
  if (!validationResult.isValid) {
1296
- validation += `${item.label}: ${validationResult.errors.join(', ')}<br/>`;
1427
+ validation += `${
1428
+ item.label
1429
+ }: ${validationResult.errors.join(', ')}<br/>`;
1297
1430
  _inputClass[item.id] = styles.inputError;
1298
1431
  }
1299
1432
  } catch (e) {
@@ -2164,9 +2297,15 @@ function Form({
2164
2297
  handleChangeSignature
2165
2298
  }
2166
2299
  onChangeToggle={handleChangeToggle}
2167
- onChangeJsonTable={handleChangeJsonTable}
2168
- onAddJsonTableRow={handleAddJsonTableRow}
2169
- onDeleteJsonTableRow={handleDeleteJsonTableRow}
2300
+ onChangeJsonTable={
2301
+ handleChangeJsonTable
2302
+ }
2303
+ onAddJsonTableRow={
2304
+ handleAddJsonTableRow
2305
+ }
2306
+ onDeleteJsonTableRow={
2307
+ handleDeleteJsonTableRow
2308
+ }
2170
2309
  onFileDownload={handleFileDownload}
2171
2310
  settings={item}
2172
2311
  setFormData={setFormData}
@@ -2809,9 +2948,15 @@ function Form({
2809
2948
  }
2810
2949
  onChangeSelect={handleChangeSelect}
2811
2950
  onChangeToggle={handleChangeToggle}
2812
- onChangeJsonTable={handleChangeJsonTable}
2813
- onAddJsonTableRow={handleAddJsonTableRow}
2814
- onDeleteJsonTableRow={handleDeleteJsonTableRow}
2951
+ onChangeJsonTable={
2952
+ handleChangeJsonTable
2953
+ }
2954
+ onAddJsonTableRow={
2955
+ handleAddJsonTableRow
2956
+ }
2957
+ onDeleteJsonTableRow={
2958
+ handleDeleteJsonTableRow
2959
+ }
2815
2960
  onFileDownload={handleFileDownload}
2816
2961
  settings={item}
2817
2962
  setFormData={setFormData}