@evenicanpm/admin-integrate 1.3.0 → 1.6.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
@@ -1,15 +1,23 @@
1
1
  import type {
2
+ ConfigExport,
3
+ ConfigurationMergeMutation,
4
+ ConfigurationMergeMutationVariables,
2
5
  FilterQueryInput,
3
6
  GetProcessTemplatesQuery,
4
7
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
8
+ import { processConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
5
9
  import { getProcessTemplates } from "@evenicanpm/admin-integrate/api/templates/queries";
6
10
  import type { Head } from "@evenicanpm/admin-integrate/components/data-table/table-header";
7
11
  import { Wizard } from "@evenicanpm/admin-integrate/components/templates";
8
12
  import TemplatesList from "@evenicanpm/admin-integrate/components/templates/templates-list";
9
- import type { ProcessConfigMerge } from "@evenicanpm/admin-integrate/components/templates/types";
13
+ import type {
14
+ Metadata,
15
+ ProcessConfigMerge,
16
+ } from "@evenicanpm/admin-integrate/components/templates/types";
17
+ import { removeTemplateConfig } from "@evenicanpm/admin-integrate/components/templates/wizard";
10
18
  import { Box, Typography, useTheme } from "@mui/material";
11
19
  import { useTranslations } from "next-intl";
12
- import { useState } from "react";
20
+ import { useEffect, useState } from "react";
13
21
  import {
14
22
  type TaskAction,
15
23
  TaskActionType,
@@ -19,15 +27,18 @@ import {
19
27
  interface Props {
20
28
  taskState: TaskState;
21
29
  dispatch: React.Dispatch<TaskAction>;
30
+ handleUpdateConfig: (newConfig: ConfigExport) => void;
22
31
  }
23
32
 
24
33
  // steps:
25
34
  // - 0: choose template from list
26
35
  // - 1: wizard (finish --> update flowchart view with added task, close drawer)
27
- export default function AddTask(props: Props) {
36
+ export default function AddTask(props: Readonly<Props>) {
28
37
  const t = useTranslations("Integrate");
29
38
  const theme = useTheme();
30
39
 
40
+ const processConfigMergeMutation = processConfigMerge();
41
+
31
42
  const heading: Head[] = [
32
43
  {
33
44
  id: "name",
@@ -44,8 +55,45 @@ export default function AddTask(props: Props) {
44
55
  },
45
56
  ];
46
57
 
47
- const [processConfigMerge, setProcessConfigMerge] =
58
+ const [processConfigMergeInput, setProcessConfigMergeInput] =
48
59
  useState<ProcessConfigMerge | null>(null);
60
+
61
+ useEffect(() => {
62
+ if (processConfigMergeInput) {
63
+ const input =
64
+ removeTemplateConfig(processConfigMergeInput?.input) ||
65
+ ({} as ConfigurationMergeMutationVariables);
66
+ processConfigMergeMutation.mutate(
67
+ {
68
+ input: input,
69
+ },
70
+ {
71
+ onSuccess: async (data: ConfigurationMergeMutation) => {
72
+ if (data.configurationMerge?.Processes?.[0]?.ProcessTasks)
73
+ data.configurationMerge.Processes[0].ProcessTasks =
74
+ data.configurationMerge.Processes[0].ProcessTasks.map(
75
+ (item, index) => ({
76
+ ...item,
77
+ Sort:
78
+ (item?.Sort ?? index) +
79
+ (props.taskState.sort as number) -
80
+ 1,
81
+ ParallelProcessingGroup:
82
+ props.taskState.parallelProcessingGroup,
83
+ }),
84
+ );
85
+ props.handleUpdateConfig(data?.configurationMerge as ConfigExport);
86
+ },
87
+ onError: (error) => {
88
+ console.error("Update failed:", error);
89
+ },
90
+ },
91
+ );
92
+ }
93
+ }, [processConfigMergeInput]);
94
+
95
+ // const [processConfigMerge, setProcessConfigMerge] =
96
+ // useState<ProcessConfigMerge | null>(null);
49
97
  const [processTemplateId, setProcessTemplateId] = useState<string | null>(
50
98
  null,
51
99
  );
@@ -97,17 +145,21 @@ export default function AddTask(props: Props) {
97
145
  handleRedirect={handleRedirect}
98
146
  />
99
147
  )}
100
- {props.taskState.step === 1 && processTemplateId && (
148
+ {props.taskState.step === 1 && (
101
149
  <Wizard
102
150
  // todo: should be set to metadata returned from api query for integration details
103
- metadata={{
104
- name: "",
105
- code: "",
106
- parallelProcessingGroup: 1,
107
- sort: 1,
108
- }}
109
- setProcessConfigMerge={setProcessConfigMerge}
110
- processTemplateId={processTemplateId}
151
+ metadata={
152
+ {
153
+ name: "", // name/code of parent Process is not relevant when editing a single task.
154
+ code: "",
155
+ parallelProcessingGroup: props.taskState
156
+ .parallelProcessingGroup as number,
157
+ sort: props.taskState.sort as number,
158
+ } as Metadata
159
+ }
160
+ setProcessConfigMerge={setProcessConfigMergeInput}
161
+ processTemplateId={processTemplateId ?? undefined}
162
+ isCreateMode
111
163
  handleBack={handleBack}
112
164
  handleFinish={handleNext}
113
165
  />
@@ -2,14 +2,9 @@ import type {
2
2
  ConfigExport,
3
3
  ConfigurationMergeMutation,
4
4
  ConfigurationMergeMutationVariables,
5
- GetProcessTaskByIdQuery,
6
5
  } from "@evenicanpm/admin-core/api/e4/graphqlRequestSdk";
7
6
  import { processConfigMerge } from "@evenicanpm/admin-integrate/api/process-config/mutation";
8
- import { getProcessTaskById } from "@evenicanpm/admin-integrate/api/process-task/queries";
9
- import {
10
- Loading,
11
- TitleEdit,
12
- } from "@evenicanpm/admin-integrate/components/core";
7
+ import { TitleEdit } from "@evenicanpm/admin-integrate/components/core";
13
8
  import { Wizard } from "@evenicanpm/admin-integrate/components/templates";
14
9
  import type {
15
10
  Metadata,
@@ -17,7 +12,13 @@ import type {
17
12
  } from "@evenicanpm/admin-integrate/components/templates/types";
18
13
  import { removeTemplateConfig } from "@evenicanpm/admin-integrate/components/templates/wizard";
19
14
  import ReportProblemIcon from "@mui/icons-material/ReportProblem";
20
- import { Box, Stack, Typography, useTheme } from "@mui/material";
15
+ import {
16
+ Box,
17
+ CircularProgress,
18
+ Stack,
19
+ Typography,
20
+ useTheme,
21
+ } from "@mui/material";
21
22
  import { useEffect, useState } from "react";
22
23
  import {
23
24
  type TaskAction,
@@ -30,9 +31,10 @@ interface Props {
30
31
  dispatch: React.Dispatch<TaskAction>;
31
32
  handleUpdateConfig: (newConfig: ConfigExport) => void;
32
33
  editable?: boolean;
34
+ templateConfigInput?: any | null;
33
35
  }
34
36
 
35
- export default function EditTask(props: Props) {
37
+ export default function EditTask(props: Readonly<Props>) {
36
38
  const theme = useTheme();
37
39
 
38
40
  const processConfigMergeMutation = processConfigMerge();
@@ -49,30 +51,9 @@ export default function EditTask(props: Props) {
49
51
  props.dispatch(action);
50
52
  };
51
53
 
52
- const { data, isLoading } = getProcessTaskById.useData({
53
- id: props.taskState.processTaskId as string,
54
- });
55
-
56
- const [metadata, setMetadata] = useState<Metadata | null>(null);
57
- const [name, setName] = useState<string>("");
54
+ const [_name, setName] = useState<string>("");
58
55
  const [sharedCount, setSharedCount] = useState<number>();
59
56
 
60
- useEffect(() => {
61
- const typedData = data as GetProcessTaskByIdQuery;
62
-
63
- if (typedData?.processTaskById) {
64
- setMetadata({
65
- name: "", // name/code of parent Process is not relevant when editing a single task.
66
- code: "",
67
- parallelProcessingGroup: typedData.processTaskById
68
- .parallelProcessingGroup as number,
69
- sort: typedData.processTaskById.sort as number,
70
- });
71
-
72
- setName(typedData?.processTaskById?.name as string);
73
- }
74
- }, [data]);
75
-
76
57
  const handleNameEdit = (input: string) => {
77
58
  setName(input);
78
59
 
@@ -101,74 +82,79 @@ export default function EditTask(props: Props) {
101
82
  }
102
83
  }, [processConfigMergeInput]);
103
84
 
104
- if (isLoading) {
105
- return (
106
- <Box sx={{ padding: theme.spacing(10, 3) }}>
107
- <Loading />
108
- </Box>
109
- );
110
- }
111
-
112
- const templateConfig = (data as GetProcessTaskByIdQuery)?.processTaskById
113
- ?.endpoint?.templateConfig;
114
-
115
85
  return (
116
86
  <>
117
- {props.taskState.step === 0 && metadata && (
118
- <Box sx={{ marginBottom: theme.spacing(1) }}>
119
- <Stack
120
- direction="row"
121
- spacing={1}
122
- sx={{ minHeight: theme.spacing(7) }}
123
- >
124
- <TitleEdit
125
- title={name}
126
- onConfirm={handleNameEdit}
127
- fullWidth
128
- variant="h6"
129
- readOnly={!props.editable}
130
- />
131
- </Stack>
132
- {sharedCount !== undefined && sharedCount > 1 && props?.editable && (
133
- <Typography
134
- variant="body2"
135
- color="error"
136
- sx={{
137
- display: "flex",
138
- alignItems: "center",
139
- gap: "5px",
140
- fontSize: "12px",
141
- }}
87
+ {props.taskState.step === 0 &&
88
+ !!props.taskState.sort &&
89
+ !!props.taskState.parallelProcessingGroup && (
90
+ <Box sx={{ marginBottom: theme.spacing(1) }}>
91
+ <Stack
92
+ direction="row"
93
+ spacing={1}
94
+ sx={{ minHeight: theme.spacing(7) }}
142
95
  >
143
- <ReportProblemIcon color="error" sx={{ fontSize: "18px" }} />{" "}
144
- Changes to this integration tasks will affect other tasks sharing
145
- the same <strong>Data Description</strong>
146
- </Typography>
147
- )}
148
- </Box>
149
- )}
96
+ <TitleEdit
97
+ title={props?.taskState?.name || "Edit Task"}
98
+ onConfirm={handleNameEdit}
99
+ fullWidth
100
+ variant="h6"
101
+ //readOnly={!props.editable}
102
+ readOnly={true}
103
+ />
104
+ </Stack>
105
+ {sharedCount !== undefined &&
106
+ sharedCount > 1 &&
107
+ props?.editable && (
108
+ <Typography
109
+ variant="body2"
110
+ color="error"
111
+ sx={{
112
+ display: "flex",
113
+ alignItems: "center",
114
+ gap: "5px",
115
+ fontSize: "12px",
116
+ }}
117
+ >
118
+ <ReportProblemIcon color="error" sx={{ fontSize: "18px" }} />{" "}
119
+ Changes to this integration tasks will affect other tasks
120
+ sharing the same <strong>Data Description</strong>
121
+ </Typography>
122
+ )}
123
+ </Box>
124
+ )}
150
125
  {props.taskState.step === 0 &&
151
- /*(data as GetProcessTaskByIdQuery).processTaskById?.endpoint
152
- ?.templateConfig &&*/
153
- metadata && (
126
+ // (data as GetProcessTaskByIdQuery)?.processTaskById?.endpoint
127
+ // ?.templateConfig &&
128
+ !!props.taskState.parallelProcessingGroup &&
129
+ !!props.taskState.sort && (
154
130
  <Wizard
155
- metadata={metadata as Metadata}
131
+ metadata={
132
+ {
133
+ //name: "", // name/code of parent Process is not relevant when editing a single task.
134
+ //code: "",
135
+ parallelProcessingGroup: props.taskState
136
+ .parallelProcessingGroup as number,
137
+ sort: props.taskState.sort as number,
138
+ processTaskId: props?.taskState?.processTaskId
139
+ ? Number.parseInt(props.taskState.processTaskId)
140
+ : null,
141
+ } as Metadata
142
+ }
156
143
  setProcessConfigMerge={setProcessConfigMergeInput}
157
144
  handleBack={handleBack}
158
145
  handleFinish={handleFinish}
159
- templateConfig={templateConfig}
160
- processTemplateId={
161
- (data as GetProcessTaskByIdQuery).processTaskById?.endpoint
162
- ?.processTemplate?.id as string
163
- }
146
+ templateConfig={props.taskState.templateConfig}
147
+ processTemplateId={props.taskState.processTemplateId as string}
164
148
  isEditMode
149
+ isCreateMode={false}
165
150
  disableBackToTemplates
166
151
  readOnly={!props.editable}
167
152
  sharedCount={(count: number) => setSharedCount(count)}
168
153
  />
169
154
  )}
170
155
  {props.taskState.step === 1 && (
171
- <Typography>{JSON.stringify(processConfigMergeInput)}</Typography>
156
+ // <Typography>{JSON.stringify(processConfigMergeInput)}</Typography>
157
+ <CircularProgress sx={{ margin: theme.spacing(10, 0) }} />
172
158
  )}
173
159
  </>
174
160
  );
@@ -24,8 +24,11 @@ import {
24
24
 
25
25
  interface Props extends DrawerProps {
26
26
  taskState: TaskState;
27
+ renderKey: any;
27
28
  dispatch: React.Dispatch<TaskAction>;
28
- handleUpdateConfig: (newConfig: ConfigExport) => void;
29
+ handleUpdateConfig?: (newConfig: ConfigExport) => void;
30
+ templateConfigInput?: any | null;
31
+ config: ConfigExport;
29
32
  }
30
33
 
31
34
  const Drawer = styled(MuiDrawer)({
@@ -40,10 +43,11 @@ const Drawer = styled(MuiDrawer)({
40
43
 
41
44
  export default function TaskDrawer({
42
45
  taskState,
46
+ renderKey,
43
47
  dispatch,
44
48
  handleUpdateConfig,
45
49
  ...props
46
- }: Props) {
50
+ }: Readonly<Props>) {
47
51
  const t = useTranslations("Integrate.IntegrationDetails.TaskDrawer");
48
52
 
49
53
  const theme = useTheme();
@@ -103,7 +107,16 @@ export default function TaskDrawer({
103
107
  </DrawerButtons>
104
108
  <Box sx={styles.main}>
105
109
  {taskState.mode === TaskMode.ADD && (
106
- <AddTask taskState={taskState} dispatch={dispatch} />
110
+ <AddTask
111
+ taskState={taskState}
112
+ dispatch={dispatch}
113
+ handleUpdateConfig={(newConfig: ConfigExport) => {
114
+ setEditable(false);
115
+ if (handleUpdateConfig) {
116
+ handleUpdateConfig(newConfig);
117
+ }
118
+ }}
119
+ />
107
120
  )}
108
121
  {taskState.mode === TaskMode.EDIT && (
109
122
  <EditTask
@@ -111,7 +124,12 @@ export default function TaskDrawer({
111
124
  taskState={taskState}
112
125
  dispatch={dispatch}
113
126
  editable={editable}
114
- handleUpdateConfig={handleUpdateConfig}
127
+ handleUpdateConfig={(newConfig: ConfigExport) => {
128
+ setEditable(false);
129
+ if (handleUpdateConfig) {
130
+ handleUpdateConfig(newConfig);
131
+ }
132
+ }}
115
133
  />
116
134
  )}
117
135
  </Box>
@@ -18,6 +18,11 @@ export interface TaskAction {
18
18
 
19
19
  export interface EditAction extends TaskAction {
20
20
  processTaskId: string;
21
+ templateConfig?: string;
22
+ sort?: number;
23
+ parallelProcessingGroup?: number;
24
+ processTemplateId?: string;
25
+ name?: string;
21
26
  }
22
27
 
23
28
  export interface TaskState {
@@ -25,6 +30,11 @@ export interface TaskState {
25
30
  mode: TaskMode;
26
31
  step: number | null;
27
32
  processTaskId?: string | null;
33
+ templateConfig?: string;
34
+ sort?: number;
35
+ parallelProcessingGroup?: number;
36
+ processTemplateId?: string;
37
+ name?: string;
28
38
  }
29
39
 
30
40
  export function taskReducer(state: TaskState, action: TaskAction): TaskState {
@@ -43,6 +53,9 @@ export function taskReducer(state: TaskState, action: TaskAction): TaskState {
43
53
  mode: TaskMode.ADD,
44
54
  step: 0,
45
55
  processTaskId: null,
56
+ sort: (action as EditAction).sort,
57
+ parallelProcessingGroup: (action as EditAction).parallelProcessingGroup,
58
+ name: undefined,
46
59
  };
47
60
  }
48
61
  case TaskActionType.OPEN_EDIT: {
@@ -51,18 +64,35 @@ export function taskReducer(state: TaskState, action: TaskAction): TaskState {
51
64
  mode: TaskMode.EDIT,
52
65
  step: 0,
53
66
  processTaskId: (action as EditAction).processTaskId,
67
+ templateConfig: (action as EditAction).templateConfig,
68
+ sort: (action as EditAction).sort,
69
+ parallelProcessingGroup: (action as EditAction).parallelProcessingGroup,
70
+ processTemplateId: (action as EditAction).processTemplateId,
71
+ name: (action as EditAction).name,
54
72
  };
55
73
  }
56
74
  case TaskActionType.INCREMENT_STEP: {
75
+ let step = null;
76
+
77
+ if (state.step !== null) {
78
+ step = state.step + 1;
79
+ }
80
+
57
81
  return {
58
82
  ...state,
59
- step: state.step !== null ? state.step + 1 : null,
83
+ step,
60
84
  };
61
85
  }
62
86
  case TaskActionType.DECREMENT_STEP: {
87
+ let step = null;
88
+
89
+ if (state.step !== null) {
90
+ step = Math.max(state.step - 1, 0);
91
+ }
92
+
63
93
  return {
64
94
  ...state,
65
- step: state.step !== null ? Math.max(state.step - 1, 0) : null,
95
+ step,
66
96
  };
67
97
  }
68
98
  default: {
@@ -16,7 +16,7 @@ interface Props {
16
16
  setDrawerOpen: React.Dispatch<React.SetStateAction<DrawerOpen | null>>;
17
17
  }
18
18
 
19
- export default function SchedulesListTable(props: Props) {
19
+ export default function SchedulesListTable(props: Readonly<Props>) {
20
20
  const handleRequestSort = (property: string) => {
21
21
  const current = props.input.sort;
22
22
  if (property === current) {