@integry/sdk 4.6.91 → 4.6.93
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.d.ts +5 -0
- package/dist/esm/index.csm.js +1 -1
- package/dist/umd/index.umd.d.ts +5 -0
- package/dist/umd/index.umd.js +1 -1
- package/package.json +1 -1
- package/src/features/common/DynamicTypedField/index.ts +78 -27
- package/src/features/common/FunctionForm/index.ts +16 -2
- package/src/index.ts +10 -1
- package/src/types/index.ts +5 -0
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
import { html } from 'htm/preact';
|
|
2
4
|
import { connect } from 'unistore/preact';
|
|
3
|
-
import { useContext, useEffect, useState } from 'preact/hooks';
|
|
4
|
-
import { DynamicField, NestedObject } from '@/interfaces';
|
|
5
|
+
import { useContext, useEffect, useState, useRef } from 'preact/hooks';
|
|
6
|
+
import type { DynamicField, NestedObject } from '@/interfaces';
|
|
5
7
|
import AppContext from '@/contexts/AppContext';
|
|
6
|
-
import { StoreType } from '@/types/store';
|
|
7
|
-
import { IntegryAPI } from '@/modules/api';
|
|
8
|
-
import { Input } from '@/components/Input';
|
|
8
|
+
import type { StoreType } from '@/types/store';
|
|
9
|
+
import type { IntegryAPI } from '@/modules/api';
|
|
9
10
|
import { MultipurposeField } from '@/components/MultipurposeField';
|
|
10
11
|
import { Loader } from '@/components/Loader';
|
|
11
12
|
import { actionFunctions } from '@/store';
|
|
@@ -36,6 +37,8 @@ export type DynamicFieldsProps = {
|
|
|
36
37
|
value?: any;
|
|
37
38
|
isDisabled?: boolean;
|
|
38
39
|
onChangeCallback?: (val: any) => void;
|
|
40
|
+
dependsOn?: string[];
|
|
41
|
+
isArray?: boolean; // New prop to determine if the output should be an array
|
|
39
42
|
} & StoreType;
|
|
40
43
|
|
|
41
44
|
interface DynamicDataItem {
|
|
@@ -55,8 +58,6 @@ interface ApiResponse {
|
|
|
55
58
|
const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
56
59
|
const {
|
|
57
60
|
dynamicField,
|
|
58
|
-
endpointData,
|
|
59
|
-
sourceFunctionData = {},
|
|
60
61
|
sourceFlowIntegrataionInvocationUrl = '',
|
|
61
62
|
selectedAuthId = '',
|
|
62
63
|
dataSourceBody,
|
|
@@ -67,21 +68,35 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
67
68
|
onChange,
|
|
68
69
|
isDisabled = false,
|
|
69
70
|
onChangeCallback = () => null,
|
|
71
|
+
dependsOn = [],
|
|
72
|
+
isArray = false, // Default to false for backward compatibility
|
|
70
73
|
} = props;
|
|
71
74
|
const [dynamicItems, setDynamicItems] = useState<DynamicDataItem[]>([]);
|
|
72
75
|
const [loading, setLoading] = useState<boolean>(true);
|
|
73
|
-
const [customFieldsData, setCustomFieldsData] = useState<any>(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
const [customFieldsData, setCustomFieldsData] = useState<any>(() => {
|
|
77
|
+
// Initialize from value prop if available
|
|
78
|
+
if (value) {
|
|
79
|
+
const parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
80
|
+
|
|
81
|
+
// If isArray is true and the value is an array, extract the first object
|
|
82
|
+
if (isArray && Array.isArray(parsedValue) && parsedValue.length > 0) {
|
|
83
|
+
return parsedValue[0];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return parsedValue;
|
|
87
|
+
}
|
|
88
|
+
return {};
|
|
89
|
+
});
|
|
76
90
|
const [
|
|
77
91
|
isErrorOnLoadingCustomFields,
|
|
78
92
|
setIsErrorOnLoadingCustomFields,
|
|
79
93
|
] = useState<boolean>(false);
|
|
80
94
|
|
|
81
95
|
const context = useContext(AppContext);
|
|
82
|
-
const isReadOnly = context?.isReadOnly;
|
|
83
96
|
const apiHandlerRef = context?.apiHandler || props.apiHandler;
|
|
84
97
|
|
|
98
|
+
const fieldsHaveBeenFetched = useRef(false);
|
|
99
|
+
|
|
85
100
|
const resolveValue = (path: string, item: any): any => {
|
|
86
101
|
// If the path contains template tags, process it
|
|
87
102
|
if (/{([^}]+)}/.test(path)) {
|
|
@@ -149,25 +164,61 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
149
164
|
}
|
|
150
165
|
};
|
|
151
166
|
|
|
167
|
+
// Split the effects - one for fetching fields, one for handling value changes
|
|
152
168
|
useEffect(() => {
|
|
153
|
-
|
|
154
|
-
|
|
169
|
+
// Only fetch fields on initial mount or when parentFieldsChanged changes
|
|
170
|
+
if (dependsOn.length > 0 && !parentFieldsChanged) {
|
|
171
|
+
setLoading(false);
|
|
172
|
+
setIsErrorOnLoadingCustomFields(false);
|
|
173
|
+
return;
|
|
155
174
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const onFieldChange = (id: string, val: string, type: string) => {
|
|
160
|
-
const data = {
|
|
161
|
-
...customFieldsData,
|
|
162
|
-
[id]: val,
|
|
163
|
-
};
|
|
164
|
-
setCustomFieldsData(data);
|
|
165
|
-
if (onChange) {
|
|
166
|
-
onChange(data);
|
|
175
|
+
if (!fieldsHaveBeenFetched.current || parentFieldsChanged) {
|
|
176
|
+
fetchDynamicFields();
|
|
177
|
+
fieldsHaveBeenFetched.current = true;
|
|
167
178
|
}
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
}, [parentFieldsChanged]); // Remove value from dependencies
|
|
180
|
+
|
|
181
|
+
// Separate effect for handling external value changes
|
|
182
|
+
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
|
+
if (value && !loading) {
|
|
186
|
+
let parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
187
|
+
|
|
188
|
+
// If isArray is true and the value is an array, extract the first object for internal state
|
|
189
|
+
if (isArray && Array.isArray(parsedValue) && parsedValue.length > 0) {
|
|
190
|
+
[parsedValue] = parsedValue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Compare if the value is actually different to avoid unnecessary updates
|
|
194
|
+
const currentValueStr = JSON.stringify(customFieldsData);
|
|
195
|
+
const newValueStr = JSON.stringify(parsedValue);
|
|
196
|
+
|
|
197
|
+
if (currentValueStr !== newValueStr) {
|
|
198
|
+
setCustomFieldsData(parsedValue);
|
|
199
|
+
}
|
|
170
200
|
}
|
|
201
|
+
}, [value, loading, isArray]);
|
|
202
|
+
|
|
203
|
+
// Modify the onFieldChange function to handle array output if isArray is true
|
|
204
|
+
const onFieldChange = (id: string, val: string, type: string) => {
|
|
205
|
+
// Update local state immediately
|
|
206
|
+
setCustomFieldsData((prevData: any) => {
|
|
207
|
+
const newData = {
|
|
208
|
+
...prevData,
|
|
209
|
+
[id]: val,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Call parent callbacks with the new data, wrapping in array if isArray is true
|
|
213
|
+
if (onChange) {
|
|
214
|
+
onChange(isArray ? [newData] : newData);
|
|
215
|
+
}
|
|
216
|
+
if (onChangeCallback) {
|
|
217
|
+
onChangeCallback(JSON.stringify(isArray ? [newData] : newData));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return newData;
|
|
221
|
+
});
|
|
171
222
|
};
|
|
172
223
|
|
|
173
224
|
return html`
|
|
@@ -182,7 +233,7 @@ const DynamicTypedFields = (props: DynamicFieldsProps) => {
|
|
|
182
233
|
: html`
|
|
183
234
|
${dynamicItems.map(
|
|
184
235
|
(el) => html`
|
|
185
|
-
<div class=${styles.dynamicTypedFieldWrapper}>
|
|
236
|
+
<div class=${styles.dynamicTypedFieldWrapper} key=${el.id}>
|
|
186
237
|
<${MultipurposeField}
|
|
187
238
|
id="${el.id}"
|
|
188
239
|
title="${el.title}"
|
|
@@ -52,6 +52,8 @@ interface ActionFormStateType {
|
|
|
52
52
|
parentFields: any;
|
|
53
53
|
parentFieldsChanged: boolean;
|
|
54
54
|
aiAssistedFields: string[]; // New state to track fields with AI assist enabled
|
|
55
|
+
changedParentMachineName?: string; // New prop to track changes in parent machine name
|
|
56
|
+
parentChangeVersion?: number; // New prop to track changes in parent machine name
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
interface StepDataMapping {
|
|
@@ -78,6 +80,8 @@ class FunctionForm extends Component<
|
|
|
78
80
|
parentFields: [],
|
|
79
81
|
parentFieldsChanged: false,
|
|
80
82
|
aiAssistedFields: [], // Initialize empty array for AI assisted fields
|
|
83
|
+
changedParentMachineName: '',
|
|
84
|
+
parentChangeVersion: 0,
|
|
81
85
|
};
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -411,7 +415,10 @@ class FunctionForm extends Component<
|
|
|
411
415
|
|
|
412
416
|
// Check if the field is a parent field
|
|
413
417
|
if (this.state.parentFields.includes(fieldId)) {
|
|
414
|
-
this.setState({
|
|
418
|
+
this.setState({
|
|
419
|
+
changedParentMachineName: fieldId,
|
|
420
|
+
parentChangeVersion: Date.now(),
|
|
421
|
+
});
|
|
415
422
|
}
|
|
416
423
|
|
|
417
424
|
if (this.props.customSaveCallback) {
|
|
@@ -894,7 +901,12 @@ class FunctionForm extends Component<
|
|
|
894
901
|
field.dataSourceBody,
|
|
895
902
|
this.state.dynamicFieldDataState,
|
|
896
903
|
)}
|
|
897
|
-
parentFieldsChanged=${
|
|
904
|
+
parentFieldsChanged=${field.dependsOn.length > 0 &&
|
|
905
|
+
field.dependsOn.includes(
|
|
906
|
+
this.state.changedParentMachineName,
|
|
907
|
+
)
|
|
908
|
+
? this.state.parentChangeVersion
|
|
909
|
+
: 0}
|
|
898
910
|
activityOutputData=${arrayToNestedJSONWithFirstValue(
|
|
899
911
|
JSONToActivityOutputData(this.props.variables || {}),
|
|
900
912
|
JSONToDynamicFieldData(this.props.variables || {}),
|
|
@@ -904,6 +916,8 @@ class FunctionForm extends Component<
|
|
|
904
916
|
)}
|
|
905
917
|
value=${this.state.dynamicFieldDataState[field.id] || {}}
|
|
906
918
|
isDisabled=${isAIAssisted}
|
|
919
|
+
dependsOn=${field.dependsOn}
|
|
920
|
+
isArray=${field.dataType === 'array'}
|
|
907
921
|
/>
|
|
908
922
|
`,
|
|
909
923
|
)}
|
package/src/index.ts
CHANGED
|
@@ -609,7 +609,8 @@ export class IntegryJS {
|
|
|
609
609
|
if (
|
|
610
610
|
options.connectedAccountId &&
|
|
611
611
|
!response.meta.app.connected_accounts.find(
|
|
612
|
-
(account: any) =>
|
|
612
|
+
(account: any) =>
|
|
613
|
+
Number(account.id) === Number(options.connectedAccountId),
|
|
613
614
|
)
|
|
614
615
|
) {
|
|
615
616
|
return reject(new Error('Connected account not found.'));
|
|
@@ -2055,6 +2056,11 @@ export class IntegryJS {
|
|
|
2055
2056
|
onTagSelect: () => {
|
|
2056
2057
|
// Placeholder function for future implementation
|
|
2057
2058
|
},
|
|
2059
|
+
renderValuesTab: false,
|
|
2060
|
+
options: [],
|
|
2061
|
+
onOptionClick: () => {
|
|
2062
|
+
// Placeholder function for future implementation
|
|
2063
|
+
},
|
|
2058
2064
|
},
|
|
2059
2065
|
) => {
|
|
2060
2066
|
const target = document.getElementById(options.containerId);
|
|
@@ -2074,6 +2080,9 @@ export class IntegryJS {
|
|
|
2074
2080
|
<${TagsMenu}
|
|
2075
2081
|
tagsTree=${options.tagsTree}
|
|
2076
2082
|
onSelect=${options.onTagSelect}
|
|
2083
|
+
renderValuesTab=${options.renderValuesTab}
|
|
2084
|
+
options=${options.options}
|
|
2085
|
+
onOptionClick=${options.onOptionClick}
|
|
2077
2086
|
/>
|
|
2078
2087
|
<//>
|
|
2079
2088
|
<//>
|
package/src/types/index.ts
CHANGED
|
@@ -304,6 +304,11 @@ export type RenderMappingMenuOptions = {
|
|
|
304
304
|
containerId: string;
|
|
305
305
|
tagsTree: any;
|
|
306
306
|
onTagSelect: (tag: any) => void;
|
|
307
|
+
renderValuesTab?: boolean;
|
|
308
|
+
options?: {
|
|
309
|
+
[key: string]: any;
|
|
310
|
+
};
|
|
311
|
+
onOptionClick?: (option: any) => void;
|
|
307
312
|
};
|
|
308
313
|
export type ShowFunctionOptions = {
|
|
309
314
|
params?: Record<string, any>;
|