@svadmin/ui 0.57.0 → 0.58.0
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/components/AICommandBar.svelte +33 -10
- package/dist/components/AdminApp.svelte +16 -5
- package/dist/components/AutoForm.svelte +4 -4
- package/dist/components/AutoTable.svelte +866 -204
- package/dist/components/AutoTable.svelte.d.ts +1 -1
- package/dist/components/CommandPalette.svelte +39 -17
- package/dist/components/ConfirmDialog.svelte +4 -3
- package/dist/components/ConfirmDialog.svelte.d.ts +1 -0
- package/dist/components/CopilotPanel.svelte +3 -3
- package/dist/components/DraggableHeader.svelte +15 -36
- package/dist/components/DraggableHeader.svelte.d.ts +13 -4
- package/dist/components/EditPage.svelte +4 -4
- package/dist/components/ListPage.svelte +4 -12
- package/dist/components/ListPage.svelte.d.ts +1 -1
- package/dist/components/RecordDetailDrawer.svelte +121 -0
- package/dist/components/RecordDetailDrawer.svelte.d.ts +9 -0
- package/dist/components/ResourceAccessGuard.svelte +68 -0
- package/dist/components/ResourceAccessGuard.svelte.d.ts +12 -0
- package/dist/components/ResourceOperationsPage.svelte +8 -3
- package/dist/components/ShowPage.svelte +5 -6
- package/dist/components/TenantSwitcher.svelte +1 -0
- package/dist/components/Toast.svelte +35 -1
- package/dist/components/UndoableNotification.svelte +12 -6
- package/dist/components/UndoableNotification.svelte.d.ts +2 -0
- package/dist/components/buttons/CloneButton.svelte +9 -2
- package/dist/components/buttons/CreateButton.svelte +9 -2
- package/dist/components/buttons/DeleteButton.svelte +9 -2
- package/dist/components/buttons/EditButton.svelte +9 -2
- package/dist/components/buttons/ListButton.svelte +1 -1
- package/dist/components/buttons/ShowButton.svelte +9 -2
- package/dist/components/saved-list-views.d.ts +35 -0
- package/dist/components/saved-list-views.js +168 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +2 -2
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { captureAdminContext, toggleTheme } from '@svadmin/core';
|
|
2
|
+
import { captureAdminContext, toggleTheme, useNavigation } from '@svadmin/core';
|
|
3
3
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
4
4
|
import { Command } from './ui/command/index.js';
|
|
5
5
|
import * as Dialog from './ui/dialog/index.js';
|
|
6
6
|
import { Search, LayoutDashboard, Plus, Sun, FileText, Sparkles, Loader2 } from '@lucide/svelte';
|
|
7
7
|
import MarkdownRenderer from './MarkdownRenderer.svelte';
|
|
8
|
+
import CanAccess from './CanAccess.svelte';
|
|
8
9
|
|
|
9
10
|
const i18n = useTranslation();
|
|
10
11
|
|
|
11
12
|
let { open = $bindable(false) } = $props<{ open?: boolean }>();
|
|
12
13
|
const adminContext = captureAdminContext();
|
|
14
|
+
const navigation = useNavigation();
|
|
13
15
|
let searchValue = $state('');
|
|
14
16
|
|
|
15
17
|
const resources = $derived(adminContext.resources);
|
|
@@ -127,7 +129,8 @@
|
|
|
127
129
|
/>
|
|
128
130
|
{#if searchValue.trim() && !aiMode}
|
|
129
131
|
<button
|
|
130
|
-
|
|
132
|
+
type="button"
|
|
133
|
+
class="absolute right-3 flex items-center gap-1 text-[10px] font-medium text-warning bg-warning/10 hover:bg-warning/20 px-2 py-1 rounded transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
131
134
|
onclick={askAI}
|
|
132
135
|
>
|
|
133
136
|
<Sparkles class="h-3 w-3" />
|
|
@@ -149,10 +152,19 @@
|
|
|
149
152
|
{i18n.t('common.home')}
|
|
150
153
|
</Command.Item>
|
|
151
154
|
{#each resources as r, _i (_i)}
|
|
152
|
-
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
{#if adminContext.accessControlProvider}
|
|
156
|
+
<CanAccess resource={r.name} action="list">
|
|
157
|
+
<Command.Item value={r.name} onSelect={() => act(() => navigation.list(r.name))} class={itemClass}>
|
|
158
|
+
<FileText class="h-4 w-4 text-muted-foreground" />
|
|
159
|
+
{r.label}
|
|
160
|
+
</Command.Item>
|
|
161
|
+
</CanAccess>
|
|
162
|
+
{:else}
|
|
163
|
+
<Command.Item value={r.name} onSelect={() => act(() => navigation.list(r.name))} class={itemClass}>
|
|
164
|
+
<FileText class="h-4 w-4 text-muted-foreground" />
|
|
165
|
+
{r.label}
|
|
166
|
+
</Command.Item>
|
|
167
|
+
{/if}
|
|
156
168
|
{/each}
|
|
157
169
|
</Command.Group>
|
|
158
170
|
|
|
@@ -161,10 +173,21 @@
|
|
|
161
173
|
<!-- Actions -->
|
|
162
174
|
<Command.Group heading={i18n.t('common.actions')}>
|
|
163
175
|
{#each resources as r, _i (_i)}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
176
|
+
{#if r.canCreate !== false}
|
|
177
|
+
{#if adminContext.accessControlProvider}
|
|
178
|
+
<CanAccess resource={r.name} action="create">
|
|
179
|
+
<Command.Item value={`create-${r.name}`} onSelect={() => act(() => navigation.create(r.name))} class={itemClass}>
|
|
180
|
+
<Plus class="h-4 w-4 text-muted-foreground" />
|
|
181
|
+
{i18n.t('common.create')} {r.label}
|
|
182
|
+
</Command.Item>
|
|
183
|
+
</CanAccess>
|
|
184
|
+
{:else}
|
|
185
|
+
<Command.Item value={`create-${r.name}`} onSelect={() => act(() => navigation.create(r.name))} class={itemClass}>
|
|
186
|
+
<Plus class="h-4 w-4 text-muted-foreground" />
|
|
187
|
+
{i18n.t('common.create')} {r.label}
|
|
188
|
+
</Command.Item>
|
|
189
|
+
{/if}
|
|
190
|
+
{/if}
|
|
168
191
|
{/each}
|
|
169
192
|
<Command.Item value="toggle-theme" onSelect={() => act(() => toggleTheme())} class={itemClass}>
|
|
170
193
|
<Sun class="h-4 w-4 text-muted-foreground" />
|
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
import ErrorPage from './ErrorPage.svelte';
|
|
74
74
|
import SystemPageShell from './SystemPageShell.svelte';
|
|
75
75
|
import LazyPage from './LazyPage.svelte';
|
|
76
|
+
import ResourceAccessGuard from './ResourceAccessGuard.svelte';
|
|
76
77
|
import { Button } from './ui/button/index.js';
|
|
77
78
|
import { Input } from './ui/input/index.js';
|
|
78
79
|
import { Badge } from './ui/badge/index.js';
|
|
@@ -609,27 +610,37 @@
|
|
|
609
610
|
{:else if (renderedRoute === '/:resource' || renderedRoute === '/:parent/:parentId/:resource') && renderedHasRouteResource}
|
|
610
611
|
{#key renderedParams.resource}
|
|
611
612
|
{@const Comp = renderedResourcePages?.list ?? mergedComponents.AutoTable}
|
|
612
|
-
<
|
|
613
|
+
<ResourceAccessGuard resourceName={renderedParams.resource} action="list">
|
|
614
|
+
<Comp resourceName={renderedParams.resource} />
|
|
615
|
+
</ResourceAccessGuard>
|
|
613
616
|
{/key}
|
|
614
617
|
{:else if (renderedRoute === '/:resource/create' || renderedRoute === '/:parent/:parentId/:resource/create') && renderedHasRouteResource}
|
|
615
618
|
{#key renderedParams.resource}
|
|
616
619
|
{@const Comp = renderedResourcePages?.create ?? mergedComponents.AutoForm}
|
|
617
|
-
<
|
|
620
|
+
<ResourceAccessGuard resourceName={renderedParams.resource} action="create">
|
|
621
|
+
<Comp resourceName={renderedParams.resource} mode="create" />
|
|
622
|
+
</ResourceAccessGuard>
|
|
618
623
|
{/key}
|
|
619
624
|
{:else if (renderedRoute === '/:resource/edit/:id' || renderedRoute === '/:resource/:id/edit' || renderedRoute === '/:parent/:parentId/:resource/edit/:id') && renderedHasRouteResource}
|
|
620
625
|
{#key `${renderedParams.resource}-${renderedParams.id}`}
|
|
621
626
|
{@const Comp = renderedResourcePages?.edit ?? mergedComponents.AutoForm}
|
|
622
|
-
<
|
|
627
|
+
<ResourceAccessGuard resourceName={renderedParams.resource} action="edit" id={renderedParams.id}>
|
|
628
|
+
<Comp resourceName={renderedParams.resource} mode="edit" id={renderedParams.id} />
|
|
629
|
+
</ResourceAccessGuard>
|
|
623
630
|
{/key}
|
|
624
631
|
{:else if (renderedRoute === '/:resource/show/:id' || renderedRoute === '/:resource/:id' || renderedRoute === '/:parent/:parentId/:resource/show/:id') && renderedHasRouteResource}
|
|
625
632
|
{#key `${renderedParams.resource}-${renderedParams.id}`}
|
|
626
633
|
{@const Comp = renderedResourcePages?.show ?? mergedComponents.ShowPage}
|
|
627
|
-
<
|
|
634
|
+
<ResourceAccessGuard resourceName={renderedParams.resource} action="show" id={renderedParams.id}>
|
|
635
|
+
<Comp resourceName={renderedParams.resource} id={renderedParams.id} />
|
|
636
|
+
</ResourceAccessGuard>
|
|
628
637
|
{/key}
|
|
629
638
|
{:else if (renderedRoute === '/:resource/clone/:id' || renderedRoute === '/:parent/:parentId/:resource/clone/:id') && renderedHasRouteResource}
|
|
630
639
|
{#key `${renderedParams.resource}-clone-${renderedParams.id}`}
|
|
631
640
|
{@const Comp = renderedResourcePages?.clone ?? mergedComponents.AutoForm}
|
|
632
|
-
<
|
|
641
|
+
<ResourceAccessGuard resourceName={renderedParams.resource} action="create" id={renderedParams.id} requireSourceRead>
|
|
642
|
+
<Comp resourceName={renderedParams.resource} mode="clone" id={renderedParams.id} />
|
|
643
|
+
</ResourceAccessGuard>
|
|
633
644
|
{/key}
|
|
634
645
|
{:else}
|
|
635
646
|
{@const ErrorComp = mergedComponents.ErrorPage || ErrorPage}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useForm, getResource, deriveValidator, useNavigation } from '@svadmin/core';
|
|
3
3
|
import { slide } from 'svelte/transition';
|
|
4
4
|
import type { FieldDefinition } from '@svadmin/core';
|
|
5
5
|
import { useTranslation } from '@svadmin/core/i18n';
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
onSuccess,
|
|
46
46
|
onNavigationGuardReady,
|
|
47
47
|
}: Props = $props();
|
|
48
|
-
const
|
|
48
|
+
const navigation = useNavigation();
|
|
49
49
|
const isReadonly = $derived(mode === 'show');
|
|
50
50
|
const isCompact = $derived(density === 'compact');
|
|
51
51
|
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
<div class="flex items-center gap-4">
|
|
197
197
|
<TooltipButton
|
|
198
198
|
tooltip={i18n.t('common.back')}
|
|
199
|
-
onclick={() => guardNavigate(() =>
|
|
199
|
+
onclick={() => guardNavigate(() => navigation.list(resourceName))}
|
|
200
200
|
>
|
|
201
201
|
<ArrowLeft class="h-5 w-5" />
|
|
202
202
|
</TooltipButton>
|
|
@@ -311,7 +311,7 @@
|
|
|
311
311
|
type="button"
|
|
312
312
|
variant="outline"
|
|
313
313
|
size={isCompact ? 'sm' : 'default'}
|
|
314
|
-
onclick={() => guardNavigate(() =>
|
|
314
|
+
onclick={() => guardNavigate(() => navigation.list(resourceName))}
|
|
315
315
|
>
|
|
316
316
|
{i18n.t('common.cancel')}
|
|
317
317
|
</Button>
|