@evenicanpm/admin-integrate 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/documents/ConfigImport/configuration-import.ts +1 -1
  2. package/documents/Endpoint/list.ts +3 -3
  3. package/documents/Process/list.ts +3 -3
  4. package/documents/ProcessExecution/list.ts +2 -2
  5. package/documents/ProcessExport/read.ts +1 -1
  6. package/documents/ProcessSchedule/read.ts +1 -1
  7. package/documents/ProcessScheduleGroup/read.ts +3 -3
  8. package/documents/ProcessTemplate/read.ts +1 -1
  9. package/documents/ScheduledProcess/list.ts +1 -1
  10. package/package.json +2 -2
  11. package/src/components/integration-view/animated-svg.tsx +0 -1
  12. package/src/components/integration-view/elk-types.ts +1 -1
  13. package/src/components/integration-view/integration-view.tsx +267 -175
  14. package/src/components/integration-view/nodes/execution-entry-node.tsx +3 -2
  15. package/src/components/integration-view/types.ts +2 -0
  16. package/src/components/integration-view/utils/mapping.ts +62 -41
  17. package/src/components/list-filter/list-filter-types.ts +6 -0
  18. package/src/components/list-filter/list-filter.tsx +19 -15
  19. package/src/components/list-filter/multi-select-filter.tsx +7 -7
  20. package/src/components/list-filter/select-filter.tsx +6 -6
  21. package/src/components/scheduler/day-selector.tsx +1 -1
  22. package/src/components/templatesV2/inputs/form-type.ts +7 -1
  23. package/src/components/templatesV2/inputs/renderers/renderFormControl.tsx +19 -11
  24. package/src/components/templatesV2/inputs/renderers/renderSearchInput.tsx +3 -4
  25. package/src/components/templatesV2/inputs/search/useSearchInput.ts +12 -7
  26. package/src/components/templatesV2/inputs/table/InputTable.tsx +20 -11
  27. package/src/components/templatesV2/inputs/utils/arrangeInputs.ts +4 -3
  28. package/src/components/templatesV2/pageForm.tsx +9 -7
  29. package/src/components/templatesV2/validation/buildZodSchema.ts +0 -4
  30. package/src/components/templatesV2/wizard.tsx +5 -3
  31. package/src/pages/dashboard/dashboard-link-cards.tsx +0 -1
  32. package/src/pages/dashboard/dashboard-list-sections.tsx +1 -1
  33. package/src/pages/dashboard/dashboard.tsx +0 -1
  34. package/src/pages/executions/executions-list/executions-list-table.tsx +0 -1
  35. package/src/pages/executions/executions.tsx +1 -1
  36. package/src/pages/integration-create/integration-create.tsx +20 -14
  37. package/src/pages/integration-create/pre-creation-step.tsx +9 -9
  38. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +1 -3
  39. package/src/pages/integration-details/integration-details.tsx +1 -1
  40. package/src/pages/integration-details/task-drawer/edit-task.tsx +2 -2
  41. package/src/pages/integration-details/task-drawer/task-drawer.tsx +2 -2
@@ -9,6 +9,7 @@ import {
9
9
  useTheme,
10
10
  } from "@mui/material";
11
11
  import { Handle, type NodeProps, Position } from "@xyflow/react";
12
+ import type { ReactNode } from "react";
12
13
 
13
14
  export function ExecutionEntryNode(props: NodeProps): JSX.Element {
14
15
  const theme = useTheme();
@@ -50,7 +51,7 @@ export function ExecutionEntryNode(props: NodeProps): JSX.Element {
50
51
  }}
51
52
  >
52
53
  <CardContent sx={styles.cardContent}>
53
- {props?.data?.icon as any}
54
+ {props?.data?.icon as ReactNode}
54
55
  <Typography variant="h6" sx={styles.label}>
55
56
  {props?.data?.label as string}
56
57
  </Typography>
@@ -61,7 +62,7 @@ export function ExecutionEntryNode(props: NodeProps): JSX.Element {
61
62
  <>
62
63
  <Divider sx={styles.divider} />
63
64
  <CardContent sx={styles.cardContent}>
64
- {props?.data?.icon2 as any}
65
+ {props?.data?.icon2 as ReactNode}
65
66
  <Typography variant="h6" sx={styles.label}>
66
67
  {props?.data?.label2 as string}
67
68
  </Typography>
@@ -1,3 +1,4 @@
1
+ /*
1
2
  type ElkOptions = {};
2
3
 
3
4
  type ElkPosition = {};
@@ -10,3 +11,4 @@ interface ElkItem {
10
11
  y: number;
11
12
  layoutOptions: ElkOptions;
12
13
  }
14
+ */
@@ -1,14 +1,14 @@
1
+ import { MarkerType } from "@xyflow/react";
2
+ import _ from "lodash";
1
3
  import type {
2
4
  ConfigExport,
5
+ Process,
3
6
  ProcessExecutionDetails,
4
7
  ProcessExport,
5
8
  ProcessTask,
6
9
  ProcessTaskExecution,
7
10
  ProcessTaskExport,
8
- } from "@evenicanpm/admin-core/src/api/e4/graphqlRequestSdk";
9
- import { MarkerType } from "@xyflow/react";
10
- import _ from "lodash";
11
- import type { Process } from "../../../../../admin-core/src/api/e4/graphqlRequestSdk";
11
+ } from "../../../../../admin-core/src/api/e4/graphqlRequestSdk";
12
12
  import type {
13
13
  ElkExtendedEdgeWithFlow,
14
14
  ElkNodeWithFlow,
@@ -23,11 +23,23 @@ const markerEnd = {
23
23
  height: 20,
24
24
  };
25
25
 
26
+ type TaskRecord = Record<string, unknown>;
27
+ type BuildGroupsTask = (group: GroupNode) => TaskRecord[];
28
+ type BuildNodeMapper = (
29
+ task: TaskRecord,
30
+ index: number,
31
+ partitionLen: number,
32
+ parentId: string,
33
+ ) => ElkNodeWithFlow;
34
+ export type AddHandler = unknown;
35
+ const asIdentifierString = (value: unknown) =>
36
+ typeof value === "string" || typeof value === "number" ? String(value) : "";
37
+
26
38
  export function mapToCamelCase(processTask: ProcessTaskExport): ProcessTask {
27
39
  let key: string;
28
40
  const keys = Object.keys(processTask);
29
41
  let n = keys.length;
30
- const newobj: { [key: string]: any } = {};
42
+ const newobj: Record<string, unknown> = {};
31
43
  while (n--) {
32
44
  key = keys[n];
33
45
  newobj[key.substring(0, 1).toLowerCase() + key.substring(1)] =
@@ -144,17 +156,17 @@ function buildGroupsAndEdges({
144
156
  entryPoint: ElkNodeWithFlow;
145
157
  entryPointConnector: ElkNodeWithFlow;
146
158
  groupLabels: number[];
147
- getGroupTasks: Function;
159
+ getGroupTasks: BuildGroupsTask;
148
160
  // nodeWidth: number,
149
161
  variant: "process" | "process-execution";
150
- onAdd?: Function;
151
- mapTaskToNode: Function;
162
+ onAdd?: AddHandler;
163
+ mapTaskToNode: BuildNodeMapper;
152
164
  groupSortKey: string;
153
165
  taskIdKey: string;
154
166
  taskNameKey: string;
155
167
  connectorIdPrefix: string;
156
168
  }) {
157
- const groups: GroupNode[] = groupLabels.map((groupLabel: any) => ({
169
+ const groups: GroupNode[] = groupLabels.map((groupLabel: number) => ({
158
170
  id: `group-${groupLabel}`,
159
171
  data: {
160
172
  label: `Group ${groupLabel}`,
@@ -170,7 +182,7 @@ function buildGroupsAndEdges({
170
182
  },
171
183
  draggable: false,
172
184
  }));
173
- const edges: any[] = [];
185
+ const edges: ElkExtendedEdgeWithFlow[] = [];
174
186
  edges.push({
175
187
  id: `entry-point-entry-point-connector`,
176
188
  sources: ["entry-point"],
@@ -187,21 +199,25 @@ function buildGroupsAndEdges({
187
199
  });
188
200
  const groupTasks = getGroupTasks(group);
189
201
  const tasksPartitioned = _.values(_.groupBy(groupTasks, groupSortKey));
190
- const groupNodes: any[] = [];
202
+ const groupNodes: ElkNodeWithFlow[] = [];
191
203
  tasksPartitioned.forEach((partition) => {
192
- partition.forEach((task: any, index: number) => {
204
+ partition.forEach((task: TaskRecord, index: number) => {
193
205
  groupNodes.push(mapTaskToNode(task, index, partition.length, group.id));
194
206
  });
195
207
  });
196
208
  let prevConnectorId: string | null = null;
197
209
  tasksPartitioned.forEach((partition, tpIndex) => {
198
- _.sortBy(partition, [(task: any) => task[taskNameKey]]);
210
+ _.sortBy(partition, [(task: TaskRecord) => task[taskNameKey]]);
199
211
  if (prevConnectorId) {
200
- partition.forEach((task: any) => {
212
+ const fromConnectorId = prevConnectorId;
213
+ partition.forEach((task: TaskRecord) => {
214
+ const taskIdentifier = asIdentifierString(
215
+ task[taskIdKey] ?? task[taskNameKey],
216
+ );
201
217
  edges.push({
202
- id: `${prevConnectorId}-${task[taskIdKey] || task[taskNameKey]}`,
203
- sources: [prevConnectorId],
204
- targets: [`task-${task[taskIdKey] || task[taskNameKey]}`],
218
+ id: `${fromConnectorId}-${taskIdentifier}`,
219
+ sources: [fromConnectorId],
220
+ targets: [`task-${taskIdentifier}`],
205
221
  type: "default-edge",
206
222
  markerEnd: markerEnd,
207
223
  });
@@ -210,10 +226,13 @@ function buildGroupsAndEdges({
210
226
  const connectorId = `${connectorIdPrefix}${group.id}-connect-${tpIndex}`;
211
227
  prevConnectorId = connectorId;
212
228
  if (tpIndex !== tasksPartitioned.length - 1) {
213
- partition.forEach((task: any) => {
229
+ partition.forEach((task: TaskRecord) => {
230
+ const taskIdentifier = asIdentifierString(
231
+ task[taskIdKey] ?? task[taskNameKey],
232
+ );
214
233
  edges.push({
215
- id: `task-${task[taskIdKey] || task[taskNameKey]}-${connectorId}`,
216
- sources: [`task-${task[taskIdKey] || task[taskNameKey]}`],
234
+ id: `task-${taskIdentifier}-${connectorId}`,
235
+ sources: [`task-${taskIdentifier}`],
217
236
  targets: [connectorId],
218
237
  type: "default-edge",
219
238
  });
@@ -240,7 +259,7 @@ export const mapProcessConfigToNodesAndEdges = (
240
259
  data: ConfigExport,
241
260
  nodeWidth: number,
242
261
  variant: "process" | "process-execution",
243
- onAdd?: Function,
262
+ onAdd?: AddHandler,
244
263
  ) => {
245
264
  const process = data.Processes?.[0] as ProcessExport;
246
265
  const entryPoint: ElkNodeWithFlow = {
@@ -273,25 +292,25 @@ export const mapProcessConfigToNodesAndEdges = (
273
292
  entryPoint,
274
293
  entryPointConnector,
275
294
  groupLabels,
276
- getGroupTasks: (group: any) =>
295
+ getGroupTasks: (group: GroupNode) =>
277
296
  _.sortBy(
278
297
  process?.ProcessTasks?.filter(
279
- (task) =>
280
- task?.ParallelProcessingGroup?.toString() ===
281
- group.id.split("-")[1],
282
- ),
298
+ (task): task is ProcessTaskExport =>
299
+ task != null &&
300
+ task.ParallelProcessingGroup?.toString() === group.id.split("-")[1],
301
+ ) ?? [],
283
302
  ["Sort", "Name"],
284
- ),
303
+ ) as TaskRecord[],
285
304
  //nodeWidth,
286
305
  variant,
287
306
  onAdd,
288
307
  mapTaskToNode: (
289
- task: any,
308
+ task: TaskRecord,
290
309
  index: number,
291
310
  partitionLen: number,
292
311
  parentId: string,
293
312
  ) => ({
294
- id: `task-${task?.ProcessTaskId || task?.Name}`,
313
+ id: `task-${asIdentifierString(task.ProcessTaskId ?? task.Name)}`,
295
314
  data: {
296
315
  processTask: mapToCamelCase(task as ProcessTaskExport) || undefined,
297
316
  label: task?.Name as string,
@@ -359,28 +378,30 @@ export const mapProcessTasksToNodesAndEdges = (
359
378
  entryPoint,
360
379
  entryPointConnector,
361
380
  groupLabels,
362
- getGroupTasks: (group: any) =>
363
- _.sortBy(
364
- (variant === "process"
381
+ getGroupTasks: (group: GroupNode) => {
382
+ const tasks =
383
+ variant === "process"
365
384
  ? (data as Process)?.processTasks
366
- : (data as ProcessExecutionDetails)?.processTaskExecutions
367
- )?.filter(
368
- (task) =>
369
- task?.parallelProcessingGroup?.toString() ===
370
- group.id.split("-")[1],
371
- ),
385
+ : (data as ProcessExecutionDetails)?.processTaskExecutions;
386
+ return _.sortBy(
387
+ tasks?.filter(
388
+ (task): task is ProcessTask | ProcessTaskExecution =>
389
+ task != null &&
390
+ task.parallelProcessingGroup?.toString() === group.id.split("-")[1],
391
+ ) ?? [],
372
392
  ["sort", "name"],
373
- ),
393
+ ) as TaskRecord[];
394
+ },
374
395
  //nodeWidth,
375
396
  variant,
376
397
  onAdd: undefined,
377
398
  mapTaskToNode: (
378
- task: any,
399
+ task: TaskRecord,
379
400
  index: number,
380
401
  partitionLen: number,
381
402
  parentId: string,
382
403
  ) => ({
383
- id: `task-${task?.id}`,
404
+ id: `task-${asIdentifierString(task.id)}`,
384
405
  data: {
385
406
  processTask: variant === "process" ? (task as ProcessTask) : undefined,
386
407
  processTaskExecution:
@@ -38,6 +38,12 @@ export interface Filters {
38
38
  | MultiSelectFilter;
39
39
  }
40
40
 
41
+ export type FilterValue =
42
+ | DateFilter["value"]
43
+ | DateRangeFilter["value"]
44
+ | SelectFilter["value"]
45
+ | MultiSelectFilter["value"];
46
+
41
47
  export type FilterResult<FilterShape extends Filters> = {
42
48
  [Property in keyof FilterShape]: FilterShape[Property]["value"];
43
49
  };
@@ -33,6 +33,7 @@ import type {
33
33
  FilterConfig,
34
34
  FilterResult,
35
35
  Filters,
36
+ FilterValue,
36
37
  ListFilterOutput,
37
38
  } from "./list-filter-types";
38
39
  import MultiSelectFilterComponent from "./multi-select-filter";
@@ -71,22 +72,22 @@ const ListFilter = function ListFilter<FilterShape extends Filters>(
71
72
 
72
73
  const defaultValues = Object.entries(filters).reduce(
73
74
  (values, [key, filter]) => {
74
- if (filter.type === "select" && filter.value)
75
- return {
76
- ...values,
75
+ if (filter.type === "select" && filter.value) {
76
+ return Object.assign(values, {
77
77
  // @ts-expect-error
78
78
  [key]: filter.options.find((o) => o.id === filter.value[0].id),
79
- };
80
- if (filter.type === "multiSelect" && filter.value)
81
- return {
82
- ...values,
79
+ });
80
+ }
81
+ if (filter.type === "multiSelect" && filter.value) {
82
+ return Object.assign(values, {
83
83
  [key]: filter.options.filter((o) =>
84
84
  // @ts-expect-error
85
85
  filter.value.find((v) => v.id === o.id),
86
86
  ),
87
- };
87
+ });
88
+ }
88
89
 
89
- return { ...values, [key]: filter.value };
90
+ return Object.assign(values, { [key]: filter.value });
90
91
  },
91
92
  {},
92
93
  ) as FilterResult<FilterShape>;
@@ -94,10 +95,10 @@ const ListFilter = function ListFilter<FilterShape extends Filters>(
94
95
  const filterErrorsBase: FilterErrors<FilterShape> = Object.keys(
95
96
  filters,
96
97
  ).reduce(
97
- (values, key) => ({
98
- ...values,
99
- [key]: false,
100
- }),
98
+ (values, key) =>
99
+ Object.assign(values, {
100
+ [key]: false,
101
+ }),
101
102
  {},
102
103
  ) as FilterErrors<FilterShape>;
103
104
 
@@ -124,7 +125,7 @@ const ListFilter = function ListFilter<FilterShape extends Filters>(
124
125
  0,
125
126
  );
126
127
 
127
- const updateFilterValue = (name: string, value: any) => {
128
+ const updateFilterValue = (name: string, value: FilterValue | undefined) => {
128
129
  if (Array.isArray(value) && !value.length) value = null;
129
130
  setFilterValues({
130
131
  ...filterValues,
@@ -174,7 +175,10 @@ const ListFilter = function ListFilter<FilterShape extends Filters>(
174
175
 
175
176
  const handleFilterClear = () => {
176
177
  const emptyFilterValues = Object.keys(filterValues).reduce(
177
- (values, key) => ({ ...values, [key]: null }),
178
+ (values, key) =>
179
+ Object.assign(values, {
180
+ [key]: null,
181
+ }),
178
182
  {},
179
183
  ) as FilterResult<FilterShape>;
180
184
  setPublishedFilterValues(emptyFilterValues);
@@ -31,15 +31,15 @@ const MultiSelectFilterComponent: React.FC<FilterProps<MultiSelectFilter>> = ({
31
31
  const t = useTranslations("Integrate");
32
32
 
33
33
  const mappedOptionDictionary = filter.options.reduce(
34
- (dictionary, option) => ({
35
- ...dictionary,
36
- [option.id]: {
34
+ (dictionary, option) => {
35
+ dictionary[option.id] = {
37
36
  id: option.id,
38
37
  value: t(option.value),
39
- },
40
- }),
41
- {},
42
- ) as { [id: string | number]: FilterOption };
38
+ };
39
+ return dictionary;
40
+ },
41
+ {} as { [id: string | number]: FilterOption },
42
+ );
43
43
 
44
44
  const [value, setValue] = useState(current);
45
45
 
@@ -31,12 +31,12 @@ const SelectFilterComponent: React.FC<FilterProps<SelectFilter>> = ({
31
31
  const [value, setValue] = useState(current);
32
32
 
33
33
  const mappedOptionDictionary = filter.options.reduce(
34
- (dictionary, option) => ({
35
- ...dictionary,
36
- [option.id]: option,
37
- }),
38
- {},
39
- ) as { [id: string | number]: FilterOption };
34
+ (dictionary: { [id: string | number]: FilterOption }, option) => {
35
+ dictionary[option.id] = option;
36
+ return dictionary;
37
+ },
38
+ {} as { [id: string | number]: FilterOption },
39
+ );
40
40
 
41
41
  const updateValue = (optionId: string | number | null) => {
42
42
  if (optionId == null) {
@@ -158,7 +158,7 @@ const getStyles = (theme: Theme): DaySelectorStyles => {
158
158
  },
159
159
  dayOfWeek: {
160
160
  color: "grey.700",
161
- border: "solid " + theme.palette.grey[500] + " " + theme.spacing(0.5),
161
+ border: `solid ${theme.palette.grey[500]} ${theme.spacing(0.5)}`,
162
162
  backgroundColor: theme.palette.grey[50],
163
163
  borderRadius: "50%",
164
164
  width: theme.spacing(5),
@@ -5,6 +5,12 @@ export type TableRow = Record<string, string | number | boolean | null>;
5
5
 
6
6
  export type SetRowsFn = (rows: TableRow[]) => void;
7
7
 
8
+ /** Used for TEXT_UNIQUE_IDENTIFIER when updating a sibling field (e.g. `isUnique`). */
9
+ export type SearchInputExtendedSetValue = (
10
+ v: FieldValue,
11
+ fieldName?: string,
12
+ ) => void;
13
+
8
14
  export interface InputTableProps {
9
15
  rows: TableRow[];
10
16
  setRows: SetRowsFn;
@@ -25,7 +31,7 @@ export type SearchInputWrapperProps = {
25
31
  setValue:
26
32
  | ((v: string) => void)
27
33
  | ((v: string[]) => void)
28
- | ((v: string, fieldName?: string) => void);
34
+ | SearchInputExtendedSetValue;
29
35
 
30
36
  placeholder?: string | null;
31
37
  helpText?: string | null;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { Box, FormHelperText, Typography } from "@mui/material";
4
- import { Field } from "formik";
4
+ import { Field, type FieldProps } from "formik";
5
5
  import type * as React from "react";
6
6
  import type {
7
7
  ErrorState,
@@ -76,9 +76,13 @@ function queryInputType(
76
76
  function normalizeInputTableRows(
77
77
  value: unknown,
78
78
  input: ProcessTemplateInput,
79
- ): Array<Record<string, unknown>> {
80
- const rows: Array<Record<string, unknown>> = Array.isArray(value)
81
- ? (value as Array<Record<string, unknown>>)
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
+ >)
82
86
  : [];
83
87
  if (!value || rows.length > 0 || (input.schemas?.length ?? 0) !== 2) {
84
88
  return rows;
@@ -151,7 +155,11 @@ function renderInputTable({
151
155
  <InputTable
152
156
  rows={rows}
153
157
  setRows={(newRows) =>
154
- handleFieldChange(templateId, input.fieldName ?? "", newRows)
158
+ handleFieldChange(
159
+ templateId,
160
+ input.fieldName ?? "",
161
+ newRows as Array<Record<string, string>>,
162
+ )
155
163
  }
156
164
  schemas={(input.schemas as ProcessTemplateInputSchema[]) ?? []}
157
165
  tableError={tableErrorToShow ?? null}
@@ -204,7 +212,7 @@ export function renderFormControl({
204
212
  value: FieldValue,
205
213
  ) => void;
206
214
  setFieldTouched?: (field: string, value: boolean) => void;
207
- validateField?: (field: string) => void | Promise<unknown>;
215
+ validateField?: (field: string) => undefined | Promise<unknown>;
208
216
  validateForm?: () => Promise<Record<string, unknown>>;
209
217
  readOnly?: boolean;
210
218
  disabledFields?: Set<string>;
@@ -230,7 +238,7 @@ export function renderFormControl({
230
238
  const submitValidationResult = submitValidationResults?.[k] ?? null;
231
239
  return (
232
240
  <Field name={k}>
233
- {({ field, form, meta }: any) => (
241
+ {({ field, form, meta }: FieldProps) => (
234
242
  <TextWithQueryInput
235
243
  inputType={queryInputTypeVal}
236
244
  label={input.label ?? ""}
@@ -264,7 +272,7 @@ export function renderFormControl({
264
272
  if (input.inputType === InputType.CHECKBOX) {
265
273
  return (
266
274
  <Field name={k}>
267
- {({ field, form }: any) => (
275
+ {({ field, form }: FieldProps) => (
268
276
  <CheckboxInput
269
277
  label={input.label ?? ""}
270
278
  checked={Boolean(field.value ?? false)}
@@ -280,7 +288,7 @@ export function renderFormControl({
280
288
  if (input.inputType === InputType.NUMBER) {
281
289
  return (
282
290
  <Field name={k}>
283
- {({ field, form, meta }: any) => (
291
+ {({ field, form, meta }: FieldProps) => (
284
292
  <NumberInput
285
293
  label={input.label ?? ""}
286
294
  value={(field.value as number) ?? ""}
@@ -299,7 +307,7 @@ export function renderFormControl({
299
307
  if (input.inputType === InputType.SELECTOR) {
300
308
  return (
301
309
  <Field name={k}>
302
- {({ field, form, meta }: any) => (
310
+ {({ field, form, meta }: FieldProps) => (
303
311
  <SelectorInput
304
312
  fieldName={input.fieldName ?? ""}
305
313
  label={input.label ?? ""}
@@ -359,7 +367,7 @@ export function renderFormControl({
359
367
 
360
368
  return (
361
369
  <Field name={k}>
362
- {({ field, form, meta }: any) => (
370
+ {({ field, form, meta }: FieldProps) => (
363
371
  <TextInput
364
372
  label={input.label ?? ""}
365
373
  value={(field.value as string) ?? ""}
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
 
3
3
  import { Field, type FieldProps } from "formik";
4
- import * as React from "react";
5
4
  import {
6
5
  type FieldValue,
7
6
  type ProcessTemplateInput,
@@ -46,7 +45,7 @@ export function renderSearchInput({
46
45
  if (input.inputType === InputType.MULTI_TEXT_SEARCH) {
47
46
  return (
48
47
  <Field name={k}>
49
- {({ field, form, meta }: any) => (
48
+ {({ field, form, meta }: FieldProps) => (
50
49
  <SearchInputWrapper
51
50
  inputType={InputType.MULTI_TEXT_SEARCH}
52
51
  queryName={queryName}
@@ -66,7 +65,7 @@ export function renderSearchInput({
66
65
  if (input.inputType === InputType.TEXT_SEARCH) {
67
66
  return (
68
67
  <Field name={k}>
69
- {({ field, form, meta }: any) => (
68
+ {({ field, form, meta }: FieldProps) => (
70
69
  <SearchInputWrapper
71
70
  inputType={InputType.TEXT_SEARCH}
72
71
  queryName={queryName}
@@ -97,7 +96,7 @@ export function renderSearchInput({
97
96
 
98
97
  <Field name={k}>
99
98
  {({ field, form, meta }: FieldProps) => {
100
- const setUniqueValue = (v: string, fieldName?: string) => {
99
+ const setUniqueValue = (v: FieldValue, fieldName?: string) => {
101
100
  const targetKey = fieldName
102
101
  ? templateFieldKey(templateId, fieldName)
103
102
  : k;
@@ -3,19 +3,21 @@ import type {
3
3
  GetSourceEndpointsQuery,
4
4
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
5
5
  import { templateInputSearch } from "@evenicanpm/admin-integrate/api/templates/queries";
6
- import type { TemplateInputSearchQueryKey } from "@evenicanpm/admin-integrate/api/templates/queries/types";
7
6
  import { useSearchParams } from "next/navigation";
8
7
  import React from "react";
9
8
  import type { SearchOption } from "../../types";
10
9
  import { ReservedFieldName } from "../field-names";
10
+ import type {
11
+ SearchInputExtendedSetValue,
12
+ SearchInputWrapperProps,
13
+ } from "../form-type";
11
14
  import { InputType } from "../input-type";
12
15
  import { TemplateSearchQueryKey } from "./search-query-key";
13
16
 
14
- type UseSearchInputProps = {
15
- inputType: InputType;
16
- queryName: TemplateInputSearchQueryKey;
17
- setValue?: (v: any, fieldName?: string) => void;
18
- };
17
+ type UseSearchInputProps = Pick<
18
+ SearchInputWrapperProps,
19
+ "inputType" | "queryName" | "setValue"
20
+ >;
19
21
 
20
22
  export function useSearchInput({
21
23
  inputType,
@@ -59,7 +61,10 @@ export function useSearchInput({
59
61
  const typed = data as CheckUniqueIdentifierQuery;
60
62
  const unique = typed.checkUniqueIdentifier?.isUnique ?? null;
61
63
  setIsUnique(unique);
62
- setValue?.(unique, ReservedFieldName.IsUnique);
64
+ (setValue as SearchInputExtendedSetValue | undefined)?.(
65
+ unique,
66
+ ReservedFieldName.IsUnique,
67
+ );
63
68
  break;
64
69
  }
65
70
  }
@@ -28,15 +28,17 @@ import { renderReadOnlyText } from "../utils/renderReadOnlyText";
28
28
  /** Reserved key for React list key; not a schema column. */
29
29
  const ROW_ID_KEY = "__rowId" as const;
30
30
 
31
- function getRowId(row: Record<string, any>, index: number): string {
31
+ type RowRecord = Record<string, string | number | boolean | null | undefined>;
32
+
33
+ function getRowId(row: RowRecord, index: number): string {
32
34
  const id = row[ROW_ID_KEY];
33
35
  if (typeof id === "string" && id.length > 0) return id;
34
36
  return `row-${index}`;
35
37
  }
36
38
 
37
39
  function ensureRowIds(
38
- rows: Array<Record<string, any>>,
39
- setRows: (rows: Array<Record<string, any>>) => void,
40
+ rows: RowRecord[],
41
+ setRows: (rows: RowRecord[]) => void,
40
42
  ): void {
41
43
  const needsId = rows.some(
42
44
  (r) => r[ROW_ID_KEY] == null || r[ROW_ID_KEY] === "",
@@ -60,8 +62,8 @@ export function InputTable({
60
62
  readOnly,
61
63
  onCellBlur,
62
64
  }: Readonly<{
63
- rows: Array<Record<string, any>>;
64
- setRows: (rows: Array<Record<string, any>>) => void;
65
+ rows: RowRecord[];
66
+ setRows: (rows: RowRecord[]) => void;
65
67
  schemas: ProcessTemplateInputSchema[];
66
68
  tableError: string | null;
67
69
  rowErrors?: Array<Record<string, string>>;
@@ -95,7 +97,7 @@ export function InputTable({
95
97
  }, [rows, ordered]);
96
98
 
97
99
  const addRow = () => {
98
- const empty: Record<string, any> = {
100
+ const empty: RowRecord = {
99
101
  [ROW_ID_KEY]: crypto.randomUUID(),
100
102
  };
101
103
  ordered.forEach((s, colIndex) => {
@@ -112,7 +114,11 @@ export function InputTable({
112
114
  setRows(copy);
113
115
  };
114
116
 
115
- const updateCell = (idx: number, columnKey: string, value: any) => {
117
+ const updateCell = (
118
+ idx: number,
119
+ columnKey: string,
120
+ value: string | number | boolean | null | undefined,
121
+ ) => {
116
122
  const copy = [...rows];
117
123
  copy[idx] = { ...copy[idx], [columnKey]: value };
118
124
  setRows(copy);
@@ -141,7 +147,7 @@ export function InputTable({
141
147
  </TableRow>
142
148
  </TableHead>
143
149
  <TableBody>
144
- {(rows ?? []).map((r: Record<string, any>, i: number) => (
150
+ {(rows ?? []).map((r: RowRecord, i: number) => (
145
151
  <TableRow key={getRowId(r, i)}>
146
152
  {ordered.map(
147
153
  (s: ProcessTemplateInputSchema, colIndex: number) => {
@@ -188,7 +194,7 @@ export function InputTable({
188
194
  minWidth={120}
189
195
  fieldName={columnKey}
190
196
  label={s.label ?? ""}
191
- value={cell}
197
+ value={cell == null ? "" : String(cell)}
192
198
  options={opts}
193
199
  setValue={(v) => updateCell(i, columnKey, v)}
194
200
  error={cellError}
@@ -201,11 +207,14 @@ export function InputTable({
201
207
  return (
202
208
  <TableCell key={s.id}>
203
209
  {readOnly ? (
204
- renderReadOnlyText(undefined, cell)
210
+ renderReadOnlyText(
211
+ undefined,
212
+ typeof cell === "boolean" ? String(cell) : cell,
213
+ )
205
214
  ) : (
206
215
  <TextField
207
216
  size="small"
208
- value={cell}
217
+ value={cell == null ? "" : String(cell)}
209
218
  onChange={(e) =>
210
219
  updateCell(i, columnKey, e.target.value)
211
220
  }