@oneuptime/common 10.2.20 → 10.2.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/UI/Components/Workflow/ArgumentsForm.tsx +55 -12
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +143 -255
- package/UI/Components/Workflow/ModelFieldPicker.tsx +1234 -0
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +32 -10
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +57 -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";
|
|
@@ -190,15 +193,51 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
190
193
|
const isWorkflowSelect: boolean =
|
|
191
194
|
arg.type === ComponentInputType.WorkflowSelect;
|
|
192
195
|
|
|
196
|
+
/*
|
|
197
|
+
* Database Select args (the "Select Fields" / "Listen on"
|
|
198
|
+
* trigger inputs) get a tree-style field picker backed by
|
|
199
|
+
* the model's schema, instead of a raw JSON textarea. We
|
|
200
|
+
* need a tableName on the component metadata to fetch the
|
|
201
|
+
* column list; without it, fall back to the JSON editor.
|
|
202
|
+
*/
|
|
203
|
+
const useFieldPicker: boolean =
|
|
204
|
+
arg.type === ComponentInputType.Select &&
|
|
205
|
+
Boolean(component.metadata.tableName);
|
|
206
|
+
|
|
193
207
|
const baseField: {
|
|
194
208
|
fieldType: import("../Forms/Types/FormFieldSchemaType").default;
|
|
195
209
|
dropdownOptions?: Array<DropdownOption> | undefined;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
210
|
+
getCustomElement?: (
|
|
211
|
+
values: FormValues<JSONObject>,
|
|
212
|
+
customProps: CustomElementProps,
|
|
213
|
+
) => ReactElement | undefined;
|
|
214
|
+
} = useFieldPicker
|
|
215
|
+
? {
|
|
216
|
+
fieldType: FormFieldSchemaType.CustomComponent,
|
|
217
|
+
getCustomElement: (
|
|
218
|
+
_values: FormValues<JSONObject>,
|
|
219
|
+
customProps: CustomElementProps,
|
|
220
|
+
): ReactElement => {
|
|
221
|
+
return (
|
|
222
|
+
<ModelFieldPicker
|
|
223
|
+
tableName={component.metadata.tableName as string}
|
|
224
|
+
initialValue={customProps.initialValue}
|
|
225
|
+
onChange={(value: string) => {
|
|
226
|
+
void customProps.onChange?.(value);
|
|
227
|
+
}}
|
|
228
|
+
placeholder={customProps.placeholder}
|
|
229
|
+
error={customProps.error}
|
|
230
|
+
tabIndex={customProps.tabIndex}
|
|
231
|
+
/>
|
|
232
|
+
);
|
|
233
|
+
},
|
|
234
|
+
}
|
|
235
|
+
: componentInputTypeToFormFieldType(
|
|
236
|
+
arg.type,
|
|
237
|
+
component.arguments && component.arguments[arg.id]
|
|
238
|
+
? component.arguments[arg.id]
|
|
239
|
+
: null,
|
|
240
|
+
);
|
|
202
241
|
|
|
203
242
|
/*
|
|
204
243
|
* For WorkflowSelect, inject the dynamically fetched list
|
|
@@ -208,13 +247,17 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
208
247
|
baseField.dropdownOptions = workflowDropdownOptions;
|
|
209
248
|
}
|
|
210
249
|
|
|
250
|
+
/*
|
|
251
|
+
* The "pick from component / variable" footer doesn't
|
|
252
|
+
* apply to the field picker (it edits a structured object,
|
|
253
|
+
* not a free-text expression) or to WorkflowSelect.
|
|
254
|
+
*/
|
|
255
|
+
const showVariableFooter: boolean =
|
|
256
|
+
!isWorkflowSelect && !useFieldPicker;
|
|
257
|
+
|
|
211
258
|
return {
|
|
212
259
|
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 : (
|
|
260
|
+
footerElement: showVariableFooter ? (
|
|
218
261
|
<div className="text-gray-500">
|
|
219
262
|
<p className="text-sm">
|
|
220
263
|
Pick this value from other{" "}
|
|
@@ -239,7 +282,7 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
239
282
|
</button>
|
|
240
283
|
</p>
|
|
241
284
|
</div>
|
|
242
|
-
),
|
|
285
|
+
) : undefined,
|
|
243
286
|
description: `${
|
|
244
287
|
arg.required ? "Required" : "Optional"
|
|
245
288
|
}. ${arg.description}`,
|
|
@@ -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,113 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
38
68
|
const [showDeleteConfirmation, setShowDeleteConfirmation] =
|
|
39
69
|
useState<boolean>(false);
|
|
40
70
|
|
|
71
|
+
const argumentsSection: ReactElement = (
|
|
72
|
+
<SectionCard icon={IconProp.Settings} title="Configuration">
|
|
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 identitySection: ReactElement = (
|
|
91
|
+
<SectionCard
|
|
92
|
+
icon={IconProp.Label}
|
|
93
|
+
title={`${component.metadata.componentType} ID`}
|
|
94
|
+
>
|
|
95
|
+
<BasicForm
|
|
96
|
+
hideSubmitButton={true}
|
|
97
|
+
initialValues={{ id: component?.id }}
|
|
98
|
+
onChange={(values: FormValues<JSONObject>) => {
|
|
99
|
+
setComponent({ ...component, ...values });
|
|
100
|
+
}}
|
|
101
|
+
onFormValidationErrorChanged={(hasError: boolean) => {
|
|
102
|
+
setHasFormValidationErrors({
|
|
103
|
+
...hasFormValidationErrors,
|
|
104
|
+
id: hasError,
|
|
105
|
+
});
|
|
106
|
+
}}
|
|
107
|
+
fields={[
|
|
108
|
+
{
|
|
109
|
+
title: "Identifier",
|
|
110
|
+
description: `Used to reference this ${component.metadata.componentType.toLowerCase()} from other components.`,
|
|
111
|
+
field: { id: true },
|
|
112
|
+
required: true,
|
|
113
|
+
fieldType: FormFieldSchemaType.Text,
|
|
114
|
+
},
|
|
115
|
+
]}
|
|
116
|
+
/>
|
|
117
|
+
</SectionCard>
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const documentationSection: ReactElement | null = component.metadata
|
|
121
|
+
.documentationLink ? (
|
|
122
|
+
<SectionCard icon={IconProp.Book} title="Documentation" tone="info">
|
|
123
|
+
<DocumentationViewer
|
|
124
|
+
documentationLink={component.metadata.documentationLink}
|
|
125
|
+
workflowId={props.workflowId}
|
|
126
|
+
webhookSecretKey={props.webhookSecretKey}
|
|
127
|
+
/>
|
|
128
|
+
</SectionCard>
|
|
129
|
+
) : null;
|
|
130
|
+
|
|
131
|
+
const connectionsSection: ReactElement = (
|
|
132
|
+
<SectionCard icon={IconProp.Link} title="Connections">
|
|
133
|
+
<>
|
|
134
|
+
<ComponentPortViewer
|
|
135
|
+
name="In Ports"
|
|
136
|
+
description="Input connections for this component"
|
|
137
|
+
ports={component.metadata.inPorts}
|
|
138
|
+
/>
|
|
139
|
+
<ComponentPortViewer
|
|
140
|
+
name="Out Ports"
|
|
141
|
+
description="Output connections from this component"
|
|
142
|
+
ports={component.metadata.outPorts}
|
|
143
|
+
/>
|
|
144
|
+
</>
|
|
145
|
+
</SectionCard>
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const outputSection: ReactElement = (
|
|
149
|
+
<SectionCard icon={IconProp.ArrowCircleRight} title="Output">
|
|
150
|
+
<ComponentReturnValueViewer
|
|
151
|
+
name="Return Values"
|
|
152
|
+
description="Values this component produces for downstream use"
|
|
153
|
+
returnValues={component.metadata.returnValues}
|
|
154
|
+
/>
|
|
155
|
+
</SectionCard>
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const hasErrors: boolean = Object.values(hasFormValidationErrors).some(
|
|
159
|
+
(v: boolean) => {
|
|
160
|
+
return v;
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
|
|
41
164
|
return (
|
|
42
|
-
<
|
|
165
|
+
<Modal
|
|
43
166
|
title={props.title}
|
|
44
167
|
description={props.description}
|
|
45
168
|
onClose={props.onClose}
|
|
46
169
|
onSubmit={() => {
|
|
47
170
|
return component && props.onSave(component);
|
|
48
171
|
}}
|
|
172
|
+
submitButtonText="Save"
|
|
173
|
+
modalWidth={ModalWidth.Large}
|
|
174
|
+
disableSubmitButton={hasErrors}
|
|
49
175
|
leftFooterElement={
|
|
50
176
|
<Button
|
|
51
|
-
title=
|
|
177
|
+
title="Delete"
|
|
52
178
|
icon={IconProp.Trash}
|
|
53
179
|
buttonStyle={ButtonStyleType.DANGER_OUTLINE}
|
|
54
180
|
onClick={() => {
|
|
@@ -65,7 +191,7 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
65
191
|
onClose={() => {
|
|
66
192
|
setShowDeleteConfirmation(false);
|
|
67
193
|
}}
|
|
68
|
-
submitButtonText=
|
|
194
|
+
submitButtonText="Delete"
|
|
69
195
|
onSubmit={() => {
|
|
70
196
|
props.onDelete(component);
|
|
71
197
|
setShowDeleteConfirmation(false);
|
|
@@ -75,260 +201,22 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
75
201
|
/>
|
|
76
202
|
)}
|
|
77
203
|
|
|
78
|
-
{/*
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
style={{
|
|
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>
|
|
114
|
-
</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>
|
|
204
|
+
{/*
|
|
205
|
+
* Two-column layout: arguments take the main column (2/3 width on
|
|
206
|
+
* md+), metadata sits in a narrower sidebar. Collapses to one
|
|
207
|
+
* column below md.
|
|
208
|
+
*/}
|
|
209
|
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
210
|
+
<div className="md:col-span-2 space-y-4">{argumentsSection}</div>
|
|
211
|
+
<div className="md:col-span-1 space-y-4">
|
|
212
|
+
{identitySection}
|
|
213
|
+
{documentationSection}
|
|
214
|
+
{connectionsSection}
|
|
215
|
+
{outputSection}
|
|
323
216
|
</div>
|
|
324
|
-
<ComponentReturnValueViewer
|
|
325
|
-
name="Return Values"
|
|
326
|
-
description="Values this component produces for downstream use"
|
|
327
|
-
returnValues={component.metadata.returnValues}
|
|
328
|
-
/>
|
|
329
217
|
</div>
|
|
330
218
|
</>
|
|
331
|
-
</
|
|
219
|
+
</Modal>
|
|
332
220
|
);
|
|
333
221
|
};
|
|
334
222
|
|