@svadmin/ui 0.34.10 → 0.36.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/app.css +746 -22
- package/dist/component-registry.svelte.d.ts +1 -0
- package/dist/components/AdminApp.svelte +94 -15
- package/dist/components/AdminApp.svelte.d.ts +32 -2
- package/dist/components/ApiSettings.svelte +191 -0
- package/dist/components/ApiSettings.svelte.d.ts +3 -0
- package/dist/components/AutoForm.svelte +47 -42
- package/dist/components/AutoTable.svelte +29 -24
- package/dist/components/ErrorPage.svelte +58 -0
- package/dist/components/ErrorPage.svelte.d.ts +8 -0
- package/dist/components/FieldRenderer.svelte +2 -2
- package/dist/components/ForgotPasswordPage.svelte +111 -68
- package/dist/components/Header.svelte +6 -7
- package/dist/components/IntegrationsSettings.svelte +70 -0
- package/dist/components/IntegrationsSettings.svelte.d.ts +4 -0
- package/dist/components/Layout.svelte +7 -7
- package/dist/components/LoginPage.svelte +207 -105
- package/dist/components/LoginPage.svelte.d.ts +3 -15
- package/dist/components/NotificationsSettings.svelte +115 -0
- package/dist/components/NotificationsSettings.svelte.d.ts +3 -0
- package/dist/components/PageHeader.svelte +9 -7
- package/dist/components/RegisterPage.svelte +103 -65
- package/dist/components/ResourceOperationsPage.svelte +151 -0
- package/dist/components/ResourceOperationsPage.svelte.d.ts +37 -0
- package/dist/components/SecuritySettings.svelte +179 -0
- package/dist/components/SecuritySettings.svelte.d.ts +4 -0
- package/dist/components/SettingsPage.svelte +120 -87
- package/dist/components/SettingsPage.svelte.d.ts +25 -1
- package/dist/components/ShowPage.svelte +9 -9
- package/dist/components/Sidebar.svelte +278 -189
- package/dist/components/SidebarItem.svelte +77 -18
- package/dist/components/TwoFactorAuthPage.svelte +247 -0
- package/dist/components/TwoFactorAuthPage.svelte.d.ts +3 -0
- package/dist/components/UpdatePasswordPage.svelte +86 -48
- package/dist/components/account/CompanyProfilePage.svelte +99 -0
- package/dist/components/account/CompanyProfilePage.svelte.d.ts +3 -0
- package/dist/components/account/GetStartedPage.svelte +123 -0
- package/dist/components/account/GetStartedPage.svelte.d.ts +4 -0
- package/dist/components/account/ImportMembersPage.svelte +143 -0
- package/dist/components/account/ImportMembersPage.svelte.d.ts +3 -0
- package/dist/components/account/MembersStarterPage.svelte +104 -0
- package/dist/components/account/MembersStarterPage.svelte.d.ts +3 -0
- package/dist/components/account/SecurityLogPage.svelte +135 -0
- package/dist/components/account/SecurityLogPage.svelte.d.ts +3 -0
- package/dist/components/account/SettingsEnterprisePage.svelte +131 -0
- package/dist/components/account/SettingsEnterprisePage.svelte.d.ts +3 -0
- package/dist/components/account/SettingsPlainPage.svelte +81 -0
- package/dist/components/account/SettingsPlainPage.svelte.d.ts +3 -0
- package/dist/components/account/SettingsSidebarPage.svelte +98 -0
- package/dist/components/account/SettingsSidebarPage.svelte.d.ts +3 -0
- package/dist/components/account/TeamMembersPage.svelte +98 -0
- package/dist/components/account/TeamMembersPage.svelte.d.ts +3 -0
- package/dist/components/network/TeamCrewTablePage.svelte +155 -0
- package/dist/components/network/TeamCrewTablePage.svelte.d.ts +3 -0
- package/dist/components/network/UserCardsNFTPage.svelte +134 -0
- package/dist/components/network/UserCardsNFTPage.svelte.d.ts +3 -0
- package/dist/components/profile/ActivityTimeline.svelte +77 -0
- package/dist/components/profile/ActivityTimeline.svelte.d.ts +16 -0
- package/dist/components/profile/ProfileCard.svelte +216 -0
- package/dist/components/profile/ProfileCard.svelte.d.ts +27 -0
- package/dist/components/profile/ProjectsGrid.svelte +91 -0
- package/dist/components/profile/ProjectsGrid.svelte.d.ts +17 -0
- package/dist/components/profile/PublicProfilePage.svelte +179 -0
- package/dist/components/profile/PublicProfilePage.svelte.d.ts +10 -0
- package/dist/components/profile/TeamsShowcase.svelte +98 -0
- package/dist/components/profile/TeamsShowcase.svelte.d.ts +19 -0
- package/dist/components/ui/pagination/pagination-ellipsis.svelte +1 -1
- package/dist/index.d.ts +23 -0
- package/dist/index.js +27 -0
- package/dist/router-state.svelte.js +17 -0
- package/package.json +2 -2
|
@@ -1,118 +1,151 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
2
|
+
import type { Component, Snippet } from "svelte";
|
|
3
|
+
import { t } from "@svadmin/core/i18n";
|
|
4
|
+
import { navigate } from "@svadmin/core/router";
|
|
5
|
+
import { User, Info, FileSearch, Lock, Puzzle } from "@lucide/svelte";
|
|
6
|
+
import ProfilePage from "./ProfilePage.svelte";
|
|
7
|
+
import AppearanceSettings from "./AppearanceSettings.svelte";
|
|
8
|
+
import AboutSettings from "./AboutSettings.svelte";
|
|
9
|
+
import RolesSettings from "./RolesSettings.svelte";
|
|
10
|
+
import AuditLogViewer from "./AuditLogViewer.svelte";
|
|
11
|
+
import SecuritySettings from "./SecuritySettings.svelte";
|
|
12
|
+
import IntegrationsSettings from "./IntegrationsSettings.svelte";
|
|
13
|
+
import NotificationsSettings from "./NotificationsSettings.svelte";
|
|
14
|
+
import ApiSettings from "./ApiSettings.svelte";
|
|
15
|
+
import { getAuthProvider } from "@svadmin/core";
|
|
11
16
|
|
|
12
17
|
const authProvider = getAuthProvider({ optional: true });
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
interface SettingsItem {
|
|
20
|
+
key: string;
|
|
21
|
+
path: string;
|
|
22
|
+
icon: Component;
|
|
23
|
+
label: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface SettingsSection {
|
|
27
|
+
group: string;
|
|
28
|
+
items: SettingsItem[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface Props {
|
|
32
|
+
customSections?: SettingsSection[];
|
|
33
|
+
profile?: Snippet;
|
|
34
|
+
appearance?: Snippet;
|
|
35
|
+
roles?: Snippet;
|
|
36
|
+
security?: Snippet;
|
|
37
|
+
integrations?: Snippet;
|
|
38
|
+
notifications?: Snippet;
|
|
39
|
+
api?: Snippet;
|
|
40
|
+
audit?: Snippet;
|
|
41
|
+
about?: Snippet;
|
|
42
|
+
content?: Snippet<[string]>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let {
|
|
46
|
+
customSections,
|
|
47
|
+
profile,
|
|
48
|
+
appearance,
|
|
49
|
+
roles,
|
|
50
|
+
security,
|
|
51
|
+
integrations,
|
|
52
|
+
notifications,
|
|
53
|
+
api,
|
|
54
|
+
audit,
|
|
55
|
+
about,
|
|
56
|
+
content,
|
|
57
|
+
}: Props = $props();
|
|
58
|
+
|
|
59
|
+
const defaultSections = [
|
|
15
60
|
{
|
|
16
|
-
group:
|
|
61
|
+
group: "settings.general",
|
|
17
62
|
items: [
|
|
18
|
-
{ key:
|
|
19
|
-
{ key: 'appearance', path: '/settings/appearance', icon: Palette, label: 'settings.appearance' },
|
|
63
|
+
{ key: "account", path: "/settings/account", icon: User, label: "settings.accountPreferences" },
|
|
20
64
|
],
|
|
21
65
|
},
|
|
22
66
|
{
|
|
23
|
-
group:
|
|
67
|
+
group: "settings.workspace",
|
|
68
|
+
items: [
|
|
69
|
+
{ key: "access", path: "/settings/access", icon: Lock, label: "settings.accessSecurity" },
|
|
70
|
+
{ key: "developer", path: "/settings/developer", icon: Puzzle, label: "settings.integrationApi" },
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
group: "settings.developer",
|
|
24
75
|
items: [
|
|
25
76
|
...(authProvider ? [
|
|
26
|
-
{ key:
|
|
27
|
-
{ key: 'audit', path: '/settings/audit', icon: FileSearch, label: 'settings.auditLogs' },
|
|
77
|
+
{ key: "audit", path: "/settings/audit", icon: FileSearch, label: "settings.auditLogs" },
|
|
28
78
|
] : []),
|
|
29
|
-
{ key:
|
|
79
|
+
{ key: "about", path: "/settings/about", icon: Info, label: "settings.about" },
|
|
30
80
|
],
|
|
31
81
|
},
|
|
32
82
|
];
|
|
33
83
|
|
|
34
|
-
|
|
84
|
+
const resolvedSections = $derived(customSections ?? defaultSections);
|
|
85
|
+
const sectionKeys = $derived(new Set(resolvedSections.flatMap((section) => section.items.map((item) => item.key))));
|
|
86
|
+
|
|
87
|
+
import { getParams, getRoute } from "../router-state.svelte.js";
|
|
88
|
+
|
|
89
|
+
function normalizeKey(tab: string | undefined): string {
|
|
90
|
+
if (!tab) return "account";
|
|
91
|
+
if (["profile", "appearance", "notifications"].includes(tab)) return "account";
|
|
92
|
+
if (["security", "roles"].includes(tab)) return "access";
|
|
93
|
+
if (["integrations", "api"].includes(tab)) return "developer";
|
|
94
|
+
return tab;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function pathForKey(key: string): string {
|
|
98
|
+
return `/settings/${key}`;
|
|
99
|
+
}
|
|
35
100
|
|
|
36
101
|
let activeKey = $derived.by(() => {
|
|
37
102
|
const tab = getParams().tab;
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
if (tab === 'about') return 'about';
|
|
42
|
-
return 'profile';
|
|
103
|
+
const normalized = normalizeKey(tab);
|
|
104
|
+
if (sectionKeys.has(normalized)) return normalized;
|
|
105
|
+
return content ? normalized : "account";
|
|
43
106
|
});
|
|
44
107
|
|
|
45
|
-
// Default redirect to profile
|
|
46
108
|
$effect(() => {
|
|
47
|
-
if (getRoute() ===
|
|
48
|
-
navigate(
|
|
109
|
+
if (getRoute() === "/settings") {
|
|
110
|
+
navigate("/settings/account");
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const tab = getParams().tab;
|
|
115
|
+
const normalized = normalizeKey(tab);
|
|
116
|
+
if (tab && tab !== normalized && sectionKeys.has(normalized)) {
|
|
117
|
+
navigate(pathForKey(normalized));
|
|
49
118
|
}
|
|
50
119
|
});
|
|
51
120
|
</script>
|
|
52
121
|
|
|
53
|
-
<div class="
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{#each sections as section, _i (_i)}
|
|
59
|
-
{#each section.items as item, _i (_i)}
|
|
60
|
-
{@const active = activeKey === item.key}
|
|
61
|
-
<button
|
|
62
|
-
class="flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md whitespace-nowrap transition-colors
|
|
63
|
-
{active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground hover:bg-background/50'}"
|
|
64
|
-
onclick={() => navigate(item.path)}
|
|
65
|
-
>
|
|
66
|
-
<item.icon class="h-4 w-4" />
|
|
67
|
-
{t(item.label)}
|
|
68
|
-
</button>
|
|
69
|
-
{/each}
|
|
70
|
-
{/each}
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<!-- Desktop: vertical nav with groups -->
|
|
74
|
-
<div class="hidden lg:block py-6 px-3 space-y-6">
|
|
75
|
-
<div class="px-3">
|
|
76
|
-
<h2 class="text-lg font-semibold text-foreground">{t('settings.title')}</h2>
|
|
77
|
-
<p class="text-xs text-muted-foreground mt-1">{t('settings.settingsDescription')}</p>
|
|
78
|
-
</div>
|
|
79
|
-
{#each sections as section, _i (_i)}
|
|
80
|
-
<div>
|
|
81
|
-
<h3 class="px-3 mb-1 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/60">
|
|
82
|
-
{t(section.group)}
|
|
83
|
-
</h3>
|
|
84
|
-
<div class="space-y-0.5">
|
|
85
|
-
{#each section.items as item, _i (_i)}
|
|
86
|
-
{@const active = activeKey === item.key}
|
|
87
|
-
<button
|
|
88
|
-
class="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-sm transition-all
|
|
89
|
-
{active
|
|
90
|
-
? 'bg-primary/10 text-primary font-medium'
|
|
91
|
-
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'}"
|
|
92
|
-
onclick={() => navigate(item.path)}
|
|
93
|
-
>
|
|
94
|
-
<item.icon class="h-4 w-4 shrink-0" />
|
|
95
|
-
{t(item.label)}
|
|
96
|
-
</button>
|
|
97
|
-
{/each}
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
{/each}
|
|
122
|
+
<div class="min-h-full max-w-6xl">
|
|
123
|
+
<div class="mb-6 border-b border-border/70 pb-4">
|
|
124
|
+
<div class="min-w-0">
|
|
125
|
+
<h2 class="text-2xl font-semibold tracking-tight text-foreground">{t("settings.title")}</h2>
|
|
126
|
+
<p class="mt-1 text-sm text-muted-foreground">{t("settings.settingsDescription")}</p>
|
|
101
127
|
</div>
|
|
102
|
-
</
|
|
128
|
+
</div>
|
|
103
129
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{:else if activeKey ===
|
|
115
|
-
<
|
|
130
|
+
<div class="{activeKey === 'access' || activeKey === 'audit' || activeKey === 'developer' ? 'max-w-6xl' : 'max-w-3xl'} space-y-6">
|
|
131
|
+
{#if activeKey === "account"}
|
|
132
|
+
{#if profile}{@render profile()}{:else}<ProfilePage />{/if}
|
|
133
|
+
{#if appearance}{@render appearance()}{:else}<AppearanceSettings />{/if}
|
|
134
|
+
{#if notifications}{@render notifications()}{:else}<NotificationsSettings />{/if}
|
|
135
|
+
{:else if activeKey === "access"}
|
|
136
|
+
{#if security}{@render security()}{:else}<SecuritySettings />{/if}
|
|
137
|
+
{#if authProvider}
|
|
138
|
+
{#if roles}{@render roles()}{:else}<RolesSettings />{/if}
|
|
139
|
+
{/if}
|
|
140
|
+
{:else if activeKey === "developer"}
|
|
141
|
+
{#if integrations}{@render integrations()}{:else}<IntegrationsSettings />{/if}
|
|
142
|
+
{#if api}{@render api()}{:else}<ApiSettings />{/if}
|
|
143
|
+
{:else if activeKey === "audit"}
|
|
144
|
+
{#if audit}{@render audit()}{:else}<AuditLogViewer />{/if}
|
|
145
|
+
{:else if activeKey === "about"}
|
|
146
|
+
{#if about}{@render about()}{:else}<AboutSettings />{/if}
|
|
147
|
+
{:else if content}
|
|
148
|
+
{@render content(activeKey)}
|
|
116
149
|
{/if}
|
|
117
150
|
</div>
|
|
118
151
|
</div>
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Component, Snippet } from "svelte";
|
|
2
|
+
interface SettingsItem {
|
|
3
|
+
key: string;
|
|
4
|
+
path: string;
|
|
5
|
+
icon: Component;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
interface SettingsSection {
|
|
9
|
+
group: string;
|
|
10
|
+
items: SettingsItem[];
|
|
11
|
+
}
|
|
12
|
+
interface Props {
|
|
13
|
+
customSections?: SettingsSection[];
|
|
14
|
+
profile?: Snippet;
|
|
15
|
+
appearance?: Snippet;
|
|
16
|
+
roles?: Snippet;
|
|
17
|
+
security?: Snippet;
|
|
18
|
+
integrations?: Snippet;
|
|
19
|
+
notifications?: Snippet;
|
|
20
|
+
api?: Snippet;
|
|
21
|
+
audit?: Snippet;
|
|
22
|
+
about?: Snippet;
|
|
23
|
+
content?: Snippet<[string]>;
|
|
24
|
+
}
|
|
25
|
+
declare const SettingsPage: Component<Props, {}, "">;
|
|
2
26
|
type SettingsPage = ReturnType<typeof SettingsPage>;
|
|
3
27
|
export default SettingsPage;
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
</PageHeader>
|
|
39
39
|
|
|
40
40
|
{#if query.isLoading}
|
|
41
|
-
<Card.Root class="overflow-hidden border-border/
|
|
42
|
-
<Card.Content class="p-
|
|
41
|
+
<Card.Root class="overflow-hidden border-border/60 bg-card shadow-none" data-svadmin-show-card>
|
|
42
|
+
<Card.Content class="space-y-3 p-4 sm:p-5">
|
|
43
43
|
{#each showFields.slice(0, 6) as _, i (i)}
|
|
44
|
-
<div class="flex flex-col
|
|
44
|
+
<div class="flex flex-col border-b border-border/50 px-1 py-4 sm:flex-row sm:py-4">
|
|
45
45
|
<Skeleton class="h-4 w-1/2 sm:w-1/4" />
|
|
46
46
|
<Skeleton class="h-4 w-3/4 sm:w-2/5 mt-1 sm:mt-0 sm:ml-auto" />
|
|
47
47
|
</div>
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
</Card.Content>
|
|
50
50
|
</Card.Root>
|
|
51
51
|
{:else if query.data?.data}
|
|
52
|
-
<Card.Root class="overflow-hidden border-border/
|
|
53
|
-
<Card.Content class="p-
|
|
52
|
+
<Card.Root class="overflow-hidden border-border/60 bg-card shadow-none" data-svadmin-show-card>
|
|
53
|
+
<Card.Content class="space-y-3 p-4 sm:p-5">
|
|
54
54
|
{#each showFields as field, i (i)}
|
|
55
55
|
{@const value = ((query.data as { data: Record<string, unknown> }).data as Record<string, unknown>)[field.key]}
|
|
56
56
|
{@const DisplayComponent = getDisplayComponent(field.type)}
|
|
57
|
-
<div class="flex flex-col
|
|
58
|
-
<div class="
|
|
59
|
-
<div class="sm:w-2/3
|
|
57
|
+
<div class="flex flex-col border-b border-border/50 px-1 py-4 transition-colors hover:bg-muted/20 sm:flex-row sm:items-start sm:py-4 {i % 2 === 1 ? 'bg-muted/10' : ''}">
|
|
58
|
+
<div class="mb-1 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground sm:mb-0 sm:w-1/3">{field.label}</div>
|
|
59
|
+
<div class="text-sm text-foreground sm:w-2/3">
|
|
60
60
|
{#if DisplayComponent && value != null}
|
|
61
61
|
<DisplayComponent
|
|
62
62
|
{value}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
</Card.Content>
|
|
73
73
|
</Card.Root>
|
|
74
74
|
{:else}
|
|
75
|
-
<Card.Root class="overflow-hidden border-border/
|
|
75
|
+
<Card.Root class="overflow-hidden border-border/60 bg-card shadow-none" data-svadmin-show-card>
|
|
76
76
|
<Card.Content class="p-8 text-center">
|
|
77
77
|
<p class="text-muted-foreground">{t('common.noData')}</p>
|
|
78
78
|
{#if query.isError}
|