@integry/sdk 4.6.93 → 4.6.95
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/.vscode/launch.json +2 -2
- package/dist/esm/index.csm.js +1 -1
- package/dist/umd/index.umd.js +1 -1
- package/package.json +1 -1
- package/src/features/common/DynamicField/index.ts +19 -8
- package/src/features/common/DynamicTypedField/index.ts +224 -59
- package/src/features/common/DynamicTypedField/styles.module.scss +62 -0
package/package.json
CHANGED
|
@@ -5,7 +5,6 @@ import { TemplateField, NestedObject } from '@/interfaces';
|
|
|
5
5
|
import AppContext from '@/contexts/AppContext';
|
|
6
6
|
import { StoreType } from '@/types/store';
|
|
7
7
|
// import { Input } from '@/components/Input';
|
|
8
|
-
import { LargeLoader } from '@/components/LargeLoader';
|
|
9
8
|
import { Loader } from '@/components/Loader';
|
|
10
9
|
import { MultipurposeField } from '@/components/MultipurposeField';
|
|
11
10
|
import { actionFunctions } from '@/store';
|
|
@@ -141,7 +140,13 @@ const DynamicFields = (props: DynamicFieldsProps) => {
|
|
|
141
140
|
|
|
142
141
|
useEffect(() => {
|
|
143
142
|
fetchDynamicFields();
|
|
144
|
-
}, [
|
|
143
|
+
}, [parentFieldChanged]);
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (!onChangeCallback) {
|
|
147
|
+
fetchDynamicFields();
|
|
148
|
+
}
|
|
149
|
+
}, [dynamicField, endpointData, selectedAuthId]);
|
|
145
150
|
|
|
146
151
|
const getPlaceholder = () => {
|
|
147
152
|
let placeHolderValue = 'Enter text or map to fields...';
|
|
@@ -166,13 +171,19 @@ const DynamicFields = (props: DynamicFieldsProps) => {
|
|
|
166
171
|
});
|
|
167
172
|
|
|
168
173
|
if (onChangeCallback && objectValue !== null) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
// Use the functional update form of setState to ensure we're working with the latest state
|
|
175
|
+
setCustomFieldsData((prevData: any) => {
|
|
176
|
+
const updatedData = {
|
|
177
|
+
...prevData,
|
|
178
|
+
[machineName]: val,
|
|
179
|
+
};
|
|
174
180
|
|
|
175
|
-
|
|
181
|
+
// Call the callback with the updated data
|
|
182
|
+
onChangeCallback(JSON.stringify(updatedData));
|
|
183
|
+
|
|
184
|
+
// Return the updated data to set the state
|
|
185
|
+
return updatedData;
|
|
186
|
+
});
|
|
176
187
|
} else {
|
|
177
188
|
props.setStepMappingData({
|
|
178
189
|
stepId,
|
|
@@ -38,7 +38,7 @@ export type DynamicFieldsProps = {
|
|
|
38
38
|
isDisabled?: boolean;
|
|
39
39
|
onChangeCallback?: (val: any) => void;
|
|
40
40
|
dependsOn?: string[];
|
|
41
|
-
isArray?: boolean;
|
|
41
|
+
isArray?: boolean;
|
|
42
42
|
} & StoreType;
|
|
43
43
|
|
|
44
44
|
interface DynamicDataItem {
|
|
@@ -69,16 +69,37 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
69
69
|
isDisabled = false,
|
|
70
70
|
onChangeCallback = () => null,
|
|
71
71
|
dependsOn = [],
|
|
72
|
-
isArray = false,
|
|
72
|
+
isArray = false,
|
|
73
73
|
} = props;
|
|
74
|
+
|
|
74
75
|
const [dynamicItems, setDynamicItems] = useState<DynamicDataItem[]>([]);
|
|
75
76
|
const [loading, setLoading] = useState<boolean>(true);
|
|
77
|
+
|
|
78
|
+
// For array mode, we'll track multiple sets of field data
|
|
79
|
+
const [fieldSets, setFieldSets] = useState<any[]>(() => {
|
|
80
|
+
if (value) {
|
|
81
|
+
const parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
82
|
+
|
|
83
|
+
if (isArray) {
|
|
84
|
+
// If it's already an array, use it
|
|
85
|
+
if (Array.isArray(parsedValue)) {
|
|
86
|
+
return parsedValue;
|
|
87
|
+
}
|
|
88
|
+
// If it's an object, wrap it in an array
|
|
89
|
+
return [parsedValue];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// For non-array mode, we still initialize with a single object
|
|
93
|
+
return [parsedValue];
|
|
94
|
+
}
|
|
95
|
+
return [{}]; // Start with one empty object
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// For backward compatibility, maintain customFieldsData for the first set
|
|
76
99
|
const [customFieldsData, setCustomFieldsData] = useState<any>(() => {
|
|
77
|
-
// Initialize from value prop if available
|
|
78
100
|
if (value) {
|
|
79
101
|
const parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
80
102
|
|
|
81
|
-
// If isArray is true and the value is an array, extract the first object
|
|
82
103
|
if (isArray && Array.isArray(parsedValue) && parsedValue.length > 0) {
|
|
83
104
|
return parsedValue[0];
|
|
84
105
|
}
|
|
@@ -87,6 +108,7 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
87
108
|
}
|
|
88
109
|
return {};
|
|
89
110
|
});
|
|
111
|
+
|
|
90
112
|
const [
|
|
91
113
|
isErrorOnLoadingCustomFields,
|
|
92
114
|
setIsErrorOnLoadingCustomFields,
|
|
@@ -135,13 +157,13 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
135
157
|
if (Array.isArray(res)) {
|
|
136
158
|
transformedItems = res;
|
|
137
159
|
} else if (res.output && Array.isArray(res.output)) {
|
|
138
|
-
const { idKeyPath, titleKeyPath, typeKeyPath } = props;
|
|
160
|
+
const { idKeyPath, titleKeyPath, typeKeyPath } = props;
|
|
139
161
|
|
|
140
162
|
if (idKeyPath && titleKeyPath) {
|
|
141
163
|
transformedItems = res.output.map((item: any) => ({
|
|
142
|
-
id: resolveValue(idKeyPath, item),
|
|
143
|
-
title: resolveValue(titleKeyPath, item),
|
|
144
|
-
type: 'TEXTFIELD',
|
|
164
|
+
id: resolveValue(idKeyPath, item),
|
|
165
|
+
title: resolveValue(titleKeyPath, item),
|
|
166
|
+
type: 'TEXTFIELD',
|
|
145
167
|
}));
|
|
146
168
|
} else {
|
|
147
169
|
setDynamicItems([]);
|
|
@@ -164,9 +186,8 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
164
186
|
}
|
|
165
187
|
};
|
|
166
188
|
|
|
167
|
-
//
|
|
189
|
+
// Effect for fetching fields
|
|
168
190
|
useEffect(() => {
|
|
169
|
-
// Only fetch fields on initial mount or when parentFieldsChanged changes
|
|
170
191
|
if (dependsOn.length > 0 && !parentFieldsChanged) {
|
|
171
192
|
setLoading(false);
|
|
172
193
|
setIsErrorOnLoadingCustomFields(false);
|
|
@@ -176,51 +197,115 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
176
197
|
fetchDynamicFields();
|
|
177
198
|
fieldsHaveBeenFetched.current = true;
|
|
178
199
|
}
|
|
179
|
-
}, [parentFieldsChanged]);
|
|
200
|
+
}, [parentFieldsChanged]);
|
|
180
201
|
|
|
181
|
-
//
|
|
202
|
+
// Effect for handling external value changes
|
|
182
203
|
useEffect(() => {
|
|
183
|
-
// Only update from props if the value is different from current state
|
|
184
|
-
// AND it's not coming from our own onChange (which would cause a loop)
|
|
185
204
|
if (value && !loading) {
|
|
186
|
-
|
|
205
|
+
const parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
187
206
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
if (isArray) {
|
|
208
|
+
// Handle array values
|
|
209
|
+
const newFieldSets = Array.isArray(parsedValue)
|
|
210
|
+
? parsedValue
|
|
211
|
+
: [parsedValue];
|
|
192
212
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const newValueStr = JSON.stringify(parsedValue);
|
|
213
|
+
// Update fieldSets
|
|
214
|
+
setFieldSets(newFieldSets);
|
|
196
215
|
|
|
197
|
-
|
|
216
|
+
// Update customFieldsData with the first item for backward compatibility
|
|
217
|
+
if (newFieldSets.length > 0) {
|
|
218
|
+
setCustomFieldsData(newFieldSets[0]);
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
// Handle single object value
|
|
198
222
|
setCustomFieldsData(parsedValue);
|
|
223
|
+
setFieldSets([parsedValue]);
|
|
199
224
|
}
|
|
200
225
|
}
|
|
201
226
|
}, [value, loading, isArray]);
|
|
202
227
|
|
|
203
|
-
//
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
228
|
+
// Function to add a new empty set of fields
|
|
229
|
+
const addNewFieldSet = () => {
|
|
230
|
+
setFieldSets((prev) => {
|
|
231
|
+
const newFieldSets = [...prev, {}];
|
|
232
|
+
|
|
233
|
+
// Call parent callbacks with the updated array
|
|
234
|
+
if (onChange) {
|
|
235
|
+
onChange(newFieldSets);
|
|
236
|
+
}
|
|
237
|
+
if (onChangeCallback) {
|
|
238
|
+
onChangeCallback(JSON.stringify(newFieldSets));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return newFieldSets;
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// Function to remove a field set
|
|
246
|
+
const removeFieldSet = (index: number) => {
|
|
247
|
+
if (fieldSets.length <= 1) return; // Don't remove the last set
|
|
248
|
+
|
|
249
|
+
setFieldSets((prev) => {
|
|
250
|
+
const newFieldSets = prev.filter((_, i) => i !== index);
|
|
251
|
+
|
|
252
|
+
// Update customFieldsData if we're removing the first set
|
|
253
|
+
if (index === 0 && newFieldSets.length > 0) {
|
|
254
|
+
setCustomFieldsData(newFieldSets[0]);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Call parent callbacks with the updated array
|
|
258
|
+
if (onChange) {
|
|
259
|
+
onChange(newFieldSets);
|
|
260
|
+
}
|
|
261
|
+
if (onChangeCallback) {
|
|
262
|
+
onChangeCallback(JSON.stringify(newFieldSets));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return newFieldSets;
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// Function to update a specific field in a specific set
|
|
270
|
+
const onFieldSetChange = (
|
|
271
|
+
setIndex: number,
|
|
272
|
+
fieldId: string,
|
|
273
|
+
val: string,
|
|
274
|
+
type: string,
|
|
275
|
+
) => {
|
|
276
|
+
setFieldSets((prev) => {
|
|
277
|
+
const newFieldSets = [...prev];
|
|
278
|
+
|
|
279
|
+
// Create or update the field in the specified set
|
|
280
|
+
newFieldSets[setIndex] = {
|
|
281
|
+
...newFieldSets[setIndex],
|
|
282
|
+
[fieldId]: val,
|
|
210
283
|
};
|
|
211
284
|
|
|
212
|
-
//
|
|
285
|
+
// If this is the first set, also update customFieldsData for backward compatibility
|
|
286
|
+
if (setIndex === 0) {
|
|
287
|
+
setCustomFieldsData(newFieldSets[0]);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Call parent callbacks with the updated array
|
|
213
291
|
if (onChange) {
|
|
214
|
-
onChange(isArray ?
|
|
292
|
+
onChange(isArray ? newFieldSets : newFieldSets[0]);
|
|
215
293
|
}
|
|
216
294
|
if (onChangeCallback) {
|
|
217
|
-
onChangeCallback(
|
|
295
|
+
onChangeCallback(
|
|
296
|
+
JSON.stringify(isArray ? newFieldSets : newFieldSets[0]),
|
|
297
|
+
);
|
|
218
298
|
}
|
|
219
299
|
|
|
220
|
-
return
|
|
300
|
+
return newFieldSets;
|
|
221
301
|
});
|
|
222
302
|
};
|
|
223
303
|
|
|
304
|
+
// For backward compatibility, maintain the original onFieldChange function
|
|
305
|
+
const onFieldChange = (id: string, val: string, type: string) => {
|
|
306
|
+
onFieldSetChange(0, id, val, type);
|
|
307
|
+
};
|
|
308
|
+
|
|
224
309
|
return html`
|
|
225
310
|
<div>
|
|
226
311
|
${loading
|
|
@@ -231,31 +316,111 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
231
316
|
Loading custom fields...
|
|
232
317
|
</div> `
|
|
233
318
|
: html`
|
|
234
|
-
${
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
319
|
+
${isArray
|
|
320
|
+
? dynamicItems.length > 0 &&
|
|
321
|
+
html`
|
|
322
|
+
${fieldSets.map(
|
|
323
|
+
(fieldSet, setIndex) => html`
|
|
324
|
+
<div
|
|
325
|
+
class=${styles.dynamicTypedFieldSetContainer}
|
|
326
|
+
key=${`fieldset-${setIndex}`}
|
|
327
|
+
>
|
|
328
|
+
<div class=${styles.fieldSetHeader}>
|
|
329
|
+
<h4>${dynamicField.title} ${setIndex + 1}</h4>
|
|
330
|
+
${setIndex > 0 &&
|
|
331
|
+
html`
|
|
332
|
+
<button
|
|
333
|
+
type="button"
|
|
334
|
+
class=${styles.removeButton}
|
|
335
|
+
onClick=${() => removeFieldSet(setIndex)}
|
|
336
|
+
disabled=${isDisabled}
|
|
337
|
+
>
|
|
338
|
+
Remove
|
|
339
|
+
</button>
|
|
340
|
+
`}
|
|
341
|
+
</div>
|
|
342
|
+
${dynamicItems.map(
|
|
343
|
+
(el) => html`
|
|
344
|
+
<div
|
|
345
|
+
class=${styles.dynamicTypedFieldWrapper}
|
|
346
|
+
key=${`${setIndex}-${el.id}`}
|
|
347
|
+
>
|
|
348
|
+
<${MultipurposeField}
|
|
349
|
+
id="${`${setIndex}_${el.id}`}"
|
|
350
|
+
title="${el.title}"
|
|
351
|
+
placeholder="${dynamicField.placeholder}"
|
|
352
|
+
isRequired="${dynamicField.is_required}"
|
|
353
|
+
isEditable="${dynamicField.is_editable}"
|
|
354
|
+
fieldId=${`${setIndex}_${el.id}`}
|
|
355
|
+
onChange=${(val: any) => {
|
|
356
|
+
onFieldSetChange(
|
|
357
|
+
setIndex,
|
|
358
|
+
el.id,
|
|
359
|
+
val,
|
|
360
|
+
el.type || 'string',
|
|
361
|
+
);
|
|
362
|
+
}}
|
|
363
|
+
value=${fieldSet[el.id] || ''}
|
|
364
|
+
activityOutputData=${activityOutputData}
|
|
365
|
+
activityOutputDataRaw=${activityOutputDataRaw}
|
|
366
|
+
type=${el.type || 'TEXTFIELD'}
|
|
367
|
+
isMappable=${Object.entries(
|
|
368
|
+
activityOutputData || {},
|
|
369
|
+
).length > 0}
|
|
370
|
+
allowTagsInText=${true}
|
|
371
|
+
isDisabled=${isDisabled}
|
|
372
|
+
><//>
|
|
373
|
+
</div>
|
|
374
|
+
`,
|
|
375
|
+
)}
|
|
376
|
+
${setIndex === fieldSets.length - 1 &&
|
|
377
|
+
html`
|
|
378
|
+
<div class=${styles.addButtonContainer}>
|
|
379
|
+
<button
|
|
380
|
+
type="button"
|
|
381
|
+
class=${styles.addButton}
|
|
382
|
+
onClick=${addNewFieldSet}
|
|
383
|
+
disabled=${isDisabled}
|
|
384
|
+
>
|
|
385
|
+
+ Add Another ${dynamicField.title}
|
|
386
|
+
</button>
|
|
387
|
+
</div>
|
|
388
|
+
`}
|
|
389
|
+
</div>
|
|
390
|
+
`,
|
|
391
|
+
)}
|
|
392
|
+
`
|
|
393
|
+
: dynamicItems.length > 0 &&
|
|
394
|
+
html`
|
|
395
|
+
${dynamicItems.map(
|
|
396
|
+
(el) => html`
|
|
397
|
+
<div
|
|
398
|
+
class=${styles.dynamicTypedFieldWrapper}
|
|
399
|
+
key=${el.id}
|
|
400
|
+
>
|
|
401
|
+
<${MultipurposeField}
|
|
402
|
+
id="${el.id}"
|
|
403
|
+
title="${el.title}"
|
|
404
|
+
placeholder="${dynamicField.placeholder}"
|
|
405
|
+
isRequired="${dynamicField.is_required}"
|
|
406
|
+
isEditable="${dynamicField.is_editable}"
|
|
407
|
+
fieldId=${el.id}
|
|
408
|
+
onChange=${(val: any) => {
|
|
409
|
+
onFieldChange(el.id, val, el.type || 'string');
|
|
410
|
+
}}
|
|
411
|
+
value=${customFieldsData[el.id] || ''}
|
|
412
|
+
activityOutputData=${activityOutputData}
|
|
413
|
+
activityOutputDataRaw=${activityOutputDataRaw}
|
|
414
|
+
type=${el.type || 'TEXTFIELD'}
|
|
415
|
+
isMappable=${Object.entries(activityOutputData || {})
|
|
416
|
+
.length > 0}
|
|
417
|
+
allowTagsInText=${true}
|
|
418
|
+
isDisabled=${isDisabled}
|
|
419
|
+
><//>
|
|
420
|
+
</div>
|
|
421
|
+
`,
|
|
422
|
+
)}
|
|
423
|
+
`}
|
|
259
424
|
`}
|
|
260
425
|
${!isErrorOnLoadingCustomFields
|
|
261
426
|
? ''
|
|
@@ -71,3 +71,65 @@ a.optionsRefresh {
|
|
|
71
71
|
height: 37px;
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
// New styles for field sets
|
|
76
|
+
.dynamicTypedFieldSetContainer {
|
|
77
|
+
margin-bottom: 20px;
|
|
78
|
+
padding: 15px;
|
|
79
|
+
border: 1px solid #e0e0e0;
|
|
80
|
+
border-radius: 4px;
|
|
81
|
+
background-color: #f9f9f9;
|
|
82
|
+
|
|
83
|
+
.fieldSetHeader {
|
|
84
|
+
display: flex;
|
|
85
|
+
justify-content: space-between;
|
|
86
|
+
align-items: center;
|
|
87
|
+
margin-bottom: 10px;
|
|
88
|
+
padding-bottom: 10px;
|
|
89
|
+
border-bottom: 1px solid #e0e0e0;
|
|
90
|
+
|
|
91
|
+
h4 {
|
|
92
|
+
margin: 0;
|
|
93
|
+
font-size: 12px;
|
|
94
|
+
font-weight: 500;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.removeButton {
|
|
99
|
+
background-color: #f44336;
|
|
100
|
+
color: white;
|
|
101
|
+
border: none;
|
|
102
|
+
border-radius: 4px;
|
|
103
|
+
padding: 5px 10px;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
font-size: 12px;
|
|
106
|
+
|
|
107
|
+
&:hover {
|
|
108
|
+
background-color: #d32f2f;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&:disabled {
|
|
112
|
+
background-color: #cccccc;
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.addButtonContainer {
|
|
118
|
+
margin-top: 15px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.addButton {
|
|
122
|
+
background-color: unset;
|
|
123
|
+
color: #007bff;
|
|
124
|
+
border: none;
|
|
125
|
+
border-radius: 4px;
|
|
126
|
+
padding: 8px 16px;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
font-size: 12px;
|
|
129
|
+
|
|
130
|
+
&:disabled {
|
|
131
|
+
background-color: #cccccc;
|
|
132
|
+
cursor: not-allowed;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|