@evenicanpm/admin-integrate 1.1.0 → 1.2.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 (101) hide show
  1. package/documents/ProcessSchedule/fragments.ts +24 -0
  2. package/documents/ProcessSchedule/read.ts +12 -0
  3. package/documents/ProcessScheduleGroup/fragments.ts +29 -0
  4. package/documents/ProcessScheduleGroup/read.ts +12 -0
  5. package/documents/ScheduledProcess/fragments.ts +24 -0
  6. package/documents/ScheduledProcess/list.ts +27 -0
  7. package/package.json +21 -17
  8. package/src/api/dashboard/queries/get-process-executions.query.ts +33 -36
  9. package/src/api/dashboard/queries/get-process-executions.server.ts +4 -4
  10. package/src/api/scheduler/queries/get-process-schedule-group-details.query.ts +45 -0
  11. package/src/api/scheduler/queries/get-process-schedule-group-details.server.ts +14 -0
  12. package/src/api/scheduler/queries/get-process-schedule.query.ts +45 -0
  13. package/src/api/scheduler/queries/get-process-schedule.server.ts +14 -0
  14. package/src/api/scheduler/queries/get-scheduled-processes.query.ts +45 -0
  15. package/src/api/scheduler/queries/get-scheduled-processes.server.ts +11 -0
  16. package/src/api/scheduler/queries/index.ts +3 -0
  17. package/src/components/breadcrumbs/breadcrumbs.tsx +23 -26
  18. package/src/components/breadcrumbs/index.ts +1 -1
  19. package/src/components/breadcrumbs/types.tsx +4 -0
  20. package/src/components/button/outlined-icon-button.tsx +26 -38
  21. package/src/components/core/date-time-popover.tsx +32 -0
  22. package/src/components/core/edited-typography.tsx +20 -0
  23. package/src/components/core/index.ts +3 -0
  24. package/src/components/core/loading.tsx +6 -6
  25. package/src/components/core/title-edit.tsx +122 -0
  26. package/src/components/dashboard-list/dashboard-list-row.tsx +114 -115
  27. package/src/components/dashboard-list/dashboard-list.tsx +119 -119
  28. package/src/components/data-table/table-header.tsx +85 -81
  29. package/src/components/data-table/table-pagination.tsx +27 -27
  30. package/src/components/data-table/table-row.tsx +14 -14
  31. package/src/components/data-table/table-skeleton.tsx +34 -34
  32. package/src/components/execution/execution-filter.ts +22 -22
  33. package/src/components/execution/execution-status-icon.tsx +16 -17
  34. package/src/components/execution/execution-tag.tsx +81 -80
  35. package/src/components/footer/footer.tsx +34 -34
  36. package/src/components/header/dashboard-list-header.tsx +64 -63
  37. package/src/components/header/execution-details-header.tsx +102 -129
  38. package/src/components/header/header.tsx +27 -27
  39. package/src/components/header/index.ts +1 -0
  40. package/src/components/header/integration-details-header.tsx +99 -0
  41. package/src/components/icons/up-down.tsx +15 -15
  42. package/src/components/integration-view/edges/default-edge.tsx +18 -17
  43. package/src/components/integration-view/elk-layout-options.ts +26 -26
  44. package/src/components/integration-view/elk-types.ts +16 -12
  45. package/src/components/integration-view/flow-types.tsx +5 -5
  46. package/src/components/integration-view/integration-view.tsx +132 -130
  47. package/src/components/integration-view/nodes/base-node.tsx +50 -0
  48. package/src/components/integration-view/nodes/connection-node.tsx +8 -8
  49. package/src/components/integration-view/nodes/entry-node.tsx +8 -8
  50. package/src/components/integration-view/nodes/group-node.tsx +47 -6
  51. package/src/components/integration-view/nodes/task-node.tsx +58 -13
  52. package/src/components/integration-view/temp-data/initialElements.tsx +224 -0
  53. package/src/components/integration-view/types.ts +6 -6
  54. package/src/components/layouts/main-layout.tsx +13 -13
  55. package/src/components/layouts/root-container.tsx +25 -25
  56. package/src/components/link-cards/link-card.tsx +23 -23
  57. package/src/components/link-cards/styles.ts +15 -15
  58. package/src/components/list-filter/date-filter.tsx +41 -45
  59. package/src/components/list-filter/date-range-filter.tsx +78 -77
  60. package/src/components/list-filter/list-filter-types.ts +38 -38
  61. package/src/components/list-filter/list-filter.tsx +363 -354
  62. package/src/components/list-filter/multi-select-filter.tsx +94 -95
  63. package/src/components/list-filter/select-filter.tsx +67 -64
  64. package/src/components/scheduler/day-selector.tsx +174 -0
  65. package/src/components/scheduler/day-tag.tsx +73 -0
  66. package/src/components/scheduler/index.ts +4 -0
  67. package/src/components/scheduler/schedule-filter.ts +25 -0
  68. package/src/components/scheduler/schedule-icon.tsx +87 -0
  69. package/src/components/scheduler/scheduler-types.ts +40 -0
  70. package/src/hooks/use-breadcrumbs.ts +31 -31
  71. package/src/hooks/use-recurrence.tsx +13 -0
  72. package/src/hooks/use-timestamp.tsx +21 -21
  73. package/src/pages/dashboard/dashboard-link-cards.tsx +99 -99
  74. package/src/pages/dashboard/dashboard-list-sections.tsx +130 -125
  75. package/src/pages/dashboard/dashboard.tsx +6 -6
  76. package/src/pages/execution-details/execution-details.tsx +23 -29
  77. package/src/pages/executions/executions-list/executions-list-row.tsx +101 -104
  78. package/src/pages/executions/executions-list/executions-list-table.tsx +45 -53
  79. package/src/pages/executions/executions-list/executions-list.tsx +219 -212
  80. package/src/pages/executions/executions.tsx +67 -72
  81. package/src/pages/integrations/integrations.tsx +17 -25
  82. package/src/pages/scheduler/schedule-drawer/edited/edited-types.ts +17 -0
  83. package/src/pages/scheduler/schedule-drawer/edited/index.ts +1 -0
  84. package/src/pages/scheduler/schedule-drawer/index.ts +1 -0
  85. package/src/pages/scheduler/schedule-drawer/schedule-details-integrations.tsx +227 -0
  86. package/src/pages/scheduler/schedule-drawer/schedule-details-main.tsx +292 -0
  87. package/src/pages/scheduler/schedule-drawer/schedule-details-name.tsx +77 -0
  88. package/src/pages/scheduler/schedule-drawer/schedule-details-skeleton.tsx +64 -0
  89. package/src/pages/scheduler/schedule-drawer/schedule-details.tsx +42 -0
  90. package/src/pages/scheduler/schedule-drawer/schedule-drawer-buttons.tsx +72 -0
  91. package/src/pages/scheduler/schedule-drawer/schedule-drawer-group.tsx +103 -0
  92. package/src/pages/scheduler/schedule-drawer/schedule-drawer-legacy.tsx +94 -0
  93. package/src/pages/scheduler/schedule-drawer/schedule-drawer.tsx +101 -0
  94. package/src/pages/scheduler/schedule-drawer/sortable-integration-row.tsx +93 -0
  95. package/src/pages/scheduler/scheduler.tsx +106 -30
  96. package/src/pages/scheduler/schedules-list/index.ts +1 -0
  97. package/src/pages/scheduler/schedules-list/schedules-list-row.tsx +235 -0
  98. package/src/pages/scheduler/schedules-list/schedules-list-table.tsx +74 -0
  99. package/src/pages/scheduler/schedules-list/schedules-list.tsx +280 -0
  100. package/tsconfig.json +29 -26
  101. package/src/components/integration-view/temp-data/initialElements.ts +0 -238
@@ -4,32 +4,32 @@ import { useTranslations } from "next-intl";
4
4
  import React, { useEffect, useState } from "react";
5
5
 
6
6
  import {
7
- Search,
8
- FilterAltOutlined,
9
- CloseOutlined,
10
- ArrowForwardIos,
11
- Delete,
7
+ Search,
8
+ FilterAltOutlined,
9
+ CloseOutlined,
10
+ ArrowForwardIos,
11
+ Delete,
12
12
  } from "@mui/icons-material";
13
13
  import {
14
- Box,
15
- Button,
16
- IconButton,
17
- TextField,
18
- InputAdornment,
19
- Select,
20
- MenuItem,
21
- Theme,
22
- useTheme,
23
- Paper,
24
- Popper,
25
- Badge,
26
- ClickAwayListener,
14
+ Box,
15
+ Button,
16
+ IconButton,
17
+ TextField,
18
+ InputAdornment,
19
+ Select,
20
+ MenuItem,
21
+ Theme,
22
+ useTheme,
23
+ Paper,
24
+ Popper,
25
+ Badge,
26
+ ClickAwayListener,
27
27
  } from "@mui/material";
28
28
  import {
29
- Filters,
30
- FilterResult,
31
- ListFilterOutput,
32
- FilterConfig,
29
+ Filters,
30
+ FilterResult,
31
+ ListFilterOutput,
32
+ FilterConfig,
33
33
  } from "./list-filter-types";
34
34
 
35
35
  import { OutlinedIconButton } from "../button";
@@ -39,371 +39,380 @@ import DateFilterComponent from "./date-filter";
39
39
  import DateRangeFilterComponent from "./date-range-filter";
40
40
 
41
41
  interface FilterProps<FilterShape extends Filters> {
42
- setFilters: (filterUpdate: ListFilterOutput<FilterShape>) => void;
43
- clearFilters: () => void;
44
- filters?: FilterShape;
45
- config?: FilterConfig;
46
- manualClose?: boolean;
42
+ setFilters: (filterUpdate: ListFilterOutput<FilterShape>) => void;
43
+ clearFilters: () => void;
44
+ filters?: FilterShape;
45
+ config?: FilterConfig;
46
+ manualClose?: boolean;
47
47
  }
48
48
 
49
49
  type FilterErrors<FilterShape extends Filters> = {
50
- [Property in keyof FilterShape]: boolean;
50
+ [Property in keyof FilterShape]: boolean;
51
51
  };
52
52
 
53
53
  const ListFilter = function ListFilter<FilterShape extends Filters>(
54
- props: FilterProps<FilterShape>,
54
+ props: FilterProps<FilterShape>,
55
55
  ) {
56
- const t = useTranslations("Integrate.Filter");
57
- const theme = useTheme();
58
- const styles = getStyles(theme);
56
+ const t = useTranslations("Integrate.Filter");
57
+ const theme = useTheme();
58
+ const styles = getStyles(theme);
59
59
 
60
- const {
61
- setFilters,
62
- clearFilters,
63
- filters = {} as FilterShape,
64
- manualClose = false,
65
- config: { pagination = {}, search = {} } = {},
66
- } = props;
60
+ const {
61
+ setFilters,
62
+ clearFilters,
63
+ filters = {} as FilterShape,
64
+ manualClose = false,
65
+ config: { pagination = {}, search = {} } = {},
66
+ } = props;
67
67
 
68
- const { pageOptions = [10, 20, 30], pageDefault = 10 } = pagination || {};
68
+ const { pageOptions = [10, 20, 30], pageDefault = 10 } = pagination || {};
69
69
 
70
- const { label: searchLabel = t("defaultSearchLabel") } = search || {};
70
+ const { label: searchLabel = t("defaultSearchLabel") } = search || {};
71
71
 
72
- const defaultValues = Object.entries(filters).reduce(
73
- (values, [key, filter]) => {
74
- if (filter.type === "select" && filter.value)
75
- return {
76
- ...values,
77
- [key]: filter.options.find((o) => o.id === filter.value[0].id),
78
- };
79
- if (filter.type === "multiSelect" && filter.value)
80
- return {
81
- ...values,
82
- [key]: filter.options.filter((o) =>
83
- filter.value.find((v) => v.id === o.id),
84
- ),
85
- };
72
+ const defaultValues = Object.entries(filters).reduce(
73
+ (values, [key, filter]) => {
74
+ if (filter.type === "select" && filter.value)
75
+ return {
76
+ ...values,
77
+ // @ts-ignore
78
+ [key]: filter.options.find((o) => o.id === filter.value[0].id),
79
+ };
80
+ if (filter.type === "multiSelect" && filter.value)
81
+ return {
82
+ ...values,
83
+ [key]: filter.options.filter((o) =>
84
+ // @ts-ignore
85
+ filter.value.find((v) => v.id === o.id),
86
+ ),
87
+ };
86
88
 
87
- return { ...values, [key]: filter.value };
88
- },
89
- {},
90
- ) as FilterResult<FilterShape>;
89
+ return { ...values, [key]: filter.value };
90
+ },
91
+ {},
92
+ ) as FilterResult<FilterShape>;
91
93
 
92
- const filterErrorsBase: FilterErrors<FilterShape> = Object.keys(
93
- filters,
94
- ).reduce(
95
- (values, key) => ({
96
- ...values,
97
- [key]: false,
98
- }),
99
- {},
100
- ) as FilterErrors<FilterShape>;
94
+ const filterErrorsBase: FilterErrors<FilterShape> = Object.keys(
95
+ filters,
96
+ ).reduce(
97
+ (values, key) => ({
98
+ ...values,
99
+ [key]: false,
100
+ }),
101
+ {},
102
+ ) as FilterErrors<FilterShape>;
101
103
 
102
- const [perPage, setPerPage] = useState(pageDefault);
103
- const [searchTerm, setSearchTerm] = useState("");
104
- const [open, setOpen] = useState(false);
105
- const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
106
- const [filterErrors, setFilterErrors] = useState(filterErrorsBase);
107
- const [publishedFilterValues, setPublishedFilterValues] =
108
- useState<FilterResult<FilterShape>>(defaultValues);
109
- const [filterValues, setFilterValues] = useState<FilterResult<FilterShape>>(
110
- publishedFilterValues,
111
- );
104
+ const [perPage, setPerPage] = useState(pageDefault);
105
+ const [searchTerm, setSearchTerm] = useState("");
106
+ const [open, setOpen] = useState(false);
107
+ const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
108
+ const [filterErrors, setFilterErrors] = useState(filterErrorsBase);
109
+ const [publishedFilterValues, setPublishedFilterValues] =
110
+ useState<FilterResult<FilterShape>>(defaultValues);
111
+ const [filterValues, setFilterValues] = useState<FilterResult<FilterShape>>(
112
+ publishedFilterValues,
113
+ );
112
114
 
113
- const activeFilterCount = Object.entries(publishedFilterValues).reduce(
114
- (sum, [key, value]) => {
115
- if (!value) return sum;
115
+ const activeFilterCount = Object.entries(publishedFilterValues).reduce(
116
+ (sum, [key, value]) => {
117
+ if (!value) return sum;
116
118
 
117
- const activeFilters =
118
- filters[key].type === "multiSelect" ? value.length : 1;
119
+ const activeFilters =
120
+ filters[key].type === "multiSelect" ? value.length : 1;
119
121
 
120
- return sum + activeFilters;
121
- },
122
- 0,
123
- );
122
+ return sum + activeFilters;
123
+ },
124
+ 0,
125
+ );
124
126
 
125
- const updateFilterValue = (name, value) => {
126
- if (Array.isArray(value) && !value.length) value = null;
127
- setFilterValues({
128
- ...filterValues,
129
- [name]: value || null,
130
- });
131
- };
127
+ const updateFilterValue = (name: string, value: any) => {
128
+ if (Array.isArray(value) && !value.length) value = null;
129
+ setFilterValues({
130
+ ...filterValues,
131
+ [name]: value || null,
132
+ });
133
+ };
132
134
 
133
- const updateFilterErrors = (name: keyof FilterShape, error: boolean) => {
134
- setFilterErrors({
135
- ...filterErrors,
136
- [name]: error,
137
- });
138
- };
135
+ const updateFilterErrors = (name: keyof FilterShape, error: boolean) => {
136
+ setFilterErrors({
137
+ ...filterErrors,
138
+ [name]: error,
139
+ });
140
+ };
139
141
 
140
- const sendFilterOutput = (
141
- update: {
142
- search?: string;
143
- itemsPerPage?: number;
144
- filters?: FilterResult<FilterShape>;
145
- } = {},
146
- ) => {
147
- setFilters({
148
- search: searchTerm,
149
- itemsPerPage: perPage,
150
- filters: publishedFilterValues,
151
- ...update,
152
- });
153
- };
142
+ const sendFilterOutput = (
143
+ update: {
144
+ search?: string;
145
+ itemsPerPage?: number;
146
+ filters?: FilterResult<FilterShape>;
147
+ } = {},
148
+ ) => {
149
+ setFilters({
150
+ search: searchTerm,
151
+ itemsPerPage: perPage,
152
+ filters: publishedFilterValues,
153
+ ...update,
154
+ });
155
+ };
154
156
 
155
- const handleFilterMenuClick = (event: React.MouseEvent<HTMLElement>) => {
156
- if (!open) {
157
- setFilterValues(publishedFilterValues);
158
- setAnchorEl(event.currentTarget);
159
- }
160
- setOpen(!open);
161
- };
157
+ const handleFilterMenuClick = (event: React.MouseEvent<HTMLElement>) => {
158
+ if (!open) {
159
+ setFilterValues(publishedFilterValues);
160
+ setAnchorEl(event.currentTarget);
161
+ }
162
+ setOpen(!open);
163
+ };
162
164
 
163
- const handleFilterSet = () => {
164
- setPublishedFilterValues(filterValues);
165
- sendFilterOutput({ filters: filterValues });
166
- setOpen(false);
167
- };
165
+ const handleFilterSet = () => {
166
+ if (Object.values(filterValues).some((value) => value !== null)) {
167
+ setPublishedFilterValues(filterValues);
168
+ sendFilterOutput({ filters: filterValues });
169
+ setOpen(false);
170
+ } else {
171
+ handleFilterClear();
172
+ }
173
+ };
168
174
 
169
- const handleFilterClear = () => {
170
- const emptyFilterValues = Object.keys(filterValues).reduce(
171
- (values, key) => ({ ...values, [key]: null }),
172
- {},
173
- ) as FilterResult<FilterShape>;
174
- setPublishedFilterValues(emptyFilterValues);
175
- setOpen(false);
176
- clearFilters();
177
- };
175
+ const handleFilterClear = () => {
176
+ const emptyFilterValues = Object.keys(filterValues).reduce(
177
+ (values, key) => ({ ...values, [key]: null }),
178
+ {},
179
+ ) as FilterResult<FilterShape>;
180
+ setPublishedFilterValues(emptyFilterValues);
181
+ setOpen(false);
182
+ clearFilters();
183
+ };
178
184
 
179
- const debounceSendSearchOutput = debounce(
180
- (s) => sendFilterOutput({ search: s }),
181
- 400,
182
- );
185
+ const debounceSendSearchOutput = debounce(
186
+ (s) => sendFilterOutput({ search: s }),
187
+ 400,
188
+ );
183
189
 
184
- useEffect(() => {
185
- debounceSendSearchOutput(searchTerm);
186
- return debounceSendSearchOutput.cancel;
187
- }, [searchTerm]);
190
+ useEffect(() => {
191
+ debounceSendSearchOutput(searchTerm);
192
+ return debounceSendSearchOutput.cancel;
193
+ }, [searchTerm]);
188
194
 
189
- const handlePerPageUpdate = (itemsPerPage: number) => {
190
- setPerPage(itemsPerPage);
191
- sendFilterOutput({ itemsPerPage });
192
- };
195
+ const handlePerPageUpdate = (itemsPerPage: number) => {
196
+ setPerPage(itemsPerPage);
197
+ sendFilterOutput({ itemsPerPage });
198
+ };
193
199
 
194
- return (
195
- <Box sx={styles.filter}>
196
- {Object.keys(filters).length ? (
197
- <ClickAwayListener
198
- onClickAway={() => !manualClose && setOpen(false)}
199
- mouseEvent="onMouseUp"
200
- >
201
- <Box>
202
- <Badge
203
- badgeContent={activeFilterCount}
204
- color="error"
205
- invisible={!activeFilterCount}
206
- >
207
- <OutlinedIconButton
208
- color="info"
209
- onClick={(e) => handleFilterMenuClick(e)}
210
- >
211
- <FilterAltOutlined />
212
- </OutlinedIconButton>
213
- </Badge>
214
- <Popper open={open} anchorEl={anchorEl} placement="bottom-start">
215
- <Paper sx={styles.popOut} elevation={3}>
216
- <Box sx={styles.closeRow}>
217
- {manualClose ? (
218
- <IconButton
219
- centerRipple={false}
220
- onClick={() => setOpen(false)}
221
- >
222
- <CloseOutlined />
223
- </IconButton>
224
- ) : (
225
- <Box sx={styles.bufferRow} />
226
- )}
227
- </Box>
200
+ return (
201
+ <Box sx={styles.filter}>
202
+ {Object.keys(filters).length ? (
203
+ <ClickAwayListener
204
+ onClickAway={() => !manualClose && setOpen(false)}
205
+ mouseEvent="onMouseUp"
206
+ >
207
+ <Box>
208
+ <Badge
209
+ badgeContent={activeFilterCount}
210
+ color="error"
211
+ invisible={!activeFilterCount}
212
+ >
213
+ <OutlinedIconButton
214
+ color="info"
215
+ onClick={(e) => handleFilterMenuClick(e)}
216
+ >
217
+ <FilterAltOutlined />
218
+ </OutlinedIconButton>
219
+ </Badge>
220
+ <Popper open={open} anchorEl={anchorEl} placement="bottom-start">
221
+ <Paper sx={styles.popOut} elevation={3}>
222
+ <Box sx={styles.closeRow}>
223
+ {manualClose ? (
224
+ <IconButton
225
+ centerRipple={false}
226
+ onClick={() => setOpen(false)}
227
+ >
228
+ <CloseOutlined />
229
+ </IconButton>
230
+ ) : (
231
+ <Box sx={styles.bufferRow} />
232
+ )}
233
+ </Box>
228
234
 
229
- <Box sx={styles.filterRows}>
230
- {Object.entries(filters)
231
- .sort(([keyA, { sort: a }], [keyB, { sort: b }]) => a - b)
232
- .map(([name, filter]) => {
233
- switch (filter.type) {
234
- case "select":
235
- return (
236
- <SelectFilterComponent
237
- key={name}
238
- filter={filter}
239
- current={
240
- filterValues[name] as (typeof filter)["value"]
241
- }
242
- onSet={(v) => updateFilterValue(name, v)}
243
- onError={(e) => updateFilterErrors(name, e)}
244
- />
245
- );
246
- case "multiSelect":
247
- return (
248
- <MultiSelectFilterComponent
249
- key={name}
250
- filter={filter}
251
- current={
252
- filterValues[name] as (typeof filter)["value"]
253
- }
254
- onSet={(v) => updateFilterValue(name, v)}
255
- onError={(e) => updateFilterErrors(name, e)}
256
- />
257
- );
258
- case "date":
259
- return (
260
- <DateFilterComponent
261
- key={name}
262
- filter={filter}
263
- current={
264
- filterValues[name] as (typeof filter)["value"]
265
- }
266
- onSet={(v) => updateFilterValue(name, v)}
267
- onError={(e) => updateFilterErrors(name, e)}
268
- />
269
- );
270
- case "dateRange":
271
- return (
272
- <DateRangeFilterComponent
273
- key={name}
274
- filter={filter}
275
- current={
276
- filterValues[name] as (typeof filter)["value"]
277
- }
278
- onSet={(v) => updateFilterValue(name, v)}
279
- onError={(e) => updateFilterErrors(name, e)}
280
- />
281
- );
282
- }
283
- })}
284
- <Box sx={styles.buttonRow}>
285
- {activeFilterCount ? (
286
- <Button
287
- variant="contained"
288
- color="error"
289
- startIcon={<Delete />}
290
- onClick={handleFilterClear}
291
- >
292
- Clear
293
- </Button>
294
- ) : (
295
- ""
296
- )}
235
+ <Box sx={styles.filterRows}>
236
+ {Object.entries(filters)
237
+ .sort(
238
+ ([, { sort: a }], [, { sort: b }]) =>
239
+ (a ?? Infinity) - (b ?? Infinity),
240
+ )
241
+ .map(([name, filter]) => {
242
+ switch (filter.type) {
243
+ case "select":
244
+ return (
245
+ <SelectFilterComponent
246
+ key={name}
247
+ filter={filter}
248
+ current={
249
+ filterValues[name] as (typeof filter)["value"]
250
+ }
251
+ onSet={(v) => updateFilterValue(name, v)}
252
+ onError={(e) => updateFilterErrors(name, e)}
253
+ />
254
+ );
255
+ case "multiSelect":
256
+ return (
257
+ <MultiSelectFilterComponent
258
+ key={name}
259
+ filter={filter}
260
+ current={
261
+ filterValues[name] as (typeof filter)["value"]
262
+ }
263
+ onSet={(v) => updateFilterValue(name, v)}
264
+ onError={(e) => updateFilterErrors(name, e)}
265
+ />
266
+ );
267
+ case "date":
268
+ return (
269
+ <DateFilterComponent
270
+ key={name}
271
+ filter={filter}
272
+ current={
273
+ filterValues[name] as (typeof filter)["value"]
274
+ }
275
+ onSet={(v) => updateFilterValue(name, v)}
276
+ onError={(e) => updateFilterErrors(name, e)}
277
+ />
278
+ );
279
+ case "dateRange":
280
+ return (
281
+ <DateRangeFilterComponent
282
+ key={name}
283
+ filter={filter}
284
+ current={
285
+ filterValues[name] as (typeof filter)["value"]
286
+ }
287
+ onSet={(v) => updateFilterValue(name, v)}
288
+ onError={(e) => updateFilterErrors(name, e)}
289
+ />
290
+ );
291
+ }
292
+ })}
293
+ <Box sx={styles.buttonRow}>
294
+ {activeFilterCount ? (
295
+ <Button
296
+ variant="contained"
297
+ color="error"
298
+ startIcon={<Delete />}
299
+ onClick={handleFilterClear}
300
+ >
301
+ Clear
302
+ </Button>
303
+ ) : (
304
+ ""
305
+ )}
297
306
 
298
- <Button
299
- variant="contained"
300
- color="primary"
301
- startIcon={<ArrowForwardIos />}
302
- disabled={Object.values(filterErrors).some((v) => v)}
303
- onClick={handleFilterSet}
304
- >
305
- Filter
306
- </Button>
307
- </Box>
308
- </Box>
309
- </Paper>
310
- </Popper>
311
- </Box>
312
- </ClickAwayListener>
313
- ) : (
314
- ""
315
- )}
307
+ <Button
308
+ variant="contained"
309
+ color="primary"
310
+ startIcon={<ArrowForwardIos />}
311
+ disabled={Object.values(filterErrors).some((v) => v)}
312
+ onClick={handleFilterSet}
313
+ >
314
+ Filter
315
+ </Button>
316
+ </Box>
317
+ </Box>
318
+ </Paper>
319
+ </Popper>
320
+ </Box>
321
+ </ClickAwayListener>
322
+ ) : (
323
+ ""
324
+ )}
316
325
 
317
- {search ? (
318
- <TextField
319
- sx={styles.search}
320
- variant="outlined"
321
- label={searchLabel}
322
- value={searchTerm}
323
- onChange={(e) => setSearchTerm(e.target.value)}
324
- slotProps={{
325
- input: {
326
- startAdornment: (
327
- <InputAdornment position="start">
328
- <Search />
329
- </InputAdornment>
330
- ),
331
- },
332
- }}
333
- />
334
- ) : (
335
- ""
336
- )}
337
- {pagination ? (
338
- <Select
339
- sx={styles.select}
340
- value={perPage}
341
- onChange={(e) => handlePerPageUpdate(e.target.value as number)}
342
- >
343
- {pageOptions.map((option) => (
344
- <MenuItem value={option}>
345
- {option} {t("itemsPerPage")}
346
- </MenuItem>
347
- ))}
348
- </Select>
349
- ) : (
350
- ""
351
- )}
352
- </Box>
353
- );
326
+ {search ? (
327
+ <TextField
328
+ sx={styles.search}
329
+ variant="outlined"
330
+ label={searchLabel}
331
+ value={searchTerm}
332
+ onChange={(e) => setSearchTerm(e.target.value)}
333
+ slotProps={{
334
+ input: {
335
+ startAdornment: (
336
+ <InputAdornment position="start">
337
+ <Search />
338
+ </InputAdornment>
339
+ ),
340
+ },
341
+ }}
342
+ />
343
+ ) : (
344
+ ""
345
+ )}
346
+ {pagination ? (
347
+ <Select
348
+ sx={styles.select}
349
+ value={perPage}
350
+ onChange={(e) => handlePerPageUpdate(e.target.value as number)}
351
+ >
352
+ {pageOptions.map((option) => (
353
+ <MenuItem value={option}>
354
+ {option} {t("itemsPerPage")}
355
+ </MenuItem>
356
+ ))}
357
+ </Select>
358
+ ) : (
359
+ ""
360
+ )}
361
+ </Box>
362
+ );
354
363
  };
355
364
 
356
365
  const getStyles = (theme: Theme) => {
357
- return {
358
- filter: {
359
- width: "100%",
360
- maxWidth: "600px",
361
- display: "flex",
362
- justifyContent: "center",
363
- alignItems: "center",
364
- columnGap: theme.spacing(2),
365
- },
366
- popOut: {
367
- width: "512px",
368
- padding: theme.spacing(2),
369
- paddingTop: theme.spacing(1),
370
- margin: theme.spacing(1, 0),
371
- },
372
- filterRows: {
373
- display: "flex",
374
- flexDirection: "column",
375
- rowGap: theme.spacing(2),
376
- },
377
- closeRow: {
378
- display: "flex",
379
- justifyContent: "end",
380
- },
381
- bufferRow: {
382
- paddingTop: theme.spacing(1),
383
- },
384
- buttonRow: {
385
- width: "100%",
386
- display: "flex",
387
- justifyContent: "end",
388
- columnGap: theme.spacing(1),
389
- },
390
- search: {
391
- "& .MuiOutlinedInput-root": {
392
- "& input": {
393
- padding: theme.spacing(1.5),
394
- },
395
- },
396
- backgroundColor: theme.palette.common.white,
397
- width: "100%",
398
- flexGrow: "1",
399
- },
400
- select: {
401
- "& .MuiSelect-select": {
402
- padding: theme.spacing(1.5),
403
- },
404
- backgroundColor: theme.palette.common.white,
405
- },
406
- };
366
+ return {
367
+ filter: {
368
+ width: "100%",
369
+ maxWidth: "600px",
370
+ display: "flex",
371
+ justifyContent: "center",
372
+ alignItems: "center",
373
+ columnGap: theme.spacing(2),
374
+ },
375
+ popOut: {
376
+ width: "512px",
377
+ padding: theme.spacing(2),
378
+ paddingTop: theme.spacing(1),
379
+ margin: theme.spacing(1, 0),
380
+ },
381
+ filterRows: {
382
+ display: "flex",
383
+ flexDirection: "column",
384
+ rowGap: theme.spacing(2),
385
+ },
386
+ closeRow: {
387
+ display: "flex",
388
+ justifyContent: "end",
389
+ },
390
+ bufferRow: {
391
+ paddingTop: theme.spacing(1),
392
+ },
393
+ buttonRow: {
394
+ width: "100%",
395
+ display: "flex",
396
+ justifyContent: "end",
397
+ columnGap: theme.spacing(1),
398
+ },
399
+ search: {
400
+ "& .MuiOutlinedInput-root": {
401
+ "& input": {
402
+ padding: theme.spacing(1.5),
403
+ },
404
+ },
405
+ backgroundColor: theme.palette.common.white,
406
+ width: "100%",
407
+ flexGrow: "1",
408
+ },
409
+ select: {
410
+ "& .MuiSelect-select": {
411
+ padding: theme.spacing(1.5),
412
+ },
413
+ backgroundColor: theme.palette.common.white,
414
+ },
415
+ };
407
416
  };
408
417
 
409
418
  export default ListFilter;