@open-kingdom/shared-frontend-feature-user-management 0.0.2-16 → 0.0.2-17
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/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +598 -358
- package/dist/lib/components/invitations/AcceptInvitation.component.d.ts.map +1 -1
- package/dist/lib/components/invitations/InvitationList.component.d.ts.map +1 -1
- package/dist/lib/components/invitations/InviteUserModal.component.d.ts.map +1 -1
- package/dist/lib/components/roles/RoleList.component.d.ts +2 -0
- package/dist/lib/components/roles/RoleList.component.d.ts.map +1 -0
- package/dist/lib/components/roles/RolePermissionsModal.component.d.ts +11 -0
- package/dist/lib/components/roles/RolePermissionsModal.component.d.ts.map +1 -0
- package/dist/lib/components/roles/index.d.ts +3 -0
- package/dist/lib/components/roles/index.d.ts.map +1 -0
- package/dist/lib/components/shared/ConfirmDialog.component.d.ts.map +1 -1
- package/dist/lib/components/shared/FormField.component.d.ts.map +1 -1
- package/dist/lib/components/shared/RoleBadge.component.d.ts +1 -2
- package/dist/lib/components/shared/RoleBadge.component.d.ts.map +1 -1
- package/dist/lib/components/shared/StatusBadge.component.d.ts.map +1 -1
- package/dist/lib/components/shared/StatusCard.component.d.ts.map +1 -1
- package/dist/lib/components/users/RoleChangeModal.component.d.ts +12 -0
- package/dist/lib/components/users/RoleChangeModal.component.d.ts.map +1 -0
- package/dist/lib/components/users/UserList.component.d.ts.map +1 -1
- package/dist/lib/hooks/useHasPermission.d.ts +2 -0
- package/dist/lib/hooks/useHasPermission.d.ts.map +1 -0
- package/dist/lib/types.d.ts +2 -2
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +19 -1
- package/dist/lib/components/shared/ModalOverlay.component.d.ts +0 -9
- package/dist/lib/components/shared/ModalOverlay.component.d.ts.map +0 -1
- package/dist/lib/styles.d.ts +0 -9
- package/dist/lib/styles.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,411 +1,356 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
2
|
-
import {
|
|
1
|
+
import { jsx as e, jsxs as i } from "react/jsx-runtime";
|
|
2
|
+
import { useState as N, useMemo as R, useCallback as W } from "react";
|
|
3
3
|
import { useDispatch as I } from "react-redux";
|
|
4
|
-
import { useInvitationsControllerInviteMutation as
|
|
5
|
-
import { showSuccessNotification as
|
|
4
|
+
import { useInvitationsControllerInviteMutation as X, useRolesControllerFindAllQuery as F, useInvitationsControllerValidateQuery as Z, useInvitationsControllerAcceptMutation as _, useInvitationsControllerFindAllQuery as ee, useInvitationsControllerCancelMutation as te, useUserRolesControllerSetRolesMutation as ne, useAuthControllerGetProfileQuery as ie, useUsersControllerFindAllQuery as ae, useUsersControllerDeleteMutation as se, usePermissionsControllerFindAllQuery as re, useRolesControllerGetPermissionsQuery as le, useRolesControllerSetPermissionsMutation as oe, useRolesControllerDeleteMutation as de } from "@open-kingdom/shared-frontend-data-access-api-client";
|
|
5
|
+
import { showSuccessNotification as A } from "@open-kingdom/shared-frontend-data-access-notifications";
|
|
6
6
|
import { DataGrid as U } from "@open-kingdom/shared-frontend-ui-datagrid";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
function
|
|
7
|
+
import { AlertDialog as ce, AlertDialogContent as ue, AlertDialogHeader as me, AlertDialogTitle as fe, AlertDialogDescription as he, AlertDialogFooter as pe, AlertDialogCancel as ge, AlertDialogAction as ve, Badge as V, Label as be, Dialog as j, DialogContent as E, DialogHeader as O, DialogTitle as G, Input as P, Button as w, Card as M, CardContent as T, DialogDescription as $ } from "@open-kingdom/shared-frontend-ui-primitives";
|
|
8
|
+
import { useForm as B } from "react-hook-form";
|
|
9
|
+
import { zodResolver as q } from "@hookform/resolvers/zod";
|
|
10
|
+
import { z as C } from "zod";
|
|
11
|
+
import { formatDate as z } from "@open-kingdom/shared-poly-util-date";
|
|
12
|
+
import { useDeepCompareEffect as H } from "@react-hookz/web";
|
|
13
|
+
function Q({
|
|
14
14
|
isOpen: t,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
title: n,
|
|
16
|
+
message: s,
|
|
17
|
+
confirmLabel: m = "Confirm",
|
|
18
|
+
onConfirm: f,
|
|
19
|
+
onCancel: b,
|
|
20
|
+
isLoading: d = !1
|
|
18
21
|
}) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
22
|
-
const l = L((s) => {
|
|
23
|
-
s?.focus();
|
|
24
|
-
}, []);
|
|
25
|
-
return t ? /* @__PURE__ */ e(
|
|
26
|
-
"div",
|
|
22
|
+
return /* @__PURE__ */ e(
|
|
23
|
+
ce,
|
|
27
24
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
children: /* @__PURE__ */
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
open: t,
|
|
26
|
+
onOpenChange: (l) => !l && b(),
|
|
27
|
+
children: /* @__PURE__ */ i(ue, { children: [
|
|
28
|
+
/* @__PURE__ */ i(me, { children: [
|
|
29
|
+
/* @__PURE__ */ e(fe, { children: n }),
|
|
30
|
+
/* @__PURE__ */ e(he, { children: s })
|
|
31
|
+
] }),
|
|
32
|
+
/* @__PURE__ */ i(pe, { children: [
|
|
33
|
+
/* @__PURE__ */ e(
|
|
34
|
+
ge,
|
|
35
|
+
{
|
|
36
|
+
"data-testid": "confirm-cancel-btn",
|
|
37
|
+
disabled: d,
|
|
38
|
+
onClick: b,
|
|
39
|
+
children: "Cancel"
|
|
40
|
+
}
|
|
41
|
+
),
|
|
42
|
+
/* @__PURE__ */ e(
|
|
43
|
+
ve,
|
|
44
|
+
{
|
|
45
|
+
"data-testid": "confirm-btn",
|
|
46
|
+
disabled: d,
|
|
47
|
+
onClick: f,
|
|
48
|
+
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
49
|
+
children: m
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
] })
|
|
53
|
+
] })
|
|
43
54
|
}
|
|
44
|
-
)
|
|
45
|
-
}
|
|
46
|
-
const v = "w-full px-3 py-2 border border-neutral-300 dark:border-neutral-600 rounded-md bg-white dark:bg-neutral-700 text-neutral-900 dark:text-neutral-100", Z = "block text-sm font-medium text-neutral-700 dark:text-neutral-300 mb-1", C = "max-w-md mx-auto mt-8 p-6 bg-white dark:bg-neutral-800 rounded-lg shadow-lg", S = "text-neutral-600 dark:text-neutral-400", A = "rounded-md px-4 py-2 text-sm font-medium transition-colors", F = `${A} bg-primary-500 text-white hover:bg-primary-600 disabled:opacity-50`, E = `${A} border border-neutral-300 text-neutral-700 hover:bg-neutral-50 dark:border-neutral-600 dark:text-neutral-300 dark:hover:bg-neutral-700`, _ = `${A} bg-error-500 text-white hover:bg-error-600 disabled:opacity-50`, ee = "rounded px-2 py-1 text-xs font-medium text-error-600 transition-colors hover:bg-error-50 disabled:cursor-not-allowed disabled:opacity-40 dark:text-error-400 dark:hover:bg-error-900/20";
|
|
47
|
-
function B({
|
|
48
|
-
isOpen: t,
|
|
49
|
-
title: a,
|
|
50
|
-
message: r,
|
|
51
|
-
confirmLabel: i = "Confirm",
|
|
52
|
-
onConfirm: l,
|
|
53
|
-
onCancel: s,
|
|
54
|
-
isLoading: c = !1
|
|
55
|
-
}) {
|
|
56
|
-
const u = "confirm-dialog-title";
|
|
57
|
-
return /* @__PURE__ */ n(M, { isOpen: t, onClose: s, ariaLabelledBy: u, children: [
|
|
58
|
-
/* @__PURE__ */ e(
|
|
59
|
-
"h3",
|
|
60
|
-
{
|
|
61
|
-
id: u,
|
|
62
|
-
className: "text-lg font-semibold text-neutral-900 dark:text-neutral-100",
|
|
63
|
-
children: a
|
|
64
|
-
}
|
|
65
|
-
),
|
|
66
|
-
/* @__PURE__ */ e("p", { className: "mt-2 text-sm text-neutral-600 dark:text-neutral-400", children: r }),
|
|
67
|
-
/* @__PURE__ */ n("div", { className: "mt-6 flex justify-end gap-3", children: [
|
|
68
|
-
/* @__PURE__ */ e(
|
|
69
|
-
"button",
|
|
70
|
-
{
|
|
71
|
-
type: "button",
|
|
72
|
-
"data-testid": "confirm-cancel-btn",
|
|
73
|
-
onClick: s,
|
|
74
|
-
disabled: c,
|
|
75
|
-
className: E,
|
|
76
|
-
children: "Cancel"
|
|
77
|
-
}
|
|
78
|
-
),
|
|
79
|
-
/* @__PURE__ */ e(
|
|
80
|
-
"button",
|
|
81
|
-
{
|
|
82
|
-
type: "button",
|
|
83
|
-
"data-testid": "confirm-btn",
|
|
84
|
-
onClick: l,
|
|
85
|
-
disabled: c,
|
|
86
|
-
className: _,
|
|
87
|
-
children: i
|
|
88
|
-
}
|
|
89
|
-
)
|
|
90
|
-
] })
|
|
91
|
-
] });
|
|
55
|
+
);
|
|
92
56
|
}
|
|
93
|
-
const
|
|
94
|
-
admin: "
|
|
95
|
-
user: "
|
|
96
|
-
guest: "
|
|
57
|
+
const xe = {
|
|
58
|
+
admin: "secondary",
|
|
59
|
+
user: "default",
|
|
60
|
+
guest: "muted"
|
|
97
61
|
};
|
|
98
|
-
function
|
|
62
|
+
function Y({ role: t }) {
|
|
99
63
|
if (!t) return null;
|
|
100
|
-
const
|
|
101
|
-
return /* @__PURE__ */ e(
|
|
102
|
-
"span",
|
|
103
|
-
{
|
|
104
|
-
className: `inline-block rounded-full px-2.5 py-0.5 text-xs font-medium ${te[t]}`,
|
|
105
|
-
children: a
|
|
106
|
-
}
|
|
107
|
-
);
|
|
64
|
+
const n = t.charAt(0).toUpperCase() + t.slice(1);
|
|
65
|
+
return /* @__PURE__ */ e(V, { variant: xe[t] ?? "default", children: n });
|
|
108
66
|
}
|
|
109
|
-
function
|
|
67
|
+
function D({
|
|
110
68
|
label: t,
|
|
111
|
-
htmlFor:
|
|
112
|
-
required:
|
|
113
|
-
error:
|
|
114
|
-
children:
|
|
69
|
+
htmlFor: n,
|
|
70
|
+
required: s,
|
|
71
|
+
error: m,
|
|
72
|
+
children: f
|
|
115
73
|
}) {
|
|
116
|
-
return /* @__PURE__ */
|
|
117
|
-
/* @__PURE__ */
|
|
74
|
+
return /* @__PURE__ */ i("div", { children: [
|
|
75
|
+
/* @__PURE__ */ i(be, { htmlFor: n, className: "mb-1", children: [
|
|
118
76
|
t,
|
|
119
77
|
" ",
|
|
120
|
-
|
|
78
|
+
s && /* @__PURE__ */ e("span", { className: "text-destructive", children: "*" })
|
|
121
79
|
] }),
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"p",
|
|
125
|
-
{
|
|
126
|
-
"data-testid": "field-error",
|
|
127
|
-
className: "mt-1 text-sm text-error-600 dark:text-error-400",
|
|
128
|
-
children: i
|
|
129
|
-
}
|
|
130
|
-
)
|
|
80
|
+
f,
|
|
81
|
+
m && /* @__PURE__ */ e("p", { "data-testid": "field-error", className: "mt-1 text-sm text-destructive", children: m })
|
|
131
82
|
] });
|
|
132
83
|
}
|
|
133
|
-
const
|
|
134
|
-
email:
|
|
135
|
-
role:
|
|
84
|
+
const ye = C.object({
|
|
85
|
+
email: C.string().email("Invalid email address"),
|
|
86
|
+
role: C.string().min(1)
|
|
136
87
|
});
|
|
137
|
-
function
|
|
138
|
-
const
|
|
139
|
-
register:
|
|
140
|
-
handleSubmit:
|
|
141
|
-
reset:
|
|
142
|
-
formState: { errors:
|
|
143
|
-
} =
|
|
144
|
-
resolver:
|
|
88
|
+
function Ce({ isOpen: t, onClose: n }) {
|
|
89
|
+
const s = I(), [m, { isLoading: f }] = X(), { data: b } = F(), d = b ?? [], {
|
|
90
|
+
register: l,
|
|
91
|
+
handleSubmit: r,
|
|
92
|
+
reset: c,
|
|
93
|
+
formState: { errors: g }
|
|
94
|
+
} = B({
|
|
95
|
+
resolver: q(ye),
|
|
145
96
|
defaultValues: { email: "", role: "guest" }
|
|
146
|
-
}),
|
|
147
|
-
|
|
97
|
+
}), a = () => {
|
|
98
|
+
c(), n();
|
|
148
99
|
};
|
|
149
|
-
return /* @__PURE__ */
|
|
150
|
-
|
|
100
|
+
return /* @__PURE__ */ e(
|
|
101
|
+
j,
|
|
151
102
|
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
/* @__PURE__ */
|
|
157
|
-
"h3",
|
|
158
|
-
{
|
|
159
|
-
id: d,
|
|
160
|
-
className: "text-lg font-semibold text-neutral-900 dark:text-neutral-100",
|
|
161
|
-
children: "Invite User"
|
|
162
|
-
}
|
|
163
|
-
),
|
|
164
|
-
/* @__PURE__ */ n("form", { onSubmit: c(async (f) => {
|
|
103
|
+
open: t,
|
|
104
|
+
onOpenChange: (u) => !u && a(),
|
|
105
|
+
children: /* @__PURE__ */ i(E, { children: [
|
|
106
|
+
/* @__PURE__ */ e(O, { children: /* @__PURE__ */ e(G, { children: "Invite User" }) }),
|
|
107
|
+
/* @__PURE__ */ i("form", { onSubmit: r(async (u) => {
|
|
165
108
|
try {
|
|
166
|
-
await
|
|
109
|
+
await m({ inviteUserDto: u }).unwrap(), s(A("Invitation sent successfully")), c(), n();
|
|
167
110
|
} catch {
|
|
168
111
|
}
|
|
169
|
-
}), className: "
|
|
112
|
+
}), className: "space-y-4", children: [
|
|
170
113
|
/* @__PURE__ */ e(
|
|
171
|
-
|
|
114
|
+
D,
|
|
172
115
|
{
|
|
173
116
|
label: "Email",
|
|
174
117
|
htmlFor: "invite-email",
|
|
175
118
|
required: !0,
|
|
176
|
-
error:
|
|
119
|
+
error: g.email?.message,
|
|
177
120
|
children: /* @__PURE__ */ e(
|
|
178
|
-
|
|
121
|
+
P,
|
|
179
122
|
{
|
|
180
123
|
id: "invite-email",
|
|
181
124
|
"data-testid": "invite-email-input",
|
|
182
125
|
type: "email",
|
|
183
126
|
placeholder: "user@example.com",
|
|
184
|
-
|
|
185
|
-
...s("email")
|
|
127
|
+
...l("email")
|
|
186
128
|
}
|
|
187
129
|
)
|
|
188
130
|
}
|
|
189
131
|
),
|
|
190
|
-
/* @__PURE__ */ e(
|
|
132
|
+
/* @__PURE__ */ e(D, { label: "Role", htmlFor: "invite-role", children: /* @__PURE__ */ e(
|
|
191
133
|
"select",
|
|
192
134
|
{
|
|
193
135
|
id: "invite-role",
|
|
194
136
|
"data-testid": "invite-role-select",
|
|
195
|
-
className:
|
|
196
|
-
...
|
|
197
|
-
children:
|
|
198
|
-
/* @__PURE__ */ e("option", { value: "guest", children: "Guest" }),
|
|
199
|
-
/* @__PURE__ */ e("option", { value: "user", children: "User" }),
|
|
200
|
-
/* @__PURE__ */ e("option", { value: "admin", children: "Admin" })
|
|
201
|
-
]
|
|
137
|
+
className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
138
|
+
...l("role"),
|
|
139
|
+
children: d.map((u) => /* @__PURE__ */ e("option", { value: u.name, children: u.name.charAt(0).toUpperCase() + u.name.slice(1) }, u.id))
|
|
202
140
|
}
|
|
203
141
|
) }),
|
|
204
|
-
/* @__PURE__ */
|
|
142
|
+
/* @__PURE__ */ i("div", { className: "flex justify-end gap-3", children: [
|
|
205
143
|
/* @__PURE__ */ e(
|
|
206
|
-
|
|
144
|
+
w,
|
|
207
145
|
{
|
|
208
146
|
type: "button",
|
|
147
|
+
variant: "secondary",
|
|
209
148
|
"data-testid": "invite-cancel-btn",
|
|
210
|
-
onClick:
|
|
211
|
-
disabled:
|
|
212
|
-
className: E,
|
|
149
|
+
onClick: a,
|
|
150
|
+
disabled: f,
|
|
213
151
|
children: "Cancel"
|
|
214
152
|
}
|
|
215
153
|
),
|
|
216
154
|
/* @__PURE__ */ e(
|
|
217
|
-
|
|
155
|
+
w,
|
|
218
156
|
{
|
|
219
157
|
type: "submit",
|
|
220
158
|
"data-testid": "invite-submit-btn",
|
|
221
|
-
disabled:
|
|
222
|
-
|
|
223
|
-
children: l ? "Sending..." : "Send Invitation"
|
|
159
|
+
disabled: f,
|
|
160
|
+
children: f ? "Sending..." : "Send Invitation"
|
|
224
161
|
}
|
|
225
162
|
)
|
|
226
163
|
] })
|
|
227
164
|
] })
|
|
228
|
-
]
|
|
165
|
+
] })
|
|
229
166
|
}
|
|
230
167
|
);
|
|
231
168
|
}
|
|
232
|
-
const
|
|
233
|
-
error: "text-xl font-bold text-
|
|
234
|
-
success: "text-xl font-bold text-success
|
|
169
|
+
const Ne = {
|
|
170
|
+
error: "text-xl font-bold text-destructive",
|
|
171
|
+
success: "text-xl font-bold text-success"
|
|
235
172
|
};
|
|
236
|
-
function
|
|
173
|
+
function k({
|
|
237
174
|
variant: t,
|
|
238
|
-
title:
|
|
239
|
-
message:
|
|
240
|
-
children:
|
|
175
|
+
title: n,
|
|
176
|
+
message: s,
|
|
177
|
+
children: m
|
|
241
178
|
}) {
|
|
242
|
-
return t === "loading" ? /* @__PURE__ */ e("
|
|
243
|
-
|
|
179
|
+
return t === "loading" ? /* @__PURE__ */ e(M, { className: "max-w-md mx-auto mt-8", children: /* @__PURE__ */ e(T, { className: "pt-6", children: /* @__PURE__ */ e("p", { className: "text-center text-muted-foreground", children: s }) }) }) : /* @__PURE__ */ e(
|
|
180
|
+
M,
|
|
244
181
|
{
|
|
245
|
-
className:
|
|
182
|
+
className: "max-w-md mx-auto mt-8",
|
|
246
183
|
role: t === "error" ? "alert" : void 0,
|
|
247
|
-
children: [
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
184
|
+
children: /* @__PURE__ */ i(T, { className: "pt-6", children: [
|
|
185
|
+
n && /* @__PURE__ */ e(
|
|
186
|
+
"h2",
|
|
187
|
+
{
|
|
188
|
+
"data-testid": "status-card-title",
|
|
189
|
+
className: Ne[t],
|
|
190
|
+
children: n
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
/* @__PURE__ */ e(
|
|
194
|
+
"p",
|
|
195
|
+
{
|
|
196
|
+
"data-testid": "status-card-message",
|
|
197
|
+
className: "mt-2 text-muted-foreground",
|
|
198
|
+
children: s
|
|
199
|
+
}
|
|
200
|
+
),
|
|
201
|
+
m
|
|
202
|
+
] })
|
|
252
203
|
}
|
|
253
204
|
);
|
|
254
205
|
}
|
|
255
|
-
const
|
|
256
|
-
firstName:
|
|
257
|
-
lastName:
|
|
258
|
-
password:
|
|
259
|
-
confirmPassword:
|
|
206
|
+
const we = C.object({
|
|
207
|
+
firstName: C.string().optional(),
|
|
208
|
+
lastName: C.string().optional(),
|
|
209
|
+
password: C.string().min(8, "Password must be at least 8 characters"),
|
|
210
|
+
confirmPassword: C.string()
|
|
260
211
|
}).refine((t) => t.password === t.confirmPassword, {
|
|
261
212
|
message: "Passwords do not match",
|
|
262
213
|
path: ["confirmPassword"]
|
|
263
214
|
});
|
|
264
|
-
function
|
|
215
|
+
function Ye({ token: t, loginPath: n }) {
|
|
265
216
|
const {
|
|
266
|
-
data:
|
|
267
|
-
isLoading:
|
|
268
|
-
error:
|
|
269
|
-
} =
|
|
270
|
-
register:
|
|
271
|
-
handleSubmit:
|
|
272
|
-
formState: { errors:
|
|
273
|
-
} =
|
|
274
|
-
resolver:
|
|
217
|
+
data: s,
|
|
218
|
+
isLoading: m,
|
|
219
|
+
error: f
|
|
220
|
+
} = Z({ token: t }), [b, { isLoading: d, isSuccess: l }] = _(), {
|
|
221
|
+
register: r,
|
|
222
|
+
handleSubmit: c,
|
|
223
|
+
formState: { errors: g }
|
|
224
|
+
} = B({
|
|
225
|
+
resolver: q(we),
|
|
275
226
|
defaultValues: {
|
|
276
227
|
firstName: "",
|
|
277
228
|
lastName: "",
|
|
278
229
|
password: "",
|
|
279
230
|
confirmPassword: ""
|
|
280
231
|
}
|
|
281
|
-
}),
|
|
232
|
+
}), a = s?.email ?? "", v = async (u) => {
|
|
282
233
|
try {
|
|
283
|
-
await
|
|
234
|
+
await b({
|
|
284
235
|
acceptInvitationDto: {
|
|
285
236
|
token: t,
|
|
286
|
-
password:
|
|
287
|
-
firstName:
|
|
288
|
-
lastName:
|
|
237
|
+
password: u.password,
|
|
238
|
+
firstName: u.firstName || void 0,
|
|
239
|
+
lastName: u.lastName || void 0
|
|
289
240
|
}
|
|
290
241
|
}).unwrap();
|
|
291
242
|
} catch {
|
|
292
243
|
}
|
|
293
244
|
};
|
|
294
|
-
return
|
|
295
|
-
|
|
245
|
+
return l ? /* @__PURE__ */ e(
|
|
246
|
+
k,
|
|
296
247
|
{
|
|
297
248
|
variant: "success",
|
|
298
249
|
title: "Account Created",
|
|
299
250
|
message: "Your account has been created successfully. You can now log in with your email and password.",
|
|
300
|
-
children:
|
|
251
|
+
children: n && /* @__PURE__ */ e(
|
|
301
252
|
"a",
|
|
302
253
|
{
|
|
303
|
-
href:
|
|
254
|
+
href: n,
|
|
304
255
|
"data-testid": "accept-login-link",
|
|
305
|
-
className: "mt-4 inline-block text-sm font-medium text-primary
|
|
256
|
+
className: "mt-4 inline-block text-sm font-medium text-primary hover:underline",
|
|
306
257
|
children: "Go to login"
|
|
307
258
|
}
|
|
308
259
|
)
|
|
309
260
|
}
|
|
310
|
-
) :
|
|
311
|
-
|
|
261
|
+
) : m ? /* @__PURE__ */ e(k, { variant: "loading", message: "Validating invitation..." }) : f ? /* @__PURE__ */ e(
|
|
262
|
+
k,
|
|
312
263
|
{
|
|
313
264
|
variant: "error",
|
|
314
265
|
title: "Validation Failed",
|
|
315
266
|
message: "Unable to validate this invitation. Please check your connection and try again."
|
|
316
267
|
}
|
|
317
|
-
) :
|
|
268
|
+
) : s?.valid ? /* @__PURE__ */ e(M, { className: "max-w-md mx-auto mt-8", children: /* @__PURE__ */ i(T, { className: "pt-6", children: [
|
|
318
269
|
/* @__PURE__ */ e(
|
|
319
270
|
"h2",
|
|
320
271
|
{
|
|
321
272
|
"data-testid": "accept-heading",
|
|
322
|
-
className: "text-xl font-bold text-
|
|
273
|
+
className: "text-xl font-bold text-foreground",
|
|
323
274
|
children: "Accept Invitation"
|
|
324
275
|
}
|
|
325
276
|
),
|
|
326
|
-
/* @__PURE__ */
|
|
327
|
-
"You've been invited
|
|
328
|
-
/* @__PURE__ */ e("strong", { "data-testid": "accept-role", children: f }),
|
|
277
|
+
/* @__PURE__ */ i("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
278
|
+
"You've been invited with email",
|
|
329
279
|
" ",
|
|
330
|
-
"
|
|
331
|
-
/* @__PURE__ */ e("strong", { "data-testid": "accept-email", children: b })
|
|
280
|
+
/* @__PURE__ */ e("strong", { "data-testid": "accept-email", children: a })
|
|
332
281
|
] }),
|
|
333
|
-
/* @__PURE__ */
|
|
334
|
-
/* @__PURE__ */ e(
|
|
335
|
-
|
|
282
|
+
/* @__PURE__ */ i("form", { onSubmit: c(v), className: "mt-4 space-y-4", children: [
|
|
283
|
+
/* @__PURE__ */ e(D, { label: "First Name", htmlFor: "accept-firstName", children: /* @__PURE__ */ e(
|
|
284
|
+
P,
|
|
336
285
|
{
|
|
337
286
|
id: "accept-firstName",
|
|
338
287
|
"data-testid": "accept-first-name-input",
|
|
339
288
|
type: "text",
|
|
340
289
|
placeholder: "John",
|
|
341
|
-
|
|
342
|
-
...o("firstName")
|
|
290
|
+
...r("firstName")
|
|
343
291
|
}
|
|
344
292
|
) }),
|
|
345
|
-
/* @__PURE__ */ e(
|
|
346
|
-
|
|
293
|
+
/* @__PURE__ */ e(D, { label: "Last Name", htmlFor: "accept-lastName", children: /* @__PURE__ */ e(
|
|
294
|
+
P,
|
|
347
295
|
{
|
|
348
296
|
id: "accept-lastName",
|
|
349
297
|
"data-testid": "accept-last-name-input",
|
|
350
298
|
type: "text",
|
|
351
299
|
placeholder: "Doe",
|
|
352
|
-
|
|
353
|
-
...o("lastName")
|
|
300
|
+
...r("lastName")
|
|
354
301
|
}
|
|
355
302
|
) }),
|
|
356
303
|
/* @__PURE__ */ e(
|
|
357
|
-
|
|
304
|
+
D,
|
|
358
305
|
{
|
|
359
306
|
label: "Password",
|
|
360
307
|
htmlFor: "accept-password",
|
|
361
308
|
required: !0,
|
|
362
|
-
error:
|
|
309
|
+
error: g.password?.message,
|
|
363
310
|
children: /* @__PURE__ */ e(
|
|
364
|
-
|
|
311
|
+
P,
|
|
365
312
|
{
|
|
366
313
|
id: "accept-password",
|
|
367
314
|
"data-testid": "accept-password-input",
|
|
368
315
|
type: "password",
|
|
369
316
|
placeholder: "Min. 8 characters",
|
|
370
|
-
|
|
371
|
-
...o("password")
|
|
317
|
+
...r("password")
|
|
372
318
|
}
|
|
373
319
|
)
|
|
374
320
|
}
|
|
375
321
|
),
|
|
376
322
|
/* @__PURE__ */ e(
|
|
377
|
-
|
|
323
|
+
D,
|
|
378
324
|
{
|
|
379
325
|
label: "Confirm Password",
|
|
380
326
|
htmlFor: "accept-confirmPassword",
|
|
381
327
|
required: !0,
|
|
382
|
-
error:
|
|
328
|
+
error: g.confirmPassword?.message,
|
|
383
329
|
children: /* @__PURE__ */ e(
|
|
384
|
-
|
|
330
|
+
P,
|
|
385
331
|
{
|
|
386
332
|
id: "accept-confirmPassword",
|
|
387
333
|
"data-testid": "accept-confirm-password-input",
|
|
388
334
|
type: "password",
|
|
389
335
|
placeholder: "Repeat password",
|
|
390
|
-
|
|
391
|
-
...o("confirmPassword")
|
|
336
|
+
...r("confirmPassword")
|
|
392
337
|
}
|
|
393
338
|
)
|
|
394
339
|
}
|
|
395
340
|
),
|
|
396
341
|
/* @__PURE__ */ e(
|
|
397
|
-
|
|
342
|
+
w,
|
|
398
343
|
{
|
|
399
344
|
type: "submit",
|
|
400
345
|
"data-testid": "accept-submit-btn",
|
|
401
|
-
disabled:
|
|
402
|
-
className:
|
|
403
|
-
children:
|
|
346
|
+
disabled: d,
|
|
347
|
+
className: "w-full",
|
|
348
|
+
children: d ? "Creating account..." : "Create Account"
|
|
404
349
|
}
|
|
405
350
|
)
|
|
406
351
|
] })
|
|
407
|
-
] }) : /* @__PURE__ */ e(
|
|
408
|
-
|
|
352
|
+
] }) }) : /* @__PURE__ */ e(
|
|
353
|
+
k,
|
|
409
354
|
{
|
|
410
355
|
variant: "error",
|
|
411
356
|
title: "Invalid Invitation",
|
|
@@ -413,252 +358,547 @@ function Ae({ token: t, loginPath: a }) {
|
|
|
413
358
|
}
|
|
414
359
|
);
|
|
415
360
|
}
|
|
416
|
-
const
|
|
417
|
-
pending: "
|
|
418
|
-
accepted: "
|
|
419
|
-
expired: "
|
|
361
|
+
const De = {
|
|
362
|
+
pending: "warning",
|
|
363
|
+
accepted: "success",
|
|
364
|
+
expired: "muted"
|
|
420
365
|
};
|
|
421
|
-
function
|
|
366
|
+
function Se({ status: t }) {
|
|
422
367
|
if (!t) return null;
|
|
423
|
-
const
|
|
424
|
-
return /* @__PURE__ */ e(
|
|
425
|
-
"span",
|
|
426
|
-
{
|
|
427
|
-
className: `inline-block rounded-full px-2.5 py-0.5 text-xs font-medium ${le[t]}`,
|
|
428
|
-
children: a
|
|
429
|
-
}
|
|
430
|
-
);
|
|
368
|
+
const n = t.charAt(0).toUpperCase() + t.slice(1);
|
|
369
|
+
return /* @__PURE__ */ e(V, { variant: De[t], children: n });
|
|
431
370
|
}
|
|
432
|
-
const
|
|
371
|
+
const Re = {
|
|
433
372
|
field: "email",
|
|
434
373
|
headerName: "Email",
|
|
435
374
|
flex: 2
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
375
|
+
};
|
|
376
|
+
function Ie(t) {
|
|
377
|
+
return {
|
|
378
|
+
headerName: "Role",
|
|
379
|
+
flex: 1,
|
|
380
|
+
cellRenderer: (n) => n.data ? /* @__PURE__ */ e(Y, { role: t.get(n.data.roleId) ?? null }) : null
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
const Ae = {
|
|
442
384
|
field: "status",
|
|
443
385
|
headerName: "Status",
|
|
444
386
|
flex: 1,
|
|
445
|
-
cellRenderer: (t) => t.data ? /* @__PURE__ */ e(
|
|
446
|
-
},
|
|
387
|
+
cellRenderer: (t) => t.data ? /* @__PURE__ */ e(Se, { status: t.data.status }) : null
|
|
388
|
+
}, Pe = {
|
|
447
389
|
headerName: "Invited",
|
|
448
390
|
flex: 1,
|
|
449
|
-
valueGetter: (t) =>
|
|
450
|
-
},
|
|
391
|
+
valueGetter: (t) => z(t.data?.invitedAt)
|
|
392
|
+
}, ke = {
|
|
451
393
|
headerName: "Expires",
|
|
452
394
|
flex: 1,
|
|
453
|
-
valueGetter: (t) =>
|
|
395
|
+
valueGetter: (t) => z(t.data?.tokenExpiry)
|
|
454
396
|
};
|
|
455
|
-
function
|
|
397
|
+
function Le(t) {
|
|
456
398
|
return {
|
|
457
399
|
headerName: "Actions",
|
|
458
400
|
flex: 1,
|
|
459
401
|
sortable: !1,
|
|
460
402
|
filter: !1,
|
|
461
|
-
cellRenderer: (
|
|
403
|
+
cellRenderer: (n) => n.data ? /* @__PURE__ */ e(
|
|
462
404
|
"button",
|
|
463
405
|
{
|
|
464
|
-
onClick: () =>
|
|
465
|
-
className:
|
|
406
|
+
onClick: () => n.data && t(n.data),
|
|
407
|
+
className: "text-destructive text-xs font-medium rounded px-2 py-1 transition-colors hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-40",
|
|
466
408
|
children: "Cancel"
|
|
467
409
|
}
|
|
468
410
|
) : null
|
|
469
411
|
};
|
|
470
412
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
413
|
+
function Fe(t, n) {
|
|
414
|
+
return [
|
|
415
|
+
Re,
|
|
416
|
+
Ie(n),
|
|
417
|
+
Ae,
|
|
418
|
+
Pe,
|
|
419
|
+
ke,
|
|
420
|
+
Le(t)
|
|
421
|
+
];
|
|
480
422
|
}
|
|
481
|
-
function
|
|
482
|
-
const t = I(), {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
423
|
+
function Je() {
|
|
424
|
+
const t = I(), { data: n, isLoading: s, error: m, refetch: f } = ee(), [b, { isLoading: d }] = te(), { data: l } = F(), [r, c] = N(null), g = n ?? [], a = R(() => {
|
|
425
|
+
const y = l ?? [];
|
|
426
|
+
return new Map(y.map((o) => [o.id, o.name]));
|
|
427
|
+
}, [l]);
|
|
428
|
+
async function v() {
|
|
429
|
+
if (r)
|
|
430
|
+
try {
|
|
431
|
+
await b({ id: r.id }).unwrap(), t(A("Invitation cancelled successfully"));
|
|
432
|
+
} catch {
|
|
433
|
+
} finally {
|
|
434
|
+
c(null);
|
|
435
|
+
}
|
|
486
436
|
}
|
|
487
|
-
const
|
|
488
|
-
|
|
437
|
+
const u = R(
|
|
438
|
+
() => Fe(c, a),
|
|
439
|
+
[a]
|
|
440
|
+
);
|
|
441
|
+
return m ? /* @__PURE__ */ i(
|
|
489
442
|
"div",
|
|
490
443
|
{
|
|
491
444
|
"data-testid": "invitations-error",
|
|
492
|
-
className: "rounded-lg bg-
|
|
445
|
+
className: "rounded-lg bg-destructive/10 p-6 text-center",
|
|
493
446
|
role: "alert",
|
|
494
447
|
children: [
|
|
495
|
-
/* @__PURE__ */ e("p", { className: "text-
|
|
448
|
+
/* @__PURE__ */ e("p", { className: "text-destructive", children: "Failed to load invitations." }),
|
|
496
449
|
/* @__PURE__ */ e(
|
|
497
450
|
"button",
|
|
498
451
|
{
|
|
499
452
|
"data-testid": "invitations-retry-btn",
|
|
500
|
-
onClick:
|
|
501
|
-
className: "mt-2 text-sm font-medium text-primary
|
|
453
|
+
onClick: f,
|
|
454
|
+
className: "mt-2 text-sm font-medium text-primary hover:underline",
|
|
502
455
|
children: "Try again"
|
|
503
456
|
}
|
|
504
457
|
)
|
|
505
458
|
]
|
|
506
459
|
}
|
|
507
|
-
) : /* @__PURE__ */
|
|
460
|
+
) : /* @__PURE__ */ i("div", { children: [
|
|
508
461
|
/* @__PURE__ */ e("div", { className: "mb-4 flex items-center justify-between", children: /* @__PURE__ */ e(
|
|
509
462
|
"h2",
|
|
510
463
|
{
|
|
511
464
|
"data-testid": "invitations-heading",
|
|
512
|
-
className: "text-xl font-semibold text-
|
|
465
|
+
className: "text-xl font-semibold text-foreground",
|
|
513
466
|
children: "Invitations"
|
|
514
467
|
}
|
|
515
468
|
) }),
|
|
516
469
|
/* @__PURE__ */ e(
|
|
517
470
|
U,
|
|
518
471
|
{
|
|
519
|
-
rowData:
|
|
520
|
-
columnDefs:
|
|
521
|
-
|
|
522
|
-
theme: a,
|
|
523
|
-
loading: l
|
|
472
|
+
rowData: g,
|
|
473
|
+
columnDefs: u,
|
|
474
|
+
loading: s
|
|
524
475
|
}
|
|
525
476
|
),
|
|
526
477
|
/* @__PURE__ */ e(
|
|
527
|
-
|
|
478
|
+
Q,
|
|
528
479
|
{
|
|
529
|
-
isOpen: !!
|
|
480
|
+
isOpen: !!r,
|
|
530
481
|
title: "Cancel Invitation",
|
|
531
|
-
message: `Are you sure you want to cancel the invitation for ${
|
|
532
|
-
confirmLabel:
|
|
533
|
-
onConfirm:
|
|
534
|
-
onCancel: () =>
|
|
535
|
-
isLoading:
|
|
482
|
+
message: `Are you sure you want to cancel the invitation for ${r?.email}? This action cannot be undone.`,
|
|
483
|
+
confirmLabel: d ? "Cancelling..." : "Cancel Invitation",
|
|
484
|
+
onConfirm: v,
|
|
485
|
+
onCancel: () => c(null),
|
|
486
|
+
isLoading: d
|
|
536
487
|
}
|
|
537
488
|
)
|
|
538
489
|
] });
|
|
539
490
|
}
|
|
540
|
-
function
|
|
541
|
-
|
|
542
|
-
|
|
491
|
+
function Me({
|
|
492
|
+
isOpen: t,
|
|
493
|
+
onClose: n,
|
|
494
|
+
user: s
|
|
495
|
+
}) {
|
|
496
|
+
const m = I(), { data: f } = F(), [b, { isLoading: d }] = ne(), l = R(
|
|
497
|
+
() => f ?? [],
|
|
498
|
+
[f]
|
|
499
|
+
), [r, c] = N(null);
|
|
500
|
+
H(() => {
|
|
501
|
+
if (!l.length) return;
|
|
502
|
+
const a = l.find((v) => v.name === s.role);
|
|
503
|
+
c(a?.id ?? null);
|
|
504
|
+
}, [l, s.role]);
|
|
505
|
+
const g = async (a) => {
|
|
506
|
+
if (a.preventDefault(), r !== null)
|
|
507
|
+
try {
|
|
508
|
+
await b({
|
|
509
|
+
userId: s.id,
|
|
510
|
+
updateUserRolesDto: { roleIds: [r] }
|
|
511
|
+
}).unwrap(), m(A("Role updated successfully")), n();
|
|
512
|
+
} catch {
|
|
513
|
+
}
|
|
514
|
+
};
|
|
515
|
+
return /* @__PURE__ */ e(j, { open: t, onOpenChange: (a) => !a && n(), children: /* @__PURE__ */ i(E, { children: [
|
|
516
|
+
/* @__PURE__ */ i(O, { children: [
|
|
517
|
+
/* @__PURE__ */ e(G, { children: "Change Role" }),
|
|
518
|
+
/* @__PURE__ */ i($, { children: [
|
|
519
|
+
"Changing role for ",
|
|
520
|
+
/* @__PURE__ */ e("strong", { children: s.email })
|
|
521
|
+
] })
|
|
522
|
+
] }),
|
|
523
|
+
/* @__PURE__ */ i("form", { onSubmit: g, className: "space-y-4", children: [
|
|
524
|
+
/* @__PURE__ */ e(D, { label: "Role", htmlFor: "role-select", children: /* @__PURE__ */ e(
|
|
525
|
+
"select",
|
|
526
|
+
{
|
|
527
|
+
id: "role-select",
|
|
528
|
+
"data-testid": "role-select",
|
|
529
|
+
className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
530
|
+
value: r ?? "",
|
|
531
|
+
onChange: (a) => c(Number(a.target.value)),
|
|
532
|
+
children: l.map((a) => /* @__PURE__ */ e("option", { value: a.id, children: a.name.charAt(0).toUpperCase() + a.name.slice(1) }, a.id))
|
|
533
|
+
}
|
|
534
|
+
) }),
|
|
535
|
+
/* @__PURE__ */ i("div", { className: "flex justify-end gap-3", children: [
|
|
536
|
+
/* @__PURE__ */ e(
|
|
537
|
+
w,
|
|
538
|
+
{
|
|
539
|
+
type: "button",
|
|
540
|
+
variant: "secondary",
|
|
541
|
+
"data-testid": "role-change-cancel-btn",
|
|
542
|
+
onClick: n,
|
|
543
|
+
disabled: d,
|
|
544
|
+
children: "Cancel"
|
|
545
|
+
}
|
|
546
|
+
),
|
|
547
|
+
/* @__PURE__ */ e(
|
|
548
|
+
w,
|
|
549
|
+
{
|
|
550
|
+
type: "submit",
|
|
551
|
+
"data-testid": "role-change-submit-btn",
|
|
552
|
+
disabled: d || r === null,
|
|
553
|
+
children: d ? "Saving..." : "Save"
|
|
554
|
+
}
|
|
555
|
+
)
|
|
556
|
+
] })
|
|
557
|
+
] })
|
|
558
|
+
] }) });
|
|
559
|
+
}
|
|
560
|
+
function L(t, n) {
|
|
561
|
+
const { data: s } = ie();
|
|
562
|
+
return s?.permissions ? s.permissions.includes(`${t}:${n}`) : !1;
|
|
563
|
+
}
|
|
564
|
+
function Ke({ currentUserId: t }) {
|
|
565
|
+
const n = I(), { data: s, isLoading: m, error: f, refetch: b } = ae(), [d, { isLoading: l }] = se(), r = L("users", "delete"), c = L("roles", "update"), [g, a] = N(!1), [v, u] = N(null), [y, o] = N(null), p = s ?? [], h = W(async () => {
|
|
566
|
+
if (v)
|
|
543
567
|
try {
|
|
544
|
-
await
|
|
568
|
+
await d({ id: v.id }).unwrap(), n(A("User deleted successfully"));
|
|
545
569
|
} catch {
|
|
546
570
|
} finally {
|
|
547
|
-
|
|
571
|
+
u(null);
|
|
548
572
|
}
|
|
549
|
-
}, [
|
|
573
|
+
}, [v, d, n]), J = R(
|
|
550
574
|
() => [
|
|
551
575
|
{ field: "email", headerName: "Email", flex: 2 },
|
|
552
576
|
{
|
|
553
577
|
headerName: "Name",
|
|
554
578
|
flex: 2,
|
|
555
|
-
valueGetter: (
|
|
556
|
-
const { firstName:
|
|
557
|
-
return [
|
|
579
|
+
valueGetter: (x) => {
|
|
580
|
+
const { firstName: S, lastName: K } = x.data ?? {};
|
|
581
|
+
return [S, K].filter(Boolean).join(" ") || "—";
|
|
558
582
|
}
|
|
559
583
|
},
|
|
560
584
|
{
|
|
561
585
|
field: "role",
|
|
562
586
|
headerName: "Role",
|
|
563
587
|
flex: 1,
|
|
564
|
-
cellRenderer: (
|
|
588
|
+
cellRenderer: (x) => x.data ? /* @__PURE__ */ e(Y, { role: x.data.role }) : null
|
|
565
589
|
},
|
|
566
590
|
{
|
|
567
591
|
headerName: "Actions",
|
|
568
592
|
flex: 1,
|
|
569
593
|
sortable: !1,
|
|
570
594
|
filter: !1,
|
|
571
|
-
cellRenderer: (
|
|
572
|
-
if (!
|
|
573
|
-
const
|
|
574
|
-
return /* @__PURE__ */
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
595
|
+
cellRenderer: (x) => {
|
|
596
|
+
if (!x.data) return null;
|
|
597
|
+
const S = x.data.id === t;
|
|
598
|
+
return /* @__PURE__ */ i("div", { className: "flex gap-1", children: [
|
|
599
|
+
c && /* @__PURE__ */ e(
|
|
600
|
+
"button",
|
|
601
|
+
{
|
|
602
|
+
onClick: () => x.data && o(x.data),
|
|
603
|
+
disabled: S,
|
|
604
|
+
title: S ? "Cannot change your own role" : "Change user role",
|
|
605
|
+
className: "rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10 disabled:cursor-not-allowed disabled:opacity-40",
|
|
606
|
+
children: "Change Role"
|
|
607
|
+
}
|
|
608
|
+
),
|
|
609
|
+
r && /* @__PURE__ */ e(
|
|
610
|
+
"button",
|
|
611
|
+
{
|
|
612
|
+
onClick: () => x.data && u(x.data),
|
|
613
|
+
disabled: S,
|
|
614
|
+
title: S ? "Cannot delete your own account" : "Delete user",
|
|
615
|
+
className: "rounded px-2 py-1 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-40",
|
|
616
|
+
children: "Delete"
|
|
617
|
+
}
|
|
618
|
+
)
|
|
619
|
+
] });
|
|
584
620
|
}
|
|
585
621
|
}
|
|
586
622
|
],
|
|
587
|
-
[t]
|
|
623
|
+
[t, c, r]
|
|
588
624
|
);
|
|
589
|
-
return
|
|
625
|
+
return f ? /* @__PURE__ */ i(
|
|
590
626
|
"div",
|
|
591
627
|
{
|
|
592
628
|
"data-testid": "users-error",
|
|
593
|
-
className: "rounded-lg bg-
|
|
629
|
+
className: "rounded-lg bg-destructive/10 p-6 text-center",
|
|
594
630
|
role: "alert",
|
|
595
631
|
children: [
|
|
596
|
-
/* @__PURE__ */ e("p", { className: "text-
|
|
632
|
+
/* @__PURE__ */ e("p", { className: "text-destructive", children: "Failed to load users." }),
|
|
597
633
|
/* @__PURE__ */ e(
|
|
598
634
|
"button",
|
|
599
635
|
{
|
|
600
636
|
"data-testid": "users-retry-btn",
|
|
601
|
-
onClick:
|
|
602
|
-
className: "mt-2 text-sm font-medium text-primary
|
|
637
|
+
onClick: b,
|
|
638
|
+
className: "mt-2 text-sm font-medium text-primary hover:underline",
|
|
603
639
|
children: "Try again"
|
|
604
640
|
}
|
|
605
641
|
)
|
|
606
642
|
]
|
|
607
643
|
}
|
|
608
|
-
) : /* @__PURE__ */
|
|
609
|
-
/* @__PURE__ */
|
|
644
|
+
) : /* @__PURE__ */ i("div", { children: [
|
|
645
|
+
/* @__PURE__ */ i("div", { className: "mb-4 flex items-center justify-between", children: [
|
|
610
646
|
/* @__PURE__ */ e(
|
|
611
647
|
"h2",
|
|
612
648
|
{
|
|
613
649
|
"data-testid": "users-heading",
|
|
614
|
-
className: "text-xl font-semibold text-
|
|
650
|
+
className: "text-xl font-semibold text-foreground",
|
|
615
651
|
children: "Users"
|
|
616
652
|
}
|
|
617
653
|
),
|
|
618
654
|
/* @__PURE__ */ e(
|
|
619
|
-
|
|
655
|
+
w,
|
|
620
656
|
{
|
|
621
657
|
"data-testid": "invite-user-btn",
|
|
622
|
-
onClick: () =>
|
|
623
|
-
className: F,
|
|
658
|
+
onClick: () => a(!0),
|
|
624
659
|
children: "Invite User"
|
|
625
660
|
}
|
|
626
661
|
)
|
|
627
662
|
] }),
|
|
663
|
+
/* @__PURE__ */ e(U, { rowData: p, columnDefs: J, loading: m }),
|
|
628
664
|
/* @__PURE__ */ e(
|
|
629
|
-
|
|
665
|
+
Ce,
|
|
630
666
|
{
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
mode: i,
|
|
634
|
-
theme: r,
|
|
635
|
-
loading: s
|
|
667
|
+
isOpen: g,
|
|
668
|
+
onClose: () => a(!1)
|
|
636
669
|
}
|
|
637
670
|
),
|
|
638
671
|
/* @__PURE__ */ e(
|
|
639
|
-
|
|
672
|
+
Me,
|
|
640
673
|
{
|
|
641
|
-
isOpen:
|
|
642
|
-
onClose: () =>
|
|
674
|
+
isOpen: !!y,
|
|
675
|
+
onClose: () => o(null),
|
|
676
|
+
user: {
|
|
677
|
+
id: y?.id ?? 0,
|
|
678
|
+
email: y?.email ?? "",
|
|
679
|
+
role: y?.role ?? ""
|
|
680
|
+
}
|
|
643
681
|
}
|
|
644
682
|
),
|
|
645
683
|
/* @__PURE__ */ e(
|
|
646
|
-
|
|
684
|
+
Q,
|
|
647
685
|
{
|
|
648
|
-
isOpen: !!
|
|
686
|
+
isOpen: !!v,
|
|
649
687
|
title: "Delete User",
|
|
650
|
-
message: `Are you sure you want to delete ${
|
|
688
|
+
message: `Are you sure you want to delete ${v?.email}? This action cannot be undone.`,
|
|
689
|
+
confirmLabel: l ? "Deleting..." : "Delete",
|
|
690
|
+
onConfirm: h,
|
|
691
|
+
onCancel: () => u(null),
|
|
692
|
+
isLoading: l
|
|
693
|
+
}
|
|
694
|
+
)
|
|
695
|
+
] });
|
|
696
|
+
}
|
|
697
|
+
function Te({
|
|
698
|
+
isOpen: t,
|
|
699
|
+
onClose: n,
|
|
700
|
+
role: s
|
|
701
|
+
}) {
|
|
702
|
+
const m = I(), { data: f } = re(), { data: b } = le(
|
|
703
|
+
{ id: s.id },
|
|
704
|
+
{ skip: !t }
|
|
705
|
+
), [d, { isLoading: l }] = oe(), [r, c] = N(/* @__PURE__ */ new Set()), g = f ?? [], a = b ?? [];
|
|
706
|
+
H(() => {
|
|
707
|
+
c(new Set(a.map((o) => o.id)));
|
|
708
|
+
}, [a]);
|
|
709
|
+
const v = R(() => {
|
|
710
|
+
const o = /* @__PURE__ */ new Map();
|
|
711
|
+
for (const p of g) {
|
|
712
|
+
const h = o.get(p.resource) ?? [];
|
|
713
|
+
h.push(p), o.set(p.resource, h);
|
|
714
|
+
}
|
|
715
|
+
return o;
|
|
716
|
+
}, [g]);
|
|
717
|
+
function u(o) {
|
|
718
|
+
c((p) => {
|
|
719
|
+
const h = new Set(p);
|
|
720
|
+
return h.has(o) ? h.delete(o) : h.add(o), h;
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
async function y(o) {
|
|
724
|
+
o.preventDefault();
|
|
725
|
+
try {
|
|
726
|
+
await d({
|
|
727
|
+
id: s.id,
|
|
728
|
+
setRolePermissionsDto: { permissionIds: [...r] }
|
|
729
|
+
}).unwrap(), m(A("Permissions updated successfully")), n();
|
|
730
|
+
} catch {
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return /* @__PURE__ */ e(j, { open: t, onOpenChange: (o) => !o && n(), children: /* @__PURE__ */ i(E, { children: [
|
|
734
|
+
/* @__PURE__ */ i(O, { children: [
|
|
735
|
+
/* @__PURE__ */ e(G, { children: "Manage Permissions" }),
|
|
736
|
+
/* @__PURE__ */ i($, { children: [
|
|
737
|
+
"Editing permissions for ",
|
|
738
|
+
/* @__PURE__ */ e("strong", { children: s.name })
|
|
739
|
+
] })
|
|
740
|
+
] }),
|
|
741
|
+
/* @__PURE__ */ i("form", { onSubmit: y, className: "mt-4", children: [
|
|
742
|
+
/* @__PURE__ */ e("div", { className: "max-h-64 space-y-4 overflow-y-auto", children: [...v.entries()].map(([o, p]) => /* @__PURE__ */ i("fieldset", { children: [
|
|
743
|
+
/* @__PURE__ */ e("legend", { className: "text-sm font-medium capitalize text-foreground", children: o }),
|
|
744
|
+
/* @__PURE__ */ e("div", { className: "mt-1 space-y-1", children: p.map((h) => /* @__PURE__ */ i(
|
|
745
|
+
"label",
|
|
746
|
+
{
|
|
747
|
+
className: "flex items-center gap-2 text-sm text-muted-foreground",
|
|
748
|
+
children: [
|
|
749
|
+
/* @__PURE__ */ e(
|
|
750
|
+
"input",
|
|
751
|
+
{
|
|
752
|
+
type: "checkbox",
|
|
753
|
+
checked: r.has(h.id),
|
|
754
|
+
onChange: () => u(h.id),
|
|
755
|
+
className: "rounded border-input text-primary focus:ring-ring"
|
|
756
|
+
}
|
|
757
|
+
),
|
|
758
|
+
/* @__PURE__ */ e("span", { children: h.action }),
|
|
759
|
+
h.description && /* @__PURE__ */ i("span", { className: "text-xs text-muted-foreground/70", children: [
|
|
760
|
+
"— ",
|
|
761
|
+
h.description
|
|
762
|
+
] })
|
|
763
|
+
]
|
|
764
|
+
},
|
|
765
|
+
h.id
|
|
766
|
+
)) })
|
|
767
|
+
] }, o)) }),
|
|
768
|
+
/* @__PURE__ */ i("div", { className: "mt-4 flex justify-end gap-3", children: [
|
|
769
|
+
/* @__PURE__ */ e(
|
|
770
|
+
w,
|
|
771
|
+
{
|
|
772
|
+
type: "button",
|
|
773
|
+
variant: "secondary",
|
|
774
|
+
"data-testid": "permissions-cancel-btn",
|
|
775
|
+
onClick: n,
|
|
776
|
+
disabled: l,
|
|
777
|
+
children: "Cancel"
|
|
778
|
+
}
|
|
779
|
+
),
|
|
780
|
+
/* @__PURE__ */ e(
|
|
781
|
+
w,
|
|
782
|
+
{
|
|
783
|
+
type: "submit",
|
|
784
|
+
"data-testid": "permissions-save-btn",
|
|
785
|
+
disabled: l,
|
|
786
|
+
children: l ? "Saving..." : "Save"
|
|
787
|
+
}
|
|
788
|
+
)
|
|
789
|
+
] })
|
|
790
|
+
] })
|
|
791
|
+
] }) });
|
|
792
|
+
}
|
|
793
|
+
function We() {
|
|
794
|
+
const t = I(), { data: n, isLoading: s, error: m, refetch: f } = F(), [b, { isLoading: d }] = de(), l = L("roles", "delete"), r = L("roles", "update"), [c, g] = N(null), [a, v] = N(null), u = n ?? [];
|
|
795
|
+
async function y() {
|
|
796
|
+
if (c)
|
|
797
|
+
try {
|
|
798
|
+
await b({ id: c.id }).unwrap(), t(A("Role deleted successfully"));
|
|
799
|
+
} catch {
|
|
800
|
+
} finally {
|
|
801
|
+
g(null);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
const o = R(
|
|
805
|
+
() => [
|
|
806
|
+
{ field: "name", headerName: "Name", flex: 1 },
|
|
807
|
+
{ field: "description", headerName: "Description", flex: 2 },
|
|
808
|
+
{
|
|
809
|
+
headerName: "Type",
|
|
810
|
+
flex: 1,
|
|
811
|
+
valueGetter: (p) => p.data?.isSystem ? "System" : "Custom"
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
headerName: "Actions",
|
|
815
|
+
flex: 1,
|
|
816
|
+
sortable: !1,
|
|
817
|
+
filter: !1,
|
|
818
|
+
cellRenderer: (p) => {
|
|
819
|
+
if (!p.data) return null;
|
|
820
|
+
const h = !!p.data.isSystem;
|
|
821
|
+
return /* @__PURE__ */ i("div", { className: "flex gap-1", children: [
|
|
822
|
+
r && /* @__PURE__ */ e(
|
|
823
|
+
"button",
|
|
824
|
+
{
|
|
825
|
+
onClick: () => p.data && v(p.data),
|
|
826
|
+
className: "rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10",
|
|
827
|
+
children: "Permissions"
|
|
828
|
+
}
|
|
829
|
+
),
|
|
830
|
+
l && /* @__PURE__ */ e(
|
|
831
|
+
"button",
|
|
832
|
+
{
|
|
833
|
+
onClick: () => p.data && g(p.data),
|
|
834
|
+
disabled: h,
|
|
835
|
+
title: h ? "Cannot delete a system role" : "Delete role",
|
|
836
|
+
className: "rounded px-2 py-1 text-xs font-medium text-destructive transition-colors hover:bg-destructive/10 disabled:cursor-not-allowed disabled:opacity-40",
|
|
837
|
+
children: "Delete"
|
|
838
|
+
}
|
|
839
|
+
)
|
|
840
|
+
] });
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
],
|
|
844
|
+
[r, l]
|
|
845
|
+
);
|
|
846
|
+
return m ? /* @__PURE__ */ i(
|
|
847
|
+
"div",
|
|
848
|
+
{
|
|
849
|
+
"data-testid": "roles-error",
|
|
850
|
+
className: "rounded-lg bg-destructive/10 p-6 text-center",
|
|
851
|
+
role: "alert",
|
|
852
|
+
children: [
|
|
853
|
+
/* @__PURE__ */ e("p", { className: "text-destructive", children: "Failed to load roles." }),
|
|
854
|
+
/* @__PURE__ */ e(
|
|
855
|
+
"button",
|
|
856
|
+
{
|
|
857
|
+
"data-testid": "roles-retry-btn",
|
|
858
|
+
onClick: f,
|
|
859
|
+
className: "mt-2 text-sm font-medium text-primary hover:underline",
|
|
860
|
+
children: "Try again"
|
|
861
|
+
}
|
|
862
|
+
)
|
|
863
|
+
]
|
|
864
|
+
}
|
|
865
|
+
) : /* @__PURE__ */ i("div", { children: [
|
|
866
|
+
/* @__PURE__ */ e("div", { className: "mb-4 flex items-center justify-between", children: /* @__PURE__ */ e(
|
|
867
|
+
"h2",
|
|
868
|
+
{
|
|
869
|
+
"data-testid": "roles-heading",
|
|
870
|
+
className: "text-xl font-semibold text-foreground",
|
|
871
|
+
children: "Roles & Permissions"
|
|
872
|
+
}
|
|
873
|
+
) }),
|
|
874
|
+
/* @__PURE__ */ e(U, { rowData: u, columnDefs: o, loading: s }),
|
|
875
|
+
/* @__PURE__ */ e(
|
|
876
|
+
Te,
|
|
877
|
+
{
|
|
878
|
+
isOpen: !!a,
|
|
879
|
+
onClose: () => v(null),
|
|
880
|
+
role: a ? { id: a.id, name: a.name } : { id: 0, name: "" }
|
|
881
|
+
}
|
|
882
|
+
),
|
|
883
|
+
/* @__PURE__ */ e(
|
|
884
|
+
Q,
|
|
885
|
+
{
|
|
886
|
+
isOpen: !!c,
|
|
887
|
+
title: "Delete Role",
|
|
888
|
+
message: `Are you sure you want to delete the "${c?.name}" role? This action cannot be undone.`,
|
|
651
889
|
confirmLabel: d ? "Deleting..." : "Delete",
|
|
652
|
-
onConfirm:
|
|
653
|
-
onCancel: () =>
|
|
890
|
+
onConfirm: y,
|
|
891
|
+
onCancel: () => g(null),
|
|
654
892
|
isLoading: d
|
|
655
893
|
}
|
|
656
894
|
)
|
|
657
895
|
] });
|
|
658
896
|
}
|
|
659
897
|
export {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
898
|
+
Ye as AcceptInvitation,
|
|
899
|
+
Je as InvitationList,
|
|
900
|
+
We as RoleList,
|
|
901
|
+
k as StatusCard,
|
|
902
|
+
Ke as UserList,
|
|
903
|
+
L as useHasPermission
|
|
664
904
|
};
|