df-ae-forms-package 1.0.89 → 1.0.91
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/dist/index.esm.js +115 -73
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +115 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5303,9 +5303,27 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
|
|
|
5303
5303
|
|
|
5304
5304
|
// Dynamic imports to avoid circular dependencies
|
|
5305
5305
|
const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
|
|
5306
|
+
// Normalize a table row from API format (object with numeric keys) into a proper array.
|
|
5307
|
+
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
5308
|
+
const normalizeTableRow = (row) => {
|
|
5309
|
+
if (Array.isArray(row))
|
|
5310
|
+
return row;
|
|
5311
|
+
if (row && typeof row === 'object') {
|
|
5312
|
+
const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
|
|
5313
|
+
if (keys.length > 0)
|
|
5314
|
+
return keys.map(k => row[k]);
|
|
5315
|
+
}
|
|
5316
|
+
return [];
|
|
5317
|
+
};
|
|
5306
5318
|
const DfFormPreview = ({ formComponents = [], currentDevice = 'desktop', isPreviewMode = false, initialFormData = [], onSubmit, onFormDataChange, formTitle, formDescription, formTemplateId,
|
|
5307
5319
|
// Add component management props for edit mode
|
|
5308
5320
|
onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, workOrderNumber, assetNumber, isStandalone, user, onCreateIssue, onUpdateIssue }) => {
|
|
5321
|
+
// Local copy of formComponents so structure updates (e.g. table cell init) are reflected immediately
|
|
5322
|
+
const [localFormComponents, setLocalFormComponents] = React.useState(formComponents);
|
|
5323
|
+
// Sync local state when the prop changes from the parent
|
|
5324
|
+
React.useEffect(() => {
|
|
5325
|
+
setLocalFormComponents(formComponents);
|
|
5326
|
+
}, [formComponents]);
|
|
5309
5327
|
// Form state
|
|
5310
5328
|
const [formValues, setFormValues] = React.useState({});
|
|
5311
5329
|
const [validationErrors, setValidationErrors] = React.useState({});
|
|
@@ -5326,7 +5344,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5326
5344
|
// Initialize form state
|
|
5327
5345
|
React.useEffect(() => {
|
|
5328
5346
|
initializeFormState();
|
|
5329
|
-
}, [
|
|
5347
|
+
}, [localFormComponents, initialFormData]);
|
|
5330
5348
|
// Recursive function to initialize values from nested components
|
|
5331
5349
|
const initializeComponentValues = (components, values) => {
|
|
5332
5350
|
components.forEach(component => {
|
|
@@ -5355,13 +5373,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5355
5373
|
// Handle nested components in table cells
|
|
5356
5374
|
if (component.cells && Array.isArray(component.cells)) {
|
|
5357
5375
|
component.cells.forEach((row, _rowIndex) => {
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
});
|
|
5364
|
-
}
|
|
5376
|
+
normalizeTableRow(row).forEach((cell, _cellIndex) => {
|
|
5377
|
+
if (cell && cell.components && Array.isArray(cell.components)) {
|
|
5378
|
+
initializeComponentValues(cell.components, values);
|
|
5379
|
+
}
|
|
5380
|
+
});
|
|
5365
5381
|
});
|
|
5366
5382
|
}
|
|
5367
5383
|
// Handle nested components in datagrid entries
|
|
@@ -5424,11 +5440,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5424
5440
|
extractNotesAndAttachments(comp.children);
|
|
5425
5441
|
if (comp.cells && Array.isArray(comp.cells))
|
|
5426
5442
|
comp.cells.forEach((row) => {
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
});
|
|
5443
|
+
normalizeTableRow(row).forEach((cell) => {
|
|
5444
|
+
if (cell && cell.components)
|
|
5445
|
+
extractNotesAndAttachments(cell.components);
|
|
5446
|
+
});
|
|
5432
5447
|
});
|
|
5433
5448
|
if (comp.entries)
|
|
5434
5449
|
comp.entries.forEach((entry) => {
|
|
@@ -5467,8 +5482,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5467
5482
|
}
|
|
5468
5483
|
if (validatedComponent.cells && Array.isArray(validatedComponent.cells)) {
|
|
5469
5484
|
validatedComponent.cells = validatedComponent.cells.map((row) => {
|
|
5470
|
-
|
|
5471
|
-
|
|
5485
|
+
const normalizedRow = normalizeTableRow(row);
|
|
5486
|
+
if (normalizedRow.length > 0) {
|
|
5487
|
+
return normalizedRow.map((cell) => {
|
|
5472
5488
|
if (cell && cell.components && Array.isArray(cell.components)) {
|
|
5473
5489
|
return {
|
|
5474
5490
|
...cell,
|
|
@@ -5496,11 +5512,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5496
5512
|
});
|
|
5497
5513
|
};
|
|
5498
5514
|
// Initialize validated components
|
|
5499
|
-
let validatedFormComponents =
|
|
5500
|
-
if (
|
|
5501
|
-
validatedFormComponents = getValidatedComponents(
|
|
5515
|
+
let validatedFormComponents = localFormComponents;
|
|
5516
|
+
if (localFormComponents && localFormComponents.length > 0) {
|
|
5517
|
+
validatedFormComponents = getValidatedComponents(localFormComponents);
|
|
5502
5518
|
// Notifying parent of changed components if they were mutated (IDs added/fixed)
|
|
5503
|
-
if (JSON.stringify(validatedFormComponents) !== JSON.stringify(
|
|
5519
|
+
if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
|
|
5504
5520
|
onFormDataChange?.(validatedFormComponents);
|
|
5505
5521
|
}
|
|
5506
5522
|
}
|
|
@@ -5528,7 +5544,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5528
5544
|
setComponentAttachments(prev => ({ ...initialAttachments, ...prev }));
|
|
5529
5545
|
// Conditional logic evaluation disabled temporarily to fix table issues
|
|
5530
5546
|
// evaluateConditionalLogic()
|
|
5531
|
-
}, [initialFormData,
|
|
5547
|
+
}, [initialFormData, localFormComponents]);
|
|
5532
5548
|
// Conditional logic disabled temporarily - all components are always visible
|
|
5533
5549
|
const shouldShowComponent = React.useCallback((_componentId) => {
|
|
5534
5550
|
return true;
|
|
@@ -5541,7 +5557,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5541
5557
|
return;
|
|
5542
5558
|
}
|
|
5543
5559
|
// CRITICAL: Check if multiple components share this ID (ID collision detection)
|
|
5544
|
-
const componentsWithSameId =
|
|
5560
|
+
const componentsWithSameId = localFormComponents.filter(comp => comp.id === change.id);
|
|
5545
5561
|
if (componentsWithSameId.length > 1) {
|
|
5546
5562
|
console.error(`[DfFormPreview] ID COLLISION DETECTED! Multiple components share ID "${change.id}":`, componentsWithSameId.map(c => ({ id: c.id, name: c.name, label: c.basic?.label })));
|
|
5547
5563
|
// Don't update - this would cause all components with this ID to get the same value
|
|
@@ -5562,7 +5578,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5562
5578
|
}
|
|
5563
5579
|
// Clear raised issues for this component when value changes
|
|
5564
5580
|
// This ensures that if threshold condition changes, user must raise issue again
|
|
5565
|
-
const component =
|
|
5581
|
+
const component = localFormComponents.find(comp => comp.id === change.id);
|
|
5566
5582
|
if (component) {
|
|
5567
5583
|
const threshold = component?.threshold;
|
|
5568
5584
|
if (threshold && threshold.conditions && threshold.conditions.length > 0) {
|
|
@@ -5615,13 +5631,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5615
5631
|
if (component.name === 'table' && component.cells) {
|
|
5616
5632
|
return {
|
|
5617
5633
|
...component,
|
|
5618
|
-
cells: component.cells.map((row) =>
|
|
5634
|
+
cells: component.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
5619
5635
|
const updatedCell = { ...cell };
|
|
5620
5636
|
if (updatedCell.components) {
|
|
5621
5637
|
updatedCell.components = updateComponentValue(updatedCell.components);
|
|
5622
5638
|
}
|
|
5623
5639
|
return updatedCell;
|
|
5624
|
-
})
|
|
5640
|
+
}))
|
|
5625
5641
|
};
|
|
5626
5642
|
}
|
|
5627
5643
|
if (component.name === 'datagrid' && component.entries) {
|
|
@@ -5640,7 +5656,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5640
5656
|
});
|
|
5641
5657
|
};
|
|
5642
5658
|
// Update form components
|
|
5643
|
-
const updatedComponents = updateComponentValue(
|
|
5659
|
+
const updatedComponents = updateComponentValue(localFormComponents);
|
|
5660
|
+
// CRITICAL: Update local state immediately so structure changes (e.g. table cell init)
|
|
5661
|
+
// are reflected without waiting for Angular parent round-trip
|
|
5662
|
+
setLocalFormComponents(updatedComponents);
|
|
5644
5663
|
onFormDataChange?.(updatedComponents);
|
|
5645
5664
|
// Clear validation errors when user starts typing and re-validate
|
|
5646
5665
|
if (validationErrors[change.id]) {
|
|
@@ -5677,7 +5696,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5677
5696
|
}
|
|
5678
5697
|
// Conditional logic evaluation disabled temporarily
|
|
5679
5698
|
// evaluateConditionalLogic(newFormValues, updatedComponents)
|
|
5680
|
-
}, [
|
|
5699
|
+
}, [localFormComponents, formValues, validationErrors, onFormDataChange]);
|
|
5681
5700
|
// Recursive function to find a component by ID in nested structures
|
|
5682
5701
|
const findComponentById = React.useCallback((components, fieldId) => {
|
|
5683
5702
|
for (const comp of components) {
|
|
@@ -5721,7 +5740,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5721
5740
|
if (isPreviewMode)
|
|
5722
5741
|
return;
|
|
5723
5742
|
// Find component recursively (handles nested components)
|
|
5724
|
-
const component = findComponentById(
|
|
5743
|
+
const component = findComponentById(localFormComponents, fieldId);
|
|
5725
5744
|
if (!component)
|
|
5726
5745
|
return;
|
|
5727
5746
|
// Get current value from form values (real-time input)
|
|
@@ -5816,7 +5835,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5816
5835
|
...prev,
|
|
5817
5836
|
[fieldId]: errorMessage
|
|
5818
5837
|
}));
|
|
5819
|
-
}, [
|
|
5838
|
+
}, [localFormComponents, isPreviewMode, formValues, findComponentById]);
|
|
5820
5839
|
// Handle form control blur
|
|
5821
5840
|
const onFormControlBlur = React.useCallback((fieldId) => {
|
|
5822
5841
|
setTouchedFields(prev => ({
|
|
@@ -5846,11 +5865,11 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5846
5865
|
// useEffect(() => {
|
|
5847
5866
|
// if (!isPreviewMode && Object.keys(formValues).length > 0) {
|
|
5848
5867
|
// // Validate all form components when form values change (but not on initial load)
|
|
5849
|
-
//
|
|
5868
|
+
// localFormComponents.forEach(component => {
|
|
5850
5869
|
// validateField(component.id)
|
|
5851
5870
|
// })
|
|
5852
5871
|
// }
|
|
5853
|
-
// }, [formValues, validateField, isPreviewMode,
|
|
5872
|
+
// }, [formValues, validateField, isPreviewMode, localFormComponents])
|
|
5854
5873
|
// Enhanced form validity check
|
|
5855
5874
|
const isFormValid = React.useCallback(() => {
|
|
5856
5875
|
// Check if there are any validation errors
|
|
@@ -5859,7 +5878,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5859
5878
|
return false;
|
|
5860
5879
|
}
|
|
5861
5880
|
// Check required fields
|
|
5862
|
-
return
|
|
5881
|
+
return localFormComponents.every(component => {
|
|
5863
5882
|
// Use real-time form values instead of component values
|
|
5864
5883
|
const currentValue = formValues[component.id] || '';
|
|
5865
5884
|
// Check if field has a value
|
|
@@ -5905,7 +5924,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5905
5924
|
}
|
|
5906
5925
|
return true;
|
|
5907
5926
|
});
|
|
5908
|
-
}, [
|
|
5927
|
+
}, [localFormComponents, formValues, validationErrors]);
|
|
5909
5928
|
// Evaluate threshold condition (handles both numeric and string values)
|
|
5910
5929
|
const evaluateThresholdCondition = React.useCallback((condition, currentVal) => {
|
|
5911
5930
|
// Handle array values (for checkbox)
|
|
@@ -5959,7 +5978,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5959
5978
|
if (isPreviewMode)
|
|
5960
5979
|
return [];
|
|
5961
5980
|
const metConditions = [];
|
|
5962
|
-
|
|
5981
|
+
localFormComponents.forEach(component => {
|
|
5963
5982
|
const condition = component?.condition;
|
|
5964
5983
|
if (!condition || !condition.conditions || condition.conditions.length === 0) {
|
|
5965
5984
|
return;
|
|
@@ -5985,7 +6004,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5985
6004
|
});
|
|
5986
6005
|
});
|
|
5987
6006
|
return metConditions;
|
|
5988
|
-
}, [
|
|
6007
|
+
}, [localFormComponents, formValues, isPreviewMode, evaluateThresholdCondition]);
|
|
5989
6008
|
// Validate threshold conditions - check if all met conditions have all mandatory actions completed
|
|
5990
6009
|
const validateThresholdConditions = React.useCallback(() => {
|
|
5991
6010
|
if (isPreviewMode)
|
|
@@ -6070,7 +6089,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6070
6089
|
let isValid = true;
|
|
6071
6090
|
setFormSubmitted(true);
|
|
6072
6091
|
const errors = {};
|
|
6073
|
-
|
|
6092
|
+
localFormComponents.forEach(component => {
|
|
6074
6093
|
// Use real-time form values instead of component values
|
|
6075
6094
|
const currentValue = formValues[component.id] || '';
|
|
6076
6095
|
// Check if field has a value
|
|
@@ -6137,13 +6156,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6137
6156
|
});
|
|
6138
6157
|
setValidationErrors(errors);
|
|
6139
6158
|
return isValid;
|
|
6140
|
-
}, [
|
|
6159
|
+
}, [localFormComponents, isPreviewMode, formValues]);
|
|
6141
6160
|
// Handle form submission
|
|
6142
6161
|
const handleSubmit = React.useCallback((status = 'Submitted') => {
|
|
6143
6162
|
setFormSubmitted(true);
|
|
6144
6163
|
if (!validateAllFields()) {
|
|
6145
6164
|
// Focus on the first invalid field
|
|
6146
|
-
const firstErrorField =
|
|
6165
|
+
const firstErrorField = localFormComponents.find(comp => {
|
|
6147
6166
|
const currentValue = formValues[comp.id] || '';
|
|
6148
6167
|
// Check if field has a value
|
|
6149
6168
|
let hasValue = false;
|
|
@@ -6225,13 +6244,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6225
6244
|
updatedComponent.children = updateComponentValues(updatedComponent.children);
|
|
6226
6245
|
}
|
|
6227
6246
|
if (updatedComponent.name === 'table' && updatedComponent.cells) {
|
|
6228
|
-
updatedComponent.cells = updatedComponent.cells.map((row) =>
|
|
6247
|
+
updatedComponent.cells = updatedComponent.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
6229
6248
|
const updatedCell = { ...cell };
|
|
6230
6249
|
if (updatedCell.components) {
|
|
6231
6250
|
updatedCell.components = updateComponentValues(updatedCell.components);
|
|
6232
6251
|
}
|
|
6233
6252
|
return updatedCell;
|
|
6234
|
-
})
|
|
6253
|
+
}));
|
|
6235
6254
|
}
|
|
6236
6255
|
if (updatedComponent.name === 'datagrid' && updatedComponent.entries) {
|
|
6237
6256
|
updatedComponent.entries = updatedComponent.entries.map((entry) => {
|
|
@@ -6246,12 +6265,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6246
6265
|
});
|
|
6247
6266
|
};
|
|
6248
6267
|
// Prepare final form data
|
|
6249
|
-
const finalFormData = updateComponentValues(
|
|
6268
|
+
const finalFormData = updateComponentValues(localFormComponents);
|
|
6250
6269
|
// Also prepare a clean key-value payload
|
|
6251
6270
|
const payloadValues = { ...formValues, status };
|
|
6252
6271
|
// Pass both the updated component tree and the flat values object
|
|
6253
6272
|
onSubmit?.(finalFormData, payloadValues);
|
|
6254
|
-
}, [
|
|
6273
|
+
}, [localFormComponents, formValues, validateAllFields, onSubmit, componentNotes, componentAttachments]);
|
|
6255
6274
|
// Get preview classes
|
|
6256
6275
|
const getPreviewClasses = React.useCallback(() => {
|
|
6257
6276
|
return {
|
|
@@ -6313,7 +6332,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6313
6332
|
// Debug: Log if formValue is being shared incorrectly
|
|
6314
6333
|
if (formValue !== undefined) {
|
|
6315
6334
|
// Check if this value is being used by multiple components
|
|
6316
|
-
const componentsWithSameValue =
|
|
6335
|
+
const componentsWithSameValue = localFormComponents.filter(comp => comp.id !== componentId && formValues[comp.id] === formValue);
|
|
6317
6336
|
if (componentsWithSameValue.length > 0) {
|
|
6318
6337
|
console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, componentsWithSameValue.map(c => c.id));
|
|
6319
6338
|
}
|
|
@@ -6412,9 +6431,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6412
6431
|
return renderFormComponent(field);
|
|
6413
6432
|
}, onNotesChange: (componentId, notes) => {
|
|
6414
6433
|
// Handle notes change for table cell components
|
|
6415
|
-
const updatedComponents =
|
|
6434
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6416
6435
|
if (comp.id === component.id && comp.cells) {
|
|
6417
|
-
const updatedCells = comp.cells.map((row) =>
|
|
6436
|
+
const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
6418
6437
|
if (cell.components) {
|
|
6419
6438
|
const updatedCellComponents = cell.components.map((cellComp) => {
|
|
6420
6439
|
if (cellComp.id === componentId) {
|
|
@@ -6431,7 +6450,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6431
6450
|
return { ...cell, components: updatedCellComponents };
|
|
6432
6451
|
}
|
|
6433
6452
|
return cell;
|
|
6434
|
-
})
|
|
6453
|
+
}));
|
|
6435
6454
|
return { ...comp, cells: updatedCells };
|
|
6436
6455
|
}
|
|
6437
6456
|
return comp;
|
|
@@ -6439,9 +6458,9 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6439
6458
|
onFormDataChange?.(updatedComponents);
|
|
6440
6459
|
}, onAttachmentChange: (componentId, attachments) => {
|
|
6441
6460
|
// Handle attachment change for table cell components
|
|
6442
|
-
const updatedComponents =
|
|
6461
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6443
6462
|
if (comp.id === component.id && comp.cells) {
|
|
6444
|
-
const updatedCells = comp.cells.map((row) =>
|
|
6463
|
+
const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
6445
6464
|
if (cell.components) {
|
|
6446
6465
|
const updatedCellComponents = cell.components.map((cellComp) => {
|
|
6447
6466
|
if (cellComp.id === componentId) {
|
|
@@ -6458,7 +6477,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6458
6477
|
return { ...cell, components: updatedCellComponents };
|
|
6459
6478
|
}
|
|
6460
6479
|
return cell;
|
|
6461
|
-
})
|
|
6480
|
+
}));
|
|
6462
6481
|
return { ...comp, cells: updatedCells };
|
|
6463
6482
|
}
|
|
6464
6483
|
return comp;
|
|
@@ -6469,7 +6488,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6469
6488
|
return (jsxRuntime.jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
|
|
6470
6489
|
handleComponentNotesChange(componentId, notes);
|
|
6471
6490
|
// Handle notes change for datagrid entry components
|
|
6472
|
-
const updatedComponents =
|
|
6491
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6473
6492
|
if (comp.id === component.id && comp.entries) {
|
|
6474
6493
|
const updatedEntries = comp.entries.map((entry) => {
|
|
6475
6494
|
if (entry.components) {
|
|
@@ -6497,7 +6516,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6497
6516
|
}, onAttachmentChange: (componentId, attachments) => {
|
|
6498
6517
|
handleComponentAttachmentChange(componentId, attachments);
|
|
6499
6518
|
// Handle attachment change for datagrid entry components
|
|
6500
|
-
const updatedComponents =
|
|
6519
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6501
6520
|
if (comp.id === component.id && comp.entries) {
|
|
6502
6521
|
const updatedEntries = comp.entries.map((entry) => {
|
|
6503
6522
|
if (entry.components) {
|
|
@@ -6525,8 +6544,8 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6525
6544
|
}, onValueChange: (change) => {
|
|
6526
6545
|
// Handle datagrid value changes (entries updates)
|
|
6527
6546
|
if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {
|
|
6528
|
-
// Update
|
|
6529
|
-
const updatedComponents =
|
|
6547
|
+
// Update localFormComponents with new entries structure
|
|
6548
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6530
6549
|
if (comp.id === component.id) {
|
|
6531
6550
|
return {
|
|
6532
6551
|
...comp,
|
|
@@ -6564,12 +6583,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6564
6583
|
}
|
|
6565
6584
|
}, onEntryAdd: () => {
|
|
6566
6585
|
// CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid
|
|
6567
|
-
// Get the updated component from
|
|
6568
|
-
const currentComponent =
|
|
6586
|
+
// Get the updated component from localFormComponents (which should have been updated by onValueChange)
|
|
6587
|
+
const currentComponent = localFormComponents.find(comp => comp.id === component.id);
|
|
6569
6588
|
if (currentComponent && currentComponent.entries) {
|
|
6570
6589
|
// Entry should already be in the component via onValueChange
|
|
6571
|
-
// Just ensure
|
|
6572
|
-
const updatedComponents =
|
|
6590
|
+
// Just ensure localFormComponents is in sync (no-op if already synced)
|
|
6591
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6573
6592
|
if (comp.id === component.id) {
|
|
6574
6593
|
// Ensure entries are properly structured
|
|
6575
6594
|
return {
|
|
@@ -6586,7 +6605,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6586
6605
|
setTimeout(() => {
|
|
6587
6606
|
const datagridValue = formValues[component.id];
|
|
6588
6607
|
if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {
|
|
6589
|
-
const updatedComponents =
|
|
6608
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6590
6609
|
if (comp.id === component.id) {
|
|
6591
6610
|
return {
|
|
6592
6611
|
...comp,
|
|
@@ -6601,7 +6620,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6601
6620
|
}
|
|
6602
6621
|
}, onEntryRemove: (entryIndex) => {
|
|
6603
6622
|
// Handle entry remove - update form components
|
|
6604
|
-
const updatedComponents =
|
|
6623
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6605
6624
|
if (comp.id === component.id && comp.entries) {
|
|
6606
6625
|
const currentEntries = comp.entries || [];
|
|
6607
6626
|
const updatedEntries = currentEntries
|
|
@@ -6643,7 +6662,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6643
6662
|
return (jsxRuntime.jsx("div", { className: "form-group", children: jsxRuntime.jsxs("div", { className: "form-group-label", children: ["Unsupported Component: ", component.name] }) }));
|
|
6644
6663
|
}
|
|
6645
6664
|
};
|
|
6646
|
-
return (jsxRuntime.jsx("div", { className: "form-preview-container", children: jsxRuntime.jsx("div", { className: "form-preview-wrapper", children: jsxRuntime.jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsxRuntime.jsx("div", { className: "form-canvas-header" }),
|
|
6665
|
+
return (jsxRuntime.jsx("div", { className: "form-preview-container", children: jsxRuntime.jsx("div", { className: "form-preview-wrapper", children: jsxRuntime.jsxs("div", { className: `form-preview ${Object.entries(getPreviewClasses()).map(([key, value]) => value ? key : '').join(' ')}`, children: [jsxRuntime.jsx("div", { className: "form-canvas-header" }), localFormComponents.length === 0 ? (jsxRuntime.jsx("div", { className: "empty-state", children: jsxRuntime.jsx("div", { className: "empty-state-card", children: jsxRuntime.jsx("div", { className: "empty-state-preview-area", children: jsxRuntime.jsx("span", { className: "empty-state-placeholder", children: "Add components to see the form preview" }) }) }) })) : (jsxRuntime.jsxs("form", { className: "form-preview-form", onSubmit: (e) => { e.preventDefault(); handleSubmit(); }, children: [(formTitle || formDescription) && (jsxRuntime.jsxs("div", { className: "form-header", children: [formTitle && (jsxRuntime.jsx("h1", { className: "form-title", children: formTitle })), formDescription && (jsxRuntime.jsx("p", { className: "form-description", children: formDescription }))] })), localFormComponents.map((component) => {
|
|
6647
6666
|
const basic = component.basic;
|
|
6648
6667
|
const formValue = formValues[component.id];
|
|
6649
6668
|
const isOptionBased = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');
|
|
@@ -6695,7 +6714,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6695
6714
|
// Update local state immediately
|
|
6696
6715
|
setComponentNotes(prev => ({ ...prev, [component.id]: notes }));
|
|
6697
6716
|
// Handle notes change for regular components - update component.basic.notes
|
|
6698
|
-
const updatedComponents =
|
|
6717
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6699
6718
|
if (comp.id === component.id) {
|
|
6700
6719
|
return {
|
|
6701
6720
|
...comp,
|
|
@@ -6712,7 +6731,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6712
6731
|
// Update local state immediately
|
|
6713
6732
|
setComponentAttachments(prev => ({ ...prev, [component.id]: attachments || [] }));
|
|
6714
6733
|
// Handle attachment change for regular components - update component.basic.attachments
|
|
6715
|
-
const updatedComponents =
|
|
6734
|
+
const updatedComponents = localFormComponents.map(comp => {
|
|
6716
6735
|
if (comp.id === component.id) {
|
|
6717
6736
|
return {
|
|
6718
6737
|
...comp,
|
|
@@ -6764,6 +6783,26 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
|
|
|
6764
6783
|
return (jsxRuntime.jsxs("div", { className: `df-form-comments ${className}`, children: [jsxRuntime.jsxs("div", { className: "df-form-comments__header", children: [jsxRuntime.jsx("h3", { className: "df-form-comments__title", children: "Comments" }), jsxRuntime.jsx("button", { className: "df-form-comments__toggle", type: "button", onClick: toggleComments, "aria-expanded": isExpanded, "aria-label": "Toggle comments section", disabled: disabled, children: isExpanded ? (jsxRuntime.jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25BC" })) : (jsxRuntime.jsx("span", { className: "df-form-comments__toggle-icon", children: "\u25B6" })) })] }), jsxRuntime.jsx("div", { className: `df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`, children: jsxRuntime.jsx("div", { className: "df-form-comments__input-container", children: jsxRuntime.jsx("div", { className: "df-form-comments__input-line", children: jsxRuntime.jsx("input", { type: "text", id: "comment-input", className: "df-form-comments__input", value: currentComment, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, placeholder: placeholder, disabled: disabled }) }) }) })] }));
|
|
6765
6784
|
};
|
|
6766
6785
|
|
|
6786
|
+
// Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
|
|
6787
|
+
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
6788
|
+
const normalizeRow = (row) => {
|
|
6789
|
+
if (Array.isArray(row))
|
|
6790
|
+
return row;
|
|
6791
|
+
if (row && typeof row === 'object') {
|
|
6792
|
+
// Convert object with numeric keys to array, sorted by key
|
|
6793
|
+
const keys = Object.keys(row).filter(k => !isNaN(Number(k))).sort((a, b) => Number(a) - Number(b));
|
|
6794
|
+
if (keys.length > 0) {
|
|
6795
|
+
return keys.map(k => row[k]);
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
return [];
|
|
6799
|
+
};
|
|
6800
|
+
// Normalize the entire cells structure from API format to TableCell[][]
|
|
6801
|
+
const normalizeCells = (cells) => {
|
|
6802
|
+
if (!cells || !Array.isArray(cells))
|
|
6803
|
+
return [];
|
|
6804
|
+
return cells.map(normalizeRow);
|
|
6805
|
+
};
|
|
6767
6806
|
// Function to ensure table cell components have proper IDs
|
|
6768
6807
|
const ensureComponentHasId = (component) => {
|
|
6769
6808
|
if (!component.id) {
|
|
@@ -6848,19 +6887,22 @@ const TableCellComponent = ({ cell, mode, onComponentSelect, onComponentDelete,
|
|
|
6848
6887
|
};
|
|
6849
6888
|
const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationErrors = {}, touchedFields = {}, formSubmitted = false, onValueChange, onSelect, isSelected = false, className = '', onTableSelect, onComponentSelect, onComponentDelete, onComponentEdit, selectedComponent, renderFormComponent, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, workOrderNumber, assetNumber, user, onCreateIssue, onUpdateIssue }) => {
|
|
6850
6889
|
const [isCollapsed, setIsCollapsed] = React.useState(false); // Always start expanded to show drop zones
|
|
6890
|
+
// CRITICAL: Normalize cells from API format (object with numeric keys) to proper 2D array
|
|
6891
|
+
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...]
|
|
6892
|
+
const normalizedCells = React.useMemo(() => normalizeCells(properties.cells), [properties.cells]);
|
|
6851
6893
|
// Check if table has any components in any cells
|
|
6852
|
-
const hasAnyComponents =
|
|
6894
|
+
const hasAnyComponents = normalizedCells.some((row) => row.some((cell) => cell.components && cell.components.length > 0)) || false;
|
|
6853
6895
|
// Initialize and update table cells when rows/columns change
|
|
6854
6896
|
// Only trigger when cells are truly missing or structure doesn't match rows/columns
|
|
6855
6897
|
React.useEffect(() => {
|
|
6856
6898
|
// Get rows and columns from table properties (where they're actually stored)
|
|
6857
6899
|
const currentRows = Number(properties.table?.rows || properties.basic?.rows || 3);
|
|
6858
6900
|
const currentColumns = Number(properties.table?.columns || properties.basic?.columns || 3);
|
|
6859
|
-
const currentCells =
|
|
6901
|
+
const currentCells = normalizedCells;
|
|
6860
6902
|
// Check if we need to update the table structure
|
|
6861
6903
|
const needsUpdate = currentCells.length === 0 ||
|
|
6862
6904
|
currentCells.length !== currentRows ||
|
|
6863
|
-
(currentCells.length > 0 &&
|
|
6905
|
+
(currentCells.length > 0 && currentCells[0].length !== currentColumns);
|
|
6864
6906
|
if (needsUpdate) {
|
|
6865
6907
|
const newCells = [];
|
|
6866
6908
|
for (let row = 0; row < currentRows; row++) {
|
|
@@ -6869,7 +6911,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6869
6911
|
const cellId = `cell-${row}-${col}`;
|
|
6870
6912
|
// Try to preserve existing components if the cell exists
|
|
6871
6913
|
let existingComponents = [];
|
|
6872
|
-
if (
|
|
6914
|
+
if (currentCells[row] && currentCells[row][col]) {
|
|
6873
6915
|
existingComponents = (currentCells[row][col].components || []).map(ensureComponentHasId);
|
|
6874
6916
|
}
|
|
6875
6917
|
rowCells.push({
|
|
@@ -6887,7 +6929,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6887
6929
|
value: { ...properties, cells: newCells }
|
|
6888
6930
|
});
|
|
6889
6931
|
}
|
|
6890
|
-
}, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns,
|
|
6932
|
+
}, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, normalizedCells, id, onValueChange]);
|
|
6891
6933
|
const handleTableClick = React.useCallback((event) => {
|
|
6892
6934
|
event.stopPropagation();
|
|
6893
6935
|
onSelect?.();
|
|
@@ -6904,7 +6946,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6904
6946
|
const handleComponentDelete = React.useCallback((component, event) => {
|
|
6905
6947
|
event.stopPropagation();
|
|
6906
6948
|
// Find and remove the component from the table cell
|
|
6907
|
-
const updatedCells =
|
|
6949
|
+
const updatedCells = normalizedCells.map((row) => row.map((cell) => {
|
|
6908
6950
|
if (cell.components && cell.components.some((comp) => comp.id === component.id)) {
|
|
6909
6951
|
const filteredComponents = cell.components.filter((comp) => comp.id !== component.id);
|
|
6910
6952
|
return {
|
|
@@ -6913,7 +6955,7 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6913
6955
|
};
|
|
6914
6956
|
}
|
|
6915
6957
|
return cell;
|
|
6916
|
-
})
|
|
6958
|
+
}));
|
|
6917
6959
|
// Update the table with the modified cells
|
|
6918
6960
|
if (onValueChange) {
|
|
6919
6961
|
onValueChange({
|
|
@@ -6923,13 +6965,13 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6923
6965
|
}
|
|
6924
6966
|
// Don't call parent delete handler for table cell components
|
|
6925
6967
|
// The parent delete handler is for deleting entire fields, not components within table cells
|
|
6926
|
-
}, [onComponentDelete, properties, onValueChange, id]);
|
|
6968
|
+
}, [onComponentDelete, normalizedCells, properties, onValueChange, id]);
|
|
6927
6969
|
// CRITICAL FIX: Ensure all table cell components have proper IDs with table and cell position
|
|
6928
6970
|
// Use useMemo to prevent ID regeneration on every render
|
|
6929
6971
|
const cellsWithIds = React.useMemo(() => {
|
|
6930
|
-
if (
|
|
6972
|
+
if (normalizedCells.length === 0)
|
|
6931
6973
|
return [];
|
|
6932
|
-
return
|
|
6974
|
+
return normalizedCells.map((row, rowIndex) => row.map((cell, cellIndex) => ({
|
|
6933
6975
|
...cell,
|
|
6934
6976
|
components: (cell.components && Array.isArray(cell.components))
|
|
6935
6977
|
? cell.components.map((comp, compIndex) => {
|
|
@@ -6948,8 +6990,8 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
6948
6990
|
};
|
|
6949
6991
|
})
|
|
6950
6992
|
: []
|
|
6951
|
-
}))
|
|
6952
|
-
}, [
|
|
6993
|
+
})));
|
|
6994
|
+
}, [normalizedCells, id]); // Only recalculate if cells or table ID changes
|
|
6953
6995
|
// CRITICAL FIX: Update the parent component with the cells that have proper IDs
|
|
6954
6996
|
// Skip this in package to prevent flickering - cells are managed by parent
|
|
6955
6997
|
// useEffect(() => {
|