@integry/sdk 4.7.18 → 4.7.21
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/esm/index.csm.d.ts +1 -0
- package/dist/esm/index.csm.js +1 -1
- package/dist/umd/index.umd.d.ts +1 -0
- package/dist/umd/index.umd.js +1 -1
- package/package.json +1 -1
- package/src/components/MultipurposeField/index.tsx +142 -12
- package/src/components/MultipurposeField/styles.module.scss +1 -0
- package/src/components/TagsMenu/index.ts +38 -57
- package/src/features/common/ActionForm/index.ts +1 -0
- package/src/features/common/DynamicTypedField/index.ts +17 -3
- package/src/features/common/FunctionForm/index.ts +5 -0
- package/src/interfaces/index.ts +1 -0
package/package.json
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
/* eslint-disable no-nested-ternary */
|
|
2
4
|
import { html } from 'htm/preact';
|
|
3
5
|
import { useState, useRef, useEffect } from 'preact/hooks';
|
|
@@ -5,8 +7,8 @@ import { Input } from '@/components/Input';
|
|
|
5
7
|
import { TextArea } from '@/components/TextArea';
|
|
6
8
|
import { useOnClickOutside } from '@/hooks/useOnClickOutside';
|
|
7
9
|
import { FieldDropdown } from '@/components/MultipurposeField/TagMenu';
|
|
8
|
-
import { NestedObject } from '@/interfaces';
|
|
9
|
-
import { TagProps } from '@/components/Tag';
|
|
10
|
+
import type { NestedObject } from '@/interfaces';
|
|
11
|
+
import type { TagProps } from '@/components/Tag';
|
|
10
12
|
// import { TagsMenu } from '@/components/TagsMenu';
|
|
11
13
|
// @ts-ignore
|
|
12
14
|
import Tagify from '@yaireo/tagify';
|
|
@@ -100,10 +102,10 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
100
102
|
const [tempPlaceholder, setTempPlaceholder] = useState('');
|
|
101
103
|
const [searchValue, setSearchValue] = useState('');
|
|
102
104
|
const [tagify, setTagify] = useState<Tagify | null>(null);
|
|
103
|
-
const [defaultTagifyValue, setDefaultTagifyValue] = useState('');
|
|
104
105
|
|
|
105
106
|
const menuRef = useRef<HTMLDivElement | null>(null);
|
|
106
107
|
const inputRef = useRef<HTMLInputElement>();
|
|
108
|
+
const appIconMapRef = useRef<Record<string, string>>({});
|
|
107
109
|
|
|
108
110
|
const handleTabKeyDown = (event: KeyboardEvent) => {
|
|
109
111
|
if (event.key === 'Tab') {
|
|
@@ -155,6 +157,58 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
155
157
|
};
|
|
156
158
|
}, [value, title]);
|
|
157
159
|
|
|
160
|
+
// Helper function to extract step name from tag value
|
|
161
|
+
const getStepNameFromValue = (tagValue: string): string | null => {
|
|
162
|
+
const parts = tagValue.split('.');
|
|
163
|
+
// For values like "steps.slack_post_message_1.output.ok", "storage.user_data.value",
|
|
164
|
+
// "setup_form.api_key.value", "parameters.timeout.value" return the second part
|
|
165
|
+
if (parts.length >= 2) {
|
|
166
|
+
return parts[1];
|
|
167
|
+
}
|
|
168
|
+
// If there's no second part, return null
|
|
169
|
+
return null;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Build flattened appIcon map when tagsTree changes
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
if (!tagsTree) {
|
|
175
|
+
appIconMapRef.current = {};
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const flattenedMap: Record<string, string> = {};
|
|
180
|
+
|
|
181
|
+
// Traverse tagsTree and build flattened map
|
|
182
|
+
const traverseAndMap = (tags: any[]) => {
|
|
183
|
+
if (!Array.isArray(tags)) return;
|
|
184
|
+
|
|
185
|
+
tags.forEach((tag) => {
|
|
186
|
+
if (tag.machineName && tag.appIcon) {
|
|
187
|
+
flattenedMap[tag.machineName] = tag.appIcon;
|
|
188
|
+
}
|
|
189
|
+
// Recursively traverse nested tags
|
|
190
|
+
if (tag.tags && Array.isArray(tag.tags)) {
|
|
191
|
+
traverseAndMap(tag.tags);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Traverse all categories in tagsTree
|
|
197
|
+
for (const categoryKey in tagsTree) {
|
|
198
|
+
const category = tagsTree[categoryKey];
|
|
199
|
+
if (category.tags && Array.isArray(category.tags)) {
|
|
200
|
+
traverseAndMap(category.tags);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
appIconMapRef.current = flattenedMap;
|
|
205
|
+
}, [tagsTree]);
|
|
206
|
+
|
|
207
|
+
// Helper function to get appIcon from precomputed map
|
|
208
|
+
const getAppIconFromMap = (stepName: string): string | null => {
|
|
209
|
+
return appIconMapRef.current[stepName] || null;
|
|
210
|
+
};
|
|
211
|
+
|
|
158
212
|
useEffect(() => {
|
|
159
213
|
const textfield = inputRef.current;
|
|
160
214
|
const scalarValue = Array.isArray(value) ? value[0] : value;
|
|
@@ -178,9 +232,52 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
178
232
|
});
|
|
179
233
|
tagify
|
|
180
234
|
.on('focus', handleFieldFocus)
|
|
235
|
+
.on('blur', handleFieldBlur)
|
|
181
236
|
.on('remove', handleOnTagRemove)
|
|
182
237
|
.on('change', handleOnTagRemove);
|
|
183
238
|
setTagify(tagify);
|
|
239
|
+
|
|
240
|
+
tagify.on('click', (e: any) => {
|
|
241
|
+
const tagData = e.detail.data;
|
|
242
|
+
if (!tagData?.appIcon) {
|
|
243
|
+
return; // Ignore clicks on tags without appIcon
|
|
244
|
+
}
|
|
245
|
+
const tagElm = e.detail.tag;
|
|
246
|
+
|
|
247
|
+
// Remove the tag
|
|
248
|
+
tagify.removeTag(tagElm);
|
|
249
|
+
|
|
250
|
+
// Place caret after the removed tag
|
|
251
|
+
const selection = window.getSelection();
|
|
252
|
+
const range = document.createRange();
|
|
253
|
+
|
|
254
|
+
// Insert editable text node (without appIcon in the text)
|
|
255
|
+
const editableText = document.createTextNode(`{${tagData.value}} `);
|
|
256
|
+
|
|
257
|
+
// Insert text after the removed tag
|
|
258
|
+
tagElm.parentNode.insertBefore(editableText, tagElm.nextSibling);
|
|
259
|
+
|
|
260
|
+
// Move caret to end of inserted text
|
|
261
|
+
range.setStart(editableText, editableText.length);
|
|
262
|
+
range.setEnd(editableText, editableText.length);
|
|
263
|
+
selection?.removeAllRanges();
|
|
264
|
+
selection?.addRange(range);
|
|
265
|
+
|
|
266
|
+
// Optional: trigger input event so Tagify re-parses
|
|
267
|
+
tagify.DOM.input.dispatchEvent(new Event('input'));
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
tagify.on('keydown', (e: any) => {
|
|
271
|
+
if (
|
|
272
|
+
e?.detail?.event?.code === 'Enter' &&
|
|
273
|
+
tagsTree &&
|
|
274
|
+
type === 'TEXTAREA'
|
|
275
|
+
) {
|
|
276
|
+
e.preventDefault();
|
|
277
|
+
document.execCommand('insertHTML', false, '<br>');
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
});
|
|
184
281
|
}
|
|
185
282
|
} else if (
|
|
186
283
|
textfield &&
|
|
@@ -214,10 +311,18 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
214
311
|
};
|
|
215
312
|
const handleOnTagRemove = (e: any) => {
|
|
216
313
|
const el: any = document.getElementById(`tagify_${fieldId}`);
|
|
314
|
+
|
|
217
315
|
let newValue = el.__tagify.DOM.input.innerText;
|
|
316
|
+
|
|
317
|
+
// Process tags being removed
|
|
218
318
|
el.__tagify.value.forEach((tag: any) => {
|
|
219
|
-
newValue = newValue
|
|
319
|
+
newValue = newValue
|
|
320
|
+
.replace(tag.text, `{${tag.value}}`)
|
|
321
|
+
.replace('Step: ', '')
|
|
322
|
+
.replace('User variable: ', '')
|
|
323
|
+
.replace('Setup form: ', '');
|
|
220
324
|
});
|
|
325
|
+
|
|
221
326
|
newValue = newValue.trim();
|
|
222
327
|
// remove zero width space
|
|
223
328
|
newValue = newValue.replace(/\u200B/g, '');
|
|
@@ -225,7 +330,6 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
225
330
|
el.value = '';
|
|
226
331
|
newValue = '';
|
|
227
332
|
}
|
|
228
|
-
// newValue = newValue.replace(/^\n+|\n+$/g, ''); // remove leading and trailing newlines
|
|
229
333
|
newValue = newValue.replace(/<br>/g, '\n'); // replace <br> with newlines
|
|
230
334
|
newValue = newValue.replace(/\n{/g, '{').replace(/}\n/g, '}'); // remove \n before and after tags
|
|
231
335
|
|
|
@@ -303,9 +407,7 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
303
407
|
|
|
304
408
|
// Returns all those strings which are enclosed in curly braces {}
|
|
305
409
|
const getTags = (str: string) => {
|
|
306
|
-
|
|
307
|
-
const matches = str.match(regex);
|
|
308
|
-
return matches;
|
|
410
|
+
return str.match(/{[^{}"'<>:]+}/g) || [];
|
|
309
411
|
};
|
|
310
412
|
|
|
311
413
|
const checkIfTagExists = (AOUElement: string, tagValue: string) => {
|
|
@@ -319,14 +421,18 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
319
421
|
|
|
320
422
|
const getDefaultTagifyValue = (value: any) => {
|
|
321
423
|
const tags = getTags(value || '');
|
|
424
|
+
|
|
322
425
|
if (tags && tags.length > 0) {
|
|
323
426
|
let newValue = value;
|
|
427
|
+
|
|
324
428
|
if (type === 'TEXTAREA') {
|
|
325
429
|
newValue = newValue.replace(/\n/g, '<br>');
|
|
326
430
|
}
|
|
431
|
+
|
|
327
432
|
tags.forEach((tag) => {
|
|
328
433
|
const tagValue = tag.replace(/{|}/g, '');
|
|
329
434
|
const tagValueParts = tagValue.split('.');
|
|
435
|
+
|
|
330
436
|
let tagData = (activityOutputDataRaw || []).find((element: any) => {
|
|
331
437
|
return (
|
|
332
438
|
element.value === tagValue ||
|
|
@@ -340,8 +446,16 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
340
446
|
: tagValue,
|
|
341
447
|
title: tagValue,
|
|
342
448
|
};
|
|
449
|
+
|
|
450
|
+
// Try to get appIcon from tagsTree based on step name
|
|
451
|
+
const stepName = getStepNameFromValue(tagValue);
|
|
452
|
+
const appIconFromTree = stepName ? getAppIconFromMap(stepName) : null;
|
|
453
|
+
|
|
454
|
+
if (appIconFromTree) {
|
|
455
|
+
tagData.appIcon = appIconFromTree;
|
|
456
|
+
}
|
|
457
|
+
|
|
343
458
|
if (tagsTree) {
|
|
344
|
-
// this component has been called with explicit tagTree hence we don't need to rely on activity output data any more.
|
|
345
459
|
tagData = {
|
|
346
460
|
value: tagValue,
|
|
347
461
|
text:
|
|
@@ -349,19 +463,29 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
349
463
|
? prettifyString(tagValueParts[tagValueParts.length - 1])
|
|
350
464
|
: tagValue,
|
|
351
465
|
title: tagValue,
|
|
466
|
+
...(appIconFromTree && { appIcon: appIconFromTree }),
|
|
352
467
|
};
|
|
353
468
|
}
|
|
469
|
+
|
|
354
470
|
if (tagData) {
|
|
471
|
+
// Include appIcon in the JSON if it exists
|
|
472
|
+
const tagDataForJson = {
|
|
473
|
+
value: tagData.value,
|
|
474
|
+
text: tagData.text,
|
|
475
|
+
title: getTagData(tagData.text),
|
|
476
|
+
...(tagData.appIcon && { appIcon: tagData.appIcon }),
|
|
477
|
+
};
|
|
478
|
+
|
|
355
479
|
newValue = newValue?.replace(
|
|
356
480
|
tag,
|
|
357
|
-
`[[
|
|
358
|
-
tagData.text
|
|
359
|
-
}","title":"${getTagData(tagData.text)}"}]]`,
|
|
481
|
+
`[[${JSON.stringify(tagDataForJson)}]]`,
|
|
360
482
|
);
|
|
361
483
|
}
|
|
362
484
|
});
|
|
485
|
+
|
|
363
486
|
return newValue;
|
|
364
487
|
}
|
|
488
|
+
|
|
365
489
|
return value;
|
|
366
490
|
};
|
|
367
491
|
|
|
@@ -515,6 +639,12 @@ const MultipurposeField = (props: MultipurposeFieldProps) => {
|
|
|
515
639
|
}
|
|
516
640
|
};
|
|
517
641
|
|
|
642
|
+
const handleFieldBlur = (e: any) => {
|
|
643
|
+
const el: any = document.getElementById(`tagify_${fieldId}`);
|
|
644
|
+
const currentTagifyValue = getDefaultTagifyValue(el.value || '');
|
|
645
|
+
el.value = currentTagifyValue;
|
|
646
|
+
};
|
|
647
|
+
|
|
518
648
|
const getStringFromEnd = (str: string): string => {
|
|
519
649
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
520
650
|
const regex = /\{([^{}]+)$/;
|
|
@@ -41,6 +41,7 @@ interface TagListProps {
|
|
|
41
41
|
globalSearchMode?: boolean;
|
|
42
42
|
onSelect?: (tag: Record<string, unknown>) => void;
|
|
43
43
|
activeTab?: string;
|
|
44
|
+
parentAppIcon?: string; // Add parent app icon to props
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
interface TagsMenuProps {
|
|
@@ -88,6 +89,7 @@ const arrayToObject = (arr: unknown[]): Record<string, unknown> =>
|
|
|
88
89
|
newObj[`[${index}]`] = item;
|
|
89
90
|
return newObj;
|
|
90
91
|
}, {});
|
|
92
|
+
|
|
91
93
|
// Check if output data matches the search term
|
|
92
94
|
const outputMatchesSearch = (output: unknown, term: string): boolean => {
|
|
93
95
|
if (!term || !output) return false;
|
|
@@ -355,57 +357,7 @@ const ValuesList = ({
|
|
|
355
357
|
</div>
|
|
356
358
|
`;
|
|
357
359
|
|
|
358
|
-
//
|
|
359
|
-
const findParentWithAppIcon = (
|
|
360
|
-
tags: Record<string, unknown> | unknown[],
|
|
361
|
-
path: string,
|
|
362
|
-
): string | undefined => {
|
|
363
|
-
if (!path) return undefined;
|
|
364
|
-
|
|
365
|
-
const pathParts = path.split('.');
|
|
366
|
-
let currentTags = tags;
|
|
367
|
-
let parentWithIcon: string | undefined;
|
|
368
|
-
|
|
369
|
-
// Navigate through the path to find the parent with appIcon
|
|
370
|
-
for (let i = 0; i < pathParts.length; i += 1) {
|
|
371
|
-
const part = pathParts[i];
|
|
372
|
-
|
|
373
|
-
// Skip 'output' parts in the path
|
|
374
|
-
if (part === 'output') {
|
|
375
|
-
// Skip processing for 'output'
|
|
376
|
-
return undefined;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Handle array indices
|
|
380
|
-
if (part.startsWith('[') && part.endsWith(']')) {
|
|
381
|
-
const index = Number.parseInt(part.substring(1, part.length - 1), 10);
|
|
382
|
-
if (Array.isArray(currentTags) && index < currentTags.length) {
|
|
383
|
-
const item = currentTags[index];
|
|
384
|
-
if (isTagNode(item) && item.appIcon) {
|
|
385
|
-
parentWithIcon = item.appIcon;
|
|
386
|
-
}
|
|
387
|
-
currentTags = item as Record<string, unknown>;
|
|
388
|
-
} else {
|
|
389
|
-
break;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
// Handle object properties
|
|
393
|
-
if (!Array.isArray(currentTags) && currentTags[part]) {
|
|
394
|
-
const item = currentTags[part];
|
|
395
|
-
if (isTagNode(item) && item.appIcon) {
|
|
396
|
-
parentWithIcon = item.appIcon;
|
|
397
|
-
}
|
|
398
|
-
currentTags = item as Record<string, unknown>;
|
|
399
|
-
} else {
|
|
400
|
-
break;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return parentWithIcon;
|
|
405
|
-
};
|
|
406
|
-
|
|
407
|
-
// Update the TagList component to add the "add tag" button functionality
|
|
408
|
-
|
|
360
|
+
// Update the TagList component to pass parent app icon and include it in selections
|
|
409
361
|
const TagList = ({
|
|
410
362
|
tags,
|
|
411
363
|
searchTerm,
|
|
@@ -416,6 +368,7 @@ const TagList = ({
|
|
|
416
368
|
/* Default empty implementation */
|
|
417
369
|
},
|
|
418
370
|
activeTab = '',
|
|
371
|
+
parentAppIcon = undefined, // Add parent app icon parameter
|
|
419
372
|
}: TagListProps) => {
|
|
420
373
|
// Track which nodes are expanded to show nested steps
|
|
421
374
|
const [expandedNodes, setExpandedNodes] = useState<Record<string, boolean>>(
|
|
@@ -659,19 +612,25 @@ const TagList = ({
|
|
|
659
612
|
return stepName;
|
|
660
613
|
};
|
|
661
614
|
|
|
662
|
-
//
|
|
615
|
+
// Modified function to handle selecting a tag with parent app icon
|
|
663
616
|
const handleSelectTag = (
|
|
664
617
|
key: string,
|
|
665
618
|
value: unknown,
|
|
666
619
|
currentPath: string,
|
|
620
|
+
nodeAppIcon?: string,
|
|
667
621
|
) => {
|
|
668
622
|
const tagPath = `${activeTab}.${extractStepsFromOutputPath(currentPath)}`;
|
|
623
|
+
|
|
624
|
+
// Determine which app icon to use - prioritize node's own icon, then parent icon
|
|
625
|
+
const appIconToUse = nodeAppIcon || parentAppIcon;
|
|
626
|
+
|
|
669
627
|
onSelect({
|
|
670
628
|
currentPath: tagPath
|
|
671
629
|
.replace(/\bparameters\.parameters\b/g, 'parameters')
|
|
672
630
|
.replace(/\bauthorization\.authorization\b/g, 'authorization'),
|
|
673
631
|
key,
|
|
674
632
|
value: escapeHTMLIfNeeded(value),
|
|
633
|
+
parentAppIcon: appIconToUse, // Include parent app icon in the response
|
|
675
634
|
});
|
|
676
635
|
};
|
|
677
636
|
|
|
@@ -882,6 +841,12 @@ const TagList = ({
|
|
|
882
841
|
tagsParamForOutput = value as Record<string, unknown>;
|
|
883
842
|
}
|
|
884
843
|
|
|
844
|
+
// Determine the app icon to pass down - use current node's icon or parent's icon
|
|
845
|
+
const currentNodeAppIcon = isTagNode(value)
|
|
846
|
+
? value.appIcon
|
|
847
|
+
: undefined;
|
|
848
|
+
const appIconToPass = currentNodeAppIcon || parentAppIcon;
|
|
849
|
+
|
|
885
850
|
const handleMenuRowClcik = (e: Event) => {
|
|
886
851
|
if (isStep && hasOutput) {
|
|
887
852
|
// For step nodes with output, toggle output expansion
|
|
@@ -895,7 +860,7 @@ const TagList = ({
|
|
|
895
860
|
toggleOutputExpand(key, e);
|
|
896
861
|
} else {
|
|
897
862
|
// For leaf nodes, select the value
|
|
898
|
-
handleSelectTag(key, value, currentPath);
|
|
863
|
+
handleSelectTag(key, value, currentPath, currentNodeAppIcon);
|
|
899
864
|
}
|
|
900
865
|
};
|
|
901
866
|
|
|
@@ -923,7 +888,12 @@ const TagList = ({
|
|
|
923
888
|
toggleOutputExpand(key, e);
|
|
924
889
|
} else {
|
|
925
890
|
// For leaf nodes, select the value
|
|
926
|
-
handleSelectTag(
|
|
891
|
+
handleSelectTag(
|
|
892
|
+
key,
|
|
893
|
+
value,
|
|
894
|
+
currentPath,
|
|
895
|
+
currentNodeAppIcon,
|
|
896
|
+
);
|
|
927
897
|
}
|
|
928
898
|
}}
|
|
929
899
|
class="${styles.listItemContent}"
|
|
@@ -1007,7 +977,12 @@ const TagList = ({
|
|
|
1007
977
|
class="${styles.addTagButton}"
|
|
1008
978
|
onClick=${(e: Event) => {
|
|
1009
979
|
e.stopPropagation();
|
|
1010
|
-
handleSelectTag(
|
|
980
|
+
handleSelectTag(
|
|
981
|
+
key,
|
|
982
|
+
value,
|
|
983
|
+
currentPath,
|
|
984
|
+
currentNodeAppIcon,
|
|
985
|
+
);
|
|
1011
986
|
}}
|
|
1012
987
|
title="Add this tag"
|
|
1013
988
|
>
|
|
@@ -1211,6 +1186,7 @@ const TagList = ({
|
|
|
1211
1186
|
globalSearchMode=${globalSearchMode}
|
|
1212
1187
|
onSelect=${onSelect}
|
|
1213
1188
|
activeTab=${activeTab}
|
|
1189
|
+
parentAppIcon=${appIconToPass}
|
|
1214
1190
|
/>
|
|
1215
1191
|
`;
|
|
1216
1192
|
}
|
|
@@ -1234,6 +1210,7 @@ const TagList = ({
|
|
|
1234
1210
|
globalSearchMode=${globalSearchMode}
|
|
1235
1211
|
onSelect=${onSelect}
|
|
1236
1212
|
activeTab=${activeTab}
|
|
1213
|
+
parentAppIcon=${appIconToPass}
|
|
1237
1214
|
/>`
|
|
1238
1215
|
: ''}
|
|
1239
1216
|
<!-- Display expanded array content with additional debug info -->
|
|
@@ -1247,6 +1224,7 @@ const TagList = ({
|
|
|
1247
1224
|
globalSearchMode=${globalSearchMode}
|
|
1248
1225
|
onSelect=${onSelect}
|
|
1249
1226
|
activeTab=${activeTab}
|
|
1227
|
+
parentAppIcon=${appIconToPass}
|
|
1250
1228
|
/>
|
|
1251
1229
|
</div>`
|
|
1252
1230
|
: ''}
|
|
@@ -1267,6 +1245,7 @@ const TagList = ({
|
|
|
1267
1245
|
globalSearchMode=${globalSearchMode}
|
|
1268
1246
|
onSelect=${onSelect}
|
|
1269
1247
|
activeTab=${activeTab}
|
|
1248
|
+
parentAppIcon=${appIconToPass}
|
|
1270
1249
|
/>
|
|
1271
1250
|
</div>`
|
|
1272
1251
|
: ''}
|
|
@@ -1278,7 +1257,7 @@ const TagList = ({
|
|
|
1278
1257
|
`;
|
|
1279
1258
|
};
|
|
1280
1259
|
|
|
1281
|
-
// Update the TabMenu component to search across all tabs
|
|
1260
|
+
// Update the TabMenu component to search across all tabs and pass data to TagList
|
|
1282
1261
|
const TabMenu = ({ data, onSelect, onOptionClick }: TagMenuProps) => {
|
|
1283
1262
|
const [activeTab, setActiveTab] = useState<string>(Object.keys(data)[0]);
|
|
1284
1263
|
const [searchTerm, setSearchTerm] = useState<string>('');
|
|
@@ -1609,6 +1588,9 @@ const TabMenu = ({ data, onSelect, onOptionClick }: TagMenuProps) => {
|
|
|
1609
1588
|
globalSearchMode=${globalSearchMode}
|
|
1610
1589
|
onSelect=${onSelect}
|
|
1611
1590
|
activeTab=${data[activeTab].machineName || activeTab}
|
|
1591
|
+
parentAppIcon=${isTagNode(activeData)
|
|
1592
|
+
? activeData.appIcon
|
|
1593
|
+
: undefined}
|
|
1612
1594
|
/>
|
|
1613
1595
|
</div>`}
|
|
1614
1596
|
</div>
|
|
@@ -1683,7 +1665,6 @@ export function TagsMenu({
|
|
|
1683
1665
|
...modifiedData, // Spread the remaining tabs after "Values"
|
|
1684
1666
|
};
|
|
1685
1667
|
}
|
|
1686
|
-
|
|
1687
1668
|
return html`
|
|
1688
1669
|
<div class="${styles.tagsMenuWrapper}">
|
|
1689
1670
|
<${TabMenu}
|
|
@@ -2083,6 +2083,7 @@ class ActionForm extends Component<ActionFormPropsType, ActionFormStateType> {
|
|
|
2083
2083
|
idKeyPath=${uiField?.id_key_path}
|
|
2084
2084
|
typeKeyPath=${uiField?.type_key_path}
|
|
2085
2085
|
titleKeyPath=${uiField?.title_key_path}
|
|
2086
|
+
isRequiredKeyPath=${uiField?.is_required_key_path}
|
|
2086
2087
|
onChangeCallback=${this.props
|
|
2087
2088
|
.onFieldChangeCallback
|
|
2088
2089
|
? (val: any) => {
|
|
@@ -31,6 +31,7 @@ export type DynamicFieldsProps = {
|
|
|
31
31
|
idKeyPath?: string;
|
|
32
32
|
titleKeyPath?: string;
|
|
33
33
|
typeKeyPath?: string;
|
|
34
|
+
isRequiredKeyPath?: string;
|
|
34
35
|
onChange?: (val: any) => void;
|
|
35
36
|
dataSourceBody?: any;
|
|
36
37
|
parentFieldsChanged?: boolean;
|
|
@@ -50,6 +51,7 @@ interface DynamicDataItem {
|
|
|
50
51
|
output?: any;
|
|
51
52
|
next_page?: string;
|
|
52
53
|
type?: string;
|
|
54
|
+
is_required?: boolean;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
interface ApiResponse {
|
|
@@ -166,13 +168,21 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
166
168
|
if (Array.isArray(res)) {
|
|
167
169
|
transformedItems = res;
|
|
168
170
|
} else if (res.output && Array.isArray(res.output)) {
|
|
169
|
-
const {
|
|
171
|
+
const {
|
|
172
|
+
idKeyPath,
|
|
173
|
+
titleKeyPath,
|
|
174
|
+
typeKeyPath,
|
|
175
|
+
isRequiredKeyPath,
|
|
176
|
+
} = props;
|
|
170
177
|
|
|
171
178
|
if (idKeyPath && titleKeyPath) {
|
|
172
179
|
transformedItems = res.output.map((item: any) => ({
|
|
173
180
|
id: resolveValue(idKeyPath, item),
|
|
174
181
|
title: resolveValue(titleKeyPath, item),
|
|
175
182
|
type: 'TEXTFIELD',
|
|
183
|
+
...(isRequiredKeyPath
|
|
184
|
+
? { is_required: resolveValue(isRequiredKeyPath, item) }
|
|
185
|
+
: {}),
|
|
176
186
|
}));
|
|
177
187
|
} else {
|
|
178
188
|
setDynamicItems([]);
|
|
@@ -358,7 +368,9 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
358
368
|
id="${`${setIndex}_${el.id}`}"
|
|
359
369
|
title="${el.title}"
|
|
360
370
|
placeholder="${dynamicField.placeholder}"
|
|
361
|
-
isRequired="${
|
|
371
|
+
isRequired="${el.is_required !== undefined
|
|
372
|
+
? el.is_required
|
|
373
|
+
: dynamicField.is_required}"
|
|
362
374
|
isEditable="${dynamicField.is_editable}"
|
|
363
375
|
fieldId=${`${setIndex}_${el.id}`}
|
|
364
376
|
onChange=${(val: any) => {
|
|
@@ -413,7 +425,9 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
413
425
|
id="${el.id}"
|
|
414
426
|
title="${el.title}"
|
|
415
427
|
placeholder="${dynamicField.placeholder}"
|
|
416
|
-
isRequired="${
|
|
428
|
+
isRequired="${el.is_required !== undefined
|
|
429
|
+
? el.is_required
|
|
430
|
+
: dynamicField.is_required}"
|
|
417
431
|
isEditable="${dynamicField.is_editable}"
|
|
418
432
|
fieldId=${el.id}
|
|
419
433
|
onChange=${(val: any) => {
|
|
@@ -646,6 +646,10 @@ class FunctionForm extends Component<
|
|
|
646
646
|
fieldDetails.meta.ui.ui_field?.type === 'CUSTOM_FIELDS'
|
|
647
647
|
? fieldDetails.meta.ui.ui_field.title_key_path || ''
|
|
648
648
|
: undefined,
|
|
649
|
+
isRequiredKeyPath:
|
|
650
|
+
fieldDetails.meta.ui.ui_field?.type === 'CUSTOM_FIELDS'
|
|
651
|
+
? fieldDetails.meta.ui.ui_field.is_required_key_path || ''
|
|
652
|
+
: undefined,
|
|
649
653
|
dataSourceBody:
|
|
650
654
|
fieldDetails.meta.ui.ui_field?.type === 'DYNAMIC_DROPDOWN' ||
|
|
651
655
|
fieldDetails.meta.ui.ui_field?.type === 'CUSTOM_FIELDS'
|
|
@@ -897,6 +901,7 @@ class FunctionForm extends Component<
|
|
|
897
901
|
idKeyPath=${field.idKeyPath}
|
|
898
902
|
typeKeyPath=${field.typeKeyPath}
|
|
899
903
|
titleKeyPath=${field.titleKeyPath}
|
|
904
|
+
isRequiredKeyPath=${field.isRequiredKeyPath}
|
|
900
905
|
onChange=${(val: any) => {
|
|
901
906
|
this.onFieldChange(field.id, val, field.dataType, false);
|
|
902
907
|
}}
|