@acmekit/dashboard 2.13.7 → 2.13.8
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/dist/api-key-management-create-D57V3NN2.mjs +170 -0
- package/dist/api-key-management-detail-QURSBB6T.mjs +307 -0
- package/dist/api-key-management-edit-GG5V77GY.mjs +106 -0
- package/dist/api-key-management-list-PL64LD22.mjs +400 -0
- package/dist/app.js +16930 -1004
- package/dist/app.mjs +793 -884
- package/dist/chunk-22YYMH6M.mjs +382 -0
- package/dist/chunk-2U3RK3JG.mjs +474 -0
- package/dist/chunk-535OVBXR.mjs +226 -0
- package/dist/chunk-6SQCO25J.mjs +65 -0
- package/dist/chunk-774WSTCC.mjs +19 -0
- package/dist/chunk-7ZHDHEUH.mjs +1837 -0
- package/dist/chunk-C76H5USB.mjs +16 -0
- package/dist/chunk-DFFLVEZ5.mjs +40 -0
- package/dist/chunk-DN3MIYQH.mjs +140 -0
- package/dist/chunk-DQCEH3X2.mjs +28 -0
- package/dist/chunk-DTY37DDZ.mjs +20 -0
- package/dist/chunk-FXYH54JP.mjs +16 -0
- package/dist/chunk-G22WWLPG.mjs +44 -0
- package/dist/chunk-G2VJOHHV.mjs +32 -0
- package/dist/chunk-GBFVWROS.mjs +58 -0
- package/dist/chunk-ITNQKZQQ.mjs +142 -0
- package/dist/chunk-IUCDCPJU.mjs +0 -0
- package/dist/chunk-LKWTBYYC.mjs +35 -0
- package/dist/{chunk-4VYJHIB3.mjs → chunk-ND3ODI36.mjs} +0 -72
- package/dist/chunk-OAHCJFG3.mjs +17 -0
- package/dist/chunk-OHAFITSB.mjs +54 -0
- package/dist/chunk-RPAL6FHW.mjs +73 -0
- package/dist/{chunk-JSJZMTQG.mjs → chunk-RREPQMYC.mjs} +14 -41
- package/dist/chunk-S3REQHPQ.mjs +86 -0
- package/dist/chunk-S4DMV3ZT.mjs +35 -0
- package/dist/chunk-TCNCAWYD.mjs +9 -0
- package/dist/chunk-ULSPL3DR.mjs +126 -0
- package/dist/chunk-VBT5YZ4K.mjs +129 -0
- package/dist/chunk-WILMJYUB.mjs +35 -0
- package/dist/chunk-XIM7X4FB.mjs +83 -0
- package/dist/chunk-YB52HEIR.mjs +387 -0
- package/dist/chunk-YRWSG3YM.mjs +80 -0
- package/dist/{invite-S5USGDOZ.mjs → invite-BAFXQBLJ.mjs} +15 -7
- package/dist/{login-AIMR26AL.mjs → login-YURMNRCS.mjs} +23 -9
- package/dist/profile-detail-SJWODS2K.mjs +96 -0
- package/dist/profile-edit-HSGF4UXZ.mjs +173 -0
- package/dist/{reset-password-UQPRHMB3.mjs → reset-password-RQ5M7HQC.mjs} +8 -4
- package/dist/settings-3XWLL5LG.mjs +545 -0
- package/dist/store-detail-SQKV5KBD.mjs +109 -0
- package/dist/store-edit-WGGIJMYJ.mjs +97 -0
- package/dist/store-metadata-CSBUGX6Z.mjs +49 -0
- package/dist/translation-list-H5X4DVCC.mjs +587 -0
- package/dist/translations-edit-NPAUN2GZ.mjs +5376 -0
- package/dist/user-detail-7SUQ35G7.mjs +169 -0
- package/dist/user-edit-KUZV37AH.mjs +114 -0
- package/dist/user-invite-OREFWWYL.mjs +361 -0
- package/dist/user-list-OWUR75OP.mjs +1116 -0
- package/dist/user-metadata-QHUX5SHZ.mjs +51 -0
- package/dist/workflow-execution-detail-MWNM25TF.mjs +820 -0
- package/dist/workflow-execution-list-IGYF44UH.mjs +175 -0
- package/package.json +9 -9
- package/src/components/layout/settings-layout/settings-layout.tsx +8 -2
- package/dist/chunk-FBTP4AJM.mjs +0 -221
- package/dist/chunk-QYOO4QR6.mjs +0 -73
|
@@ -0,0 +1,1116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useFeatureFlag
|
|
3
|
+
} from "./chunk-DQCEH3X2.mjs";
|
|
4
|
+
import {
|
|
5
|
+
SingleColumnPage
|
|
6
|
+
} from "./chunk-22YYMH6M.mjs";
|
|
7
|
+
import {
|
|
8
|
+
useExtension
|
|
9
|
+
} from "./chunk-C5P5PL3E.mjs";
|
|
10
|
+
import {
|
|
11
|
+
useActiveViewConfiguration,
|
|
12
|
+
useCreateViewConfiguration,
|
|
13
|
+
useDeleteViewConfiguration,
|
|
14
|
+
useSetActiveViewConfiguration,
|
|
15
|
+
useUpdateViewConfiguration,
|
|
16
|
+
useViewConfigurations
|
|
17
|
+
} from "./chunk-DN3MIYQH.mjs";
|
|
18
|
+
import {
|
|
19
|
+
useUsers
|
|
20
|
+
} from "./chunk-YRWSG3YM.mjs";
|
|
21
|
+
import {
|
|
22
|
+
useQueryParams
|
|
23
|
+
} from "./chunk-C76H5USB.mjs";
|
|
24
|
+
import {
|
|
25
|
+
useDate
|
|
26
|
+
} from "./chunk-DFFLVEZ5.mjs";
|
|
27
|
+
import "./chunk-535OVBXR.mjs";
|
|
28
|
+
import {
|
|
29
|
+
ActionMenu
|
|
30
|
+
} from "./chunk-S3REQHPQ.mjs";
|
|
31
|
+
import "./chunk-OAHCJFG3.mjs";
|
|
32
|
+
import "./chunk-S4DMV3ZT.mjs";
|
|
33
|
+
import "./chunk-FXYH54JP.mjs";
|
|
34
|
+
import "./chunk-774WSTCC.mjs";
|
|
35
|
+
import "./chunk-DTY37DDZ.mjs";
|
|
36
|
+
import "./chunk-QZ7TP4HQ.mjs";
|
|
37
|
+
|
|
38
|
+
// src/routes/users/user-list/components/user-list-table/user-list-table.tsx
|
|
39
|
+
import { Container, createDataTableColumnHelper as createDataTableColumnHelper2 } from "@acmekit/ui";
|
|
40
|
+
import { keepPreviousData } from "@tanstack/react-query";
|
|
41
|
+
import { useMemo as useMemo5 } from "react";
|
|
42
|
+
import { useTranslation as useTranslation4 } from "react-i18next";
|
|
43
|
+
import { useNavigate as useNavigate2 } from "react-router-dom";
|
|
44
|
+
import { PencilSquare as PencilSquare3 } from "@acmekit/icons";
|
|
45
|
+
|
|
46
|
+
// src/components/data-table/data-table.tsx
|
|
47
|
+
import {
|
|
48
|
+
DataTable as UiDataTable,
|
|
49
|
+
useDataTable,
|
|
50
|
+
Heading as Heading2,
|
|
51
|
+
Text as Text2,
|
|
52
|
+
Button as Button3
|
|
53
|
+
} from "@acmekit/ui";
|
|
54
|
+
import React4, { useCallback, useMemo as useMemo2 } from "react";
|
|
55
|
+
import { useTranslation } from "react-i18next";
|
|
56
|
+
import { Link, useNavigate, useSearchParams } from "react-router-dom";
|
|
57
|
+
|
|
58
|
+
// src/components/table/view-selector/view-selector.tsx
|
|
59
|
+
import { useEffect, useState as useState2 } from "react";
|
|
60
|
+
import {
|
|
61
|
+
Button as Button2,
|
|
62
|
+
Tooltip,
|
|
63
|
+
DropdownMenu,
|
|
64
|
+
usePrompt
|
|
65
|
+
} from "@acmekit/ui";
|
|
66
|
+
import {
|
|
67
|
+
Eye,
|
|
68
|
+
Plus,
|
|
69
|
+
Trash,
|
|
70
|
+
PencilSquare,
|
|
71
|
+
Star,
|
|
72
|
+
CheckCircleSolid,
|
|
73
|
+
ArrowUturnLeft
|
|
74
|
+
} from "@acmekit/icons";
|
|
75
|
+
|
|
76
|
+
// src/hooks/use-view-configurations.tsx
|
|
77
|
+
import { useMemo } from "react";
|
|
78
|
+
import { toast } from "@acmekit/ui";
|
|
79
|
+
import { FetchError } from "@acmekit/js-sdk";
|
|
80
|
+
var handleError = (error, message) => {
|
|
81
|
+
let errorMessage = message;
|
|
82
|
+
if (!errorMessage) {
|
|
83
|
+
if (error instanceof FetchError) {
|
|
84
|
+
errorMessage = error.message;
|
|
85
|
+
} else if (error.message) {
|
|
86
|
+
errorMessage = error.message;
|
|
87
|
+
} else {
|
|
88
|
+
errorMessage = "An error occurred";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
toast.error(errorMessage);
|
|
92
|
+
};
|
|
93
|
+
var useViewConfigurations2 = (entity) => {
|
|
94
|
+
const isViewConfigEnabled = useFeatureFlag("view_configurations");
|
|
95
|
+
const listViews = useViewConfigurations(entity, { limit: 100 }, {
|
|
96
|
+
enabled: isViewConfigEnabled && !!entity
|
|
97
|
+
});
|
|
98
|
+
const activeView = useActiveViewConfiguration(entity, {
|
|
99
|
+
enabled: isViewConfigEnabled && !!entity
|
|
100
|
+
});
|
|
101
|
+
const createView = useCreateViewConfiguration(entity, {
|
|
102
|
+
onSuccess: () => {
|
|
103
|
+
toast.success(`View created`);
|
|
104
|
+
},
|
|
105
|
+
onError: (error) => {
|
|
106
|
+
handleError(error, "Failed to create view");
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const setActiveView = useSetActiveViewConfiguration(entity, {
|
|
110
|
+
onSuccess: () => {
|
|
111
|
+
},
|
|
112
|
+
onError: (error) => {
|
|
113
|
+
handleError(error, "Failed to update active view");
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return useMemo(() => ({
|
|
117
|
+
isViewConfigEnabled,
|
|
118
|
+
listViews,
|
|
119
|
+
activeView,
|
|
120
|
+
createView,
|
|
121
|
+
setActiveView,
|
|
122
|
+
isDefaultViewActive: activeView?.is_default_active ?? true
|
|
123
|
+
}), [
|
|
124
|
+
isViewConfigEnabled,
|
|
125
|
+
listViews,
|
|
126
|
+
activeView,
|
|
127
|
+
createView,
|
|
128
|
+
setActiveView
|
|
129
|
+
]);
|
|
130
|
+
};
|
|
131
|
+
var useViewConfiguration = (entity, viewId) => {
|
|
132
|
+
const updateView = useUpdateViewConfiguration(entity, viewId, {
|
|
133
|
+
onSuccess: () => {
|
|
134
|
+
toast.success(`View updated`);
|
|
135
|
+
},
|
|
136
|
+
onError: (error) => {
|
|
137
|
+
handleError(error, "Failed to update view");
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const deleteView = useDeleteViewConfiguration(entity, viewId, {
|
|
141
|
+
onSuccess: () => {
|
|
142
|
+
toast.success("View deleted successfully");
|
|
143
|
+
},
|
|
144
|
+
onError: (error) => {
|
|
145
|
+
handleError(error, "Failed to delete view");
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
updateView,
|
|
150
|
+
deleteView
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// src/components/table/save-view-dialog/save-view-dialog.tsx
|
|
155
|
+
import { useState } from "react";
|
|
156
|
+
import {
|
|
157
|
+
Button,
|
|
158
|
+
Input,
|
|
159
|
+
Label,
|
|
160
|
+
Drawer,
|
|
161
|
+
Heading,
|
|
162
|
+
Text
|
|
163
|
+
} from "@acmekit/ui";
|
|
164
|
+
import { useForm } from "react-hook-form";
|
|
165
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
166
|
+
var SaveViewDialog = ({
|
|
167
|
+
entity,
|
|
168
|
+
currentColumns,
|
|
169
|
+
currentConfiguration,
|
|
170
|
+
editingView,
|
|
171
|
+
onClose,
|
|
172
|
+
onSaved
|
|
173
|
+
}) => {
|
|
174
|
+
const { createView } = useViewConfigurations2(entity);
|
|
175
|
+
const { updateView } = useViewConfiguration(entity, editingView?.id || "");
|
|
176
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
177
|
+
const {
|
|
178
|
+
register,
|
|
179
|
+
handleSubmit,
|
|
180
|
+
formState: { errors }
|
|
181
|
+
} = useForm({
|
|
182
|
+
defaultValues: {
|
|
183
|
+
name: editingView?.name || ""
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
const onSubmit = async (data) => {
|
|
187
|
+
if (!data.name.trim()) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
setIsLoading(true);
|
|
191
|
+
try {
|
|
192
|
+
if (editingView) {
|
|
193
|
+
const result = await updateView.mutateAsync({
|
|
194
|
+
name: data.name.trim(),
|
|
195
|
+
configuration: {
|
|
196
|
+
visible_columns: currentColumns?.visible || editingView.configuration.visible_columns,
|
|
197
|
+
column_order: currentColumns?.order || editingView.configuration.column_order,
|
|
198
|
+
filters: currentConfiguration?.filters || editingView.configuration.filters || {},
|
|
199
|
+
sorting: currentConfiguration?.sorting || editingView.configuration.sorting || null,
|
|
200
|
+
search: currentConfiguration?.search || editingView.configuration.search || ""
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
onSaved(result.view_configuration);
|
|
204
|
+
} else {
|
|
205
|
+
const result = await createView.mutateAsync({
|
|
206
|
+
name: data.name.trim(),
|
|
207
|
+
set_active: true,
|
|
208
|
+
configuration: {
|
|
209
|
+
visible_columns: currentColumns?.visible || [],
|
|
210
|
+
column_order: currentColumns?.order || [],
|
|
211
|
+
filters: currentConfiguration?.filters || {},
|
|
212
|
+
sorting: currentConfiguration?.sorting || null,
|
|
213
|
+
search: currentConfiguration?.search || ""
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
onSaved(result.view_configuration);
|
|
217
|
+
}
|
|
218
|
+
} catch (error) {
|
|
219
|
+
} finally {
|
|
220
|
+
setIsLoading(false);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
return /* @__PURE__ */ jsx(Drawer, { open: true, onOpenChange: onClose, children: /* @__PURE__ */ jsxs(Drawer.Content, { className: "flex flex-col", children: [
|
|
224
|
+
/* @__PURE__ */ jsxs(Drawer.Header, { children: [
|
|
225
|
+
/* @__PURE__ */ jsx(Drawer.Title, { asChild: true, children: /* @__PURE__ */ jsx(Heading, { children: editingView ? "Edit View Name" : "Save as New View" }) }),
|
|
226
|
+
/* @__PURE__ */ jsx(Drawer.Description, { asChild: true, children: /* @__PURE__ */ jsx(Text, { children: editingView ? "Change the name of your saved view" : "Save your current configuration as a new view" }) })
|
|
227
|
+
] }),
|
|
228
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(onSubmit), className: "flex flex-1 flex-col", children: [
|
|
229
|
+
/* @__PURE__ */ jsx(Drawer.Body, { className: "flex-1", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
230
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "name", weight: "plus", children: "View Name" }),
|
|
231
|
+
/* @__PURE__ */ jsx(
|
|
232
|
+
Input,
|
|
233
|
+
{
|
|
234
|
+
...register("name", {
|
|
235
|
+
required: "Name is required",
|
|
236
|
+
validate: (value) => value.trim().length > 0 || "Name cannot be empty"
|
|
237
|
+
}),
|
|
238
|
+
type: "text",
|
|
239
|
+
placeholder: "Enter view name",
|
|
240
|
+
autoFocus: true
|
|
241
|
+
}
|
|
242
|
+
),
|
|
243
|
+
errors.name && /* @__PURE__ */ jsx("span", { className: "text-sm text-ui-fg-error", children: errors.name.message })
|
|
244
|
+
] }) }),
|
|
245
|
+
/* @__PURE__ */ jsxs(Drawer.Footer, { children: [
|
|
246
|
+
/* @__PURE__ */ jsx(Drawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
247
|
+
Button,
|
|
248
|
+
{
|
|
249
|
+
variant: "secondary",
|
|
250
|
+
size: "small",
|
|
251
|
+
type: "button",
|
|
252
|
+
children: "Cancel"
|
|
253
|
+
}
|
|
254
|
+
) }),
|
|
255
|
+
/* @__PURE__ */ jsx(
|
|
256
|
+
Button,
|
|
257
|
+
{
|
|
258
|
+
variant: "primary",
|
|
259
|
+
size: "small",
|
|
260
|
+
type: "submit",
|
|
261
|
+
isLoading,
|
|
262
|
+
children: editingView ? "Update" : "Save"
|
|
263
|
+
}
|
|
264
|
+
)
|
|
265
|
+
] })
|
|
266
|
+
] })
|
|
267
|
+
] }) });
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// src/components/table/view-selector/view-selector.tsx
|
|
271
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
272
|
+
|
|
273
|
+
// src/components/table/view-selector/view-pills.tsx
|
|
274
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
275
|
+
import {
|
|
276
|
+
Badge as Badge2,
|
|
277
|
+
usePrompt as usePrompt2,
|
|
278
|
+
toast as toast3,
|
|
279
|
+
DropdownMenu as DropdownMenu2
|
|
280
|
+
} from "@acmekit/ui";
|
|
281
|
+
import {
|
|
282
|
+
Trash as Trash2,
|
|
283
|
+
PencilSquare as PencilSquare2,
|
|
284
|
+
ArrowUturnLeft as ArrowUturnLeft2
|
|
285
|
+
} from "@acmekit/icons";
|
|
286
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
287
|
+
var ViewPills = ({
|
|
288
|
+
entity,
|
|
289
|
+
currentColumns,
|
|
290
|
+
currentConfiguration
|
|
291
|
+
}) => {
|
|
292
|
+
const {
|
|
293
|
+
listViews,
|
|
294
|
+
activeView,
|
|
295
|
+
setActiveView,
|
|
296
|
+
isDefaultViewActive
|
|
297
|
+
} = useViewConfigurations2(entity);
|
|
298
|
+
const views = listViews?.view_configurations || [];
|
|
299
|
+
const [saveDialogOpen, setSaveDialogOpen] = useState3(false);
|
|
300
|
+
const [editingView, setEditingView] = useState3(null);
|
|
301
|
+
const [contextMenuOpen, setContextMenuOpen] = useState3(null);
|
|
302
|
+
const [contextMenuPosition, setContextMenuPosition] = useState3({ x: 0, y: 0 });
|
|
303
|
+
const [deletingViewId, setDeletingViewId] = useState3(null);
|
|
304
|
+
const prompt = usePrompt2();
|
|
305
|
+
const currentActiveView = activeView?.view_configuration || null;
|
|
306
|
+
const { deleteView } = useViewConfiguration(entity, deletingViewId || "");
|
|
307
|
+
const handleViewSelect = async (viewId) => {
|
|
308
|
+
try {
|
|
309
|
+
if (viewId === null) {
|
|
310
|
+
await setActiveView.mutateAsync(null);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
const view = views.find((v) => v.id === viewId);
|
|
314
|
+
if (view) {
|
|
315
|
+
await setActiveView.mutateAsync(viewId);
|
|
316
|
+
}
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error("Error in handleViewSelect:", error);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
const handleDeleteView = async (view) => {
|
|
322
|
+
const result = await prompt({
|
|
323
|
+
title: "Delete view",
|
|
324
|
+
description: `Are you sure you want to delete "${view.name}"? This action cannot be undone.`,
|
|
325
|
+
confirmText: "Delete",
|
|
326
|
+
cancelText: "Cancel"
|
|
327
|
+
});
|
|
328
|
+
if (result) {
|
|
329
|
+
setDeletingViewId(view.id);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
useEffect2(() => {
|
|
333
|
+
if (deletingViewId && deleteView.mutateAsync) {
|
|
334
|
+
deleteView.mutateAsync().then(() => {
|
|
335
|
+
setDeletingViewId(null);
|
|
336
|
+
}).catch(() => {
|
|
337
|
+
setDeletingViewId(null);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}, [deletingViewId, deleteView.mutateAsync]);
|
|
341
|
+
const handleEditView = (view) => {
|
|
342
|
+
setEditingView(view);
|
|
343
|
+
setSaveDialogOpen(true);
|
|
344
|
+
};
|
|
345
|
+
const handleResetSystemDefault = async (systemDefaultView2) => {
|
|
346
|
+
const result = await prompt({
|
|
347
|
+
title: "Reset system default",
|
|
348
|
+
description: "This will delete the saved system default and revert to the original code-level defaults. All users will be affected. Are you sure?",
|
|
349
|
+
confirmText: "Reset",
|
|
350
|
+
cancelText: "Cancel"
|
|
351
|
+
});
|
|
352
|
+
if (result) {
|
|
353
|
+
setDeletingViewId(systemDefaultView2.id);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
const systemDefaultView = views.find((v) => v.is_system_default);
|
|
357
|
+
const personalViews = views.filter((v) => !v.is_system_default);
|
|
358
|
+
const isDefaultActive = isDefaultViewActive;
|
|
359
|
+
const defaultLabel = "Default";
|
|
360
|
+
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
361
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
|
|
362
|
+
/* @__PURE__ */ jsxs3("div", { className: "relative inline-block", children: [
|
|
363
|
+
/* @__PURE__ */ jsx3(
|
|
364
|
+
Badge2,
|
|
365
|
+
{
|
|
366
|
+
color: isDefaultActive ? "blue" : "grey",
|
|
367
|
+
size: "xsmall",
|
|
368
|
+
className: "cursor-pointer",
|
|
369
|
+
onClick: () => handleViewSelect(null),
|
|
370
|
+
onContextMenu: (e) => {
|
|
371
|
+
e.preventDefault();
|
|
372
|
+
if (systemDefaultView) {
|
|
373
|
+
setContextMenuPosition({ x: e.clientX, y: e.clientY });
|
|
374
|
+
setContextMenuOpen("default");
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
children: defaultLabel
|
|
378
|
+
}
|
|
379
|
+
),
|
|
380
|
+
systemDefaultView && contextMenuOpen === "default" && /* @__PURE__ */ jsxs3(
|
|
381
|
+
DropdownMenu2,
|
|
382
|
+
{
|
|
383
|
+
open: true,
|
|
384
|
+
onOpenChange: (open) => {
|
|
385
|
+
if (!open) setContextMenuOpen(null);
|
|
386
|
+
},
|
|
387
|
+
children: [
|
|
388
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx3(
|
|
389
|
+
"div",
|
|
390
|
+
{
|
|
391
|
+
style: {
|
|
392
|
+
position: "fixed",
|
|
393
|
+
left: contextMenuPosition.x,
|
|
394
|
+
top: contextMenuPosition.y,
|
|
395
|
+
width: 0,
|
|
396
|
+
height: 0
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
) }),
|
|
400
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Content, { align: "start", sideOffset: 0, children: /* @__PURE__ */ jsxs3(
|
|
401
|
+
DropdownMenu2.Item,
|
|
402
|
+
{
|
|
403
|
+
onClick: () => {
|
|
404
|
+
handleResetSystemDefault(systemDefaultView);
|
|
405
|
+
setContextMenuOpen(null);
|
|
406
|
+
},
|
|
407
|
+
className: "flex items-center gap-x-2",
|
|
408
|
+
children: [
|
|
409
|
+
/* @__PURE__ */ jsx3(ArrowUturnLeft2, { className: "text-ui-fg-subtle" }),
|
|
410
|
+
/* @__PURE__ */ jsx3("span", { children: "Reset to code defaults" })
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
) })
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
)
|
|
417
|
+
] }),
|
|
418
|
+
personalViews.length > 0 && /* @__PURE__ */ jsx3("div", { className: "text-ui-fg-muted", children: "|" }),
|
|
419
|
+
personalViews.map((view) => /* @__PURE__ */ jsxs3("div", { className: "relative inline-block", children: [
|
|
420
|
+
/* @__PURE__ */ jsx3(
|
|
421
|
+
Badge2,
|
|
422
|
+
{
|
|
423
|
+
color: currentActiveView?.id === view.id ? "blue" : "grey",
|
|
424
|
+
size: "xsmall",
|
|
425
|
+
className: "cursor-pointer",
|
|
426
|
+
onClick: () => handleViewSelect(view.id),
|
|
427
|
+
onContextMenu: (e) => {
|
|
428
|
+
e.preventDefault();
|
|
429
|
+
setContextMenuPosition({ x: e.clientX, y: e.clientY });
|
|
430
|
+
setContextMenuOpen(view.id);
|
|
431
|
+
},
|
|
432
|
+
children: view.name
|
|
433
|
+
}
|
|
434
|
+
),
|
|
435
|
+
contextMenuOpen === view.id && /* @__PURE__ */ jsxs3(
|
|
436
|
+
DropdownMenu2,
|
|
437
|
+
{
|
|
438
|
+
open: true,
|
|
439
|
+
onOpenChange: (open) => {
|
|
440
|
+
if (!open) setContextMenuOpen(null);
|
|
441
|
+
},
|
|
442
|
+
children: [
|
|
443
|
+
/* @__PURE__ */ jsx3(DropdownMenu2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx3(
|
|
444
|
+
"div",
|
|
445
|
+
{
|
|
446
|
+
style: {
|
|
447
|
+
position: "fixed",
|
|
448
|
+
left: contextMenuPosition.x,
|
|
449
|
+
top: contextMenuPosition.y,
|
|
450
|
+
width: 0,
|
|
451
|
+
height: 0
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
) }),
|
|
455
|
+
/* @__PURE__ */ jsxs3(DropdownMenu2.Content, { align: "start", sideOffset: 0, children: [
|
|
456
|
+
/* @__PURE__ */ jsxs3(
|
|
457
|
+
DropdownMenu2.Item,
|
|
458
|
+
{
|
|
459
|
+
onClick: () => {
|
|
460
|
+
handleEditView(view);
|
|
461
|
+
setContextMenuOpen(null);
|
|
462
|
+
},
|
|
463
|
+
className: "flex items-center gap-x-2",
|
|
464
|
+
children: [
|
|
465
|
+
/* @__PURE__ */ jsx3(PencilSquare2, { className: "text-ui-fg-subtle" }),
|
|
466
|
+
/* @__PURE__ */ jsx3("span", { children: "Edit name" })
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
),
|
|
470
|
+
/* @__PURE__ */ jsxs3(
|
|
471
|
+
DropdownMenu2.Item,
|
|
472
|
+
{
|
|
473
|
+
onClick: () => {
|
|
474
|
+
handleDeleteView(view);
|
|
475
|
+
setContextMenuOpen(null);
|
|
476
|
+
},
|
|
477
|
+
className: "flex items-center gap-x-2 text-ui-fg-error",
|
|
478
|
+
children: [
|
|
479
|
+
/* @__PURE__ */ jsx3(Trash2, {}),
|
|
480
|
+
/* @__PURE__ */ jsx3("span", { children: "Delete" })
|
|
481
|
+
]
|
|
482
|
+
}
|
|
483
|
+
)
|
|
484
|
+
] })
|
|
485
|
+
]
|
|
486
|
+
}
|
|
487
|
+
)
|
|
488
|
+
] }, view.id))
|
|
489
|
+
] }),
|
|
490
|
+
saveDialogOpen && /* @__PURE__ */ jsx3(
|
|
491
|
+
SaveViewDialog,
|
|
492
|
+
{
|
|
493
|
+
entity,
|
|
494
|
+
currentColumns,
|
|
495
|
+
currentConfiguration,
|
|
496
|
+
editingView,
|
|
497
|
+
onClose: () => {
|
|
498
|
+
setSaveDialogOpen(false);
|
|
499
|
+
setEditingView(null);
|
|
500
|
+
},
|
|
501
|
+
onSaved: async (newView) => {
|
|
502
|
+
setSaveDialogOpen(false);
|
|
503
|
+
setEditingView(null);
|
|
504
|
+
toast3.success(`View "${newView.name}" saved successfully`);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
)
|
|
508
|
+
] });
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
// src/components/data-table/data-table.tsx
|
|
512
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
513
|
+
var DataTable = ({
|
|
514
|
+
data = [],
|
|
515
|
+
columns,
|
|
516
|
+
filters,
|
|
517
|
+
commands,
|
|
518
|
+
action,
|
|
519
|
+
actions,
|
|
520
|
+
actionMenu,
|
|
521
|
+
getRowId,
|
|
522
|
+
rowCount = 0,
|
|
523
|
+
enablePagination = true,
|
|
524
|
+
enableSearch = true,
|
|
525
|
+
autoFocusSearch = false,
|
|
526
|
+
enableFilterMenu,
|
|
527
|
+
rowHref,
|
|
528
|
+
heading,
|
|
529
|
+
headingLevel = "h1",
|
|
530
|
+
subHeading,
|
|
531
|
+
prefix,
|
|
532
|
+
pageSize = 10,
|
|
533
|
+
emptyState,
|
|
534
|
+
rowSelection,
|
|
535
|
+
isLoading = false,
|
|
536
|
+
layout = "auto",
|
|
537
|
+
enableColumnVisibility = false,
|
|
538
|
+
initialColumnVisibility = {},
|
|
539
|
+
onColumnVisibilityChange,
|
|
540
|
+
columnOrder,
|
|
541
|
+
onColumnOrderChange,
|
|
542
|
+
enableViewSelector = false,
|
|
543
|
+
entity,
|
|
544
|
+
currentColumns,
|
|
545
|
+
filterBarContent
|
|
546
|
+
}) => {
|
|
547
|
+
const { t } = useTranslation();
|
|
548
|
+
const isViewConfigEnabled = useFeatureFlag("view_configurations");
|
|
549
|
+
const effectiveEnableColumnVisibility = isViewConfigEnabled && enableColumnVisibility;
|
|
550
|
+
const effectiveEnableViewSelector = isViewConfigEnabled && enableViewSelector;
|
|
551
|
+
const enableFiltering = filters && filters.length > 0;
|
|
552
|
+
const showFilterMenu = enableFilterMenu !== void 0 ? enableFilterMenu : enableFiltering;
|
|
553
|
+
const enableCommands = commands && commands.length > 0;
|
|
554
|
+
const enableSorting = columns.some((column) => column.enableSorting);
|
|
555
|
+
const [columnVisibility, setColumnVisibility] = React4.useState(initialColumnVisibility);
|
|
556
|
+
React4.useEffect(() => {
|
|
557
|
+
const currentKeys = Object.keys(columnVisibility).sort();
|
|
558
|
+
const newKeys = Object.keys(initialColumnVisibility).sort();
|
|
559
|
+
const hasChanged = currentKeys.length !== newKeys.length || currentKeys.some((key, index) => key !== newKeys[index]) || Object.entries(initialColumnVisibility).some(
|
|
560
|
+
([key, value]) => columnVisibility[key] !== value
|
|
561
|
+
);
|
|
562
|
+
if (hasChanged) {
|
|
563
|
+
setColumnVisibility(initialColumnVisibility);
|
|
564
|
+
}
|
|
565
|
+
}, [initialColumnVisibility]);
|
|
566
|
+
const handleColumnVisibilityChange = React4.useCallback(
|
|
567
|
+
(visibility) => {
|
|
568
|
+
setColumnVisibility(visibility);
|
|
569
|
+
onColumnVisibilityChange?.(visibility);
|
|
570
|
+
},
|
|
571
|
+
[onColumnVisibilityChange]
|
|
572
|
+
);
|
|
573
|
+
const filterIds = useMemo2(() => filters?.map((f) => f.id) ?? [], [filters]);
|
|
574
|
+
const prefixedFilterIds = filterIds.map((id) => getQueryParamKey(id, prefix));
|
|
575
|
+
const { offset, order, q, ...filterParams } = useQueryParams(
|
|
576
|
+
[
|
|
577
|
+
...filterIds,
|
|
578
|
+
...enableSorting ? ["order"] : [],
|
|
579
|
+
...enableSearch ? ["q"] : [],
|
|
580
|
+
...enablePagination ? ["offset"] : []
|
|
581
|
+
],
|
|
582
|
+
prefix
|
|
583
|
+
);
|
|
584
|
+
const [_, setSearchParams] = useSearchParams();
|
|
585
|
+
const search = useMemo2(() => {
|
|
586
|
+
return q ?? "";
|
|
587
|
+
}, [q]);
|
|
588
|
+
const handleSearchChange = (value) => {
|
|
589
|
+
setSearchParams((prev) => {
|
|
590
|
+
if (value) {
|
|
591
|
+
prev.set(getQueryParamKey("q", prefix), value);
|
|
592
|
+
} else {
|
|
593
|
+
prev.delete(getQueryParamKey("q", prefix));
|
|
594
|
+
}
|
|
595
|
+
return prev;
|
|
596
|
+
});
|
|
597
|
+
};
|
|
598
|
+
const pagination = useMemo2(() => {
|
|
599
|
+
return offset ? parsePaginationState(offset, pageSize) : { pageIndex: 0, pageSize };
|
|
600
|
+
}, [offset, pageSize]);
|
|
601
|
+
const handlePaginationChange = (value) => {
|
|
602
|
+
setSearchParams((prev) => {
|
|
603
|
+
if (value.pageIndex === 0) {
|
|
604
|
+
prev.delete(getQueryParamKey("offset", prefix));
|
|
605
|
+
} else {
|
|
606
|
+
prev.set(
|
|
607
|
+
getQueryParamKey("offset", prefix),
|
|
608
|
+
transformPaginationState(value).toString()
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
return prev;
|
|
612
|
+
});
|
|
613
|
+
};
|
|
614
|
+
const filtering = useMemo2(
|
|
615
|
+
() => parseFilterState(filterIds, filterParams),
|
|
616
|
+
[filterIds, filterParams]
|
|
617
|
+
);
|
|
618
|
+
const handleFilteringChange = (value) => {
|
|
619
|
+
setSearchParams((prev) => {
|
|
620
|
+
Array.from(prev.keys()).forEach((key) => {
|
|
621
|
+
if (prefixedFilterIds.includes(key)) {
|
|
622
|
+
const unprefixedKey = prefix ? key.replace(`${prefix}_`, "") : key;
|
|
623
|
+
if (!(unprefixedKey in value)) {
|
|
624
|
+
prev.delete(key);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
Object.entries(value).forEach(([key, filter]) => {
|
|
629
|
+
const prefixedKey = getQueryParamKey(key, prefix);
|
|
630
|
+
if (filter !== void 0) {
|
|
631
|
+
prev.set(prefixedKey, JSON.stringify(filter));
|
|
632
|
+
} else {
|
|
633
|
+
prev.delete(prefixedKey);
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
return prev;
|
|
637
|
+
});
|
|
638
|
+
};
|
|
639
|
+
const sorting = useMemo2(() => {
|
|
640
|
+
return order ? parseSortingState(order) : null;
|
|
641
|
+
}, [order]);
|
|
642
|
+
const currentConfiguration = useMemo2(
|
|
643
|
+
() => ({
|
|
644
|
+
filters: filtering,
|
|
645
|
+
sorting,
|
|
646
|
+
search
|
|
647
|
+
}),
|
|
648
|
+
[filtering, sorting, search]
|
|
649
|
+
);
|
|
650
|
+
const handleSortingChange = (value) => {
|
|
651
|
+
setSearchParams((prev) => {
|
|
652
|
+
if (value) {
|
|
653
|
+
const valueToStore = transformSortingState(value);
|
|
654
|
+
prev.set(getQueryParamKey("order", prefix), valueToStore);
|
|
655
|
+
} else {
|
|
656
|
+
prev.delete(getQueryParamKey("order", prefix));
|
|
657
|
+
}
|
|
658
|
+
return prev;
|
|
659
|
+
});
|
|
660
|
+
};
|
|
661
|
+
const { pagination: paginationTranslations, toolbar: toolbarTranslations } = useDataTableTranslations();
|
|
662
|
+
const navigate = useNavigate();
|
|
663
|
+
const onRowClick = useCallback(
|
|
664
|
+
(event, row) => {
|
|
665
|
+
if (!rowHref) {
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
const href = rowHref(row);
|
|
669
|
+
const basePath = __BASE__ || "/";
|
|
670
|
+
const hrefWithBasePath = `${basePath === "/" ? "" : basePath}${href}`;
|
|
671
|
+
if (event.metaKey || event.ctrlKey || event.button === 1) {
|
|
672
|
+
window.open(hrefWithBasePath, "_blank", "noreferrer");
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (event.shiftKey) {
|
|
676
|
+
window.open(hrefWithBasePath, void 0, "noreferrer");
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
navigate(href);
|
|
680
|
+
},
|
|
681
|
+
[navigate, rowHref]
|
|
682
|
+
);
|
|
683
|
+
const instance = useDataTable({
|
|
684
|
+
data,
|
|
685
|
+
columns,
|
|
686
|
+
filters,
|
|
687
|
+
commands,
|
|
688
|
+
rowCount,
|
|
689
|
+
getRowId,
|
|
690
|
+
onRowClick: rowHref ? onRowClick : void 0,
|
|
691
|
+
pagination: enablePagination ? {
|
|
692
|
+
state: pagination,
|
|
693
|
+
onPaginationChange: handlePaginationChange
|
|
694
|
+
} : void 0,
|
|
695
|
+
filtering: enableFiltering ? {
|
|
696
|
+
state: filtering,
|
|
697
|
+
onFilteringChange: handleFilteringChange
|
|
698
|
+
} : void 0,
|
|
699
|
+
sorting: enableSorting ? {
|
|
700
|
+
state: sorting,
|
|
701
|
+
onSortingChange: handleSortingChange
|
|
702
|
+
} : void 0,
|
|
703
|
+
search: enableSearch ? {
|
|
704
|
+
state: search,
|
|
705
|
+
onSearchChange: handleSearchChange
|
|
706
|
+
} : void 0,
|
|
707
|
+
rowSelection,
|
|
708
|
+
isLoading,
|
|
709
|
+
columnVisibility: effectiveEnableColumnVisibility ? {
|
|
710
|
+
state: columnVisibility,
|
|
711
|
+
onColumnVisibilityChange: handleColumnVisibilityChange
|
|
712
|
+
} : void 0,
|
|
713
|
+
columnOrder: effectiveEnableColumnVisibility && columnOrder && onColumnOrderChange ? {
|
|
714
|
+
state: columnOrder,
|
|
715
|
+
onColumnOrderChange
|
|
716
|
+
} : void 0
|
|
717
|
+
});
|
|
718
|
+
const shouldRenderHeading = heading || subHeading;
|
|
719
|
+
return /* @__PURE__ */ jsxs4(
|
|
720
|
+
UiDataTable,
|
|
721
|
+
{
|
|
722
|
+
instance,
|
|
723
|
+
className: layout === "fill" ? "h-full [&_tr]:last-of-type:!border-b" : void 0,
|
|
724
|
+
children: [
|
|
725
|
+
/* @__PURE__ */ jsx4(
|
|
726
|
+
UiDataTable.Toolbar,
|
|
727
|
+
{
|
|
728
|
+
className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center",
|
|
729
|
+
translations: toolbarTranslations,
|
|
730
|
+
filterBarContent,
|
|
731
|
+
children: /* @__PURE__ */ jsxs4("div", { className: "flex w-full items-center justify-between gap-2", children: [
|
|
732
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-x-4", children: [
|
|
733
|
+
shouldRenderHeading && /* @__PURE__ */ jsxs4("div", { children: [
|
|
734
|
+
heading && /* @__PURE__ */ jsx4(Heading2, { level: headingLevel, children: heading }),
|
|
735
|
+
subHeading && /* @__PURE__ */ jsx4(Text2, { size: "small", className: "text-ui-fg-subtle", children: subHeading })
|
|
736
|
+
] }),
|
|
737
|
+
effectiveEnableViewSelector && entity && /* @__PURE__ */ jsx4(
|
|
738
|
+
ViewPills,
|
|
739
|
+
{
|
|
740
|
+
entity,
|
|
741
|
+
currentColumns,
|
|
742
|
+
currentConfiguration
|
|
743
|
+
}
|
|
744
|
+
)
|
|
745
|
+
] }),
|
|
746
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-x-2", children: [
|
|
747
|
+
showFilterMenu && /* @__PURE__ */ jsx4(UiDataTable.FilterMenu, {}),
|
|
748
|
+
enableSorting && /* @__PURE__ */ jsx4(UiDataTable.SortingMenu, {}),
|
|
749
|
+
enableSearch && /* @__PURE__ */ jsx4("div", { className: "w-full md:w-auto", children: /* @__PURE__ */ jsx4(
|
|
750
|
+
UiDataTable.Search,
|
|
751
|
+
{
|
|
752
|
+
placeholder: t("filters.searchLabel"),
|
|
753
|
+
autoFocus: autoFocusSearch
|
|
754
|
+
}
|
|
755
|
+
) }),
|
|
756
|
+
actionMenu && /* @__PURE__ */ jsx4(ActionMenu, { variant: "primary", ...actionMenu }),
|
|
757
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsx4(DataTableActions, { actions }),
|
|
758
|
+
!actions && action && /* @__PURE__ */ jsx4(DataTableAction, { ...action })
|
|
759
|
+
] })
|
|
760
|
+
] })
|
|
761
|
+
}
|
|
762
|
+
),
|
|
763
|
+
/* @__PURE__ */ jsx4(UiDataTable.Table, { emptyState }),
|
|
764
|
+
enablePagination && /* @__PURE__ */ jsx4(UiDataTable.Pagination, { translations: paginationTranslations }),
|
|
765
|
+
enableCommands && /* @__PURE__ */ jsx4(
|
|
766
|
+
UiDataTable.CommandBar,
|
|
767
|
+
{
|
|
768
|
+
selectedLabel: (count) => `${count} selected`
|
|
769
|
+
}
|
|
770
|
+
)
|
|
771
|
+
]
|
|
772
|
+
}
|
|
773
|
+
);
|
|
774
|
+
};
|
|
775
|
+
function transformSortingState(value) {
|
|
776
|
+
return value.desc ? `-${value.id}` : value.id;
|
|
777
|
+
}
|
|
778
|
+
function parseSortingState(value) {
|
|
779
|
+
return value.startsWith("-") ? { id: value.slice(1), desc: true } : { id: value, desc: false };
|
|
780
|
+
}
|
|
781
|
+
function transformPaginationState(value) {
|
|
782
|
+
return value.pageIndex * value.pageSize;
|
|
783
|
+
}
|
|
784
|
+
function parsePaginationState(value, pageSize) {
|
|
785
|
+
const offset = parseInt(value);
|
|
786
|
+
return {
|
|
787
|
+
pageIndex: Math.floor(offset / pageSize),
|
|
788
|
+
pageSize
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function parseFilterState(filterIds, value) {
|
|
792
|
+
if (!value) {
|
|
793
|
+
return {};
|
|
794
|
+
}
|
|
795
|
+
const filters = {};
|
|
796
|
+
for (const id of filterIds) {
|
|
797
|
+
const filterValue = value[id];
|
|
798
|
+
if (filterValue !== void 0) {
|
|
799
|
+
filters[id] = JSON.parse(filterValue);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return filters;
|
|
803
|
+
}
|
|
804
|
+
function getQueryParamKey(key, prefix) {
|
|
805
|
+
return prefix ? `${prefix}_${key}` : key;
|
|
806
|
+
}
|
|
807
|
+
var useDataTableTranslations = () => {
|
|
808
|
+
const { t } = useTranslation();
|
|
809
|
+
const paginationTranslations = {
|
|
810
|
+
of: t("general.of"),
|
|
811
|
+
results: t("general.results"),
|
|
812
|
+
pages: t("general.pages"),
|
|
813
|
+
prev: t("general.prev"),
|
|
814
|
+
next: t("general.next")
|
|
815
|
+
};
|
|
816
|
+
const toolbarTranslations = {
|
|
817
|
+
clearAll: t("actions.clearAll"),
|
|
818
|
+
sort: t("filters.sortLabel"),
|
|
819
|
+
columns: "Columns"
|
|
820
|
+
};
|
|
821
|
+
return {
|
|
822
|
+
pagination: paginationTranslations,
|
|
823
|
+
toolbar: toolbarTranslations
|
|
824
|
+
};
|
|
825
|
+
};
|
|
826
|
+
var DataTableAction = ({
|
|
827
|
+
label,
|
|
828
|
+
disabled,
|
|
829
|
+
...props
|
|
830
|
+
}) => {
|
|
831
|
+
const buttonProps = {
|
|
832
|
+
size: "small",
|
|
833
|
+
disabled: disabled ?? false,
|
|
834
|
+
type: "button",
|
|
835
|
+
variant: "secondary"
|
|
836
|
+
};
|
|
837
|
+
if ("to" in props) {
|
|
838
|
+
return /* @__PURE__ */ jsx4(Button3, { ...buttonProps, asChild: true, children: /* @__PURE__ */ jsx4(Link, { to: props.to, children: label }) });
|
|
839
|
+
}
|
|
840
|
+
return /* @__PURE__ */ jsx4(Button3, { ...buttonProps, onClick: props.onClick, children: label });
|
|
841
|
+
};
|
|
842
|
+
var DataTableActions = ({ actions }) => {
|
|
843
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex items-center gap-x-2", children: actions.map((action, index) => /* @__PURE__ */ jsx4(DataTableAction, { ...action }, index)) });
|
|
844
|
+
};
|
|
845
|
+
|
|
846
|
+
// src/components/data-table/helpers/general/use-data-table-date-columns.tsx
|
|
847
|
+
import {
|
|
848
|
+
createDataTableColumnHelper,
|
|
849
|
+
Tooltip as Tooltip2
|
|
850
|
+
} from "@acmekit/ui";
|
|
851
|
+
import { useMemo as useMemo3 } from "react";
|
|
852
|
+
import { useTranslation as useTranslation2 } from "react-i18next";
|
|
853
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
854
|
+
var columnHelper = createDataTableColumnHelper();
|
|
855
|
+
var useDataTableDateColumns = () => {
|
|
856
|
+
const { t } = useTranslation2();
|
|
857
|
+
const { getFullDate } = useDate();
|
|
858
|
+
return useMemo3(() => {
|
|
859
|
+
return [
|
|
860
|
+
columnHelper.accessor("created_at", {
|
|
861
|
+
header: t("fields.createdAt"),
|
|
862
|
+
cell: ({ row }) => {
|
|
863
|
+
return /* @__PURE__ */ jsx5(
|
|
864
|
+
Tooltip2,
|
|
865
|
+
{
|
|
866
|
+
content: getFullDate({
|
|
867
|
+
date: row.original.created_at,
|
|
868
|
+
includeTime: true
|
|
869
|
+
}),
|
|
870
|
+
children: /* @__PURE__ */ jsx5("span", { children: getFullDate({ date: row.original.created_at }) })
|
|
871
|
+
}
|
|
872
|
+
);
|
|
873
|
+
},
|
|
874
|
+
enableSorting: true,
|
|
875
|
+
sortAscLabel: t("filters.sorting.dateAsc"),
|
|
876
|
+
sortDescLabel: t("filters.sorting.dateDesc")
|
|
877
|
+
}),
|
|
878
|
+
columnHelper.accessor("updated_at", {
|
|
879
|
+
header: t("fields.updatedAt"),
|
|
880
|
+
cell: ({ row }) => {
|
|
881
|
+
return /* @__PURE__ */ jsx5(
|
|
882
|
+
Tooltip2,
|
|
883
|
+
{
|
|
884
|
+
content: getFullDate({
|
|
885
|
+
date: row.original.updated_at,
|
|
886
|
+
includeTime: true
|
|
887
|
+
}),
|
|
888
|
+
children: /* @__PURE__ */ jsx5("span", { children: getFullDate({ date: row.original.updated_at }) })
|
|
889
|
+
}
|
|
890
|
+
);
|
|
891
|
+
},
|
|
892
|
+
enableSorting: true,
|
|
893
|
+
sortAscLabel: t("filters.sorting.dateAsc"),
|
|
894
|
+
sortDescLabel: t("filters.sorting.dateDesc")
|
|
895
|
+
})
|
|
896
|
+
];
|
|
897
|
+
}, [t, getFullDate]);
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
// src/components/data-table/helpers/general/use-data-table-date-filters.tsx
|
|
901
|
+
import { createDataTableFilterHelper } from "@acmekit/ui";
|
|
902
|
+
import { subDays, subMonths } from "date-fns";
|
|
903
|
+
import { useMemo as useMemo4 } from "react";
|
|
904
|
+
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
905
|
+
var filterHelper = createDataTableFilterHelper();
|
|
906
|
+
var useDateFilterOptions = () => {
|
|
907
|
+
const { t } = useTranslation3();
|
|
908
|
+
const today = useMemo4(() => {
|
|
909
|
+
const date = /* @__PURE__ */ new Date();
|
|
910
|
+
date.setHours(0, 0, 0, 0);
|
|
911
|
+
return date;
|
|
912
|
+
}, []);
|
|
913
|
+
return useMemo4(() => {
|
|
914
|
+
return [
|
|
915
|
+
{
|
|
916
|
+
label: t("filters.date.today"),
|
|
917
|
+
value: {
|
|
918
|
+
$gte: today.toISOString()
|
|
919
|
+
}
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
label: t("filters.date.lastSevenDays"),
|
|
923
|
+
value: {
|
|
924
|
+
$gte: subDays(today, 7).toISOString()
|
|
925
|
+
// 7 days ago
|
|
926
|
+
}
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
label: t("filters.date.lastThirtyDays"),
|
|
930
|
+
value: {
|
|
931
|
+
$gte: subDays(today, 30).toISOString()
|
|
932
|
+
// 30 days ago
|
|
933
|
+
}
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
label: t("filters.date.lastNinetyDays"),
|
|
937
|
+
value: {
|
|
938
|
+
$gte: subDays(today, 90).toISOString()
|
|
939
|
+
// 90 days ago
|
|
940
|
+
}
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
label: t("filters.date.lastTwelveMonths"),
|
|
944
|
+
value: {
|
|
945
|
+
$gte: subMonths(today, 12).toISOString()
|
|
946
|
+
// 12 months ago
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
];
|
|
950
|
+
}, [today, t]);
|
|
951
|
+
};
|
|
952
|
+
var useDataTableDateFilters = (disableRangeOption) => {
|
|
953
|
+
const { t } = useTranslation3();
|
|
954
|
+
const { getFullDate } = useDate();
|
|
955
|
+
const dateFilterOptions = useDateFilterOptions();
|
|
956
|
+
const rangeOptions = useMemo4(() => {
|
|
957
|
+
if (disableRangeOption) {
|
|
958
|
+
return {
|
|
959
|
+
disableRangeOption: true
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
return {
|
|
963
|
+
rangeOptionStartLabel: t("filters.date.starting"),
|
|
964
|
+
rangeOptionEndLabel: t("filters.date.ending"),
|
|
965
|
+
rangeOptionLabel: t("filters.date.custom"),
|
|
966
|
+
options: dateFilterOptions
|
|
967
|
+
};
|
|
968
|
+
}, [disableRangeOption, t, dateFilterOptions]);
|
|
969
|
+
return useMemo4(() => {
|
|
970
|
+
return [
|
|
971
|
+
filterHelper.accessor("created_at", {
|
|
972
|
+
type: "date",
|
|
973
|
+
label: t("fields.createdAt"),
|
|
974
|
+
format: "date",
|
|
975
|
+
formatDateValue: (date) => getFullDate({ date }),
|
|
976
|
+
options: dateFilterOptions,
|
|
977
|
+
...rangeOptions
|
|
978
|
+
}),
|
|
979
|
+
filterHelper.accessor("updated_at", {
|
|
980
|
+
type: "date",
|
|
981
|
+
label: t("fields.updatedAt"),
|
|
982
|
+
format: "date",
|
|
983
|
+
formatDateValue: (date) => getFullDate({ date }),
|
|
984
|
+
options: dateFilterOptions,
|
|
985
|
+
...rangeOptions
|
|
986
|
+
})
|
|
987
|
+
];
|
|
988
|
+
}, [t, dateFilterOptions, getFullDate, rangeOptions]);
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
// src/routes/users/user-list/components/user-list-table/user-list-table.tsx
|
|
992
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
993
|
+
var PAGE_SIZE = 20;
|
|
994
|
+
var UserListTable = () => {
|
|
995
|
+
const { q, order, offset } = useQueryParams(["q", "order", "offset"]);
|
|
996
|
+
const { users, count, isPending, isError, error } = useUsers(
|
|
997
|
+
{
|
|
998
|
+
q,
|
|
999
|
+
order,
|
|
1000
|
+
offset: offset ? parseInt(offset) : 0,
|
|
1001
|
+
limit: PAGE_SIZE
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
placeholderData: keepPreviousData
|
|
1005
|
+
}
|
|
1006
|
+
);
|
|
1007
|
+
const columns = useColumns();
|
|
1008
|
+
const filters = useFilters();
|
|
1009
|
+
const { t } = useTranslation4();
|
|
1010
|
+
if (isError) {
|
|
1011
|
+
throw error;
|
|
1012
|
+
}
|
|
1013
|
+
return /* @__PURE__ */ jsx6(Container, { className: "divide-y p-0", children: /* @__PURE__ */ jsx6(
|
|
1014
|
+
DataTable,
|
|
1015
|
+
{
|
|
1016
|
+
data: users,
|
|
1017
|
+
columns,
|
|
1018
|
+
filters,
|
|
1019
|
+
getRowId: (row) => row.id,
|
|
1020
|
+
rowCount: count,
|
|
1021
|
+
pageSize: PAGE_SIZE,
|
|
1022
|
+
heading: t("users.domain"),
|
|
1023
|
+
rowHref: (row) => `${row.id}`,
|
|
1024
|
+
isLoading: isPending,
|
|
1025
|
+
action: {
|
|
1026
|
+
label: t("users.invite"),
|
|
1027
|
+
to: "invite"
|
|
1028
|
+
},
|
|
1029
|
+
emptyState: {
|
|
1030
|
+
empty: {
|
|
1031
|
+
heading: t("users.list.empty.heading"),
|
|
1032
|
+
description: t("users.list.empty.description")
|
|
1033
|
+
},
|
|
1034
|
+
filtered: {
|
|
1035
|
+
heading: t("users.list.filtered.heading"),
|
|
1036
|
+
description: t("users.list.filtered.description")
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
) });
|
|
1041
|
+
};
|
|
1042
|
+
var columnHelper2 = createDataTableColumnHelper2();
|
|
1043
|
+
var useColumns = () => {
|
|
1044
|
+
const { t } = useTranslation4();
|
|
1045
|
+
const navigate = useNavigate2();
|
|
1046
|
+
const dateColumns = useDataTableDateColumns();
|
|
1047
|
+
return useMemo5(
|
|
1048
|
+
() => [
|
|
1049
|
+
columnHelper2.accessor("email", {
|
|
1050
|
+
header: t("fields.email"),
|
|
1051
|
+
cell: ({ row }) => {
|
|
1052
|
+
return row.original.email;
|
|
1053
|
+
},
|
|
1054
|
+
enableSorting: true,
|
|
1055
|
+
sortAscLabel: t("filters.sorting.alphabeticallyAsc"),
|
|
1056
|
+
sortDescLabel: t("filters.sorting.alphabeticallyDesc")
|
|
1057
|
+
}),
|
|
1058
|
+
columnHelper2.accessor("first_name", {
|
|
1059
|
+
header: t("fields.firstName"),
|
|
1060
|
+
cell: ({ row }) => {
|
|
1061
|
+
return row.original.first_name || "-";
|
|
1062
|
+
},
|
|
1063
|
+
enableSorting: true,
|
|
1064
|
+
sortAscLabel: t("filters.sorting.alphabeticallyAsc"),
|
|
1065
|
+
sortDescLabel: t("filters.sorting.alphabeticallyDesc")
|
|
1066
|
+
}),
|
|
1067
|
+
columnHelper2.accessor("last_name", {
|
|
1068
|
+
header: t("fields.lastName"),
|
|
1069
|
+
cell: ({ row }) => {
|
|
1070
|
+
return row.original.last_name || "-";
|
|
1071
|
+
},
|
|
1072
|
+
enableSorting: true,
|
|
1073
|
+
sortAscLabel: t("filters.sorting.alphabeticallyAsc"),
|
|
1074
|
+
sortDescLabel: t("filters.sorting.alphabeticallyDesc")
|
|
1075
|
+
}),
|
|
1076
|
+
...dateColumns,
|
|
1077
|
+
columnHelper2.action({
|
|
1078
|
+
actions: [
|
|
1079
|
+
{
|
|
1080
|
+
label: t("actions.edit"),
|
|
1081
|
+
icon: /* @__PURE__ */ jsx6(PencilSquare3, {}),
|
|
1082
|
+
onClick: (ctx) => {
|
|
1083
|
+
navigate(`${ctx.row.original.id}/edit`);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
]
|
|
1087
|
+
})
|
|
1088
|
+
],
|
|
1089
|
+
[t, navigate, dateColumns]
|
|
1090
|
+
);
|
|
1091
|
+
};
|
|
1092
|
+
var useFilters = () => {
|
|
1093
|
+
const dateFilters = useDataTableDateFilters();
|
|
1094
|
+
return useMemo5(() => {
|
|
1095
|
+
return dateFilters;
|
|
1096
|
+
}, [dateFilters]);
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
// src/routes/users/user-list/user-list.tsx
|
|
1100
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1101
|
+
var UserList = () => {
|
|
1102
|
+
const { getWidgets } = useExtension();
|
|
1103
|
+
return /* @__PURE__ */ jsx7(
|
|
1104
|
+
SingleColumnPage,
|
|
1105
|
+
{
|
|
1106
|
+
widgets: {
|
|
1107
|
+
after: getWidgets("user.list.after"),
|
|
1108
|
+
before: getWidgets("user.list.before")
|
|
1109
|
+
},
|
|
1110
|
+
children: /* @__PURE__ */ jsx7(UserListTable, {})
|
|
1111
|
+
}
|
|
1112
|
+
);
|
|
1113
|
+
};
|
|
1114
|
+
export {
|
|
1115
|
+
UserList as Component
|
|
1116
|
+
};
|