@evenicanpm/portal-table-ui 1.8.3 → 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.
- package/package.json +4 -4
- package/src/auth/auth-context.tsx +3 -3
- package/src/features/table/components/dashboard/table/data-mask-map.ts +2 -2
- package/src/features/table/components/dashboard/table/details/details.tsx +6 -2
- package/src/features/table/components/dashboard/table/details/templates/invoice-details.tsx +75 -17
- package/src/features/table/components/dashboard/table/details/templates/template-registry.ts +1 -0
- package/src/features/table/components/dashboard/table/index.ts +1 -0
- package/src/features/table/components/dashboard/table/table-header.tsx +0 -1
- package/src/features/table/components/dashboard/table/table-input.tsx +8 -5
- package/src/features/table/components/dashboard/table/table-row/table-row.tsx +3 -3
- package/src/features/table/components/dashboard/table/table.tsx +30 -9
- package/src/features/table/logic/resolvers.ts +1 -1
- package/src/features/table/types/schemas.ts +16 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/portal-table-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@arrows/multimethod": "^2.1.0",
|
|
44
|
-
"@evenicanpm/portal-types-schemas": "^
|
|
45
|
-
"@evenicanpm/ui": "^
|
|
44
|
+
"@evenicanpm/portal-types-schemas": "^2.0.0",
|
|
45
|
+
"@evenicanpm/ui": "^2.0.0",
|
|
46
46
|
"@mui/lab": "^7.0.1-beta.19",
|
|
47
47
|
"@tanstack/react-query": "^5.90.11",
|
|
48
48
|
"date-fns": "^4.1.0"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "bbaff05f6f592114ad7a25caeee531e4fa1b14cf"
|
|
51
51
|
}
|
|
@@ -9,7 +9,7 @@ export const dataMaskMap: Table.Handlers.DataMaskMap = {
|
|
|
9
9
|
|
|
10
10
|
const date = new Date(value);
|
|
11
11
|
|
|
12
|
-
if (isNaN(date.getTime())) {
|
|
12
|
+
if (Number.isNaN(date.getTime())) {
|
|
13
13
|
console.warn("Invalid datetime value:", value);
|
|
14
14
|
return "";
|
|
15
15
|
}
|
|
@@ -21,7 +21,7 @@ export const dataMaskMap: Table.Handlers.DataMaskMap = {
|
|
|
21
21
|
|
|
22
22
|
const date = new Date(value);
|
|
23
23
|
|
|
24
|
-
if (isNaN(date.getTime())) {
|
|
24
|
+
if (Number.isNaN(date.getTime())) {
|
|
25
25
|
console.warn("Invalid date value:", value);
|
|
26
26
|
return "";
|
|
27
27
|
}
|
|
@@ -19,7 +19,9 @@ interface DetailsProps {
|
|
|
19
19
|
/** What is the id field name */
|
|
20
20
|
id: string | number;
|
|
21
21
|
/** The actual pojo of data from the API */
|
|
22
|
-
documentData
|
|
22
|
+
documentData?: unknown;
|
|
23
|
+
/** The row data for the document */
|
|
24
|
+
row: Types.Queries.Row;
|
|
23
25
|
/* the label of the document type ie 'INVOICES' */
|
|
24
26
|
documentTypeLabel: string;
|
|
25
27
|
/** Special instructions for how to render certain properties */
|
|
@@ -46,6 +48,7 @@ const Details = ({
|
|
|
46
48
|
id,
|
|
47
49
|
documentTypeLabel,
|
|
48
50
|
documentData,
|
|
51
|
+
row,
|
|
49
52
|
handleBack,
|
|
50
53
|
columns,
|
|
51
54
|
dataMaskMap,
|
|
@@ -69,7 +72,7 @@ const Details = ({
|
|
|
69
72
|
? undefined
|
|
70
73
|
: visibleDetails?.map((col) => ({
|
|
71
74
|
key: col.Data,
|
|
72
|
-
value:
|
|
75
|
+
value: row?.[col.Data], // use row instead of documentData
|
|
73
76
|
maskFn: resolvers.resolveDataMask(col, dataMaskMap),
|
|
74
77
|
mask: col.DataMask,
|
|
75
78
|
col,
|
|
@@ -98,6 +101,7 @@ const Details = ({
|
|
|
98
101
|
{TemplateComponent ? (
|
|
99
102
|
<TemplateComponent
|
|
100
103
|
data={documentData}
|
|
104
|
+
row={row}
|
|
101
105
|
statusColorMap={statusColorMap}
|
|
102
106
|
statusTextMap={statusTextMap}
|
|
103
107
|
loading={loading}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import FlagIcon from "@mui/icons-material/Flag";
|
|
2
3
|
import {
|
|
3
4
|
Box,
|
|
4
5
|
Card,
|
|
@@ -35,7 +36,7 @@ const formatDate = (dateString?: string): string => {
|
|
|
35
36
|
if (!dateString) return "—";
|
|
36
37
|
try {
|
|
37
38
|
const date = new Date(dateString);
|
|
38
|
-
if (isNaN(date.getTime())) return dateString;
|
|
39
|
+
if (Number.isNaN(date.getTime())) return dateString;
|
|
39
40
|
return new Intl.DateTimeFormat("en-US", {
|
|
40
41
|
year: "numeric",
|
|
41
42
|
month: "long",
|
|
@@ -60,6 +61,7 @@ interface InvoiceLine {
|
|
|
60
61
|
|
|
61
62
|
interface InvoiceData {
|
|
62
63
|
Status?: string | number;
|
|
64
|
+
IsOverdue?: boolean;
|
|
63
65
|
SalesInvoiceLine?: InvoiceLine[];
|
|
64
66
|
InvoiceSubtotal?: number;
|
|
65
67
|
TotalTaxAmount?: number;
|
|
@@ -74,8 +76,13 @@ interface InvoiceData {
|
|
|
74
76
|
DueDate?: string;
|
|
75
77
|
Notes?: string;
|
|
76
78
|
Id: string;
|
|
79
|
+
OrderedByCustomerName?: string;
|
|
77
80
|
}
|
|
78
81
|
|
|
82
|
+
const detailSkeletonKeys = ["from", "bill-to", "invoice-date", "due-date"];
|
|
83
|
+
const tableSkeletonRowKeys = ["line-1", "line-2", "line-3", "line-4"];
|
|
84
|
+
const totalSkeletonKeys = ["subtotal", "tax", "total"];
|
|
85
|
+
|
|
79
86
|
const isDataEmpty = (data: InvoiceData | null | undefined): boolean => {
|
|
80
87
|
if (!data) return true;
|
|
81
88
|
const hasNoLineItems =
|
|
@@ -88,6 +95,7 @@ const isDataEmpty = (data: InvoiceData | null | undefined): boolean => {
|
|
|
88
95
|
export const InvoiceDetailsTemplate = ({
|
|
89
96
|
data,
|
|
90
97
|
statusColorMap,
|
|
98
|
+
row,
|
|
91
99
|
statusTextMap,
|
|
92
100
|
loading = false,
|
|
93
101
|
actions,
|
|
@@ -105,6 +113,7 @@ export const InvoiceDetailsTemplate = ({
|
|
|
105
113
|
return (
|
|
106
114
|
<Box sx={{ p: { xs: 2, sm: 3 }, width: containerWidth, mx: "auto" }}>
|
|
107
115
|
<Card
|
|
116
|
+
variant="outlined"
|
|
108
117
|
sx={{ p: { xs: 3, sm: 6 }, borderRadius: 3, textAlign: "center" }}
|
|
109
118
|
>
|
|
110
119
|
<Typography variant="h6" color="text.secondary" gutterBottom>
|
|
@@ -145,10 +154,10 @@ export const InvoiceDetailsTemplate = ({
|
|
|
145
154
|
<Skeleton variant="rectangular" width={100} height={32} />
|
|
146
155
|
<Skeleton variant="rectangular" width={120} height={40} />
|
|
147
156
|
</Box>
|
|
148
|
-
<Card sx={{ p: { xs: 2, sm: 4 }, borderRadius: 3 }}>
|
|
157
|
+
<Card variant="outlined" sx={{ p: { xs: 2, sm: 4 }, borderRadius: 3 }}>
|
|
149
158
|
<Grid2 container spacing={{ xs: 2, sm: 4 }}>
|
|
150
|
-
{
|
|
151
|
-
<Grid2 size={{ xs: 12, sm: 6 }} key={
|
|
159
|
+
{detailSkeletonKeys.map((key) => (
|
|
160
|
+
<Grid2 size={{ xs: 12, sm: 6 }} key={key}>
|
|
152
161
|
<Skeleton width="40%" height={20} />
|
|
153
162
|
<Skeleton width="80%" />
|
|
154
163
|
<Skeleton width="60%" />
|
|
@@ -176,8 +185,8 @@ export const InvoiceDetailsTemplate = ({
|
|
|
176
185
|
</TableRow>
|
|
177
186
|
</TableHead>
|
|
178
187
|
<TableBody>
|
|
179
|
-
{
|
|
180
|
-
<TableRow key={
|
|
188
|
+
{tableSkeletonRowKeys.map((key) => (
|
|
189
|
+
<TableRow key={key}>
|
|
181
190
|
{columns.map((col) => (
|
|
182
191
|
<TableCell
|
|
183
192
|
key={col.label}
|
|
@@ -194,9 +203,9 @@ export const InvoiceDetailsTemplate = ({
|
|
|
194
203
|
|
|
195
204
|
<Box mt={3} display="flex" justifyContent="flex-end">
|
|
196
205
|
<Box width={{ xs: "100%", sm: 300 }}>
|
|
197
|
-
{
|
|
206
|
+
{totalSkeletonKeys.map((key) => (
|
|
198
207
|
<Box
|
|
199
|
-
key={
|
|
208
|
+
key={key}
|
|
200
209
|
display="flex"
|
|
201
210
|
justifyContent="space-between"
|
|
202
211
|
mb={1}
|
|
@@ -232,8 +241,7 @@ export const InvoiceDetailsTemplate = ({
|
|
|
232
241
|
)}
|
|
233
242
|
<Box display="flex" gap={2} alignItems="center">
|
|
234
243
|
{actions?.map((action) => {
|
|
235
|
-
const
|
|
236
|
-
const enabled = !isPaid && action.isEnabled;
|
|
244
|
+
const enabled = !action.isEnabled || action.isEnabled(row);
|
|
237
245
|
if (!enabled) {
|
|
238
246
|
return (
|
|
239
247
|
<span
|
|
@@ -260,7 +268,10 @@ export const InvoiceDetailsTemplate = ({
|
|
|
260
268
|
|
|
261
269
|
{/* Notes Section */}
|
|
262
270
|
{invoice?.Notes && (
|
|
263
|
-
<Card
|
|
271
|
+
<Card
|
|
272
|
+
variant="outlined"
|
|
273
|
+
sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3, mb: 3 }}
|
|
274
|
+
>
|
|
264
275
|
<Typography variant="subtitle1" color="text.secondary" mb={1}>
|
|
265
276
|
Notes
|
|
266
277
|
</Typography>
|
|
@@ -275,16 +286,49 @@ export const InvoiceDetailsTemplate = ({
|
|
|
275
286
|
)}
|
|
276
287
|
|
|
277
288
|
{/* Main Invoice Card */}
|
|
278
|
-
<Card sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3 }}>
|
|
289
|
+
<Card variant="outlined" sx={{ p: { xs: 2, sm: 3 }, borderRadius: 3 }}>
|
|
279
290
|
{/* Details Section */}
|
|
280
291
|
{(invoice?.CompanyName ||
|
|
281
292
|
invoice?.Name ||
|
|
282
293
|
invoice?.InvoiceDate ||
|
|
283
294
|
invoice?.DueDate) && (
|
|
284
295
|
<>
|
|
285
|
-
<
|
|
286
|
-
|
|
287
|
-
|
|
296
|
+
<Box
|
|
297
|
+
sx={{
|
|
298
|
+
display: "flex",
|
|
299
|
+
flexDirection: { xs: "column", sm: "row" },
|
|
300
|
+
gap: 1,
|
|
301
|
+
justifyContent: "space-between",
|
|
302
|
+
alignItems: { xs: "flex-start", sm: "center" },
|
|
303
|
+
marginBottom: 2,
|
|
304
|
+
}}
|
|
305
|
+
>
|
|
306
|
+
<Typography variant="subtitle1" color="text.secondary">
|
|
307
|
+
Details
|
|
308
|
+
</Typography>
|
|
309
|
+
|
|
310
|
+
{invoice.OrderedByCustomerName && (
|
|
311
|
+
<Box
|
|
312
|
+
sx={{
|
|
313
|
+
display: "flex",
|
|
314
|
+
gap: 1,
|
|
315
|
+
alignItems: "center",
|
|
316
|
+
flexWrap: "wrap",
|
|
317
|
+
}}
|
|
318
|
+
>
|
|
319
|
+
<Typography variant="body2" color="text.secondary">
|
|
320
|
+
Order Placed By:
|
|
321
|
+
</Typography>
|
|
322
|
+
<Typography
|
|
323
|
+
variant="body2"
|
|
324
|
+
sx={{ wordBreak: "break-all" }}
|
|
325
|
+
fontWeight={600}
|
|
326
|
+
>
|
|
327
|
+
{invoice.OrderedByCustomerName}
|
|
328
|
+
</Typography>
|
|
329
|
+
</Box>
|
|
330
|
+
)}
|
|
331
|
+
</Box>
|
|
288
332
|
<Grid2 container spacing={{ xs: 2, sm: 4 }}>
|
|
289
333
|
{invoice?.CompanyName && (
|
|
290
334
|
<Grid2 size={{ xs: 12, sm: 6 }}>
|
|
@@ -337,7 +381,14 @@ export const InvoiceDetailsTemplate = ({
|
|
|
337
381
|
<Typography variant="body2" color="text.secondary">
|
|
338
382
|
Due Date
|
|
339
383
|
</Typography>
|
|
340
|
-
|
|
384
|
+
|
|
385
|
+
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
|
386
|
+
<Typography>{formatDate(invoice.DueDate)}</Typography>
|
|
387
|
+
|
|
388
|
+
{invoice?.IsOverdue && (
|
|
389
|
+
<FlagIcon sx={{ color: "error.main" }} fontSize="small" />
|
|
390
|
+
)}
|
|
391
|
+
</Box>
|
|
341
392
|
</Grid2>
|
|
342
393
|
)}
|
|
343
394
|
</Grid2>
|
|
@@ -375,9 +426,16 @@ export const InvoiceDetailsTemplate = ({
|
|
|
375
426
|
const unitPrice = item.Price ?? 0;
|
|
376
427
|
const quantity = item.Quantity ?? 0;
|
|
377
428
|
const lineTotal = item.NetAmount ?? unitPrice * quantity;
|
|
429
|
+
const itemKey = [
|
|
430
|
+
item.ItemId ?? "item",
|
|
431
|
+
productName,
|
|
432
|
+
quantity,
|
|
433
|
+
unitPrice,
|
|
434
|
+
lineTotal,
|
|
435
|
+
].join("-");
|
|
378
436
|
|
|
379
437
|
return (
|
|
380
|
-
<TableRow key={
|
|
438
|
+
<TableRow key={itemKey}>
|
|
381
439
|
<TableCell sx={{ width: 60, minWidth: 60 }}>
|
|
382
440
|
<Typography variant="body2">
|
|
383
441
|
{item?.ItemId || idx + 1}
|
package/src/features/table/components/dashboard/table/details/templates/template-registry.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { InvoiceDetailsTemplate } from "./invoice-details";
|
|
|
8
8
|
*/
|
|
9
9
|
export interface DetailsTemplateProps {
|
|
10
10
|
data: unknown;
|
|
11
|
+
row: Types.Queries.Row;
|
|
11
12
|
statusColorMap: Types.Schemas.StatusColorMap;
|
|
12
13
|
statusTextMap: Types.Schemas.StatusTextMap;
|
|
13
14
|
loading?: boolean;
|
|
@@ -5,7 +5,6 @@ import { styled } from "@mui/material/styles";
|
|
|
5
5
|
import TableCell from "@mui/material/TableCell";
|
|
6
6
|
import TableHead from "@mui/material/TableHead";
|
|
7
7
|
import TableRow from "@mui/material/TableRow";
|
|
8
|
-
import type React from "react";
|
|
9
8
|
|
|
10
9
|
// STYLED COMPONENTS
|
|
11
10
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
|
@@ -6,8 +6,8 @@ import React from "react";
|
|
|
6
6
|
interface SearchProps {
|
|
7
7
|
searchTerm: string;
|
|
8
8
|
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
|
|
9
|
-
setColumn: React.Dispatch<React.SetStateAction<
|
|
10
|
-
selectedColumn:
|
|
9
|
+
setColumn: React.Dispatch<React.SetStateAction<Column>>;
|
|
10
|
+
selectedColumn: Column;
|
|
11
11
|
searchCols: Column[];
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -78,12 +78,15 @@ const SearchField = React.memo(
|
|
|
78
78
|
onChange={(e) => {
|
|
79
79
|
setSearchTerm(e.target.value);
|
|
80
80
|
}}
|
|
81
|
-
placeholder={`Seach by ${selectedColumn}`}
|
|
81
|
+
placeholder={`Seach by ${selectedColumn.Label}`}
|
|
82
82
|
endAdornment={
|
|
83
83
|
<ColumnSelect
|
|
84
|
-
selected={selectedColumn}
|
|
84
|
+
selected={selectedColumn.Data}
|
|
85
85
|
searchCols={searchCols}
|
|
86
|
-
handleChange={
|
|
86
|
+
handleChange={(value) => {
|
|
87
|
+
const col = searchCols.find((c) => c.Data === value);
|
|
88
|
+
if (col) setColumn(col);
|
|
89
|
+
}}
|
|
87
90
|
/>
|
|
88
91
|
}
|
|
89
92
|
/>
|
|
@@ -14,13 +14,13 @@ type ColumnLogic =
|
|
|
14
14
|
| {
|
|
15
15
|
id: string;
|
|
16
16
|
mask: string | undefined;
|
|
17
|
-
maskFn:
|
|
17
|
+
maskFn: unknown;
|
|
18
18
|
cellFn:
|
|
19
19
|
| ((
|
|
20
20
|
value: string | number | string[],
|
|
21
21
|
) => React.ReactElement<
|
|
22
|
-
|
|
23
|
-
string | React.JSXElementConstructor<
|
|
22
|
+
unknown,
|
|
23
|
+
string | React.JSXElementConstructor<unknown>
|
|
24
24
|
>)
|
|
25
25
|
| ((value: string | number) => string | number);
|
|
26
26
|
}[]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Column } from "@evenicanpm/portal-types-schemas";
|
|
1
2
|
import { FlexBox, ResponsiveTablePagination } from "@evenicanpm/ui";
|
|
2
3
|
import Table from "@mui/material/Table";
|
|
3
4
|
import TableBody from "@mui/material/TableBody";
|
|
@@ -150,14 +151,25 @@ export default function DocumentTable({
|
|
|
150
151
|
const visibleCols = transformers.getVisibleColumns(columns);
|
|
151
152
|
|
|
152
153
|
// Depends on searchableCols, must be declared after transformer
|
|
153
|
-
const [searchColumn, setSearchColumn] = useState(
|
|
154
|
-
() => searchableCols?.[0]
|
|
154
|
+
const [searchColumn, setSearchColumn] = useState<Column>(
|
|
155
|
+
() => searchableCols?.[0],
|
|
155
156
|
);
|
|
156
157
|
|
|
157
|
-
const { data:
|
|
158
|
-
resource.rowsQueryFn({
|
|
158
|
+
const { data: fetchedRows, isPending: rowsPending } = useQuery(
|
|
159
|
+
resource.rowsQueryFn({
|
|
160
|
+
page,
|
|
161
|
+
pageSize: pageSize + 1, // Fetch one extra to check if there's a next page
|
|
162
|
+
filters,
|
|
163
|
+
searchColumn: searchColumn?.Data,
|
|
164
|
+
searchTerm,
|
|
165
|
+
}),
|
|
159
166
|
);
|
|
160
167
|
|
|
168
|
+
const hasNextPage = fetchedRows ? fetchedRows.data.length > pageSize : false;
|
|
169
|
+
const rows: Types.Queries.TableRows | undefined = fetchedRows
|
|
170
|
+
? { ...fetchedRows, data: fetchedRows.data.slice(0, pageSize) }
|
|
171
|
+
: undefined;
|
|
172
|
+
|
|
161
173
|
// --- Resolver --- //
|
|
162
174
|
const filterLogic = filterReqs?.map((req) => ({
|
|
163
175
|
req,
|
|
@@ -194,8 +206,8 @@ export default function DocumentTable({
|
|
|
194
206
|
!!resource.detailsQueryFn && !!resource.detailsTemplate;
|
|
195
207
|
|
|
196
208
|
const { data: detailsData, isPending: detailsPending } = useQuery(
|
|
197
|
-
hasTemplateSupport && selectedDocument
|
|
198
|
-
? resource.detailsQueryFn
|
|
209
|
+
hasTemplateSupport && selectedDocument && resource.detailsQueryFn
|
|
210
|
+
? resource.detailsQueryFn(String(selectedDocument))
|
|
199
211
|
: {
|
|
200
212
|
queryKey: [],
|
|
201
213
|
queryFn: async () => undefined,
|
|
@@ -226,14 +238,16 @@ export default function DocumentTable({
|
|
|
226
238
|
const rowSnapshot =
|
|
227
239
|
rows?.data.find((doc) => doc?.[idField] === selectedDocument) ?? {};
|
|
228
240
|
|
|
229
|
-
const
|
|
230
|
-
hasTemplateSupport && detailsData ? detailsData : rowSnapshot;
|
|
241
|
+
const shouldUseDetailsData = hasTemplateSupport;
|
|
231
242
|
|
|
232
243
|
return (
|
|
233
244
|
<Details
|
|
234
245
|
documentTypeLabel={label}
|
|
235
246
|
id={selectedDocument}
|
|
236
|
-
documentData={
|
|
247
|
+
documentData={
|
|
248
|
+
shouldUseDetailsData ? (detailsData ?? rowSnapshot) : undefined
|
|
249
|
+
}
|
|
250
|
+
row={rowSnapshot}
|
|
237
251
|
handleBack={handleBack}
|
|
238
252
|
columns={columns}
|
|
239
253
|
dataMaskMap={resolvedDataMaskMap}
|
|
@@ -357,6 +371,13 @@ export default function DocumentTable({
|
|
|
357
371
|
rowsPerPageOptions={[5, 10]}
|
|
358
372
|
onPageChange={handleChangePage}
|
|
359
373
|
onRowsPerPageChange={handleChangePageSize}
|
|
374
|
+
slotProps={{
|
|
375
|
+
actions: {
|
|
376
|
+
nextButton: {
|
|
377
|
+
disabled: !hasNextPage,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
}}
|
|
360
381
|
/>
|
|
361
382
|
</>
|
|
362
383
|
);
|
|
@@ -66,7 +66,7 @@ export const resolveCellUI = (
|
|
|
66
66
|
) => {
|
|
67
67
|
if (Object.hasOwn(handlers, col.Data)) return handlers?.[col?.Data];
|
|
68
68
|
|
|
69
|
-
return (value: string | number) => value;
|
|
69
|
+
return (value: string | number | string[]) => value;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
export function resolveActions(
|
|
@@ -30,20 +30,28 @@ type BaseAction = {
|
|
|
30
30
|
icon?: SvgIconComponent;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
type MutationArgs = {
|
|
34
|
+
resourceName: string;
|
|
35
|
+
docId: string | number;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type BulkMutationArgs = {
|
|
39
|
+
resourceName: string;
|
|
40
|
+
selectedIds: (string | number)[];
|
|
41
|
+
};
|
|
42
|
+
|
|
33
43
|
export type UIAction = BaseAction & {
|
|
34
44
|
isEnabled?: (row: Record<string, unknown>) => boolean;
|
|
35
|
-
mutation: (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}) => UseMutationOptions<any, any, any, any>;
|
|
45
|
+
mutation: (
|
|
46
|
+
args: MutationArgs,
|
|
47
|
+
) => UseMutationOptions<unknown, unknown, MutationArgs, unknown>;
|
|
39
48
|
};
|
|
40
49
|
|
|
41
50
|
export type UIBulkAction = BaseAction & {
|
|
42
51
|
isAllowed?: (rows: Record<string, unknown>[]) => boolean;
|
|
43
|
-
mutation: (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}) => UseMutationOptions<any, any, any, any>;
|
|
52
|
+
mutation: (
|
|
53
|
+
args: BulkMutationArgs,
|
|
54
|
+
) => UseMutationOptions<unknown, unknown, BulkMutationArgs, unknown>;
|
|
47
55
|
};
|
|
48
56
|
|
|
49
57
|
/**
|