@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,10 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
|
+
|
|
3
4
|
import { getTheme, setTheme, getColorTheme, setColorTheme, getColorPresets } from '@svadmin/core';
|
|
4
|
-
import { getLocale, setLocale, getAvailableLocales } from '@svadmin/core/i18n';
|
|
5
5
|
import * as Card from './ui/card/index.js';
|
|
6
6
|
import { Sun, Moon, Monitor, Check } from '@lucide/svelte';
|
|
7
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
8
10
|
// Theme mode
|
|
9
11
|
const themeOptions = [
|
|
10
12
|
{ value: 'light' as const, icon: Sun, label: 'settings.light' },
|
|
@@ -14,8 +16,8 @@
|
|
|
14
16
|
|
|
15
17
|
let currentTheme = $derived(getTheme());
|
|
16
18
|
let currentColor = $derived(getColorTheme());
|
|
17
|
-
let currentLocale = $derived(
|
|
18
|
-
const availableLocales = getAvailableLocales();
|
|
19
|
+
let currentLocale = $derived(i18n.locale);
|
|
20
|
+
const availableLocales = i18n.getAvailableLocales();
|
|
19
21
|
const presets = getColorPresets();
|
|
20
22
|
|
|
21
23
|
// Sidebar density
|
|
@@ -55,14 +57,14 @@
|
|
|
55
57
|
|
|
56
58
|
<div class="space-y-6">
|
|
57
59
|
<div>
|
|
58
|
-
<h2 class="text-xl font-semibold text-foreground">{t('settings.appearance')}</h2>
|
|
59
|
-
<p class="text-sm text-muted-foreground mt-1">{t('settings.settingsDescription')}</p>
|
|
60
|
+
<h2 class="text-xl font-semibold text-foreground">{i18n.t('settings.appearance')}</h2>
|
|
61
|
+
<p class="text-sm text-muted-foreground mt-1">{i18n.t('settings.settingsDescription')}</p>
|
|
60
62
|
</div>
|
|
61
63
|
|
|
62
64
|
<!-- Theme Mode -->
|
|
63
65
|
<Card.Card>
|
|
64
66
|
<Card.CardHeader class="pb-3">
|
|
65
|
-
<Card.CardTitle class="text-base">{t('settings.themeMode')}</Card.CardTitle>
|
|
67
|
+
<Card.CardTitle class="text-base">{i18n.t('settings.themeMode')}</Card.CardTitle>
|
|
66
68
|
</Card.CardHeader>
|
|
67
69
|
<Card.CardContent>
|
|
68
70
|
<div class="grid grid-cols-3 gap-3">
|
|
@@ -85,7 +87,7 @@
|
|
|
85
87
|
<opt.icon class="h-5 w-5" />
|
|
86
88
|
</div>
|
|
87
89
|
<span class="text-xs font-medium {active ? 'text-primary' : 'text-muted-foreground'}">
|
|
88
|
-
{t(opt.label)}
|
|
90
|
+
{i18n.t(opt.label)}
|
|
89
91
|
</span>
|
|
90
92
|
</button>
|
|
91
93
|
{/each}
|
|
@@ -96,7 +98,7 @@
|
|
|
96
98
|
<!-- Color Accent -->
|
|
97
99
|
<Card.Card>
|
|
98
100
|
<Card.CardHeader class="pb-3">
|
|
99
|
-
<Card.CardTitle class="text-base">{t('settings.colorAccent')}</Card.CardTitle>
|
|
101
|
+
<Card.CardTitle class="text-base">{i18n.t('settings.colorAccent')}</Card.CardTitle>
|
|
100
102
|
</Card.CardHeader>
|
|
101
103
|
<Card.CardContent>
|
|
102
104
|
<div class="flex flex-wrap gap-3">
|
|
@@ -121,20 +123,20 @@
|
|
|
121
123
|
<!-- Interface -->
|
|
122
124
|
<Card.Card>
|
|
123
125
|
<Card.CardHeader class="pb-3">
|
|
124
|
-
<Card.CardTitle class="text-base">{t('settings.interface')}</Card.CardTitle>
|
|
126
|
+
<Card.CardTitle class="text-base">{i18n.t('settings.interface')}</Card.CardTitle>
|
|
125
127
|
</Card.CardHeader>
|
|
126
128
|
<Card.CardContent class="space-y-5">
|
|
127
129
|
<!-- Language -->
|
|
128
130
|
<div class="flex items-center justify-between">
|
|
129
131
|
<div>
|
|
130
|
-
<p class="text-sm font-medium text-foreground">{t('settings.language')}</p>
|
|
132
|
+
<p class="text-sm font-medium text-foreground">{i18n.t('settings.language')}</p>
|
|
131
133
|
<p class="text-xs text-muted-foreground">{localeNames[currentLocale] ?? currentLocale}</p>
|
|
132
134
|
</div>
|
|
133
135
|
<select
|
|
134
136
|
class="h-9 rounded-md border border-input bg-background px-3 text-sm ring-offset-background
|
|
135
137
|
focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
|
136
138
|
value={currentLocale}
|
|
137
|
-
onchange={(e) => setLocale((e.target as HTMLSelectElement).value)}
|
|
139
|
+
onchange={(e) => i18n.setLocale((e.target as HTMLSelectElement).value)}
|
|
138
140
|
>
|
|
139
141
|
{#each availableLocales as loc, _i (_i)}
|
|
140
142
|
<option value={loc}>{localeNames[loc] ?? loc}</option>
|
|
@@ -147,19 +149,19 @@
|
|
|
147
149
|
<!-- Sidebar Density -->
|
|
148
150
|
<div class="flex items-center justify-between">
|
|
149
151
|
<div>
|
|
150
|
-
<p class="text-sm font-medium text-foreground">{t('settings.sidebarDensity')}</p>
|
|
152
|
+
<p class="text-sm font-medium text-foreground">{i18n.t('settings.sidebarDensity')}</p>
|
|
151
153
|
</div>
|
|
152
154
|
<div class="flex rounded-lg border border-input overflow-hidden">
|
|
153
155
|
<button
|
|
154
156
|
class="px-3 py-1.5 text-xs font-medium transition-colors
|
|
155
157
|
{density === 'compact' ? 'bg-primary text-primary-foreground' : 'bg-background text-muted-foreground hover:bg-accent'}"
|
|
156
158
|
onclick={() => setDensity('compact')}
|
|
157
|
-
>{t('settings.compact')}</button>
|
|
159
|
+
>{i18n.t('settings.compact')}</button>
|
|
158
160
|
<button
|
|
159
161
|
class="px-3 py-1.5 text-xs font-medium transition-colors
|
|
160
162
|
{density === 'standard' ? 'bg-primary text-primary-foreground' : 'bg-background text-muted-foreground hover:bg-accent'}"
|
|
161
163
|
onclick={() => setDensity('standard')}
|
|
162
|
-
>{t('settings.standard')}</button>
|
|
164
|
+
>{i18n.t('settings.standard')}</button>
|
|
163
165
|
</div>
|
|
164
166
|
</div>
|
|
165
167
|
|
|
@@ -168,7 +170,7 @@
|
|
|
168
170
|
<!-- Default Page Size -->
|
|
169
171
|
<div class="flex items-center justify-between">
|
|
170
172
|
<div>
|
|
171
|
-
<p class="text-sm font-medium text-foreground">{t('settings.defaultPageSize')}</p>
|
|
173
|
+
<p class="text-sm font-medium text-foreground">{i18n.t('settings.defaultPageSize')}</p>
|
|
172
174
|
</div>
|
|
173
175
|
<div class="flex rounded-lg border border-input overflow-hidden">
|
|
174
176
|
{#each pageSizeOptions as size, _i (_i)}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { getAuditLogProvider,
|
|
2
|
+
import { getAuditLogProvider, useTranslation } from '@svadmin/core';
|
|
3
|
+
|
|
3
4
|
import type { AuditEntry } from '@svadmin/core';
|
|
4
5
|
import * as Sheet from './ui/sheet/index.js';
|
|
5
6
|
import { History, Loader2 } from '@lucide/svelte';
|
|
6
7
|
|
|
8
|
+
const i18n = useTranslation();
|
|
9
|
+
|
|
7
10
|
let { open = $bindable(false), resource, recordId } = $props<{
|
|
8
11
|
open: boolean;
|
|
9
12
|
resource: string;
|
|
@@ -47,7 +50,7 @@
|
|
|
47
50
|
<Sheet.Header>
|
|
48
51
|
<Sheet.Title class="flex items-center gap-2">
|
|
49
52
|
<History class="h-5 w-5" />
|
|
50
|
-
{t('common.history') || 'History'}
|
|
53
|
+
{i18n.t('common.history') || 'History'}
|
|
51
54
|
</Sheet.Title>
|
|
52
55
|
<Sheet.Description>
|
|
53
56
|
Audit log and revision history for this record.
|
|
@@ -63,7 +66,7 @@
|
|
|
63
66
|
<div class="text-center py-10">
|
|
64
67
|
<History class="h-8 w-8 mx-auto text-muted-foreground/30 mb-3" />
|
|
65
68
|
<p class="text-sm text-muted-foreground">
|
|
66
|
-
{t('common.noData') || 'No audit logs found'}
|
|
69
|
+
{i18n.t('common.noData') || 'No audit logs found'}
|
|
67
70
|
</p>
|
|
68
71
|
</div>
|
|
69
72
|
{:else}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
3
|
+
|
|
3
4
|
import { getAuthProvider } from '@svadmin/core';
|
|
4
5
|
import type { AuditLog } from '@svadmin/core';
|
|
5
6
|
import { toast } from '@svadmin/core/toast';
|
|
@@ -9,6 +10,8 @@
|
|
|
9
10
|
import { Input } from './ui/input/index.js';
|
|
10
11
|
import { Loader2, ChevronLeft, ChevronRight, Search, FileSearch, Eye, X } from '@lucide/svelte';
|
|
11
12
|
|
|
13
|
+
const i18n = useTranslation();
|
|
14
|
+
|
|
12
15
|
const authProvider = getAuthProvider({ optional: true });
|
|
13
16
|
|
|
14
17
|
let logs = $state<AuditLog[]>([]);
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
|
|
28
31
|
async function loadLogs() {
|
|
29
32
|
if (!authProvider?.getAuditLogs) {
|
|
30
|
-
error = t('settings.auditNotSupported') ?? 'Audit logs are not supported by the current AuthProvider';
|
|
33
|
+
error = i18n.t('settings.auditNotSupported') ?? 'Audit logs are not supported by the current AuthProvider';
|
|
31
34
|
loading = false;
|
|
32
35
|
return;
|
|
33
36
|
}
|
|
@@ -87,10 +90,10 @@
|
|
|
87
90
|
<div class="mb-6">
|
|
88
91
|
<h2 class="text-xl font-semibold text-foreground flex items-center gap-2">
|
|
89
92
|
<FileSearch class="h-5 w-5 text-muted-foreground" />
|
|
90
|
-
{t('settings.auditLogs') ?? 'Audit Logs'}
|
|
93
|
+
{i18n.t('settings.auditLogs') ?? 'Audit Logs'}
|
|
91
94
|
</h2>
|
|
92
95
|
<p class="text-sm text-muted-foreground mt-1">
|
|
93
|
-
{t('settings.auditDescription') ?? 'Track and review all system operations for compliance and debugging.'}
|
|
96
|
+
{i18n.t('settings.auditDescription') ?? 'Track and review all system operations for compliance and debugging.'}
|
|
94
97
|
</p>
|
|
95
98
|
</div>
|
|
96
99
|
|
|
@@ -104,7 +107,7 @@
|
|
|
104
107
|
<Search class="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
|
105
108
|
<Input
|
|
106
109
|
bind:value={searchQuery}
|
|
107
|
-
placeholder={t('settings.searchLogs') ?? 'Search by user, action, or resource...'}
|
|
110
|
+
placeholder={i18n.t('settings.searchLogs') ?? 'Search by user, action, or resource...'}
|
|
108
111
|
class="pl-9"
|
|
109
112
|
/>
|
|
110
113
|
</div>
|
|
@@ -114,19 +117,19 @@
|
|
|
114
117
|
{#if loading}
|
|
115
118
|
<div class="flex items-center justify-center h-48 text-muted-foreground">
|
|
116
119
|
<Loader2 class="h-5 w-5 animate-spin mr-2" />
|
|
117
|
-
{t('common.loading')}
|
|
120
|
+
{i18n.t('common.loading')}
|
|
118
121
|
</div>
|
|
119
122
|
{:else}
|
|
120
123
|
<div class="overflow-auto">
|
|
121
124
|
<Table.Root>
|
|
122
125
|
<Table.Header>
|
|
123
126
|
<Table.Row>
|
|
124
|
-
<Table.Head class="w-[160px]">{t('settings.auditTime') ?? 'Time'}</Table.Head>
|
|
125
|
-
<Table.Head>{t('settings.auditUser') ?? 'User'}</Table.Head>
|
|
126
|
-
<Table.Head>{t('settings.auditAction') ?? 'Action'}</Table.Head>
|
|
127
|
-
<Table.Head>{t('settings.auditResource') ?? 'Resource'}</Table.Head>
|
|
128
|
-
<Table.Head class="w-[120px]">{t('settings.auditIp') ?? 'IP Address'}</Table.Head>
|
|
129
|
-
<Table.Head class="w-[60px] text-center">{t('common.detail') ?? 'Detail'}</Table.Head>
|
|
127
|
+
<Table.Head class="w-[160px]">{i18n.t('settings.auditTime') ?? 'Time'}</Table.Head>
|
|
128
|
+
<Table.Head>{i18n.t('settings.auditUser') ?? 'User'}</Table.Head>
|
|
129
|
+
<Table.Head>{i18n.t('settings.auditAction') ?? 'Action'}</Table.Head>
|
|
130
|
+
<Table.Head>{i18n.t('settings.auditResource') ?? 'Resource'}</Table.Head>
|
|
131
|
+
<Table.Head class="w-[120px]">{i18n.t('settings.auditIp') ?? 'IP Address'}</Table.Head>
|
|
132
|
+
<Table.Head class="w-[60px] text-center">{i18n.t('common.detail') ?? 'Detail'}</Table.Head>
|
|
130
133
|
</Table.Row>
|
|
131
134
|
</Table.Header>
|
|
132
135
|
<Table.Body>
|
|
@@ -152,7 +155,7 @@
|
|
|
152
155
|
{:else}
|
|
153
156
|
<Table.Row>
|
|
154
157
|
<Table.Cell colspan={6} class="h-24 text-center text-muted-foreground">
|
|
155
|
-
{t('common.noData')}
|
|
158
|
+
{i18n.t('common.noData')}
|
|
156
159
|
</Table.Cell>
|
|
157
160
|
</Table.Row>
|
|
158
161
|
{/each}
|
|
@@ -164,7 +167,7 @@
|
|
|
164
167
|
|
|
165
168
|
<!-- Pagination -->
|
|
166
169
|
<div class="mt-4 flex items-center justify-between text-sm text-muted-foreground">
|
|
167
|
-
<span>{total} {t('settings.auditTotal') ?? 'total records'}</span>
|
|
170
|
+
<span>{total} {i18n.t('settings.auditTotal') ?? 'total records'}</span>
|
|
168
171
|
<div class="flex items-center gap-2">
|
|
169
172
|
<Button
|
|
170
173
|
variant="outline" size="sm"
|
|
@@ -199,7 +202,7 @@
|
|
|
199
202
|
<div>
|
|
200
203
|
<h2 class="text-lg font-bold text-foreground flex items-center gap-2">
|
|
201
204
|
<FileSearch class="h-5 w-5 text-primary" />
|
|
202
|
-
{t('settings.auditSnapshot') ?? 'Change Snapshot'}
|
|
205
|
+
{i18n.t('settings.auditSnapshot') ?? 'Change Snapshot'}
|
|
203
206
|
</h2>
|
|
204
207
|
<p class="text-xs text-muted-foreground mt-1">{formatDate(drawerLog.createdAt)} · {drawerLog.userName ?? drawerLog.userId}</p>
|
|
205
208
|
</div>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { captureAdminContext, useIsAuthenticated } from '@svadmin/core';
|
|
3
3
|
import type { Snippet } from 'svelte';
|
|
4
|
-
import { navigate } from '@svadmin/core';
|
|
5
4
|
|
|
6
5
|
let {
|
|
7
6
|
children,
|
|
@@ -17,13 +16,14 @@
|
|
|
17
16
|
appendCurrentPathToQuery?: boolean;
|
|
18
17
|
}>();
|
|
19
18
|
|
|
19
|
+
const adminContext = captureAdminContext();
|
|
20
20
|
const isAuth = useIsAuthenticated();
|
|
21
21
|
|
|
22
22
|
function triggerRedirect() {
|
|
23
23
|
if (fallback) return;
|
|
24
24
|
let url = redirectTo;
|
|
25
25
|
if (appendCurrentPathToQuery && typeof window !== 'undefined') {
|
|
26
|
-
const rp =
|
|
26
|
+
const rp = adminContext.routerProvider;
|
|
27
27
|
let currentString = window.location.pathname + window.location.search;
|
|
28
28
|
if (rp) {
|
|
29
29
|
const parsed = rp.parse();
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
const current = encodeURIComponent(currentString);
|
|
34
34
|
url += url.includes('?') ? `&to=${current}` : `?to=${current}`;
|
|
35
35
|
}
|
|
36
|
-
navigate(url);
|
|
36
|
+
adminContext.navigate(url);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
$effect(() => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { useForm, getResource, deriveValidator } from '@svadmin/core';
|
|
2
|
+
import { captureAdminContext, useForm, getResource, deriveValidator } from '@svadmin/core';
|
|
3
3
|
import { slide } from 'svelte/transition';
|
|
4
4
|
import type { FieldDefinition } from '@svadmin/core';
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
6
|
+
|
|
7
7
|
import { Button } from './ui/button/index.js';
|
|
8
8
|
import TooltipButton from './TooltipButton.svelte';
|
|
9
9
|
import * as Card from './ui/card/index.js';
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
import ConfirmDialog from './ConfirmDialog.svelte';
|
|
16
16
|
import type { Snippet } from 'svelte';
|
|
17
17
|
|
|
18
|
+
const i18n = useTranslation();
|
|
19
|
+
|
|
18
20
|
interface Props {
|
|
19
21
|
resourceName: string;
|
|
20
22
|
id?: string | number;
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
let { resourceName, id, mode = 'create', fieldRenderer, formActions, headerContent, onSuccess }: Props = $props();
|
|
31
|
+
const adminContext = captureAdminContext();
|
|
29
32
|
const isReadonly = $derived(mode === 'show');
|
|
30
33
|
|
|
31
34
|
// ─── Resource metadata ────────────────────────────────────────────
|
|
@@ -73,7 +76,7 @@
|
|
|
73
76
|
return d;
|
|
74
77
|
})());
|
|
75
78
|
|
|
76
|
-
const validator = $derived(deriveValidator(formFields));
|
|
79
|
+
const validator = $derived(deriveValidator(formFields, { translate: i18n.t }));
|
|
77
80
|
|
|
78
81
|
// ─── useForm: single source of truth for values, errors, tainted ──
|
|
79
82
|
const form = useForm({
|
|
@@ -95,16 +98,16 @@
|
|
|
95
98
|
await form.submit();
|
|
96
99
|
onSuccess?.();
|
|
97
100
|
} catch (e) {
|
|
98
|
-
submitError = e instanceof Error ? e.message : t('common.operationFailed');
|
|
101
|
+
submitError = e instanceof Error ? e.message : i18n.t('common.operationFailed');
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
104
|
|
|
102
105
|
const pageTitle = $derived(
|
|
103
106
|
mode === 'create'
|
|
104
|
-
? `${t('common.create')}${resource.label}`
|
|
107
|
+
? `${i18n.t('common.create')}${resource.label}`
|
|
105
108
|
: mode === 'show'
|
|
106
|
-
? `${t('common.detail')}${resource.label}`
|
|
107
|
-
: `${t('common.edit')}${resource.label}`
|
|
109
|
+
? `${i18n.t('common.detail')}${resource.label}`
|
|
110
|
+
: `${i18n.t('common.edit')}${resource.label}`
|
|
108
111
|
);
|
|
109
112
|
|
|
110
113
|
// ─── Unsaved changes guard ────────────────────────────────────────
|
|
@@ -135,8 +138,8 @@
|
|
|
135
138
|
<div class="space-y-6">
|
|
136
139
|
<div class="flex items-center gap-4">
|
|
137
140
|
<TooltipButton
|
|
138
|
-
tooltip={t('common.back')}
|
|
139
|
-
onclick={() => guardNavigate(() => navigate(`/${resourceName}`))}
|
|
141
|
+
tooltip={i18n.t('common.back')}
|
|
142
|
+
onclick={() => guardNavigate(() => adminContext.navigate(`/${resourceName}`))}
|
|
140
143
|
>
|
|
141
144
|
<ArrowLeft class="h-5 w-5" />
|
|
142
145
|
</TooltipButton>
|
|
@@ -145,7 +148,7 @@
|
|
|
145
148
|
{@render headerContent()}
|
|
146
149
|
{/if}
|
|
147
150
|
{#if form.isTainted()}
|
|
148
|
-
<Badge variant="outline" class="border-warning/30 bg-warning/10 text-warning-foreground">{t('common.unsaved')}</Badge>
|
|
151
|
+
<Badge variant="outline" class="border-warning/30 bg-warning/10 text-warning-foreground">{i18n.t('common.unsaved')}</Badge>
|
|
149
152
|
{/if}
|
|
150
153
|
</div>
|
|
151
154
|
|
|
@@ -234,14 +237,14 @@
|
|
|
234
237
|
{:else}
|
|
235
238
|
<Save class="h-4 w-4" data-icon="inline-start" />
|
|
236
239
|
{/if}
|
|
237
|
-
{t('common.save')}
|
|
240
|
+
{i18n.t('common.save')}
|
|
238
241
|
</Button>
|
|
239
242
|
<Button
|
|
240
243
|
type="button"
|
|
241
244
|
variant="outline"
|
|
242
|
-
onclick={() => guardNavigate(() => navigate(`/${resourceName}`))}
|
|
245
|
+
onclick={() => guardNavigate(() => adminContext.navigate(`/${resourceName}`))}
|
|
243
246
|
>
|
|
244
|
-
{t('common.cancel')}
|
|
247
|
+
{i18n.t('common.cancel')}
|
|
245
248
|
</Button>
|
|
246
249
|
{/if}
|
|
247
250
|
</div>
|
|
@@ -251,8 +254,8 @@
|
|
|
251
254
|
|
|
252
255
|
<ConfirmDialog
|
|
253
256
|
open={confirmOpen}
|
|
254
|
-
message={t('common.unsavedChanges')}
|
|
255
|
-
confirmText={t('common.confirm')}
|
|
257
|
+
message={i18n.t('common.unsavedChanges')}
|
|
258
|
+
confirmText={i18n.t('common.confirm')}
|
|
256
259
|
onconfirm={confirmNavigate}
|
|
257
260
|
oncancel={cancelNavigate}
|
|
258
261
|
/>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { fade, fly } from 'svelte/transition';
|
|
3
3
|
import { Loader2, Check, X, Cloud } from '@lucide/svelte';
|
|
4
|
-
import {
|
|
4
|
+
import { useTranslation } from '@svadmin/core/i18n';
|
|
5
|
+
|
|
6
|
+
const i18n = useTranslation();
|
|
5
7
|
|
|
6
8
|
let {
|
|
7
9
|
status = 'idle',
|
|
@@ -19,16 +21,16 @@
|
|
|
19
21
|
<div class="flex items-center gap-2" in:fly={{ y: -8, duration: 200 }} out:fade={{ duration: 150 }}>
|
|
20
22
|
{#if status === 'idle'}
|
|
21
23
|
<Cloud class="h-4 w-4" />
|
|
22
|
-
<span>{t('autoSave.idle')}</span>
|
|
24
|
+
<span>{i18n.t('autoSave.idle')}</span>
|
|
23
25
|
{:else if status === 'loading'}
|
|
24
26
|
<Loader2 class="h-4 w-4 animate-spin text-primary" />
|
|
25
|
-
<span>{t('autoSave.saving')}</span>
|
|
27
|
+
<span>{i18n.t('autoSave.saving')}</span>
|
|
26
28
|
{:else if status === 'success'}
|
|
27
29
|
<Check class="h-4 w-4 text-green-500" />
|
|
28
|
-
<span class="text-green-500">{t('autoSave.saved')}</span>
|
|
30
|
+
<span class="text-green-500">{i18n.t('autoSave.saved')}</span>
|
|
29
31
|
{:else if status === 'error'}
|
|
30
32
|
<X class="h-4 w-4 text-destructive" />
|
|
31
|
-
<span class="text-destructive" title={error}>{t('autoSave.error')}</span>
|
|
33
|
+
<span class="text-destructive" title={error}>{i18n.t('autoSave.error')}</span>
|
|
32
34
|
{/if}
|
|
33
35
|
</div>
|
|
34
36
|
{/key}
|