@evenicanpm/admin-integrate 1.3.0 → 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 (79) hide show
  1. package/documents/Endpoint/list.ts +8 -0
  2. package/documents/Process/get-process-details.ts +0 -1
  3. package/documents/ProcessConfig/fragments.ts +1 -1
  4. package/documents/ProcessExport/read.ts +108 -0
  5. package/documents/ProcessTask/fragments.ts +4 -1
  6. package/documents/ProcessTemplate/fragments.ts +6 -1
  7. package/package.json +2 -2
  8. package/src/api/configuration/queries/configuration-export.query.ts +48 -0
  9. package/src/api/configuration/queries/configuration-export.server.ts +9 -0
  10. package/src/api/configuration/queries/index.ts +1 -0
  11. package/src/api/process/mutations/copy-process.mutation.ts +2 -5
  12. package/src/api/process-config/mutation/process-config-import.mutation.ts +9 -0
  13. package/src/api/process-task/queries/get-process-task-by-id.query.ts +1 -0
  14. package/src/api/scheduler/mutation/create-process-schedule-group-details.mutation.ts +2 -2
  15. package/src/api/scheduler/mutation/update-process-schedule-group-details.mutation.ts +2 -2
  16. package/src/api/templates/queries/template-input-search.query.ts +5 -0
  17. package/src/api/templates/queries/template-input-search.server.ts +8 -1
  18. package/src/api/templates/queries/types.ts +9 -3
  19. package/src/components/breadcrumbs/breadcrumbs.tsx +1 -1
  20. package/src/components/core/date-time-popover.tsx +1 -1
  21. package/src/components/core/drawer-buttons.tsx +1 -1
  22. package/src/components/core/edited-typography.tsx +1 -1
  23. package/src/components/core/title-edit.tsx +13 -11
  24. package/src/components/dashboard-list/dashboard-list.tsx +1 -1
  25. package/src/components/data-table/table-header.tsx +1 -1
  26. package/src/components/data-table/table-skeleton.tsx +1 -1
  27. package/src/components/execution-history-drawer/execution-history-drawer.tsx +1 -2
  28. package/src/components/header/integration-details-header.tsx +4 -0
  29. package/src/components/integration-list/list/integration-list-row.tsx +2 -2
  30. package/src/components/integration-list/list/integration-list-table.tsx +3 -3
  31. package/src/components/integration-list/list/integration-list.tsx +3 -3
  32. package/src/components/integration-view/edges/default-edge.tsx +1 -5
  33. package/src/components/integration-view/flow-types.tsx +2 -0
  34. package/src/components/integration-view/integration-view.tsx +148 -577
  35. package/src/components/integration-view/nodes/add-node.tsx +20 -0
  36. package/src/components/integration-view/nodes/group-node.tsx +15 -1
  37. package/src/components/integration-view/nodes/task-node.tsx +38 -10
  38. package/src/components/integration-view/temp-data/initialElements.tsx +0 -2
  39. package/src/components/integration-view/utils/mapping.ts +404 -0
  40. package/src/components/layouts/main-layout.tsx +1 -1
  41. package/src/components/layouts/root-container.tsx +2 -5
  42. package/src/components/link-cards/link-card.tsx +1 -1
  43. package/src/components/list-filter/date-filter.tsx +3 -1
  44. package/src/components/list-filter/date-range-filter.tsx +4 -2
  45. package/src/components/list-filter/list-filter.tsx +1 -1
  46. package/src/components/list-filter/select-filter.tsx +10 -4
  47. package/src/components/scheduler/schedule-drawer/schedule-details-integrations.tsx +6 -8
  48. package/src/components/scheduler/schedule-drawer/schedule-details-main.tsx +1 -1
  49. package/src/components/scheduler/schedule-drawer/schedule-details-name.tsx +1 -1
  50. package/src/components/scheduler/schedule-drawer/schedule-details.tsx +1 -1
  51. package/src/components/scheduler/schedule-drawer/schedule-drawer-group.tsx +4 -8
  52. package/src/components/scheduler/schedule-drawer/schedule-drawer-legacy.tsx +1 -1
  53. package/src/components/scheduler/schedule-drawer/schedule-drawer.tsx +2 -2
  54. package/src/components/scheduler/schedule-drawer/sortable-integration-row.tsx +1 -1
  55. package/src/components/templates/inputs/index.tsx +162 -121
  56. package/src/components/templates/templates-list/templates-list-table.tsx +2 -2
  57. package/src/components/templates/templates-list/templates-list.tsx +1 -1
  58. package/src/components/templates/types.tsx +1 -0
  59. package/src/components/templates/wizard.tsx +98 -50
  60. package/src/pages/dashboard/dashboard-list-sections.tsx +2 -2
  61. package/src/pages/execution-details/execution-details.tsx +4 -3
  62. package/src/pages/execution-details/task-execution-details.tsx +1 -1
  63. package/src/pages/execution-details/task-execution-drawer.tsx +1 -1
  64. package/src/pages/executions/executions-list/executions-list-table.tsx +1 -1
  65. package/src/pages/integration-create/integration-create.tsx +87 -45
  66. package/src/pages/integration-create/pre-creation-step.tsx +77 -5
  67. package/src/pages/integration-create/select-step.tsx +1 -1
  68. package/src/pages/integration-create/wizard-step.tsx +2 -1
  69. package/src/pages/integration-details/import-process/copy-tasks-list.tsx +2 -2
  70. package/src/pages/integration-details/import-process/copy-tasks-row.tsx +1 -1
  71. package/src/pages/integration-details/import-process/import-confirm.tsx +1 -1
  72. package/src/pages/integration-details/import-process/import-drawer.tsx +1 -1
  73. package/src/pages/integration-details/import-process/import-process.tsx +1 -1
  74. package/src/pages/integration-details/integration-details.tsx +290 -43
  75. package/src/pages/integration-details/task-drawer/add-task.tsx +65 -13
  76. package/src/pages/integration-details/task-drawer/edit-task.tsx +69 -83
  77. package/src/pages/integration-details/task-drawer/task-drawer.tsx +22 -4
  78. package/src/pages/integration-details/task-drawer/task-reducer.ts +32 -2
  79. package/src/pages/scheduler/schedules-list/schedules-list-table.tsx +1 -1
@@ -24,7 +24,7 @@ interface Props {
24
24
  readOnly?: boolean;
25
25
  }
26
26
 
27
- export default function ScheduleDetailsName(props: Props) {
27
+ export default function ScheduleDetailsName(props: Readonly<Props>) {
28
28
  const t = useTranslations("Integrate.Scheduler");
29
29
 
30
30
  const theme = useTheme();
@@ -17,7 +17,7 @@ interface Props {
17
17
  drawerOpen?: DrawerOpen;
18
18
  }
19
19
 
20
- export default function ScheduleDetails(props: Props) {
20
+ export default function ScheduleDetails(props: Readonly<Props>) {
21
21
  const theme = useTheme();
22
22
  const styles = getStyles(theme);
23
23
 
@@ -34,7 +34,7 @@ interface Props {
34
34
  handleSave?: (loading: boolean) => void;
35
35
  }
36
36
 
37
- export default function ScheduleDrawerGroup(props: Props) {
37
+ export default function ScheduleDrawerGroup(props: Readonly<Props>) {
38
38
  const theme = useTheme();
39
39
  const styles = getStyles(theme);
40
40
 
@@ -69,11 +69,7 @@ export default function ScheduleDrawerGroup(props: Props) {
69
69
  }, [props.drawerOpen]);
70
70
 
71
71
  useEffect(() => {
72
- if (
73
- props.drawerOpen.addMode &&
74
- props.detailsState &&
75
- props.detailsState.details === null
76
- ) {
72
+ if (props.drawerOpen.addMode && props?.detailsState?.details === null) {
77
73
  props.dispatchDetails({ type: DetailsActionType.INIT_BLANK });
78
74
  }
79
75
  }, []);
@@ -149,9 +145,9 @@ export default function ScheduleDrawerGroup(props: Props) {
149
145
  }
150
146
  };
151
147
 
152
- const isEdited = Object.values(props.edited).some((value) => value);
148
+ const isEdited = Object.values(props.edited).some(Boolean);
153
149
  const isError = props.detailsState?.errors
154
- ? Object.values(props.detailsState.errors).some((value) => value)
150
+ ? Object.values(props.detailsState.errors).some(Boolean)
155
151
  : false;
156
152
 
157
153
  return (
@@ -18,7 +18,7 @@ interface Props {
18
18
  handleClose: () => void;
19
19
  }
20
20
 
21
- export default function ScheduleDrawerLegacy(props: Props) {
21
+ export default function ScheduleDrawerLegacy(props: Readonly<Props>) {
22
22
  const styles = getStyles();
23
23
 
24
24
  const { data } = getProcessScheduleById.useData({
@@ -30,7 +30,7 @@ interface Props {
30
30
  handleSave?: (loading: boolean) => void;
31
31
  }
32
32
 
33
- export default function ScheduleDrawer(props: Props) {
33
+ export default function ScheduleDrawer(props: Readonly<Props>) {
34
34
  const t = useTranslations("Integrate.Scheduler");
35
35
 
36
36
  const theme = useTheme();
@@ -46,7 +46,7 @@ export default function ScheduleDrawer(props: Props) {
46
46
 
47
47
  const handleClose = (confirmClose?: boolean) => {
48
48
  if (confirmClose) {
49
- const isEdited = Object.values(edited).some((value) => value);
49
+ const isEdited = Object.values(edited).some(Boolean);
50
50
  if (isEdited && !props.drawerOpen?.addMode) {
51
51
  const confirmClose = confirm(t("unsavedChanges"));
52
52
  if (!confirmClose) return;
@@ -28,7 +28,7 @@ interface Props {
28
28
  nonScheduledMode?: boolean;
29
29
  }
30
30
 
31
- export default function SortableIntegrationRow(props: Props) {
31
+ export default function SortableIntegrationRow(props: Readonly<Props>) {
32
32
  const styles = getStyles();
33
33
 
34
34
  const { attributes, listeners, setNodeRef, transform, transition } =
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import type {
4
- GetDataDescriptionsQuery,
4
+ CheckUniqueIdentifierQuery,
5
5
  GetSourceEndpointsQuery,
6
6
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
7
7
  import { templateInputSearch } from "@evenicanpm/admin-integrate/api/templates/queries";
@@ -28,10 +28,8 @@ import {
28
28
  TableHead,
29
29
  TableRow,
30
30
  TextField,
31
- Tooltip,
32
31
  Typography,
33
32
  } from "@mui/material";
34
- import { red } from "@mui/material/colors";
35
33
  import { debounce } from "lodash";
36
34
  import { useSearchParams } from "next/navigation";
37
35
  import * as React from "react";
@@ -60,7 +58,7 @@ export function TextInput({
60
58
  error,
61
59
  helpText,
62
60
  readOnly,
63
- }: {
61
+ }: Readonly<{
64
62
  label: string;
65
63
  placeholder?: string | null;
66
64
  value: string;
@@ -68,7 +66,7 @@ export function TextInput({
68
66
  error?: string | null;
69
67
  helpText?: string | null;
70
68
  readOnly?: boolean;
71
- }) {
69
+ }>) {
72
70
  if (readOnly) return renderReadOnlyText(label, value);
73
71
 
74
72
  return (
@@ -93,7 +91,7 @@ export function NumberInput({
93
91
  error,
94
92
  helpText,
95
93
  readOnly,
96
- }: {
94
+ }: Readonly<{
97
95
  label: string;
98
96
  placeholder?: string | null;
99
97
  value: number | "" | null;
@@ -101,7 +99,7 @@ export function NumberInput({
101
99
  error?: string | null;
102
100
  helpText?: string | null;
103
101
  readOnly?: boolean;
104
- }) {
102
+ }>) {
105
103
  if (readOnly) return renderReadOnlyText(label, value);
106
104
 
107
105
  return (
@@ -127,13 +125,13 @@ export function CheckboxInput({
127
125
  setChecked,
128
126
  helpText,
129
127
  readOnly,
130
- }: {
128
+ }: Readonly<{
131
129
  label: string;
132
130
  checked: boolean;
133
131
  setChecked: (v: boolean) => void;
134
132
  helpText?: string | null;
135
133
  readOnly?: boolean;
136
- }) {
134
+ }>) {
137
135
  return (
138
136
  <Box>
139
137
  <FormControlLabel
@@ -198,18 +196,18 @@ export function SelectorInput({
198
196
  insideTable = false,
199
197
  minWidth,
200
198
  readOnly,
201
- }: {
199
+ }: Readonly<{
202
200
  fieldName: string;
203
201
  label: string;
204
202
  value: string;
205
- setValue: (v: string) => void;
203
+ setValue: (v: string | null) => void;
206
204
  helpText?: string | null;
207
205
  error?: string | null;
208
206
  options?: string[];
209
207
  insideTable?: boolean;
210
208
  minWidth?: number;
211
209
  readOnly?: boolean;
212
- }) {
210
+ }>) {
213
211
  const opts = options ?? [];
214
212
  const allowFreeText = opts.length === 0;
215
213
  const id = `selector-${fieldName}`;
@@ -231,7 +229,7 @@ export function SelectorInput({
231
229
  options={opts}
232
230
  freeSolo={allowFreeText}
233
231
  value={value ?? ""}
234
- onChange={(_e, val) => setValue((val as string) ?? "")}
232
+ onChange={(_e, val) => setValue((val as string | null) ?? "")}
235
233
  onInputChange={(_e, val) => setValue(val)}
236
234
  disabled={readOnly}
237
235
  renderInput={(params) => (
@@ -264,17 +262,20 @@ function SearchInputWrapper({
264
262
  handleFieldChange,
265
263
  clearTemplateFields,
266
264
  readOnly,
267
- sharedCountCallBack,
268
265
  isEditMode,
266
+ isCreateMode,
269
267
  setFieldsDisabled,
270
268
  templateId,
271
269
  disabledFields,
272
- }: {
270
+ templateConfig,
271
+ }: Readonly<{
273
272
  fieldName?: string;
274
- inputType: "multi-text-search" | "text-search";
273
+ inputType: "multi-text-search" | "text-search" | "text-unique-identifier";
275
274
  label: string;
276
- value: string | string[];
277
- setValue: ((v: string) => void) | ((v: string[]) => void);
275
+ value: string | string[] | null;
276
+ setValue:
277
+ | ((v: string | string[] | boolean | null, fieldName?: string) => void)
278
+ | ((v: string | string[] | boolean | null) => void);
278
279
  placeholder?: string | null;
279
280
  helpText?: string | null;
280
281
  error?: string | null;
@@ -288,6 +289,7 @@ function SearchInputWrapper({
288
289
  readOnly?: boolean;
289
290
  sharedCountCallBack?: (count: number) => void;
290
291
  isEditMode?: boolean;
292
+ isCreateMode?: boolean;
291
293
  setFieldsDisabled?: (
292
294
  templateId: string,
293
295
  fieldNames: string[],
@@ -295,20 +297,24 @@ function SearchInputWrapper({
295
297
  ) => void;
296
298
  templateId?: string;
297
299
  disabledFields?: Set<string>;
298
- }) {
300
+ templateConfig?: string;
301
+ }>) {
299
302
  const searchParams = useSearchParams();
300
303
 
301
304
  const [searchText, setSearchText] = React.useState<string>("");
302
305
  const [options, setOptions] = React.useState<SearchOption[]>([]);
303
- const [sharedCount, setSharedCount] = React.useState<number>();
304
306
 
305
307
  const { data } = templateInputSearch.useData(
306
- {
307
- input: {
308
- processTemplateId: searchParams.get("template")?.toString() ?? null,
309
- searchText: searchText,
310
- },
311
- },
308
+ inputType === "text-unique-identifier"
309
+ ? {
310
+ uniqueIdentifier: searchText,
311
+ }
312
+ : {
313
+ input: {
314
+ processTemplateId: searchParams.get("template")?.toString() ?? null,
315
+ searchText: searchText,
316
+ },
317
+ },
312
318
  queryName,
313
319
  );
314
320
 
@@ -325,25 +331,16 @@ function SearchInputWrapper({
325
331
  );
326
332
  break;
327
333
  }
328
- case "getDataDescriptions": {
329
- const typedData = data as GetDataDescriptionsQuery;
330
-
331
- const options =
332
- typedData.getDataDescriptions?.map((d) => {
333
- if (d?.dataDescription) {
334
- setSharedCount(d?.sharedCount ?? 0);
335
- sharedCountCallBack?.(d?.sharedCount ?? 0);
336
- }
337
-
338
- return {
339
- name: d?.dataDescription ?? "",
340
- templateConfig: d?.templateConfig ?? "",
341
- sharedCount: d?.sharedCount ?? 0,
342
- };
343
- }) ?? [];
344
-
345
- setOptions(options);
346
-
334
+ case "checkUniqueIdentifier": {
335
+ const typedData = data as CheckUniqueIdentifierQuery;
336
+ setValue(
337
+ (typedData.checkUniqueIdentifier?.isUnique ?? null) as
338
+ | string
339
+ | string[]
340
+ | boolean
341
+ | null,
342
+ "isUnique",
343
+ );
347
344
  break;
348
345
  }
349
346
  }
@@ -354,55 +351,6 @@ function SearchInputWrapper({
354
351
  return renderReadOnlyText(label, value);
355
352
  }
356
353
 
357
- const WarningCountIcon = ({ count }: { count: number }) => {
358
- const color = red[600];
359
-
360
- return (
361
- <svg width="26" height="24" viewBox="0 0 24 24">
362
- <polygon
363
- points="12,2 22,20 2,20"
364
- fill={color}
365
- stroke="white"
366
- strokeWidth="1"
367
- />
368
- <text
369
- x="12"
370
- y="17"
371
- fontSize="8"
372
- fontWeight="bold"
373
- fill="white"
374
- textAnchor="middle"
375
- >
376
- {count}
377
- </text>
378
- </svg>
379
- );
380
- };
381
-
382
- const SharedWarning = ({ sharedCount }: { sharedCount?: number }) => {
383
- if (!sharedCount || sharedCount <= 1 || !isEditMode) return null;
384
-
385
- return (
386
- <Box sx={{ marginTop: "8px" }}>
387
- <Tooltip
388
- title={`This data description is shared with ${sharedCount} other integration task`}
389
- arrow
390
- placement="bottom"
391
- >
392
- <Box
393
- sx={{
394
- display: "inline-flex",
395
- alignItems: "center",
396
- cursor: "pointer",
397
- }}
398
- >
399
- <WarningCountIcon count={sharedCount} />
400
- </Box>
401
- </Tooltip>
402
- </Box>
403
- );
404
- };
405
-
406
354
  return (
407
355
  <>
408
356
  {inputType === "multi-text-search" && (
@@ -418,8 +366,6 @@ function SearchInputWrapper({
418
366
  setSearchText={setSearchText}
419
367
  readOnly={readOnly}
420
368
  />
421
-
422
- <SharedWarning sharedCount={sharedCount} />
423
369
  </Box>
424
370
  )}
425
371
 
@@ -429,7 +375,9 @@ function SearchInputWrapper({
429
375
  fieldName={fieldName}
430
376
  label={label}
431
377
  value={value as string}
432
- setValue={setValue as (v: string) => void}
378
+ setValue={
379
+ setValue as (v: string | string[] | boolean | null) => void
380
+ }
433
381
  options={options}
434
382
  placeholder={placeholder}
435
383
  helpText={helpText}
@@ -442,9 +390,34 @@ function SearchInputWrapper({
442
390
  templateId={templateId}
443
391
  disabledFields={disabledFields}
444
392
  isEditMode={isEditMode}
393
+ templateConfig={templateConfig}
445
394
  />
395
+ </Box>
396
+ )}
446
397
 
447
- <SharedWarning sharedCount={sharedCount} />
398
+ {inputType === "text-unique-identifier" && (
399
+ <Box sx={{ display: "flex", gap: "10px" }}>
400
+ <TextSearchInput
401
+ fieldName={fieldName}
402
+ label={label}
403
+ value={value as string}
404
+ setValue={
405
+ setValue as (v: string | string[] | boolean | null) => void
406
+ }
407
+ options={[]}
408
+ placeholder={placeholder}
409
+ helpText={helpText}
410
+ error={error}
411
+ setSearchText={setSearchText}
412
+ handleFieldChange={handleFieldChange}
413
+ clearTemplateFields={clearTemplateFields}
414
+ readOnly={isCreateMode === false || readOnly}
415
+ setFieldsDisabled={setFieldsDisabled}
416
+ templateId={templateId}
417
+ disabledFields={disabledFields}
418
+ isEditMode={isEditMode}
419
+ templateConfig={templateConfig}
420
+ />
448
421
  </Box>
449
422
  )}
450
423
  </>
@@ -494,11 +467,12 @@ export function TextSearchInput({
494
467
  templateId,
495
468
  disabledFields,
496
469
  isEditMode,
497
- }: {
470
+ templateConfig,
471
+ }: Readonly<{
498
472
  fieldName?: string;
499
473
  label: string;
500
474
  value: string;
501
- setValue: (v: string) => void;
475
+ setValue: (v: string | string[] | boolean | null) => void;
502
476
  options: SearchOption[];
503
477
  placeholder?: string | null;
504
478
  helpText?: string | null;
@@ -519,7 +493,8 @@ export function TextSearchInput({
519
493
  templateId?: string;
520
494
  disabledFields?: Set<string>;
521
495
  isEditMode?: boolean;
522
- }) {
496
+ templateConfig?: string;
497
+ }>) {
523
498
  const searchParams = useSearchParams();
524
499
  const [selected, setSelected] = React.useState<string | null>(value ?? null);
525
500
 
@@ -550,6 +525,16 @@ export function TextSearchInput({
550
525
  const option = options.find((o) => o?.name === selected);
551
526
  if (option) {
552
527
  try {
528
+ const config = JSON.parse(option.templateConfig);
529
+
530
+ if (
531
+ config &&
532
+ templateConfig //&&
533
+ //config.dataDescription === inputConfig.dataDescription
534
+ ) {
535
+ option.templateConfig = templateConfig;
536
+ }
537
+
553
538
  // Always apply config (both edit and non-edit modes)
554
539
  applyTemplateConfig(option, handleFieldChange);
555
540
  appliedOptionRef.current = option.name ?? null;
@@ -690,7 +675,7 @@ export function MultiTextSearchInput({
690
675
  error,
691
676
  setSearchText,
692
677
  readOnly,
693
- }: {
678
+ }: Readonly<{
694
679
  label: string;
695
680
  value: string[];
696
681
  setValue: (v: string[]) => void;
@@ -700,7 +685,7 @@ export function MultiTextSearchInput({
700
685
  error?: string | null;
701
686
  setSearchText: React.Dispatch<React.SetStateAction<string>>;
702
687
  readOnly?: boolean;
703
- }) {
688
+ }>) {
704
689
  const [input, setInput] = React.useState<string>("");
705
690
 
706
691
  const debouncedSetSearchText = React.useMemo(
@@ -719,8 +704,6 @@ export function MultiTextSearchInput({
719
704
  _e: React.SyntheticEvent,
720
705
  val: string[],
721
706
  ) => {
722
- console.log("onSelect log", val);
723
-
724
707
  setValue(val);
725
708
  debouncedSetSearchText("");
726
709
  };
@@ -763,13 +746,13 @@ export function InputTable({
763
746
  schemas,
764
747
  tableError,
765
748
  readOnly,
766
- }: {
749
+ }: Readonly<{
767
750
  rows: Array<Record<string, any>>;
768
751
  setRows: (rows: Array<Record<string, any>>) => void;
769
752
  schemas: ProcessTemplateInputSchema[];
770
753
  tableError: string | null;
771
754
  readOnly?: boolean;
772
- }) {
755
+ }>) {
773
756
  const ordered = React.useMemo(
774
757
  () => sortBy<ProcessTemplateInputSchema>(schemas),
775
758
  [schemas],
@@ -820,7 +803,7 @@ export function InputTable({
820
803
  </TableHead>
821
804
  <TableBody>
822
805
  {(rows ?? []).map((r: Record<string, any>, i: number) => (
823
- <TableRow key={i}>
806
+ <TableRow key={`table-row-${i + 1}`}>
824
807
  {ordered.map((s: ProcessTemplateInputSchema) => {
825
808
  const columnKey = s.fieldKey ?? s.label;
826
809
  const cell = columnKey ? r[columnKey] : "";
@@ -924,9 +907,11 @@ function renderFormControl({
924
907
  readOnly,
925
908
  sharedCount,
926
909
  isEditMode,
910
+ isCreateMode,
927
911
  disabledFields,
928
912
  setFieldsDisabled,
929
- }: {
913
+ templateConfig,
914
+ }: Readonly<{
930
915
  input: ProcessTemplateInput;
931
916
  templateId: string;
932
917
  values: FormState;
@@ -940,21 +925,25 @@ function renderFormControl({
940
925
  readOnly?: boolean;
941
926
  sharedCount?: (count: number) => void;
942
927
  isEditMode?: boolean;
928
+ isCreateMode?: boolean;
943
929
  disabledFields?: Set<string>;
944
930
  setFieldsDisabled?: (
945
931
  templateId: string,
946
932
  fieldNames: string[],
947
933
  disabled: boolean,
948
934
  ) => void;
949
- }) {
935
+ templateConfig?: string;
936
+ }>) {
950
937
  const k = templateFieldKey(templateId, input.fieldName ?? "");
951
938
  const err = errors[k] ?? null;
952
939
  const isFieldDisabled = disabledFields?.has(k) ?? false;
953
940
  const finalReadOnly = readOnly || isFieldDisabled;
954
941
 
955
- console.log("isFieldDisabled", finalReadOnly);
956
-
957
- if (input.inputType === "hidden" || input.inputType === "hidden-number") {
942
+ if (
943
+ input.inputType === "hidden" ||
944
+ input.inputType === "hidden-number" ||
945
+ input.inputType === "hidden-number-or-null"
946
+ ) {
958
947
  return null;
959
948
  }
960
949
 
@@ -1013,7 +1002,7 @@ function renderFormControl({
1013
1002
  queryName={queryName}
1014
1003
  label={input.label ?? ""}
1015
1004
  value={(values[k] as string[]) ?? []}
1016
- setValue={(v: string[]) =>
1005
+ setValue={(v: string | string[] | boolean | null) =>
1017
1006
  handleFieldChange(templateId, input.fieldName ?? "", v)
1018
1007
  }
1019
1008
  placeholder={input.placeholder ?? ""}
@@ -1027,6 +1016,7 @@ function renderFormControl({
1027
1016
  templateId={templateId}
1028
1017
  disabledFields={disabledFields}
1029
1018
  fieldName={input.fieldName ?? ""}
1019
+ templateConfig={templateConfig}
1030
1020
  />
1031
1021
  );
1032
1022
  }
@@ -1039,7 +1029,7 @@ function renderFormControl({
1039
1029
  queryName={queryName}
1040
1030
  label={input.label ?? ""}
1041
1031
  value={(values[k] as string) ?? ""}
1042
- setValue={(v: string) =>
1032
+ setValue={(v: string | string[] | boolean | null) =>
1043
1033
  handleFieldChange(templateId, input.fieldName ?? "", v)
1044
1034
  }
1045
1035
  placeholder={input.placeholder ?? ""}
@@ -1054,6 +1044,43 @@ function renderFormControl({
1054
1044
  templateId={templateId}
1055
1045
  disabledFields={disabledFields}
1056
1046
  fieldName={input.fieldName ?? ""}
1047
+ templateConfig={templateConfig}
1048
+ />
1049
+ );
1050
+ }
1051
+
1052
+ if (input.inputType === "text-unique-identifier") {
1053
+ const queryName = parseQueryName(input.queryName ?? "");
1054
+ return (
1055
+ <SearchInputWrapper
1056
+ inputType="text-unique-identifier"
1057
+ queryName={queryName}
1058
+ label={input.label ?? ""}
1059
+ value={(values[k] as string) ?? ""}
1060
+ setValue={(
1061
+ v: string | string[] | boolean | null,
1062
+ fieldName?: string,
1063
+ ) => {
1064
+ if (fieldName) {
1065
+ handleFieldChange(templateId, fieldName, v);
1066
+ } else {
1067
+ handleFieldChange(templateId, input.fieldName ?? "", v);
1068
+ }
1069
+ }}
1070
+ placeholder={input.placeholder ?? ""}
1071
+ helpText={input.helpText ?? ""}
1072
+ error={err}
1073
+ handleFieldChange={handleFieldChange}
1074
+ clearTemplateFields={clearTemplateFields}
1075
+ readOnly={readOnly}
1076
+ sharedCountCallBack={(count) => sharedCount?.(count)}
1077
+ isEditMode={isEditMode}
1078
+ isCreateMode={isCreateMode}
1079
+ setFieldsDisabled={setFieldsDisabled}
1080
+ templateId={templateId}
1081
+ disabledFields={disabledFields}
1082
+ fieldName={input.fieldName ?? ""}
1083
+ templateConfig={templateConfig}
1057
1084
  />
1058
1085
  );
1059
1086
  }
@@ -1179,9 +1206,11 @@ export default function PageBody({
1179
1206
  readOnly,
1180
1207
  sharedCount,
1181
1208
  isEditMode,
1209
+ isCreateMode,
1182
1210
  disabledFields,
1183
1211
  setFieldsDisabled,
1184
- }: {
1212
+ templateConfig,
1213
+ }: Readonly<{
1185
1214
  templateId: string;
1186
1215
  page: ProcessTemplatePage;
1187
1216
  values: FormState;
@@ -1194,6 +1223,7 @@ export default function PageBody({
1194
1223
  clearTemplateFields: (templateId: string) => void;
1195
1224
  readOnly?: boolean;
1196
1225
  isEditMode?: boolean;
1226
+ isCreateMode?: boolean;
1197
1227
  sharedCount?: (count: number) => void;
1198
1228
  disabledFields?: Set<string>;
1199
1229
  setFieldsDisabled?: (
@@ -1201,12 +1231,15 @@ export default function PageBody({
1201
1231
  fieldNames: string[],
1202
1232
  disabled: boolean,
1203
1233
  ) => void;
1204
- }) {
1234
+ templateConfig?: string;
1235
+ }>) {
1205
1236
  React.useEffect(
1206
1237
  function ensureHiddenDefaults() {
1207
1238
  const hiddenInputs = page.inputs?.filter(
1208
1239
  (i: ProcessTemplateInput | null) =>
1209
- i?.inputType === "hidden" || i?.inputType === "hidden-number",
1240
+ i?.inputType === "hidden" ||
1241
+ i?.inputType === "hidden-number" ||
1242
+ i?.inputType === "hidden-number-or-null",
1210
1243
  );
1211
1244
 
1212
1245
  if (hiddenInputs) {
@@ -1228,7 +1261,9 @@ export default function PageBody({
1228
1261
  input?.fieldName ?? "",
1229
1262
  input?.inputType === "hidden-number"
1230
1263
  ? (0 as FieldValue)
1231
- : ("" as FieldValue),
1264
+ : input?.inputType === "hidden-number-or-null"
1265
+ ? null
1266
+ : ("" as FieldValue),
1232
1267
  );
1233
1268
  break;
1234
1269
  }
@@ -1248,7 +1283,7 @@ export default function PageBody({
1248
1283
  {arrangedInputs.map((ai: InputRow, idx: number) => {
1249
1284
  if (ai.type === "full") {
1250
1285
  return (
1251
- <Box key={`full-${idx}`} sx={{ width: "100%" }}>
1286
+ <Box key={`full-${idx + 1}`} sx={{ width: "100%" }}>
1252
1287
  {renderFormControl({
1253
1288
  input: ai.item,
1254
1289
  templateId,
@@ -1259,8 +1294,10 @@ export default function PageBody({
1259
1294
  readOnly,
1260
1295
  sharedCount,
1261
1296
  isEditMode,
1297
+ isCreateMode,
1262
1298
  disabledFields,
1263
1299
  setFieldsDisabled,
1300
+ templateConfig,
1264
1301
  })}
1265
1302
  </Box>
1266
1303
  );
@@ -1269,7 +1306,7 @@ export default function PageBody({
1269
1306
  const [i, j] = ai.items;
1270
1307
  return (
1271
1308
  <Box
1272
- key={`pair-${idx}`}
1309
+ key={`pair-${idx + 1}`}
1273
1310
  sx={{
1274
1311
  display: "grid",
1275
1312
  gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" },
@@ -1289,8 +1326,10 @@ export default function PageBody({
1289
1326
  readOnly,
1290
1327
  sharedCount,
1291
1328
  isEditMode,
1329
+ isCreateMode,
1292
1330
  disabledFields,
1293
1331
  setFieldsDisabled,
1332
+ templateConfig,
1294
1333
  })}
1295
1334
  </Box>
1296
1335
  <Box>
@@ -1304,8 +1343,10 @@ export default function PageBody({
1304
1343
  readOnly,
1305
1344
  sharedCount,
1306
1345
  isEditMode,
1346
+ isCreateMode,
1307
1347
  disabledFields,
1308
1348
  setFieldsDisabled,
1349
+ templateConfig,
1309
1350
  })}
1310
1351
  </Box>
1311
1352
  </Box>