@evenicanpm/admin-integrate 1.2.2 → 1.4.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 (215) 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 +30 -0
  5. package/documents/Process/fragments.ts +22 -0
  6. package/documents/Process/get-process-details.ts +72 -0
  7. package/documents/Process/list.ts +24 -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/ProcessExport/read.ts +108 -0
  15. package/documents/ProcessScheduleGroup/read.ts +43 -0
  16. package/documents/ProcessTask/fragments.ts +288 -0
  17. package/documents/ProcessTask/read.ts +12 -0
  18. package/documents/ProcessTemplate/fragments.ts +74 -0
  19. package/documents/ProcessTemplate/list.ts +67 -0
  20. package/documents/ProcessTemplate/read.ts +12 -0
  21. package/documents/RunProcess/run.ts +11 -0
  22. package/package.json +4 -3
  23. package/src/api/Integrations/queries/get-process.query.ts +12 -12
  24. package/src/api/Integrations/queries/get-process.server.ts +7 -2
  25. package/src/api/configuration/queries/configuration-export.query.ts +48 -0
  26. package/src/api/configuration/queries/configuration-export.server.ts +9 -0
  27. package/src/api/configuration/queries/index.ts +1 -0
  28. package/src/api/dashboard/queries/get-process-executions.query.ts +6 -3
  29. package/src/api/dashboard/queries/get-process-executions.server.ts +1 -1
  30. package/src/api/execution-details/queries/get-process-execution-details.query.ts +46 -0
  31. package/src/api/execution-details/queries/get-process-execution-details.server.ts +11 -0
  32. package/src/api/execution-details/queries/get-process-executions-by-process.query.ts +48 -0
  33. package/src/api/execution-details/queries/get-process-executions-by-process.server.ts +11 -0
  34. package/src/api/execution-details/queries/index.ts +2 -0
  35. package/src/api/process/mutations/copy-process.mutation.ts +45 -0
  36. package/src/api/process/mutations/copy-process.server.ts +14 -0
  37. package/src/api/process/mutations/index.ts +2 -0
  38. package/src/api/process/mutations/run-process.mutation.ts +41 -0
  39. package/src/api/process/mutations/run-process.server.ts +14 -0
  40. package/src/api/process/queries/get-process-by-id.query.ts +85 -0
  41. package/src/api/process/queries/get-process-by-id.server.ts +20 -0
  42. package/src/api/process/queries/index.ts +4 -0
  43. package/src/api/process-config/mutation/index.ts +2 -0
  44. package/src/api/process-config/mutation/process-config-import.mutation.ts +42 -0
  45. package/src/api/process-config/mutation/process-config-import.server.ts +14 -0
  46. package/src/api/process-config/mutation/process-config-merge.mutation.ts +33 -0
  47. package/src/api/process-config/mutation/process-config-merge.server.ts +14 -0
  48. package/src/api/process-task/queries/get-process-task-by-id.query.ts +46 -0
  49. package/src/api/process-task/queries/get-process-task-by-id.server.ts +9 -0
  50. package/src/api/process-task/queries/index.ts +1 -0
  51. package/src/api/scheduler/mutation/create-process-schedule-group-details.mutation.ts +47 -0
  52. package/src/api/scheduler/mutation/create-process-schedule-group-details.server.ts +14 -0
  53. package/src/api/scheduler/mutation/index.ts +2 -0
  54. package/src/api/scheduler/mutation/update-process-schedule-group-details.mutation.ts +47 -0
  55. package/src/api/scheduler/mutation/update-process-schedule-group-details.server.ts +14 -0
  56. package/src/api/scheduler/queries/get-non-scheduled-processes.query.ts +48 -0
  57. package/src/api/scheduler/queries/get-non-scheduled-processes.server.ts +11 -0
  58. package/src/api/scheduler/queries/get-process-schedule-group-details.query.ts +6 -3
  59. package/src/api/scheduler/queries/get-process-schedule-group-details.server.ts +3 -3
  60. package/src/api/scheduler/queries/get-process-schedule.query.ts +6 -3
  61. package/src/api/scheduler/queries/get-process-schedule.server.ts +3 -3
  62. package/src/api/scheduler/queries/get-scheduled-processes.query.ts +6 -3
  63. package/src/api/scheduler/queries/get-scheduled-processes.server.ts +1 -1
  64. package/src/api/scheduler/queries/index.ts +3 -2
  65. package/src/api/templates/queries/get-process-template-groups.query.ts +48 -0
  66. package/src/api/templates/queries/get-process-template-groups.server.ts +11 -0
  67. package/src/api/templates/queries/get-process-template-records.query.ts +48 -0
  68. package/src/api/templates/queries/get-process-template-records.server.ts +11 -0
  69. package/src/api/templates/queries/get-process-template.query.ts +48 -0
  70. package/src/api/templates/queries/get-process-template.server.ts +9 -0
  71. package/src/api/templates/queries/get-process-templates.query.ts +45 -0
  72. package/src/api/templates/queries/get-process-templates.server.ts +9 -0
  73. package/src/api/templates/queries/index.ts +5 -0
  74. package/src/api/templates/queries/template-input-search.query.ts +39 -0
  75. package/src/api/templates/queries/template-input-search.server.ts +42 -0
  76. package/src/api/templates/queries/types.ts +34 -0
  77. package/src/components/breadcrumbs/breadcrumbs.tsx +33 -6
  78. package/src/components/button/outlined-icon-button.tsx +2 -2
  79. package/src/components/core/date-time-popover.tsx +12 -5
  80. package/src/components/core/drawer-buttons.tsx +52 -0
  81. package/src/components/core/edited-typography.tsx +2 -2
  82. package/src/components/core/index.ts +4 -2
  83. package/src/components/core/loading.tsx +1 -1
  84. package/src/components/core/status-tag.tsx +97 -0
  85. package/src/components/core/title-edit.tsx +31 -22
  86. package/src/components/dashboard-list/dashboard-list-row.tsx +22 -29
  87. package/src/components/dashboard-list/dashboard-list.tsx +20 -16
  88. package/src/components/data-table/table-header.tsx +6 -8
  89. package/src/components/data-table/table-pagination.tsx +1 -1
  90. package/src/components/data-table/table-row.tsx +1 -1
  91. package/src/components/data-table/table-skeleton.tsx +10 -5
  92. package/src/components/execution/execution-filter.ts +1 -1
  93. package/src/components/execution/execution-status-icon.tsx +7 -7
  94. package/src/components/execution/execution-tag.tsx +12 -77
  95. package/src/components/execution/index.ts +1 -1
  96. package/src/components/execution-history-drawer/execution-history-drawer.tsx +202 -0
  97. package/src/components/execution-history-drawer/executions-card.tsx +85 -0
  98. package/src/components/execution-history-drawer/index.ts +1 -0
  99. package/src/components/footer/footer.tsx +10 -6
  100. package/src/components/header/dashboard-list-header.tsx +12 -7
  101. package/src/components/header/execution-details-header.tsx +35 -26
  102. package/src/components/header/header.tsx +10 -3
  103. package/src/components/header/index.ts +1 -1
  104. package/src/components/header/integration-details-header.tsx +108 -45
  105. package/src/components/integration-list/index.ts +2 -1
  106. package/src/components/integration-list/integration-filter.ts +1 -1
  107. package/src/components/integration-list/integration-status-icon.tsx +7 -8
  108. package/src/components/integration-list/integration-tag.tsx +6 -50
  109. package/src/components/integration-list/list/integration-list-row.tsx +161 -0
  110. package/src/components/integration-list/list/integration-list-table.tsx +62 -0
  111. package/src/{pages/integrations/integration-list → components/integration-list/list}/integration-list.tsx +47 -51
  112. package/src/components/integration-view/animated-svg.tsx +31 -0
  113. package/src/components/integration-view/edges/default-edge.tsx +2 -6
  114. package/src/components/integration-view/elk-layout-options.ts +2 -2
  115. package/src/components/integration-view/elk-types.ts +35 -6
  116. package/src/components/integration-view/flow-types.tsx +12 -0
  117. package/src/components/integration-view/integration-view.tsx +562 -56
  118. package/src/components/integration-view/nodes/add-node.tsx +20 -0
  119. package/src/components/integration-view/nodes/empty-node.tsx +65 -0
  120. package/src/components/integration-view/nodes/entry-node.tsx +98 -4
  121. package/src/components/integration-view/nodes/execution-entry-node.tsx +107 -0
  122. package/src/components/integration-view/nodes/execution-task-node.tsx +88 -0
  123. package/src/components/integration-view/nodes/group-node.tsx +33 -13
  124. package/src/components/integration-view/nodes/row-node.tsx +19 -0
  125. package/src/components/integration-view/nodes/task-node.tsx +50 -16
  126. package/src/components/integration-view/task-icon.tsx +193 -0
  127. package/src/components/integration-view/temp-data/initialElements.tsx +34 -32
  128. package/src/components/integration-view/types.ts +2 -2
  129. package/src/components/integration-view/utils/mapping.ts +404 -0
  130. package/src/components/layouts/main-layout.tsx +3 -4
  131. package/src/components/layouts/root-container.tsx +5 -11
  132. package/src/components/link-cards/link-card.tsx +15 -4
  133. package/src/components/link-cards/styles.ts +1 -1
  134. package/src/components/list-filter/date-filter.tsx +7 -4
  135. package/src/components/list-filter/date-range-filter.tsx +15 -7
  136. package/src/components/list-filter/index.ts +1 -1
  137. package/src/components/list-filter/list-filter.tsx +31 -26
  138. package/src/components/list-filter/multi-select-filter.tsx +11 -10
  139. package/src/components/list-filter/select-filter.tsx +23 -12
  140. package/src/components/scheduler/day-selector.tsx +29 -15
  141. package/src/components/scheduler/day-tag.tsx +14 -51
  142. package/src/components/scheduler/index.ts +2 -1
  143. package/src/components/scheduler/schedule-drawer/details-reducer.ts +217 -0
  144. package/src/components/scheduler/schedule-drawer/schedule-details-integrations.tsx +501 -0
  145. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details-main.tsx +137 -100
  146. package/src/components/scheduler/schedule-drawer/schedule-details-name.tsx +94 -0
  147. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details-skeleton.tsx +1 -2
  148. package/src/{pages → components}/scheduler/schedule-drawer/schedule-details.tsx +10 -14
  149. package/src/components/scheduler/schedule-drawer/schedule-drawer-group.tsx +214 -0
  150. package/src/{pages → components}/scheduler/schedule-drawer/schedule-drawer-legacy.tsx +7 -26
  151. package/src/components/scheduler/schedule-drawer/schedule-drawer.tsx +116 -0
  152. package/src/components/scheduler/schedule-drawer/sortable-integration-row.tsx +130 -0
  153. package/src/components/scheduler/schedule-filter.ts +1 -1
  154. package/src/components/scheduler/schedule-icon.tsx +5 -6
  155. package/src/components/scheduler/schedule-integration-icon.tsx +31 -0
  156. package/src/components/templates/index.ts +1 -0
  157. package/src/components/templates/inputs/index.tsx +1392 -0
  158. package/src/components/templates/template-filter.ts +5 -0
  159. package/src/components/templates/templates-list/index.ts +1 -0
  160. package/src/components/templates/templates-list/templates-list-row.tsx +55 -0
  161. package/src/components/templates/templates-list/templates-list-table.tsx +58 -0
  162. package/src/components/templates/templates-list/templates-list.tsx +253 -0
  163. package/src/components/templates/types.tsx +76 -0
  164. package/src/components/templates/wizard.tsx +737 -0
  165. package/src/hooks/use-breadcrumbs.ts +1 -1
  166. package/src/hooks/use-recurrence.tsx +1 -2
  167. package/src/pages/dashboard/dashboard-link-cards.tsx +8 -11
  168. package/src/pages/dashboard/dashboard-list-sections.tsx +8 -10
  169. package/src/pages/dashboard/dashboard.tsx +1 -2
  170. package/src/pages/execution-details/execution-details.tsx +212 -14
  171. package/src/pages/execution-details/task-execution-details.tsx +160 -0
  172. package/src/pages/execution-details/task-execution-drawer.tsx +54 -0
  173. package/src/pages/executions/executions-list/executions-list-row.tsx +21 -27
  174. package/src/pages/executions/executions-list/executions-list-table.tsx +29 -36
  175. package/src/pages/executions/executions-list/executions-list.tsx +24 -18
  176. package/src/pages/executions/executions.tsx +11 -15
  177. package/src/pages/integration-create/index.ts +1 -0
  178. package/src/pages/integration-create/integration-create.tsx +216 -0
  179. package/src/pages/integration-create/pre-creation-step.tsx +84 -0
  180. package/src/pages/integration-create/select-step.tsx +105 -0
  181. package/src/pages/integration-create/template-list-step.tsx +77 -0
  182. package/src/pages/integration-create/wizard-step.tsx +51 -0
  183. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +265 -0
  184. package/src/pages/integration-details/import-process/copy-tasks-row.tsx +77 -0
  185. package/src/pages/integration-details/import-process/import-confirm.tsx +61 -0
  186. package/src/pages/integration-details/import-process/import-drawer.tsx +48 -0
  187. package/src/pages/integration-details/import-process/import-process-reducer.ts +90 -0
  188. package/src/pages/integration-details/import-process/import-process.tsx +149 -0
  189. package/src/pages/integration-details/index.ts +1 -0
  190. package/src/pages/integration-details/integration-details.tsx +468 -0
  191. package/src/pages/integration-details/task-drawer/add-task.tsx +172 -0
  192. package/src/pages/integration-details/task-drawer/edit-task.tsx +161 -0
  193. package/src/pages/integration-details/task-drawer/task-drawer.tsx +157 -0
  194. package/src/pages/integration-details/task-drawer/task-reducer.ts +103 -0
  195. package/src/pages/integrations/integrations.tsx +11 -14
  196. package/src/pages/scheduler/scheduler.tsx +12 -24
  197. package/src/pages/scheduler/schedules-list/schedules-list-row.tsx +27 -37
  198. package/src/pages/scheduler/schedules-list/schedules-list-table.tsx +28 -43
  199. package/src/pages/scheduler/schedules-list/schedules-list.tsx +48 -21
  200. package/src/utils/date-functions.ts +69 -0
  201. package/src/utils/slugify.ts +3 -0
  202. package/tsconfig.json +12 -4
  203. package/src/hooks/use-timestamp.tsx +0 -25
  204. package/src/pages/integrations/integration-list/integration-list-row.tsx +0 -147
  205. package/src/pages/integrations/integration-list/integration-list-table.tsx +0 -78
  206. package/src/pages/scheduler/schedule-drawer/schedule-details-integrations.tsx +0 -227
  207. package/src/pages/scheduler/schedule-drawer/schedule-details-name.tsx +0 -77
  208. package/src/pages/scheduler/schedule-drawer/schedule-drawer-buttons.tsx +0 -72
  209. package/src/pages/scheduler/schedule-drawer/schedule-drawer-group.tsx +0 -103
  210. package/src/pages/scheduler/schedule-drawer/schedule-drawer.tsx +0 -101
  211. package/src/pages/scheduler/schedule-drawer/sortable-integration-row.tsx +0 -93
  212. /package/src/{pages/integrations/integration-list → components/integration-list/list}/index.ts +0 -0
  213. /package/src/{pages → components}/scheduler/schedule-drawer/edited/edited-types.ts +0 -0
  214. /package/src/{pages → components}/scheduler/schedule-drawer/edited/index.ts +0 -0
  215. /package/src/{pages → components}/scheduler/schedule-drawer/index.ts +0 -0
@@ -1,31 +1,63 @@
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 Node,
13
19
  ReactFlow,
14
20
  ReactFlowProvider,
15
21
  useEdgesState,
16
22
  useNodesState,
17
23
  useReactFlow,
18
24
  } from "@xyflow/react";
19
-
20
- import { nodeTypes, edgeTypes } from "./flow-types";
21
-
25
+ import type {
26
+ ConfigExport,
27
+ ProcessExecutionDetails,
28
+ ProcessTask,
29
+ ProcessTaskExecution,
30
+ ProcessTaskExport,
31
+ } from "../../../../admin-core/src/api/e4/graphqlRequestSdk";
22
32
  import { layoutOptions as elkOptions } from "./elk-layout-options";
33
+ import type { ElkExtendedEdgeWithFlow, ElkNodeWithFlow } from "./elk-types";
23
34
 
24
- import { initialNodes, initialEdges } from "./temp-data/initialElements";
25
- import { ElkExtendedEdgeWithFlow, ElkNodeWithFlow } from "./elk-types";
35
+ import _ from "lodash";
36
+ import { edgeTypes, nodeTypes } from "./flow-types";
37
+
38
+ import {
39
+ mapToCamelCase,
40
+ mapEmptyNodesAndEdges,
41
+ mapProcessConfigToNodesAndEdges,
42
+ mapProcessTasksToNodesAndEdges,
43
+ } from "./utils/mapping";
26
44
 
27
45
  const elk = new ELK();
28
46
 
47
+ const calculateMaxWidth = (
48
+ processTasks: ProcessTask[] | ProcessTaskExecution[],
49
+ ) => {
50
+ let maxCharCount = 0;
51
+
52
+ processTasks.forEach((task) => {
53
+ if (task.name && task.name.length > maxCharCount) {
54
+ maxCharCount = task.name.length;
55
+ }
56
+ });
57
+
58
+ return Math.ceil(maxCharCount * 14 + 28 + 8 + 24); // Approximate width calculation
59
+ };
60
+
29
61
  const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
30
62
  const graph: ElkNodeWithFlow = {
31
63
  id: "root",
@@ -35,22 +67,30 @@ const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
35
67
  sourcePosition: "bottom",
36
68
  // Hardcoded until width and height calculation is implemented
37
69
  })),
70
+ layoutOptions: {
71
+ "org.eclipse.elk.algorithm": "org.eclipse.elk.layered",
72
+ "org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers": "120", // bigger vertical gap
73
+ },
38
74
  edges: edges,
39
75
  };
40
76
 
41
77
  return elk
42
78
  .layout(graph, { layoutOptions: options })
43
79
  .then((layoutedGraph: any) => {
44
- let nodeItems: any = [];
80
+ const nodeItems: any = [];
45
81
 
46
82
  layoutedGraph.children.forEach((node: any) => {
47
83
  nodeItems.push({
48
84
  ...node,
49
85
  // React Flow expects a position property on the node instead of `x`
50
86
  // and `y` fields.
51
- height: node.height,
87
+ height:
88
+ node.height +
89
+ (node.children && node.children.length > 0 ? calcYOffset() : null),
52
90
  width: node.width,
53
- position: { x: node.x, y: node.y + calcYOffset() },
91
+ x: node.x,
92
+ y: node.y,
93
+ position: { x: node.x, y: node.y },
54
94
  });
55
95
 
56
96
  if (node.children) {
@@ -61,6 +101,8 @@ const getLayoutedElements = (nodes: any, edges: any, options: any = {}) => {
61
101
  // and `y` fields.
62
102
  targetPosition: "top",
63
103
  sourcePosition: "bottom",
104
+ x: node2.x,
105
+ y: node2.y + calcYOffset(),
64
106
  position: { x: node2.x, y: node2.y + calcYOffset() },
65
107
  parentId: node.id,
66
108
  });
@@ -90,72 +132,536 @@ const calcYOffset = () => {
90
132
  interface Props {
91
133
  title?: string; // e.g. Executions
92
134
  section?: string; // e.g. e4Integrate
135
+ data?: ProcessExecutionDetails;
136
+ config?: ConfigExport;
137
+ variant?: "process" | "process-execution";
138
+ onTaskClick?:
139
+ | ((id: string) => void)
140
+ | ((processTaskExecution: ProcessTaskExecution) => void);
141
+ drawerOpen?: boolean;
142
+ processTaskId?: string;
143
+ onConfigChange?: (processConfig: ConfigExport) => void;
144
+ onAdd?: Function;
145
+ canEdit?: boolean;
146
+ }
147
+
148
+ function getOverlapY(rect1: any, rect2: any) {
149
+ // Calculate intersection coordinates
150
+ //const intersectX1 = Math.max(rect1.x, rect2.x);
151
+ const intersectY1 = Math.max(rect1.y, rect2.y);
152
+ const intersectY2 = Math.min(rect1.y + rect1.height, rect2.y + rect2.height);
153
+
154
+ // Check for overlap and calculate area
155
+ if (/*intersectX1 >= intersectX2 ||*/ intersectY1 >= intersectY2) {
156
+ return 0; // No overlap
157
+ } else {
158
+ const overlapHeight = intersectY2 - intersectY1;
159
+ return /*overlapWidth **/ overlapHeight;
160
+ }
93
161
  }
94
162
 
95
- const IntegrationView: React.FC<Props> = () => {
163
+ function getOverlapX(rect1: any, rect2: any) {
164
+ // Calculate intersection coordinates
165
+ //const intersectX1 = Math.max(rect1.x, rect2.x);
166
+ const intersectX1 = Math.max(rect1.x, rect2.x);
167
+ const intersectX2 = Math.min(rect1.x + rect1.width, rect2.x + rect2.width);
168
+
169
+ // Check for overlap and calculate area
170
+ if (intersectX1 >= intersectX2) {
171
+ return 0; // No overlap
172
+ } else {
173
+ const overlapHeight = intersectX2 - intersectX1;
174
+ return /*overlapWidth **/ overlapHeight;
175
+ }
176
+ }
177
+
178
+ const IntegrationView: React.FC<Props> = ({
179
+ data: processExecutionInput,
180
+ variant,
181
+ onTaskClick,
182
+ drawerOpen,
183
+ processTaskId: selectedProcessTaskId,
184
+ config: configInput,
185
+ onConfigChange,
186
+ onAdd,
187
+ canEdit,
188
+ }: Props) => {
189
+ const [processExecutionDetails, _setProcess] = useState<
190
+ ProcessExecutionDetails | undefined
191
+ >(processExecutionInput);
192
+
96
193
  const [nodes, setNodes, onNodesChange] = useNodesState<any>([]);
97
194
  const [edges, setEdges, onEdgesChange] = useEdgesState<any>([]);
98
- const { fitView } = useReactFlow();
195
+ const [zonesY, setZonesY] = useEdgesState<any>([]);
196
+ const [zonesX, setZonesX] = useEdgesState<any>([]);
197
+
198
+ const { setCenter, fitView } = useReactFlow();
99
199
 
100
200
  const onConnect = useCallback(() => {}, []);
101
201
  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
- );
202
+ (processInput: any) => {
203
+ let tasks;
204
+
205
+ if (variant == "process") {
206
+ tasks = processInput?.Processes[0]?.ProcessTasks?.map(
207
+ (processTask: ProcessTaskExport) => mapToCamelCase(processTask),
208
+ );
209
+ } else {
210
+ tasks = (processInput ?? processExecutionDetails)
211
+ ?.processTaskExecutions;
212
+ }
213
+
214
+ if (
215
+ (tasks && tasks.length > 0) ||
216
+ (processInput && processInput?.processTasks?.length > 0)
217
+ ) {
218
+ const width = calculateMaxWidth(
219
+ tasks as ProcessTask[] | ProcessTaskExecution[],
220
+ );
221
+
222
+ const mapped =
223
+ variant == "process"
224
+ ? mapProcessConfigToNodesAndEdges(
225
+ processInput,
226
+ width,
227
+ variant,
228
+ onAdd,
229
+ )
230
+ : mapProcessTasksToNodesAndEdges(
231
+ processInput ?? process,
232
+ width,
233
+ variant as "process" | "process-execution",
234
+ );
235
+
236
+ const opts = { ...elkOptions };
237
+ const ns = mapped.nodes;
238
+ const es = mapped.edges;
239
+
240
+ getLayoutedElements(ns, es, opts).then(
241
+ ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
242
+ setNodes(layoutedNodes);
243
+ setEdges(layoutedEdges);
244
+
245
+ const zonesY = _.uniqBy(
246
+ layoutedNodes.filter((n: any) => n.type === "task-node"),
247
+ "data.processTask.sort",
248
+ ).map((n: any) => ({
249
+ sort: n?.data?.processTask?.sort,
250
+ y: n.position.y,
251
+ height: n.height,
252
+ }));
253
+
254
+ setZonesY(zonesY);
255
+
256
+ const zonesX = _.uniqBy(
257
+ layoutedNodes.filter((n: any) => n.type === "group-node"),
258
+ "data.parallelProcessingGroup",
259
+ ).map((n: any) => ({
260
+ parallelProcessingGroup: n?.data?.parallelProcessingGroup,
261
+ x: n.position.x,
262
+ width: n.width,
263
+ }));
264
+
265
+ setZonesX(zonesX);
266
+
267
+ fitView();
268
+ },
269
+ );
270
+ } else if (
271
+ tasks?.length === 0 ||
272
+ (processInput && processInput?.processTasks?.length === 0)
273
+ ) {
274
+ const mapped = mapEmptyNodesAndEdges(processInput ?? process, 400);
275
+
276
+ const opts = { ...elkOptions };
277
+ const ns = mapped.nodes;
278
+ const es = mapped.edges;
279
+
280
+ getLayoutedElements(ns, es, opts).then(
281
+ ({ nodes: layoutedNodes, edges: layoutedEdges }: any) => {
282
+ setNodes(layoutedNodes);
283
+ setEdges(layoutedEdges);
284
+ fitView();
285
+ },
286
+ );
287
+ }
114
288
  },
115
289
  [nodes, edges],
116
290
  );
117
291
 
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
+ ) => {
303
+ if (!drawerOpen) {
304
+ if (onTaskClick) {
305
+ if (variant === "process") onTaskClick(node.data.processTask);
306
+ else if (variant === "process-execution")
307
+ onTaskClick(node.data.processTaskExecution);
308
+ }
309
+
310
+ setTimeout(() => {
311
+ let parentx = 0;
312
+ let parenty = 0;
313
+
314
+ if (node.parentId) {
315
+ const parentNode = nodes.find((n) => n.id === node.parentId);
316
+ if (parentNode) {
317
+ parentx = parentNode.position.x;
318
+ parenty = parentNode.position.y;
319
+ }
320
+ }
321
+
322
+ const centerX = parentx + node.position.x + node.width / 2;
323
+ const centerY = parenty + node.position.y + node.height / 2;
324
+
325
+ setCenter(centerX, centerY, { zoom: 1.2, duration: 800 });
326
+ }, 300);
327
+ }
328
+ };
329
+
118
330
  // Calculate the initial layout on mount.
119
331
  useLayoutEffect(() => {
120
- onLayout({ useInitialNodes: true });
121
- }, []);
332
+ onLayout(configInput ?? processExecutionInput);
333
+ }, [configInput, processExecutionInput]);
334
+
335
+ useLayoutEffect(() => {
336
+ let data = globalThis.structuredClone(nodes);
337
+
338
+ data = data.map((node: any) => {
339
+ return {
340
+ ...node,
341
+ data: {
342
+ ...node.data,
343
+ disabled: drawerOpen,
344
+ selected:
345
+ selectedProcessTaskId === node.data?.processTask?.id ||
346
+ selectedProcessTaskId === node.data?.processTaskExecution?.id,
347
+ },
348
+ };
349
+ });
350
+
351
+ setNodes(data);
352
+ }, [drawerOpen, selectedProcessTaskId]);
353
+
354
+ const handleNodeDragStart = (_e: ReactMouseEvent, node: Node): any => {
355
+ let edgesFiltered = [];
356
+
357
+ const edgeList: any[] = [];
358
+
359
+ let nodeIds: any[] = [];
360
+
361
+ edges.forEach((edge: any) => {
362
+ if (edge.source === node.id) {
363
+ nodeIds.push(edge.target);
364
+ }
365
+ if (edge.target === node.id) {
366
+ nodeIds.push(edge.source);
367
+ }
368
+ if (edge.source === node.id || edge.target === node.id) {
369
+ edgeList.push(edge);
370
+ }
371
+ });
372
+
373
+ nodeIds = _.uniq(nodeIds);
374
+
375
+ let edgeIds: any[] = [];
376
+
377
+ edgeList.forEach((edge: any) => {
378
+ edgeIds.push(edge.source, edge.target);
379
+ });
380
+
381
+ edgeIds = _.uniq(edgeIds);
382
+
383
+ edgesFiltered = edges.filter((edge: any) => {
384
+ return (
385
+ edgeIds.includes(edge.source) === false &&
386
+ edgeIds.includes(edge.target) === false
387
+ );
388
+ });
389
+
390
+ edgesFiltered = edgesFiltered.filter(
391
+ (edge: any) =>
392
+ !edge.id.includes((node?.data?.processTask as ProcessTask)?.id),
393
+ );
394
+
395
+ let nodesFiltered = nodes.filter(
396
+ (node: any) => !nodeIds.includes(node?.id),
397
+ );
398
+
399
+ setEdges(edgesFiltered);
400
+
401
+ setNodes(nodesFiltered);
402
+ };
403
+
404
+ const handleNodeDragEnd = (_e: ReactMouseEvent, node: Node): any => {
405
+ 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,
411
+ );
412
+
413
+ if (!zoneY) {
414
+ const maxZone = _.maxBy(zonesY, "y");
415
+ const minZone = _.minBy(zonesY, "y");
416
+
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;
443
+ }
444
+ }
445
+ }
446
+ }
447
+
448
+ const currentGroup = node?.parentId
449
+ ? nodes.find((n) => n.id === node?.parentId)
450
+ : null;
451
+
452
+ let zoneX: any;
453
+ let overlapX = 0;
454
+
455
+ for (let i = 0; i < zonesX.length; i++) {
456
+ const zone = zonesX[i];
457
+
458
+ const overlap = getOverlapX(
459
+ { x: zone.x, width: zone.width },
460
+ { x: currentGroup.x + node?.position?.x, width: node.width },
461
+ );
462
+
463
+ if (overlap > overlapX) {
464
+ overlapX = overlap;
465
+ zoneX = zone;
466
+ }
467
+ }
468
+
469
+ if (!zoneX) {
470
+ const maxZone = _.maxBy(zonesX, "x");
471
+ const minZone = _.minBy(zonesX, "x");
472
+
473
+ if (currentGroup.x + node?.position?.x + node?.width < minZone.x) {
474
+ zoneX = {
475
+ ...minZone,
476
+ parallelProcessingGroup: minZone.parallelProcessingGroup - 1,
477
+ };
478
+ } else if (
479
+ currentGroup.x + node?.position?.x >
480
+ maxZone.x + maxZone.width
481
+ ) {
482
+ zoneX = {
483
+ ...maxZone,
484
+ parallelProcessingGroup: maxZone.parallelProcessingGroup + 1,
485
+ };
486
+ } else {
487
+ const localZones = _.sortBy(zonesY, "y");
488
+
489
+ for (let i = 0; i < localZones.length - 1; i++) {
490
+ const currentZone = localZones[i];
491
+ const nextZone = localZones[i + 1];
492
+
493
+ if (
494
+ currentGroup.x + node?.position?.x > currentZone.x &&
495
+ currentGroup.x + node?.position?.x < nextZone.x + nextZone.width
496
+ ) {
497
+ zoneX = {
498
+ ...currentZone,
499
+ parallelProcessingGroup:
500
+ currentZone.parallelProcessingGroup + 0.5,
501
+ };
502
+ break;
503
+ }
504
+ }
505
+ }
506
+ }
507
+
508
+ if (!zoneY && !zoneX) {
509
+ onLayout(process);
510
+ return;
511
+ }
512
+
513
+ if (!configInput) {
514
+ throw new Error("configInput is required");
515
+ }
516
+
517
+ const modifiedProcess: ConfigExport =
518
+ globalThis.structuredClone(configInput);
519
+
520
+ let updatedTasks = modifiedProcess.Processes?.[0]?.ProcessTasks?.map(
521
+ (task) => {
522
+ if (task) {
523
+ if (
524
+ zoneX && (node?.data?.processTask as ProcessTask)?.id
525
+ ? task.ProcessTaskId ===
526
+ (node?.data?.processTask as ProcessTask)?.id
527
+ : task.Name === (node?.data?.processTask as ProcessTask)?.name
528
+ ) {
529
+ return {
530
+ ...task,
531
+ ParallelProcessingGroup: zoneX.parallelProcessingGroup,
532
+ };
533
+ }
534
+ }
535
+ return task;
536
+ },
537
+ );
538
+
539
+ updatedTasks = updatedTasks?.map((task) => {
540
+ if (task) {
541
+ if (
542
+ zoneY && (node?.data?.processTask as ProcessTask)?.id
543
+ ? task.ProcessTaskId ===
544
+ (node?.data?.processTask as ProcessTask)?.id
545
+ : task.Name === (node?.data?.processTask as ProcessTask)?.name
546
+ ) {
547
+ return {
548
+ ...task,
549
+ Sort: zoneY.sort,
550
+ };
551
+ }
552
+ }
553
+ return task;
554
+ });
555
+
556
+ let prevParallelProcessingGroup: any = null;
557
+ let index = 0;
558
+
559
+ updatedTasks = _.sortBy(updatedTasks, [
560
+ "ParallelProcessingGroup",
561
+ "Sort",
562
+ ])?.map((task) => {
563
+ if (task) {
564
+ if (task.ParallelProcessingGroup !== prevParallelProcessingGroup) {
565
+ prevParallelProcessingGroup = task.ParallelProcessingGroup;
566
+ index++;
567
+ }
568
+
569
+ task.ParallelProcessingGroup = index;
570
+ }
571
+
572
+ return task;
573
+ });
574
+
575
+ const partitionedTasks = _.values(
576
+ _.groupBy(updatedTasks, "ParallelProcessingGroup"),
577
+ );
578
+
579
+ let processTaskValue: any[] = [];
580
+
581
+ partitionedTasks.forEach((partition) => {
582
+ index = 0;
583
+ let prevSort: any = null;
584
+
585
+ const sortedPartition = _.sortBy(partition, ["Sort", "Name"]).map(
586
+ (task) => {
587
+ if (task) {
588
+ if (task.Sort !== prevSort) {
589
+ prevSort = task.Sort;
590
+ index++;
591
+ }
592
+
593
+ task.Sort = index;
594
+ }
595
+
596
+ return task;
597
+ },
598
+ );
599
+
600
+ processTaskValue = processTaskValue.concat(sortedPartition);
601
+ });
602
+
603
+ if (modifiedProcess?.Processes?.[0])
604
+ modifiedProcess.Processes[0].ProcessTasks = processTaskValue;
605
+
606
+ if (onConfigChange) onConfigChange(modifiedProcess);
607
+ };
122
608
 
123
609
  return (
124
610
  <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>
611
+ <Box sx={{ width: "100%", height: "100%" }}>
612
+ {/* <Box sx={{ width: "750px", height: "750px" }}> */}
613
+
614
+ <ReactFlow
615
+ nodes={nodes}
616
+ edges={edges}
617
+ nodeTypes={nodeTypes}
618
+ edgeTypes={edgeTypes}
619
+ onConnect={onConnect}
620
+ onNodesChange={onNodesChange}
621
+ onEdgesChange={onEdgesChange}
622
+ onNodeClick={handleNodeClick}
623
+ onNodeDragStart={handleNodeDragStart}
624
+ onNodeDragStop={handleNodeDragEnd}
625
+ fitView={true} // Fits the view on initial load
626
+ fitViewOptions={{
627
+ padding: 0.1,
628
+ includeHiddenNodes: false,
629
+ minZoom: 0.1,
630
+ maxZoom: 2,
631
+ duration: 200,
632
+ nodes: nodes, // nodes to fit
633
+ }} // Optional options for initial fit
634
+ nodesDraggable={canEdit}
635
+ minZoom={0.1} // Lock zoom to 1
636
+ maxZoom={2} // Lock zoom to 1
637
+ nodesConnectable={canEdit && !drawerOpen}
638
+ elementsSelectable={canEdit && !drawerOpen}
639
+ panOnDrag={!drawerOpen}
640
+ zoomOnScroll={!drawerOpen}
641
+ zoomOnDoubleClick={!drawerOpen}
642
+ >
643
+ <Background />
644
+ <Controls />
645
+ </ReactFlow>
646
+ </Box>
153
647
  </Box>
154
648
  );
155
649
  };
156
650
 
157
- export default () => (
651
+ const IntegrationViewWrapper = (props: Props): React.JSX.Element => (
158
652
  <ReactFlowProvider>
159
- <IntegrationView />
653
+ <IntegrationView
654
+ data={props.data}
655
+ variant={props.variant}
656
+ onTaskClick={props.onTaskClick}
657
+ drawerOpen={props.drawerOpen}
658
+ processTaskId={props.processTaskId}
659
+ config={props.config}
660
+ onConfigChange={props.onConfigChange}
661
+ onAdd={props.onAdd}
662
+ canEdit={props.canEdit}
663
+ />
160
664
  </ReactFlowProvider>
161
665
  );
666
+
667
+ export default IntegrationViewWrapper;
@@ -0,0 +1,20 @@
1
+ import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
2
+ import { IconButton, useTheme } from "@mui/material";
3
+
4
+ export function AddNode(): JSX.Element {
5
+ const theme = useTheme();
6
+
7
+ return (
8
+ <IconButton>
9
+ <AddCircleOutlineIcon
10
+ sx={{
11
+ color: "grey.600",
12
+ marginLeft: theme.spacing(1),
13
+ "&:hover": {
14
+ color: "#4E97FD", //Blue not implemented in the theme
15
+ },
16
+ }}
17
+ />
18
+ </IconButton>
19
+ );
20
+ }