@evenicanpm/admin-integrate 1.8.1 → 2.0.1
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/documents/ConfigImport/configuration-import.ts +1 -1
- package/documents/Endpoint/list.ts +3 -3
- package/documents/Process/list.ts +3 -3
- package/documents/ProcessExecution/list.ts +2 -2
- package/documents/ProcessExport/read.ts +1 -1
- package/documents/ProcessSchedule/read.ts +1 -1
- package/documents/ProcessScheduleGroup/read.ts +3 -3
- package/documents/ProcessTask/fragments.ts +4 -0
- package/documents/ProcessTemplate/fragments.ts +30 -0
- package/documents/ProcessTemplate/list.ts +29 -0
- package/documents/ProcessTemplate/read.ts +1 -1
- package/documents/ScheduledProcess/list.ts +1 -1
- package/package.json +2 -2
- package/src/api/process-config/mutation/process-config-import.mutation.ts +1 -1
- package/src/api/templates/queries/get-field-values.query.ts +48 -0
- package/src/api/templates/queries/get-field-values.server.ts +9 -0
- package/src/api/templates/queries/index.ts +4 -0
- package/src/api/templates/queries/types.ts +2 -2
- package/src/api/templates/queries/validate-field-on-check.query.ts +22 -0
- package/src/api/templates/queries/validate-field-on-check.server.ts +30 -0
- package/src/api/templates/queries/validate-field-on-submit.server.ts +18 -0
- package/src/components/data-table/table-row.tsx +1 -1
- package/src/components/icons/up-down.tsx +1 -0
- package/src/components/integration-view/animated-svg.tsx +0 -1
- package/src/components/integration-view/elk-types.ts +1 -1
- package/src/components/integration-view/integration-view.tsx +274 -187
- package/src/components/integration-view/nodes/execution-entry-node.tsx +3 -2
- package/src/components/integration-view/nodes/task-node.tsx +1 -1
- package/src/components/integration-view/types.ts +2 -0
- package/src/components/integration-view/utils/mapping.ts +68 -48
- package/src/components/list-filter/list-filter-types.ts +6 -0
- package/src/components/list-filter/list-filter.tsx +21 -15
- package/src/components/list-filter/multi-select-filter.tsx +7 -7
- package/src/components/list-filter/select-filter.tsx +6 -6
- package/src/components/scheduler/day-selector.tsx +1 -1
- package/src/components/templatesV2/inputs/FormikPageBody.tsx +191 -0
- package/src/components/templatesV2/inputs/context/FormModeContext.tsx +31 -0
- package/src/components/templatesV2/inputs/context/TemplateContext.tsx +37 -0
- package/src/components/templatesV2/inputs/field-names.ts +8 -0
- package/src/components/templatesV2/inputs/form-type.ts +54 -0
- package/src/components/templatesV2/inputs/index.tsx +33 -0
- package/src/components/templatesV2/inputs/input-type.ts +23 -0
- package/src/components/templatesV2/inputs/primitives/CheckboxInput.tsx +45 -0
- package/src/components/templatesV2/inputs/primitives/NumberInput.tsx +58 -0
- package/src/components/templatesV2/inputs/primitives/SelectorInput.tsx +111 -0
- package/src/components/templatesV2/inputs/primitives/TextInput.tsx +55 -0
- package/src/components/templatesV2/inputs/primitives/TextWithQueryInput.tsx +292 -0
- package/src/components/templatesV2/inputs/primitives/index.ts +10 -0
- package/src/components/templatesV2/inputs/renderers/index.ts +2 -0
- package/src/components/templatesV2/inputs/renderers/renderFormControl.tsx +384 -0
- package/src/components/templatesV2/inputs/renderers/renderSearchInput.tsx +128 -0
- package/src/components/templatesV2/inputs/search/MultiTextSearchInput.tsx +87 -0
- package/src/components/templatesV2/inputs/search/SearchInputWrapper.tsx +113 -0
- package/src/components/templatesV2/inputs/search/TextSearchInput.tsx +309 -0
- package/src/components/templatesV2/inputs/search/index.ts +4 -0
- package/src/components/templatesV2/inputs/search/search-query-key.ts +23 -0
- package/src/components/templatesV2/inputs/search/useFieldValuesOptions.ts +58 -0
- package/src/components/templatesV2/inputs/search/useSearchInput.ts +79 -0
- package/src/components/templatesV2/inputs/table/InputTable.tsx +268 -0
- package/src/components/templatesV2/inputs/table/index.ts +1 -0
- package/src/components/templatesV2/inputs/utils/applyTemplateConfig.ts +28 -0
- package/src/components/templatesV2/inputs/utils/arrangeInputs.ts +52 -0
- package/src/components/templatesV2/inputs/utils/index.ts +6 -0
- package/src/components/templatesV2/inputs/utils/parseQueryName.ts +20 -0
- package/src/components/templatesV2/inputs/utils/renderReadOnlyText.tsx +26 -0
- package/src/components/templatesV2/inputs/utils/selectors.ts +69 -0
- package/src/components/templatesV2/inputs/utils/toStringArray.ts +23 -0
- package/src/components/templatesV2/pageForm.tsx +153 -0
- package/src/components/{templates → templatesV2}/templates-list/templates-list-row.tsx +2 -1
- package/src/components/{templates → templatesV2}/templates-list/templates-list-table.tsx +2 -2
- package/src/components/{templates → templatesV2}/templates-list/templates-list.tsx +19 -28
- package/src/components/{templates → templatesV2}/types.tsx +12 -12
- package/src/components/templatesV2/validation/buildZodSchema.ts +212 -0
- package/src/components/templatesV2/validation/zodFormikValidate.ts +17 -0
- package/src/components/templatesV2/wizard.tsx +746 -0
- package/src/pages/dashboard/dashboard-link-cards.tsx +0 -1
- package/src/pages/dashboard/dashboard-list-sections.tsx +1 -1
- package/src/pages/dashboard/dashboard.tsx +0 -1
- package/src/pages/executions/executions-list/executions-list-table.tsx +0 -1
- package/src/pages/executions/executions.tsx +1 -1
- package/src/pages/integration-create/integration-create-steps.ts +8 -0
- package/src/pages/integration-create/integration-create.tsx +81 -28
- package/src/pages/integration-create/pre-creation-step.tsx +9 -9
- package/src/pages/integration-create/select-step.tsx +3 -3
- package/src/pages/integration-create/template-list-step.tsx +28 -3
- package/src/pages/integration-create/template-options-step.tsx +119 -0
- package/src/pages/integration-create/wizard-step.tsx +5 -4
- package/src/pages/integration-details/import-process/copy-tasks-list.tsx +1 -3
- package/src/pages/integration-details/integration-details.tsx +1 -1
- package/src/pages/integration-details/task-drawer/add-task.tsx +4 -4
- package/src/pages/integration-details/task-drawer/edit-task.tsx +5 -5
- package/src/pages/integration-details/task-drawer/task-drawer.tsx +2 -2
- package/src/components/templates/inputs/index.tsx +0 -1392
- package/src/components/templates/wizard.tsx +0 -737
- /package/src/components/{templates → templatesV2}/index.ts +0 -0
- /package/src/components/{templates → templatesV2}/template-filter.ts +0 -0
- /package/src/components/{templates → templatesV2}/templates-list/index.ts +0 -0
|
@@ -15,6 +15,7 @@ import "@xyflow/react/dist/style.css";
|
|
|
15
15
|
import {
|
|
16
16
|
Background,
|
|
17
17
|
Controls,
|
|
18
|
+
type Edge,
|
|
18
19
|
type Node,
|
|
19
20
|
ReactFlow,
|
|
20
21
|
ReactFlowProvider,
|
|
@@ -22,8 +23,10 @@ import {
|
|
|
22
23
|
useNodesState,
|
|
23
24
|
useReactFlow,
|
|
24
25
|
} from "@xyflow/react";
|
|
26
|
+
import _ from "lodash";
|
|
25
27
|
import type {
|
|
26
28
|
ConfigExport,
|
|
29
|
+
Maybe,
|
|
27
30
|
ProcessExecutionDetails,
|
|
28
31
|
ProcessTask,
|
|
29
32
|
ProcessTaskExecution,
|
|
@@ -31,18 +34,27 @@ import type {
|
|
|
31
34
|
} from "../../../../admin-core/src/api/e4/graphqlRequestSdk";
|
|
32
35
|
import { layoutOptions as elkOptions } from "./elk-layout-options";
|
|
33
36
|
import type { ElkExtendedEdgeWithFlow, ElkNodeWithFlow } from "./elk-types";
|
|
34
|
-
|
|
35
|
-
import _ from "lodash";
|
|
36
37
|
import { edgeTypes, nodeTypes } from "./flow-types";
|
|
37
38
|
|
|
38
39
|
import {
|
|
39
|
-
|
|
40
|
+
type AddHandler,
|
|
40
41
|
mapEmptyNodesAndEdges,
|
|
41
42
|
mapProcessConfigToNodesAndEdges,
|
|
42
43
|
mapProcessTasksToNodesAndEdges,
|
|
44
|
+
mapToCamelCase,
|
|
43
45
|
} from "./utils/mapping";
|
|
44
46
|
|
|
45
47
|
const elk = new ELK();
|
|
48
|
+
type VerticalOverlapRect = { y: number; height: number };
|
|
49
|
+
type HorizontalOverlapRect = { x: number; width: number };
|
|
50
|
+
type ZoneY = { sort: number; y: number; height: number };
|
|
51
|
+
type ZoneX = { parallelProcessingGroup: number; x: number; width: number };
|
|
52
|
+
type FlowNode = Node<Record<string, unknown>>;
|
|
53
|
+
type FlowEdge = Edge<Record<string, unknown>>;
|
|
54
|
+
type FlowDirectionProps = {
|
|
55
|
+
targetPosition?: "top" | "bottom" | "left" | "right";
|
|
56
|
+
sourcePosition?: "top" | "bottom" | "left" | "right";
|
|
57
|
+
};
|
|
46
58
|
|
|
47
59
|
const calculateMaxWidth = (
|
|
48
60
|
processTasks: ProcessTask[] | ProcessTaskExecution[],
|
|
@@ -58,15 +70,19 @@ const calculateMaxWidth = (
|
|
|
58
70
|
return Math.ceil(maxCharCount * 14 + 28 + 8 + 24); // Approximate width calculation
|
|
59
71
|
};
|
|
60
72
|
|
|
61
|
-
const getLayoutedElements = (
|
|
73
|
+
const getLayoutedElements = (
|
|
74
|
+
nodes: ElkNodeWithFlow[],
|
|
75
|
+
edges: ElkExtendedEdgeWithFlow[],
|
|
76
|
+
options: Record<string, string> = {},
|
|
77
|
+
) => {
|
|
62
78
|
const graph: ElkNodeWithFlow = {
|
|
63
79
|
id: "root",
|
|
64
|
-
children: nodes.map((node:
|
|
80
|
+
children: nodes.map((node: ElkNodeWithFlow) => ({
|
|
65
81
|
...node,
|
|
66
82
|
targetPosition: "top",
|
|
67
83
|
sourcePosition: "bottom",
|
|
68
84
|
// Hardcoded until width and height calculation is implemented
|
|
69
|
-
})),
|
|
85
|
+
})) as ElkNodeWithFlow[],
|
|
70
86
|
layoutOptions: {
|
|
71
87
|
"org.eclipse.elk.algorithm": "org.eclipse.elk.layered",
|
|
72
88
|
"org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers": "120", // bigger vertical gap
|
|
@@ -76,53 +92,64 @@ const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
|
|
|
76
92
|
|
|
77
93
|
return elk
|
|
78
94
|
.layout(graph, { layoutOptions: options })
|
|
79
|
-
.then((layoutedGraph:
|
|
80
|
-
const nodeItems:
|
|
95
|
+
.then((layoutedGraph: ElkNodeWithFlow) => {
|
|
96
|
+
const nodeItems: ElkNodeWithFlow[] = [];
|
|
81
97
|
|
|
82
|
-
layoutedGraph.children
|
|
98
|
+
layoutedGraph.children?.forEach((node: ElkNodeWithFlow) => {
|
|
99
|
+
const nx = node.x ?? 0;
|
|
100
|
+
const ny = node.y ?? 0;
|
|
83
101
|
nodeItems.push({
|
|
84
102
|
...node,
|
|
85
103
|
// React Flow expects a position property on the node instead of `x`
|
|
86
104
|
// and `y` fields.
|
|
87
105
|
height:
|
|
88
|
-
node.height +
|
|
89
|
-
(node.children && node.children.length > 0 ? calcYOffset() :
|
|
106
|
+
(node.height ?? 0) +
|
|
107
|
+
(node.children && node.children.length > 0 ? calcYOffset() : 0),
|
|
90
108
|
width: node.width,
|
|
91
|
-
x:
|
|
92
|
-
y:
|
|
93
|
-
position: { x:
|
|
109
|
+
x: nx,
|
|
110
|
+
y: ny,
|
|
111
|
+
position: { x: nx, y: ny },
|
|
94
112
|
});
|
|
95
113
|
|
|
96
114
|
if (node.children) {
|
|
97
|
-
node.children.forEach((node2:
|
|
115
|
+
node.children.forEach((node2: ElkNodeWithFlow) => {
|
|
116
|
+
const n2x = node2.x ?? 0;
|
|
117
|
+
const n2y = (node2.y ?? 0) + calcYOffset();
|
|
98
118
|
nodeItems.push({
|
|
99
119
|
...node2,
|
|
100
120
|
// React Flow expects a position property on the node instead of `x`
|
|
101
121
|
// and `y` fields.
|
|
102
122
|
targetPosition: "top",
|
|
103
123
|
sourcePosition: "bottom",
|
|
104
|
-
x:
|
|
105
|
-
y:
|
|
106
|
-
position: { x:
|
|
124
|
+
x: n2x,
|
|
125
|
+
y: n2y,
|
|
126
|
+
position: { x: n2x, y: n2y },
|
|
107
127
|
parentId: node.id,
|
|
108
|
-
});
|
|
128
|
+
} as ElkNodeWithFlow & FlowDirectionProps);
|
|
109
129
|
});
|
|
110
130
|
}
|
|
111
131
|
});
|
|
112
132
|
|
|
113
|
-
layoutedGraph.edges
|
|
133
|
+
const layoutEdges = layoutedGraph.edges ?? [];
|
|
134
|
+
layoutEdges.forEach((edge: ElkExtendedEdgeWithFlow) => {
|
|
114
135
|
edge.source = edge.sources[0];
|
|
115
136
|
edge.target = edge.targets[0];
|
|
116
137
|
});
|
|
117
138
|
|
|
118
139
|
return {
|
|
119
140
|
nodes: nodeItems,
|
|
120
|
-
edges:
|
|
141
|
+
edges: layoutEdges.map((edge: ElkExtendedEdgeWithFlow) => ({
|
|
121
142
|
...edge,
|
|
122
143
|
})),
|
|
123
144
|
};
|
|
124
145
|
})
|
|
125
|
-
.catch(
|
|
146
|
+
.catch((err: unknown) => {
|
|
147
|
+
console.error(err);
|
|
148
|
+
return {
|
|
149
|
+
nodes: [] as ElkNodeWithFlow[],
|
|
150
|
+
edges: [] as ElkExtendedEdgeWithFlow[],
|
|
151
|
+
};
|
|
152
|
+
});
|
|
126
153
|
};
|
|
127
154
|
|
|
128
155
|
const calcYOffset = () => {
|
|
@@ -137,15 +164,16 @@ interface Props {
|
|
|
137
164
|
variant?: "process" | "process-execution";
|
|
138
165
|
onTaskClick?:
|
|
139
166
|
| ((id: string) => void)
|
|
167
|
+
| ((processTask: ProcessTask) => void)
|
|
140
168
|
| ((processTaskExecution: ProcessTaskExecution) => void);
|
|
141
169
|
drawerOpen?: boolean;
|
|
142
170
|
processTaskId?: string;
|
|
143
171
|
onConfigChange?: (processConfig: ConfigExport) => void;
|
|
144
|
-
onAdd?:
|
|
172
|
+
onAdd?: AddHandler;
|
|
145
173
|
canEdit?: boolean;
|
|
146
174
|
}
|
|
147
175
|
|
|
148
|
-
function getOverlapY(rect1:
|
|
176
|
+
function getOverlapY(rect1: VerticalOverlapRect, rect2: VerticalOverlapRect) {
|
|
149
177
|
// Calculate intersection coordinates
|
|
150
178
|
//const intersectX1 = Math.max(rect1.x, rect2.x);
|
|
151
179
|
const intersectY1 = Math.max(rect1.y, rect2.y);
|
|
@@ -160,7 +188,10 @@ function getOverlapY(rect1: any, rect2: any) {
|
|
|
160
188
|
}
|
|
161
189
|
}
|
|
162
190
|
|
|
163
|
-
function getOverlapX(
|
|
191
|
+
function getOverlapX(
|
|
192
|
+
rect1: HorizontalOverlapRect,
|
|
193
|
+
rect2: HorizontalOverlapRect,
|
|
194
|
+
) {
|
|
164
195
|
// Calculate intersection coordinates
|
|
165
196
|
//const intersectX1 = Math.max(rect1.x, rect2.x);
|
|
166
197
|
const intersectX1 = Math.max(rect1.x, rect2.x);
|
|
@@ -190,45 +221,60 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
190
221
|
ProcessExecutionDetails | undefined
|
|
191
222
|
>(processExecutionInput);
|
|
192
223
|
|
|
193
|
-
const [nodes, setNodes, onNodesChange] = useNodesState<
|
|
194
|
-
const [edges, setEdges, onEdgesChange] = useEdgesState<
|
|
195
|
-
const [zonesY, setZonesY] =
|
|
196
|
-
const [zonesX, setZonesX] =
|
|
224
|
+
const [nodes, setNodes, onNodesChange] = useNodesState<FlowNode>([]);
|
|
225
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState<FlowEdge>([]);
|
|
226
|
+
const [zonesY, setZonesY] = useState<ZoneY[]>([]);
|
|
227
|
+
const [zonesX, setZonesX] = useState<ZoneX[]>([]);
|
|
197
228
|
|
|
198
229
|
const { setCenter, fitView } = useReactFlow();
|
|
199
230
|
|
|
200
231
|
const onConnect = useCallback(() => {}, []);
|
|
201
232
|
const onLayout = useCallback(
|
|
202
|
-
(processInput:
|
|
203
|
-
let tasks;
|
|
204
|
-
|
|
205
|
-
if (variant
|
|
206
|
-
tasks =
|
|
207
|
-
|
|
208
|
-
)
|
|
233
|
+
(processInput: unknown) => {
|
|
234
|
+
let tasks: (ProcessTask | ProcessTaskExecution)[] | undefined;
|
|
235
|
+
|
|
236
|
+
if (variant === "process") {
|
|
237
|
+
tasks = (
|
|
238
|
+
processInput as ConfigExport | undefined
|
|
239
|
+
)?.Processes?.[0]?.ProcessTasks?.filter(
|
|
240
|
+
(t): t is ProcessTaskExport => t != null,
|
|
241
|
+
).map((processTask) => mapToCamelCase(processTask));
|
|
209
242
|
} else {
|
|
210
|
-
|
|
211
|
-
|
|
243
|
+
const executionInput =
|
|
244
|
+
(processInput as ProcessExecutionDetails | undefined) ??
|
|
245
|
+
processExecutionDetails;
|
|
246
|
+
tasks = executionInput?.processTaskExecutions?.filter(
|
|
247
|
+
(t): t is ProcessTaskExecution => t != null,
|
|
248
|
+
);
|
|
212
249
|
}
|
|
213
250
|
|
|
214
251
|
if (
|
|
215
252
|
(tasks && tasks.length > 0) ||
|
|
216
|
-
(processInput &&
|
|
253
|
+
(processInput &&
|
|
254
|
+
((processInput as { processTasks?: unknown[] })?.processTasks
|
|
255
|
+
?.length ?? 0) > 0)
|
|
217
256
|
) {
|
|
218
257
|
const width = calculateMaxWidth(
|
|
219
258
|
tasks as ProcessTask[] | ProcessTaskExecution[],
|
|
220
259
|
);
|
|
221
260
|
|
|
261
|
+
const executionDetails =
|
|
262
|
+
(processInput as ProcessExecutionDetails | undefined) ??
|
|
263
|
+
processExecutionDetails;
|
|
264
|
+
if (variant !== "process" && !executionDetails) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
222
268
|
const mapped =
|
|
223
|
-
variant
|
|
269
|
+
variant === "process"
|
|
224
270
|
? mapProcessConfigToNodesAndEdges(
|
|
225
|
-
processInput,
|
|
271
|
+
processInput as ConfigExport,
|
|
226
272
|
width,
|
|
227
273
|
variant,
|
|
228
274
|
onAdd,
|
|
229
275
|
)
|
|
230
276
|
: mapProcessTasksToNodesAndEdges(
|
|
231
|
-
|
|
277
|
+
executionDetails as ProcessExecutionDetails,
|
|
232
278
|
width,
|
|
233
279
|
variant as "process" | "process-execution",
|
|
234
280
|
);
|
|
@@ -238,28 +284,42 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
238
284
|
const es = mapped.edges;
|
|
239
285
|
|
|
240
286
|
getLayoutedElements(ns, es, opts).then(
|
|
241
|
-
({
|
|
242
|
-
|
|
243
|
-
|
|
287
|
+
({
|
|
288
|
+
nodes: layoutedNodes,
|
|
289
|
+
edges: layoutedEdges,
|
|
290
|
+
}: {
|
|
291
|
+
nodes: ElkNodeWithFlow[];
|
|
292
|
+
edges: ElkExtendedEdgeWithFlow[];
|
|
293
|
+
}) => {
|
|
294
|
+
setNodes(layoutedNodes as FlowNode[]);
|
|
295
|
+
setEdges(layoutedEdges as FlowEdge[]);
|
|
244
296
|
|
|
245
297
|
const zonesY = _.uniqBy(
|
|
246
|
-
layoutedNodes.filter(
|
|
298
|
+
layoutedNodes.filter(
|
|
299
|
+
(n: ElkNodeWithFlow) => n.type === "task-node",
|
|
300
|
+
),
|
|
247
301
|
"data.processTask.sort",
|
|
248
|
-
).map((n:
|
|
249
|
-
sort:
|
|
250
|
-
|
|
251
|
-
|
|
302
|
+
).map((n: ElkNodeWithFlow) => ({
|
|
303
|
+
sort:
|
|
304
|
+
(n?.data as { processTask?: ProcessTask })?.processTask?.sort ??
|
|
305
|
+
0,
|
|
306
|
+
y: n.position?.y ?? 0,
|
|
307
|
+
height: n.height ?? 0,
|
|
252
308
|
}));
|
|
253
309
|
|
|
254
310
|
setZonesY(zonesY);
|
|
255
311
|
|
|
256
312
|
const zonesX = _.uniqBy(
|
|
257
|
-
layoutedNodes.filter(
|
|
313
|
+
layoutedNodes.filter(
|
|
314
|
+
(n: ElkNodeWithFlow) => n.type === "group-node",
|
|
315
|
+
),
|
|
258
316
|
"data.parallelProcessingGroup",
|
|
259
|
-
).map((n:
|
|
260
|
-
parallelProcessingGroup:
|
|
261
|
-
|
|
262
|
-
|
|
317
|
+
).map((n: ElkNodeWithFlow) => ({
|
|
318
|
+
parallelProcessingGroup:
|
|
319
|
+
(n?.data as { parallelProcessingGroup?: number })
|
|
320
|
+
?.parallelProcessingGroup ?? 0,
|
|
321
|
+
x: n.position?.x ?? 0,
|
|
322
|
+
width: n.width ?? 0,
|
|
263
323
|
}));
|
|
264
324
|
|
|
265
325
|
setZonesX(zonesX);
|
|
@@ -269,18 +329,32 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
269
329
|
);
|
|
270
330
|
} else if (
|
|
271
331
|
tasks?.length === 0 ||
|
|
272
|
-
(processInput &&
|
|
332
|
+
(processInput &&
|
|
333
|
+
((processInput as { processTasks?: unknown[] })?.processTasks
|
|
334
|
+
?.length ?? 0) === 0)
|
|
273
335
|
) {
|
|
274
|
-
const
|
|
336
|
+
const emptyLayoutData =
|
|
337
|
+
(processInput as ProcessExecutionDetails | undefined) ??
|
|
338
|
+
processExecutionDetails;
|
|
339
|
+
if (!emptyLayoutData) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const mapped = mapEmptyNodesAndEdges(emptyLayoutData, 400);
|
|
275
343
|
|
|
276
344
|
const opts = { ...elkOptions };
|
|
277
345
|
const ns = mapped.nodes;
|
|
278
346
|
const es = mapped.edges;
|
|
279
347
|
|
|
280
348
|
getLayoutedElements(ns, es, opts).then(
|
|
281
|
-
({
|
|
282
|
-
|
|
283
|
-
|
|
349
|
+
({
|
|
350
|
+
nodes: layoutedNodes,
|
|
351
|
+
edges: layoutedEdges,
|
|
352
|
+
}: {
|
|
353
|
+
nodes: ElkNodeWithFlow[];
|
|
354
|
+
edges: ElkExtendedEdgeWithFlow[];
|
|
355
|
+
}) => {
|
|
356
|
+
setNodes(layoutedNodes as FlowNode[]);
|
|
357
|
+
setEdges(layoutedEdges as FlowEdge[]);
|
|
284
358
|
fitView();
|
|
285
359
|
},
|
|
286
360
|
);
|
|
@@ -289,22 +363,30 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
289
363
|
[nodes, edges],
|
|
290
364
|
);
|
|
291
365
|
|
|
292
|
-
const handleNodeClick = (
|
|
293
|
-
_event: any,
|
|
294
|
-
node: {
|
|
295
|
-
id: React.SetStateAction<string>;
|
|
296
|
-
position: { x: number; y: number };
|
|
297
|
-
width: number;
|
|
298
|
-
height: number;
|
|
299
|
-
data: any;
|
|
300
|
-
parentId?: string;
|
|
301
|
-
},
|
|
302
|
-
) => {
|
|
366
|
+
const handleNodeClick = (_event: ReactMouseEvent, node: FlowNode) => {
|
|
303
367
|
if (!drawerOpen) {
|
|
368
|
+
const nodeData = node.data as {
|
|
369
|
+
processTask?: ProcessTask;
|
|
370
|
+
processTaskExecution?: ProcessTaskExecution;
|
|
371
|
+
};
|
|
304
372
|
if (onTaskClick) {
|
|
305
|
-
if (variant === "process")
|
|
306
|
-
|
|
307
|
-
|
|
373
|
+
if (variant === "process") {
|
|
374
|
+
const processTask = nodeData.processTask;
|
|
375
|
+
if (processTask) {
|
|
376
|
+
(onTaskClick as unknown as (processTask: ProcessTask) => void)(
|
|
377
|
+
processTask,
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
} else if (variant === "process-execution") {
|
|
381
|
+
const processTaskExecution = nodeData.processTaskExecution;
|
|
382
|
+
if (processTaskExecution) {
|
|
383
|
+
(
|
|
384
|
+
onTaskClick as unknown as (
|
|
385
|
+
processTaskExecution: ProcessTaskExecution,
|
|
386
|
+
) => void
|
|
387
|
+
)(processTaskExecution);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
308
390
|
}
|
|
309
391
|
|
|
310
392
|
setTimeout(() => {
|
|
@@ -319,8 +401,8 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
319
401
|
}
|
|
320
402
|
}
|
|
321
403
|
|
|
322
|
-
const centerX = parentx + node.position.x + node.width / 2;
|
|
323
|
-
const centerY = parenty + node.position.y + node.height / 2;
|
|
404
|
+
const centerX = parentx + node.position.x + (node.width ?? 0) / 2;
|
|
405
|
+
const centerY = parenty + node.position.y + (node.height ?? 0) / 2;
|
|
324
406
|
|
|
325
407
|
setCenter(centerX, centerY, { zoom: 1.2, duration: 800 });
|
|
326
408
|
}, 300);
|
|
@@ -333,32 +415,31 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
333
415
|
}, [configInput, processExecutionInput]);
|
|
334
416
|
|
|
335
417
|
useLayoutEffect(() => {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
data = data.map((node: any) => {
|
|
339
|
-
return {
|
|
418
|
+
setNodes((prevNodes) =>
|
|
419
|
+
prevNodes.map((node) => ({
|
|
340
420
|
...node,
|
|
341
421
|
data: {
|
|
342
422
|
...node.data,
|
|
343
423
|
disabled: drawerOpen,
|
|
344
424
|
selected:
|
|
345
|
-
selectedProcessTaskId ===
|
|
346
|
-
|
|
425
|
+
selectedProcessTaskId ===
|
|
426
|
+
(node.data as { processTask?: ProcessTask })?.processTask?.id ||
|
|
427
|
+
selectedProcessTaskId ===
|
|
428
|
+
(node.data as { processTaskExecution?: ProcessTaskExecution })
|
|
429
|
+
?.processTaskExecution?.id,
|
|
347
430
|
},
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
setNodes(data);
|
|
431
|
+
})),
|
|
432
|
+
);
|
|
352
433
|
}, [drawerOpen, selectedProcessTaskId]);
|
|
353
434
|
|
|
354
|
-
const handleNodeDragStart = (_e: ReactMouseEvent, node: Node)
|
|
435
|
+
const handleNodeDragStart = (_e: ReactMouseEvent, node: Node) => {
|
|
355
436
|
let edgesFiltered = [];
|
|
356
437
|
|
|
357
|
-
const edgeList:
|
|
438
|
+
const edgeList: FlowEdge[] = [];
|
|
358
439
|
|
|
359
|
-
let nodeIds:
|
|
440
|
+
let nodeIds: string[] = [];
|
|
360
441
|
|
|
361
|
-
edges.forEach((edge
|
|
442
|
+
edges.forEach((edge) => {
|
|
362
443
|
if (edge.source === node.id) {
|
|
363
444
|
nodeIds.push(edge.target);
|
|
364
445
|
}
|
|
@@ -372,15 +453,15 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
372
453
|
|
|
373
454
|
nodeIds = _.uniq(nodeIds);
|
|
374
455
|
|
|
375
|
-
let edgeIds:
|
|
456
|
+
let edgeIds: string[] = [];
|
|
376
457
|
|
|
377
|
-
edgeList.forEach((edge
|
|
458
|
+
edgeList.forEach((edge) => {
|
|
378
459
|
edgeIds.push(edge.source, edge.target);
|
|
379
460
|
});
|
|
380
461
|
|
|
381
462
|
edgeIds = _.uniq(edgeIds);
|
|
382
463
|
|
|
383
|
-
edgesFiltered = edges.filter((edge
|
|
464
|
+
edgesFiltered = edges.filter((edge) => {
|
|
384
465
|
return (
|
|
385
466
|
edgeIds.includes(edge.source) === false &&
|
|
386
467
|
edgeIds.includes(edge.target) === false
|
|
@@ -388,58 +469,58 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
388
469
|
});
|
|
389
470
|
|
|
390
471
|
edgesFiltered = edgesFiltered.filter(
|
|
391
|
-
(edge
|
|
392
|
-
!edge.id.includes((node?.data?.processTask as ProcessTask)?.id),
|
|
472
|
+
(edge) => !edge.id.includes((node?.data?.processTask as ProcessTask)?.id),
|
|
393
473
|
);
|
|
394
474
|
|
|
395
|
-
|
|
396
|
-
(node: any) => !nodeIds.includes(node?.id),
|
|
397
|
-
);
|
|
475
|
+
const nodesFiltered = nodes.filter((node) => !nodeIds.includes(node?.id));
|
|
398
476
|
|
|
399
477
|
setEdges(edgesFiltered);
|
|
400
478
|
|
|
401
479
|
setNodes(nodesFiltered);
|
|
402
480
|
};
|
|
403
481
|
|
|
404
|
-
const handleNodeDragEnd = (_e: ReactMouseEvent, node: Node)
|
|
482
|
+
const handleNodeDragEnd = (_e: ReactMouseEvent, node: Node) => {
|
|
483
|
+
const nodeY = node?.position?.y ?? 0;
|
|
484
|
+
const nodeH = node?.height ?? 0;
|
|
485
|
+
|
|
405
486
|
let zoneY = zonesY.find(
|
|
406
|
-
(z
|
|
407
|
-
getOverlapY(
|
|
408
|
-
|
|
409
|
-
{ y: node?.position?.y, height: node.height },
|
|
410
|
-
) > 0,
|
|
487
|
+
(z) =>
|
|
488
|
+
getOverlapY({ y: z.y, height: z.height }, { y: nodeY, height: nodeH }) >
|
|
489
|
+
0,
|
|
411
490
|
);
|
|
412
491
|
|
|
413
|
-
if (!zoneY) {
|
|
492
|
+
if (!zoneY && zonesY.length > 0) {
|
|
414
493
|
const maxZone = _.maxBy(zonesY, "y");
|
|
415
494
|
const minZone = _.minBy(zonesY, "y");
|
|
416
495
|
|
|
417
|
-
if (
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
496
|
+
if (minZone && maxZone) {
|
|
497
|
+
if (nodeH && nodeY + nodeH < minZone.y) {
|
|
498
|
+
zoneY = {
|
|
499
|
+
...minZone,
|
|
500
|
+
sort: minZone.sort - 1,
|
|
501
|
+
};
|
|
502
|
+
} else if (nodeY > maxZone.y + maxZone.height) {
|
|
503
|
+
zoneY = {
|
|
504
|
+
...maxZone,
|
|
505
|
+
sort: maxZone.sort + 1,
|
|
506
|
+
};
|
|
507
|
+
} else {
|
|
508
|
+
const localZones = _.sortBy(zonesY, "y");
|
|
509
|
+
|
|
510
|
+
for (let i = 0; i < localZones.length - 1; i++) {
|
|
511
|
+
const currentZone = localZones[i];
|
|
512
|
+
const nextZone = localZones[i + 1];
|
|
513
|
+
|
|
514
|
+
if (
|
|
515
|
+
nodeY > currentZone.y + currentZone.height &&
|
|
516
|
+
nodeY < nextZone.y
|
|
517
|
+
) {
|
|
518
|
+
zoneY = {
|
|
519
|
+
...currentZone,
|
|
520
|
+
sort: currentZone.sort + 0.5,
|
|
521
|
+
};
|
|
522
|
+
break;
|
|
523
|
+
}
|
|
443
524
|
}
|
|
444
525
|
}
|
|
445
526
|
}
|
|
@@ -449,13 +530,16 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
449
530
|
? nodes.find((n) => n.id === node?.parentId)
|
|
450
531
|
: null;
|
|
451
532
|
|
|
452
|
-
let zoneX:
|
|
533
|
+
let zoneX: ZoneX | undefined;
|
|
453
534
|
let overlapX = 0;
|
|
454
535
|
|
|
455
536
|
for (const zone of zonesX) {
|
|
456
537
|
const overlap = getOverlapX(
|
|
457
538
|
{ x: zone.x, width: zone.width },
|
|
458
|
-
{
|
|
539
|
+
{
|
|
540
|
+
x: (currentGroup?.position?.x ?? 0) + node.position.x,
|
|
541
|
+
width: node.width ?? 0,
|
|
542
|
+
},
|
|
459
543
|
);
|
|
460
544
|
|
|
461
545
|
if (overlap > overlapX) {
|
|
@@ -464,47 +548,48 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
464
548
|
}
|
|
465
549
|
}
|
|
466
550
|
|
|
467
|
-
if (!zoneX) {
|
|
551
|
+
if (!zoneX && zonesX.length > 0) {
|
|
468
552
|
const maxZone = _.maxBy(zonesX, "x");
|
|
469
553
|
const minZone = _.minBy(zonesX, "x");
|
|
470
554
|
|
|
471
|
-
if (
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
555
|
+
if (minZone && maxZone) {
|
|
556
|
+
const groupX = (currentGroup?.position?.x ?? 0) + node.position.x;
|
|
557
|
+
|
|
558
|
+
if (groupX + (node.width ?? 0) < minZone.x) {
|
|
559
|
+
zoneX = {
|
|
560
|
+
...minZone,
|
|
561
|
+
parallelProcessingGroup: minZone.parallelProcessingGroup - 1,
|
|
562
|
+
};
|
|
563
|
+
} else if (groupX > maxZone.x + maxZone.width) {
|
|
564
|
+
zoneX = {
|
|
565
|
+
...maxZone,
|
|
566
|
+
parallelProcessingGroup: maxZone.parallelProcessingGroup + 1,
|
|
567
|
+
};
|
|
568
|
+
} else {
|
|
569
|
+
const localZones = _.sortBy(zonesX, "x");
|
|
570
|
+
|
|
571
|
+
for (let i = 0; i < localZones.length - 1; i++) {
|
|
572
|
+
const currentZone = localZones[i];
|
|
573
|
+
const nextZone = localZones[i + 1];
|
|
574
|
+
|
|
575
|
+
if (
|
|
576
|
+
groupX > currentZone.x &&
|
|
577
|
+
groupX < nextZone.x + nextZone.width
|
|
578
|
+
) {
|
|
579
|
+
zoneX = {
|
|
580
|
+
...currentZone,
|
|
581
|
+
parallelProcessingGroup:
|
|
582
|
+
currentZone.parallelProcessingGroup + 0.5,
|
|
583
|
+
};
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
501
586
|
}
|
|
502
587
|
}
|
|
503
588
|
}
|
|
504
589
|
}
|
|
505
590
|
|
|
506
591
|
if (!zoneY && !zoneX) {
|
|
507
|
-
onLayout(
|
|
592
|
+
onLayout(processExecutionDetails);
|
|
508
593
|
return;
|
|
509
594
|
}
|
|
510
595
|
|
|
@@ -517,13 +602,12 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
517
602
|
|
|
518
603
|
let updatedTasks = modifiedProcess.Processes?.[0]?.ProcessTasks?.map(
|
|
519
604
|
(task) => {
|
|
520
|
-
if (task) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
) {
|
|
605
|
+
if (task && zoneX) {
|
|
606
|
+
const pt = (node?.data as { processTask?: ProcessTask })?.processTask;
|
|
607
|
+
const matches = pt?.id
|
|
608
|
+
? task.ProcessTaskId === pt.id
|
|
609
|
+
: task.Name === pt?.name;
|
|
610
|
+
if (matches) {
|
|
527
611
|
return {
|
|
528
612
|
...task,
|
|
529
613
|
ParallelProcessingGroup: zoneX.parallelProcessingGroup,
|
|
@@ -535,13 +619,12 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
535
619
|
);
|
|
536
620
|
|
|
537
621
|
updatedTasks = updatedTasks?.map((task) => {
|
|
538
|
-
if (task) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
) {
|
|
622
|
+
if (task && zoneY) {
|
|
623
|
+
const pt = (node?.data as { processTask?: ProcessTask })?.processTask;
|
|
624
|
+
const matches = pt?.id
|
|
625
|
+
? task.ProcessTaskId === pt.id
|
|
626
|
+
: task.Name === pt?.name;
|
|
627
|
+
if (matches) {
|
|
545
628
|
return {
|
|
546
629
|
...task,
|
|
547
630
|
Sort: zoneY.sort,
|
|
@@ -551,7 +634,7 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
551
634
|
return task;
|
|
552
635
|
});
|
|
553
636
|
|
|
554
|
-
let prevParallelProcessingGroup:
|
|
637
|
+
let prevParallelProcessingGroup: number | null = null;
|
|
555
638
|
let index = 0;
|
|
556
639
|
|
|
557
640
|
updatedTasks = _.sortBy(updatedTasks, [
|
|
@@ -559,8 +642,9 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
559
642
|
"Sort",
|
|
560
643
|
])?.map((task) => {
|
|
561
644
|
if (task) {
|
|
562
|
-
|
|
563
|
-
|
|
645
|
+
const ppg = task.ParallelProcessingGroup ?? null;
|
|
646
|
+
if (ppg !== prevParallelProcessingGroup) {
|
|
647
|
+
prevParallelProcessingGroup = ppg;
|
|
564
648
|
index++;
|
|
565
649
|
}
|
|
566
650
|
|
|
@@ -574,17 +658,18 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
574
658
|
_.groupBy(updatedTasks, "ParallelProcessingGroup"),
|
|
575
659
|
);
|
|
576
660
|
|
|
577
|
-
let processTaskValue:
|
|
661
|
+
let processTaskValue: Maybe<ProcessTaskExport>[] = [];
|
|
578
662
|
|
|
579
663
|
partitionedTasks.forEach((partition) => {
|
|
580
664
|
index = 0;
|
|
581
|
-
let prevSort:
|
|
665
|
+
let prevSort: number | null = null;
|
|
582
666
|
|
|
583
667
|
const sortedPartition = _.sortBy(partition, ["Sort", "Name"]).map(
|
|
584
668
|
(task) => {
|
|
585
669
|
if (task) {
|
|
586
|
-
|
|
587
|
-
|
|
670
|
+
const sortVal = task.Sort ?? null;
|
|
671
|
+
if (sortVal !== prevSort) {
|
|
672
|
+
prevSort = sortVal;
|
|
588
673
|
index++;
|
|
589
674
|
}
|
|
590
675
|
|
|
@@ -595,7 +680,9 @@ const IntegrationView: React.FC<Props> = ({
|
|
|
595
680
|
},
|
|
596
681
|
);
|
|
597
682
|
|
|
598
|
-
processTaskValue = processTaskValue.concat(
|
|
683
|
+
processTaskValue = processTaskValue.concat(
|
|
684
|
+
sortedPartition as Maybe<ProcessTaskExport>[],
|
|
685
|
+
);
|
|
599
686
|
});
|
|
600
687
|
|
|
601
688
|
if (modifiedProcess?.Processes?.[0])
|