@svadmin/ui 0.38.1 → 0.38.5
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/app.css +10 -5
- package/dist/app.theme.css +1374 -0
- package/dist/components/AICommandBar.svelte +16 -15
- package/dist/components/AboutSettings.svelte +12 -11
- package/dist/components/AdminApp.svelte +144 -70
- package/dist/components/AdminApp.svelte.d.ts +6 -3
- package/dist/components/ApiSettings.svelte +19 -16
- package/dist/components/AppearanceSettings.svelte +18 -16
- package/dist/components/AuditLogDrawer.svelte +6 -3
- package/dist/components/AuditLogViewer.svelte +18 -15
- package/dist/components/Authenticated.svelte +4 -4
- package/dist/components/AutoForm.svelte +19 -16
- package/dist/components/AutoSaveIndicator.svelte +7 -5
- package/dist/components/AutoTable.svelte +85 -71
- package/dist/components/AutoTable.svelte.d.ts +1 -1
- package/dist/components/Breadcrumbs.svelte +17 -13
- package/dist/components/CancelTaskButton.svelte +5 -2
- package/dist/components/CatchAllNavigate.svelte +3 -3
- package/dist/components/ChatDialog.svelte +22 -19
- package/dist/components/ComboboxField.svelte +6 -4
- package/dist/components/CommandPalette.svelte +20 -20
- package/dist/components/ConfigErrorScreen.svelte +12 -10
- package/dist/components/ConfirmDialog.svelte +6 -4
- package/dist/components/CreatePage.svelte +4 -2
- package/dist/components/DevTools.svelte +11 -9
- package/dist/components/DrawerForm.svelte +5 -2
- package/dist/components/EditPage.svelte +8 -5
- package/dist/components/EmptyState.svelte +5 -3
- package/dist/components/ErrorBoundary.svelte +5 -3
- package/dist/components/ErrorComponent.svelte +6 -4
- package/dist/components/ErrorPage.svelte +12 -10
- package/dist/components/FieldRenderer.svelte +17 -15
- package/dist/components/ForgotPasswordPage.svelte +22 -19
- package/dist/components/Header.svelte +7 -4
- package/dist/components/InfiniteList.svelte +6 -3
- package/dist/components/IntegrationsSettings.svelte +9 -6
- package/dist/components/KeyboardShortcuts.svelte +4 -2
- package/dist/components/Layout.svelte +12 -13
- package/dist/components/LazyPage.svelte +47 -0
- package/dist/components/LazyPage.svelte.d.ts +14 -0
- package/dist/components/ListPage.svelte +8 -5
- package/dist/components/LoginPage.svelte +24 -22
- package/dist/components/MarkdownRenderer.svelte +89 -35
- package/dist/components/ModalForm.svelte +4 -2
- package/dist/components/NavigateToResource.svelte +3 -3
- package/dist/components/NotificationsSettings.svelte +26 -24
- package/dist/components/PasswordInput.svelte +4 -2
- package/dist/components/PermissionMatrix.svelte +15 -12
- package/dist/components/ProfilePage.svelte +23 -21
- package/dist/components/RegisterPage.svelte +21 -19
- package/dist/components/ResourceOperationsPage.svelte +3 -2
- package/dist/components/RetryTaskButton.svelte +5 -2
- package/dist/components/RolesSettings.svelte +10 -8
- package/dist/components/SecuritySettings.svelte +26 -23
- package/dist/components/SettingsPage.svelte +14 -11
- package/dist/components/ShowPage.svelte +9 -7
- package/dist/components/Sidebar.svelte +36 -28
- package/dist/components/SidebarItem.svelte +4 -4
- package/dist/components/SidebarItem.svelte.d.ts +1 -1
- package/dist/components/StepsForm.svelte +11 -8
- package/dist/components/TaskDetails.svelte +14 -11
- package/dist/components/TaskList.svelte +14 -11
- package/dist/components/TaskQueueDrawer.svelte +34 -32
- package/dist/components/TaskStatusBadge.svelte +5 -2
- package/dist/components/Toast.svelte +18 -4
- package/dist/components/TooltipButton.svelte +25 -3
- package/dist/components/TwoFactorAuthPage.svelte +26 -24
- package/dist/components/UndoableNotification.svelte +5 -2
- package/dist/components/UpdatePasswordPage.svelte +18 -15
- package/dist/components/VirtualTable.svelte +0 -4
- package/dist/components/account/CompanyProfilePage.svelte +13 -11
- package/dist/components/account/GetStartedPage.svelte +15 -13
- package/dist/components/account/ImportMembersPage.svelte +14 -12
- package/dist/components/account/MembersStarterPage.svelte +10 -8
- package/dist/components/account/SecurityLogPage.svelte +24 -22
- package/dist/components/account/SettingsEnterprisePage.svelte +6 -4
- package/dist/components/account/SettingsPlainPage.svelte +14 -12
- package/dist/components/account/SettingsSidebarPage.svelte +11 -9
- package/dist/components/account/TeamMembersPage.svelte +10 -8
- package/dist/components/buttons/CloneButton.svelte +4 -2
- package/dist/components/buttons/CreateButton.svelte +4 -2
- package/dist/components/buttons/DeleteButton.svelte +6 -4
- package/dist/components/buttons/EditButton.svelte +4 -2
- package/dist/components/buttons/ExportButton.svelte +4 -2
- package/dist/components/buttons/ImportButton.svelte +4 -2
- package/dist/components/buttons/RefreshButton.svelte +4 -2
- package/dist/components/buttons/SaveButton.svelte +4 -2
- package/dist/components/buttons/ShowButton.svelte +4 -2
- package/dist/components/fieldComponentMap.js +0 -3
- package/dist/components/fields/ArrayField.svelte +6 -4
- package/dist/components/fields/JsonField.svelte +5 -3
- package/dist/components/fields/RelationField.svelte +3 -3
- package/dist/components/fields/RichTextField.svelte +4 -2
- package/dist/components/network/TeamCrewTablePage.svelte +18 -16
- package/dist/components/network/UserCardsNFTPage.svelte +11 -9
- package/dist/components/profile/ActivityTimeline.svelte +10 -8
- package/dist/components/profile/ProfileCard.svelte +13 -11
- package/dist/components/profile/ProjectsGrid.svelte +7 -5
- package/dist/components/profile/PublicProfilePage.svelte +18 -16
- package/dist/components/profile/TeamsShowcase.svelte +7 -5
- package/dist/components/toast-host.svelte.d.ts +5 -0
- package/dist/components/toast-host.svelte.js +21 -0
- package/dist/components/ui/command/command-dialog.svelte +29 -13
- package/dist/components/ui/command/command-dialog.svelte.d.ts +4 -3
- package/dist/components/ui/command/command-empty.svelte +18 -0
- package/dist/components/ui/command/command-empty.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-group.svelte +41 -0
- package/dist/components/ui/command/command-group.svelte.d.ts +8 -0
- package/dist/components/ui/command/command-input.svelte +23 -0
- package/dist/components/ui/command/command-input.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-item.svelte +43 -0
- package/dist/components/ui/command/command-item.svelte.d.ts +11 -0
- package/dist/components/ui/command/command-list.svelte +18 -0
- package/dist/components/ui/command/command-list.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-loading.svelte +12 -0
- package/dist/components/ui/command/command-loading.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-separator.svelte +23 -0
- package/dist/components/ui/command/command-separator.svelte.d.ts +7 -0
- package/dist/components/ui/command/command.svelte +26 -0
- package/dist/components/ui/command/command.svelte.d.ts +4 -0
- package/dist/components/ui/command/index.d.ts +55 -2
- package/dist/components/ui/command/index.js +21 -2
- package/dist/components/ui/sheet/sheet-content.svelte +1 -4
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +1 -3
- package/dist/components/ui/tabs/tabs-content.svelte +6 -2
- package/dist/components/ui/tabs/tabs-context.svelte.d.ts +5 -0
- package/dist/components/ui/tabs/tabs-context.svelte.js +2 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +49 -4
- package/dist/components/ui/tabs/tabs.svelte +12 -1
- package/dist/components/ui/tooltip/index.d.ts +4 -1
- package/dist/components/ui/tooltip/index.js +3 -1
- package/dist/components/ui/tooltip/tooltip-content.svelte +308 -35
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +42 -3
- package/dist/components/ui/tooltip/tooltip-context.svelte.d.ts +37 -0
- package/dist/components/ui/tooltip/tooltip-context.svelte.js +220 -0
- package/dist/components/ui/tooltip/tooltip-layer-registry.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-layer-registry.svelte.js +93 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +56 -3
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +23 -2
- package/dist/components/ui/tooltip/tooltip.svelte +63 -3
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +23 -2
- package/dist/router-state.svelte.d.ts +13 -0
- package/dist/router-state.svelte.js +72 -37
- package/package.json +18 -12
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { getResources, getChatProvider } from '@svadmin/core';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { toggleTheme } from '@svadmin/core';
|
|
6
|
-
import { Command } from 'cmdk-sv';
|
|
2
|
+
import { captureAdminContext, getResources, getChatProvider, toggleTheme } from '@svadmin/core';
|
|
3
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
|
+
import { Command } from './ui/command/index.js';
|
|
7
5
|
import * as Dialog from './ui/dialog/index.js';
|
|
8
6
|
import { Search, LayoutDashboard, Plus, Sun, FileText, Sparkles, Loader2 } from '@lucide/svelte';
|
|
9
7
|
import MarkdownRenderer from './MarkdownRenderer.svelte';
|
|
10
8
|
|
|
9
|
+
const i18n = useTranslation();
|
|
10
|
+
|
|
11
11
|
let { open = $bindable(false) } = $props<{ open?: boolean }>();
|
|
12
|
+
const adminContext = captureAdminContext();
|
|
12
13
|
let searchValue = $state('');
|
|
13
14
|
|
|
14
15
|
const resources = getResources();
|
|
@@ -80,14 +81,14 @@
|
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
const itemClass = 'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected
|
|
84
|
+
const itemClass = 'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[selected]:bg-accent data-[selected]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50';
|
|
84
85
|
</script>
|
|
85
86
|
|
|
86
87
|
<Dialog.Dialog bind:open onOpenChange={(v: boolean) => !v && close()}>
|
|
87
88
|
<Dialog.DialogContent class="overflow-hidden p-0 sm:max-w-[600px] border-none shadow-2xl">
|
|
88
89
|
<Command.Root
|
|
89
90
|
shouldFilter={!aiMode}
|
|
90
|
-
class="flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground [&_[data-
|
|
91
|
+
class="flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground [&_[data-command-group-heading]]:text-muted-foreground [&_[data-command-group-heading]]:px-2 [&_[data-command-group-heading]]:py-1.5 [&_[data-command-group-heading]]:text-xs [&_[data-command-group-heading]]:font-semibold [&_[data-command-group-heading]]:uppercase [&_[data-command-group-heading]]:tracking-wider"
|
|
91
92
|
>
|
|
92
93
|
<div class="flex items-center border-b px-3 h-12 relative" data-cmdk-input-wrapper="">
|
|
93
94
|
{#if aiMode}
|
|
@@ -119,13 +120,13 @@
|
|
|
119
120
|
</Command.Empty>
|
|
120
121
|
|
|
121
122
|
<!-- Navigation -->
|
|
122
|
-
<Command.Group heading={t('common.home')}>
|
|
123
|
-
<Command.Item value="home" onSelect={() => act(() => navigate('/'))} class={itemClass}>
|
|
123
|
+
<Command.Group heading={i18n.t('common.home')}>
|
|
124
|
+
<Command.Item value="home" onSelect={() => act(() => adminContext.navigate('/'))} class={itemClass}>
|
|
124
125
|
<LayoutDashboard class="h-4 w-4 text-muted-foreground" />
|
|
125
|
-
{t('common.home')}
|
|
126
|
+
{i18n.t('common.home')}
|
|
126
127
|
</Command.Item>
|
|
127
128
|
{#each resources as r, _i (_i)}
|
|
128
|
-
<Command.Item value={r.name} onSelect={() => act(() => navigate(`/${r.name}`))} class={itemClass}>
|
|
129
|
+
<Command.Item value={r.name} onSelect={() => act(() => adminContext.navigate(`/${r.name}`))} class={itemClass}>
|
|
129
130
|
<FileText class="h-4 w-4 text-muted-foreground" />
|
|
130
131
|
{r.label}
|
|
131
132
|
</Command.Item>
|
|
@@ -135,16 +136,16 @@
|
|
|
135
136
|
<Command.Separator class="mx-1 my-1 h-px bg-border" />
|
|
136
137
|
|
|
137
138
|
<!-- Actions -->
|
|
138
|
-
<Command.Group heading={t('common.actions')}>
|
|
139
|
+
<Command.Group heading={i18n.t('common.actions')}>
|
|
139
140
|
{#each resources as r, _i (_i)}
|
|
140
|
-
<Command.Item value={`create-${r.name}`} onSelect={() => act(() => navigate(`/${r.name}/create`))} class={itemClass}>
|
|
141
|
+
<Command.Item value={`create-${r.name}`} onSelect={() => act(() => adminContext.navigate(`/${r.name}/create`))} class={itemClass}>
|
|
141
142
|
<Plus class="h-4 w-4 text-muted-foreground" />
|
|
142
|
-
{t('common.create')} {r.label}
|
|
143
|
+
{i18n.t('common.create')} {r.label}
|
|
143
144
|
</Command.Item>
|
|
144
145
|
{/each}
|
|
145
146
|
<Command.Item value="toggle-theme" onSelect={() => act(() => toggleTheme())} class={itemClass}>
|
|
146
147
|
<Sun class="h-4 w-4 text-muted-foreground" />
|
|
147
|
-
{t('common.toggleTheme')}
|
|
148
|
+
{i18n.t('common.toggleTheme')}
|
|
148
149
|
</Command.Item>
|
|
149
150
|
</Command.Group>
|
|
150
151
|
</Command.List>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
3
|
import { getResources, getDataProviderNames } from '@svadmin/core';
|
|
4
|
-
import { getLocale } from '@svadmin/core/i18n';
|
|
5
4
|
import { getResolvedTheme, getColorTheme } from '@svadmin/core';
|
|
6
5
|
import * as Card from './ui/card/index.js';
|
|
7
6
|
import { Badge } from './ui/badge/index.js';
|
|
8
7
|
import { Info, Database, Globe, Palette, Layers } from '@lucide/svelte';
|
|
9
8
|
|
|
9
|
+
const i18n = useTranslation();
|
|
10
|
+
|
|
10
11
|
const resources = getResources();
|
|
11
12
|
const providerNames = getDataProviderNames();
|
|
12
13
|
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
|
|
16
17
|
<div class="space-y-6">
|
|
17
18
|
<div>
|
|
18
|
-
<h2 class="text-xl font-semibold text-foreground">{t('settings.about')}</h2>
|
|
19
|
+
<h2 class="text-xl font-semibold text-foreground">{i18n.t('settings.about')}</h2>
|
|
19
20
|
</div>
|
|
20
21
|
|
|
21
22
|
<!-- Version -->
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
<Card.CardContent>
|
|
30
31
|
<div class="grid gap-4 text-sm">
|
|
31
32
|
<div class="flex items-center justify-between">
|
|
32
|
-
<span class="text-muted-foreground">{t('settings.version')}</span>
|
|
33
|
+
<span class="text-muted-foreground">{i18n.t('settings.version')}</span>
|
|
33
34
|
<Badge variant="secondary" class="font-mono text-xs">{version}</Badge>
|
|
34
35
|
</div>
|
|
35
36
|
</div>
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
<Card.CardHeader class="pb-3">
|
|
42
43
|
<Card.CardTitle class="text-base flex items-center gap-2">
|
|
43
44
|
<Layers class="h-4 w-4 text-muted-foreground" />
|
|
44
|
-
{t('settings.registeredResources')}
|
|
45
|
+
{i18n.t('settings.registeredResources')}
|
|
45
46
|
</Card.CardTitle>
|
|
46
47
|
</Card.CardHeader>
|
|
47
48
|
<Card.CardContent>
|
|
@@ -61,7 +62,7 @@
|
|
|
61
62
|
<Card.CardHeader class="pb-3">
|
|
62
63
|
<Card.CardTitle class="text-base flex items-center gap-2">
|
|
63
64
|
<Database class="h-4 w-4 text-muted-foreground" />
|
|
64
|
-
{t('settings.dataProvider')}
|
|
65
|
+
{i18n.t('settings.dataProvider')}
|
|
65
66
|
</Card.CardTitle>
|
|
66
67
|
</Card.CardHeader>
|
|
67
68
|
<Card.CardContent>
|
|
@@ -78,25 +79,25 @@
|
|
|
78
79
|
<Card.CardHeader class="pb-3">
|
|
79
80
|
<Card.CardTitle class="text-base flex items-center gap-2">
|
|
80
81
|
<Globe class="h-4 w-4 text-muted-foreground" />
|
|
81
|
-
{t('settings.currentEnvironment')}
|
|
82
|
+
{i18n.t('settings.currentEnvironment')}
|
|
82
83
|
</Card.CardTitle>
|
|
83
84
|
</Card.CardHeader>
|
|
84
85
|
<Card.CardContent>
|
|
85
86
|
<div class="grid gap-3 text-sm">
|
|
86
87
|
<div class="flex items-center justify-between">
|
|
87
|
-
<span class="text-muted-foreground">{t('settings.language')}</span>
|
|
88
|
-
<span class="font-mono text-xs">{
|
|
88
|
+
<span class="text-muted-foreground">{i18n.t('settings.language')}</span>
|
|
89
|
+
<span class="font-mono text-xs">{i18n.locale}</span>
|
|
89
90
|
</div>
|
|
90
91
|
<div class="h-px bg-border"></div>
|
|
91
92
|
<div class="flex items-center justify-between">
|
|
92
|
-
<span class="text-muted-foreground">{t('settings.themeMode')}</span>
|
|
93
|
+
<span class="text-muted-foreground">{i18n.t('settings.themeMode')}</span>
|
|
93
94
|
<span class="font-mono text-xs">{getResolvedTheme()}</span>
|
|
94
95
|
</div>
|
|
95
96
|
<div class="h-px bg-border"></div>
|
|
96
97
|
<div class="flex items-center justify-between">
|
|
97
98
|
<span class="text-muted-foreground flex items-center gap-1.5">
|
|
98
99
|
<Palette class="h-3.5 w-3.5" />
|
|
99
|
-
{t('settings.colorAccent')}
|
|
100
|
+
{i18n.t('settings.colorAccent')}
|
|
100
101
|
</span>
|
|
101
102
|
<span class="font-mono text-xs">{getColorTheme()}</span>
|
|
102
103
|
</div>
|
|
@@ -1,11 +1,35 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
const loadPublicProfilePage = () => import('./profile/PublicProfilePage.svelte');
|
|
3
|
+
const loadGetStartedPage = () => import('./account/GetStartedPage.svelte');
|
|
4
|
+
const loadCompanyProfilePage = () => import('./account/CompanyProfilePage.svelte');
|
|
5
|
+
const loadSettingsPlainPage = () => import('./account/SettingsPlainPage.svelte');
|
|
6
|
+
const loadSettingsSidebarPage = () => import('./account/SettingsSidebarPage.svelte');
|
|
7
|
+
const loadSettingsEnterprisePage = () => import('./account/SettingsEnterprisePage.svelte');
|
|
8
|
+
const loadImportMembersPage = () => import('./account/ImportMembersPage.svelte');
|
|
9
|
+
const loadMembersStarterPage = () => import('./account/MembersStarterPage.svelte');
|
|
10
|
+
const loadTeamMembersPage = () => import('./account/TeamMembersPage.svelte');
|
|
11
|
+
const loadSecurityLogPage = () => import('./account/SecurityLogPage.svelte');
|
|
12
|
+
const loadUserCardsNFTPage = () => import('./network/UserCardsNFTPage.svelte');
|
|
13
|
+
const loadTeamCrewTablePage = () => import('./network/TeamCrewTablePage.svelte');
|
|
14
|
+
const loadTwoFactorAuthPage = () => import('./TwoFactorAuthPage.svelte');
|
|
15
|
+
</script>
|
|
16
|
+
|
|
1
17
|
<script lang="ts">
|
|
2
18
|
// Auto-inject design tokens so consumers don't need to manually import
|
|
3
19
|
import '../app.css';
|
|
4
|
-
import type
|
|
5
|
-
import type { DataProvider, AuthProvider, ResourceDefinition, ThemeMode, RouterProvider, ThemeConfig, MenuItem, TaskProvider } from '@svadmin/core';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
20
|
+
import { onDestroy, onMount, untrack, type Component, type Snippet } from 'svelte';
|
|
21
|
+
import type { DataProvider, AuthProvider, ResourceDefinition, ThemeMode, RouterProvider, ThemeConfig, MenuItem, TaskProvider, I18nProvider } from '@svadmin/core';
|
|
22
|
+
import {
|
|
23
|
+
captureAdminContext,
|
|
24
|
+
createHashRouterProvider,
|
|
25
|
+
createI18nScope,
|
|
26
|
+
provideAdminContext,
|
|
27
|
+
provideI18nScope,
|
|
28
|
+
registerThemeOwner,
|
|
29
|
+
unregisterThemeOwner,
|
|
30
|
+
updateThemeOwner,
|
|
31
|
+
} from '@svadmin/core';
|
|
32
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
9
33
|
import { QueryClient, QueryClientProvider, type DefaultOptions } from '@tanstack/svelte-query';
|
|
10
34
|
import { setComponentRegistry, type ComponentRegistry } from '../component-registry.svelte.js';
|
|
11
35
|
import Layout from './Layout.svelte';
|
|
@@ -24,24 +48,12 @@
|
|
|
24
48
|
import TaskQueueDrawer from './TaskQueueDrawer.svelte';
|
|
25
49
|
import SettingsPage from './SettingsPage.svelte';
|
|
26
50
|
import ErrorPage from './ErrorPage.svelte';
|
|
27
|
-
import
|
|
28
|
-
import GetStartedPage from './account/GetStartedPage.svelte';
|
|
29
|
-
import CompanyProfilePage from './account/CompanyProfilePage.svelte';
|
|
30
|
-
import SettingsPlainPage from './account/SettingsPlainPage.svelte';
|
|
31
|
-
import SettingsSidebarPage from './account/SettingsSidebarPage.svelte';
|
|
32
|
-
import SettingsEnterprisePage from './account/SettingsEnterprisePage.svelte';
|
|
33
|
-
import ImportMembersPage from './account/ImportMembersPage.svelte';
|
|
34
|
-
import MembersStarterPage from './account/MembersStarterPage.svelte';
|
|
35
|
-
import TeamMembersPage from './account/TeamMembersPage.svelte';
|
|
36
|
-
import SecurityLogPage from './account/SecurityLogPage.svelte';
|
|
37
|
-
import UserCardsNFTPage from './network/UserCardsNFTPage.svelte';
|
|
38
|
-
import TeamCrewTablePage from './network/TeamCrewTablePage.svelte';
|
|
39
|
-
import TwoFactorAuthPage from './TwoFactorAuthPage.svelte';
|
|
51
|
+
import LazyPage from './LazyPage.svelte';
|
|
40
52
|
import { Button } from './ui/button/index.js';
|
|
41
53
|
import { Input } from './ui/input/index.js';
|
|
42
54
|
import { Badge } from './ui/badge/index.js';
|
|
43
55
|
import { Skeleton } from './ui/skeleton/index.js';
|
|
44
|
-
import {
|
|
56
|
+
import { provideRouterState } from '../router-state.svelte.js';
|
|
45
57
|
|
|
46
58
|
interface Props {
|
|
47
59
|
dataProvider: DataProvider;
|
|
@@ -49,7 +61,10 @@
|
|
|
49
61
|
taskProvider?: TaskProvider;
|
|
50
62
|
routerProvider?: RouterProvider;
|
|
51
63
|
resources: ResourceDefinition[];
|
|
64
|
+
/** Bindable tree-local locale; defaults to the provider locale or per-tree browser detection (English during SSR). */
|
|
52
65
|
locale?: string;
|
|
66
|
+
/** Optional tree-local translation provider. */
|
|
67
|
+
i18nProvider?: I18nProvider;
|
|
53
68
|
title?: string;
|
|
54
69
|
defaultTheme?: ThemeMode;
|
|
55
70
|
/** Theme configuration for dark-first mode, CSS overrides, etc. */
|
|
@@ -90,7 +105,8 @@
|
|
|
90
105
|
taskProvider,
|
|
91
106
|
routerProvider,
|
|
92
107
|
resources,
|
|
93
|
-
locale,
|
|
108
|
+
locale = $bindable(),
|
|
109
|
+
i18nProvider,
|
|
94
110
|
title = 'Admin',
|
|
95
111
|
defaultTheme,
|
|
96
112
|
themeConfig: userThemeConfig,
|
|
@@ -122,28 +138,89 @@
|
|
|
122
138
|
const resolvedRouter = $derived(routerProvider ?? createHashRouterProvider());
|
|
123
139
|
const resolvedRouteMode = $derived(routeMode ?? (routerProvider ? 'auto' : 'hash'));
|
|
124
140
|
|
|
141
|
+
const routerState = provideRouterState(untrack(() => resolvedRouter));
|
|
142
|
+
const scopedRouterProvider: RouterProvider = {
|
|
143
|
+
go(options) {
|
|
144
|
+
resolvedRouter.go(options);
|
|
145
|
+
routerState.sync();
|
|
146
|
+
},
|
|
147
|
+
back() {
|
|
148
|
+
resolvedRouter.back();
|
|
149
|
+
routerState.sync();
|
|
150
|
+
},
|
|
151
|
+
parse() {
|
|
152
|
+
return resolvedRouter.parse();
|
|
153
|
+
},
|
|
154
|
+
formatLink(path) {
|
|
155
|
+
return resolvedRouter.formatLink?.(path) ?? `#${path.replace(/^#/, '')}`;
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
$effect.pre(() => routerState.init(resolvedRouter));
|
|
160
|
+
onDestroy(() => routerState.destroy());
|
|
161
|
+
|
|
162
|
+
function updateBoundLocale(nextLocale: string) {
|
|
163
|
+
locale = nextLocale;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const i18nScope = createI18nScope({
|
|
167
|
+
locale: untrack(() => locale),
|
|
168
|
+
provider: untrack(() => i18nProvider),
|
|
169
|
+
onLocaleChange: updateBoundLocale,
|
|
170
|
+
});
|
|
171
|
+
provideI18nScope(i18nScope);
|
|
172
|
+
const translation = useTranslation();
|
|
173
|
+
|
|
174
|
+
$effect.pre(() => {
|
|
175
|
+
const ownerProvider = i18nProvider;
|
|
176
|
+
const ownerLocale = locale;
|
|
177
|
+
untrack(() => i18nScope.updateOwner({
|
|
178
|
+
locale: ownerLocale,
|
|
179
|
+
provider: ownerProvider,
|
|
180
|
+
onLocaleChange: updateBoundLocale,
|
|
181
|
+
}));
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
let themeOwner = $state.raw<ReturnType<typeof registerThemeOwner>>(undefined);
|
|
185
|
+
|
|
186
|
+
onMount(() => {
|
|
187
|
+
themeOwner = registerThemeOwner({
|
|
188
|
+
defaultTheme,
|
|
189
|
+
themeConfig: userThemeConfig,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return () => {
|
|
193
|
+
unregisterThemeOwner(themeOwner);
|
|
194
|
+
themeOwner = undefined;
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
$effect(() => {
|
|
199
|
+
const owner = themeOwner;
|
|
200
|
+
const ownerOptions = {
|
|
201
|
+
defaultTheme,
|
|
202
|
+
themeConfig: userThemeConfig,
|
|
203
|
+
};
|
|
204
|
+
untrack(() => updateThemeOwner(owner, ownerOptions));
|
|
205
|
+
});
|
|
206
|
+
|
|
125
207
|
function syncComponentRegistry() {
|
|
126
208
|
setComponentRegistry(mergedComponents);
|
|
127
209
|
}
|
|
128
210
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if (defaultTheme) setTheme(defaultTheme);
|
|
138
|
-
}
|
|
211
|
+
provideAdminContext({
|
|
212
|
+
get dataProvider() { return dataProvider; },
|
|
213
|
+
get authProvider() { return authProvider ?? null; },
|
|
214
|
+
get taskProvider() { return taskProvider; },
|
|
215
|
+
get resources() { return resources; },
|
|
216
|
+
get routerProvider() { return scopedRouterProvider; },
|
|
217
|
+
});
|
|
218
|
+
const adminContext = captureAdminContext();
|
|
139
219
|
|
|
140
|
-
//
|
|
220
|
+
// Context must be available synchronously to descendants during their first render.
|
|
141
221
|
syncComponentRegistry();
|
|
142
|
-
syncAppContext();
|
|
143
222
|
|
|
144
|
-
// Set up context — use $effect so prop changes are tracked
|
|
145
223
|
$effect.pre(syncComponentRegistry);
|
|
146
|
-
$effect.pre(syncAppContext);
|
|
147
224
|
|
|
148
225
|
const queryClient = $derived(providedQueryClient ?? new QueryClient({
|
|
149
226
|
defaultOptions: {
|
|
@@ -152,24 +229,20 @@
|
|
|
152
229
|
},
|
|
153
230
|
}));
|
|
154
231
|
|
|
155
|
-
function syncRouter() {
|
|
156
|
-
initRouter(resolvedRouter);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Initialize router with provider synchronously
|
|
160
|
-
syncRouter();
|
|
161
|
-
$effect.pre(syncRouter);
|
|
162
|
-
|
|
163
232
|
// Reactive getters for route state
|
|
164
|
-
const route = $derived(
|
|
165
|
-
const params = $derived(
|
|
233
|
+
const route = $derived(routerState.route);
|
|
234
|
+
const params = $derived(routerState.params);
|
|
166
235
|
const resourceNames = $derived(new Set(resources.map((resource) => resource.name)));
|
|
167
236
|
const hasRouteResource = $derived(!params.resource || resourceNames.has(params.resource));
|
|
168
237
|
const currentResourcePages = $derived(params.resource ? resourcePages?.[params.resource] : undefined);
|
|
169
238
|
|
|
170
239
|
// Auth check
|
|
171
|
-
let isAuthenticated = $state(
|
|
172
|
-
let authChecked = $state(
|
|
240
|
+
let isAuthenticated = $state(untrack(() => !authProvider));
|
|
241
|
+
let authChecked = $state(untrack(() => !authProvider));
|
|
242
|
+
|
|
243
|
+
async function navigateWithinApp(path: string) {
|
|
244
|
+
await adminContext.navigate(path);
|
|
245
|
+
}
|
|
173
246
|
|
|
174
247
|
$effect(() => {
|
|
175
248
|
let cancelled = false;
|
|
@@ -183,12 +256,13 @@
|
|
|
183
256
|
}
|
|
184
257
|
return;
|
|
185
258
|
}
|
|
259
|
+
authChecked = false;
|
|
186
260
|
authProvider.check().then(result => {
|
|
187
261
|
if (cancelled) return;
|
|
188
262
|
isAuthenticated = result.authenticated;
|
|
189
263
|
authChecked = true;
|
|
190
264
|
if (!result.authenticated && _route !== '/login' && _route !== '/register' && _route !== '/forgot-password' && _route !== '/update-password') {
|
|
191
|
-
|
|
265
|
+
void navigateWithinApp(result.redirectTo ?? '/login');
|
|
192
266
|
}
|
|
193
267
|
}).catch(err => {
|
|
194
268
|
if (cancelled) return;
|
|
@@ -196,7 +270,7 @@
|
|
|
196
270
|
isAuthenticated = false;
|
|
197
271
|
authChecked = true;
|
|
198
272
|
if (_route !== '/login' && _route !== '/register' && _route !== '/forgot-password' && _route !== '/update-password') {
|
|
199
|
-
|
|
273
|
+
void navigateWithinApp('/login');
|
|
200
274
|
}
|
|
201
275
|
});
|
|
202
276
|
|
|
@@ -220,7 +294,7 @@
|
|
|
220
294
|
defaultIdentifier={loginDefaults?.identifier}
|
|
221
295
|
defaultPassword={loginDefaults?.password}
|
|
222
296
|
loginHint={loginDefaults?.hint}
|
|
223
|
-
onSuccess={() => { isAuthenticated = true;
|
|
297
|
+
onSuccess={() => { isAuthenticated = true; void navigateWithinApp('/'); }}
|
|
224
298
|
/>
|
|
225
299
|
{:else if route === '/register' && authProvider?.register}
|
|
226
300
|
<RegisterPage {title} />
|
|
@@ -229,49 +303,49 @@
|
|
|
229
303
|
{:else if route === '/update-password' && authProvider?.updatePassword}
|
|
230
304
|
<UpdatePasswordPage {title} />
|
|
231
305
|
{:else if route === '/login' || route === '/register' || route === '/forgot-password' || route === '/update-password'}
|
|
232
|
-
<ConfigErrorScreen title="{title} — {t('common.configRequired')}" />
|
|
306
|
+
<ConfigErrorScreen title="{title} — {translation.t('common.configRequired')}" />
|
|
233
307
|
{:else if isAuthenticated || !authProvider}
|
|
234
308
|
<Layout {title} {menu} {siteUrl} routeMode={resolvedRouteMode}>
|
|
235
309
|
{#key route + (params.resource ?? '') + (params.id ?? '') + (params.variant ?? '') + (params.columns ?? '')}
|
|
236
310
|
<div class="svadmin-page-enter">
|
|
237
311
|
{#if route === '/2fa' || route === '/authentication/branded/2fa'}
|
|
238
|
-
<
|
|
312
|
+
<LazyPage loader={loadTwoFactorAuthPage} props={{}} />
|
|
239
313
|
{:else if route === '/public-profile'}
|
|
240
|
-
<
|
|
314
|
+
<LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'projects' }} />
|
|
241
315
|
{:else if route === '/public-profile/projects/:columns'}
|
|
242
|
-
<
|
|
316
|
+
<LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'projects', columns: params.columns?.includes('3') ? 3 : 2 }} />
|
|
243
317
|
{:else if route === '/public-profile/activity'}
|
|
244
|
-
<
|
|
318
|
+
<LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'activity' }} />
|
|
245
319
|
{:else if route === '/public-profile/teams'}
|
|
246
|
-
<
|
|
320
|
+
<LazyPage loader={loadPublicProfilePage} props={{ variant: 'default', initialTab: 'teams' }} />
|
|
247
321
|
{:else if route === '/public-profile/profiles/:variant'}
|
|
248
|
-
<
|
|
322
|
+
<LazyPage loader={loadPublicProfilePage} props={{ variant: (params.variant === 'company' || params.variant === 'gamer' || params.variant === 'default' ? params.variant : 'default') as 'company' | 'gamer' | 'default' }} />
|
|
249
323
|
{:else if route === '/account/get-started' || route === '/account/home/get-started'}
|
|
250
|
-
<
|
|
324
|
+
<LazyPage loader={loadGetStartedPage} props={{}} />
|
|
251
325
|
{:else if route === '/account/home/user-profile'}
|
|
252
326
|
<SettingsPage />
|
|
253
327
|
{:else if route === '/account/company-profile' || route === '/account/home/company-profile'}
|
|
254
|
-
<
|
|
328
|
+
<LazyPage loader={loadCompanyProfilePage} props={{}} />
|
|
255
329
|
{:else if route === '/account/settings-plain' || route === '/account/home/settings-plain'}
|
|
256
|
-
<
|
|
330
|
+
<LazyPage loader={loadSettingsPlainPage} props={{}} />
|
|
257
331
|
{:else if route === '/account/settings-sidebar' || route === '/account/home/settings-sidebar'}
|
|
258
|
-
<
|
|
332
|
+
<LazyPage loader={loadSettingsSidebarPage} props={{}} />
|
|
259
333
|
{:else if route === '/account/settings-enterprise' || route === '/account/home/settings-enterprise'}
|
|
260
|
-
<
|
|
334
|
+
<LazyPage loader={loadSettingsEnterprisePage} props={{}} />
|
|
261
335
|
{:else if route === '/account/:tab'}
|
|
262
336
|
<SettingsPage />
|
|
263
337
|
{:else if route === '/account/import-members' || route === '/account/members/import-members'}
|
|
264
|
-
<
|
|
338
|
+
<LazyPage loader={loadImportMembersPage} props={{}} />
|
|
265
339
|
{:else if route === '/account/members-starter' || route === '/account/members/members-starter'}
|
|
266
|
-
<
|
|
340
|
+
<LazyPage loader={loadMembersStarterPage} props={{}} />
|
|
267
341
|
{:else if route === '/account/team-members' || route === '/account/members/team-members'}
|
|
268
|
-
<
|
|
342
|
+
<LazyPage loader={loadTeamMembersPage} props={{}} />
|
|
269
343
|
{:else if route === '/account/security-log' || route === '/account/security/security-log'}
|
|
270
|
-
<
|
|
344
|
+
<LazyPage loader={loadSecurityLogPage} props={{}} />
|
|
271
345
|
{:else if route === '/network/user-cards' || route === '/network/user-cards/nft'}
|
|
272
|
-
<
|
|
346
|
+
<LazyPage loader={loadUserCardsNFTPage} props={{}} />
|
|
273
347
|
{:else if route === '/network/team-crew' || route === '/network/user-table/team-crew'}
|
|
274
|
-
<
|
|
348
|
+
<LazyPage loader={loadTeamCrewTablePage} props={{}} />
|
|
275
349
|
{:else if route.startsWith('/settings')}
|
|
276
350
|
<SettingsPage />
|
|
277
351
|
{:else if route === '/500' || (route === '/:resource' && params.resource === '500')}
|
|
@@ -282,8 +356,8 @@
|
|
|
282
356
|
{@render dashboard()}
|
|
283
357
|
{:else}
|
|
284
358
|
<div class="space-y-4">
|
|
285
|
-
<h1 class="text-xl font-semibold text-foreground">{t('common.welcome', { title })}</h1>
|
|
286
|
-
<p class="text-muted-foreground">{t('common.dashboardHint')}</p>
|
|
359
|
+
<h1 class="text-xl font-semibold text-foreground">{translation.t('common.welcome', { title })}</h1>
|
|
360
|
+
<p class="text-muted-foreground">{translation.t('common.dashboardHint')}</p>
|
|
287
361
|
</div>
|
|
288
362
|
{/if}
|
|
289
363
|
{:else if (route === '/:resource' || route === '/:parent/:parentId/:resource') && hasRouteResource}
|
|
@@ -320,7 +394,7 @@
|
|
|
320
394
|
</Layout>
|
|
321
395
|
{:else}
|
|
322
396
|
<div class="flex h-screen items-center justify-center">
|
|
323
|
-
<p class="text-muted-foreground">{t('common.redirecting')}</p>
|
|
397
|
+
<p class="text-muted-foreground">{translation.t('common.redirecting')}</p>
|
|
324
398
|
</div>
|
|
325
399
|
{/if}
|
|
326
400
|
<Toast />
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '../app.css';
|
|
2
|
-
import type
|
|
3
|
-
import type { DataProvider, AuthProvider, ResourceDefinition, ThemeMode, RouterProvider, ThemeConfig, MenuItem, TaskProvider } from '@svadmin/core';
|
|
2
|
+
import { type Component, type Snippet } from 'svelte';
|
|
3
|
+
import type { DataProvider, AuthProvider, ResourceDefinition, ThemeMode, RouterProvider, ThemeConfig, MenuItem, TaskProvider, I18nProvider } from '@svadmin/core';
|
|
4
4
|
import { QueryClient, type DefaultOptions } from '@tanstack/svelte-query';
|
|
5
5
|
import { type ComponentRegistry } from '../component-registry.svelte.js';
|
|
6
6
|
interface Props {
|
|
@@ -9,7 +9,10 @@ interface Props {
|
|
|
9
9
|
taskProvider?: TaskProvider;
|
|
10
10
|
routerProvider?: RouterProvider;
|
|
11
11
|
resources: ResourceDefinition[];
|
|
12
|
+
/** Bindable tree-local locale; defaults to the provider locale or per-tree browser detection (English during SSR). */
|
|
12
13
|
locale?: string;
|
|
14
|
+
/** Optional tree-local translation provider. */
|
|
15
|
+
i18nProvider?: I18nProvider;
|
|
13
16
|
title?: string;
|
|
14
17
|
defaultTheme?: ThemeMode;
|
|
15
18
|
/** Theme configuration for dark-first mode, CSS overrides, etc. */
|
|
@@ -59,6 +62,6 @@ interface Props {
|
|
|
59
62
|
/** Optional TanStack Query default options override when QueryClient is not supplied. */
|
|
60
63
|
queryClientDefaultOptions?: DefaultOptions;
|
|
61
64
|
}
|
|
62
|
-
declare const AdminApp: Component<Props, {}, "">;
|
|
65
|
+
declare const AdminApp: Component<Props, {}, "locale">;
|
|
63
66
|
type AdminApp = ReturnType<typeof AdminApp>;
|
|
64
67
|
export default AdminApp;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
|
+
|
|
3
4
|
import { AlertCircle, Calendar, Check, Copy, Key, Plus, ShieldCheck, Trash2 } from '@lucide/svelte';
|
|
4
5
|
import * as Card from './ui/card/index.js';
|
|
5
6
|
import { Badge } from './ui/badge/index.js';
|
|
@@ -8,6 +9,8 @@
|
|
|
8
9
|
import { Input } from './ui/input/index.js';
|
|
9
10
|
import { Label } from './ui/label/index.js';
|
|
10
11
|
|
|
12
|
+
const i18n = useTranslation();
|
|
13
|
+
|
|
11
14
|
interface ApiKey {
|
|
12
15
|
id: string;
|
|
13
16
|
name: string;
|
|
@@ -76,8 +79,8 @@
|
|
|
76
79
|
|
|
77
80
|
<div class="space-y-6">
|
|
78
81
|
<div>
|
|
79
|
-
<h2 class="text-xl font-semibold text-foreground">{t('settings.api')}</h2>
|
|
80
|
-
<p class="mt-1 text-sm text-muted-foreground">{t('settings.apiDescription')}</p>
|
|
82
|
+
<h2 class="text-xl font-semibold text-foreground">{i18n.t('settings.api')}</h2>
|
|
83
|
+
<p class="mt-1 text-sm text-muted-foreground">{i18n.t('settings.apiDescription')}</p>
|
|
81
84
|
</div>
|
|
82
85
|
|
|
83
86
|
<div class="grid gap-6 lg:grid-cols-3">
|
|
@@ -85,19 +88,19 @@
|
|
|
85
88
|
<Card.CardHeader>
|
|
86
89
|
<Card.CardTitle class="flex items-center gap-2 text-base">
|
|
87
90
|
<Plus class="h-4 w-4" />
|
|
88
|
-
{t('api.generateTitle')}
|
|
91
|
+
{i18n.t('api.generateTitle')}
|
|
89
92
|
</Card.CardTitle>
|
|
90
|
-
<Card.CardDescription>{t('api.generateDesc')}</Card.CardDescription>
|
|
93
|
+
<Card.CardDescription>{i18n.t('api.generateDesc')}</Card.CardDescription>
|
|
91
94
|
</Card.CardHeader>
|
|
92
95
|
<Card.CardContent>
|
|
93
96
|
<form onsubmit={handleGenerateKey} class="space-y-4">
|
|
94
97
|
<div class="space-y-2">
|
|
95
|
-
<Label for="api-key-name">{t('api.keyName')}</Label>
|
|
98
|
+
<Label for="api-key-name">{i18n.t('api.keyName')}</Label>
|
|
96
99
|
<Input id="api-key-name" placeholder="CI deployment token" bind:value={newKeyName} required />
|
|
97
100
|
</div>
|
|
98
101
|
|
|
99
102
|
<div class="space-y-3">
|
|
100
|
-
<Label>{t('api.permissions')}</Label>
|
|
103
|
+
<Label>{i18n.t('api.permissions')}</Label>
|
|
101
104
|
{#each Object.keys(newKeyPermissions) as permission (permission)}
|
|
102
105
|
<div class="flex items-center gap-2">
|
|
103
106
|
<Checkbox id={`perm-${permission}`} bind:checked={newKeyPermissions[permission as keyof typeof newKeyPermissions]} />
|
|
@@ -106,7 +109,7 @@
|
|
|
106
109
|
{/each}
|
|
107
110
|
</div>
|
|
108
111
|
|
|
109
|
-
<Button type="submit" class="w-full">{t('api.generateButton')}</Button>
|
|
112
|
+
<Button type="submit" class="w-full">{i18n.t('api.generateButton')}</Button>
|
|
110
113
|
</form>
|
|
111
114
|
</Card.CardContent>
|
|
112
115
|
</Card.Card>
|
|
@@ -115,9 +118,9 @@
|
|
|
115
118
|
<Card.CardHeader>
|
|
116
119
|
<Card.CardTitle class="flex items-center gap-2 text-base">
|
|
117
120
|
<Key class="h-4 w-4 text-muted-foreground" />
|
|
118
|
-
{t('api.activeKeysTitle')}
|
|
121
|
+
{i18n.t('api.activeKeysTitle')}
|
|
119
122
|
</Card.CardTitle>
|
|
120
|
-
<Card.CardDescription>{t('api.activeKeysDesc')}</Card.CardDescription>
|
|
123
|
+
<Card.CardDescription>{i18n.t('api.activeKeysDesc')}</Card.CardDescription>
|
|
121
124
|
</Card.CardHeader>
|
|
122
125
|
<Card.CardContent>
|
|
123
126
|
{#if showCreatedToken}
|
|
@@ -125,8 +128,8 @@
|
|
|
125
128
|
<div class="flex items-start gap-2 text-sm text-green-700 dark:text-green-300">
|
|
126
129
|
<ShieldCheck class="mt-0.5 h-5 w-5 shrink-0" />
|
|
127
130
|
<div>
|
|
128
|
-
<h4 class="font-semibold">{t('api.successTitle')}</h4>
|
|
129
|
-
<p class="mt-0.5 text-xs">{t('api.successHint')}</p>
|
|
131
|
+
<h4 class="font-semibold">{i18n.t('api.successTitle')}</h4>
|
|
132
|
+
<p class="mt-0.5 text-xs">{i18n.t('api.successHint')}</p>
|
|
130
133
|
</div>
|
|
131
134
|
</div>
|
|
132
135
|
<div class="flex items-center gap-2">
|
|
@@ -140,7 +143,7 @@
|
|
|
140
143
|
</Button>
|
|
141
144
|
</div>
|
|
142
145
|
<div class="flex justify-end">
|
|
143
|
-
<Button variant="ghost" size="sm" onclick={() => { showCreatedToken = false; generatedToken = ''; }}>{t('common.close')}</Button>
|
|
146
|
+
<Button variant="ghost" size="sm" onclick={() => { showCreatedToken = false; generatedToken = ''; }}>{i18n.t('common.close')}</Button>
|
|
144
147
|
</div>
|
|
145
148
|
</div>
|
|
146
149
|
{/if}
|
|
@@ -160,14 +163,14 @@
|
|
|
160
163
|
</div>
|
|
161
164
|
</div>
|
|
162
165
|
<div class="flex shrink-0 items-center gap-1">
|
|
163
|
-
<Button variant="ghost" size="icon-sm" onclick={() => copyToken(key.maskedToken, key.id)} title={t('common.copy')}>
|
|
166
|
+
<Button variant="ghost" size="icon-sm" onclick={() => copyToken(key.maskedToken, key.id)} title={i18n.t('common.copy')}>
|
|
164
167
|
{#if copiedKeyId === key.id}
|
|
165
168
|
<Check class="h-4 w-4 text-green-500" />
|
|
166
169
|
{:else}
|
|
167
170
|
<Copy class="h-4 w-4" />
|
|
168
171
|
{/if}
|
|
169
172
|
</Button>
|
|
170
|
-
<Button variant="ghost" size="icon-sm" onclick={() => deleteKey(key.id)} title={t('common.delete')}>
|
|
173
|
+
<Button variant="ghost" size="icon-sm" onclick={() => deleteKey(key.id)} title={i18n.t('common.delete')}>
|
|
171
174
|
<Trash2 class="h-4 w-4" />
|
|
172
175
|
</Button>
|
|
173
176
|
</div>
|
|
@@ -181,7 +184,7 @@
|
|
|
181
184
|
{:else}
|
|
182
185
|
<div class="flex flex-col items-center gap-2 py-8 text-center text-sm text-muted-foreground">
|
|
183
186
|
<AlertCircle class="h-8 w-8 opacity-60" />
|
|
184
|
-
<span>{t('api.noKeys')}</span>
|
|
187
|
+
<span>{i18n.t('api.noKeys')}</span>
|
|
185
188
|
</div>
|
|
186
189
|
{/each}
|
|
187
190
|
</div>
|