df-ae-forms-package 1.1.1 → 1.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/dist/index.esm.js +229 -78
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +229 -78
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4243,6 +4243,33 @@ const ComponentSubmissionActions = ({ component }) => {
|
|
|
4243
4243
|
return (jsxRuntime.jsx("div", { className: "component-submission-actions", children: jsxRuntime.jsxs("div", { className: "actions-content", children: [hasNotes && (jsxRuntime.jsx("div", { className: "notes-summary-section", children: jsxRuntime.jsxs("div", { className: "notes-full-text", children: [jsxRuntime.jsx("span", { className: "notes-label", children: "Notes:" }), " ", notes] }) })), hasAttachments && (jsxRuntime.jsx("div", { className: "attachments-section", children: jsxRuntime.jsx(SubmissionAttachmentThumbnails, { attachments: attachments }) }))] }) }));
|
|
4244
4244
|
};
|
|
4245
4245
|
|
|
4246
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
4247
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
4248
|
+
function ensureStringId$2(id) {
|
|
4249
|
+
if (!id)
|
|
4250
|
+
return '';
|
|
4251
|
+
if (typeof id === 'string') {
|
|
4252
|
+
if (id.includes('[object Object]'))
|
|
4253
|
+
return '';
|
|
4254
|
+
return id;
|
|
4255
|
+
}
|
|
4256
|
+
if (typeof id === 'object' && id !== null) {
|
|
4257
|
+
if (id.$oid)
|
|
4258
|
+
return String(id.$oid);
|
|
4259
|
+
if (id._id)
|
|
4260
|
+
return ensureStringId$2(id._id);
|
|
4261
|
+
try {
|
|
4262
|
+
const str = id.toString();
|
|
4263
|
+
if (str && str !== '[object Object]')
|
|
4264
|
+
return str;
|
|
4265
|
+
return JSON.stringify(id);
|
|
4266
|
+
}
|
|
4267
|
+
catch (e) {
|
|
4268
|
+
return 'id-error';
|
|
4269
|
+
}
|
|
4270
|
+
}
|
|
4271
|
+
return String(id);
|
|
4272
|
+
}
|
|
4246
4273
|
const DraggableGridComponent = ({ component, selectedComponent, mode, onComponentSelect, onComponentDelete, onComponentEdit, renderFormComponent, isOverlay = false, formData = {}, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
|
|
4247
4274
|
const formValue = formData[component.id];
|
|
4248
4275
|
const isVisible = shouldShowComponent ? shouldShowComponent(component.id) : true;
|
|
@@ -4494,7 +4521,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4494
4521
|
let entryComponent = entry.components?.[componentIndex];
|
|
4495
4522
|
if (!entryComponent) {
|
|
4496
4523
|
// Use entry.id (which is unique) instead of entryIndex to prevent data collisions
|
|
4497
|
-
const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
|
|
4524
|
+
const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
|
|
4498
4525
|
entryComponent = {
|
|
4499
4526
|
...templateComponent,
|
|
4500
4527
|
id: uniqueId,
|
|
@@ -4507,7 +4534,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4507
4534
|
else {
|
|
4508
4535
|
entryComponent = {
|
|
4509
4536
|
...entryComponent,
|
|
4510
|
-
id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
|
|
4537
|
+
id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4511
4538
|
basic: {
|
|
4512
4539
|
...entryComponent.basic,
|
|
4513
4540
|
showLabel: columnView // Show label in column view
|
|
@@ -4566,7 +4593,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4566
4593
|
position: 'sticky',
|
|
4567
4594
|
bottom: 0,
|
|
4568
4595
|
zIndex: 5
|
|
4569
|
-
}, children: jsxRuntime.jsxs("button", { onClick: () => {
|
|
4596
|
+
}, children: jsxRuntime.jsxs("button", { onClick: (e) => {
|
|
4597
|
+
e.stopPropagation();
|
|
4598
|
+
console.log('[TableView] Add Entry button clicked (grid view)', 'entries:', dataEntries.length, 'max:', maxEntries);
|
|
4599
|
+
onAddEntry();
|
|
4600
|
+
}, disabled: dataEntries.length >= maxEntries, style: {
|
|
4570
4601
|
padding: '8px 16px',
|
|
4571
4602
|
backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',
|
|
4572
4603
|
color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',
|
|
@@ -4631,7 +4662,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4631
4662
|
comp.basic?.label === templateComponent.basic?.label);
|
|
4632
4663
|
}
|
|
4633
4664
|
if (!entryComponent) {
|
|
4634
|
-
const uniqueId = `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`;
|
|
4665
|
+
const uniqueId = `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`;
|
|
4635
4666
|
entryComponent = {
|
|
4636
4667
|
...templateComponent,
|
|
4637
4668
|
id: uniqueId,
|
|
@@ -4644,7 +4675,7 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4644
4675
|
else {
|
|
4645
4676
|
entryComponent = {
|
|
4646
4677
|
...entryComponent,
|
|
4647
|
-
id: entryComponent.id || `${templateComponent.id || 'comp'}-${entry.id}-${componentIndex}`,
|
|
4678
|
+
id: ensureStringId$2(entryComponent.id) || `${ensureStringId$2(templateComponent.id) || 'comp'}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4648
4679
|
basic: {
|
|
4649
4680
|
...entryComponent.basic,
|
|
4650
4681
|
showLabel: columnView // Show label in column view, hide in grid view
|
|
@@ -4688,7 +4719,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4688
4719
|
borderRadius: '8px',
|
|
4689
4720
|
display: 'flex',
|
|
4690
4721
|
justifyContent: 'center'
|
|
4691
|
-
}, children: jsxRuntime.jsxs("button", { onClick: () => {
|
|
4722
|
+
}, children: jsxRuntime.jsxs("button", { onClick: (e) => {
|
|
4723
|
+
e.stopPropagation();
|
|
4724
|
+
console.log('[TableView] Add Entry button clicked (list view)', 'entries:', dataEntries.length, 'max:', maxEntries);
|
|
4725
|
+
onAddEntry();
|
|
4726
|
+
}, disabled: dataEntries.length >= maxEntries, style: {
|
|
4692
4727
|
padding: '8px 16px',
|
|
4693
4728
|
backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',
|
|
4694
4729
|
color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',
|
|
@@ -4712,10 +4747,11 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
|
|
|
4712
4747
|
const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueChange, onSelect, isSelected = false, className = '', onDataGridSelect, onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, renderFormComponent, onEntryAdd, onEntryRemove, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
|
|
4713
4748
|
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
|
4714
4749
|
const hasInitialized = React.useRef(false);
|
|
4750
|
+
const gridId = ensureStringId$2(id) || properties._id || (typeof id === 'string' ? id : 'datagrid-id');
|
|
4715
4751
|
// Get all components in the grid and sanitize them to ensure no data leaks into templates
|
|
4716
4752
|
let gridComponents = (properties.templateComponents || []).map((comp, index) => ({
|
|
4717
4753
|
...comp,
|
|
4718
|
-
id: comp.id || `${
|
|
4754
|
+
id: ensureStringId$2(comp.id) || `${gridId}-template-${index}`, // CRITICAL: Ensure template components have stable string IDs
|
|
4719
4755
|
basic: {
|
|
4720
4756
|
...comp.basic,
|
|
4721
4757
|
// Use an empty string instead of undefined to satisfy component typing
|
|
@@ -4729,7 +4765,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4729
4765
|
gridComponents = dataEntries[0].components.map((comp, index) => ({
|
|
4730
4766
|
...comp,
|
|
4731
4767
|
// Remove entry suffix for template, use stable ID if missing
|
|
4732
|
-
id: comp.id
|
|
4768
|
+
id: ensureStringId$2(comp.id).replace(/-entry-.*$/, '') || `${gridId}-template-${index}`,
|
|
4733
4769
|
basic: {
|
|
4734
4770
|
...comp.basic,
|
|
4735
4771
|
// Clear any data values while keeping types happy
|
|
@@ -4772,7 +4808,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4772
4808
|
index: 0,
|
|
4773
4809
|
components: gridComponents.map((comp, componentIndex) => ({
|
|
4774
4810
|
...comp,
|
|
4775
|
-
id: `${comp.id}-${newEntryId}-${componentIndex}`,
|
|
4811
|
+
id: `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`,
|
|
4776
4812
|
basic: {
|
|
4777
4813
|
...comp.basic,
|
|
4778
4814
|
showLabel: false // Hide label in datagrid cells
|
|
@@ -4827,8 +4863,10 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4827
4863
|
// Update existing component with new template properties while ensuring unique ID and preserving form values
|
|
4828
4864
|
const updatedComponent = {
|
|
4829
4865
|
...templateComp,
|
|
4830
|
-
// Preserve existing ID or generate one if missing
|
|
4831
|
-
id: existingComponent.id
|
|
4866
|
+
// Preserve existing ID (ensure it's a string) or generate one if missing
|
|
4867
|
+
id: (existingComponent.id && typeof existingComponent.id === 'string')
|
|
4868
|
+
? existingComponent.id
|
|
4869
|
+
: `${ensureStringId$2(templateComp.id)}-${ensureStringId$2(entry.id)}-${componentIndex}`,
|
|
4832
4870
|
basic: {
|
|
4833
4871
|
...templateComp.basic,
|
|
4834
4872
|
showLabel: false, // Hide label in datagrid cells
|
|
@@ -4842,7 +4880,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4842
4880
|
// Create new component based on template
|
|
4843
4881
|
// Only for NEW components in existing entries (e.g. column added) do we generate a new ID
|
|
4844
4882
|
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
|
|
4845
|
-
const newId = `${templateComp.id}-${uniqueSuffix}-${componentIndex}`;
|
|
4883
|
+
const newId = `${ensureStringId$2(templateComp.id)}-${uniqueSuffix}-${componentIndex}`;
|
|
4846
4884
|
const newComponent = {
|
|
4847
4885
|
...templateComp,
|
|
4848
4886
|
id: newId,
|
|
@@ -4937,25 +4975,27 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4937
4975
|
// In edit/preview modes, don't handle value changes as components are read-only
|
|
4938
4976
|
}, [mode, onValueChange]);
|
|
4939
4977
|
const handleAddEntry = React.useCallback(() => {
|
|
4940
|
-
console.log('[DfFormDataGrid] handleAddEntry called');
|
|
4941
|
-
|
|
4942
|
-
|
|
4978
|
+
console.log('[DfFormDataGrid] handleAddEntry called - Component ID:', id);
|
|
4979
|
+
// Safety check: ensure we have entries array
|
|
4980
|
+
const currentEntries = Array.isArray(properties.entries) ? properties.entries : [];
|
|
4981
|
+
console.log('[DfFormDataGrid] gridComponents:', gridComponents.length);
|
|
4982
|
+
console.log('[DfFormDataGrid] current entries count:', currentEntries.length);
|
|
4943
4983
|
console.log('[DfFormDataGrid] onValueChange exists:', !!onValueChange);
|
|
4944
4984
|
// Use timestamp and random string to ensure uniqueness even if entries are deleted
|
|
4945
4985
|
const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
|
|
4946
4986
|
const newEntryId = `entry-${uniqueSuffix}`;
|
|
4947
4987
|
const newEntry = {
|
|
4948
4988
|
id: newEntryId,
|
|
4949
|
-
index:
|
|
4989
|
+
index: currentEntries.length,
|
|
4950
4990
|
components: gridComponents.map((comp, componentIndex) => {
|
|
4951
|
-
const componentId = `${comp.id}-${newEntryId}-${componentIndex}`;
|
|
4991
|
+
const componentId = `${ensureStringId$2(comp.id)}-${newEntryId}-${componentIndex}`;
|
|
4952
4992
|
return {
|
|
4953
4993
|
...comp,
|
|
4954
4994
|
// Use the unique entry ID in the component ID to prevent collisions
|
|
4955
4995
|
id: componentId,
|
|
4956
4996
|
basic: {
|
|
4957
4997
|
...comp.basic,
|
|
4958
|
-
value: '', //
|
|
4998
|
+
value: comp.basic?.defaultValue || '', // Use defaultValue if available, else empty
|
|
4959
4999
|
showLabel: false // Hide label in datagrid cells
|
|
4960
5000
|
}
|
|
4961
5001
|
};
|
|
@@ -4963,31 +5003,41 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
|
|
|
4963
5003
|
styles: {}
|
|
4964
5004
|
};
|
|
4965
5005
|
console.log('[DfFormDataGrid] newEntry created:', newEntry.id, 'with', newEntry.components.length, 'components');
|
|
4966
|
-
const updatedEntries = [...
|
|
5006
|
+
const updatedEntries = [...currentEntries, newEntry];
|
|
4967
5007
|
console.log('[DfFormDataGrid] updatedEntries count:', updatedEntries.length);
|
|
4968
5008
|
if (onValueChange) {
|
|
4969
|
-
console.log('[DfFormDataGrid] calling onValueChange with updated
|
|
5009
|
+
console.log('[DfFormDataGrid] calling onValueChange with updated datagrid structure - Entries:', updatedEntries.length);
|
|
4970
5010
|
onValueChange({
|
|
4971
|
-
id,
|
|
4972
|
-
value: {
|
|
5011
|
+
id: gridId, // Use sanitized gridId
|
|
5012
|
+
value: {
|
|
5013
|
+
...properties,
|
|
5014
|
+
entries: updatedEntries
|
|
5015
|
+
}
|
|
4973
5016
|
});
|
|
5017
|
+
// Notify parent if callback provided
|
|
5018
|
+
if (onEntryAdd) {
|
|
5019
|
+
console.log('[DfFormDataGrid] calling onEntryAdd callback');
|
|
5020
|
+
onEntryAdd();
|
|
5021
|
+
}
|
|
4974
5022
|
}
|
|
4975
5023
|
else {
|
|
4976
|
-
console.
|
|
5024
|
+
console.warn('[DfFormDataGrid] Cannot add entry: onValueChange is missing');
|
|
4977
5025
|
}
|
|
4978
|
-
|
|
4979
|
-
}, [properties, onValueChange, id, onEntryAdd, gridComponents]);
|
|
5026
|
+
}, [onValueChange, properties, gridId, gridComponents, onEntryAdd]);
|
|
4980
5027
|
const handleRemoveEntry = React.useCallback((entryIndex) => {
|
|
4981
|
-
|
|
5028
|
+
// Safety check: ensure we have entries array
|
|
5029
|
+
const currentEntries = Array.isArray(properties.entries) ? properties.entries : [];
|
|
5030
|
+
const updatedEntries = currentEntries
|
|
4982
5031
|
.filter((_, index) => index !== entryIndex)
|
|
4983
5032
|
.map((entry, index) => ({ ...entry, index })); // Only update index, preserve unique ID
|
|
4984
5033
|
if (onValueChange) {
|
|
5034
|
+
console.log('[DfFormDataGrid] Removing entry at index:', entryIndex, 'New count:', updatedEntries.length);
|
|
4985
5035
|
onValueChange({
|
|
4986
|
-
id,
|
|
5036
|
+
id: gridId, // Use sanitized gridId
|
|
4987
5037
|
value: { ...properties, entries: updatedEntries }
|
|
4988
5038
|
});
|
|
4989
5039
|
}
|
|
4990
|
-
}, [properties, onValueChange,
|
|
5040
|
+
}, [properties.entries, onValueChange, gridId, properties]);
|
|
4991
5041
|
// Use our own render function to ensure proper onComponentUpdate handling
|
|
4992
5042
|
const renderComponent = React.useCallback((field, hideLabel = false) => {
|
|
4993
5043
|
const formValue = mode === 'test' ? (formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '')) : ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '');
|
|
@@ -5312,6 +5362,37 @@ const DfFormSection = ({ id, properties, mode = 'edit', formData = {}, onValueCh
|
|
|
5312
5362
|
|
|
5313
5363
|
// Dynamic imports to avoid circular dependencies
|
|
5314
5364
|
const DfFormTable$1 = React.lazy(() => Promise.resolve().then(function () { return dfFormTable; }));
|
|
5365
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
5366
|
+
// This is used globally in this file to prevent [object Object] corruption
|
|
5367
|
+
const ensureStringId$1 = (id) => {
|
|
5368
|
+
if (!id)
|
|
5369
|
+
return '';
|
|
5370
|
+
if (typeof id === 'string') {
|
|
5371
|
+
// If the ID is already corrupted, return empty to trigger regeneration
|
|
5372
|
+
if (id.includes('[object Object]'))
|
|
5373
|
+
return '';
|
|
5374
|
+
return id;
|
|
5375
|
+
}
|
|
5376
|
+
if (typeof id === 'object' && id !== null) {
|
|
5377
|
+
if (id.$oid)
|
|
5378
|
+
return String(id.$oid);
|
|
5379
|
+
if (id._id)
|
|
5380
|
+
return ensureStringId$1(id._id);
|
|
5381
|
+
// Fallback for other object structures that might be IDs
|
|
5382
|
+
try {
|
|
5383
|
+
// If it has a toString that isn't the default, use it
|
|
5384
|
+
const str = id.toString();
|
|
5385
|
+
if (str && str !== '[object Object]')
|
|
5386
|
+
return str;
|
|
5387
|
+
// Otherwise, use a hash or just JSON
|
|
5388
|
+
return JSON.stringify(id);
|
|
5389
|
+
}
|
|
5390
|
+
catch (e) {
|
|
5391
|
+
return 'id-error';
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
return String(id);
|
|
5395
|
+
};
|
|
5315
5396
|
// Normalize a table row from API format (object with numeric keys) into a proper array.
|
|
5316
5397
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
5317
5398
|
const normalizeTableRow = (row) => {
|
|
@@ -5357,16 +5438,17 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5357
5438
|
// Recursive function to initialize values from nested components
|
|
5358
5439
|
const initializeComponentValues = (components, values) => {
|
|
5359
5440
|
components.forEach(component => {
|
|
5360
|
-
|
|
5441
|
+
const componentId = ensureStringId$1(component.id);
|
|
5442
|
+
if (componentId) {
|
|
5361
5443
|
// ALWAYS prioritize existing form state (values param) if it exists
|
|
5362
|
-
if (values[
|
|
5363
|
-
// Then
|
|
5364
|
-
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined
|
|
5365
|
-
values[
|
|
5444
|
+
if (values[componentId] !== undefined) ;
|
|
5445
|
+
// Then use captured value in basic.value
|
|
5446
|
+
else if (component.basic && 'value' in component.basic && component.basic.value !== undefined) {
|
|
5447
|
+
values[componentId] = component.basic.value;
|
|
5366
5448
|
}
|
|
5367
|
-
// Then
|
|
5368
|
-
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined
|
|
5369
|
-
values[
|
|
5449
|
+
// Then use defaultValue
|
|
5450
|
+
else if (component.basic && 'defaultValue' in component.basic && component.basic.defaultValue !== undefined) {
|
|
5451
|
+
values[componentId] = component.basic.defaultValue;
|
|
5370
5452
|
}
|
|
5371
5453
|
// Only then default to empty
|
|
5372
5454
|
else {
|
|
@@ -5436,12 +5518,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5436
5518
|
// Helper to extract notes and attachments recursively
|
|
5437
5519
|
const extractNotesAndAttachments = (components) => {
|
|
5438
5520
|
components.forEach(comp => {
|
|
5439
|
-
|
|
5521
|
+
const componentId = ensureStringId$1(comp.id);
|
|
5522
|
+
if (componentId) {
|
|
5440
5523
|
if (comp.basic?.notes || comp.basic?.comments) {
|
|
5441
|
-
initialNotes[
|
|
5524
|
+
initialNotes[componentId] = comp.basic?.notes || comp.basic?.comments;
|
|
5442
5525
|
}
|
|
5443
5526
|
if (comp.basic?.attachments) {
|
|
5444
|
-
initialAttachments[
|
|
5527
|
+
initialAttachments[componentId] = comp.basic.attachments;
|
|
5445
5528
|
}
|
|
5446
5529
|
}
|
|
5447
5530
|
// Recurse
|
|
@@ -5463,27 +5546,43 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5463
5546
|
};
|
|
5464
5547
|
// Validate component IDs for uniqueness without mutating original props
|
|
5465
5548
|
const getValidatedComponents = (components, parentId) => {
|
|
5549
|
+
const parentIdStr = parentId ? ensureStringId$1(parentId) : '';
|
|
5466
5550
|
return components.map((component, index) => {
|
|
5467
5551
|
let validatedComponent = { ...component };
|
|
5468
|
-
// Ensure component has
|
|
5469
|
-
|
|
5552
|
+
// Ensure component has a valid string ID
|
|
5553
|
+
let currentId = validatedComponent.id;
|
|
5554
|
+
// CRITICAL: Reject any ID that is not a string, is empty, or contains "[object Object]"
|
|
5555
|
+
let isIdValid = typeof currentId === 'string' &&
|
|
5556
|
+
currentId.trim() !== '' &&
|
|
5557
|
+
!currentId.includes('[object Object]');
|
|
5558
|
+
if (!isIdValid) {
|
|
5559
|
+
// If it's an object ID (but not a corrupted string), convert it to string
|
|
5560
|
+
if (currentId && typeof currentId === 'object') {
|
|
5561
|
+
const convertedId = ensureStringId$1(currentId);
|
|
5562
|
+
if (convertedId && !convertedId.includes('[object Object]')) {
|
|
5563
|
+
validatedComponent.id = convertedId;
|
|
5564
|
+
isIdValid = true;
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
if (!isIdValid) {
|
|
5470
5569
|
// Determine a base name for the ID
|
|
5471
5570
|
const name = validatedComponent.name || 'component';
|
|
5472
5571
|
const label = validatedComponent.basic?.label || '';
|
|
5473
5572
|
const safeLabel = label.replace(/[^a-zA-Z0-9]/g, '').toLowerCase().substring(0, 10);
|
|
5474
5573
|
// Generate a stable unique ID if parentId is provided, otherwise fallback to semi-stable
|
|
5475
|
-
if (
|
|
5476
|
-
validatedComponent.id = `${
|
|
5574
|
+
if (parentIdStr) {
|
|
5575
|
+
validatedComponent.id = `${parentIdStr}-${name}-${index}`;
|
|
5477
5576
|
}
|
|
5478
5577
|
else {
|
|
5479
5578
|
// For root components, use label if available for stability
|
|
5480
5579
|
const labelPart = safeLabel ? `-${safeLabel}` : '';
|
|
5481
5580
|
validatedComponent.id = `${name}${labelPart}-${index}`;
|
|
5482
5581
|
}
|
|
5483
|
-
console.warn(`[DfFormPreview]
|
|
5582
|
+
console.warn(`[DfFormPreview] Fixed missing/invalid ID: ${validatedComponent.id}`);
|
|
5484
5583
|
}
|
|
5485
5584
|
else {
|
|
5486
|
-
//
|
|
5585
|
+
// ID is a valid string, check for duplicates
|
|
5487
5586
|
if (seenIds.has(validatedComponent.id)) {
|
|
5488
5587
|
console.error(`[DfFormPreview] Duplicate component ID detected: ${validatedComponent.id}`);
|
|
5489
5588
|
// Generate a unique ID for duplicate - using index to keep it somewhat stable
|
|
@@ -5503,7 +5602,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5503
5602
|
return normalizedRow.map((cell, cellIndex) => {
|
|
5504
5603
|
if (cell && cell.components && Array.isArray(cell.components)) {
|
|
5505
5604
|
// Stable ID for table cells: tableId-row-X-cell-Y
|
|
5506
|
-
const cellContextId = `${validatedComponent.id}-row-${rowIndex}-cell-${cellIndex}`;
|
|
5605
|
+
const cellContextId = `${ensureStringId$1(validatedComponent.id)}-row-${rowIndex}-cell-${cellIndex}`;
|
|
5507
5606
|
return {
|
|
5508
5607
|
...cell,
|
|
5509
5608
|
components: getValidatedComponents(cell.components, cellContextId)
|
|
@@ -5519,14 +5618,21 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5519
5618
|
validatedComponent.entries = validatedComponent.entries.map((entry) => {
|
|
5520
5619
|
if (entry && entry.components && Array.isArray(entry.components)) {
|
|
5521
5620
|
// Stable ID for datagrid entries: datagridId-entryId or using entry.id
|
|
5621
|
+
const entryId = entry.id ? ensureStringId$1(entry.id) : `${ensureStringId$1(validatedComponent.id)}-entry-${entry.index}`;
|
|
5522
5622
|
return {
|
|
5523
5623
|
...entry,
|
|
5524
|
-
|
|
5624
|
+
id: entryId, // Ensure entry itself has a string ID
|
|
5625
|
+
components: getValidatedComponents(entry.components, entryId)
|
|
5525
5626
|
};
|
|
5526
5627
|
}
|
|
5527
5628
|
return entry;
|
|
5528
5629
|
});
|
|
5529
5630
|
}
|
|
5631
|
+
// CRITICAL: Also validate templateComponents for datagrids
|
|
5632
|
+
if (validatedComponent.name === 'datagrid' && validatedComponent.templateComponents && Array.isArray(validatedComponent.templateComponents)) {
|
|
5633
|
+
const datagridId = ensureStringId$1(validatedComponent.id);
|
|
5634
|
+
validatedComponent.templateComponents = getValidatedComponents(validatedComponent.templateComponents, `${datagridId}-template`);
|
|
5635
|
+
}
|
|
5530
5636
|
return validatedComponent;
|
|
5531
5637
|
});
|
|
5532
5638
|
};
|
|
@@ -5534,8 +5640,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
5534
5640
|
let validatedFormComponents = localFormComponents;
|
|
5535
5641
|
if (localFormComponents && localFormComponents.length > 0) {
|
|
5536
5642
|
validatedFormComponents = getValidatedComponents(localFormComponents);
|
|
5537
|
-
//
|
|
5643
|
+
// Synchronize local state if components were mutated (IDs added/fixed)
|
|
5538
5644
|
if (JSON.stringify(validatedFormComponents) !== JSON.stringify(localFormComponents)) {
|
|
5645
|
+
console.log('[DfFormPreview] Synchronizing local components after ID validation');
|
|
5646
|
+
setLocalFormComponents(validatedFormComponents);
|
|
5539
5647
|
onFormDataChange?.(validatedFormComponents);
|
|
5540
5648
|
}
|
|
5541
5649
|
}
|
|
@@ -6314,13 +6422,10 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6314
6422
|
const componentIdCacheRef = React.useRef(new Map());
|
|
6315
6423
|
const componentCounterRef = React.useRef(0);
|
|
6316
6424
|
const renderFormComponent = (component) => {
|
|
6317
|
-
// CRITICAL: Ensure component has a valid unique ID
|
|
6425
|
+
// CRITICAL: Ensure component has a valid unique string ID
|
|
6318
6426
|
// NEVER regenerate IDs - always use existing or cached ID
|
|
6319
|
-
let finalComponentId;
|
|
6320
|
-
if (
|
|
6321
|
-
// Component already has an ID - use it (most common case)
|
|
6322
|
-
finalComponentId = component.id;
|
|
6323
|
-
}
|
|
6427
|
+
let finalComponentId = ensureStringId$1(component.id);
|
|
6428
|
+
if (finalComponentId && finalComponentId.trim() !== '') ;
|
|
6324
6429
|
else {
|
|
6325
6430
|
// Component is missing an ID - need to generate and cache it
|
|
6326
6431
|
// Create a stable cache key using component properties that don't change
|
|
@@ -6450,12 +6555,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6450
6555
|
return renderFormComponent(field);
|
|
6451
6556
|
}, onNotesChange: (componentId, notes) => {
|
|
6452
6557
|
// Handle notes change for table cell components
|
|
6558
|
+
const targetTableId = ensureStringId$1(component.id);
|
|
6453
6559
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6454
|
-
if (comp.id ===
|
|
6560
|
+
if (ensureStringId$1(comp.id) === targetTableId && comp.cells) {
|
|
6455
6561
|
const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
6456
6562
|
if (cell.components) {
|
|
6457
6563
|
const updatedCellComponents = cell.components.map((cellComp) => {
|
|
6458
|
-
if (cellComp.id === componentId) {
|
|
6564
|
+
if (ensureStringId$1(cellComp.id) === componentId) {
|
|
6459
6565
|
return {
|
|
6460
6566
|
...cellComp,
|
|
6461
6567
|
basic: {
|
|
@@ -6477,12 +6583,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6477
6583
|
onFormDataChange?.(updatedComponents);
|
|
6478
6584
|
}, onAttachmentChange: (componentId, attachments) => {
|
|
6479
6585
|
// Handle attachment change for table cell components
|
|
6586
|
+
const targetTableId = ensureStringId$1(component.id);
|
|
6480
6587
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6481
|
-
if (comp.id ===
|
|
6588
|
+
if (ensureStringId$1(comp.id) === targetTableId && comp.cells) {
|
|
6482
6589
|
const updatedCells = comp.cells.map((row) => normalizeTableRow(row).map((cell) => {
|
|
6483
6590
|
if (cell.components) {
|
|
6484
6591
|
const updatedCellComponents = cell.components.map((cellComp) => {
|
|
6485
|
-
if (cellComp.id === componentId) {
|
|
6592
|
+
if (ensureStringId$1(cellComp.id) === componentId) {
|
|
6486
6593
|
return {
|
|
6487
6594
|
...cellComp,
|
|
6488
6595
|
basic: {
|
|
@@ -6507,12 +6614,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6507
6614
|
return (jsxRuntime.jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
|
|
6508
6615
|
handleComponentNotesChange(componentId, notes);
|
|
6509
6616
|
// Handle notes change for datagrid entry components
|
|
6617
|
+
const targetGridId = ensureStringId$1(component.id);
|
|
6510
6618
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6511
|
-
if (comp.id ===
|
|
6619
|
+
if (ensureStringId$1(comp.id) === targetGridId && comp.entries) {
|
|
6512
6620
|
const updatedEntries = comp.entries.map((entry) => {
|
|
6513
6621
|
if (entry.components) {
|
|
6514
6622
|
const updatedEntryComponents = entry.components.map((entryComp) => {
|
|
6515
|
-
if (entryComp.id === componentId) {
|
|
6623
|
+
if (ensureStringId$1(entryComp.id) === componentId) {
|
|
6516
6624
|
return {
|
|
6517
6625
|
...entryComp,
|
|
6518
6626
|
basic: {
|
|
@@ -6535,12 +6643,13 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6535
6643
|
}, onAttachmentChange: (componentId, attachments) => {
|
|
6536
6644
|
handleComponentAttachmentChange(componentId, attachments);
|
|
6537
6645
|
// Handle attachment change for datagrid entry components
|
|
6646
|
+
const targetGridId = ensureStringId$1(component.id);
|
|
6538
6647
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6539
|
-
if (comp.id ===
|
|
6648
|
+
if (ensureStringId$1(comp.id) === targetGridId && comp.entries) {
|
|
6540
6649
|
const updatedEntries = comp.entries.map((entry) => {
|
|
6541
6650
|
if (entry.components) {
|
|
6542
6651
|
const updatedEntryComponents = entry.components.map((entryComp) => {
|
|
6543
|
-
if (entryComp.id === componentId) {
|
|
6652
|
+
if (ensureStringId$1(entryComp.id) === componentId) {
|
|
6544
6653
|
return {
|
|
6545
6654
|
...entryComp,
|
|
6546
6655
|
basic: {
|
|
@@ -6561,13 +6670,16 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6561
6670
|
});
|
|
6562
6671
|
onFormDataChange?.(updatedComponents);
|
|
6563
6672
|
}, onValueChange: (change) => {
|
|
6564
|
-
|
|
6673
|
+
const changeId = ensureStringId$1(change.id);
|
|
6674
|
+
const componentId = ensureStringId$1(component.id);
|
|
6675
|
+
console.log(`[DfFormPreview] datagrid onValueChange - Target: ${changeId}, Component: ${componentId}`);
|
|
6565
6676
|
// Handle datagrid value changes (entries updates)
|
|
6566
|
-
if (
|
|
6677
|
+
if (changeId === componentId && change.value && typeof change.value === 'object' && 'entries' in change.value) {
|
|
6567
6678
|
console.log('[DfFormPreview] datagrid entries update - entries count:', change.value.entries?.length);
|
|
6568
6679
|
// Update localFormComponents with new entries structure
|
|
6569
6680
|
const updatedComponents = localFormComponents.map(comp => {
|
|
6570
|
-
|
|
6681
|
+
const currentCompId = ensureStringId$1(comp.id);
|
|
6682
|
+
if (currentCompId === componentId) {
|
|
6571
6683
|
return {
|
|
6572
6684
|
...comp,
|
|
6573
6685
|
...change.value
|
|
@@ -6578,26 +6690,37 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
|
|
|
6578
6690
|
// CRITICAL: Update local state immediately so new entries render without Angular round-trip
|
|
6579
6691
|
setLocalFormComponents(updatedComponents);
|
|
6580
6692
|
onFormDataChange?.(updatedComponents);
|
|
6581
|
-
// Also update formValues for nested components
|
|
6693
|
+
// Also update formValues for nested components to prevent undefined values
|
|
6582
6694
|
if (change.value.entries && Array.isArray(change.value.entries)) {
|
|
6695
|
+
const newValues = { ...formValues };
|
|
6696
|
+
let valuesChanged = false;
|
|
6583
6697
|
change.value.entries.forEach((entry) => {
|
|
6584
6698
|
if (entry.components && Array.isArray(entry.components)) {
|
|
6585
6699
|
entry.components.forEach((nestedComp) => {
|
|
6586
|
-
const
|
|
6587
|
-
if (
|
|
6588
|
-
|
|
6589
|
-
|
|
6700
|
+
const nestedId = ensureStringId$1(nestedComp.id);
|
|
6701
|
+
if (!nestedId)
|
|
6702
|
+
return;
|
|
6703
|
+
if (newValues[nestedId] === undefined) {
|
|
6704
|
+
// Initialize with defaultValue if available, otherwise empty string/array
|
|
6590
6705
|
const defaultValue = nestedComp.basic?.defaultValue;
|
|
6591
6706
|
if (defaultValue !== undefined) {
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6707
|
+
newValues[nestedId] = defaultValue;
|
|
6708
|
+
}
|
|
6709
|
+
else if (nestedComp.name === 'checkbox' || nestedComp.name === 'select') {
|
|
6710
|
+
newValues[nestedId] = [];
|
|
6596
6711
|
}
|
|
6712
|
+
else {
|
|
6713
|
+
newValues[nestedId] = '';
|
|
6714
|
+
}
|
|
6715
|
+
valuesChanged = true;
|
|
6597
6716
|
}
|
|
6598
6717
|
});
|
|
6599
6718
|
}
|
|
6600
6719
|
});
|
|
6720
|
+
if (valuesChanged) {
|
|
6721
|
+
console.log('[DfFormPreview] Initializing form values for new datagrid entries');
|
|
6722
|
+
setFormValues(newValues);
|
|
6723
|
+
}
|
|
6601
6724
|
}
|
|
6602
6725
|
}
|
|
6603
6726
|
else {
|
|
@@ -6806,6 +6929,32 @@ const DfFormComments = ({ comment = '', onSave, placeholder = 'Enter your reason
|
|
|
6806
6929
|
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 }) }) }) })] }));
|
|
6807
6930
|
};
|
|
6808
6931
|
|
|
6932
|
+
// Helper to ensure an ID is a stable string, handling MongoDB-style object IDs
|
|
6933
|
+
const ensureStringId = (id) => {
|
|
6934
|
+
if (!id)
|
|
6935
|
+
return '';
|
|
6936
|
+
if (typeof id === 'string') {
|
|
6937
|
+
if (id.includes('[object Object]'))
|
|
6938
|
+
return '';
|
|
6939
|
+
return id;
|
|
6940
|
+
}
|
|
6941
|
+
if (typeof id === 'object' && id !== null) {
|
|
6942
|
+
if (id.$oid)
|
|
6943
|
+
return String(id.$oid);
|
|
6944
|
+
if (id._id)
|
|
6945
|
+
return ensureStringId(id._id);
|
|
6946
|
+
try {
|
|
6947
|
+
const str = id.toString();
|
|
6948
|
+
if (str && str !== '[object Object]')
|
|
6949
|
+
return str;
|
|
6950
|
+
return JSON.stringify(id);
|
|
6951
|
+
}
|
|
6952
|
+
catch (e) {
|
|
6953
|
+
return 'id-error';
|
|
6954
|
+
}
|
|
6955
|
+
}
|
|
6956
|
+
return String(id);
|
|
6957
|
+
};
|
|
6809
6958
|
// Normalize a row from the API format (object with numeric keys) into a proper TableCell array.
|
|
6810
6959
|
// The API may return cells as [{"0": {cell}, "1": {cell}}, ...] instead of [[cell, cell], ...].
|
|
6811
6960
|
const normalizeRow = (row) => {
|
|
@@ -7000,13 +7149,15 @@ const DfFormTable = ({ id, properties, mode = 'edit', formData = {}, validationE
|
|
|
7000
7149
|
? cell.components.map((comp, compIndex) => {
|
|
7001
7150
|
// CRITICAL: Only generate ID if it's missing - never regenerate existing IDs
|
|
7002
7151
|
// This prevents component remounting and losing input state
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7152
|
+
const existingId = ensureStringId(comp.id);
|
|
7153
|
+
if (existingId) {
|
|
7154
|
+
// ID already exists and is valid - keep it but ensure it's a string
|
|
7155
|
+
return { ...comp, id: existingId };
|
|
7006
7156
|
}
|
|
7007
7157
|
// Generate unique ID that includes table ID, row, cell, and component index
|
|
7008
7158
|
// This ensures no conflicts with other components
|
|
7009
|
-
const
|
|
7159
|
+
const sanitizedTableId = ensureStringId(id);
|
|
7160
|
+
const uniqueId = `${comp.name || 'component'}-table-${sanitizedTableId}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;
|
|
7010
7161
|
return {
|
|
7011
7162
|
...comp,
|
|
7012
7163
|
id: uniqueId
|