@evenicanpm/admin-integrate 1.2.0 → 1.3.0

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 (208) hide show
  1. package/documents/ConfigImport/configuration-import.ts +54 -0
  2. package/documents/CopyProcess/copy.ts +25 -0
  3. package/documents/Endpoint/fragments.ts +9 -0
  4. package/documents/Endpoint/list.ts +22 -0
  5. package/documents/Process/fragments.ts +35 -0
  6. package/documents/Process/get-process-details.ts +73 -0
  7. package/documents/Process/list.ts +51 -0
  8. package/documents/ProcessConfig/fragments.ts +116 -0
  9. package/documents/ProcessConfig/read.ts +35 -0
  10. package/documents/ProcessExecution/fragments.ts +12 -0
  11. package/documents/ProcessExecution/list.ts +30 -1
  12. package/documents/ProcessExecutionDetails/fragments.ts +96 -0
  13. package/documents/ProcessExecutionDetails/read.ts +12 -0
  14. package/documents/ProcessScheduleGroup/read.ts +43 -0
  15. package/documents/ProcessTask/fragments.ts +285 -0
  16. package/documents/ProcessTask/read.ts +12 -0
  17. package/documents/ProcessTemplate/fragments.ts +69 -0
  18. package/documents/ProcessTemplate/list.ts +67 -0
  19. package/documents/ProcessTemplate/read.ts +12 -0
  20. package/documents/RunProcess/run.ts +11 -0
  21. package/package.json +4 -3
  22. package/src/api/Integrations/queries/get-process.query.ts +48 -0
  23. package/src/api/Integrations/queries/get-process.server.ts +14 -0
  24. package/src/api/Integrations/queries/index.ts +1 -0
  25. package/src/api/dashboard/queries/get-process-executions.query.ts +6 -3
  26. package/src/api/dashboard/queries/get-process-executions.server.ts +1 -1
  27. package/src/api/execution-details/queries/get-process-execution-details.query.ts +46 -0
  28. package/src/api/execution-details/queries/get-process-execution-details.server.ts +11 -0
  29. package/src/api/execution-details/queries/get-process-executions-by-process.query.ts +48 -0
  30. package/src/api/execution-details/queries/get-process-executions-by-process.server.ts +11 -0
  31. package/src/api/execution-details/queries/index.ts +2 -0
  32. package/src/api/process/mutations/copy-process.mutation.ts +48 -0
  33. package/src/api/process/mutations/copy-process.server.ts +14 -0
  34. package/src/api/process/mutations/index.ts +2 -0
  35. package/src/api/process/mutations/run-process.mutation.ts +41 -0
  36. package/src/api/process/mutations/run-process.server.ts +14 -0
  37. package/src/api/process/queries/get-process-by-id.query.ts +85 -0
  38. package/src/api/process/queries/get-process-by-id.server.ts +20 -0
  39. package/src/api/process/queries/index.ts +4 -0
  40. package/src/api/process-config/mutation/index.ts +2 -0
  41. package/src/api/process-config/mutation/process-config-import.mutation.ts +33 -0
  42. package/src/api/process-config/mutation/process-config-import.server.ts +14 -0
  43. package/src/api/process-config/mutation/process-config-merge.mutation.ts +33 -0
  44. package/src/api/process-config/mutation/process-config-merge.server.ts +14 -0
  45. package/src/api/process-task/queries/get-process-task-by-id.query.ts +45 -0
  46. package/src/api/process-task/queries/get-process-task-by-id.server.ts +9 -0
  47. package/src/api/process-task/queries/index.ts +1 -0
  48. package/src/api/scheduler/mutation/create-process-schedule-group-details.mutation.ts +47 -0
  49. package/src/api/scheduler/mutation/create-process-schedule-group-details.server.ts +14 -0
  50. package/src/api/scheduler/mutation/index.ts +2 -0
  51. package/src/api/scheduler/mutation/update-process-schedule-group-details.mutation.ts +47 -0
  52. package/src/api/scheduler/mutation/update-process-schedule-group-details.server.ts +14 -0
  53. package/src/api/scheduler/queries/get-non-scheduled-processes.query.ts +48 -0
  54. package/src/api/scheduler/queries/get-non-scheduled-processes.server.ts +11 -0
  55. package/src/api/scheduler/queries/get-process-schedule-group-details.query.ts +6 -3
  56. package/src/api/scheduler/queries/get-process-schedule-group-details.server.ts +3 -3
  57. package/src/api/scheduler/queries/get-process-schedule.query.ts +6 -3
  58. package/src/api/scheduler/queries/get-process-schedule.server.ts +3 -3
  59. package/src/api/scheduler/queries/get-scheduled-processes.query.ts +6 -3
  60. package/src/api/scheduler/queries/get-scheduled-processes.server.ts +1 -1
  61. package/src/api/scheduler/queries/index.ts +3 -2
  62. package/src/api/templates/queries/get-process-template-groups.query.ts +48 -0
  63. package/src/api/templates/queries/get-process-template-groups.server.ts +11 -0
  64. package/src/api/templates/queries/get-process-template-records.query.ts +48 -0
  65. package/src/api/templates/queries/get-process-template-records.server.ts +11 -0
  66. package/src/api/templates/queries/get-process-template.query.ts +48 -0
  67. package/src/api/templates/queries/get-process-template.server.ts +9 -0
  68. package/src/api/templates/queries/get-process-templates.query.ts +45 -0
  69. package/src/api/templates/queries/get-process-templates.server.ts +9 -0
  70. package/src/api/templates/queries/index.ts +5 -0
  71. package/src/api/templates/queries/template-input-search.query.ts +34 -0
  72. package/src/api/templates/queries/template-input-search.server.ts +35 -0
  73. package/src/api/templates/queries/types.ts +28 -0
  74. package/src/components/breadcrumbs/breadcrumbs.tsx +32 -5
  75. package/src/components/button/outlined-icon-button.tsx +2 -2
  76. package/src/components/core/date-time-popover.tsx +11 -4
  77. package/src/components/core/drawer-buttons.tsx +52 -0
  78. package/src/components/core/edited-typography.tsx +1 -1
  79. package/src/components/core/index.ts +4 -2
  80. package/src/components/core/loading.tsx +1 -1
  81. package/src/components/core/status-tag.tsx +97 -0
  82. package/src/components/core/title-edit.tsx +18 -11
  83. package/src/components/dashboard-list/dashboard-list-row.tsx +22 -29
  84. package/src/components/dashboard-list/dashboard-list.tsx +19 -15
  85. package/src/components/data-table/table-header.tsx +5 -7
  86. package/src/components/data-table/table-pagination.tsx +1 -1
  87. package/src/components/data-table/table-row.tsx +1 -1
  88. package/src/components/data-table/table-skeleton.tsx +9 -4
  89. package/src/components/execution/execution-filter.ts +1 -1
  90. package/src/components/execution/execution-status-icon.tsx +7 -7
  91. package/src/components/execution/execution-tag.tsx +12 -77
  92. package/src/components/execution/index.ts +1 -1
  93. package/src/components/execution-history-drawer/execution-history-drawer.tsx +203 -0
  94. package/src/components/execution-history-drawer/executions-card.tsx +85 -0
  95. package/src/components/execution-history-drawer/index.ts +1 -0
  96. package/src/components/footer/footer.tsx +10 -6
  97. package/src/components/header/dashboard-list-header.tsx +12 -7
  98. package/src/components/header/execution-details-header.tsx +35 -26
  99. package/src/components/header/header.tsx +10 -3
  100. package/src/components/header/index.ts +1 -1
  101. package/src/components/header/integration-details-header.tsx +104 -45
  102. package/src/components/integration-list/index.ts +3 -0
  103. package/src/components/integration-list/integration-filter.ts +21 -0
  104. package/src/components/integration-list/integration-status-icon.tsx +32 -0
  105. package/src/components/integration-list/integration-tag.tsx +33 -0
  106. package/src/components/integration-list/list/index.ts +1 -0
  107. package/src/components/integration-list/list/integration-list-row.tsx +161 -0
  108. package/src/components/integration-list/list/integration-list-table.tsx +62 -0
  109. package/src/components/integration-list/list/integration-list.tsx +258 -0
  110. package/src/components/integration-view/animated-svg.tsx +31 -0
  111. package/src/components/integration-view/edges/default-edge.tsx +1 -1
  112. package/src/components/integration-view/elk-layout-options.ts +2 -2
  113. package/src/components/integration-view/elk-types.ts +35 -6
  114. package/src/components/integration-view/flow-types.tsx +10 -0
  115. package/src/components/integration-view/integration-view.tsx +990 -55
  116. package/src/components/integration-view/nodes/empty-node.tsx +65 -0
  117. package/src/components/integration-view/nodes/entry-node.tsx +98 -4
  118. package/src/components/integration-view/nodes/execution-entry-node.tsx +107 -0
  119. package/src/components/integration-view/nodes/execution-task-node.tsx +88 -0
  120. package/src/components/integration-view/nodes/group-node.tsx +19 -13
  121. package/src/components/integration-view/nodes/row-node.tsx +19 -0
  122. package/src/components/integration-view/nodes/task-node.tsx +14 -8
  123. package/src/components/integration-view/task-icon.tsx +193 -0
  124. package/src/components/integration-view/temp-data/initialElements.tsx +36 -32
  125. package/src/components/integration-view/types.ts +2 -2
  126. package/src/components/layouts/main-layout.tsx +2 -3
  127. package/src/components/layouts/root-container.tsx +3 -6
  128. package/src/components/link-cards/link-card.tsx +15 -4
  129. package/src/components/link-cards/styles.ts +1 -1
  130. package/src/components/list-filter/date-filter.tsx +4 -3
  131. package/src/components/list-filter/date-range-filter.tsx +11 -5
  132. package/src/components/list-filter/index.ts +1 -1
  133. package/src/components/list-filter/list-filter.tsx +31 -26
  134. package/src/components/list-filter/multi-select-filter.tsx +11 -10
  135. package/src/components/list-filter/select-filter.tsx +13 -8
  136. package/src/components/scheduler/day-selector.tsx +29 -15
  137. package/src/components/scheduler/day-tag.tsx +14 -51
  138. package/src/components/scheduler/index.ts +2 -1
  139. package/src/components/scheduler/schedule-drawer/details-reducer.ts +217 -0
  140. package/src/components/scheduler/schedule-drawer/schedule-details-integrations.tsx +503 -0
  141. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details-main.tsx +136 -99
  142. package/src/components/scheduler/schedule-drawer/schedule-details-name.tsx +94 -0
  143. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details-skeleton.tsx +1 -2
  144. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details.tsx +9 -13
  145. package/src/components/scheduler/schedule-drawer/schedule-drawer-group.tsx +218 -0
  146. package/src/{pages → components}/scheduler/schedule-drawer/schedule-drawer-legacy.tsx +6 -25
  147. package/src/components/scheduler/schedule-drawer/schedule-drawer.tsx +116 -0
  148. package/src/components/scheduler/schedule-drawer/sortable-integration-row.tsx +130 -0
  149. package/src/components/scheduler/schedule-filter.ts +1 -1
  150. package/src/components/scheduler/schedule-icon.tsx +5 -6
  151. package/src/components/scheduler/schedule-integration-icon.tsx +31 -0
  152. package/src/components/templates/index.ts +1 -0
  153. package/src/components/templates/inputs/index.tsx +1351 -0
  154. package/src/components/templates/template-filter.ts +5 -0
  155. package/src/components/templates/templates-list/index.ts +1 -0
  156. package/src/components/templates/templates-list/templates-list-row.tsx +55 -0
  157. package/src/components/templates/templates-list/templates-list-table.tsx +58 -0
  158. package/src/components/templates/templates-list/templates-list.tsx +253 -0
  159. package/src/components/templates/types.tsx +75 -0
  160. package/src/components/templates/wizard.tsx +689 -0
  161. package/src/hooks/use-breadcrumbs.ts +1 -1
  162. package/src/hooks/use-recurrence.tsx +1 -2
  163. package/src/pages/dashboard/dashboard-link-cards.tsx +8 -11
  164. package/src/pages/dashboard/dashboard-list-sections.tsx +7 -9
  165. package/src/pages/dashboard/dashboard.tsx +1 -2
  166. package/src/pages/execution-details/execution-details.tsx +211 -14
  167. package/src/pages/execution-details/task-execution-details.tsx +160 -0
  168. package/src/pages/execution-details/task-execution-drawer.tsx +54 -0
  169. package/src/pages/executions/executions-list/executions-list-row.tsx +21 -27
  170. package/src/pages/executions/executions-list/executions-list-table.tsx +28 -35
  171. package/src/pages/executions/executions-list/executions-list.tsx +24 -18
  172. package/src/pages/executions/executions.tsx +11 -15
  173. package/src/pages/integration-create/index.ts +1 -0
  174. package/src/pages/integration-create/integration-create.tsx +174 -0
  175. package/src/pages/integration-create/pre-creation-step.tsx +12 -0
  176. package/src/pages/integration-create/select-step.tsx +105 -0
  177. package/src/pages/integration-create/template-list-step.tsx +77 -0
  178. package/src/pages/integration-create/wizard-step.tsx +50 -0
  179. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +265 -0
  180. package/src/pages/integration-details/import-process/copy-tasks-row.tsx +77 -0
  181. package/src/pages/integration-details/import-process/import-confirm.tsx +61 -0
  182. package/src/pages/integration-details/import-process/import-drawer.tsx +48 -0
  183. package/src/pages/integration-details/import-process/import-process-reducer.ts +90 -0
  184. package/src/pages/integration-details/import-process/import-process.tsx +149 -0
  185. package/src/pages/integration-details/index.ts +1 -0
  186. package/src/pages/integration-details/integration-details.tsx +221 -0
  187. package/src/pages/integration-details/task-drawer/add-task.tsx +120 -0
  188. package/src/pages/integration-details/task-drawer/edit-task.tsx +175 -0
  189. package/src/pages/integration-details/task-drawer/task-drawer.tsx +139 -0
  190. package/src/pages/integration-details/task-drawer/task-reducer.ts +73 -0
  191. package/src/pages/integrations/integrations.tsx +68 -8
  192. package/src/pages/scheduler/scheduler.tsx +12 -24
  193. package/src/pages/scheduler/schedules-list/schedules-list-row.tsx +27 -37
  194. package/src/pages/scheduler/schedules-list/schedules-list-table.tsx +27 -42
  195. package/src/pages/scheduler/schedules-list/schedules-list.tsx +48 -21
  196. package/src/utils/date-functions.ts +69 -0
  197. package/src/utils/slugify.ts +3 -0
  198. package/tsconfig.json +12 -4
  199. package/src/hooks/use-timestamp.tsx +0 -25
  200. package/src/pages/scheduler/schedule-drawer/schedule-details-integrations.tsx +0 -227
  201. package/src/pages/scheduler/schedule-drawer/schedule-details-name.tsx +0 -77
  202. package/src/pages/scheduler/schedule-drawer/schedule-drawer-buttons.tsx +0 -72
  203. package/src/pages/scheduler/schedule-drawer/schedule-drawer-group.tsx +0 -103
  204. package/src/pages/scheduler/schedule-drawer/schedule-drawer.tsx +0 -101
  205. package/src/pages/scheduler/schedule-drawer/sortable-integration-row.tsx +0 -93
  206. /package/src/{pages → components}/scheduler/schedule-drawer/edited/edited-types.ts +0 -0
  207. /package/src/{pages → components}/scheduler/schedule-drawer/edited/index.ts +0 -0
  208. /package/src/{pages → components}/scheduler/schedule-drawer/index.ts +0 -0
@@ -1,31 +1,79 @@
1
1
  "use client";
2
2
 
3
- import React, { useCallback, useLayoutEffect } from "react";
4
3
  import { Box } from "@mui/material";
5
-
6
4
  import ELK from "elkjs/lib/elk.bundled.js";
5
+ import type React from "react";
6
+ import {
7
+ type MouseEvent as ReactMouseEvent,
8
+ useCallback,
9
+ useLayoutEffect,
10
+ useState,
11
+ } from "react";
7
12
 
8
13
  import "@xyflow/react/dist/style.css";
9
14
 
10
15
  import {
11
16
  Background,
12
17
  Controls,
18
+ type InternalNode,
19
+ type Node,
13
20
  ReactFlow,
14
21
  ReactFlowProvider,
15
22
  useEdgesState,
16
23
  useNodesState,
17
24
  useReactFlow,
25
+ useStoreApi,
18
26
  } from "@xyflow/react";
19
-
20
- import { nodeTypes, edgeTypes } from "./flow-types";
21
-
27
+ import type {
28
+ Process,
29
+ ProcessExecutionDetails,
30
+ ProcessTask,
31
+ ProcessTaskExecution,
32
+ } from "../../../../admin-core/src/api/e4/graphqlRequestSdk";
22
33
  import { layoutOptions as elkOptions } from "./elk-layout-options";
34
+ import type {
35
+ ElkExtendedEdgeWithFlow,
36
+ ElkNodeWithFlow,
37
+ GroupNode,
38
+ ProcessTaskExecutionNode,
39
+ ProcessTaskNode,
40
+ } from "./elk-types";
23
41
 
24
- import { initialNodes, initialEdges } from "./temp-data/initialElements";
25
- import { ElkExtendedEdgeWithFlow, ElkNodeWithFlow } from "./elk-types";
42
+ // import {
43
+ // exportIcon,
44
+ // inputIcon,
45
+ // markerEnd,
46
+ // pullIcon,
47
+ // pushIcon,
48
+ // storageIcon,
49
+ // } from "./icons";
50
+
51
+ import { MarkerType } from "@xyflow/react";
52
+ import _ from "lodash";
53
+ import { edgeTypes, nodeTypes } from "./flow-types";
26
54
 
27
55
  const elk = new ELK();
28
56
 
57
+ const markerEnd = {
58
+ type: MarkerType.ArrowClosed,
59
+ width: 20,
60
+ height: 20,
61
+ };
62
+
63
+ const calculateMaxWidth = (
64
+ processTasks: ProcessTask[] | ProcessTaskExecution[],
65
+ ) => {
66
+ let maxCharCount = 0;
67
+
68
+ processTasks.forEach((task) => {
69
+ if (task.name && task.name.length > maxCharCount) {
70
+ maxCharCount = task.name.length;
71
+ }
72
+ });
73
+
74
+ return Math.ceil(maxCharCount * 14 + 28 + 8 + 24); // Approximate width calculation
75
+ };
76
+
29
77
  const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
30
78
  const graph: ElkNodeWithFlow = {
31
79
  id: "root",
@@ -35,22 +83,30 @@ const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
35
83
  sourcePosition: "bottom",
36
84
  // Hardcoded until width and height calculation is implemented
37
85
  })),
86
+ layoutOptions: {
87
+ "org.eclipse.elk.algorithm": "org.eclipse.elk.layered",
88
+ "org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers": "120", // bigger vertical gap
89
+ },
38
90
  edges: edges,
39
91
  };
40
92
 
41
93
  return elk
42
94
  .layout(graph, { layoutOptions: options })
43
95
  .then((layoutedGraph: any) => {
44
- let nodeItems: any = [];
96
+ const nodeItems: any = [];
45
97
 
46
98
  layoutedGraph.children.forEach((node: any) => {
47
99
  nodeItems.push({
48
100
  ...node,
49
101
  // React Flow expects a position property on the node instead of `x`
50
102
  // and `y` fields.
51
- height: node.height,
103
+ height:
104
+ node.height +
105
+ (node.children && node.children.length > 0 ? calcYOffset() : null),
52
106
  width: node.width,
53
- position: { x: node.x, y: node.y + calcYOffset() },
107
+ x: node.x,
108
+ y: node.y,
109
+ position: { x: node.x, y: node.y },
54
110
  });
55
111
 
56
112
  if (node.children) {
@@ -61,6 +117,8 @@ const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
61
117
  // and `y` fields.
62
118
  targetPosition: "top",
63
119
  sourcePosition: "bottom",
120
+ x: node2.x,
121
+ y: node2.y + calcYOffset(),
64
122
  position: { x: node2.x, y: node2.y + calcYOffset() },
65
123
  parentId: node.id,
66
124
  });
@@ -90,72 +148,949 @@ const calcYOffset = () => {
90
148
  interface Props {
91
149
  title?: string; // e.g. Executions
92
150
  section?: string; // e.g. e4Integrate
151
+ data?: Process | ProcessExecutionDetails;
152
+ variant?: "process" | "process-execution";
153
+ onTaskClick?:
154
+ | ((id: string) => void)
155
+ | ((processTaskExecution: ProcessTaskExecution) => void);
156
+ drawerOpen?: boolean;
157
+ processTaskId?: string;
158
+ }
159
+
160
+ const mapEmptyNodesAndEdges = (
161
+ data: Process | ProcessExecutionDetails,
162
+ nodeWidth: number,
163
+ ) => {
164
+ const nodes: ElkNodeWithFlow[] = [];
165
+ const edges: ElkExtendedEdgeWithFlow[] = [];
166
+
167
+ const entryPoint: ElkNodeWithFlow = {
168
+ id: "entry-point",
169
+ type: "entry-node",
170
+ data: {
171
+ isScheduled: false,
172
+ isTriggered: false,
173
+ },
174
+ width: nodeWidth,
175
+ height:
176
+ (data as Process)?.isScheduled && (data as Process)?.isTriggered
177
+ ? 104
178
+ : 70,
179
+ position: { x: 0, y: 0 },
180
+ layoutOptions: {
181
+ "org.eclipse.elk.priority": "1",
182
+ },
183
+ };
184
+
185
+ nodes.push(entryPoint);
186
+
187
+ const entryPointConnector: ElkNodeWithFlow = {
188
+ id: "entry-point-connector",
189
+ position: { x: 0, y: 0 },
190
+ type: "connection-node",
191
+ width: 1,
192
+ height: 1,
193
+ //extent: "parent",
194
+ };
195
+
196
+ nodes.push(entryPointConnector);
197
+
198
+ const groupId = `group-1`;
199
+
200
+ const emptyNode = {
201
+ id: groupId,
202
+ data: {
203
+ label: `Group 1`,
204
+ },
205
+ position: { x: 0, y: 0 },
206
+ type: "empty-node",
207
+ children: [],
208
+ layoutOptions: {
209
+ "org.eclipse.elk.priority": groupId,
210
+ },
211
+ draggable: false,
212
+ width: nodeWidth,
213
+ height: 100,
214
+ };
215
+
216
+ nodes.push(emptyNode);
217
+
218
+ edges.push({
219
+ id: `entry-point-entry-point-connector`,
220
+ sources: ["entry-point"],
221
+ targets: ["entry-point-connector"],
222
+ type: "default-edge",
223
+ });
224
+
225
+ edges.push({
226
+ id: `entry-point-connector-${groupId}`,
227
+ sources: ["entry-point-connector"],
228
+ targets: [groupId],
229
+ type: "default-edge",
230
+ markerEnd: markerEnd,
231
+ });
232
+
233
+ return {
234
+ nodes,
235
+ edges,
236
+ };
237
+ };
238
+
239
+ const mapProcessTasksToNodesAndEdges = (
240
+ data: Process | ProcessExecutionDetails,
241
+ nodeWidth: number,
242
+ variant: "process" | "process-execution",
243
+ ) => {
244
+ const entryPoint: ElkNodeWithFlow = {
245
+ id: "entry-point",
246
+ type: "entry-node",
247
+ data: {
248
+ isScheduled:
249
+ variant === "process" ? !!(data as Process)?.isScheduled : false,
250
+ isTriggered:
251
+ variant === "process" ? !!(data as Process)?.isTriggered : false,
252
+ },
253
+ width: nodeWidth,
254
+ height:
255
+ (data as Process)?.isScheduled && (data as Process)?.isTriggered
256
+ ? 104
257
+ : 70,
258
+ position: { x: 0, y: 0 },
259
+ layoutOptions: {
260
+ "org.eclipse.elk.priority": "1",
261
+ },
262
+ };
263
+
264
+ const entryPointConnector: ElkNodeWithFlow = {
265
+ id: "entry-point-connector",
266
+ position: { x: 0, y: 0 },
267
+ type: "connection-node",
268
+ width: 1,
269
+ height: 1,
270
+ //extent: "parent",
271
+ };
272
+
273
+ let groupLabels: number[];
274
+
275
+ if (variant === "process") {
276
+ groupLabels = _.uniq(
277
+ _.map((data as Process)?.processTasks, "parallelProcessingGroup"),
278
+ );
279
+ } else {
280
+ groupLabels = _.uniq(
281
+ _.map(
282
+ (data as ProcessExecutionDetails)?.processTaskExecutions,
283
+ "parallelProcessingGroup",
284
+ ),
285
+ );
286
+ }
287
+
288
+ groupLabels = _.sortBy(groupLabels);
289
+
290
+ const groups: GroupNode[] = groupLabels.map((groupLabel) => ({
291
+ id: `group-${groupLabel}`,
292
+ data: {
293
+ label: `Group ${groupLabel}`,
294
+ variant: variant,
295
+ parallelProcessingGroup: groupLabel,
296
+ },
297
+ position: { x: 0, y: 0 },
298
+ type: "group-node",
299
+ children: [],
300
+ layoutOptions: {
301
+ "org.eclipse.elk.priority": `${groupLabel}`,
302
+ },
303
+ draggable: false,
304
+ }));
305
+
306
+ const edges = [];
307
+
308
+ edges.push({
309
+ id: `entry-point-entry-point-connector`,
310
+ sources: ["entry-point"],
311
+ targets: ["entry-point-connector"],
312
+ type: "default-edge",
313
+ });
314
+
315
+ groups.forEach((group) => {
316
+ edges.push({
317
+ id: `entry-point-connector-${group.id}`,
318
+ sources: ["entry-point-connector"],
319
+ targets: [group.id],
320
+ type: "default-edge",
321
+ markerEnd: markerEnd,
322
+ });
323
+
324
+ const groupTasks = _.sortBy(
325
+ (variant === "process"
326
+ ? (data as Process)?.processTasks
327
+ : (data as ProcessExecutionDetails)?.processTaskExecutions
328
+ )?.filter(
329
+ (task) =>
330
+ task?.parallelProcessingGroup?.toString() === group.id.split("-")[1],
331
+ ),
332
+ ["sort", "name"],
333
+ );
334
+
335
+ var tasksPartitioned = _.values(_.groupBy(groupTasks, "sort"));
336
+
337
+ const groupNodes: (
338
+ | ProcessTaskNode
339
+ | ProcessTaskExecutionNode
340
+ | ElkNodeWithFlow
341
+ )[] = [];
342
+
343
+ tasksPartitioned.forEach((partition) => {
344
+ partition.forEach((task, index) => {
345
+ groupNodes.push({
346
+ id: `task-${task?.id}`,
347
+ data: {
348
+ processTask:
349
+ variant === "process" ? (task as ProcessTask) : undefined,
350
+ processTaskExecution:
351
+ variant === "process-execution"
352
+ ? (task as ProcessTaskExecution)
353
+ : undefined,
354
+ //label: task?.name as string,
355
+ /*icon: mapIntegrationIconByCode(
356
+ task?.orchestrationType?.code as string,
357
+ ),*/
358
+ isLast: index === partition.length - 1,
359
+ //executionStatus: variant === 'process' ? undefined : (task as ProcessTaskExecution)?.executionStatus.id,
360
+ },
361
+ position: { x: 0, y: 0 },
362
+ type: variant === "process" ? "task-node" : "execution-task-node",
363
+ width: nodeWidth + (index === partition.length - 1 ? 32 : 0), //hard coded for now
364
+ height: 70, // hard coded for now
365
+ //extent: "parent",
366
+ parentId: group.id,
367
+ //sort: task?.sort as number | undefined,
368
+ });
369
+ });
370
+ });
371
+
372
+ let prevConnectorId: string | null = null;
373
+
374
+ tasksPartitioned.forEach((partition, tpIndex) => {
375
+ _.sortBy(partition, [(task) => task?.name]);
376
+
377
+ if (prevConnectorId) {
378
+ partition.forEach((task) => {
379
+ edges.push({
380
+ id: `${prevConnectorId}-${task?.id}`,
381
+ sources: [prevConnectorId],
382
+ targets: [`task-${task?.id}`],
383
+ type: "default-edge",
384
+ markerEnd: markerEnd,
385
+ });
386
+ });
387
+ }
388
+
389
+ const connectorId = `group-${group.id}-connect-${tpIndex}`;
390
+
391
+ prevConnectorId = connectorId;
392
+
393
+ if (tpIndex !== tasksPartitioned.length - 1) {
394
+ partition.forEach((task) => {
395
+ edges.push({
396
+ id: `task-${task?.id}-${connectorId}`,
397
+ sources: [`task-${task?.id}`],
398
+ targets: [connectorId],
399
+ type: "default-edge",
400
+ });
401
+ });
402
+ }
403
+ if (prevConnectorId && tpIndex !== tasksPartitioned.length - 1) {
404
+ groupNodes.push({
405
+ id: prevConnectorId,
406
+ position: { x: 0, y: 0 },
407
+ type: "connection-node",
408
+ width: 1,
409
+ height: 1,
410
+ extent: "parent",
411
+ parentId: group.id,
412
+ });
413
+ }
414
+ });
415
+
416
+ // groupTasks.map((task) => ({
417
+ // id: `task-${task.id}`,
418
+ // data: {
419
+ // label: task.name,
420
+ // //icon: pullIcon(),
421
+ // isLast: true,
422
+ // },
423
+ // position: { x: 0, y: 0 },
424
+ // type: "task-node",
425
+ // width: 450, //hard coded for now
426
+ // height: 70, //hard coded for now
427
+ // extent: "parent",
428
+ // parentId: group.id,
429
+ // sort: task.sort,
430
+ // }));
431
+
432
+ group.children = groupNodes;
433
+ });
434
+
435
+ return { nodes: [entryPoint, entryPointConnector, ...groups], edges };
436
+ };
437
+
438
+ function getOverlapY(rect1: any, rect2: any) {
439
+ // Calculate intersection coordinates
440
+ //const intersectX1 = Math.max(rect1.x, rect2.x);
441
+ const intersectY1 = Math.max(rect1.y, rect2.y);
442
+ //const intersectX2 = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
443
+ const intersectY2 = Math.min(rect1.y + rect1.height, rect2.y + rect2.height);
444
+
445
+ // Check for overlap and calculate area
446
+ if (/*intersectX1 >= intersectX2 ||*/ intersectY1 >= intersectY2) {
447
+ return 0; // No overlap
448
+ } else {
449
+ //const overlapWidth = intersectX2 - intersectX1;
450
+ const overlapHeight = intersectY2 - intersectY1;
451
+ return /*overlapWidth **/ overlapHeight;
452
+ }
453
+ }
454
+
455
+ function getOverlapX(rect1: any, rect2: any) {
456
+ // Calculate intersection coordinates
457
+ //const intersectX1 = Math.max(rect1.x, rect2.x);
458
+ const intersectX1 = Math.max(rect1.x, rect2.x);
459
+ //const intersectX2 = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
460
+ const intersectX2 = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
461
+
462
+ // Check for overlap and calculate area
463
+ if (intersectX1 >= intersectX2) {
464
+ return 0; // No overlap
465
+ } else {
466
+ //const overlapWidth = intersectX2 - intersectX1;
467
+ const overlapHeight = intersectX2 - intersectX1;
468
+ return /*overlapWidth **/ overlapHeight;
469
+ }
93
470
  }
94
471
 
95
- const IntegrationView: React.FC<Props> = () => {
472
+ const IntegrationView: React.FC<Props> = ({
473
+ data: processInput,
474
+ variant,
475
+ onTaskClick,
476
+ drawerOpen,
477
+ processTaskId: selectedProcessTaskId,
478
+ }: Props) => {
479
+ const [process, setProcess] = useState<
480
+ Process | ProcessExecutionDetails | undefined
481
+ >(processInput);
96
482
  const [nodes, setNodes, onNodesChange] = useNodesState<any>([]);
97
483
  const [edges, setEdges, onEdgesChange] = useEdgesState<any>([]);
98
- const { fitView } = useReactFlow();
484
+ const [zonesY, setZonesY] = useEdgesState<any>([]);
485
+ const [zonesX, setZonesX] = useEdgesState<any>([]);
486
+
487
+ const { setCenter, fitView } = useReactFlow();
99
488
 
100
489
  const onConnect = useCallback(() => {}, []);
101
490
  const onLayout = useCallback(
102
- ({ useInitialNodes = false }: any) => {
103
- const opts = { ...elkOptions };
104
- const ns = useInitialNodes ? initialNodes : nodes;
105
- const es = useInitialNodes ? initialEdges : edges;
106
-
107
- getLayoutedElements(ns, es, opts).then(
108
- ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
109
- setNodes(layoutedNodes);
110
- setEdges(layoutedEdges);
111
- fitView();
112
- },
113
- );
491
+ (processInput: any) => {
492
+ const tasks = (process as Process)?.processTasks;
493
+ if (
494
+ (tasks && tasks.length > 0) ||
495
+ (processInput && processInput?.processTasks?.length > 0)
496
+ ) {
497
+ const width = calculateMaxWidth(
498
+ variant === "process"
499
+ ? ((processInput ?? (process as Process))
500
+ ?.processTasks as ProcessTask[])
501
+ : ((processInput ?? (process as ProcessExecutionDetails))
502
+ ?.processTaskExecutions as ProcessTaskExecution[]),
503
+ );
504
+
505
+ const mapped = mapProcessTasksToNodesAndEdges(
506
+ processInput ?? process,
507
+ width,
508
+ variant as "process" | "process-execution",
509
+ );
510
+
511
+ const opts = { ...elkOptions };
512
+ const ns = mapped.nodes;
513
+ const es = mapped.edges;
514
+
515
+ getLayoutedElements(ns, es, opts).then(
516
+ ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
517
+ setNodes(layoutedNodes);
518
+ setEdges(layoutedEdges);
519
+
520
+ var zonesY = _.uniqBy(
521
+ layoutedNodes.filter((n: any) => n.type === "task-node"),
522
+ "data.processTask.sort",
523
+ ).map((n: any) => ({
524
+ sort: n?.data?.processTask?.sort,
525
+ y: n.position.y,
526
+ height: n.height,
527
+ }));
528
+
529
+ setZonesY(zonesY);
530
+
531
+ var zonesX = _.uniqBy(
532
+ layoutedNodes.filter((n: any) => n.type === "group-node"),
533
+ "data.parallelProcessingGroup",
534
+ ).map((n: any) => ({
535
+ parallelProcessingGroup: n?.data?.parallelProcessingGroup,
536
+ x: n.position.x,
537
+ width: n.width,
538
+ }));
539
+
540
+ setZonesX(zonesX);
541
+
542
+ fitView();
543
+ },
544
+ );
545
+ } else if (
546
+ (tasks && tasks.length === 0) ||
547
+ (processInput && processInput?.processTasks?.length === 0)
548
+ ) {
549
+ const mapped = mapEmptyNodesAndEdges(processInput ?? process, 400);
550
+
551
+ const opts = { ...elkOptions };
552
+ const ns = mapped.nodes;
553
+ const es = mapped.edges;
554
+
555
+ getLayoutedElements(ns, es, opts).then(
556
+ ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
557
+ setNodes(layoutedNodes);
558
+ setEdges(layoutedEdges);
559
+ fitView();
560
+ },
561
+ );
562
+ }
114
563
  },
115
564
  [nodes, edges],
116
565
  );
117
566
 
567
+ const handleNodeClick = (
568
+ _event: any,
569
+ node: {
570
+ id: React.SetStateAction<string>;
571
+ position: { x: number; y: number };
572
+ width: number;
573
+ height: number;
574
+ data: any;
575
+ parentId?: string;
576
+ },
577
+ ) => {
578
+ if (!drawerOpen) {
579
+ if (onTaskClick) {
580
+ if (variant === "process") onTaskClick(node.data.processTask.id);
581
+ else if (variant === "process-execution")
582
+ onTaskClick(node.data.processTaskExecution);
583
+ }
584
+
585
+ setTimeout(() => {
586
+ var parentx = 0;
587
+ var parenty = 0;
588
+
589
+ if (node.parentId) {
590
+ const parentNode = nodes.find((n) => n.id === node.parentId);
591
+ if (parentNode) {
592
+ parentx = parentNode.position.x;
593
+ parenty = parentNode.position.y;
594
+ }
595
+ }
596
+
597
+ const centerX = parentx + node.position.x + node.width / 2;
598
+ const centerY = parenty + node.position.y + node.height / 2;
599
+
600
+ setCenter(centerX, centerY, { zoom: 1.2, duration: 800 });
601
+ }, 300);
602
+ }
603
+ };
604
+
118
605
  // Calculate the initial layout on mount.
119
606
  useLayoutEffect(() => {
120
- onLayout({ useInitialNodes: true });
607
+ onLayout(process);
121
608
  }, []);
122
609
 
610
+ // ----- Proximity Connect Logic -----
611
+ const store = useStoreApi();
612
+ const { getInternalNode } = useReactFlow();
613
+ const MIN_DISTANCE_LOCAL = 150;
614
+
615
+ const getClosestEdge = useCallback(
616
+ (node: Node, isTemp = true) => {
617
+ const { nodeLookup } = store.getState();
618
+ const internalNode = getInternalNode(node.id);
619
+ if (!internalNode) return null;
620
+
621
+ // drag vector
622
+ const dragDx =
623
+ (node.position?.x ?? internalNode.internals.positionAbsolute.x) -
624
+ internalNode.internals.positionAbsolute.x;
625
+ const dragDy =
626
+ (node.position?.y ?? internalNode.internals.positionAbsolute.y) -
627
+ internalNode.internals.positionAbsolute.y;
628
+
629
+ const isVerticalDrag = Math.abs(dragDy) > Math.abs(dragDx);
630
+ const dragSignX = Math.sign(dragDx);
631
+ const dragSignY = Math.sign(dragDy);
632
+
633
+ type Candidate = {
634
+ distance: number;
635
+ node: InternalNode<Node> | null;
636
+ dx: number;
637
+ dy: number;
638
+ };
639
+
640
+ const absolutePosWithParent = (n: InternalNode<Node>) => {
641
+ const abs = n.internals.positionAbsolute;
642
+
643
+ const parentNode = n.parentId ? getInternalNode(n.parentId) : null;
644
+ const parentAbs = parentNode?.internals.positionAbsolute ?? {
645
+ x: 0,
646
+ y: 0,
647
+ };
648
+
649
+ return { x: abs.x + parentAbs.x, y: abs.y + parentAbs.y };
650
+ };
651
+
652
+ const myPos = absolutePosWithParent(internalNode);
653
+
654
+ // Only siblings
655
+ const siblings = Array.from(nodeLookup.values()).filter(
656
+ (n) => n.parentId === internalNode.parentId,
657
+ );
658
+
659
+ const directionalCandidate = siblings.reduce<Candidate>(
660
+ (res, n) => {
661
+ if (n.id === internalNode.id) return res;
662
+ const np = absolutePosWithParent(n);
663
+ const dx = np.x - myPos.x;
664
+ const dy = np.y - myPos.y;
665
+ const d = Math.sqrt(dx * dx + dy * dy);
666
+ if (d >= MIN_DISTANCE_LOCAL) return res;
667
+
668
+ let directionMatches = true;
669
+ if (isVerticalDrag) {
670
+ if (dragSignY !== 0) directionMatches = Math.sign(dy) === dragSignY;
671
+ } else {
672
+ if (dragSignX !== 0) directionMatches = Math.sign(dx) === dragSignX;
673
+ }
674
+
675
+ if (!directionMatches) return res;
676
+ if (d < res.distance) return { distance: d, node: n, dx, dy };
677
+ return res;
678
+ },
679
+ { distance: Number.MAX_VALUE, node: null, dx: 0, dy: 0 },
680
+ );
681
+
682
+ let chosen = directionalCandidate;
683
+ if (!chosen.node) {
684
+ chosen = siblings.reduce(
685
+ (res, n) => {
686
+ if (n.id === internalNode.id) return res;
687
+ const np = absolutePosWithParent(n);
688
+ const dx = np.x - myPos.x;
689
+ const dy = np.y - myPos.y;
690
+ const d = Math.sqrt(dx * dx + dy * dy);
691
+ if (d < res.distance && d < MIN_DISTANCE_LOCAL)
692
+ return { distance: d, node: n, dx, dy };
693
+ return res;
694
+ },
695
+ { distance: Number.MAX_VALUE, node: null, dx: 0, dy: 0 } as Candidate,
696
+ );
697
+ }
698
+
699
+ if (!chosen.node) return null;
700
+
701
+ const chosenPos = absolutePosWithParent(chosen.node);
702
+ const chosenAbove = chosenPos.y < myPos.y;
703
+
704
+ // Default handle selection by ReactFlow:
705
+ // chosenAbove => chosen -> dragged
706
+ // chosenBelow => dragged -> chosen
707
+ const sourceId = chosenAbove ? chosen.node.id : internalNode.id;
708
+ const targetId = chosenAbove ? internalNode.id : chosen.node.id;
709
+
710
+ return {
711
+ id: `${sourceId}-${targetId}${isTemp ? "-temp" : "-final"}`,
712
+ source: sourceId,
713
+ target: targetId,
714
+ className: isTemp ? "temp" : "final",
715
+ };
716
+ },
717
+ [store, getInternalNode],
718
+ );
719
+
720
+ const onNodeDrag = useCallback(
721
+ (_: any, node: Node) => {
722
+ const closeEdge = getClosestEdge(node, true);
723
+ setEdges((es) => {
724
+ const nextEdges = es.filter((e) => e.className !== "temp");
725
+ if (
726
+ closeEdge &&
727
+ !nextEdges.some(
728
+ (ne) =>
729
+ ne.source === closeEdge.source && ne.target === closeEdge.target,
730
+ )
731
+ ) {
732
+ nextEdges.push(closeEdge);
733
+ }
734
+ return nextEdges;
735
+ });
736
+ },
737
+ [getClosestEdge, setEdges],
738
+ );
739
+
740
+ // const onNodeDragStop = useCallback(
741
+ // (_: any, node: Node) => {
742
+ // const closeEdge = getClosestEdge(node, false);
743
+ // setEdges((es) => {
744
+ // const nextEdges = es.filter((e) => e.className !== "temp");
745
+ // if (
746
+ // closeEdge &&
747
+ // !nextEdges.some(
748
+ // (ne) =>
749
+ // ne.source === closeEdge.source && ne.target === closeEdge.target,
750
+ // )
751
+ // ) {
752
+ // nextEdges.push(closeEdge);
753
+ // }
754
+ // return nextEdges;
755
+ // });
756
+ // },
757
+ // [getClosestEdge],
758
+ // );
759
+ // ----- End Proximity Connect Logic -----
760
+
761
+ useLayoutEffect(() => {
762
+ let data = JSON.parse(JSON.stringify(nodes));
763
+
764
+ data = data.map((node: any) => {
765
+ return {
766
+ ...node,
767
+ data: {
768
+ ...node.data,
769
+ disabled: drawerOpen,
770
+ selected:
771
+ selectedProcessTaskId === node.data?.processTask?.id ||
772
+ selectedProcessTaskId === node.data?.processTaskExecution?.id,
773
+ },
774
+ };
775
+ });
776
+
777
+ setNodes(data);
778
+ }, [drawerOpen, selectedProcessTaskId]);
779
+
780
+ // const handleNodeDragStart = (_: MouseEvent, node: Node): any => {
781
+ // let edgesFiltered = edges.filter((edge: any) => !(edge.source === node.id || edge.target === node.id));
782
+
783
+ // let edgesRemoved = edges.filter((edge: any) => (edge.source === node.id || edge.target === node.id));
784
+
785
+ // let source;
786
+
787
+ // let target;
788
+
789
+ // edgesRemoved.forEach((edge: any) => {
790
+ // if(edge.source === node.id) {
791
+ // target = edge.target;
792
+ // }
793
+ // if(edge.target === node.id) {
794
+ // source = edge.source;
795
+ // }
796
+ // });
797
+
798
+ // edgesFiltered.push({
799
+ // id: `${source}-${target}-temp`,
800
+ // sources: [source],
801
+ // targets: [target],
802
+ // source,
803
+ // target,
804
+ // type: "default-edge",
805
+ // //markerEnd: markerEnd,
806
+ // })
807
+
808
+ // setEdges(edgesFiltered);
809
+ // };
810
+
811
+ const handleNodeDragStart = (_e: ReactMouseEvent, node: Node): any => {
812
+ let edgesFiltered = [];
813
+
814
+ const edgeList: any[] = [];
815
+
816
+ edges.forEach((edge: any) => {
817
+ if (edge.source === node.id || edge.target === node.id) {
818
+ edgeList.push(edge);
819
+ }
820
+ });
821
+
822
+ let edgeIds: any[] = [];
823
+
824
+ edgeList.forEach((edge: any) => {
825
+ edgeIds.push(edge.source);
826
+ edgeIds.push(edge.target);
827
+ });
828
+
829
+ edgeIds = _.uniq(edgeIds);
830
+
831
+ edgesFiltered = edges.filter((edge: any) => {
832
+ return (
833
+ edgeIds.includes(edge.source) === false &&
834
+ edgeIds.includes(edge.target) === false
835
+ );
836
+ });
837
+
838
+ edgesFiltered = edgesFiltered.filter(
839
+ (edge: any) =>
840
+ edge.id.includes((node?.data?.processTask as ProcessTask)?.id) ===
841
+ false,
842
+ );
843
+
844
+ edgeIds = edgeIds.filter((id: any) => id !== node.id);
845
+
846
+ if (edgeIds.length === 2) {
847
+ edgesFiltered.push({
848
+ id: `${edgeIds[0]}-${edgeIds[1]}-temp`,
849
+ sources: [edgeIds[0]],
850
+ targets: [edgeIds[1]],
851
+ source: edgeIds[0],
852
+ target: edgeIds[1],
853
+ type: "default-edge",
854
+ markerEnd: markerEnd,
855
+ });
856
+ }
857
+
858
+ setEdges(edgesFiltered);
859
+ };
860
+
861
+ const handleNodeDragEnd = (_e: ReactMouseEvent, node: Node): any => {
862
+ let zoneY = zonesY.find(
863
+ (z: any) =>
864
+ getOverlapY(
865
+ { y: z.y, height: z.height },
866
+ { y: node?.position?.y, height: node.height },
867
+ ) > 0,
868
+ );
869
+
870
+ if (!zoneY) {
871
+ const maxZone = _.maxBy(zonesY, "y");
872
+ const minZone = _.minBy(zonesY, "y");
873
+
874
+ if (node?.height && node?.position?.y + node?.height < minZone.y) {
875
+ zoneY = {
876
+ ...minZone,
877
+ sort: minZone.sort - 1,
878
+ };
879
+ } else if (node?.position?.y > maxZone.y + maxZone.height) {
880
+ zoneY = {
881
+ ...maxZone,
882
+ sort: maxZone.sort + 1,
883
+ };
884
+ } else {
885
+ const localZones = _.sortBy(zonesY, "y");
886
+
887
+ for (let i = 0; i < localZones.length - 1; i++) {
888
+ const currentZone = localZones[i];
889
+ const nextZone = localZones[i + 1];
890
+
891
+ if (
892
+ node?.position?.y > currentZone.y + currentZone.height &&
893
+ node?.position?.y < nextZone.y
894
+ ) {
895
+ zoneY = {
896
+ ...currentZone,
897
+ sort: currentZone.sort + 0.5,
898
+ };
899
+ break;
900
+ }
901
+ }
902
+ }
903
+ }
904
+
905
+ const currentGroup = node?.parentId
906
+ ? nodes.find((n) => n.id === node?.parentId)
907
+ : null;
908
+
909
+ let zoneX: any;
910
+ let overlapX = 0;
911
+
912
+ for (let i = 0; i < zonesX.length; i++) {
913
+ const zone = zonesX[i];
914
+
915
+ const overlap = getOverlapX(
916
+ { x: zone.x, width: zone.width },
917
+ { x: currentGroup.x + node?.position?.x, width: node.width },
918
+ );
919
+
920
+ if (overlap > overlapX) {
921
+ overlapX = overlap;
922
+ zoneX = zone;
923
+ }
924
+ }
925
+
926
+ if (!zoneX) {
927
+ const maxZone = _.maxBy(zonesX, "x");
928
+ const minZone = _.minBy(zonesX, "x");
929
+
930
+ if (currentGroup.x + node?.position?.x + node?.width < minZone.x) {
931
+ zoneX = {
932
+ ...minZone,
933
+ parallelProcessingGroup: minZone.parallelProcessingGroup - 1,
934
+ };
935
+ } else if (
936
+ currentGroup.x + node?.position?.x >
937
+ maxZone.x + maxZone.width
938
+ ) {
939
+ zoneX = {
940
+ ...maxZone,
941
+ parallelProcessingGroup: maxZone.parallelProcessingGroup + 1,
942
+ };
943
+ } else {
944
+ const localZones = _.sortBy(zonesY, "y");
945
+
946
+ for (let i = 0; i < localZones.length - 1; i++) {
947
+ const currentZone = localZones[i];
948
+ const nextZone = localZones[i + 1];
949
+
950
+ if (
951
+ currentGroup.x + node?.position?.x > currentZone.x &&
952
+ currentGroup.x + node?.position?.x < nextZone.x + nextZone.width
953
+ ) {
954
+ zoneX = {
955
+ ...currentZone,
956
+ parallelProcessingGroup:
957
+ currentZone.parallelProcessingGroup + 0.5,
958
+ };
959
+ break;
960
+ }
961
+ }
962
+ }
963
+ }
964
+
965
+ if (!zoneY && !zoneX) {
966
+ onLayout(process);
967
+ return;
968
+ }
969
+
970
+ const modifiedProcess = JSON.parse(JSON.stringify(process));
971
+
972
+ let updatedTasks = modifiedProcess?.processTasks?.map((task: any) => {
973
+ if (zoneX && task.id === (node?.data?.processTask as ProcessTask)?.id) {
974
+ return {
975
+ ...task,
976
+ parallelProcessingGroup: zoneX.parallelProcessingGroup,
977
+ };
978
+ }
979
+ return task;
980
+ });
981
+
982
+ updatedTasks = updatedTasks.map((task: any) => {
983
+ if (zoneX && task.id === (node?.data?.processTask as ProcessTask)?.id) {
984
+ return {
985
+ ...task,
986
+ sort: zoneY.sort,
987
+ };
988
+ }
989
+ return task;
990
+ });
991
+
992
+ let prevParallelProcessingGroup: any = null;
993
+ let index = 0;
994
+
995
+ updatedTasks = _.sortBy(updatedTasks, [
996
+ "parallelProcessingGroup",
997
+ "sort",
998
+ ]).map((task: any) => {
999
+ if (task.parallelProcessingGroup !== prevParallelProcessingGroup) {
1000
+ prevParallelProcessingGroup = task.parallelProcessingGroup;
1001
+ index++;
1002
+ }
1003
+
1004
+ task.parallelProcessingGroup = index;
1005
+
1006
+ return task;
1007
+ });
1008
+
1009
+ var partitionedTasks = _.values(
1010
+ _.groupBy(updatedTasks, "parallelProcessingGroup"),
1011
+ );
1012
+
1013
+ let processTaskValue: any[] = [];
1014
+
1015
+ partitionedTasks.forEach((partition: any) => {
1016
+ index = 0;
1017
+ let prevSort: any = null;
1018
+
1019
+ const sortedPartition = _.sortBy(partition, ["sort", "name"]).map(
1020
+ (task: any) => {
1021
+ if (task.sort !== prevSort) {
1022
+ prevSort = task.sort;
1023
+ index++;
1024
+ }
1025
+
1026
+ task.sort = index;
1027
+
1028
+ return task;
1029
+ },
1030
+ );
1031
+
1032
+ processTaskValue = processTaskValue.concat(sortedPartition);
1033
+ });
1034
+
1035
+ modifiedProcess.processTasks = processTaskValue;
1036
+
1037
+ setProcess(modifiedProcess);
1038
+
1039
+ onLayout(modifiedProcess);
1040
+ };
1041
+
123
1042
  return (
124
1043
  <Box sx={{ flexGrow: 1 }}>
125
- <ReactFlowProvider>
126
- <Box sx={{ width: "750px", height: "600px" }}>
127
- <ReactFlow
128
- nodes={nodes}
129
- edges={edges}
130
- nodeTypes={nodeTypes}
131
- edgeTypes={edgeTypes}
132
- onConnect={onConnect}
133
- onNodesChange={onNodesChange}
134
- onEdgesChange={onEdgesChange}
135
- fitView={true} // Fits the view on initial load
136
- fitViewOptions={{
137
- padding: 0.1,
138
- includeHiddenNodes: false,
139
- minZoom: 0.1,
140
- maxZoom: 2,
141
- duration: 200,
142
- nodes: [{ id: "1" }, { id: "2" }], // nodes to fit
143
- }} // Optional options for initial fit
144
- nodesDraggable={false}
145
- minZoom={0.1} // Lock zoom to 1
146
- maxZoom={2} // Lock zoom to 1
147
- >
148
- <Background />
149
- <Controls />
150
- </ReactFlow>
151
- </Box>
152
- </ReactFlowProvider>
1044
+ <Box sx={{ width: "100%", height: "100%" }}>
1045
+ {/* <Box sx={{ width: "750px", height: "750px" }}> */}
1046
+
1047
+ <ReactFlow
1048
+ nodes={nodes}
1049
+ edges={edges}
1050
+ nodeTypes={nodeTypes}
1051
+ edgeTypes={edgeTypes}
1052
+ onConnect={onConnect}
1053
+ onNodesChange={onNodesChange}
1054
+ onEdgesChange={onEdgesChange}
1055
+ onNodeClick={handleNodeClick}
1056
+ onNodeDragStart={handleNodeDragStart}
1057
+ onNodeDragStop={handleNodeDragEnd}
1058
+ onNodeDrag={onNodeDrag}
1059
+ //onNodeDragStop={onNodeDragStop}
1060
+ fitView={true} // Fits the view on initial load
1061
+ fitViewOptions={{
1062
+ padding: 0.1,
1063
+ includeHiddenNodes: false,
1064
+ minZoom: 0.1,
1065
+ maxZoom: 2,
1066
+ duration: 200,
1067
+ nodes: nodes, // nodes to fit
1068
+ }} // Optional options for initial fit
1069
+ nodesDraggable={true}
1070
+ minZoom={0.1} // Lock zoom to 1
1071
+ maxZoom={2} // Lock zoom to 1
1072
+ nodesConnectable={!drawerOpen}
1073
+ elementsSelectable={!drawerOpen}
1074
+ panOnDrag={!drawerOpen}
1075
+ zoomOnScroll={!drawerOpen}
1076
+ zoomOnDoubleClick={!drawerOpen}
1077
+ >
1078
+ <Background />
1079
+ <Controls />
1080
+ </ReactFlow>
1081
+ </Box>
153
1082
  </Box>
154
1083
  );
155
1084
  };
156
1085
 
157
- export default () => (
1086
+ export default (props: Props) => (
158
1087
  <ReactFlowProvider>
159
- <IntegrationView />
1088
+ <IntegrationView
1089
+ data={props.data}
1090
+ variant={props.variant}
1091
+ onTaskClick={props.onTaskClick}
1092
+ drawerOpen={props.drawerOpen}
1093
+ processTaskId={props.processTaskId}
1094
+ />
160
1095
  </ReactFlowProvider>
161
1096
  );