@evenicanpm/admin-integrate 2.4.1 → 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 +8 -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
@@ -28,8 +28,10 @@ BaseNodeHeader.displayName = "BaseNodeHeader";
28
28
  export const BaseNodeHeaderTitle = forwardRef<
29
29
  HTMLHeadingElement,
30
30
  HTMLAttributes<HTMLHeadingElement>
31
- >(({ className, ...props }, ref) => (
32
- <h3 ref={ref} data-slot="base-node-title" {...props} />
31
+ >(({ className, children, ...props }, ref) => (
32
+ <h3 ref={ref} data-slot="base-node-title" {...props}>
33
+ {children}
34
+ </h3>
33
35
  ));
34
36
  BaseNodeHeaderTitle.displayName = "BaseNodeHeaderTitle";
35
37
 
@@ -50,13 +50,13 @@ export function TaskNode(props: NodeProps): React.ReactElement {
50
50
  >
51
51
  {mapIconByOrchestrationType(
52
52
  (props?.data?.processTask as ProcessTask)?.orchestrationType
53
- ?.code as string,
53
+ ?.code ?? undefined,
54
54
  )}
55
55
  <Typography
56
56
  variant="h6"
57
57
  sx={{ textAlign: "center", paddingLeft: theme.spacing(1) }}
58
58
  >
59
- {(props?.data?.processTask as ProcessTask)?.name as string}
59
+ {(props?.data?.processTask as ProcessTask)?.name}
60
60
  </Typography>
61
61
  </CardContent>
62
62
  <Handle type="target" position={Position.Top} />
@@ -71,8 +71,7 @@ export function TaskNode(props: NodeProps): React.ReactElement {
71
71
  document.dispatchEvent(
72
72
  new CustomEvent("addItem", {
73
73
  detail: {
74
- sort: (props?.data?.processTask as ProcessTask)
75
- ?.sort as number,
74
+ sort: (props?.data?.processTask as ProcessTask)?.sort,
76
75
  paralellelProcessingGroup: (
77
76
  props?.data?.processTask as ProcessTask
78
77
  )?.parallelProcessingGroup,
@@ -31,6 +31,17 @@ export const mapIconByOrchestrationType = (code: string | undefined) => {
31
31
  return inputIcon();
32
32
  }
33
33
 
34
+ const icon =
35
+ code === "PubSubPush" ? (
36
+ <FileUploadIcon sx={{ color: dark }} />
37
+ ) : code === "PubSubPull" ? (
38
+ <DownloadIcon sx={{ color: dark }} />
39
+ ) : code === "SQLProcess" ? (
40
+ <StorageIcon sx={{ color: dark }} />
41
+ ) : code === "ExportStaged" ? (
42
+ <IosShareIcon sx={{ color: dark }} />
43
+ ) : null;
44
+
34
45
  return (
35
46
  <Box
36
47
  sx={{
@@ -45,15 +56,7 @@ export const mapIconByOrchestrationType = (code: string | undefined) => {
45
56
  padding: "2px",
46
57
  }}
47
58
  >
48
- {code === "PubSubPush" ? (
49
- <FileUploadIcon sx={{ color: dark }} />
50
- ) : code === "PubSubPull" ? (
51
- <DownloadIcon sx={{ color: dark }} />
52
- ) : code === "SQLProcess" ? (
53
- <StorageIcon sx={{ color: dark }} />
54
- ) : code === "ExportStaged" ? (
55
- <IosShareIcon sx={{ color: dark }} />
56
- ) : null}
59
+ {icon}
57
60
  </Box>
58
61
  );
59
62
  };
@@ -4,7 +4,6 @@ import type {
4
4
  ConfigExport,
5
5
  Process,
6
6
  ProcessExecutionDetails,
7
- ProcessExport,
8
7
  ProcessTask,
9
8
  ProcessTaskExecution,
10
9
  ProcessTaskExport,
@@ -31,7 +30,6 @@ type BuildNodeMapper = (
31
30
  partitionLen: number,
32
31
  parentId: string,
33
32
  ) => ElkNodeWithFlow;
34
- export type AddHandler = unknown;
35
33
  const asIdentifierString = (value: unknown) =>
36
34
  typeof value === "string" || typeof value === "number" ? String(value) : "";
37
35
 
@@ -159,7 +157,7 @@ function buildGroupsAndEdges({
159
157
  getGroupTasks: BuildGroupsTask;
160
158
  // nodeWidth: number,
161
159
  variant: "process" | "process-execution";
162
- onAdd?: AddHandler;
160
+ onAdd?: unknown;
163
161
  mapTaskToNode: BuildNodeMapper;
164
162
  groupSortKey: string;
165
163
  taskIdKey: string;
@@ -259,9 +257,9 @@ export const mapProcessConfigToNodesAndEdges = (
259
257
  data: ConfigExport,
260
258
  nodeWidth: number,
261
259
  variant: "process" | "process-execution",
262
- onAdd?: AddHandler,
260
+ onAdd?: unknown,
263
261
  ) => {
264
- const process = data.Processes?.[0] as ProcessExport;
262
+ const process = data.Processes?.[0];
265
263
  const entryPoint: ElkNodeWithFlow = {
266
264
  id: "entry-point",
267
265
  type: "entry-node",
@@ -312,7 +310,7 @@ export const mapProcessConfigToNodesAndEdges = (
312
310
  ) => ({
313
311
  id: `task-${asIdentifierString(task.ProcessTaskId ?? task.Name)}`,
314
312
  data: {
315
- processTask: mapToCamelCase(task as ProcessTaskExport) || undefined,
313
+ processTask: mapToCamelCase(task) || undefined,
316
314
  label: task?.Name as string,
317
315
  isLast: onAdd ? index === partitionLen - 1 : false,
318
316
  },
@@ -359,7 +359,7 @@ const ListFilter = function ListFilter<FilterShape extends Filters>(
359
359
  onChange={(e) => handlePerPageUpdate(e.target.value as number)}
360
360
  >
361
361
  {pageOptions.map((option) => (
362
- <MenuItem value={option}>
362
+ <MenuItem key={option} value={option}>
363
363
  {option} {t("itemsPerPage")}
364
364
  </MenuItem>
365
365
  ))}
@@ -30,16 +30,15 @@ const MultiSelectFilterComponent: React.FC<FilterProps<MultiSelectFilter>> = ({
30
30
 
31
31
  const t = useTranslations("Integrate");
32
32
 
33
- const mappedOptionDictionary = filter.options.reduce(
34
- (dictionary, option) => {
35
- dictionary[option.id] = {
36
- id: option.id,
37
- value: t(option.value),
38
- };
39
- return dictionary;
40
- },
41
- {} as { [id: string | number]: FilterOption },
42
- );
33
+ const mappedOptionDictionary = filter.options.reduce<
34
+ Record<string | number, FilterOption>
35
+ >((dictionary, option) => {
36
+ dictionary[option.id] = {
37
+ id: option.id,
38
+ value: t(option.value),
39
+ };
40
+ return dictionary;
41
+ }, {});
43
42
 
44
43
  const [value, setValue] = useState(current);
45
44
 
@@ -30,13 +30,12 @@ const SelectFilterComponent: React.FC<FilterProps<SelectFilter>> = ({
30
30
 
31
31
  const [value, setValue] = useState(current);
32
32
 
33
- const mappedOptionDictionary = filter.options.reduce(
34
- (dictionary: { [id: string | number]: FilterOption }, option) => {
35
- dictionary[option.id] = option;
36
- return dictionary;
37
- },
38
- {} as { [id: string | number]: FilterOption },
39
- );
33
+ const mappedOptionDictionary = filter.options.reduce<
34
+ Record<string | number, FilterOption>
35
+ >((dictionary, option) => {
36
+ dictionary[option.id] = option;
37
+ return dictionary;
38
+ }, {});
40
39
 
41
40
  const updateValue = (optionId: string | number | null) => {
42
41
  if (optionId == null) {
@@ -85,7 +85,7 @@ export function detailsReducer(
85
85
  ...state,
86
86
  details,
87
87
  errors: {
88
- name: !details.name || details.name === "",
88
+ name: !details.name,
89
89
  startDate: !details.startDate,
90
90
  interval: !details.interval,
91
91
  processes: !details.processes || details.processes.length === 0,
@@ -107,7 +107,7 @@ export function detailsReducer(
107
107
  ...state,
108
108
  details: blankState,
109
109
  errors: {
110
- name: !blankState.name || blankState.name === "",
110
+ name: !blankState.name,
111
111
  processes: !blankState.processes || blankState.processes.length === 0,
112
112
  },
113
113
  };
@@ -110,6 +110,12 @@ export default function ScheduleDetailsIntegrations(props: Readonly<Props>) {
110
110
  }),
111
111
  );
112
112
 
113
+ const markIntegrationsEdited = () => {
114
+ if (!props.edited.integrations) {
115
+ props.setEdited({ ...props.edited, integrations: true });
116
+ }
117
+ };
118
+
113
119
  // Drag and drop
114
120
  function handleDragEnd(event: DragEndEvent) {
115
121
  if (props.dispatchDetails && props.details.processes) {
@@ -128,12 +134,7 @@ export default function ScheduleDetailsIntegrations(props: Readonly<Props>) {
128
134
  };
129
135
  props.dispatchDetails(action);
130
136
 
131
- if (!props.edited.integrations) {
132
- props.setEdited({
133
- ...props.edited,
134
- integrations: true,
135
- });
136
- }
137
+ markIntegrationsEdited();
137
138
  }
138
139
  }
139
140
  }
@@ -198,12 +199,7 @@ export default function ScheduleDetailsIntegrations(props: Readonly<Props>) {
198
199
  (props.details.processes ? props.details.processes.length : 0) + 1,
199
200
  };
200
201
 
201
- if (!props.edited.integrations) {
202
- props.setEdited({
203
- ...props.edited,
204
- integrations: true,
205
- });
206
- }
202
+ markIntegrationsEdited();
207
203
 
208
204
  const newProcesses = [...(props.details.processes || []), updatedItem];
209
205
  const action: EditIntegrationsAction = {
@@ -225,12 +221,7 @@ export default function ScheduleDetailsIntegrations(props: Readonly<Props>) {
225
221
 
226
222
  const handleDeleteIntegration = (item: Process) => {
227
223
  if (props.dispatchDetails && props.details.processes) {
228
- if (!props.edited.integrations) {
229
- props.setEdited({
230
- ...props.edited,
231
- integrations: true,
232
- });
233
- }
224
+ markIntegrationsEdited();
234
225
 
235
226
  const newProcesses = props.details.processes.filter(
236
227
  (process) => process.id !== item.id,
@@ -241,13 +232,11 @@ export default function ScheduleDetailsIntegrations(props: Readonly<Props>) {
241
232
  };
242
233
  props.dispatchDetails(action);
243
234
 
244
- if (newProcesses.length === 0) {
245
- const clearErrorAction: SetErrorsAction = {
246
- type: DetailsActionType.SET_ERRORS,
247
- errors: { processes: true },
248
- };
249
- props.dispatchDetails(clearErrorAction);
250
- }
235
+ const clearErrorAction: SetErrorsAction = {
236
+ type: DetailsActionType.SET_ERRORS,
237
+ errors: { processes: newProcesses.length === 0 },
238
+ };
239
+ props.dispatchDetails(clearErrorAction);
251
240
  }
252
241
  };
253
242
 
@@ -275,7 +275,7 @@ export default function ScheduleDetailsMain(props: Readonly<Props>) {
275
275
  </Stack>
276
276
  <Stack direction="row" spacing={1} alignItems="flex-start">
277
277
  <TextField
278
- value={props.details?.interval as number}
278
+ value={props.details?.interval}
279
279
  onChange={handleIntervalChange}
280
280
  error={props.errors?.interval}
281
281
  helperText={props.errors?.interval ? t("invalidInterval") : ""}
@@ -290,7 +290,7 @@ export default function ScheduleDetailsMain(props: Readonly<Props>) {
290
290
  disabled={props.readOnly}
291
291
  />
292
292
  <Select
293
- value={props.details?.intervalUnitId as string}
293
+ value={props.details?.intervalUnitId ?? undefined}
294
294
  onChange={handleIntervalUnitChange}
295
295
  sx={styles.recurrenceUnit}
296
296
  disabled={props.readOnly}
@@ -4,8 +4,8 @@ import type {
4
4
  ProcessScheduleGroupDetailsUpdate,
5
5
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
6
6
  import {
7
- createProcessScheduleGroupDetails,
8
- updateProcessScheduleGroupDetails,
7
+ useCreateProcessScheduleGroupDetails,
8
+ useUpdateProcessScheduleGroupDetails,
9
9
  } from "@evenicanpm/admin-integrate/api/scheduler/mutation";
10
10
  import { getProcessScheduleGroupDetails } from "@evenicanpm/admin-integrate/api/scheduler/queries";
11
11
  import { DrawerButtons } from "@evenicanpm/admin-integrate/components/core";
@@ -74,8 +74,8 @@ export default function ScheduleDrawerGroup(props: Readonly<Props>) {
74
74
  }
75
75
  }, []);
76
76
 
77
- const updateMutation = updateProcessScheduleGroupDetails();
78
- const createMutation = createProcessScheduleGroupDetails();
77
+ const updateMutation = useUpdateProcessScheduleGroupDetails();
78
+ const createMutation = useCreateProcessScheduleGroupDetails();
79
79
 
80
80
  const handleSave = () => {
81
81
  if (props.detailsState?.details?.processes) {
@@ -31,7 +31,7 @@ export default function ScheduleDrawerLegacy(props: Readonly<Props>) {
31
31
  if (typedData.processScheduleById) {
32
32
  const fetchedDetails = typedData.processScheduleById;
33
33
 
34
- props.setDetails(fetchedDetails as ProcessScheduleById);
34
+ props.setDetails(fetchedDetails);
35
35
  } else {
36
36
  props.setDetails(null);
37
37
  }
@@ -29,9 +29,9 @@ function isHiddenInput(input: ProcessTemplateInput | null): boolean {
29
29
  function getDefaultHiddenFieldValue(
30
30
  input: ProcessTemplateInput | null,
31
31
  ): FieldValue {
32
- if (input?.inputType === InputType.HIDDEN_NUMBER) return 0 as FieldValue;
32
+ if (input?.inputType === InputType.HIDDEN_NUMBER) return 0;
33
33
  if (input?.inputType === InputType.HIDDEN_NUMBER_OR_NULL) return null;
34
- return "" as FieldValue;
34
+ return "";
35
35
  }
36
36
 
37
37
  export function FormikPageBody({
@@ -75,15 +75,14 @@ export function SelectorInput({
75
75
  disablePortal={insideTable}
76
76
  options={opts}
77
77
  getOptionLabel={getOptionLabel}
78
- isOptionEqualToValue={(opt, v) =>
79
- v == null
80
- ? false
81
- : opt === v ||
82
- optionEquals(opt, typeof v === "string" ? v : getOptionValue(v))
83
- }
78
+ isOptionEqualToValue={(opt, v) => {
79
+ if (v == null) return false;
80
+ const vValue = typeof v === "string" ? v : getOptionValue(v);
81
+ return opt === v || optionEquals(opt, vValue);
82
+ }}
84
83
  freeSolo={allowFreeText}
85
84
  value={selectedOption ?? null}
86
- onChange={(_e, val) => setValue(val != null ? getOptionValue(val) : "")}
85
+ onChange={(_e, val) => setValue(val == null ? "" : getOptionValue(val))}
87
86
  onInputChange={(_e, val) => setValue(val)}
88
87
  disabled={disabled ?? readOnly}
89
88
  renderInput={(params) => (
@@ -8,7 +8,6 @@ import type {
8
8
  FieldValue,
9
9
  FormState,
10
10
  ProcessTemplateInput,
11
- ProcessTemplateInputSchema,
12
11
  } from "../../types";
13
12
  import { templateFieldKey } from "../../types";
14
13
  import { InputType } from "../input-type";
@@ -25,6 +24,8 @@ import {
25
24
  } from "../utils/selectors";
26
25
  import { renderSearchInput } from "./renderSearchInput";
27
26
 
27
+ type RowValue = string | number | boolean | null | undefined;
28
+
28
29
  const QUERY_NAME_INPUT_TYPES = [
29
30
  InputType.TEXT,
30
31
  InputType.TEXT_UNIQUE_IDENTIFIER,
@@ -76,13 +77,9 @@ function queryInputType(
76
77
  function normalizeInputTableRows(
77
78
  value: unknown,
78
79
  input: ProcessTemplateInput,
79
- ): Array<Record<string, string | number | boolean | null | undefined>> {
80
- const rows: Array<
81
- Record<string, string | number | boolean | null | undefined>
82
- > = Array.isArray(value)
83
- ? (value as Array<
84
- Record<string, string | number | boolean | null | undefined>
85
- >)
80
+ ): Array<Record<string, RowValue>> {
81
+ const rows: Array<Record<string, RowValue>> = Array.isArray(value)
82
+ ? (value as Array<Record<string, RowValue>>)
86
83
  : [];
87
84
  if (!value || rows.length > 0 || (input.schemas?.length ?? 0) !== 2) {
88
85
  return rows;
@@ -161,7 +158,7 @@ function renderInputTable({
161
158
  newRows as Array<Record<string, string>>,
162
159
  )
163
160
  }
164
- schemas={(input.schemas as ProcessTemplateInputSchema[]) ?? []}
161
+ schemas={input.schemas?.filter((s) => s != null) ?? []}
165
162
  tableError={tableErrorToShow ?? null}
166
163
  rowErrors={rowErrorsToShow}
167
164
  readOnly={finalReadOnly}
@@ -155,6 +155,8 @@ export function InputTable({
155
155
  s.fieldKey ?? s.label ?? `col_${colIndex}`;
156
156
  const cell = r[columnKey];
157
157
  const cellError = rowErrors?.[i]?.[columnKey] ?? null;
158
+ const cellDisplayValue =
159
+ typeof cell === "boolean" ? String(cell) : cell;
158
160
  if (s.inputType === InputType.CHECKBOX) {
159
161
  return (
160
162
  <TableCell key={s.id}>
@@ -207,10 +209,7 @@ export function InputTable({
207
209
  return (
208
210
  <TableCell key={s.id}>
209
211
  {readOnly ? (
210
- renderReadOnlyText(
211
- undefined,
212
- typeof cell === "boolean" ? String(cell) : cell,
213
- )
212
+ renderReadOnlyText(undefined, cellDisplayValue)
214
213
  ) : (
215
214
  <TextField
216
215
  size="small"
@@ -9,11 +9,11 @@ export function parseQueryName(queryName: string): TemplateInputSearchQueryKey {
9
9
  const qn = queryName.substring(0, indexOf < 0 ? undefined : indexOf).trim();
10
10
 
11
11
  if (isTemplateInputSearchQueryKey(qn)) {
12
- return qn as TemplateInputSearchQueryKey;
12
+ return qn;
13
13
  }
14
14
  const mapped = qn ? TEMPLATE_QUERY_NAME_TO_KEY[qn] : undefined;
15
15
  if (mapped !== undefined) {
16
- return mapped as TemplateInputSearchQueryKey;
16
+ return mapped;
17
17
  }
18
18
 
19
19
  throw new Error(`queryName ${queryName} invalid`);
@@ -22,7 +22,7 @@ export function getSelectorOptionsFromInput(
22
22
 
23
23
  const raw = schemaWithOptions?.options;
24
24
  if (raw == null) return [];
25
- if (!Array.isArray(raw)) return toStringArray(raw) as string[];
25
+ if (!Array.isArray(raw)) return toStringArray(raw);
26
26
 
27
27
  const result: SelectorOption[] = [];
28
28
  for (const item of raw) {
@@ -7,6 +7,90 @@ import type { FlatPage, FormState } from "./types";
7
7
  import { buildZodSchemaForPage } from "./validation/buildZodSchema";
8
8
  import { zodFormikValidate } from "./validation/zodFormikValidate";
9
9
 
10
+ type PageFormContentProps = Readonly<{
11
+ formik: FormikProps<FormState>;
12
+ formikRef: React.MutableRefObject<FormikProps<FormState> | null>;
13
+ submit: () => Promise<boolean>;
14
+ stepKey: string;
15
+ templateId: string;
16
+ page: FlatPage;
17
+ setSubmitRef?: (fn: (() => Promise<boolean>) | undefined) => void;
18
+ setPageValidity?: (valid: boolean) => void;
19
+ clearTemplateFields: (templateId: string) => void;
20
+ readOnly?: boolean;
21
+ isEditMode?: boolean;
22
+ isCreateMode?: boolean;
23
+ disabledFields?: Set<string>;
24
+ setFieldsDisabled?: (
25
+ templateId: string,
26
+ fieldNames: string[],
27
+ disabled: boolean,
28
+ ) => void;
29
+ templateConfig?: string;
30
+ setFieldValidationInProgress?: (inProgress: boolean) => void;
31
+ submitValidationResults?: Record<
32
+ string,
33
+ { isValid: boolean; message: string }
34
+ >;
35
+ }>;
36
+
37
+ function PageFormContent({
38
+ formik,
39
+ formikRef,
40
+ submit,
41
+ stepKey,
42
+ templateId,
43
+ page,
44
+ setSubmitRef,
45
+ setPageValidity,
46
+ clearTemplateFields,
47
+ readOnly,
48
+ isEditMode,
49
+ isCreateMode,
50
+ disabledFields,
51
+ setFieldsDisabled,
52
+ templateConfig,
53
+ setFieldValidationInProgress,
54
+ submitValidationResults,
55
+ }: PageFormContentProps) {
56
+ formikRef.current = formik;
57
+
58
+ useEffect(() => {
59
+ if (setSubmitRef) setSubmitRef(submit);
60
+ return () => {
61
+ if (setSubmitRef) setSubmitRef(undefined);
62
+ };
63
+ }, [submit, setSubmitRef]);
64
+
65
+ useEffect(() => {
66
+ if (setPageValidity) setPageValidity(true);
67
+ }, [stepKey, setPageValidity]);
68
+
69
+ // Keep Next button enabled so user can always click it. Validation runs on Next click (submit).
70
+ // We do not disable Next based on errors; errors show after they click Next or touch a field.
71
+ useEffect(() => {
72
+ if (setPageValidity) setPageValidity(true);
73
+ }, [setPageValidity]);
74
+
75
+ return (
76
+ <form onSubmit={formik.handleSubmit}>
77
+ <FormikPageBody
78
+ templateId={templateId}
79
+ page={page}
80
+ clearTemplateFields={() => clearTemplateFields(templateId)}
81
+ readOnly={readOnly}
82
+ isEditMode={isEditMode}
83
+ isCreateMode={isCreateMode}
84
+ disabledFields={disabledFields}
85
+ setFieldsDisabled={setFieldsDisabled}
86
+ templateConfig={templateConfig}
87
+ setFieldValidationInProgress={setFieldValidationInProgress}
88
+ submitValidationResults={submitValidationResults}
89
+ />
90
+ </form>
91
+ );
92
+ }
93
+
10
94
  export default function PageForm({
11
95
  templateId,
12
96
  page,
@@ -112,40 +196,26 @@ export default function PageForm({
112
196
  }}
113
197
  >
114
198
  {(formik) => {
115
- formikRef.current = formik as FormikProps<FormState>;
116
- useEffect(() => {
117
- if (setSubmitRef) setSubmitRef(submit);
118
- return () => {
119
- if (setSubmitRef) setSubmitRef(undefined);
120
- };
121
- }, [submit, setSubmitRef]);
122
-
123
- useEffect(() => {
124
- if (setPageValidity) setPageValidity(true);
125
- }, [stepKey, setPageValidity]);
126
-
127
- // Keep Next button enabled so user can always click it. Validation runs on Next click (submit).
128
- // We do not disable Next based on errors; errors show after they click Next or touch a field.
129
- useEffect(() => {
130
- if (setPageValidity) setPageValidity(true);
131
- }, [setPageValidity]);
132
-
133
199
  return (
134
- <form onSubmit={formik.handleSubmit}>
135
- <FormikPageBody
136
- templateId={templateId}
137
- page={page}
138
- clearTemplateFields={() => clearTemplateFields(templateId)}
139
- readOnly={readOnly}
140
- isEditMode={isEditMode}
141
- isCreateMode={isCreateMode}
142
- disabledFields={disabledFields}
143
- setFieldsDisabled={setFieldsDisabled}
144
- templateConfig={templateConfig}
145
- setFieldValidationInProgress={setFieldValidationInProgress}
146
- submitValidationResults={submitValidationResults}
147
- />
148
- </form>
200
+ <PageFormContent
201
+ formik={formik as FormikProps<FormState>}
202
+ formikRef={formikRef}
203
+ submit={submit}
204
+ stepKey={stepKey}
205
+ templateId={templateId}
206
+ page={page}
207
+ setSubmitRef={setSubmitRef}
208
+ setPageValidity={setPageValidity}
209
+ clearTemplateFields={clearTemplateFields}
210
+ readOnly={readOnly}
211
+ isEditMode={isEditMode}
212
+ isCreateMode={isCreateMode}
213
+ disabledFields={disabledFields}
214
+ setFieldsDisabled={setFieldsDisabled}
215
+ templateConfig={templateConfig}
216
+ setFieldValidationInProgress={setFieldValidationInProgress}
217
+ submitValidationResults={submitValidationResults}
218
+ />
149
219
  );
150
220
  }}
151
221
  </Formik>
@@ -89,7 +89,7 @@ export default function TemplatesList(props: Readonly<Props>) {
89
89
  skip: 0,
90
90
  search: search,
91
91
  });
92
- setPerPage(itemsPerPage as number);
92
+ setPerPage(itemsPerPage || 10);
93
93
  setPage(1);
94
94
  };
95
95
 
@@ -189,7 +189,7 @@ export default function TemplatesList(props: Readonly<Props>) {
189
189
  <TablePagination
190
190
  page={page}
191
191
  onChange={handleChangePage}
192
- count={Math.ceil(recordCount / (props.input.top as number))}
192
+ count={Math.ceil(recordCount / (props.input.top || 10))}
193
193
  />
194
194
  </FlexBox>
195
195
  </Grid>
@@ -31,7 +31,6 @@ import {
31
31
  type ProcessTemplate,
32
32
  type ProcessTemplateInputSchema,
33
33
  type ProcessTemplatePage,
34
- type SearchOption,
35
34
  sortBy,
36
35
  templateFieldKey,
37
36
  } from "./types";
@@ -136,7 +135,7 @@ function getInitialValuesFromTemplates(
136
135
  input?.defaultValue !== null &&
137
136
  !newInitialValues[key]
138
137
  ) {
139
- newInitialValues[key] = input.defaultValue as FieldValue;
138
+ newInitialValues[key] = input.defaultValue;
140
139
  }
141
140
  });
142
141
  });
@@ -429,9 +428,9 @@ export default function Wizard({ metadata, sharedCount, ...props }: Props) {
429
428
  const config = JSON.parse(props.templateConfig);
430
429
  applyTemplateConfig(
431
430
  {
432
- name: config.taskName as string,
431
+ name: config.taskName,
433
432
  templateConfig: props.templateConfig,
434
- } as SearchOption,
433
+ },
435
434
  (templateId: string, fieldName: string, value: FieldValue) => {
436
435
  const key = templateFieldKey(templateId, fieldName);
437
436
  setInitialValues((prev) => ({ ...prev, [key]: value }));