@oneuptime/common 12.0.7 → 12.0.8
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/Models/DatabaseModels/TelemetryEntity.ts +45 -0
- package/Models/DatabaseModels/TelemetryEntityRelationship.ts +26 -0
- package/Models/DatabaseModels/WorkflowLog.ts +38 -0
- package/Server/API/UserAPI.ts +16 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +11 -6
- package/Server/Services/TelemetryEntityRelationshipService.ts +3 -0
- package/Server/Services/TelemetryEntityService.ts +114 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +44 -1
- package/Server/Types/Workflow/TriggerCode.ts +12 -0
- package/Server/Types/Workflow/Workflow.ts +5 -0
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +689 -0
- package/Server/Utils/VM/VMAPI.ts +56 -8
- package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +574 -0
- package/Tests/Server/API/UserProjectsAPI.test.ts +478 -4
- package/Tests/Server/Services/TelemetryEntityManualCreate.test.ts +248 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentHeaders.test.ts +192 -0
- package/Tests/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.test.ts +152 -0
- package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +322 -0
- package/Tests/Server/Utils/VM/VMAPISubstitution.test.ts +243 -0
- package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +197 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +140 -0
- package/Tests/Types/Workflow/StepTrace.test.ts +235 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +379 -0
- package/Tests/Types/Workflow/Templates.test.ts +403 -0
- package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +459 -0
- package/Tests/UI/Components/DictionaryAttributeFilterRow.test.tsx +477 -0
- package/Tests/UI/Components/Forms/AnchoredFieldPopupKeyboard.test.tsx +382 -0
- package/Tests/UI/Components/Forms/ColorPickerPicking.test.tsx +569 -0
- package/Tests/UI/Components/Forms/ValidationJSON.test.ts +241 -0
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +42 -0
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +90 -0
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +49 -7
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +325 -0
- package/Tests/UI/Components/Workflow/GraphLint.test.ts +821 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +287 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +185 -0
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +174 -0
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +152 -0
- package/Tests/UI/Components/Workflow/Utils.test.ts +192 -0
- package/Tests/UI/Monitor/MonitorStepCriteriaView.test.tsx +432 -0
- package/Tests/Utils/Monitor/NetworkDeviceRoleUtil.test.ts +514 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +240 -0
- package/Tests/Utils/Schema/AnalyticsModelSchema.test.ts +469 -0
- package/Tests/Utils/Schema/ModelSchema.test.ts +268 -0
- package/Tests/Utils/Telemetry/EntityKeyNonTelemetry.test.ts +193 -0
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -0
- package/Types/SerializableObjectDictionary.ts +133 -39
- package/Types/Telemetry/EntitySource.ts +40 -0
- package/Types/Telemetry/EntityType.ts +27 -0
- package/Types/Telemetry/EntityTypeGroups.ts +65 -0
- package/Types/Workflow/Component.ts +29 -0
- package/Types/Workflow/Components/API.ts +35 -0
- package/Types/Workflow/Components/BaseModel.ts +7 -3
- package/Types/Workflow/StepTrace.ts +181 -0
- package/Types/Workflow/TemplateSyntax.ts +499 -0
- package/Types/Workflow/Templates.ts +316 -0
- package/UI/Components/Date/CustomTimeRangeModal.tsx +278 -0
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +250 -0
- package/UI/Components/Dictionary/Dictionary.tsx +23 -6
- package/UI/Components/Forms/Fields/ColorPicker.tsx +66 -10
- package/UI/Components/Forms/Fields/IconPicker.tsx +48 -10
- package/UI/Components/Forms/Types/Field.ts +7 -0
- package/UI/Components/Forms/Validation.ts +63 -1
- package/UI/Components/Input/Input.tsx +31 -3
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +11 -216
- package/UI/Components/Modal/Modal.tsx +37 -4
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +11 -210
- package/UI/Components/Workflow/ArgumentsForm.tsx +194 -7
- package/UI/Components/Workflow/Component.tsx +28 -26
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +69 -8
- package/UI/Components/Workflow/GraphLint.ts +591 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +396 -0
- package/UI/Components/Workflow/ModelSchema.ts +196 -0
- package/UI/Components/Workflow/RunForm.tsx +41 -7
- package/UI/Components/Workflow/RunStatusWatcher.ts +122 -0
- package/UI/Components/Workflow/StepTraceViewer.tsx +186 -0
- package/UI/Components/Workflow/Utils.ts +93 -1
- package/UI/Components/Workflow/Workflow.tsx +77 -4
- package/UI/Types/LayeredDismissal.ts +31 -0
- package/UI/Types/UseAnchoredFieldPopup.ts +99 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +533 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +45 -7
- package/Utils/Telemetry/EntityKey.ts +66 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js +47 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js +27 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLog.js +39 -0
- package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +16 -1
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -6
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +3 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +91 -1
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +28 -0
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +507 -0
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js +51 -4
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Types/SerializableObjectDictionary.js +133 -39
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/EntitySource.js +39 -0
- package/build/dist/Types/Telemetry/EntitySource.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +27 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js +57 -0
- package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -0
- package/build/dist/Types/Workflow/Component.js +21 -0
- package/build/dist/Types/Workflow/Component.js.map +1 -1
- package/build/dist/Types/Workflow/Components/API.js +35 -0
- package/build/dist/Types/Workflow/Components/API.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +7 -3
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/StepTrace.js +104 -0
- package/build/dist/Types/Workflow/StepTrace.js.map +1 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js +326 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -0
- package/build/dist/Types/Workflow/Templates.js +218 -0
- package/build/dist/Types/Workflow/Templates.js.map +1 -0
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +126 -0
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +123 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -0
- package/build/dist/UI/Components/Dictionary/Dictionary.js +22 -6
- package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +52 -13
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -12
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +44 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +12 -4
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +5 -108
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +31 -5
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +5 -105
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +140 -11
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Component.js +20 -19
- package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +31 -3
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +396 -0
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +225 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js +118 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -0
- package/build/dist/UI/Components/Workflow/RunForm.js +22 -6
- package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +76 -0
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +76 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -0
- package/build/dist/UI/Components/Workflow/Utils.js +73 -1
- package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +51 -6
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Types/LayeredDismissal.js +21 -0
- package/build/dist/UI/Types/LayeredDismissal.js.map +1 -0
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js +74 -1
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +386 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +35 -6
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityKey.js +52 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,8 +6,12 @@ import { CustomElementProps } from "../Forms/Types/Field";
|
|
|
6
6
|
import FormValues from "../Forms/Types/FormValues";
|
|
7
7
|
import ComponentValuePickerModal from "./ComponentValuePickerModal";
|
|
8
8
|
import CronScheduleField from "./CronScheduleField";
|
|
9
|
+
import ModelColumnEditor, { ModelColumnEditorMode } from "./ModelColumnEditor";
|
|
9
10
|
import ModelFieldPicker from "./ModelFieldPicker";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
componentInputTypeToFormFieldType,
|
|
13
|
+
parseStringDictionaryValue,
|
|
14
|
+
} from "./Utils";
|
|
11
15
|
import VariableModal from "./VariableModal";
|
|
12
16
|
import Dictionary from "../../../Types/Dictionary";
|
|
13
17
|
import { JSONObject } from "../../../Types/JSON";
|
|
@@ -16,6 +20,7 @@ import {
|
|
|
16
20
|
Argument,
|
|
17
21
|
ComponentInputType,
|
|
18
22
|
NodeDataProp,
|
|
23
|
+
isJSON5ToleratedInputType,
|
|
19
24
|
} from "../../../Types/Workflow/Component";
|
|
20
25
|
import { DropdownOption } from "../Dropdown/Dropdown";
|
|
21
26
|
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
|
|
@@ -53,6 +58,96 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
53
58
|
|
|
54
59
|
const [selectedArgId, setSelectedArgId] = useState<string>("");
|
|
55
60
|
|
|
61
|
+
/*
|
|
62
|
+
* Arguments flagged isAdvanced are collapsed behind a disclosure, so the
|
|
63
|
+
* settings panel opens on the two or three fields that actually decide what
|
|
64
|
+
* the step does rather than on every knob it has. A required argument is
|
|
65
|
+
* never collapsed no matter how it is flagged: BasicForm skips validation
|
|
66
|
+
* for a field hidden by showIf, so hiding a required one would let an
|
|
67
|
+
* incomplete step save cleanly.
|
|
68
|
+
*/
|
|
69
|
+
const collapsibleAdvancedArguments: Array<Argument> = (
|
|
70
|
+
component.metadata.arguments || []
|
|
71
|
+
).filter((arg: Argument) => {
|
|
72
|
+
return Boolean(arg.isAdvanced) && !arg.required;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const hasValueForArgument: (arg: Argument) => boolean = (
|
|
76
|
+
arg: Argument,
|
|
77
|
+
): boolean => {
|
|
78
|
+
const value: unknown = component.arguments
|
|
79
|
+
? component.arguments[arg.id]
|
|
80
|
+
: undefined;
|
|
81
|
+
|
|
82
|
+
if (value === undefined || value === null) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (typeof value === "string") {
|
|
87
|
+
return value.trim() !== "";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (typeof value === "object") {
|
|
91
|
+
return Object.keys(value as JSONObject).length > 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return true;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* Open on load when something down there is already set, so an existing
|
|
99
|
+
* configuration is never hidden from the person who comes back to read it.
|
|
100
|
+
*/
|
|
101
|
+
const [showAdvanced, setShowAdvanced] = useState<boolean>(
|
|
102
|
+
collapsibleAdvancedArguments.some(hasValueForArgument),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const isCollapsibleAdvanced: (arg: Argument) => boolean = (
|
|
106
|
+
arg: Argument,
|
|
107
|
+
): boolean => {
|
|
108
|
+
return collapsibleAdvancedArguments.some((advancedArg: Argument) => {
|
|
109
|
+
return advancedArg.id === arg.id;
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* StringDictionary arguments render as key/value rows, and the row editor
|
|
115
|
+
* needs a real object. Every workflow written before that change stored a
|
|
116
|
+
* JSON string, so parse those on the way into the form. Anything
|
|
117
|
+
* parseStringDictionaryValue declines stays a string and keeps the JSON
|
|
118
|
+
* editor (see componentInputTypeToFormFieldType), so the two always agree.
|
|
119
|
+
*/
|
|
120
|
+
const formInitialValues: JSONObject = { ...(component.arguments || {}) };
|
|
121
|
+
|
|
122
|
+
for (const arg of component.metadata.arguments || []) {
|
|
123
|
+
if (arg.type !== ComponentInputType.StringDictionary) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const parsed: JSONObject | null = parseStringDictionaryValue(
|
|
128
|
+
formInitialValues[arg.id],
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
if (parsed !== null) {
|
|
132
|
+
formInitialValues[arg.id] = parsed;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/*
|
|
137
|
+
* Everyday settings first, collapsible ones last, each group keeping its
|
|
138
|
+
* declared order. Without this an advanced argument declared in the middle
|
|
139
|
+
* would pop into the middle of the form when the disclosure opens.
|
|
140
|
+
*/
|
|
141
|
+
const orderedArguments: Array<Argument> = [
|
|
142
|
+
...(component.metadata.arguments || []).filter((arg: Argument) => {
|
|
143
|
+
return !isCollapsibleAdvanced(arg);
|
|
144
|
+
}),
|
|
145
|
+
...collapsibleAdvancedArguments,
|
|
146
|
+
];
|
|
147
|
+
|
|
148
|
+
const firstAdvancedArgumentIndex: number =
|
|
149
|
+
orderedArguments.length - collapsibleAdvancedArguments.length;
|
|
150
|
+
|
|
56
151
|
/*
|
|
57
152
|
* Workflows in the current project, used to populate dropdowns for any
|
|
58
153
|
* argument of type WorkflowSelect (e.g. the "Workflow" field on the
|
|
@@ -163,7 +258,7 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
163
258
|
hideSubmitButton={true}
|
|
164
259
|
ref={formRef}
|
|
165
260
|
initialValues={{
|
|
166
|
-
...
|
|
261
|
+
...formInitialValues,
|
|
167
262
|
}}
|
|
168
263
|
onChange={(values: FormValues<JSONObject>) => {
|
|
169
264
|
setComponent({
|
|
@@ -175,16 +270,23 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
175
270
|
});
|
|
176
271
|
}}
|
|
177
272
|
onFormValidationErrorChanged={(hasError: boolean) => {
|
|
178
|
-
|
|
273
|
+
/*
|
|
274
|
+
* Keyed "arguments", not "id": the Identifier field in the
|
|
275
|
+
* settings modal reports into the same dictionary under "id",
|
|
276
|
+
* so both forms were overwriting each other. Typing in the
|
|
277
|
+
* Identifier box cleared an outstanding argument error and
|
|
278
|
+
* re-enabled Save on a component that was still invalid.
|
|
279
|
+
*/
|
|
280
|
+
if (hasFormValidationErrors["arguments"] !== hasError) {
|
|
179
281
|
setHasFormValidationErrors({
|
|
180
282
|
...hasFormValidationErrors,
|
|
181
|
-
|
|
283
|
+
arguments: hasError,
|
|
182
284
|
});
|
|
183
285
|
}
|
|
184
286
|
}}
|
|
185
287
|
fields={
|
|
186
288
|
component.metadata.arguments &&
|
|
187
|
-
|
|
289
|
+
orderedArguments.map((arg: Argument, argIndex: number) => {
|
|
188
290
|
const isWorkflowSelect: boolean =
|
|
189
291
|
arg.type === ComponentInputType.WorkflowSelect;
|
|
190
292
|
|
|
@@ -207,6 +309,25 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
207
309
|
const useCronPicker: boolean =
|
|
208
310
|
arg.type === ComponentInputType.CronTab;
|
|
209
311
|
|
|
312
|
+
/*
|
|
313
|
+
* Query arguments (which records does this act on) and
|
|
314
|
+
* BaseModel arguments (which values does it write) are both
|
|
315
|
+
* keyed on the model's columns, so both get the row editor
|
|
316
|
+
* backed by the model schema. Same tableName requirement as
|
|
317
|
+
* the field picker.
|
|
318
|
+
*
|
|
319
|
+
* BaseModelArray is deliberately not included: it holds a
|
|
320
|
+
* list of records, which rows cannot represent.
|
|
321
|
+
*/
|
|
322
|
+
const columnEditorMode: ModelColumnEditorMode | undefined =
|
|
323
|
+
!component.metadata.tableName
|
|
324
|
+
? undefined
|
|
325
|
+
: arg.type === ComponentInputType.Query
|
|
326
|
+
? ModelColumnEditorMode.Query
|
|
327
|
+
: arg.type === ComponentInputType.BaseModel
|
|
328
|
+
? ModelColumnEditorMode.Record
|
|
329
|
+
: undefined;
|
|
330
|
+
|
|
210
331
|
let baseField: {
|
|
211
332
|
fieldType: import("../Forms/Types/FormFieldSchemaType").default;
|
|
212
333
|
dropdownOptions?: Array<DropdownOption> | undefined;
|
|
@@ -216,7 +337,29 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
216
337
|
) => ReactElement | undefined;
|
|
217
338
|
};
|
|
218
339
|
|
|
219
|
-
if (
|
|
340
|
+
if (columnEditorMode) {
|
|
341
|
+
baseField = {
|
|
342
|
+
fieldType: FormFieldSchemaType.CustomComponent,
|
|
343
|
+
getCustomElement: (
|
|
344
|
+
_values: FormValues<JSONObject>,
|
|
345
|
+
customProps: CustomElementProps,
|
|
346
|
+
): ReactElement => {
|
|
347
|
+
return (
|
|
348
|
+
<ModelColumnEditor
|
|
349
|
+
tableName={component.metadata.tableName as string}
|
|
350
|
+
mode={columnEditorMode}
|
|
351
|
+
initialValue={customProps.initialValue}
|
|
352
|
+
onChange={(value: string) => {
|
|
353
|
+
void customProps.onChange?.(value);
|
|
354
|
+
}}
|
|
355
|
+
placeholder={customProps.placeholder}
|
|
356
|
+
error={customProps.error}
|
|
357
|
+
tabIndex={customProps.tabIndex}
|
|
358
|
+
/>
|
|
359
|
+
);
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
} else if (useFieldPicker) {
|
|
220
363
|
baseField = {
|
|
221
364
|
fieldType: FormFieldSchemaType.CustomComponent,
|
|
222
365
|
getCustomElement: (
|
|
@@ -285,10 +428,29 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
285
428
|
* and a schedule can't reference component return values).
|
|
286
429
|
*/
|
|
287
430
|
const showVariableFooter: boolean =
|
|
288
|
-
!isWorkflowSelect &&
|
|
431
|
+
!isWorkflowSelect &&
|
|
432
|
+
!useFieldPicker &&
|
|
433
|
+
!useCronPicker &&
|
|
434
|
+
!columnEditorMode;
|
|
435
|
+
|
|
436
|
+
const isAdvanced: boolean = isCollapsibleAdvanced(arg);
|
|
289
437
|
|
|
290
438
|
return {
|
|
291
439
|
title: `${arg.name}`,
|
|
440
|
+
/*
|
|
441
|
+
* The heading sits on the first advanced field, so the
|
|
442
|
+
* disclosure reads as a labelled section rather than as a
|
|
443
|
+
* run of extra inputs appearing out of nowhere.
|
|
444
|
+
*/
|
|
445
|
+
sectionTitle:
|
|
446
|
+
isAdvanced && argIndex === firstAdvancedArgumentIndex
|
|
447
|
+
? "Advanced"
|
|
448
|
+
: undefined,
|
|
449
|
+
showIf: isAdvanced
|
|
450
|
+
? (): boolean => {
|
|
451
|
+
return showAdvanced;
|
|
452
|
+
}
|
|
453
|
+
: undefined,
|
|
292
454
|
footerElement: showVariableFooter ? (
|
|
293
455
|
<div className="text-gray-500">
|
|
294
456
|
<p className="text-sm">
|
|
@@ -323,12 +485,37 @@ const ArgumentsForm: FunctionComponent<ComponentProps> = (
|
|
|
323
485
|
},
|
|
324
486
|
required: arg.required,
|
|
325
487
|
placeholder: arg.placeholder,
|
|
488
|
+
/*
|
|
489
|
+
* Some argument types are read back with JSON5 rather than
|
|
490
|
+
* JSON, so the check has to be no stricter than the parser
|
|
491
|
+
* that will actually see the value.
|
|
492
|
+
*/
|
|
493
|
+
allowJSON5: isJSON5ToleratedInputType(arg.type),
|
|
326
494
|
...baseField,
|
|
327
495
|
};
|
|
328
496
|
})
|
|
329
497
|
}
|
|
330
498
|
/>
|
|
331
499
|
)}
|
|
500
|
+
|
|
501
|
+
{collapsibleAdvancedArguments.length > 0 && (
|
|
502
|
+
<div className="mt-3">
|
|
503
|
+
<button
|
|
504
|
+
type="button"
|
|
505
|
+
aria-expanded={showAdvanced}
|
|
506
|
+
className="text-sm underline text-blue-500 hover:text-blue-600 cursor-pointer"
|
|
507
|
+
onClick={() => {
|
|
508
|
+
setShowAdvanced(!showAdvanced);
|
|
509
|
+
}}
|
|
510
|
+
>
|
|
511
|
+
{showAdvanced
|
|
512
|
+
? "Hide advanced settings"
|
|
513
|
+
: `Show ${collapsibleAdvancedArguments.length} advanced setting${
|
|
514
|
+
collapsibleAdvancedArguments.length === 1 ? "" : "s"
|
|
515
|
+
}`}
|
|
516
|
+
</button>
|
|
517
|
+
</div>
|
|
518
|
+
)}
|
|
332
519
|
</div>
|
|
333
520
|
{showVariableModal && (
|
|
334
521
|
<VariableModal
|
|
@@ -372,35 +372,37 @@ const Node: FunctionComponent<ComponentProps> = (props: ComponentProps) => {
|
|
|
372
372
|
</div>
|
|
373
373
|
)}
|
|
374
374
|
|
|
375
|
-
{/* Error indicator */}
|
|
375
|
+
{/* Error indicator — hover it to read what is actually wrong. */}
|
|
376
376
|
{!props.data.isPreview && hasError && (
|
|
377
|
-
<
|
|
378
|
-
|
|
379
|
-
position: "absolute",
|
|
380
|
-
top: "8px",
|
|
381
|
-
right: "8px",
|
|
382
|
-
zIndex: 10,
|
|
383
|
-
width: "22px",
|
|
384
|
-
height: "22px",
|
|
385
|
-
borderRadius: "50%",
|
|
386
|
-
backgroundColor:
|
|
387
|
-
"color-mix(in srgb, #ef4444 15%, var(--ou-surface-primary, #ffffff))",
|
|
388
|
-
display: "flex",
|
|
389
|
-
alignItems: "center",
|
|
390
|
-
justifyContent: "center",
|
|
391
|
-
border: "1px solid rgb(248 113 113 / 45%)",
|
|
392
|
-
}}
|
|
393
|
-
>
|
|
394
|
-
<Icon
|
|
395
|
-
icon={IconProp.Alert}
|
|
377
|
+
<Tooltip text={props.data.error}>
|
|
378
|
+
<div
|
|
396
379
|
style={{
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
380
|
+
position: "absolute",
|
|
381
|
+
top: "8px",
|
|
382
|
+
right: "8px",
|
|
383
|
+
zIndex: 10,
|
|
384
|
+
width: "22px",
|
|
385
|
+
height: "22px",
|
|
386
|
+
borderRadius: "50%",
|
|
387
|
+
backgroundColor:
|
|
388
|
+
"color-mix(in srgb, #ef4444 15%, var(--ou-surface-primary, #ffffff))",
|
|
389
|
+
display: "flex",
|
|
390
|
+
alignItems: "center",
|
|
391
|
+
justifyContent: "center",
|
|
392
|
+
border: "1px solid rgb(248 113 113 / 45%)",
|
|
400
393
|
}}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
394
|
+
>
|
|
395
|
+
<Icon
|
|
396
|
+
icon={IconProp.Alert}
|
|
397
|
+
style={{
|
|
398
|
+
color: "#ef4444",
|
|
399
|
+
width: "0.75rem",
|
|
400
|
+
height: "0.75rem",
|
|
401
|
+
}}
|
|
402
|
+
thick={ThickProp.Thick}
|
|
403
|
+
/>
|
|
404
|
+
</div>
|
|
405
|
+
</Tooltip>
|
|
404
406
|
)}
|
|
405
407
|
|
|
406
408
|
{/* Header bar with gradient */}
|
|
@@ -22,6 +22,11 @@ export interface ComponentProps {
|
|
|
22
22
|
onClose: () => void;
|
|
23
23
|
onSave: (component: NodeDataProp) => void;
|
|
24
24
|
onDelete: (component: NodeDataProp) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Run this one step now. Absent for triggers, which have nothing to run on
|
|
27
|
+
* their own.
|
|
28
|
+
*/
|
|
29
|
+
onRunStep?: ((component: NodeDataProp) => void) | undefined;
|
|
25
30
|
component: NodeDataProp;
|
|
26
31
|
graphComponents: Array<NodeDataProp>;
|
|
27
32
|
workflowId: ObjectID;
|
|
@@ -67,6 +72,8 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
67
72
|
>({});
|
|
68
73
|
const [showDeleteConfirmation, setShowDeleteConfirmation] =
|
|
69
74
|
useState<boolean>(false);
|
|
75
|
+
const [showRunStepConfirmation, setShowRunStepConfirmation] =
|
|
76
|
+
useState<boolean>(false);
|
|
70
77
|
|
|
71
78
|
const settingsSection: ReactElement = (
|
|
72
79
|
<SectionCard icon={IconProp.Settings} title="Settings">
|
|
@@ -188,17 +195,71 @@ const ComponentSettingsModal: FunctionComponent<ComponentProps> = (
|
|
|
188
195
|
modalWidth={ModalWidth.Large}
|
|
189
196
|
disableSubmitButton={hasErrors}
|
|
190
197
|
leftFooterElement={
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
/*
|
|
199
|
+
* Say why Save is off. Form errors are only rendered under a field
|
|
200
|
+
* once it has been touched, so a component opened with a setting that
|
|
201
|
+
* was already invalid — a stored JSON value that does not parse, say —
|
|
202
|
+
* otherwise presents a dead button and no explanation anywhere.
|
|
203
|
+
*/
|
|
204
|
+
hasErrors ? (
|
|
205
|
+
<div className="flex items-center gap-3">
|
|
206
|
+
<Button
|
|
207
|
+
title="Delete"
|
|
208
|
+
icon={IconProp.Trash}
|
|
209
|
+
buttonStyle={ButtonStyleType.DANGER_OUTLINE}
|
|
210
|
+
onClick={() => {
|
|
211
|
+
setShowDeleteConfirmation(true);
|
|
212
|
+
}}
|
|
213
|
+
/>
|
|
214
|
+
<span className="text-sm text-red-600">
|
|
215
|
+
Some settings need fixing before this can be saved.
|
|
216
|
+
</span>
|
|
217
|
+
</div>
|
|
218
|
+
) : (
|
|
219
|
+
<div className="flex items-center gap-3">
|
|
220
|
+
<Button
|
|
221
|
+
title="Delete"
|
|
222
|
+
icon={IconProp.Trash}
|
|
223
|
+
buttonStyle={ButtonStyleType.DANGER_OUTLINE}
|
|
224
|
+
onClick={() => {
|
|
225
|
+
setShowDeleteConfirmation(true);
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
228
|
+
{props.onRunStep && (
|
|
229
|
+
<Button
|
|
230
|
+
title="Run just this step"
|
|
231
|
+
icon={IconProp.Play}
|
|
232
|
+
buttonStyle={ButtonStyleType.OUTLINE}
|
|
233
|
+
onClick={() => {
|
|
234
|
+
setShowRunStepConfirmation(true);
|
|
235
|
+
}}
|
|
236
|
+
/>
|
|
237
|
+
)}
|
|
238
|
+
</div>
|
|
239
|
+
)
|
|
199
240
|
}
|
|
200
241
|
>
|
|
201
242
|
<>
|
|
243
|
+
{showRunStepConfirmation && (
|
|
244
|
+
<ConfirmModal
|
|
245
|
+
title={`Run this step now?`}
|
|
246
|
+
/*
|
|
247
|
+
* Worded as what it is. There is no dry run: the step executes for
|
|
248
|
+
* real, and anything it sends or changes is not undone afterwards.
|
|
249
|
+
*/
|
|
250
|
+
description={`This runs "${component.metadata.title}" for real, on its own. Anything it sends, writes or deletes actually happens. Values it reads from other steps will be empty, because nothing else runs.`}
|
|
251
|
+
onClose={() => {
|
|
252
|
+
setShowRunStepConfirmation(false);
|
|
253
|
+
}}
|
|
254
|
+
submitButtonText="Run this step"
|
|
255
|
+
onSubmit={() => {
|
|
256
|
+
setShowRunStepConfirmation(false);
|
|
257
|
+
props.onRunStep?.(component);
|
|
258
|
+
}}
|
|
259
|
+
submitButtonType={ButtonStyleType.NORMAL}
|
|
260
|
+
/>
|
|
261
|
+
)}
|
|
262
|
+
|
|
202
263
|
{showDeleteConfirmation && (
|
|
203
264
|
<ConfirmModal
|
|
204
265
|
title={`Delete ${component.metadata.componentType}`}
|