@evenicanpm/admin-integrate 2.4.2 → 2.5.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 (46) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/package.json +9 -1
  3. package/src/api/process/mutations/copy-process.mutation.ts +3 -1
  4. package/src/api/process/mutations/index.ts +5 -2
  5. package/src/api/process/mutations/run-process.mutation.ts +3 -1
  6. package/src/api/process-config/mutation/index.ts +8 -2
  7. package/src/api/process-config/mutation/process-config-import.mutation.ts +3 -1
  8. package/src/api/process-config/mutation/process-config-merge.mutation.ts +3 -1
  9. package/src/api/scheduler/mutation/create-process-schedule-group-details.mutation.ts +4 -1
  10. package/src/api/scheduler/mutation/index.ts +8 -2
  11. package/src/api/scheduler/mutation/update-process-schedule-group-details.mutation.ts +4 -1
  12. package/src/components/data-table/table-header.tsx +32 -20
  13. package/src/components/integration-list/list/integration-list.tsx +1 -1
  14. package/src/components/integration-view/integration-view.tsx +163 -192
  15. package/src/components/integration-view/nodes/base-node.tsx +4 -2
  16. package/src/components/integration-view/nodes/task-node.tsx +3 -4
  17. package/src/components/integration-view/task-icon.tsx +12 -9
  18. package/src/components/integration-view/utils/mapping.ts +4 -6
  19. package/src/components/list-filter/list-filter.tsx +1 -1
  20. package/src/components/list-filter/multi-select-filter.tsx +9 -10
  21. package/src/components/list-filter/select-filter.tsx +6 -7
  22. package/src/components/scheduler/schedule-drawer/details-reducer.ts +2 -2
  23. package/src/components/scheduler/schedule-drawer/schedule-details-integrations.tsx +14 -25
  24. package/src/components/scheduler/schedule-drawer/schedule-details-main.tsx +2 -2
  25. package/src/components/scheduler/schedule-drawer/schedule-drawer-group.tsx +4 -4
  26. package/src/components/scheduler/schedule-drawer/schedule-drawer-legacy.tsx +1 -1
  27. package/src/components/templatesV2/inputs/FormikPageBody.tsx +2 -2
  28. package/src/components/templatesV2/inputs/primitives/SelectorInput.tsx +6 -7
  29. package/src/components/templatesV2/inputs/renderers/renderFormControl.tsx +6 -9
  30. package/src/components/templatesV2/inputs/table/InputTable.tsx +3 -4
  31. package/src/components/templatesV2/inputs/utils/parseQueryName.ts +2 -2
  32. package/src/components/templatesV2/inputs/utils/selectors.ts +1 -1
  33. package/src/components/templatesV2/pageForm.tsx +103 -33
  34. package/src/components/templatesV2/templates-list/templates-list.tsx +2 -2
  35. package/src/components/templatesV2/wizard.tsx +3 -4
  36. package/src/pages/execution-details/execution-details.tsx +4 -4
  37. package/src/pages/executions/executions-list/executions-list.tsx +1 -1
  38. package/src/pages/integration-create/integration-create.tsx +5 -8
  39. package/src/pages/integration-create/template-list-step.tsx +1 -2
  40. package/src/pages/integration-create/template-options-step.tsx +1 -1
  41. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +4 -4
  42. package/src/pages/integration-details/integration-details.tsx +66 -50
  43. package/src/pages/integration-details/task-drawer/add-task.tsx +7 -7
  44. package/src/pages/integration-details/task-drawer/edit-task.tsx +9 -9
  45. package/src/pages/scheduler/schedules-list/schedules-list-row.tsx +3 -3
  46. package/src/components/integration-view/types.ts +0 -14
@@ -104,7 +104,7 @@ const ExecutionsList: React.FC<Props> = (props: Props) => {
104
104
  ),
105
105
  });
106
106
  setFetched(false);
107
- setPerPage(itemsPerPage as number);
107
+ setPerPage(itemsPerPage || 10);
108
108
  setPage(1);
109
109
  };
110
110
 
@@ -1,11 +1,10 @@
1
1
  import type {
2
2
  ConfigExport,
3
3
  ConfigImport,
4
- ConfigurationMergeMutationVariables,
5
4
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
6
5
  import {
7
- processConfigImport,
8
- processConfigMerge,
6
+ useProcessConfigImport,
7
+ useProcessConfigMerge,
9
8
  } from "@evenicanpm/admin-integrate/api/process-config/mutation";
10
9
  import {
11
10
  type Crumb,
@@ -36,8 +35,8 @@ export default function IntegrationCreate() {
36
35
  const router = useRouter();
37
36
  const searchParams = useSearchParams();
38
37
  const pathname = usePathname();
39
- const processConfigMergeMutation = processConfigMerge();
40
- const processConfigImportMutation = processConfigImport();
38
+ const processConfigMergeMutation = useProcessConfigMerge();
39
+ const processConfigImportMutation = useProcessConfigImport();
41
40
 
42
41
  const breadcrumbs: Crumb[] = [
43
42
  {
@@ -116,9 +115,7 @@ export default function IntegrationCreate() {
116
115
 
117
116
  processConfigMergeMutation.mutate(
118
117
  {
119
- input:
120
- removeTemplateConfig(newProcessConfigMerge?.input) ||
121
- ({} as ConfigurationMergeMutationVariables),
118
+ input: removeTemplateConfig(newProcessConfigMerge?.input) || {},
122
119
  },
123
120
  {
124
121
  onSuccess: ({ configurationMerge }) => {
@@ -17,12 +17,11 @@ export enum DirectionType {
17
17
 
18
18
  interface Props {
19
19
  listStepTitle?: string;
20
- directionType?: DirectionType;
21
20
  /** When set, skips default `group` URL handoff (e.g. source pick in dual flow). */
22
21
  onSelectTemplate?: (id: string) => void;
23
22
  }
24
23
 
25
- export default function TemplateListStep(props?: Props) {
24
+ export default function TemplateListStep(props?: Readonly<Props>) {
26
25
  const t = useTranslations("Integrate.Templates");
27
26
 
28
27
  const router = useRouter();
@@ -19,7 +19,7 @@ interface Props {
19
19
  onSourceAndTarget?: () => void;
20
20
  }
21
21
 
22
- export default function TemplateOptionsStep(props: Props) {
22
+ export default function TemplateOptionsStep(props: Readonly<Props>) {
23
23
  const t = useTranslations("Integrate.Templates");
24
24
  const theme = useTheme();
25
25
  const styles = getStyles(theme);
@@ -3,7 +3,7 @@ import type {
3
3
  ProcessTask,
4
4
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
5
5
  import { getQueryClient } from "@evenicanpm/admin-core/api/sdk/get-query-client";
6
- import { copyProcess } from "@evenicanpm/admin-integrate/api/process/mutations";
6
+ import { useCopyProcess } from "@evenicanpm/admin-integrate/api/process/mutations";
7
7
  import { buildProcessByIdQueryKey } from "@evenicanpm/admin-integrate/api/process/queries/get-process-by-id.query";
8
8
  import {
9
9
  TableHeader,
@@ -102,14 +102,14 @@ export default function CopyTasksList(props: Readonly<Props>) {
102
102
  setChecked(newChecked);
103
103
  };
104
104
 
105
- const copy = copyProcess();
105
+ const copy = useCopyProcess();
106
106
 
107
107
  const handleConfirm = () => {
108
108
  if (props.data?.processById && checked) {
109
109
  const idsToCopy: string[] = [];
110
110
  for (const id of Object.keys(checked)) {
111
111
  if (checked[id]) {
112
- idsToCopy.push(id as string);
112
+ idsToCopy.push(id);
113
113
  }
114
114
  }
115
115
 
@@ -162,7 +162,7 @@ export default function CopyTasksList(props: Readonly<Props>) {
162
162
  {!props.loading && props.data?.processById?.processTasks && (
163
163
  <Box>
164
164
  <Typography sx={styles.name} variant="h6">
165
- {props.data.processById.name as string}
165
+ {props.data.processById.name}
166
166
  </Typography>
167
167
  <Card>
168
168
  {props.data.processById.processTasks.length > 0 && checked && (
@@ -24,7 +24,7 @@ import { useTranslations } from "next-intl";
24
24
  import { useEffect, useReducer, useState } from "react";
25
25
  import { configurationExport } from "../../api/configuration/queries";
26
26
  import { buildConfigurationExportQueryKey } from "../../api/configuration/queries/configuration-export.query";
27
- import { processConfigImport } from "../../api/process-config/mutation";
27
+ import { useProcessConfigImport } from "../../api/process-config/mutation";
28
28
  import ImportDrawer from "./import-process/import-drawer";
29
29
  import {
30
30
  ImportActionType,
@@ -38,64 +38,82 @@ import {
38
38
  taskReducer,
39
39
  } from "./task-drawer/task-reducer";
40
40
 
41
- function mergeByKey<T>(
42
- keyFields: string | string[],
43
- arr1: T[] = [],
44
- arr2: T[] = [],
45
- ): T[] {
46
- const keys = Array.isArray(keyFields) ? keyFields : [keyFields];
41
+ type ItemRecord = Record<string, unknown> | null | undefined;
42
+
43
+ const MERGE_EXCLUDED_PROPS = new Set(["Sort", "ParallelProcessingGroup"]);
47
44
 
48
- // Build lookup maps for each key -> value => baseItem (from arr1)
45
+ function getItemVal(item: unknown, key: string): unknown {
46
+ return (item as ItemRecord)?.[key];
47
+ }
48
+
49
+ function registerInLookups<T>(
50
+ item: T,
51
+ keys: string[],
52
+ lookupByKey: Record<string, Map<unknown, T>>,
53
+ ): void {
54
+ for (const key of keys) {
55
+ const val = getItemVal(item, key);
56
+ if (val !== undefined && val !== null) {
57
+ lookupByKey[key].set(val, item);
58
+ }
59
+ }
60
+ }
61
+
62
+ function buildLookupMaps<T>(
63
+ keys: string[],
64
+ arr: T[],
65
+ ): Record<string, Map<unknown, T>> {
49
66
  const lookupByKey: Record<string, Map<unknown, T>> = {};
50
67
  for (const k of keys) {
51
68
  lookupByKey[k] = new Map();
52
69
  }
70
+ for (const item of arr) {
71
+ registerInLookups(item, keys, lookupByKey);
72
+ }
73
+ return lookupByKey;
74
+ }
53
75
 
54
- for (const item of arr1) {
55
- for (const key of keys) {
56
- const val = (item as Record<string, unknown> | null | undefined)?.[key];
57
- if (val !== undefined && val !== null) {
58
- lookupByKey[key].set(val, item);
59
- }
76
+ function findMatchByKeys<T>(
77
+ item: T,
78
+ keys: string[],
79
+ lookupByKey: Record<string, Map<unknown, T>>,
80
+ ): T | undefined {
81
+ for (const key of keys) {
82
+ const val = getItemVal(item, key);
83
+ if (val !== undefined && val !== null) {
84
+ const candidate = lookupByKey[key].get(val);
85
+ if (candidate !== undefined) return candidate;
60
86
  }
61
87
  }
88
+ return undefined;
89
+ }
62
90
 
63
- // Use a Set to preserve insertion order and ensure uniqueness
91
+ function mergeItemProps<T>(base: T, source: T): void {
92
+ const sourceRecord = source as ItemRecord;
93
+ for (const prop of Object.keys(sourceRecord ?? {})) {
94
+ if (!MERGE_EXCLUDED_PROPS.has(prop)) {
95
+ (base as Record<string, unknown>)[prop] = sourceRecord?.[prop];
96
+ }
97
+ }
98
+ }
99
+
100
+ function mergeByKey<T>(
101
+ keyFields: string | string[],
102
+ arr1: T[] = [],
103
+ arr2: T[] = [],
104
+ ): T[] {
105
+ const keys = Array.isArray(keyFields) ? keyFields : [keyFields];
106
+ const lookupByKey = buildLookupMaps(keys, arr1);
64
107
  const resultSet = new Set<T>(arr1);
65
108
 
66
109
  for (const item of arr2) {
67
- let matchedBase: T | undefined;
68
-
69
- // Try keys in order of priority
70
- for (const key of keys) {
71
- const val = (item as Record<string, unknown> | null | undefined)?.[key];
72
- if (val !== undefined && val !== null) {
73
- const candidate = lookupByKey[key].get(val);
74
- if (candidate !== undefined) {
75
- matchedBase = candidate;
76
- break;
77
- }
78
- }
79
- }
110
+ const matchedBase = findMatchByKeys(item, keys, lookupByKey);
80
111
 
81
- if (matchedBase !== undefined) {
82
- // Merge properties from item into matched base (respecting exclusions)
83
- const itemRecord = item as Record<string, unknown> | null | undefined;
84
- for (const prop of Object.keys(itemRecord ?? {})) {
85
- if (prop !== "Sort" && prop !== "ParallelProcessingGroup") {
86
- (matchedBase as Record<string, unknown>)[prop] = itemRecord?.[prop];
87
- }
88
- }
89
- } else {
90
- // No match found by any tiered key -> add as new
112
+ if (matchedBase === undefined) {
91
113
  resultSet.add(item);
92
- // Register the newly added item in lookups so subsequent arr2 items can match it
93
- for (const key of keys) {
94
- const val = (item as Record<string, unknown> | null | undefined)?.[key];
95
- if (val !== undefined && val !== null) {
96
- lookupByKey[key].set(val, item);
97
- }
98
- }
114
+ registerInLookups(item, keys, lookupByKey);
115
+ } else {
116
+ mergeItemProps(matchedBase, item);
99
117
  }
100
118
  }
101
119
 
@@ -225,7 +243,7 @@ export default function IntegrationDetails() {
225
243
  setConfig(configData);
226
244
  };
227
245
 
228
- const processConfigImportMutation = processConfigImport();
246
+ const processConfigImportMutation = useProcessConfigImport();
229
247
 
230
248
  const handleProcessConfigImport = () => {
231
249
  if (config) {
@@ -249,11 +267,10 @@ export default function IntegrationDetails() {
249
267
  const details = data as GetProcessByIdQuery | undefined;
250
268
 
251
269
  useEffect(() => {
252
- const typedData = details as GetProcessByIdQuery;
253
- if (typedData?.processById) {
270
+ if (details?.processById) {
254
271
  if (breadcrumbs.length === 2) {
255
272
  const newCrumbs: Crumb[] = structuredClone(breadcrumbs);
256
- newCrumbs.push({ name: typedData.processById.name as string });
273
+ newCrumbs.push({ name: details.processById.name as string });
257
274
  setBreadcrumbs(newCrumbs);
258
275
  }
259
276
  }
@@ -398,7 +415,6 @@ export default function IntegrationDetails() {
398
415
  <IntegrationView
399
416
  canEdit
400
417
  key={viewRefreshKey}
401
- //data={(data as GetProcessByIdQuery)?.processById as Process}
402
418
  config={
403
419
  config ||
404
420
  ((configFromApi as ConfigurationExportQuery)
@@ -5,7 +5,7 @@ import type {
5
5
  FilterQueryInput,
6
6
  GetProcessTemplatesQuery,
7
7
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
8
- import { processConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
8
+ import { useProcessConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
9
9
  import { getProcessTemplates } from "@evenicanpm/admin-integrate/api/templates/queries";
10
10
  import type { Head } from "@evenicanpm/admin-integrate/components/data-table/table-header";
11
11
  import { Wizard } from "@evenicanpm/admin-integrate/components/templatesV2";
@@ -37,7 +37,7 @@ export default function AddTask(props: Readonly<Props>) {
37
37
  const t = useTranslations("Integrate");
38
38
  const theme = useTheme();
39
39
 
40
- const processConfigMergeMutation = processConfigMerge();
40
+ const processConfigMergeMutation = useProcessConfigMerge();
41
41
 
42
42
  const heading: Head[] = [
43
43
  {
@@ -55,13 +55,13 @@ export default function AddTask(props: Readonly<Props>) {
55
55
  },
56
56
  ];
57
57
 
58
- const [processConfigMergeInput, setProcessConfigMergeInput] =
58
+ const [useProcessConfigMergeInput, setProcessConfigMergeInput] =
59
59
  useState<ProcessConfigMerge | null>(null);
60
60
 
61
61
  useEffect(() => {
62
- if (processConfigMergeInput) {
62
+ if (useProcessConfigMergeInput) {
63
63
  const input =
64
- removeTemplateConfig(processConfigMergeInput?.input) ||
64
+ removeTemplateConfig(useProcessConfigMergeInput?.input) ||
65
65
  ({} as ConfigurationMergeMutationVariables);
66
66
  processConfigMergeMutation.mutate(
67
67
  {
@@ -90,7 +90,7 @@ export default function AddTask(props: Readonly<Props>) {
90
90
  },
91
91
  );
92
92
  }
93
- }, [processConfigMergeInput]);
93
+ }, [useProcessConfigMergeInput]);
94
94
 
95
95
  const [processTemplateId, setProcessTemplateId] = useState<string | null>(
96
96
  null,
@@ -163,7 +163,7 @@ export default function AddTask(props: Readonly<Props>) {
163
163
  />
164
164
  )}
165
165
  {props.taskState.step === 2 && (
166
- <Typography>{JSON.stringify(processConfigMerge)}</Typography>
166
+ <Typography>{JSON.stringify(useProcessConfigMerge)}</Typography>
167
167
  )}
168
168
  </>
169
169
  );
@@ -3,7 +3,7 @@ import type {
3
3
  ConfigurationMergeMutation,
4
4
  ConfigurationMergeMutationVariables,
5
5
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
6
- import { processConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
6
+ import { useProcessConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
7
7
  import { TitleEdit } from "@evenicanpm/admin-integrate/components/core";
8
8
  import { Wizard } from "@evenicanpm/admin-integrate/components/templatesV2";
9
9
  import type {
@@ -31,15 +31,15 @@ interface Props {
31
31
  dispatch: React.Dispatch<TaskAction>;
32
32
  handleUpdateConfig: (newConfig: ConfigExport) => void;
33
33
  editable?: boolean;
34
- templateConfigInput?: unknown | null;
34
+ templateConfigInput?: unknown;
35
35
  }
36
36
 
37
37
  export default function EditTask(props: Readonly<Props>) {
38
38
  const theme = useTheme();
39
39
 
40
- const processConfigMergeMutation = processConfigMerge();
40
+ const processConfigMergeMutation = useProcessConfigMerge();
41
41
 
42
- const [processConfigMergeInput, setProcessConfigMergeInput] =
42
+ const [useProcessConfigMergeInput, setProcessConfigMergeInput] =
43
43
  useState<ProcessConfigMerge | null>(null);
44
44
 
45
45
  const handleFinish = () => {
@@ -51,7 +51,7 @@ export default function EditTask(props: Readonly<Props>) {
51
51
  props.dispatch(action);
52
52
  };
53
53
 
54
- const [_name, setName] = useState<string>("");
54
+ const [, setName] = useState<string>("");
55
55
  const [sharedCount, setSharedCount] = useState<number>();
56
56
 
57
57
  const handleNameEdit = (input: string) => {
@@ -62,9 +62,9 @@ export default function EditTask(props: Readonly<Props>) {
62
62
  };
63
63
 
64
64
  useEffect(() => {
65
- if (processConfigMergeInput) {
65
+ if (useProcessConfigMergeInput) {
66
66
  const input =
67
- removeTemplateConfig(processConfigMergeInput?.input) ||
67
+ removeTemplateConfig(useProcessConfigMergeInput?.input) ||
68
68
  ({} as ConfigurationMergeMutationVariables);
69
69
  processConfigMergeMutation.mutate(
70
70
  {
@@ -80,7 +80,7 @@ export default function EditTask(props: Readonly<Props>) {
80
80
  },
81
81
  );
82
82
  }
83
- }, [processConfigMergeInput]);
83
+ }, [useProcessConfigMergeInput]);
84
84
 
85
85
  return (
86
86
  <>
@@ -153,7 +153,7 @@ export default function EditTask(props: Readonly<Props>) {
153
153
  />
154
154
  )}
155
155
  {props.taskState.step === 1 && (
156
- // <Typography>{JSON.stringify(processConfigMergeInput)}</Typography>
156
+ // <Typography>{JSON.stringify(useProcessConfigMergeInput)}</Typography>
157
157
  <CircularProgress sx={{ margin: theme.spacing(10, 0) }} />
158
158
  )}
159
159
  </>
@@ -52,7 +52,7 @@ const SchedulesListRow: React.FC<Props> = (props: Props) => {
52
52
  null,
53
53
  );
54
54
  const modifiedOpen = Boolean(modifiedAnchorEl);
55
- const [startDateAnchorEl, setStartDateAnchorlEl] =
55
+ const [startDateAnchorEl, setStartDateAnchorEl] =
56
56
  useState<HTMLElement | null>(null);
57
57
  const startDateOpen = Boolean(startDateAnchorEl);
58
58
 
@@ -61,13 +61,13 @@ const SchedulesListRow: React.FC<Props> = (props: Props) => {
61
61
  if (classList.contains("scheduled-process-modified")) {
62
62
  setModifiedAnchorEl(event.currentTarget);
63
63
  } else if (classList.contains("scheduled-process-start-date")) {
64
- setStartDateAnchorlEl(event.currentTarget);
64
+ setStartDateAnchorEl(event.currentTarget);
65
65
  }
66
66
  };
67
67
 
68
68
  const handlePopoverClose = () => {
69
69
  setModifiedAnchorEl(null);
70
- setStartDateAnchorlEl(null);
70
+ setStartDateAnchorEl(null);
71
71
  };
72
72
 
73
73
  const handleMenuOpen = () => {
@@ -1,14 +0,0 @@
1
- /*
2
- type ElkOptions = {};
3
-
4
- type ElkPosition = {};
5
-
6
- interface ElkItem {
7
- id: string;
8
- type: "input";
9
- data: { label: string };
10
- x: number;
11
- y: number;
12
- layoutOptions: ElkOptions;
13
- }
14
- */