@simple-auth-kit/cli 1.3.2 → 1.4.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/lib/copy.ts +67 -10
- package/package.json +1 -1
- package/registry/admin-apps/nextjs/shared/.husky/commit-msg +1 -0
- package/registry/admin-apps/nextjs/shared/.husky/pre-commit +1 -0
- package/registry/admin-apps/nextjs/shared/.lintstagedrc.json +4 -0
- package/registry/admin-apps/nextjs/shared/.prettierrc.json +3 -0
- package/registry/admin-apps/nextjs/shared/commitlint.config.js +5 -0
- package/registry/admin-apps/nextjs/shared/eslint.config.js +28 -0
- package/registry/admin-apps/nextjs/shared/gitignore +11 -0
- package/registry/admin-apps/nextjs/variants/base/package.json +11 -2
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/audit-log/page.tsx +72 -16
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/edit/page.tsx +107 -26
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/page.tsx +131 -29
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/edit/page.tsx +111 -25
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/page.tsx +97 -22
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/edit/page.tsx +129 -46
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/page.tsx +64 -14
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/page.tsx +91 -22
- package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/edit/page.tsx +94 -23
- package/registry/admin-apps/nextjs/variants/workspaces/package.json +11 -2
- package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/account/page.tsx +179 -41
- package/registry/admin-apps/react/shared/.husky/commit-msg +1 -0
- package/registry/admin-apps/react/shared/.husky/pre-commit +1 -0
- package/registry/admin-apps/react/shared/.lintstagedrc.json +4 -0
- package/registry/admin-apps/react/shared/.prettierrc.json +3 -0
- package/registry/admin-apps/react/shared/commitlint.config.js +3 -0
- package/registry/admin-apps/react/shared/eslint.config.js +38 -0
- package/registry/admin-apps/react/shared/gitignore +17 -0
- package/registry/admin-apps/react/variants/base/package.json +15 -2
- package/registry/admin-apps/react/variants/base/src/pages/CountryDetailPage.tsx +76 -19
- package/registry/admin-apps/react/variants/base/src/pages/CustomerDetailPage.tsx +110 -26
- package/registry/admin-apps/react/variants/base/src/pages/EditCountryPage.tsx +115 -29
- package/registry/admin-apps/react/variants/base/src/pages/EditCustomerPage.tsx +123 -31
- package/registry/admin-apps/react/variants/base/src/pages/EditLanguagePage.tsx +100 -24
- package/registry/admin-apps/react/variants/base/src/pages/EditRolePage.tsx +99 -26
- package/registry/admin-apps/react/variants/base/src/pages/EditUserPage.tsx +126 -31
- package/registry/admin-apps/react/variants/base/src/pages/LanguageDetailPage.tsx +75 -19
- package/registry/admin-apps/react/variants/base/src/pages/PermissionDetailPage.tsx +58 -13
- package/registry/admin-apps/react/variants/base/src/pages/PermissionsPage.tsx +132 -29
- package/registry/admin-apps/react/variants/base/src/pages/RoleDetailPage.tsx +70 -17
- package/registry/admin-apps/react/variants/base/src/pages/RolesPage.tsx +277 -59
- package/registry/admin-apps/react/variants/workspaces/package.json +15 -2
- package/registry/combos/express-drizzle/eslint.config.js +18 -0
- package/registry/combos/express-drizzle/package.json +5 -1
- package/registry/combos/express-drizzle/shared/src/request-context.ts +3 -0
- package/registry/combos/express-prisma/eslint.config.js +18 -0
- package/registry/combos/express-prisma/package.json +5 -1
- package/registry/combos/express-prisma/shared/src/request-context.ts +3 -0
- package/registry/combos/nestjs-drizzle/eslint.config.js +18 -0
- package/registry/combos/nestjs-drizzle/package.json +5 -1
- package/registry/combos/nestjs-drizzle/shared/src/auth.controller.ts +138 -33
- package/registry/combos/nestjs-drizzle/shared/src/route-tiers.ts +71 -18
- package/registry/combos/nestjs-prisma/eslint.config.js +18 -0
- package/registry/combos/nestjs-prisma/package.json +5 -1
- package/registry/combos/nestjs-prisma/shared/src/auth.controller.ts +148 -35
- package/registry/combos/nestjs-prisma/shared/src/route-tiers.ts +72 -18
- package/registry/mobile-apps/bare-rn/shared/.husky/commit-msg +1 -0
- package/registry/mobile-apps/bare-rn/shared/.husky/pre-commit +1 -0
- package/registry/mobile-apps/bare-rn/shared/.lintstagedrc.json +4 -0
- package/registry/mobile-apps/bare-rn/shared/.prettierrc.json +5 -0
- package/registry/mobile-apps/bare-rn/shared/commitlint.config.js +3 -0
- package/registry/mobile-apps/bare-rn/shared/eslint.config.js +19 -0
- package/registry/mobile-apps/bare-rn/shared/gitignore +78 -0
- package/registry/mobile-apps/bare-rn/variants/base/package.json +17 -12
- package/registry/mobile-apps/bare-rn/variants/workspaces/package.json +17 -12
- package/registry/mobile-apps/expo/shared/.husky/commit-msg +1 -0
- package/registry/mobile-apps/expo/shared/.husky/pre-commit +1 -0
- package/registry/mobile-apps/expo/shared/.lintstagedrc.json +4 -0
- package/registry/mobile-apps/expo/shared/.prettierrc.json +5 -0
- package/registry/mobile-apps/expo/shared/commitlint.config.js +3 -0
- package/registry/mobile-apps/expo/shared/eslint.config.js +9 -0
- package/registry/mobile-apps/expo/shared/gitignore +44 -0
- package/registry/mobile-apps/expo/shared/src/screens/SessionsScreen.tsx +6 -17
- package/registry/mobile-apps/expo/shared/src/store/sessionsStore.ts +35 -0
- package/registry/mobile-apps/expo/variants/base/package.json +12 -3
- package/registry/mobile-apps/expo/variants/workspaces/package.json +12 -3
- package/registry/mobile-apps/expo/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +1 -1
- package/registry.json +13 -36
- package/registry/mobile-apps/bare-rn/shared/.eslintrc.js +0 -4
- package/registry/mobile-apps/bare-rn/shared/.prettierrc.js +0 -5
|
@@ -1,20 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type FormEvent,
|
|
3
|
+
startTransition,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
2
8
|
import { useNavigate, useParams } from "react-router-dom";
|
|
3
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
AuthApiError,
|
|
11
|
+
type LanguageSummary,
|
|
12
|
+
type UpdateLanguageInput,
|
|
13
|
+
} from "@simple-auth-kit/auth-client";
|
|
4
14
|
import { toast } from "sonner";
|
|
5
15
|
import { authClient } from "@/lib/auth-client";
|
|
6
16
|
import { errorMessage, errorMessages } from "@/lib/error";
|
|
7
17
|
import { Breadcrumb } from "@/components/breadcrumb";
|
|
8
18
|
import { FormErrorAlert } from "@/components/form-error-alert";
|
|
9
19
|
import { Button } from "@/components/ui/button";
|
|
10
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
Card,
|
|
22
|
+
CardContent,
|
|
23
|
+
CardDescription,
|
|
24
|
+
CardFooter,
|
|
25
|
+
CardHeader,
|
|
26
|
+
CardTitle,
|
|
27
|
+
} from "@/components/ui/card";
|
|
11
28
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
12
29
|
import { Combobox } from "@/components/ui/combobox";
|
|
13
30
|
import { Heading } from "@/components/ui/heading";
|
|
14
31
|
import { Input } from "@/components/ui/input";
|
|
15
32
|
import { Label } from "@/components/ui/label";
|
|
16
33
|
import { Separator } from "@/components/ui/separator";
|
|
17
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
DIRECTION_OPTIONS,
|
|
36
|
+
emptyLanguageFields,
|
|
37
|
+
type LanguageFormFields,
|
|
38
|
+
} from "./language-schema";
|
|
18
39
|
|
|
19
40
|
function apiErrorMessage(err: unknown, fallback: string): string {
|
|
20
41
|
return err instanceof AuthApiError ? err.message : fallback;
|
|
@@ -31,7 +52,8 @@ function toForm(language: LanguageSummary): LanguageFormFields {
|
|
|
31
52
|
};
|
|
32
53
|
}
|
|
33
54
|
|
|
34
|
-
const inputClassName =
|
|
55
|
+
const inputClassName =
|
|
56
|
+
"bg-background border-2 focus:border-purple-500 transition-colors";
|
|
35
57
|
|
|
36
58
|
export function EditLanguagePage() {
|
|
37
59
|
const { id } = useParams<{ id: string }>();
|
|
@@ -58,7 +80,7 @@ export function EditLanguagePage() {
|
|
|
58
80
|
}, [id]);
|
|
59
81
|
|
|
60
82
|
useEffect(() => {
|
|
61
|
-
void load();
|
|
83
|
+
startTransition(() => void load());
|
|
62
84
|
}, [load]);
|
|
63
85
|
|
|
64
86
|
if (!id) return null;
|
|
@@ -101,7 +123,9 @@ export function EditLanguagePage() {
|
|
|
101
123
|
</div>
|
|
102
124
|
<Separator />
|
|
103
125
|
|
|
104
|
-
{loading && !language &&
|
|
126
|
+
{loading && !language && (
|
|
127
|
+
<p className="text-sm text-muted-foreground">Loading…</p>
|
|
128
|
+
)}
|
|
105
129
|
|
|
106
130
|
{language && (
|
|
107
131
|
<Card>
|
|
@@ -111,13 +135,19 @@ export function EditLanguagePage() {
|
|
|
111
135
|
<form onSubmit={handleSubmit} className="space-y-8 w-full">
|
|
112
136
|
<Card className="w-full">
|
|
113
137
|
<CardHeader className="border-b bg-muted/50">
|
|
114
|
-
<CardTitle className="text-2xl">
|
|
115
|
-
|
|
138
|
+
<CardTitle className="text-2xl">
|
|
139
|
+
Language Information
|
|
140
|
+
</CardTitle>
|
|
141
|
+
<CardDescription className="text-base">
|
|
142
|
+
Enter language details
|
|
143
|
+
</CardDescription>
|
|
116
144
|
</CardHeader>
|
|
117
145
|
<CardContent className="pt-6">
|
|
118
146
|
<div className="space-y-6">
|
|
119
147
|
<div className="space-y-4">
|
|
120
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
148
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
149
|
+
Basic Information
|
|
150
|
+
</h3>
|
|
121
151
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
122
152
|
<div className="flex flex-col gap-2">
|
|
123
153
|
<Label htmlFor="name">Language Name</Label>
|
|
@@ -127,7 +157,9 @@ export function EditLanguagePage() {
|
|
|
127
157
|
placeholder="e.g., English"
|
|
128
158
|
required
|
|
129
159
|
value={form.name}
|
|
130
|
-
onChange={(e) =>
|
|
160
|
+
onChange={(e) =>
|
|
161
|
+
setForm({ ...form, name: e.target.value })
|
|
162
|
+
}
|
|
131
163
|
type="text"
|
|
132
164
|
className={inputClassName}
|
|
133
165
|
/>
|
|
@@ -135,7 +167,9 @@ export function EditLanguagePage() {
|
|
|
135
167
|
<div className="flex flex-col gap-2">
|
|
136
168
|
<Label htmlFor="code">
|
|
137
169
|
Language Code
|
|
138
|
-
<span className="text-xs text-destructive dark:text-destructive-foreground">
|
|
170
|
+
<span className="text-xs text-destructive dark:text-destructive-foreground">
|
|
171
|
+
(ISO code, e.g., en, ar, bn)
|
|
172
|
+
</span>
|
|
139
173
|
</Label>
|
|
140
174
|
<Input
|
|
141
175
|
id="code"
|
|
@@ -143,7 +177,12 @@ export function EditLanguagePage() {
|
|
|
143
177
|
placeholder="e.g., en"
|
|
144
178
|
required
|
|
145
179
|
value={form.code}
|
|
146
|
-
onChange={(e) =>
|
|
180
|
+
onChange={(e) =>
|
|
181
|
+
setForm({
|
|
182
|
+
...form,
|
|
183
|
+
code: e.target.value.toLowerCase(),
|
|
184
|
+
})
|
|
185
|
+
}
|
|
147
186
|
type="text"
|
|
148
187
|
maxLength={10}
|
|
149
188
|
className={`${inputClassName} lowercase`}
|
|
@@ -152,7 +191,9 @@ export function EditLanguagePage() {
|
|
|
152
191
|
<div className="flex flex-col gap-2">
|
|
153
192
|
<Label htmlFor="nativeName">
|
|
154
193
|
Native Name
|
|
155
|
-
<span className="text-xs text-muted-foreground">
|
|
194
|
+
<span className="text-xs text-muted-foreground">
|
|
195
|
+
(e.g., العربية, বাংলা)
|
|
196
|
+
</span>
|
|
156
197
|
</Label>
|
|
157
198
|
<Input
|
|
158
199
|
id="nativeName"
|
|
@@ -160,7 +201,9 @@ export function EditLanguagePage() {
|
|
|
160
201
|
placeholder="e.g., English"
|
|
161
202
|
required
|
|
162
203
|
value={form.nativeName}
|
|
163
|
-
onChange={(e) =>
|
|
204
|
+
onChange={(e) =>
|
|
205
|
+
setForm({ ...form, nativeName: e.target.value })
|
|
206
|
+
}
|
|
164
207
|
type="text"
|
|
165
208
|
className={inputClassName}
|
|
166
209
|
/>
|
|
@@ -171,7 +214,12 @@ export function EditLanguagePage() {
|
|
|
171
214
|
options={DIRECTION_OPTIONS}
|
|
172
215
|
selected={form.direction}
|
|
173
216
|
placeholder="Select text direction"
|
|
174
|
-
onChange={(option) =>
|
|
217
|
+
onChange={(option) =>
|
|
218
|
+
setForm({
|
|
219
|
+
...form,
|
|
220
|
+
direction: option.value as "ltr" | "rtl",
|
|
221
|
+
})
|
|
222
|
+
}
|
|
175
223
|
showCreate={false}
|
|
176
224
|
popoverClassName="min-w-[250px]"
|
|
177
225
|
/>
|
|
@@ -183,26 +231,54 @@ export function EditLanguagePage() {
|
|
|
183
231
|
|
|
184
232
|
<div className="flex flex-wrap justify-center gap-4 mt-6">
|
|
185
233
|
<label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
|
|
186
|
-
<Checkbox
|
|
234
|
+
<Checkbox
|
|
235
|
+
checked={form.isDefault}
|
|
236
|
+
onCheckedChange={(checked) =>
|
|
237
|
+
setForm({ ...form, isDefault: checked === true })
|
|
238
|
+
}
|
|
239
|
+
/>
|
|
187
240
|
<span className="space-y-1 leading-none">
|
|
188
|
-
<span className="block text-base font-medium">
|
|
189
|
-
|
|
241
|
+
<span className="block text-base font-medium">
|
|
242
|
+
Default Language
|
|
243
|
+
</span>
|
|
244
|
+
<span className="block text-sm text-muted-foreground">
|
|
245
|
+
The default language is the one a new deployment's
|
|
246
|
+
locale falls back to
|
|
247
|
+
</span>
|
|
190
248
|
</span>
|
|
191
249
|
</label>
|
|
192
250
|
<label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
|
|
193
|
-
<Checkbox
|
|
251
|
+
<Checkbox
|
|
252
|
+
checked={form.isActive}
|
|
253
|
+
onCheckedChange={(checked) =>
|
|
254
|
+
setForm({ ...form, isActive: checked === true })
|
|
255
|
+
}
|
|
256
|
+
/>
|
|
194
257
|
<span className="space-y-1 leading-none">
|
|
195
|
-
<span className="block text-base font-medium">
|
|
196
|
-
|
|
258
|
+
<span className="block text-base font-medium">
|
|
259
|
+
Active Status
|
|
260
|
+
</span>
|
|
261
|
+
<span className="block text-sm text-muted-foreground">
|
|
262
|
+
Language will be active and available for selection
|
|
263
|
+
</span>
|
|
197
264
|
</span>
|
|
198
265
|
</label>
|
|
199
266
|
</div>
|
|
200
267
|
|
|
201
268
|
<CardFooter className="flex justify-center gap-4 mt-8 pb-8">
|
|
202
|
-
<Button
|
|
269
|
+
<Button
|
|
270
|
+
type="button"
|
|
271
|
+
variant="outline"
|
|
272
|
+
onClick={() => navigate(`/languages/${id}`)}
|
|
273
|
+
disabled={saving}
|
|
274
|
+
>
|
|
203
275
|
Cancel
|
|
204
276
|
</Button>
|
|
205
|
-
<Button
|
|
277
|
+
<Button
|
|
278
|
+
disabled={saving}
|
|
279
|
+
className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32"
|
|
280
|
+
type="submit"
|
|
281
|
+
>
|
|
206
282
|
{saving ? "Updating..." : "Update Language"}
|
|
207
283
|
</Button>
|
|
208
284
|
</CardFooter>
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type FormEvent,
|
|
3
|
+
startTransition,
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState,
|
|
7
|
+
} from "react";
|
|
2
8
|
import { useNavigate, useParams } from "react-router-dom";
|
|
3
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
PermissionSummary,
|
|
11
|
+
RoleSummary,
|
|
12
|
+
} from "@simple-auth-kit/auth-client";
|
|
4
13
|
import { AuthApiError } from "@simple-auth-kit/auth-client";
|
|
5
14
|
import { toast } from "sonner";
|
|
6
15
|
import { PERMISSIONS, useAbility } from "@/lib/ability";
|
|
@@ -10,7 +19,14 @@ import { Breadcrumb } from "@/components/breadcrumb";
|
|
|
10
19
|
import { FormErrorAlert } from "@/components/form-error-alert";
|
|
11
20
|
import { PermissionGroupSelect } from "@/components/permission-group-select";
|
|
12
21
|
import { Button } from "@/components/ui/button";
|
|
13
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
Card,
|
|
24
|
+
CardContent,
|
|
25
|
+
CardDescription,
|
|
26
|
+
CardFooter,
|
|
27
|
+
CardHeader,
|
|
28
|
+
CardTitle,
|
|
29
|
+
} from "@/components/ui/card";
|
|
14
30
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
15
31
|
import { Heading } from "@/components/ui/heading";
|
|
16
32
|
import { Input } from "@/components/ui/input";
|
|
@@ -25,13 +41,17 @@ function sameSlugs(a: string[], b: string[]): boolean {
|
|
|
25
41
|
return JSON.stringify([...a].sort()) === JSON.stringify([...b].sort());
|
|
26
42
|
}
|
|
27
43
|
|
|
28
|
-
const inputClassName =
|
|
44
|
+
const inputClassName =
|
|
45
|
+
"bg-background border-2 focus:border-purple-500 transition-colors";
|
|
29
46
|
|
|
30
47
|
export function EditRolePage() {
|
|
31
48
|
const { id } = useParams<{ id: string }>();
|
|
32
49
|
const navigate = useNavigate();
|
|
33
50
|
const ability = useAbility();
|
|
34
|
-
const canReadPermissions = ability.can(
|
|
51
|
+
const canReadPermissions = ability.can(
|
|
52
|
+
PERMISSIONS.permissionsRead,
|
|
53
|
+
"permission",
|
|
54
|
+
);
|
|
35
55
|
|
|
36
56
|
const [role, setRole] = useState<RoleSummary | null>(null);
|
|
37
57
|
const [loading, setLoading] = useState(false);
|
|
@@ -40,7 +60,9 @@ export function EditRolePage() {
|
|
|
40
60
|
const [isDefault, setIsDefault] = useState(false);
|
|
41
61
|
const [isActive, setIsActive] = useState(true);
|
|
42
62
|
const [selectedPermissions, setSelectedPermissions] = useState<string[]>([]);
|
|
43
|
-
const [permissionCatalog, setPermissionCatalog] = useState<
|
|
63
|
+
const [permissionCatalog, setPermissionCatalog] = useState<
|
|
64
|
+
PermissionSummary[]
|
|
65
|
+
>([]);
|
|
44
66
|
const [formError, setFormError] = useState<string[] | null>(null);
|
|
45
67
|
const [saving, setSaving] = useState(false);
|
|
46
68
|
|
|
@@ -70,7 +92,7 @@ export function EditRolePage() {
|
|
|
70
92
|
}, [id]);
|
|
71
93
|
|
|
72
94
|
useEffect(() => {
|
|
73
|
-
void load();
|
|
95
|
+
startTransition(() => void load());
|
|
74
96
|
}, [load]);
|
|
75
97
|
|
|
76
98
|
useEffect(() => {
|
|
@@ -78,7 +100,11 @@ export function EditRolePage() {
|
|
|
78
100
|
authClient
|
|
79
101
|
.listPermissions({ activeOnly: true })
|
|
80
102
|
.then(setPermissionCatalog)
|
|
81
|
-
.catch((err) =>
|
|
103
|
+
.catch((err) =>
|
|
104
|
+
toast.error(
|
|
105
|
+
apiErrorMessage(err, "Couldn't load the permission catalog."),
|
|
106
|
+
),
|
|
107
|
+
);
|
|
82
108
|
}, [canReadPermissions]);
|
|
83
109
|
|
|
84
110
|
const unchanged =
|
|
@@ -96,8 +122,12 @@ export function EditRolePage() {
|
|
|
96
122
|
setSaving(true);
|
|
97
123
|
try {
|
|
98
124
|
// No bulk "set permissions" endpoint — diffs against the role loaded at mount and attaches/detaches only the delta.
|
|
99
|
-
const toAttach = selectedPermissions.filter(
|
|
100
|
-
|
|
125
|
+
const toAttach = selectedPermissions.filter(
|
|
126
|
+
(slug) => !role.permissions.includes(slug),
|
|
127
|
+
);
|
|
128
|
+
const toDetach = role.permissions.filter(
|
|
129
|
+
(slug) => !selectedPermissions.includes(slug),
|
|
130
|
+
);
|
|
101
131
|
const [updated] = await Promise.all([
|
|
102
132
|
authClient.updateRole(role.id, {
|
|
103
133
|
displayName: displayName.trim() === "" ? undefined : displayName,
|
|
@@ -105,14 +135,20 @@ export function EditRolePage() {
|
|
|
105
135
|
isDefault,
|
|
106
136
|
isActive,
|
|
107
137
|
}),
|
|
108
|
-
...toAttach.map((slug) =>
|
|
109
|
-
|
|
138
|
+
...toAttach.map((slug) =>
|
|
139
|
+
authClient.attachPermissionToRole(role.id, slug),
|
|
140
|
+
),
|
|
141
|
+
...toDetach.map((slug) =>
|
|
142
|
+
authClient.detachPermissionFromRole(role.id, slug),
|
|
143
|
+
),
|
|
110
144
|
]);
|
|
111
145
|
toast.success(`Role "${updated.name}" updated.`);
|
|
112
146
|
navigate("/roles");
|
|
113
147
|
} catch (err) {
|
|
114
148
|
setFormError(errorMessages(err));
|
|
115
|
-
toast.error(
|
|
149
|
+
toast.error(
|
|
150
|
+
apiErrorMessage(err, "Couldn't update this role. Try again."),
|
|
151
|
+
);
|
|
116
152
|
setSaving(false);
|
|
117
153
|
}
|
|
118
154
|
}
|
|
@@ -131,7 +167,9 @@ export function EditRolePage() {
|
|
|
131
167
|
</div>
|
|
132
168
|
<Separator />
|
|
133
169
|
|
|
134
|
-
{loading && !role &&
|
|
170
|
+
{loading && !role && (
|
|
171
|
+
<p className="text-sm text-muted-foreground">Loading…</p>
|
|
172
|
+
)}
|
|
135
173
|
|
|
136
174
|
{role && (
|
|
137
175
|
<Card>
|
|
@@ -142,12 +180,16 @@ export function EditRolePage() {
|
|
|
142
180
|
<Card className="w-full">
|
|
143
181
|
<CardHeader className="border-b bg-muted/50">
|
|
144
182
|
<CardTitle className="text-2xl">Role Information</CardTitle>
|
|
145
|
-
<CardDescription className="text-base">
|
|
183
|
+
<CardDescription className="text-base">
|
|
184
|
+
{role.name}
|
|
185
|
+
</CardDescription>
|
|
146
186
|
</CardHeader>
|
|
147
187
|
<CardContent className="pt-6">
|
|
148
188
|
<div className="space-y-6">
|
|
149
189
|
<div className="space-y-4">
|
|
150
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
190
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
191
|
+
Basic Information
|
|
192
|
+
</h3>
|
|
151
193
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
152
194
|
<div className="flex flex-col gap-2">
|
|
153
195
|
<Label htmlFor="displayName">Display Name</Label>
|
|
@@ -182,12 +224,20 @@ export function EditRolePage() {
|
|
|
182
224
|
<>
|
|
183
225
|
<CardHeader className="border-b bg-muted/50 mt-6">
|
|
184
226
|
<CardTitle className="text-2xl">Permissions</CardTitle>
|
|
185
|
-
<CardDescription className="text-base">
|
|
227
|
+
<CardDescription className="text-base">
|
|
228
|
+
Pick the permissions this role grants
|
|
229
|
+
</CardDescription>
|
|
186
230
|
</CardHeader>
|
|
187
231
|
<CardContent className="pt-6">
|
|
188
232
|
<div className="space-y-4">
|
|
189
|
-
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
190
|
-
|
|
233
|
+
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
|
|
234
|
+
Permissions
|
|
235
|
+
</h3>
|
|
236
|
+
<PermissionGroupSelect
|
|
237
|
+
permissions={permissionCatalog}
|
|
238
|
+
selected={selectedPermissions}
|
|
239
|
+
onChange={setSelectedPermissions}
|
|
240
|
+
/>
|
|
191
241
|
</div>
|
|
192
242
|
</CardContent>
|
|
193
243
|
</>
|
|
@@ -195,23 +245,46 @@ export function EditRolePage() {
|
|
|
195
245
|
|
|
196
246
|
<div className="flex flex-wrap justify-center gap-4 mt-6">
|
|
197
247
|
<label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
|
|
198
|
-
<Checkbox
|
|
248
|
+
<Checkbox
|
|
249
|
+
checked={isDefault}
|
|
250
|
+
onCheckedChange={(checked) =>
|
|
251
|
+
setIsDefault(checked === true)
|
|
252
|
+
}
|
|
253
|
+
/>
|
|
199
254
|
<span className="space-y-1 leading-none">
|
|
200
|
-
<span className="block text-base font-medium">
|
|
201
|
-
|
|
255
|
+
<span className="block text-base font-medium">
|
|
256
|
+
Default Role
|
|
257
|
+
</span>
|
|
258
|
+
<span className="block text-sm text-muted-foreground">
|
|
259
|
+
Given to every newly signed-up user
|
|
260
|
+
</span>
|
|
202
261
|
</span>
|
|
203
262
|
</label>
|
|
204
263
|
<label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
|
|
205
|
-
<Checkbox
|
|
264
|
+
<Checkbox
|
|
265
|
+
checked={isActive}
|
|
266
|
+
onCheckedChange={(checked) =>
|
|
267
|
+
setIsActive(checked === true)
|
|
268
|
+
}
|
|
269
|
+
/>
|
|
206
270
|
<span className="space-y-1 leading-none">
|
|
207
|
-
<span className="block text-base font-medium">
|
|
208
|
-
|
|
271
|
+
<span className="block text-base font-medium">
|
|
272
|
+
Active Status
|
|
273
|
+
</span>
|
|
274
|
+
<span className="block text-sm text-muted-foreground">
|
|
275
|
+
This role will be active and can be assigned to users
|
|
276
|
+
</span>
|
|
209
277
|
</span>
|
|
210
278
|
</label>
|
|
211
279
|
</div>
|
|
212
280
|
|
|
213
281
|
<CardFooter className="flex justify-center gap-4 mt-8 pb-8">
|
|
214
|
-
<Button
|
|
282
|
+
<Button
|
|
283
|
+
type="button"
|
|
284
|
+
variant="outline"
|
|
285
|
+
onClick={() => navigate("/roles")}
|
|
286
|
+
disabled={saving}
|
|
287
|
+
>
|
|
215
288
|
Cancel
|
|
216
289
|
</Button>
|
|
217
290
|
<Button
|