@allbluecn/admin-app 0.2.0 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -10
- package/src/components/admin/admin-user-menu.tsx +12 -6
- package/src/components/admin/developer-log.tsx +42 -44
- package/src/components/ai-provider/model-list-editor.tsx +5 -4
- package/src/components/ai-provider/provider-form.tsx +63 -64
- package/src/components/ai-provider/provider-table.tsx +35 -36
- package/src/components/auth/admin-login-form.tsx +23 -24
- package/src/components/auth/oauth-section.tsx +3 -5
- package/src/components/auth/password-input.tsx +2 -3
- package/src/components/common/placeholder-page.tsx +2 -4
- package/src/components/component/component-form-dialog.tsx +48 -49
- package/src/components/component/component-import-dialog.tsx +5 -5
- package/src/components/component/component-table.tsx +13 -14
- package/src/components/data-table/data-table-pagination.tsx +4 -6
- package/src/components/data-table/table-detail-layout.tsx +2 -3
- package/src/components/dependency/changelog-dialog.tsx +3 -4
- package/src/components/dependency/columns.tsx +32 -24
- package/src/components/dependency/dependency-table.tsx +37 -29
- package/src/components/dependency/edit-dialog.tsx +24 -25
- package/src/components/knowledge-public/bookmark-form-dialog.tsx +7 -7
- package/src/components/knowledge-public/compliance-form-dialog.tsx +13 -13
- package/src/components/knowledge-public/legal-form-dialog.tsx +51 -46
- package/src/components/layout/sidebar-02/app-sidebar.tsx +33 -34
- package/src/components/layout/sidebar-02/nav-main.tsx +1 -1
- package/src/components/market/columns.tsx +20 -21
- package/src/components/market/market-app-form.tsx +45 -38
- package/src/components/market/market-app-list.tsx +16 -17
- package/src/components/monitoring/error-list.tsx +18 -19
- package/src/components/monitoring/health-cards.tsx +11 -13
- package/src/components/monitoring/metrics-stats.tsx +11 -12
- package/src/components/monitoring/request-log-table.tsx +8 -9
- package/src/components/ui/pagination.tsx +0 -2
- package/src/components/ui/sidebar.tsx +1 -1
- package/src/components/user/columns.tsx +9 -9
- package/src/components/user/settings-activity-log.tsx +39 -29
- package/src/components/user/settings-profile.tsx +36 -36
- package/src/components/user/user-create-dialog.tsx +4 -4
- package/src/components/user/user-filters.tsx +16 -18
- package/src/lib/i18n/config.ts +0 -32
- package/src/providers/index.tsx +6 -16
- package/src/routeTree.gen.ts +1199 -0
- package/src/routes/__root.tsx +9 -23
- package/src/routes/_nav/apps/route.lazy.tsx +2 -3
- package/src/routes/_nav/audit/route.lazy.tsx +10 -11
- package/src/routes/_nav/billing/invoices/route.lazy.tsx +6 -7
- package/src/routes/_nav/billing/route.lazy.tsx +3 -4
- package/src/routes/_nav/billing/subscriptions/$subscriptionId/route.lazy.tsx +16 -17
- package/src/routes/_nav/billing/subscriptions/route.lazy.tsx +9 -10
- package/src/routes/_nav/compliance/route.lazy.tsx +34 -35
- package/src/routes/_nav/components/route.lazy.tsx +6 -6
- package/src/routes/_nav/dashboard/route.lazy.tsx +3 -5
- package/src/routes/_nav/dependencies/route.lazy.tsx +7 -8
- package/src/routes/_nav/docs/route.lazy.tsx +2 -3
- package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +40 -41
- package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +32 -33
- package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +32 -33
- package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +24 -31
- package/src/routes/_nav/licenses/new/route.lazy.tsx +25 -26
- package/src/routes/_nav/licenses/route.lazy.tsx +17 -18
- package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +26 -27
- package/src/routes/_nav/monitoring/errors/route.lazy.tsx +11 -12
- package/src/routes/_nav/monitoring/health/route.lazy.tsx +18 -20
- package/src/routes/_nav/monitoring/logs/route.lazy.tsx +12 -13
- package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +13 -15
- package/src/routes/_nav/monitoring/overview/route.lazy.tsx +12 -13
- package/src/routes/_nav/monitoring/route.lazy.tsx +8 -9
- package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +55 -57
- package/src/routes/_nav/permissions/route.lazy.tsx +48 -50
- package/src/routes/_nav/settings/route.lazy.tsx +2 -3
- package/src/routes/_nav/sso/route.lazy.tsx +20 -18
- package/src/routes/_nav/users/$userId/route.lazy.tsx +86 -82
- package/src/routes/_nav/users/route.lazy.tsx +4 -5
- package/src/routes/setup/route.lazy.tsx +15 -16
- package/src/start.ts +2 -2
- package/src/lib/i18n/client.ts +0 -32
- package/src/lib/i18n/locales/en/admin-ai.json +0 -128
- package/src/lib/i18n/locales/en/admin-billing.json +0 -56
- package/src/lib/i18n/locales/en/admin-users.json +0 -88
- package/src/lib/i18n/locales/en/common.json +0 -877
- package/src/lib/i18n/locales/en/enterprise.json +0 -208
- package/src/lib/i18n/locales/zh/admin-ai.json +0 -128
- package/src/lib/i18n/locales/zh/admin-billing.json +0 -56
- package/src/lib/i18n/locales/zh/admin-users.json +0 -88
- package/src/lib/i18n/locales/zh/common.json +0 -877
- package/src/lib/i18n/locales/zh/enterprise.json +0 -208
- package/src/lib/i18n/server.ts +0 -18
- package/src/lib/i18n/types.ts +0 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createLazyFileRoute, Link, useLocation } from '@tanstack/react-router'
|
|
2
|
+
import { m } from '@/paraglide/messages.js'
|
|
3
|
+
import { getLocale } from '@/paraglide/runtime.js'
|
|
2
4
|
import { useServerFn } from '@tanstack/react-start'
|
|
3
|
-
import { useTranslation } from 'react-i18next'
|
|
4
5
|
import { toast } from 'sonner'
|
|
5
6
|
import { useCallback, useEffect, useState } from 'react'
|
|
6
7
|
import type React from 'react'
|
|
@@ -112,7 +113,6 @@ function CreateRoleDialog({
|
|
|
112
113
|
i18nLang: string
|
|
113
114
|
onCreated: () => void
|
|
114
115
|
}): React.ReactElement {
|
|
115
|
-
const { t } = useTranslation('enterprise')
|
|
116
116
|
const createRole = useServerFn(createRoleFn)
|
|
117
117
|
const [name, setName] = useState('')
|
|
118
118
|
const [permissions, setPermissions] = useState<ResourcePermission>({})
|
|
@@ -132,7 +132,7 @@ function CreateRoleDialog({
|
|
|
132
132
|
|
|
133
133
|
const handleSubmit = async () => {
|
|
134
134
|
if (!name.trim()) {
|
|
135
|
-
toast.warning(
|
|
135
|
+
toast.warning(m.enterprise_permissions_toast_nameRequired())
|
|
136
136
|
return
|
|
137
137
|
}
|
|
138
138
|
await createRole({
|
|
@@ -142,7 +142,7 @@ function CreateRoleDialog({
|
|
|
142
142
|
permissions,
|
|
143
143
|
},
|
|
144
144
|
})
|
|
145
|
-
toast.success(
|
|
145
|
+
toast.success(m.enterprise_permissions_toast_created({ name: name.trim() }))
|
|
146
146
|
onOpenChange(false)
|
|
147
147
|
onCreated()
|
|
148
148
|
}
|
|
@@ -151,24 +151,24 @@ function CreateRoleDialog({
|
|
|
151
151
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
152
152
|
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
|
153
153
|
<DialogHeader>
|
|
154
|
-
<DialogTitle>{
|
|
155
|
-
<DialogDescription>{
|
|
154
|
+
<DialogTitle>{m.enterprise_permissions_createRole()}</DialogTitle>
|
|
155
|
+
<DialogDescription>{m.enterprise_permissions_createRoleDesc()}</DialogDescription>
|
|
156
156
|
</DialogHeader>
|
|
157
157
|
|
|
158
158
|
<div className="space-y-4">
|
|
159
159
|
<div className="grid gap-2">
|
|
160
|
-
<Label htmlFor="role-name">{
|
|
160
|
+
<Label htmlFor="role-name">{m.enterprise_permissions_roleName()}</Label>
|
|
161
161
|
<Input
|
|
162
162
|
id="role-name"
|
|
163
163
|
value={name}
|
|
164
|
-
onChange={(e) => setName(e.target.value)}
|
|
165
|
-
placeholder={
|
|
164
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setName(e.target.value)}
|
|
165
|
+
placeholder={m.enterprise_permissions_roleNamePlaceholder()}
|
|
166
166
|
autoFocus
|
|
167
167
|
/>
|
|
168
168
|
</div>
|
|
169
169
|
|
|
170
170
|
<div className="space-y-3">
|
|
171
|
-
<Label>{
|
|
171
|
+
<Label>{m.enterprise_permissions_permissionsMatrix()}</Label>
|
|
172
172
|
{ALL_RESOURCES.map((resource) => (
|
|
173
173
|
<div key={resource.key} className="space-y-2">
|
|
174
174
|
<span className="text-sm font-medium">{isZh ? resource.labelZh : resource.labelEn}</span>
|
|
@@ -177,7 +177,7 @@ function CreateRoleDialog({
|
|
|
177
177
|
<Select
|
|
178
178
|
key={action.key}
|
|
179
179
|
value={permissions[`${resource.key}:${action.key}`] || 'none'}
|
|
180
|
-
onValueChange={(value) => handleLevelChange(resource.key, action.key, value)}
|
|
180
|
+
onValueChange={(value: string) => handleLevelChange(resource.key, action.key, value)}
|
|
181
181
|
>
|
|
182
182
|
<SelectTrigger className="h-8">
|
|
183
183
|
<SelectValue>
|
|
@@ -201,9 +201,9 @@ function CreateRoleDialog({
|
|
|
201
201
|
|
|
202
202
|
<DialogFooter>
|
|
203
203
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
204
|
-
{
|
|
204
|
+
{m.enterprise_permissions_dialog_cancel()}
|
|
205
205
|
</Button>
|
|
206
|
-
<Button onClick={handleSubmit}>{
|
|
206
|
+
<Button onClick={handleSubmit}>{m.enterprise_permissions_dialog_create()}</Button>
|
|
207
207
|
</DialogFooter>
|
|
208
208
|
</DialogContent>
|
|
209
209
|
</Dialog>
|
|
@@ -223,7 +223,6 @@ function AssignDialog({
|
|
|
223
223
|
i18nLang: string
|
|
224
224
|
onAssigned: () => void
|
|
225
225
|
}): React.ReactElement {
|
|
226
|
-
const { t } = useTranslation('enterprise')
|
|
227
226
|
const assignRole = useServerFn(assignRoleFn)
|
|
228
227
|
const unassignRole = useServerFn(unassignRoleFn)
|
|
229
228
|
const listAssignments = useServerFn(listRoleAssignmentsFn)
|
|
@@ -234,7 +233,7 @@ function AssignDialog({
|
|
|
234
233
|
useEffect(() => {
|
|
235
234
|
if (open && role) {
|
|
236
235
|
listAssignments({ data: { roleId: role.id } })
|
|
237
|
-
.then((result) => setAssignments(result))
|
|
236
|
+
.then((result: any) => setAssignments(result))
|
|
238
237
|
.catch(() => setAssignments([]))
|
|
239
238
|
}
|
|
240
239
|
}, [open, role, listAssignments])
|
|
@@ -242,14 +241,14 @@ function AssignDialog({
|
|
|
242
241
|
const handleAssign = async () => {
|
|
243
242
|
if (!searchUser.trim() || !role) return
|
|
244
243
|
await assignRole({ data: { userId: searchUser.trim(), roleId: role.id } })
|
|
245
|
-
toast.success(
|
|
244
|
+
toast.success(m.enterprise_permissions_toast_assigned())
|
|
246
245
|
setSearchUser('')
|
|
247
246
|
onAssigned()
|
|
248
247
|
}
|
|
249
248
|
|
|
250
249
|
const handleUnassign = async (assignmentId: string) => {
|
|
251
250
|
await unassignRole({ data: { assignmentId } })
|
|
252
|
-
toast.success(
|
|
251
|
+
toast.success(m.enterprise_permissions_toast_unassigned())
|
|
253
252
|
setAssignments(assignments.filter((a) => a.id !== assignmentId))
|
|
254
253
|
}
|
|
255
254
|
|
|
@@ -258,25 +257,25 @@ function AssignDialog({
|
|
|
258
257
|
<DialogContent className="max-w-lg">
|
|
259
258
|
<DialogHeader>
|
|
260
259
|
<DialogTitle>
|
|
261
|
-
{
|
|
260
|
+
{m.enterprise_permissions_assign({ name: role?.name ?? '' })}
|
|
262
261
|
</DialogTitle>
|
|
263
|
-
<DialogDescription>{
|
|
262
|
+
<DialogDescription>{m.enterprise_permissions_assignDesc()}</DialogDescription>
|
|
264
263
|
</DialogHeader>
|
|
265
264
|
|
|
266
265
|
<div className="space-y-4">
|
|
267
266
|
<div className="flex gap-2">
|
|
268
267
|
<Input
|
|
269
268
|
value={searchUser}
|
|
270
|
-
onChange={(e) => setSearchUser(e.target.value)}
|
|
271
|
-
placeholder={
|
|
269
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchUser(e.target.value)}
|
|
270
|
+
placeholder={m.enterprise_permissions_searchUserPlaceholder()}
|
|
272
271
|
/>
|
|
273
272
|
<Button onClick={handleAssign} disabled={!searchUser.trim()}>
|
|
274
|
-
{
|
|
273
|
+
{m.enterprise_permissions_assignUser()}
|
|
275
274
|
</Button>
|
|
276
275
|
</div>
|
|
277
276
|
|
|
278
277
|
{assignments.length === 0 ? (
|
|
279
|
-
<p className="text-sm text-muted-foreground">{
|
|
278
|
+
<p className="text-sm text-muted-foreground">{m.enterprise_permissions_noAssignments()}</p>
|
|
280
279
|
) : (
|
|
281
280
|
<Table>
|
|
282
281
|
<TableHeader>
|
|
@@ -297,7 +296,7 @@ function AssignDialog({
|
|
|
297
296
|
className="text-destructive hover:underline"
|
|
298
297
|
onClick={() => handleUnassign(a.id)}
|
|
299
298
|
>
|
|
300
|
-
{
|
|
299
|
+
{m.enterprise_permissions_unassign()}
|
|
301
300
|
</button>
|
|
302
301
|
</TableCell>
|
|
303
302
|
</TableRow>
|
|
@@ -309,7 +308,7 @@ function AssignDialog({
|
|
|
309
308
|
|
|
310
309
|
<DialogFooter>
|
|
311
310
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
312
|
-
{
|
|
311
|
+
{m.enterprise_permissions_dialog_close()}
|
|
313
312
|
</Button>
|
|
314
313
|
</DialogFooter>
|
|
315
314
|
</DialogContent>
|
|
@@ -318,7 +317,6 @@ function AssignDialog({
|
|
|
318
317
|
}
|
|
319
318
|
|
|
320
319
|
function PermissionsPage(): React.ReactElement {
|
|
321
|
-
const { t, i18n } = useTranslation('enterprise')
|
|
322
320
|
const location = useLocation()
|
|
323
321
|
const selectedWorkspaceId =
|
|
324
322
|
(location.search as { workspaceId?: string }).workspaceId ??
|
|
@@ -337,7 +335,7 @@ function PermissionsPage(): React.ReactElement {
|
|
|
337
335
|
useEffect(() => {
|
|
338
336
|
if (selectedWorkspaceId) {
|
|
339
337
|
listRoles({ data: { workspaceId: selectedWorkspaceId } })
|
|
340
|
-
.then((result) => {
|
|
338
|
+
.then((result: any) => {
|
|
341
339
|
const data = result as { items: RoleItem[]; total: number; seeded: string }
|
|
342
340
|
setRoles(data.items)
|
|
343
341
|
})
|
|
@@ -347,11 +345,11 @@ function PermissionsPage(): React.ReactElement {
|
|
|
347
345
|
|
|
348
346
|
const handleDelete = async (role: RoleItem) => {
|
|
349
347
|
if (role.isSystem) {
|
|
350
|
-
toast.info(
|
|
348
|
+
toast.info(m.enterprise_permissions_toast_systemRole())
|
|
351
349
|
return
|
|
352
350
|
}
|
|
353
351
|
await deleteRole({ data: { roleId: role.id } })
|
|
354
|
-
toast.success(
|
|
352
|
+
toast.success(m.enterprise_permissions_toast_deleted({ name: role.name }))
|
|
355
353
|
setRoles(roles.filter((r) => r.id !== role.id))
|
|
356
354
|
}
|
|
357
355
|
|
|
@@ -361,10 +359,10 @@ function PermissionsPage(): React.ReactElement {
|
|
|
361
359
|
}
|
|
362
360
|
|
|
363
361
|
const PERMISSION_LEVELS: Record<string, () => string> = {
|
|
364
|
-
admin: () =>
|
|
365
|
-
write: () =>
|
|
366
|
-
read: () =>
|
|
367
|
-
none: () =>
|
|
362
|
+
admin: () => m.enterprise_permissions_level_admin(),
|
|
363
|
+
write: () => m.enterprise_permissions_level_write(),
|
|
364
|
+
read: () => m.enterprise_permissions_level_read(),
|
|
365
|
+
none: () => m.enterprise_permissions_level_none(),
|
|
368
366
|
}
|
|
369
367
|
|
|
370
368
|
const workspaces = (Route.useLoaderData() as {
|
|
@@ -374,13 +372,13 @@ function PermissionsPage(): React.ReactElement {
|
|
|
374
372
|
return (
|
|
375
373
|
<div className="space-y-4">
|
|
376
374
|
<div>
|
|
377
|
-
<h1 className="text-2xl font-bold">{
|
|
378
|
-
<p className="text-sm text-muted-foreground mt-1">{
|
|
375
|
+
<h1 className="text-2xl font-bold">{m.enterprise_permissions_title()}</h1>
|
|
376
|
+
<p className="text-sm text-muted-foreground mt-1">{m.enterprise_permissions_subtitle()}</p>
|
|
379
377
|
</div>
|
|
380
378
|
|
|
381
379
|
{workspaces.length > 0 && (
|
|
382
380
|
<div className="flex items-center gap-2">
|
|
383
|
-
<span className="text-sm text-muted-foreground">{
|
|
381
|
+
<span className="text-sm text-muted-foreground">{m.enterprise_permissions_workspaceLabel()}</span>
|
|
384
382
|
{workspaces.map((ws) => (
|
|
385
383
|
<Link
|
|
386
384
|
key={ws.id}
|
|
@@ -400,18 +398,18 @@ function PermissionsPage(): React.ReactElement {
|
|
|
400
398
|
|
|
401
399
|
{roles.length === 0 ? (
|
|
402
400
|
<div className="rounded-lg border border-border p-8 text-center text-muted-foreground">
|
|
403
|
-
{
|
|
401
|
+
{m.enterprise_permissions_empty()}
|
|
404
402
|
</div>
|
|
405
403
|
) : (
|
|
406
404
|
<div className="rounded-lg border border-border overflow-hidden">
|
|
407
405
|
<Table>
|
|
408
406
|
<TableHeader>
|
|
409
407
|
<TableRow>
|
|
410
|
-
<TableHead>{
|
|
411
|
-
<TableHead>{
|
|
412
|
-
<TableHead>{
|
|
413
|
-
<TableHead>{
|
|
414
|
-
<TableHead>{
|
|
408
|
+
<TableHead>{m.enterprise_permissions_table_role()}</TableHead>
|
|
409
|
+
<TableHead>{m.enterprise_permissions_table_type()}</TableHead>
|
|
410
|
+
<TableHead>{m.enterprise_permissions_table_members()}</TableHead>
|
|
411
|
+
<TableHead>{m.enterprise_permissions_table_permissions()}</TableHead>
|
|
412
|
+
<TableHead>{m.enterprise_permissions_table_actions()}</TableHead>
|
|
415
413
|
</TableRow>
|
|
416
414
|
</TableHeader>
|
|
417
415
|
<TableBody>
|
|
@@ -420,7 +418,7 @@ function PermissionsPage(): React.ReactElement {
|
|
|
420
418
|
<TableCell className="font-medium">{role.name}</TableCell>
|
|
421
419
|
<TableCell>
|
|
422
420
|
<Badge variant={role.isSystem ? 'default' : 'secondary'}>
|
|
423
|
-
{role.isSystem ?
|
|
421
|
+
{role.isSystem ? m.enterprise_permissions_type_system() : m.enterprise_permissions_type_custom()}
|
|
424
422
|
</Badge>
|
|
425
423
|
</TableCell>
|
|
426
424
|
<TableCell>{role._count?.assignments}</TableCell>
|
|
@@ -443,7 +441,7 @@ function PermissionsPage(): React.ReactElement {
|
|
|
443
441
|
className="text-primary hover:underline text-sm"
|
|
444
442
|
onClick={() => handleOpenAssign(role)}
|
|
445
443
|
>
|
|
446
|
-
{
|
|
444
|
+
{m.enterprise_permissions_action_viewAssignments()}
|
|
447
445
|
</button>
|
|
448
446
|
<button
|
|
449
447
|
type="button"
|
|
@@ -451,7 +449,7 @@ function PermissionsPage(): React.ReactElement {
|
|
|
451
449
|
onClick={() => handleDelete(role)}
|
|
452
450
|
disabled={role.isSystem}
|
|
453
451
|
>
|
|
454
|
-
{role.isSystem ?
|
|
452
|
+
{role.isSystem ? m.enterprise_permissions_action_notAvailable() : m.enterprise_permissions_action_delete()}
|
|
455
453
|
</button>
|
|
456
454
|
</div>
|
|
457
455
|
</TableCell>
|
|
@@ -464,7 +462,7 @@ function PermissionsPage(): React.ReactElement {
|
|
|
464
462
|
|
|
465
463
|
{selectedWorkspaceId && (
|
|
466
464
|
<div className="flex justify-end">
|
|
467
|
-
<Button onClick={() => setCreateDialogOpen(true)}>{
|
|
465
|
+
<Button onClick={() => setCreateDialogOpen(true)}>{m.enterprise_permissions_action_createRole()}</Button>
|
|
468
466
|
</div>
|
|
469
467
|
)}
|
|
470
468
|
|
|
@@ -472,11 +470,11 @@ function PermissionsPage(): React.ReactElement {
|
|
|
472
470
|
open={createDialogOpen}
|
|
473
471
|
onOpenChange={setCreateDialogOpen}
|
|
474
472
|
workspaceId={selectedWorkspaceId}
|
|
475
|
-
i18nLang={
|
|
473
|
+
i18nLang={getLocale()}
|
|
476
474
|
onCreated={() => {
|
|
477
475
|
if (selectedWorkspaceId) {
|
|
478
476
|
listRoles({ data: { workspaceId: selectedWorkspaceId } })
|
|
479
|
-
.then((result) => {
|
|
477
|
+
.then((result: any) => {
|
|
480
478
|
const data = result as { items: RoleItem[] }
|
|
481
479
|
setRoles(data.items)
|
|
482
480
|
})
|
|
@@ -488,11 +486,11 @@ function PermissionsPage(): React.ReactElement {
|
|
|
488
486
|
open={assignDialogOpen}
|
|
489
487
|
onOpenChange={setAssignDialogOpen}
|
|
490
488
|
role={selectedRole}
|
|
491
|
-
i18nLang={
|
|
489
|
+
i18nLang={getLocale()}
|
|
492
490
|
onAssigned={() => {
|
|
493
491
|
if (selectedWorkspaceId) {
|
|
494
492
|
listRoles({ data: { workspaceId: selectedWorkspaceId } })
|
|
495
|
-
.then((result) => {
|
|
493
|
+
.then((result: any) => {
|
|
496
494
|
const data = result as { items: RoleItem[] }
|
|
497
495
|
setRoles(data.items)
|
|
498
496
|
})
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import {
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
20
20
|
import { Settings } from 'lucide-react'
|
|
21
21
|
import { PlaceholderPage } from '@/components/common/placeholder-page'
|
|
22
22
|
|
|
@@ -25,6 +25,5 @@ export const Route = createLazyFileRoute('/_nav/settings')({
|
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
function SettingsPage() {
|
|
28
|
-
|
|
29
|
-
return <PlaceholderPage title={t('settings.title')} icon={Settings} />
|
|
28
|
+
return <PlaceholderPage title={m.common_settings_title()} icon={Settings} />
|
|
30
29
|
}
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
19
20
|
import { useServerFn } from '@tanstack/react-start'
|
|
20
|
-
import { useTranslation } from 'react-i18next'
|
|
21
21
|
import { toast } from 'sonner'
|
|
22
22
|
import type React from 'react'
|
|
23
23
|
import { deleteSsoProviderFn, toggleSsoProviderFn } from '@/server/serverFns/sso-config'
|
|
@@ -33,7 +33,6 @@ export const Route = createLazyFileRoute('/_nav/sso')({
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
function SsoConfigPage(): React.ReactElement {
|
|
36
|
-
const { t } = useTranslation('enterprise')
|
|
37
36
|
const { items, total } = Route.useLoaderData() as {
|
|
38
37
|
items: Array<{
|
|
39
38
|
id: string
|
|
@@ -55,13 +54,16 @@ function SsoConfigPage(): React.ReactElement {
|
|
|
55
54
|
|
|
56
55
|
const handleToggle = async (provider: typeof items[0]) => {
|
|
57
56
|
await toggleFn({ data: { providerId: provider.id, enabled: !provider.enabled } })
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
if (!provider.enabled) {
|
|
58
|
+
toast.success(m.enterprise_sso_toastEnabled({ name: provider.name }))
|
|
59
|
+
} else {
|
|
60
|
+
toast.success(m.enterprise_sso_toastDisabled({ name: provider.name }))
|
|
61
|
+
}
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
const handleDelete = async (provider: typeof items[0]) => {
|
|
63
65
|
await deleteFn({ data: { providerId: provider.id } })
|
|
64
|
-
toast.success(
|
|
66
|
+
toast.success(m.enterprise_sso_toastDeleted({ name: provider.name }))
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
const TYPE_LABELS: Record<string, string> = {
|
|
@@ -75,26 +77,26 @@ function SsoConfigPage(): React.ReactElement {
|
|
|
75
77
|
return (
|
|
76
78
|
<div className="space-y-4">
|
|
77
79
|
<div>
|
|
78
|
-
<h1 className="text-2xl font-bold">{
|
|
79
|
-
<p className="text-sm text-muted-foreground mt-1">{
|
|
80
|
+
<h1 className="text-2xl font-bold">{m.enterprise_sso_title()}</h1>
|
|
81
|
+
<p className="text-sm text-muted-foreground mt-1">{m.enterprise_sso_subtitle({ count: total })}</p>
|
|
80
82
|
</div>
|
|
81
83
|
|
|
82
84
|
{items.length === 0 ? (
|
|
83
85
|
<div className="rounded-lg border border-border p-8 text-center text-muted-foreground">
|
|
84
|
-
{
|
|
86
|
+
{m.enterprise_sso_empty()}
|
|
85
87
|
</div>
|
|
86
88
|
) : (
|
|
87
89
|
<div className="rounded-lg border border-border overflow-hidden">
|
|
88
90
|
<table className="w-full text-sm">
|
|
89
91
|
<thead>
|
|
90
92
|
<tr className="border-b border-border bg-muted/50">
|
|
91
|
-
<th className="p-3 text-left font-medium">{
|
|
92
|
-
<th className="p-3 text-left font-medium">{
|
|
93
|
-
<th className="p-3 text-left font-medium">{
|
|
94
|
-
<th className="p-3 text-left font-medium">{
|
|
95
|
-
<th className="p-3 text-left font-medium">{
|
|
96
|
-
<th className="p-3 text-left font-medium">{
|
|
97
|
-
<th className="p-3 text-left font-medium">{
|
|
93
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_provider()}</th>
|
|
94
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_type()}</th>
|
|
95
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_domain()}</th>
|
|
96
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_workspace()}</th>
|
|
97
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_mappings()}</th>
|
|
98
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_statusLabel()}</th>
|
|
99
|
+
<th className="p-3 text-left font-medium">{m.enterprise_sso_actions()}</th>
|
|
98
100
|
</tr>
|
|
99
101
|
</thead>
|
|
100
102
|
<tbody>
|
|
@@ -115,7 +117,7 @@ function SsoConfigPage(): React.ReactElement {
|
|
|
115
117
|
: 'bg-muted text-muted-foreground'
|
|
116
118
|
}`}
|
|
117
119
|
>
|
|
118
|
-
{provider.enabled ?
|
|
120
|
+
{provider.enabled ? m.enterprise_sso_enabled() : m.enterprise_sso_disabled()}
|
|
119
121
|
</span>
|
|
120
122
|
</td>
|
|
121
123
|
<td className="p-3 flex items-center gap-2">
|
|
@@ -124,14 +126,14 @@ function SsoConfigPage(): React.ReactElement {
|
|
|
124
126
|
className="text-primary hover:underline"
|
|
125
127
|
onClick={() => handleToggle(provider)}
|
|
126
128
|
>
|
|
127
|
-
{provider.enabled ?
|
|
129
|
+
{provider.enabled ? m.enterprise_sso_actionDisable() : m.enterprise_sso_actionEnable()}
|
|
128
130
|
</button>
|
|
129
131
|
<button
|
|
130
132
|
type="button"
|
|
131
133
|
className="text-destructive hover:underline"
|
|
132
134
|
onClick={() => handleDelete(provider)}
|
|
133
135
|
>
|
|
134
|
-
{
|
|
136
|
+
{m.enterprise_sso_actionDelete()}
|
|
135
137
|
</button>
|
|
136
138
|
</td>
|
|
137
139
|
</tr>
|