@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.
Files changed (97) hide show
  1. package/documents/ConfigImport/configuration-import.ts +1 -1
  2. package/documents/Endpoint/list.ts +3 -3
  3. package/documents/Process/list.ts +3 -3
  4. package/documents/ProcessExecution/list.ts +2 -2
  5. package/documents/ProcessExport/read.ts +1 -1
  6. package/documents/ProcessSchedule/read.ts +1 -1
  7. package/documents/ProcessScheduleGroup/read.ts +3 -3
  8. package/documents/ProcessTask/fragments.ts +4 -0
  9. package/documents/ProcessTemplate/fragments.ts +30 -0
  10. package/documents/ProcessTemplate/list.ts +29 -0
  11. package/documents/ProcessTemplate/read.ts +1 -1
  12. package/documents/ScheduledProcess/list.ts +1 -1
  13. package/package.json +2 -2
  14. package/src/api/process-config/mutation/process-config-import.mutation.ts +1 -1
  15. package/src/api/templates/queries/get-field-values.query.ts +48 -0
  16. package/src/api/templates/queries/get-field-values.server.ts +9 -0
  17. package/src/api/templates/queries/index.ts +4 -0
  18. package/src/api/templates/queries/types.ts +2 -2
  19. package/src/api/templates/queries/validate-field-on-check.query.ts +22 -0
  20. package/src/api/templates/queries/validate-field-on-check.server.ts +30 -0
  21. package/src/api/templates/queries/validate-field-on-submit.server.ts +18 -0
  22. package/src/components/data-table/table-row.tsx +1 -1
  23. package/src/components/icons/up-down.tsx +1 -0
  24. package/src/components/integration-view/animated-svg.tsx +0 -1
  25. package/src/components/integration-view/elk-types.ts +1 -1
  26. package/src/components/integration-view/integration-view.tsx +274 -187
  27. package/src/components/integration-view/nodes/execution-entry-node.tsx +3 -2
  28. package/src/components/integration-view/nodes/task-node.tsx +1 -1
  29. package/src/components/integration-view/types.ts +2 -0
  30. package/src/components/integration-view/utils/mapping.ts +68 -48
  31. package/src/components/list-filter/list-filter-types.ts +6 -0
  32. package/src/components/list-filter/list-filter.tsx +21 -15
  33. package/src/components/list-filter/multi-select-filter.tsx +7 -7
  34. package/src/components/list-filter/select-filter.tsx +6 -6
  35. package/src/components/scheduler/day-selector.tsx +1 -1
  36. package/src/components/templatesV2/inputs/FormikPageBody.tsx +191 -0
  37. package/src/components/templatesV2/inputs/context/FormModeContext.tsx +31 -0
  38. package/src/components/templatesV2/inputs/context/TemplateContext.tsx +37 -0
  39. package/src/components/templatesV2/inputs/field-names.ts +8 -0
  40. package/src/components/templatesV2/inputs/form-type.ts +54 -0
  41. package/src/components/templatesV2/inputs/index.tsx +33 -0
  42. package/src/components/templatesV2/inputs/input-type.ts +23 -0
  43. package/src/components/templatesV2/inputs/primitives/CheckboxInput.tsx +45 -0
  44. package/src/components/templatesV2/inputs/primitives/NumberInput.tsx +58 -0
  45. package/src/components/templatesV2/inputs/primitives/SelectorInput.tsx +111 -0
  46. package/src/components/templatesV2/inputs/primitives/TextInput.tsx +55 -0
  47. package/src/components/templatesV2/inputs/primitives/TextWithQueryInput.tsx +292 -0
  48. package/src/components/templatesV2/inputs/primitives/index.ts +10 -0
  49. package/src/components/templatesV2/inputs/renderers/index.ts +2 -0
  50. package/src/components/templatesV2/inputs/renderers/renderFormControl.tsx +384 -0
  51. package/src/components/templatesV2/inputs/renderers/renderSearchInput.tsx +128 -0
  52. package/src/components/templatesV2/inputs/search/MultiTextSearchInput.tsx +87 -0
  53. package/src/components/templatesV2/inputs/search/SearchInputWrapper.tsx +113 -0
  54. package/src/components/templatesV2/inputs/search/TextSearchInput.tsx +309 -0
  55. package/src/components/templatesV2/inputs/search/index.ts +4 -0
  56. package/src/components/templatesV2/inputs/search/search-query-key.ts +23 -0
  57. package/src/components/templatesV2/inputs/search/useFieldValuesOptions.ts +58 -0
  58. package/src/components/templatesV2/inputs/search/useSearchInput.ts +79 -0
  59. package/src/components/templatesV2/inputs/table/InputTable.tsx +268 -0
  60. package/src/components/templatesV2/inputs/table/index.ts +1 -0
  61. package/src/components/templatesV2/inputs/utils/applyTemplateConfig.ts +28 -0
  62. package/src/components/templatesV2/inputs/utils/arrangeInputs.ts +52 -0
  63. package/src/components/templatesV2/inputs/utils/index.ts +6 -0
  64. package/src/components/templatesV2/inputs/utils/parseQueryName.ts +20 -0
  65. package/src/components/templatesV2/inputs/utils/renderReadOnlyText.tsx +26 -0
  66. package/src/components/templatesV2/inputs/utils/selectors.ts +69 -0
  67. package/src/components/templatesV2/inputs/utils/toStringArray.ts +23 -0
  68. package/src/components/templatesV2/pageForm.tsx +153 -0
  69. package/src/components/{templates → templatesV2}/templates-list/templates-list-row.tsx +2 -1
  70. package/src/components/{templates → templatesV2}/templates-list/templates-list-table.tsx +2 -2
  71. package/src/components/{templates → templatesV2}/templates-list/templates-list.tsx +19 -28
  72. package/src/components/{templates → templatesV2}/types.tsx +12 -12
  73. package/src/components/templatesV2/validation/buildZodSchema.ts +212 -0
  74. package/src/components/templatesV2/validation/zodFormikValidate.ts +17 -0
  75. package/src/components/templatesV2/wizard.tsx +746 -0
  76. package/src/pages/dashboard/dashboard-link-cards.tsx +0 -1
  77. package/src/pages/dashboard/dashboard-list-sections.tsx +1 -1
  78. package/src/pages/dashboard/dashboard.tsx +0 -1
  79. package/src/pages/executions/executions-list/executions-list-table.tsx +0 -1
  80. package/src/pages/executions/executions.tsx +1 -1
  81. package/src/pages/integration-create/integration-create-steps.ts +8 -0
  82. package/src/pages/integration-create/integration-create.tsx +81 -28
  83. package/src/pages/integration-create/pre-creation-step.tsx +9 -9
  84. package/src/pages/integration-create/select-step.tsx +3 -3
  85. package/src/pages/integration-create/template-list-step.tsx +28 -3
  86. package/src/pages/integration-create/template-options-step.tsx +119 -0
  87. package/src/pages/integration-create/wizard-step.tsx +5 -4
  88. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +1 -3
  89. package/src/pages/integration-details/integration-details.tsx +1 -1
  90. package/src/pages/integration-details/task-drawer/add-task.tsx +4 -4
  91. package/src/pages/integration-details/task-drawer/edit-task.tsx +5 -5
  92. package/src/pages/integration-details/task-drawer/task-drawer.tsx +2 -2
  93. package/src/components/templates/inputs/index.tsx +0 -1392
  94. package/src/components/templates/wizard.tsx +0 -737
  95. /package/src/components/{templates → templatesV2}/index.ts +0 -0
  96. /package/src/components/{templates → templatesV2}/template-filter.ts +0 -0
  97. /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
- mapToCamelCase,
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 = (nodes: any, edges: any, options: any = {}) => {
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: any) => ({
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: any) => {
80
- const nodeItems: any = [];
95
+ .then((layoutedGraph: ElkNodeWithFlow) => {
96
+ const nodeItems: ElkNodeWithFlow[] = [];
81
97
 
82
- layoutedGraph.children.forEach((node: any) => {
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() : null),
106
+ (node.height ?? 0) +
107
+ (node.children && node.children.length > 0 ? calcYOffset() : 0),
90
108
  width: node.width,
91
- x: node.x,
92
- y: node.y,
93
- position: { x: node.x, y: node.y },
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: any) => {
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: node2.x,
105
- y: node2.y + calcYOffset(),
106
- position: { x: node2.x, y: node2.y + calcYOffset() },
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.forEach((edge: ElkExtendedEdgeWithFlow) => {
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: layoutedGraph.edges.map((edge: ElkExtendedEdgeWithFlow) => ({
141
+ edges: layoutEdges.map((edge: ElkExtendedEdgeWithFlow) => ({
121
142
  ...edge,
122
143
  })),
123
144
  };
124
145
  })
125
- .catch(console.error);
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?: Function;
172
+ onAdd?: AddHandler;
145
173
  canEdit?: boolean;
146
174
  }
147
175
 
148
- function getOverlapY(rect1: any, rect2: any) {
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(rect1: any, rect2: any) {
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<any>([]);
194
- const [edges, setEdges, onEdgesChange] = useEdgesState<any>([]);
195
- const [zonesY, setZonesY] = useEdgesState<any>([]);
196
- const [zonesX, setZonesX] = useEdgesState<any>([]);
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: any) => {
203
- let tasks;
204
-
205
- if (variant == "process") {
206
- tasks = processInput?.Processes[0]?.ProcessTasks?.map(
207
- (processTask: ProcessTaskExport) => mapToCamelCase(processTask),
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
- tasks = (processInput ?? processExecutionDetails)
211
- ?.processTaskExecutions;
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 && processInput?.processTasks?.length > 0)
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 == "process"
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
- processInput ?? process,
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
- ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
242
- setNodes(layoutedNodes);
243
- setEdges(layoutedEdges);
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((n: any) => n.type === "task-node"),
298
+ layoutedNodes.filter(
299
+ (n: ElkNodeWithFlow) => n.type === "task-node",
300
+ ),
247
301
  "data.processTask.sort",
248
- ).map((n: any) => ({
249
- sort: n?.data?.processTask?.sort,
250
- y: n.position.y,
251
- height: n.height,
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((n: any) => n.type === "group-node"),
313
+ layoutedNodes.filter(
314
+ (n: ElkNodeWithFlow) => n.type === "group-node",
315
+ ),
258
316
  "data.parallelProcessingGroup",
259
- ).map((n: any) => ({
260
- parallelProcessingGroup: n?.data?.parallelProcessingGroup,
261
- x: n.position.x,
262
- width: n.width,
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 && processInput?.processTasks?.length === 0)
332
+ (processInput &&
333
+ ((processInput as { processTasks?: unknown[] })?.processTasks
334
+ ?.length ?? 0) === 0)
273
335
  ) {
274
- const mapped = mapEmptyNodesAndEdges(processInput ?? process, 400);
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
- ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
282
- setNodes(layoutedNodes);
283
- setEdges(layoutedEdges);
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") onTaskClick(node.data.processTask);
306
- else if (variant === "process-execution")
307
- onTaskClick(node.data.processTaskExecution);
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
- let data = globalThis.structuredClone(nodes);
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 === node.data?.processTask?.id ||
346
- selectedProcessTaskId === node.data?.processTaskExecution?.id,
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): any => {
435
+ const handleNodeDragStart = (_e: ReactMouseEvent, node: Node) => {
355
436
  let edgesFiltered = [];
356
437
 
357
- const edgeList: any[] = [];
438
+ const edgeList: FlowEdge[] = [];
358
439
 
359
- let nodeIds: any[] = [];
440
+ let nodeIds: string[] = [];
360
441
 
361
- edges.forEach((edge: any) => {
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: any[] = [];
456
+ let edgeIds: string[] = [];
376
457
 
377
- edgeList.forEach((edge: any) => {
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: any) => {
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: any) =>
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
- let nodesFiltered = nodes.filter(
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): any => {
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: any) =>
407
- getOverlapY(
408
- { y: z.y, height: z.height },
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 (node?.height && node?.position?.y + node?.height < minZone.y) {
418
- zoneY = {
419
- ...minZone,
420
- sort: minZone.sort - 1,
421
- };
422
- } else if (node?.position?.y > maxZone.y + maxZone.height) {
423
- zoneY = {
424
- ...maxZone,
425
- sort: maxZone.sort + 1,
426
- };
427
- } else {
428
- const localZones = _.sortBy(zonesY, "y");
429
-
430
- for (let i = 0; i < localZones.length - 1; i++) {
431
- const currentZone = localZones[i];
432
- const nextZone = localZones[i + 1];
433
-
434
- if (
435
- node?.position?.y > currentZone.y + currentZone.height &&
436
- node?.position?.y < nextZone.y
437
- ) {
438
- zoneY = {
439
- ...currentZone,
440
- sort: currentZone.sort + 0.5,
441
- };
442
- break;
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: any;
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
- { x: currentGroup.x + node?.position?.x, width: node.width },
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 (currentGroup.x + node?.position?.x + node?.width < minZone.x) {
472
- zoneX = {
473
- ...minZone,
474
- parallelProcessingGroup: minZone.parallelProcessingGroup - 1,
475
- };
476
- } else if (
477
- currentGroup.x + node?.position?.x >
478
- maxZone.x + maxZone.width
479
- ) {
480
- zoneX = {
481
- ...maxZone,
482
- parallelProcessingGroup: maxZone.parallelProcessingGroup + 1,
483
- };
484
- } else {
485
- const localZones = _.sortBy(zonesY, "y");
486
-
487
- for (let i = 0; i < localZones.length - 1; i++) {
488
- const currentZone = localZones[i];
489
- const nextZone = localZones[i + 1];
490
-
491
- if (
492
- currentGroup.x + node?.position?.x > currentZone.x &&
493
- currentGroup.x + node?.position?.x < nextZone.x + nextZone.width
494
- ) {
495
- zoneX = {
496
- ...currentZone,
497
- parallelProcessingGroup:
498
- currentZone.parallelProcessingGroup + 0.5,
499
- };
500
- break;
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(process);
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
- if (
522
- zoneX && (node?.data?.processTask as ProcessTask)?.id
523
- ? task.ProcessTaskId ===
524
- (node?.data?.processTask as ProcessTask)?.id
525
- : task.Name === (node?.data?.processTask as ProcessTask)?.name
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
- if (
540
- zoneY && (node?.data?.processTask as ProcessTask)?.id
541
- ? task.ProcessTaskId ===
542
- (node?.data?.processTask as ProcessTask)?.id
543
- : task.Name === (node?.data?.processTask as ProcessTask)?.name
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: any = null;
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
- if (task.ParallelProcessingGroup !== prevParallelProcessingGroup) {
563
- prevParallelProcessingGroup = task.ParallelProcessingGroup;
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: any[] = [];
661
+ let processTaskValue: Maybe<ProcessTaskExport>[] = [];
578
662
 
579
663
  partitionedTasks.forEach((partition) => {
580
664
  index = 0;
581
- let prevSort: any = null;
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
- if (task.Sort !== prevSort) {
587
- prevSort = task.Sort;
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(sortedPartition);
683
+ processTaskValue = processTaskValue.concat(
684
+ sortedPartition as Maybe<ProcessTaskExport>[],
685
+ );
599
686
  });
600
687
 
601
688
  if (modifiedProcess?.Processes?.[0])