@oneuptime/common 10.2.20 → 10.2.22
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/UI/Components/Workflow/ArgumentsForm.tsx +58 -21
- package/UI/Components/Workflow/ComponentPortViewer.tsx +8 -4
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +8 -4
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +159 -255
- package/UI/Components/Workflow/ModelFieldPicker.tsx +1234 -0
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +35 -15
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js +4 -4
- package/build/dist/UI/Components/Workflow/ComponentPortViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +4 -4
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +69 -145
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +694 -0
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import ComponentLoader from "../ComponentLoader/ComponentLoader";
|
|
2
2
|
import ErrorMessage from "../ErrorMessage/ErrorMessage";
|
|
3
3
|
import BasicForm, { FormProps } from "../Forms/BasicForm";
|
|
4
|
+
import FormFieldSchemaType from "../Forms/Types/FormFieldSchemaType";
|
|
5
|
+
import { CustomElementProps } from "../Forms/Types/Field";
|
|
4
6
|
import FormValues from "../Forms/Types/FormValues";
|
|
5
7
|
import ComponentValuePickerModal from "./ComponentValuePickerModal";
|
|
8
|
+
import ModelFieldPicker from "./ModelFieldPicker";
|
|
6
9
|
import { componentInputTypeToFormFieldType } from "./Utils";
|
|
7
10
|
import VariableModal from "./VariableModal";
|
|
8
11
|
import Dictionary from "../../../Types/Dictionary";
|
|
@@ -140,17 +143,11 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
140
143
|
}, [component]);
|
|
141
144
|
|
|
142
145
|
return (
|
|
143
|
-
<div
|
|
144
|
-
<div
|
|
145
|
-
<h2 className="text-base font-medium text-gray-500">Arguments</h2>
|
|
146
|
-
<p className="text-sm font-medium text-gray-400 mb-5">
|
|
147
|
-
Arguments for this component
|
|
148
|
-
</p>
|
|
146
|
+
<div>
|
|
147
|
+
<div>
|
|
149
148
|
{component.metadata.arguments &&
|
|
150
149
|
component.metadata.arguments.length === 0 && (
|
|
151
|
-
<ErrorMessage
|
|
152
|
-
message={"This component does not take any arguments."}
|
|
153
|
-
/>
|
|
150
|
+
<ErrorMessage message={"This step does not need any settings."} />
|
|
154
151
|
)}
|
|
155
152
|
{/*
|
|
156
153
|
If any argument is a WorkflowSelect and we're still fetching the
|
|
@@ -190,15 +187,51 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
190
187
|
const isWorkflowSelect: boolean =
|
|
191
188
|
arg.type === ComponentInputType.WorkflowSelect;
|
|
192
189
|
|
|
190
|
+
/*
|
|
191
|
+
* Database Select args (the "Select Fields" / "Listen on"
|
|
192
|
+
* trigger inputs) get a tree-style field picker backed by
|
|
193
|
+
* the model's schema, instead of a raw JSON textarea. We
|
|
194
|
+
* need a tableName on the component metadata to fetch the
|
|
195
|
+
* column list; without it, fall back to the JSON editor.
|
|
196
|
+
*/
|
|
197
|
+
const useFieldPicker: boolean =
|
|
198
|
+
arg.type === ComponentInputType.Select &&
|
|
199
|
+
Boolean(component.metadata.tableName);
|
|
200
|
+
|
|
193
201
|
const baseField: {
|
|
194
202
|
fieldType: import("../Forms/Types/FormFieldSchemaType").default;
|
|
195
203
|
dropdownOptions?: Array<DropdownOption> | undefined;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
204
|
+
getCustomElement?: (
|
|
205
|
+
values: FormValues<JSONObject>,
|
|
206
|
+
customProps: CustomElementProps,
|
|
207
|
+
) => ReactElement | undefined;
|
|
208
|
+
} = useFieldPicker
|
|
209
|
+
? {
|
|
210
|
+
fieldType: FormFieldSchemaType.CustomComponent,
|
|
211
|
+
getCustomElement: (
|
|
212
|
+
_values: FormValues<JSONObject>,
|
|
213
|
+
customProps: CustomElementProps,
|
|
214
|
+
): ReactElement => {
|
|
215
|
+
return (
|
|
216
|
+
<ModelFieldPicker
|
|
217
|
+
tableName={component.metadata.tableName as string}
|
|
218
|
+
initialValue={customProps.initialValue}
|
|
219
|
+
onChange={(value: string) => {
|
|
220
|
+
void customProps.onChange?.(value);
|
|
221
|
+
}}
|
|
222
|
+
placeholder={customProps.placeholder}
|
|
223
|
+
error={customProps.error}
|
|
224
|
+
tabIndex={customProps.tabIndex}
|
|
225
|
+
/>
|
|
226
|
+
);
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
: componentInputTypeToFormFieldType(
|
|
230
|
+
arg.type,
|
|
231
|
+
component.arguments && component.arguments[arg.id]
|
|
232
|
+
? component.arguments[arg.id]
|
|
233
|
+
: null,
|
|
234
|
+
);
|
|
202
235
|
|
|
203
236
|
/*
|
|
204
237
|
* For WorkflowSelect, inject the dynamically fetched list
|
|
@@ -208,13 +241,17 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
208
241
|
baseField.dropdownOptions = workflowDropdownOptions;
|
|
209
242
|
}
|
|
210
243
|
|
|
244
|
+
/*
|
|
245
|
+
* The "pick from component / variable" footer doesn't
|
|
246
|
+
* apply to the field picker (it edits a structured object,
|
|
247
|
+
* not a free-text expression) or to WorkflowSelect.
|
|
248
|
+
*/
|
|
249
|
+
const showVariableFooter: boolean =
|
|
250
|
+
!isWorkflowSelect && !useFieldPicker;
|
|
251
|
+
|
|
211
252
|
return {
|
|
212
253
|
title: `${arg.name}`,
|
|
213
|
-
|
|
214
|
-
* WorkflowSelect has no "pick from component/variable"
|
|
215
|
-
* footer — it's a bound dropdown, not a free-text field.
|
|
216
|
-
*/
|
|
217
|
-
footerElement: isWorkflowSelect ? undefined : (
|
|
254
|
+
footerElement: showVariableFooter ? (
|
|
218
255
|
<div className="text-gray-500">
|
|
219
256
|
<p className="text-sm">
|
|
220
257
|
Pick this value from other{" "}
|
|
@@ -239,7 +276,7 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
239
276
|
</button>
|
|
240
277
|
</p>
|
|
241
278
|
</div>
|
|
242
|
-
),
|
|
279
|
+
) : undefined,
|
|
243
280
|
description: `${
|
|
244
281
|
arg.required ? "Required" : "Optional"
|
|
245
282
|
}. ${arg.description}`,
|
|
@@ -11,11 +11,15 @@ const ComponentPortViewer: FunctionComponent<ComponentProps> = (
|
|
|
11
11
|
props: ComponentProps,
|
|
12
12
|
): ReactElement => {
|
|
13
13
|
return (
|
|
14
|
-
<div
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
<div>
|
|
15
|
+
{props.name && (
|
|
16
|
+
<h2 className="text-sm font-semibold text-gray-600">{props.name}</h2>
|
|
17
|
+
)}
|
|
18
|
+
{props.description && (
|
|
19
|
+
<p className="text-xs text-gray-400 mb-2">{props.description}</p>
|
|
20
|
+
)}
|
|
17
21
|
{props.ports && props.ports.length === 0 && (
|
|
18
|
-
<p className="text-xs text-gray-400 italic">No
|
|
22
|
+
<p className="text-xs text-gray-400 italic">No connections.</p>
|
|
19
23
|
)}
|
|
20
24
|
<div>
|
|
21
25
|
{props.ports &&
|
|
@@ -11,12 +11,16 @@ const ComponentReturnValueViewer: FunctionComponent<ComponentProps> = (
|
|
|
11
11
|
props: ComponentProps,
|
|
12
12
|
): ReactElement => {
|
|
13
13
|
return (
|
|
14
|
-
<div
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
<div>
|
|
15
|
+
{props.name && (
|
|
16
|
+
<h2 className="text-sm font-semibold text-gray-600">{props.name}</h2>
|
|
17
|
+
)}
|
|
18
|
+
{props.description && (
|
|
19
|
+
<p className="text-xs text-gray-400 mb-2">{props.description}</p>
|
|
20
|
+
)}
|
|
17
21
|
{props.returnValues && props.returnValues.length === 0 && (
|
|
18
22
|
<p className="text-xs text-gray-400 italic">
|
|
19
|
-
This
|
|
23
|
+
This step does not return any data.
|
|
20
24
|
</p>
|
|
21
25
|
)}
|
|
22
26
|
<div>
|
|
@@ -3,7 +3,7 @@ import BasicForm from "../Forms/BasicForm";
|
|
|
3
3
|
import FormFieldSchemaType from "../Forms/Types/FormFieldSchemaType";
|
|
4
4
|
import FormValues from "../Forms/Types/FormValues";
|
|
5
5
|
import ConfirmModal from "../Modal/ConfirmModal";
|
|
6
|
-
import
|
|
6
|
+
import Modal, { ModalWidth } from "../Modal/Modal";
|
|
7
7
|
import ArgumentsForm from "./ArgumentsForm";
|
|
8
8
|
import ComponentPortViewer from "./ComponentPortViewer";
|
|
9
9
|
import ComponentReturnValueViewer from "./ComponentReturnValueViewer";
|
|
@@ -28,6 +28,36 @@ export interface ComponentProps {
|
|
|
28
28
|
webhookSecretKey?: string | undefined;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
interface SectionCardProps {
|
|
32
|
+
icon: IconProp;
|
|
33
|
+
title: string;
|
|
34
|
+
children: ReactElement | Array<ReactElement>;
|
|
35
|
+
tone?: "default" | "info" | undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const SectionCard: FunctionComponent<SectionCardProps> = (
|
|
39
|
+
props: SectionCardProps,
|
|
40
|
+
): ReactElement => {
|
|
41
|
+
const isInfo: boolean = props.tone === "info";
|
|
42
|
+
const containerClass: string = isInfo
|
|
43
|
+
? "rounded-lg border border-blue-100 bg-blue-50/40 p-4"
|
|
44
|
+
: "rounded-lg border border-gray-200 bg-white p-4";
|
|
45
|
+
const iconClass: string = isInfo ? "text-blue-500" : "text-gray-400";
|
|
46
|
+
const titleClass: string = isInfo
|
|
47
|
+
? "text-[11px] font-semibold uppercase tracking-wider text-blue-700"
|
|
48
|
+
: "text-[11px] font-semibold uppercase tracking-wider text-gray-500";
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div className={containerClass}>
|
|
52
|
+
<div className="flex items-center gap-1.5 mb-3">
|
|
53
|
+
<Icon icon={props.icon} className={`h-3.5 w-3.5 ${iconClass}`} />
|
|
54
|
+
<span className={titleClass}>{props.title}</span>
|
|
55
|
+
</div>
|
|
56
|
+
{props.children}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
31
61
|
const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
32
62
|
props: ComponentProps,
|
|
33
63
|
): ReactElement => {
|
|
@@ -38,17 +68,128 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
38
68
|
const [showDeleteConfirmation, setShowDeleteConfirmation] =
|
|
39
69
|
useState<boolean>(false);
|
|
40
70
|
|
|
71
|
+
const settingsSection: ReactElement = (
|
|
72
|
+
<SectionCard icon={IconProp.Settings} title="Settings">
|
|
73
|
+
<ArgumentsForm
|
|
74
|
+
graphComponents={props.graphComponents}
|
|
75
|
+
workflowId={props.workflowId}
|
|
76
|
+
component={component}
|
|
77
|
+
onFormChange={(c: NodeDataProp) => {
|
|
78
|
+
setComponent({ ...c });
|
|
79
|
+
}}
|
|
80
|
+
onHasFormValidationErrors={(value: Dictionary<boolean>) => {
|
|
81
|
+
setHasFormValidationErrors({
|
|
82
|
+
...hasFormValidationErrors,
|
|
83
|
+
...value,
|
|
84
|
+
});
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
</SectionCard>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const idSection: ReactElement = (
|
|
91
|
+
<SectionCard icon={IconProp.Label} title="ID">
|
|
92
|
+
<BasicForm
|
|
93
|
+
hideSubmitButton={true}
|
|
94
|
+
initialValues={{ id: component?.id }}
|
|
95
|
+
onChange={(values: FormValues<JSONObject>) => {
|
|
96
|
+
setComponent({ ...component, ...values });
|
|
97
|
+
}}
|
|
98
|
+
onFormValidationErrorChanged={(hasError: boolean) => {
|
|
99
|
+
setHasFormValidationErrors({
|
|
100
|
+
...hasFormValidationErrors,
|
|
101
|
+
id: hasError,
|
|
102
|
+
});
|
|
103
|
+
}}
|
|
104
|
+
fields={[
|
|
105
|
+
{
|
|
106
|
+
title: "Identifier",
|
|
107
|
+
description: `Used to reference this ${component.metadata.componentType.toLowerCase()} from other steps.`,
|
|
108
|
+
field: { id: true },
|
|
109
|
+
required: true,
|
|
110
|
+
fieldType: FormFieldSchemaType.Text,
|
|
111
|
+
},
|
|
112
|
+
]}
|
|
113
|
+
/>
|
|
114
|
+
</SectionCard>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const documentationSection: ReactElement | null = component.metadata
|
|
118
|
+
.documentationLink ? (
|
|
119
|
+
<SectionCard icon={IconProp.Book} title="Documentation" tone="info">
|
|
120
|
+
<DocumentationViewer
|
|
121
|
+
documentationLink={component.metadata.documentationLink}
|
|
122
|
+
workflowId={props.workflowId}
|
|
123
|
+
webhookSecretKey={props.webhookSecretKey}
|
|
124
|
+
/>
|
|
125
|
+
</SectionCard>
|
|
126
|
+
) : null;
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* Each connection/output card is only rendered if there's something to
|
|
130
|
+
* show — keeps the sidebar lean for triggers (no inputs) and components
|
|
131
|
+
* that don't return any data.
|
|
132
|
+
*/
|
|
133
|
+
const hasInputs: boolean =
|
|
134
|
+
Array.isArray(component.metadata.inPorts) &&
|
|
135
|
+
component.metadata.inPorts.length > 0;
|
|
136
|
+
const hasOutputs: boolean =
|
|
137
|
+
Array.isArray(component.metadata.outPorts) &&
|
|
138
|
+
component.metadata.outPorts.length > 0;
|
|
139
|
+
const hasReturns: boolean =
|
|
140
|
+
Array.isArray(component.metadata.returnValues) &&
|
|
141
|
+
component.metadata.returnValues.length > 0;
|
|
142
|
+
|
|
143
|
+
const inputsSection: ReactElement | null = hasInputs ? (
|
|
144
|
+
<SectionCard icon={IconProp.ArrowCircleDown} title="Inputs">
|
|
145
|
+
<ComponentPortViewer
|
|
146
|
+
name=""
|
|
147
|
+
description="Where this step is reached from."
|
|
148
|
+
ports={component.metadata.inPorts}
|
|
149
|
+
/>
|
|
150
|
+
</SectionCard>
|
|
151
|
+
) : null;
|
|
152
|
+
|
|
153
|
+
const outputsSection: ReactElement | null = hasOutputs ? (
|
|
154
|
+
<SectionCard icon={IconProp.ArrowCircleRight} title="Outputs">
|
|
155
|
+
<ComponentPortViewer
|
|
156
|
+
name=""
|
|
157
|
+
description="What runs after this step."
|
|
158
|
+
ports={component.metadata.outPorts}
|
|
159
|
+
/>
|
|
160
|
+
</SectionCard>
|
|
161
|
+
) : null;
|
|
162
|
+
|
|
163
|
+
const returnsSection: ReactElement | null = hasReturns ? (
|
|
164
|
+
<SectionCard icon={IconProp.Database} title="Returns">
|
|
165
|
+
<ComponentReturnValueViewer
|
|
166
|
+
name=""
|
|
167
|
+
description="Data this step makes available downstream."
|
|
168
|
+
returnValues={component.metadata.returnValues}
|
|
169
|
+
/>
|
|
170
|
+
</SectionCard>
|
|
171
|
+
) : null;
|
|
172
|
+
|
|
173
|
+
const hasErrors: boolean = Object.values(hasFormValidationErrors).some(
|
|
174
|
+
(v: boolean) => {
|
|
175
|
+
return v;
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
41
179
|
return (
|
|
42
|
-
<
|
|
180
|
+
<Modal
|
|
43
181
|
title={props.title}
|
|
44
182
|
description={props.description}
|
|
45
183
|
onClose={props.onClose}
|
|
46
184
|
onSubmit={() => {
|
|
47
185
|
return component && props.onSave(component);
|
|
48
186
|
}}
|
|
187
|
+
submitButtonText="Save"
|
|
188
|
+
modalWidth={ModalWidth.Large}
|
|
189
|
+
disableSubmitButton={hasErrors}
|
|
49
190
|
leftFooterElement={
|
|
50
191
|
<Button
|
|
51
|
-
title=
|
|
192
|
+
title="Delete"
|
|
52
193
|
icon={IconProp.Trash}
|
|
53
194
|
buttonStyle={ButtonStyleType.DANGER_OUTLINE}
|
|
54
195
|
onClick={() => {
|
|
@@ -65,7 +206,7 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
65
206
|
onClose={() => {
|
|
66
207
|
setShowDeleteConfirmation(false);
|
|
67
208
|
}}
|
|
68
|
-
submitButtonText=
|
|
209
|
+
submitButtonText="Delete"
|
|
69
210
|
onSubmit={() => {
|
|
70
211
|
props.onDelete(component);
|
|
71
212
|
setShowDeleteConfirmation(false);
|
|
@@ -75,260 +216,23 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
75
216
|
/>
|
|
76
217
|
)}
|
|
77
218
|
|
|
78
|
-
{/*
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
display: "flex",
|
|
92
|
-
alignItems: "center",
|
|
93
|
-
gap: "0.5rem",
|
|
94
|
-
marginBottom: "0.5rem",
|
|
95
|
-
}}
|
|
96
|
-
>
|
|
97
|
-
<Icon
|
|
98
|
-
icon={IconProp.Label}
|
|
99
|
-
style={{
|
|
100
|
-
color: "#64748b",
|
|
101
|
-
width: "0.875rem",
|
|
102
|
-
height: "0.875rem",
|
|
103
|
-
}}
|
|
104
|
-
/>
|
|
105
|
-
<span
|
|
106
|
-
style={{
|
|
107
|
-
fontSize: "0.8125rem",
|
|
108
|
-
fontWeight: 600,
|
|
109
|
-
color: "#334155",
|
|
110
|
-
}}
|
|
111
|
-
>
|
|
112
|
-
Identity
|
|
113
|
-
</span>
|
|
219
|
+
{/*
|
|
220
|
+
* Two-column layout: arguments take the main column (2/3 width on
|
|
221
|
+
* md+), metadata sits in a narrower sidebar. Collapses to one
|
|
222
|
+
* column below md.
|
|
223
|
+
*/}
|
|
224
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
225
|
+
<div className="md:col-span-2 space-y-4">{settingsSection}</div>
|
|
226
|
+
<div className="md:col-span-1 space-y-4">
|
|
227
|
+
{idSection}
|
|
228
|
+
{documentationSection}
|
|
229
|
+
{inputsSection}
|
|
230
|
+
{outputsSection}
|
|
231
|
+
{returnsSection}
|
|
114
232
|
</div>
|
|
115
|
-
<BasicForm
|
|
116
|
-
hideSubmitButton={true}
|
|
117
|
-
initialValues={{
|
|
118
|
-
id: component?.id,
|
|
119
|
-
}}
|
|
120
|
-
onChange={(values: FormValues<JSONObject>) => {
|
|
121
|
-
setComponent({ ...component, ...values });
|
|
122
|
-
}}
|
|
123
|
-
onFormValidationErrorChanged={(hasError: boolean) => {
|
|
124
|
-
setHasFormValidationErrors({
|
|
125
|
-
...hasFormValidationErrors,
|
|
126
|
-
id: hasError,
|
|
127
|
-
});
|
|
128
|
-
}}
|
|
129
|
-
fields={[
|
|
130
|
-
{
|
|
131
|
-
title: `${component.metadata.componentType} ID`,
|
|
132
|
-
description: `Unique identifier used to reference this ${component.metadata.componentType.toLowerCase()} from other components.`,
|
|
133
|
-
field: {
|
|
134
|
-
id: true,
|
|
135
|
-
},
|
|
136
|
-
required: true,
|
|
137
|
-
fieldType: FormFieldSchemaType.Text,
|
|
138
|
-
},
|
|
139
|
-
]}
|
|
140
|
-
/>
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
{/* Documentation Section */}
|
|
144
|
-
{component.metadata.documentationLink && (
|
|
145
|
-
<div
|
|
146
|
-
style={{
|
|
147
|
-
backgroundColor: "#eff6ff",
|
|
148
|
-
borderRadius: "10px",
|
|
149
|
-
border: "1px solid #bfdbfe",
|
|
150
|
-
padding: "1rem",
|
|
151
|
-
marginBottom: "1rem",
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
<div
|
|
155
|
-
style={{
|
|
156
|
-
display: "flex",
|
|
157
|
-
alignItems: "center",
|
|
158
|
-
gap: "0.5rem",
|
|
159
|
-
marginBottom: "0.5rem",
|
|
160
|
-
}}
|
|
161
|
-
>
|
|
162
|
-
<Icon
|
|
163
|
-
icon={IconProp.Book}
|
|
164
|
-
style={{
|
|
165
|
-
color: "#3b82f6",
|
|
166
|
-
width: "0.875rem",
|
|
167
|
-
height: "0.875rem",
|
|
168
|
-
}}
|
|
169
|
-
/>
|
|
170
|
-
<span
|
|
171
|
-
style={{
|
|
172
|
-
fontSize: "0.8125rem",
|
|
173
|
-
fontWeight: 600,
|
|
174
|
-
color: "#1e40af",
|
|
175
|
-
}}
|
|
176
|
-
>
|
|
177
|
-
Documentation
|
|
178
|
-
</span>
|
|
179
|
-
</div>
|
|
180
|
-
<DocumentationViewer
|
|
181
|
-
documentationLink={component.metadata.documentationLink}
|
|
182
|
-
workflowId={props.workflowId}
|
|
183
|
-
webhookSecretKey={props.webhookSecretKey}
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
)}
|
|
187
|
-
|
|
188
|
-
{/* Arguments Section */}
|
|
189
|
-
<div
|
|
190
|
-
style={{
|
|
191
|
-
backgroundColor: "#ffffff",
|
|
192
|
-
borderRadius: "10px",
|
|
193
|
-
border: "1px solid #e2e8f0",
|
|
194
|
-
padding: "1rem",
|
|
195
|
-
marginBottom: "1rem",
|
|
196
|
-
}}
|
|
197
|
-
>
|
|
198
|
-
<div
|
|
199
|
-
style={{
|
|
200
|
-
display: "flex",
|
|
201
|
-
alignItems: "center",
|
|
202
|
-
gap: "0.5rem",
|
|
203
|
-
marginBottom: "0.75rem",
|
|
204
|
-
}}
|
|
205
|
-
>
|
|
206
|
-
<Icon
|
|
207
|
-
icon={IconProp.Settings}
|
|
208
|
-
style={{
|
|
209
|
-
color: "#64748b",
|
|
210
|
-
width: "0.875rem",
|
|
211
|
-
height: "0.875rem",
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
<span
|
|
215
|
-
style={{
|
|
216
|
-
fontSize: "0.8125rem",
|
|
217
|
-
fontWeight: 600,
|
|
218
|
-
color: "#334155",
|
|
219
|
-
}}
|
|
220
|
-
>
|
|
221
|
-
Configuration
|
|
222
|
-
</span>
|
|
223
|
-
</div>
|
|
224
|
-
<ArgumentsForm
|
|
225
|
-
graphComponents={props.graphComponents}
|
|
226
|
-
workflowId={props.workflowId}
|
|
227
|
-
component={component}
|
|
228
|
-
onFormChange={(component: NodeDataProp) => {
|
|
229
|
-
setComponent({ ...component });
|
|
230
|
-
}}
|
|
231
|
-
onHasFormValidationErrors={(value: Dictionary<boolean>) => {
|
|
232
|
-
setHasFormValidationErrors({
|
|
233
|
-
...hasFormValidationErrors,
|
|
234
|
-
...value,
|
|
235
|
-
});
|
|
236
|
-
}}
|
|
237
|
-
/>
|
|
238
|
-
</div>
|
|
239
|
-
|
|
240
|
-
{/* Ports Section */}
|
|
241
|
-
<div
|
|
242
|
-
style={{
|
|
243
|
-
backgroundColor: "#ffffff",
|
|
244
|
-
borderRadius: "10px",
|
|
245
|
-
border: "1px solid #e2e8f0",
|
|
246
|
-
padding: "1rem",
|
|
247
|
-
marginBottom: "1rem",
|
|
248
|
-
}}
|
|
249
|
-
>
|
|
250
|
-
<div
|
|
251
|
-
style={{
|
|
252
|
-
display: "flex",
|
|
253
|
-
alignItems: "center",
|
|
254
|
-
gap: "0.5rem",
|
|
255
|
-
marginBottom: "0.25rem",
|
|
256
|
-
}}
|
|
257
|
-
>
|
|
258
|
-
<Icon
|
|
259
|
-
icon={IconProp.Link}
|
|
260
|
-
style={{
|
|
261
|
-
color: "#64748b",
|
|
262
|
-
width: "0.875rem",
|
|
263
|
-
height: "0.875rem",
|
|
264
|
-
}}
|
|
265
|
-
/>
|
|
266
|
-
<span
|
|
267
|
-
style={{
|
|
268
|
-
fontSize: "0.8125rem",
|
|
269
|
-
fontWeight: 600,
|
|
270
|
-
color: "#334155",
|
|
271
|
-
}}
|
|
272
|
-
>
|
|
273
|
-
Connections
|
|
274
|
-
</span>
|
|
275
|
-
</div>
|
|
276
|
-
<ComponentPortViewer
|
|
277
|
-
name="In Ports"
|
|
278
|
-
description="Input connections for this component"
|
|
279
|
-
ports={component.metadata.inPorts}
|
|
280
|
-
/>
|
|
281
|
-
<ComponentPortViewer
|
|
282
|
-
name="Out Ports"
|
|
283
|
-
description="Output connections from this component"
|
|
284
|
-
ports={component.metadata.outPorts}
|
|
285
|
-
/>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
{/* Return Values Section */}
|
|
289
|
-
<div
|
|
290
|
-
style={{
|
|
291
|
-
backgroundColor: "#ffffff",
|
|
292
|
-
borderRadius: "10px",
|
|
293
|
-
border: "1px solid #e2e8f0",
|
|
294
|
-
padding: "1rem",
|
|
295
|
-
marginBottom: "1rem",
|
|
296
|
-
}}
|
|
297
|
-
>
|
|
298
|
-
<div
|
|
299
|
-
style={{
|
|
300
|
-
display: "flex",
|
|
301
|
-
alignItems: "center",
|
|
302
|
-
gap: "0.5rem",
|
|
303
|
-
marginBottom: "0.25rem",
|
|
304
|
-
}}
|
|
305
|
-
>
|
|
306
|
-
<Icon
|
|
307
|
-
icon={IconProp.ArrowCircleRight}
|
|
308
|
-
style={{
|
|
309
|
-
color: "#64748b",
|
|
310
|
-
width: "0.875rem",
|
|
311
|
-
height: "0.875rem",
|
|
312
|
-
}}
|
|
313
|
-
/>
|
|
314
|
-
<span
|
|
315
|
-
style={{
|
|
316
|
-
fontSize: "0.8125rem",
|
|
317
|
-
fontWeight: 600,
|
|
318
|
-
color: "#334155",
|
|
319
|
-
}}
|
|
320
|
-
>
|
|
321
|
-
Output
|
|
322
|
-
</span>
|
|
323
|
-
</div>
|
|
324
|
-
<ComponentReturnValueViewer
|
|
325
|
-
name="Return Values"
|
|
326
|
-
description="Values this component produces for downstream use"
|
|
327
|
-
returnValues={component.metadata.returnValues}
|
|
328
|
-
/>
|
|
329
233
|
</div>
|
|
330
234
|
</>
|
|
331
|
-
</
|
|
235
|
+
</Modal>
|
|
332
236
|
);
|
|
333
237
|
};
|
|
334
238
|
|