@kyro-cms/admin 0.12.3 → 0.12.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/index.cjs +64 -26
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +64 -26
- package/package.json +8 -2
- package/src/components/ActionBar.tsx +16 -16
- package/src/components/ApiHealth.tsx +522 -0
- package/src/components/ApiKeysManager.tsx +6 -4
- package/src/components/AuditLogsPage.tsx +4 -2
- package/src/components/AutoForm.tsx +10 -7
- package/src/components/BrandingHub.tsx +3 -1
- package/src/components/Dashboard.tsx +44 -37
- package/src/components/DashboardMetrics.tsx +168 -58
- package/src/components/DetailView.tsx +125 -50
- package/src/components/DeveloperCenter.tsx +5 -3
- package/src/components/GraphQLPlayground.tsx +10 -8
- package/src/components/ListView.tsx +66 -45
- package/src/components/LoginPage.tsx +21 -19
- package/src/components/MarketplaceManager.tsx +3 -1
- package/src/components/MediaGallery.tsx +12 -9
- package/src/components/PluginsManager.tsx +6 -4
- package/src/components/RestPlayground.tsx +8 -6
- package/src/components/SessionsManager.tsx +3 -1
- package/src/components/Sidebar.astro +180 -92
- package/src/components/UserManagement.tsx +8 -6
- package/src/components/UserMenu.tsx +19 -17
- package/src/components/VersionHistoryPanel.tsx +6 -4
- package/src/components/WebhookManager.tsx +143 -15
- package/src/components/autoform/AutoFormApiView.tsx +3 -1
- package/src/components/autoform/AutoFormEditView.tsx +5 -3
- package/src/components/autoform/AutoFormHeader.tsx +6 -6
- package/src/components/blocks/AccordionBlock.tsx +5 -3
- package/src/components/blocks/ArrayBlock.tsx +5 -3
- package/src/components/blocks/BlockWrapper.tsx +5 -3
- package/src/components/blocks/CodeBlock.tsx +4 -2
- package/src/components/blocks/FileBlock.tsx +5 -3
- package/src/components/blocks/HeroBlock.tsx +5 -3
- package/src/components/blocks/ImageBlock.tsx +6 -4
- package/src/components/blocks/ListBlock.tsx +5 -3
- package/src/components/blocks/ParagraphBlock.tsx +3 -1
- package/src/components/blocks/RelationshipBlock.tsx +5 -3
- package/src/components/blocks/RichTextBlock.tsx +5 -3
- package/src/components/blocks/VideoBlock.tsx +5 -3
- package/src/components/fields/AccordionField.tsx +10 -51
- package/src/components/fields/ArrayField.tsx +9 -7
- package/src/components/fields/ArrayLayout.tsx +3 -1
- package/src/components/fields/BlocksField.tsx +24 -75
- package/src/components/fields/ButtonField.tsx +3 -1
- package/src/components/fields/CardField.tsx +6 -4
- package/src/components/fields/GroupLayout.tsx +2 -49
- package/src/components/fields/HeadingField.tsx +3 -1
- package/src/components/fields/HeadingSubheadingField.tsx +4 -2
- package/src/components/fields/HeroField.tsx +8 -6
- package/src/components/fields/JSONField.tsx +9 -10
- package/src/components/fields/LinkField.tsx +4 -2
- package/src/components/fields/ListField.tsx +3 -1
- package/src/components/fields/MarkdownField.tsx +3 -17
- package/src/components/fields/RelationshipBlockField.tsx +7 -5
- package/src/components/fields/RelationshipField.tsx +3 -1
- package/src/components/fields/RichTextField.tsx +19 -16
- package/src/components/fields/SecretField.tsx +9 -69
- package/src/components/fields/SelectField.tsx +11 -6
- package/src/components/fields/TabsLayout.tsx +2 -48
- package/src/components/fields/TextField.tsx +9 -7
- package/src/components/fields/UploadField.tsx +3 -1
- package/src/components/fields/VideoField.tsx +6 -4
- package/src/components/ui/BlockDrawer.tsx +3 -1
- package/src/components/ui/CommandPalette.tsx +9 -7
- package/src/components/ui/CommandPaletteWrapper.tsx +3 -1
- package/src/components/ui/IconPickerModal.tsx +4 -2
- package/src/components/ui/PageHeader.tsx +48 -20
- package/src/components/users/UserDetail.tsx +3 -1
- package/src/components/users/UserForm.tsx +5 -3
- package/src/fields/examples/sample-field-2.tsx +3 -1
- package/src/fields/examples/sample-field.tsx +3 -1
- package/src/hooks/useAutoFormState.ts +19 -11
- package/src/integration.ts +21 -0
- package/src/layouts/AdminLayout.astro +252 -189
- package/src/layouts/AuthLayout.astro +52 -31
- package/src/lib/api.ts +7 -7
- package/src/lib/autoform-store.ts +4 -0
- package/src/lib/deep-equal.ts +3 -3
- package/src/lib/i18n.ts +44 -0
- package/src/lib/vite-shim-plugin.ts +3 -0
- package/src/locales/de.json +163 -0
- package/src/locales/en.json +163 -0
- package/src/locales/es.json +163 -0
- package/src/locales/fr.json +163 -0
- package/src/locales/pt.json +163 -0
- package/src/pages/403.astro +2 -1
- package/src/pages/[collection]/[id].astro +23 -10
- package/src/pages/[collection]/index.astro +48 -34
- package/src/pages/audit/index.astro +2 -1
- package/src/pages/graphql-explorer.astro +2 -1
- package/src/pages/graphql.astro +2 -1
- package/src/pages/health.astro +9 -0
- package/src/pages/index.astro +6 -5
- package/src/pages/keys.astro +2 -1
- package/src/pages/marketplace.astro +2 -1
- package/src/pages/media.astro +2 -1
- package/src/pages/plugins.astro +2 -1
- package/src/pages/rest-playground.astro +2 -1
- package/src/pages/roles/index.astro +16 -52
- package/src/pages/sessions.astro +2 -1
- package/src/pages/settings/[slug].astro +45 -30
- package/src/pages/users/[id].astro +1 -0
- package/src/pages/users/index.astro +2 -1
- package/src/pages/users/new.astro +2 -1
- package/src/pages/webhooks.astro +2 -1
- package/src/pages/index_ALT.astro +0 -3
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from '../../layouts/AdminLayout.astro';
|
|
3
|
+
import i18next from '../../lib/i18n';
|
|
3
4
|
import { AuditLogsPage } from '../../components/AuditLogsPage';
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from '../../lib/paths';
|
|
6
7
|
---
|
|
7
8
|
|
|
8
|
-
<AdminLayout title="Audit Logs">
|
|
9
|
+
<AdminLayout title={i18next.t("pages." + "Audit Logs".replace(/ /g, ""), { defaultValue: "Audit Logs" })}>
|
|
9
10
|
<AuditLogsPage client:only="react" />
|
|
10
11
|
</AdminLayout>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { GraphQLPlayground } from "../components/GraphQLPlayground";
|
|
4
5
|
import { apiPath } from "../lib/paths";
|
|
5
6
|
import { getGlobal } from "../lib/globals";
|
|
@@ -9,7 +10,7 @@ const apiAccess = accessSettings?.apiAccess || {};
|
|
|
9
10
|
const graphqlEnabled = apiAccess.graphqlEnabled !== false;
|
|
10
11
|
---
|
|
11
12
|
|
|
12
|
-
<AdminLayout title="GraphQL Explorer">
|
|
13
|
+
<AdminLayout title={i18next.t("pages." + "GraphQL Explorer".replace(/ /g, ""), { defaultValue: "GraphQL Explorer" })}>
|
|
13
14
|
<div class="flex-1 overflow-hidden h-[calc(100vh-64px)] md:h-[calc(100vh-80px)]">
|
|
14
15
|
{graphqlEnabled ? (
|
|
15
16
|
<GraphQLPlayground
|
package/src/pages/graphql.astro
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { GraphQLPlayground } from "../components/GraphQLPlayground";
|
|
4
5
|
import { apiPath } from "../lib/paths";
|
|
5
6
|
import { getGlobal } from "../lib/globals";
|
|
@@ -13,7 +14,7 @@ const params = new URL(url).searchParams;
|
|
|
13
14
|
const initialQuery = params.get("query") || "";
|
|
14
15
|
---
|
|
15
16
|
|
|
16
|
-
<AdminLayout title="GraphQL Playground">
|
|
17
|
+
<AdminLayout title={i18next.t("pages." + "GraphQL Playground".replace(/ /g, ""), { defaultValue: "GraphQL Playground" })}>
|
|
17
18
|
<div class="flex-1 overflow-hidden h-[calc(100vh-64px)] md:h-[calc(100vh-80px)]">
|
|
18
19
|
{graphqlEnabled ? (
|
|
19
20
|
<GraphQLPlayground
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
4
|
+
import { ApiHealth } from "../components/ApiHealth";
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<AdminLayout title={i18next.t("pages." + "API Health".replace(/ /g, ""), { defaultValue: "API Health" })}>
|
|
8
|
+
<ApiHealth client:only="react" />
|
|
9
|
+
</AdminLayout>
|
package/src/pages/index.astro
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { collections } from "../lib/config";
|
|
4
5
|
const authCollections = ["users", "audit_logs"];
|
|
5
6
|
import { adminPath, apiPath } from "../lib/paths";
|
|
6
|
-
import { DashboardMetrics } from "../components/DashboardMetrics";
|
|
7
|
+
import { DashboardMetrics, RevenueChart } from "../components/DashboardMetrics";
|
|
7
8
|
|
|
8
9
|
const authItems = authCollections.map((slug) => ({
|
|
9
10
|
slug,
|
|
@@ -12,7 +13,7 @@ const authItems = authCollections.map((slug) => ({
|
|
|
12
13
|
}));
|
|
13
14
|
---
|
|
14
15
|
|
|
15
|
-
<AdminLayout title="Dashboard">
|
|
16
|
+
<AdminLayout title={i18next.t("pages." + "Dashboard".replace(/ /g, ""), { defaultValue: "Dashboard" })}>
|
|
16
17
|
<div class="flex-1 overflow-y-auto space-y-8">
|
|
17
18
|
<!-- Header -->
|
|
18
19
|
<div class="surface-tile p-6 flex items-center justify-between gap-8">
|
|
@@ -50,7 +51,8 @@ const authItems = authCollections.map((slug) => ({
|
|
|
50
51
|
</div>
|
|
51
52
|
|
|
52
53
|
<!-- CMS Metrics -->
|
|
53
|
-
<DashboardMetrics client:load />
|
|
54
|
+
<DashboardMetrics client:load isEcommerce={!!collections['orders'] || !!collections['products']} />
|
|
55
|
+
{(!!collections['orders'] || !!collections['products']) && <RevenueChart client:load />}
|
|
54
56
|
|
|
55
57
|
<!-- Quick Links Section -->
|
|
56
58
|
<div class="surface-tile overflow-hidden mt-8">
|
|
@@ -151,8 +153,7 @@ const authItems = authCollections.map((slug) => ({
|
|
|
151
153
|
</a>
|
|
152
154
|
|
|
153
155
|
<a
|
|
154
|
-
href={`${
|
|
155
|
-
target="_blank"
|
|
156
|
+
href={`${adminPath}/health`}
|
|
156
157
|
class="p-5 bg-[var(--kyro-surface-accent)] rounded-lg hover:bg-[var(--kyro-surface-accent)] transition-all border border-transparent hover:border-[var(--kyro-border)] group"
|
|
157
158
|
>
|
|
158
159
|
<div class="w-10 h-10 rounded-lg bg-green-500/10 text-green-500 flex items-center justify-center mb-3">
|
package/src/pages/keys.astro
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { ApiKeysManager } from "../components/ApiKeysManager";
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from '../lib/paths';
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
9
|
-
<AdminLayout title="API Keys">
|
|
10
|
+
<AdminLayout title={i18next.t("pages." + "API Keys".replace(/ /g, ""), { defaultValue: "API Keys" })}>
|
|
10
11
|
<ApiKeysManager client:only="react" />
|
|
11
12
|
</AdminLayout>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { MarketplaceManager } from "../components/MarketplaceManager";
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from '../lib/paths';
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
9
|
-
<AdminLayout title="Marketplace">
|
|
10
|
+
<AdminLayout title={i18next.t("pages." + "Marketplace".replace(/ /g, ""), { defaultValue: "Marketplace" })}>
|
|
10
11
|
<MarketplaceManager client:only="react" />
|
|
11
12
|
</AdminLayout>
|
package/src/pages/media.astro
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from '../layouts/AdminLayout.astro';
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { MediaGallery } from '../components/MediaGallery';
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from '../lib/paths';
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
9
|
-
<AdminLayout title="Media Library">
|
|
10
|
+
<AdminLayout title={i18next.t("pages." + "Media Library".replace(/ /g, ""), { defaultValue: "Media Library" })}>
|
|
10
11
|
<div class="flex-1 flex flex-col h-full min-h-0 overflow-hidden -m-4 md:m-0">
|
|
11
12
|
<MediaGallery client:load />
|
|
12
13
|
</div>
|
package/src/pages/plugins.astro
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { PluginsManager } from "../components/PluginsManager";
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
<AdminLayout title="Plugins">
|
|
7
|
+
<AdminLayout title={i18next.t("pages." + "Plugins".replace(/ /g, ""), { defaultValue: "Plugins" })}>
|
|
7
8
|
<PluginsManager client:only="react" />
|
|
8
9
|
</AdminLayout>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { RestPlayground } from "../components/RestPlayground";
|
|
4
5
|
import { apiPath } from "../lib/paths";
|
|
5
6
|
|
|
@@ -10,7 +11,7 @@ const collectionsData = await collectionsResponse.json();
|
|
|
10
11
|
const collections = collectionsData.collections || [];
|
|
11
12
|
---
|
|
12
13
|
|
|
13
|
-
<AdminLayout title="REST Playground">
|
|
14
|
+
<AdminLayout title={i18next.t("pages." + "REST Playground".replace(/ /g, ""), { defaultValue: "REST Playground" })}>
|
|
14
15
|
<div class="flex-1 overflow-hidden h-[calc(100vh-64px)] md:h-[calc(100vh-80px)]">
|
|
15
16
|
<RestPlayground client:load collections={collections} />
|
|
16
17
|
</div>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../../layouts/AdminLayout.astro";
|
|
3
|
-
|
|
4
|
-
import { adminPath, apiPath } from "../../lib/paths";
|
|
3
|
+
import i18next from "../../lib/i18n";
|
|
5
4
|
|
|
6
5
|
const defaultRoles = [
|
|
7
6
|
{
|
|
@@ -37,8 +36,7 @@ const defaultRoles = [
|
|
|
37
36
|
level: 30,
|
|
38
37
|
inherits: [],
|
|
39
38
|
description: "Access own data and make purchases",
|
|
40
|
-
color:
|
|
41
|
-
"bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] border-[var(--kyro-border)]",
|
|
39
|
+
color: "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] border-[var(--kyro-border)]",
|
|
42
40
|
},
|
|
43
41
|
{
|
|
44
42
|
name: "guest",
|
|
@@ -59,15 +57,11 @@ const permissions: Record<string, string[]> = {
|
|
|
59
57
|
};
|
|
60
58
|
---
|
|
61
59
|
|
|
62
|
-
<AdminLayout title="Roles">
|
|
63
|
-
<div class="flex-1 overflow-y-auto
|
|
60
|
+
<AdminLayout title={i18next.t("pages." + "Roles".replace(/ /g, ""), { defaultValue: "Roles" })}>
|
|
61
|
+
<div class="flex-1 overflow-y-auto space-y-8">
|
|
64
62
|
<!-- Header -->
|
|
65
63
|
<div class="surface-tile p-6">
|
|
66
|
-
<h1
|
|
67
|
-
class="text-xl font-bold tracking-tighter text-[var(--kyro-text-primary)]"
|
|
68
|
-
>
|
|
69
|
-
Roles & Permissions
|
|
70
|
-
</h1>
|
|
64
|
+
<h1 class="text-xl font-bold tracking-tighter text-[var(--kyro-text-primary)]">Roles & Permissions</h1>
|
|
71
65
|
<p class="text-sm text-[var(--kyro-text-secondary)] mt-1 font-regular">
|
|
72
66
|
Role-based access control with hierarchical permissions
|
|
73
67
|
</p>
|
|
@@ -77,22 +71,14 @@ const permissions: Record<string, string[]> = {
|
|
|
77
71
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
78
72
|
{
|
|
79
73
|
defaultRoles.map((role) => (
|
|
80
|
-
<div
|
|
81
|
-
class={`surface-tile p-6 border-2 ${role.color.split(" ").slice(2).join(" ")} rounded-2xl`}
|
|
82
|
-
>
|
|
74
|
+
<div class={`surface-tile p-6 border-2 ${role.color.split(" ").slice(2).join(" ")} rounded-2xl`}>
|
|
83
75
|
<div class="flex items-center justify-between mb-4">
|
|
84
|
-
<h3 class="text-xl font-bold text-[var(--kyro-text-primary)] tracking-tighter">
|
|
85
|
-
|
|
86
|
-
</h3>
|
|
87
|
-
<span
|
|
88
|
-
class={`px-3 py-1 rounded-lg text-xs font-bold ${role.color.split(" ").slice(0, 2).join(" ")}`}
|
|
89
|
-
>
|
|
76
|
+
<h3 class="text-xl font-bold text-[var(--kyro-text-primary)] tracking-tighter">{role.name}</h3>
|
|
77
|
+
<span class={`px-3 py-1 rounded-lg text-xs font-bold ${role.color.split(" ").slice(0, 2).join(" ")}`}>
|
|
90
78
|
Level {role.level}
|
|
91
79
|
</span>
|
|
92
80
|
</div>
|
|
93
|
-
<p class="text-sm text-[var(--kyro-text-secondary)] mb-4">
|
|
94
|
-
{role.description}
|
|
95
|
-
</p>
|
|
81
|
+
<p class="text-sm text-[var(--kyro-text-secondary)] mb-4">{role.description}</p>
|
|
96
82
|
{role.inherits.length > 0 && (
|
|
97
83
|
<div class="mb-4">
|
|
98
84
|
<span class="text-xs font-bold text-[var(--kyro-text-secondary)] tracking-[0.1em] opacity-50">
|
|
@@ -126,14 +112,8 @@ const permissions: Record<string, string[]> = {
|
|
|
126
112
|
|
|
127
113
|
<!-- Permission Matrix -->
|
|
128
114
|
<div class="surface-tile overflow-hidden">
|
|
129
|
-
<div
|
|
130
|
-
class="
|
|
131
|
-
>
|
|
132
|
-
<h2
|
|
133
|
-
class="text-xl font-bold text-[var(--kyro-text-primary)] tracking-tighter"
|
|
134
|
-
>
|
|
135
|
-
Permission Matrix
|
|
136
|
-
</h2>
|
|
115
|
+
<div class="p-6 border-b border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]">
|
|
116
|
+
<h2 class="text-xl font-bold text-[var(--kyro-text-primary)] tracking-tighter">Permission Matrix</h2>
|
|
137
117
|
</div>
|
|
138
118
|
<table class="w-full text-left">
|
|
139
119
|
<thead>
|
|
@@ -141,11 +121,7 @@ const permissions: Record<string, string[]> = {
|
|
|
141
121
|
class="text-[var(--kyro-text-secondary)] font-bold text-[10px] tracking-[0.3em] border-b border-[var(--kyro-border)]"
|
|
142
122
|
>
|
|
143
123
|
<th class="px-6 py-4">Resource</th>
|
|
144
|
-
{
|
|
145
|
-
defaultRoles.map((role) => (
|
|
146
|
-
<th class="px-4 py-4 text-center">{role.name}</th>
|
|
147
|
-
))
|
|
148
|
-
}
|
|
124
|
+
{defaultRoles.map((role) => <th class="px-4 py-4 text-center">{role.name}</th>)}
|
|
149
125
|
</tr>
|
|
150
126
|
</thead>
|
|
151
127
|
<tbody class="divide-y divide-[var(--kyro-border)]">
|
|
@@ -171,24 +147,16 @@ const permissions: Record<string, string[]> = {
|
|
|
171
147
|
{ resource: "Audit Logs", actions: ["read"] },
|
|
172
148
|
].map((row) => (
|
|
173
149
|
<tr class="hover:bg-[var(--kyro-surface-accent)] transition-colors">
|
|
174
|
-
<td class="px-6 py-4 font-medium text-[var(--kyro-text-primary)]">
|
|
175
|
-
{row.resource}
|
|
176
|
-
</td>
|
|
150
|
+
<td class="px-6 py-4 font-medium text-[var(--kyro-text-primary)]">{row.resource}</td>
|
|
177
151
|
{defaultRoles.map((role) => {
|
|
178
152
|
const hasAll = permissions[role.name]?.includes("*");
|
|
179
153
|
const hasResource = permissions[role.name]?.some(
|
|
180
|
-
(p) =>
|
|
181
|
-
p.startsWith(row.resource.toLowerCase() + ":") ||
|
|
182
|
-
p === "*",
|
|
154
|
+
(p) => p.startsWith(row.resource.toLowerCase() + ":") || p === "*",
|
|
183
155
|
);
|
|
184
156
|
return (
|
|
185
157
|
<td class="px-4 py-4 text-center">
|
|
186
158
|
{hasAll || hasResource ? (
|
|
187
|
-
<svg
|
|
188
|
-
class="w-5 h-5 text-green-500 mx-auto"
|
|
189
|
-
fill="currentColor"
|
|
190
|
-
viewBox="0 0 20 20"
|
|
191
|
-
>
|
|
159
|
+
<svg class="w-5 h-5 text-green-500 mx-auto" fill="currentColor" viewBox="0 0 20 20">
|
|
192
160
|
<path
|
|
193
161
|
fill-rule="evenodd"
|
|
194
162
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
|
@@ -196,11 +164,7 @@ const permissions: Record<string, string[]> = {
|
|
|
196
164
|
/>
|
|
197
165
|
</svg>
|
|
198
166
|
) : (
|
|
199
|
-
<svg
|
|
200
|
-
class="w-5 h-5 text-[var(--kyro-border)] mx-auto"
|
|
201
|
-
fill="currentColor"
|
|
202
|
-
viewBox="0 0 20 20"
|
|
203
|
-
>
|
|
167
|
+
<svg class="w-5 h-5 text-[var(--kyro-border)] mx-auto" fill="currentColor" viewBox="0 0 20 20">
|
|
204
168
|
<path
|
|
205
169
|
fill-rule="evenodd"
|
|
206
170
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
package/src/pages/sessions.astro
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { SessionsManager } from "../components/SessionsManager";
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
<AdminLayout title="Sessions">
|
|
7
|
+
<AdminLayout title={i18next.t("pages." + "Sessions".replace(/ /g, ""), { defaultValue: "Sessions" })}>
|
|
7
8
|
<SessionsManager client:only="react" />
|
|
8
9
|
</AdminLayout>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../../lib/i18n';
|
|
3
4
|
import { globals } from "../../lib/config";
|
|
4
5
|
import { SettingsPage } from "../../components/SettingsPage";
|
|
6
|
+
import { getGlobal } from "../../lib/globals";
|
|
5
7
|
|
|
6
8
|
import { adminPath } from "../../lib/paths";
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
const slug = Astro.props.slug || Astro.params.slug || Astro.params.id;
|
|
9
11
|
|
|
10
12
|
// Validate global exists
|
|
11
13
|
if (!slug || !globals[slug]) {
|
|
@@ -13,6 +15,7 @@ if (!slug || !globals[slug]) {
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
const config = globals[slug];
|
|
18
|
+
const data = (await getGlobal(slug, { request: Astro.request })) || {};
|
|
16
19
|
const hasVersioning = !!config.versions;
|
|
17
20
|
|
|
18
21
|
const activeSlug = slug;
|
|
@@ -20,14 +23,13 @@ const allGlobals = Object.values(globals);
|
|
|
20
23
|
|
|
21
24
|
const title = config.label || slug;
|
|
22
25
|
const description =
|
|
23
|
-
config.admin?.description ||
|
|
26
|
+
(config as any).admin?.description ||
|
|
24
27
|
`Manage your ${title.toLowerCase()} configurations.`;
|
|
25
28
|
---
|
|
26
29
|
|
|
27
30
|
<AdminLayout title={`Settings - ${title}`}>
|
|
28
31
|
<div class="flex-1 overflow-y-auto">
|
|
29
32
|
{ !hasVersioning && (
|
|
30
|
-
<!-- Standard Header (Only if no versioning/AutoForm header) -->
|
|
31
33
|
<div class="surface-tile p-8 pb-0 mb-6">
|
|
32
34
|
<div class="flex items-center justify-between mb-8">
|
|
33
35
|
<div>
|
|
@@ -94,6 +96,7 @@ const description =
|
|
|
94
96
|
config={config}
|
|
95
97
|
globalSlug={slug}
|
|
96
98
|
layout={hasVersioning ? "split" : "single"}
|
|
99
|
+
data={data}
|
|
97
100
|
/>
|
|
98
101
|
<input type="hidden" id="form-data" name="form-data" value="{}" />
|
|
99
102
|
</form>
|
|
@@ -101,34 +104,46 @@ const description =
|
|
|
101
104
|
</div>
|
|
102
105
|
|
|
103
106
|
<script>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
const initSettingsPage = () => {
|
|
108
|
+
console.log("[Astro] Settings page init");
|
|
109
|
+
const saveBtn = document.getElementById("settings-save-btn");
|
|
110
|
+
|
|
111
|
+
saveBtn?.addEventListener("click", () => {
|
|
112
|
+
console.log("[Astro] Header save clicked");
|
|
113
|
+
const btn = document.getElementById("btn-save");
|
|
114
|
+
if (btn) {
|
|
115
|
+
console.log("[Astro] Triggering hidden button click");
|
|
116
|
+
btn.click();
|
|
117
|
+
} else {
|
|
118
|
+
console.error("[Astro] Hidden save button not found!");
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
};
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
if (saveBtn) {
|
|
120
|
-
saveBtn.disabled = true;
|
|
121
|
-
saveBtn.innerHTML = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>Saving...`;
|
|
122
|
-
saveBtn.classList.add("opacity-50", "cursor-wait");
|
|
123
|
-
}
|
|
124
|
-
});
|
|
123
|
+
document.addEventListener("astro:page-load", initSettingsPage);
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
saveBtn.
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
// Global listeners should only be attached once
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
if (!window.__kyroSettingsGlobalListenersAttached) {
|
|
128
|
+
window.addEventListener("kyro:global-save-start", () => {
|
|
129
|
+
const saveBtn = document.getElementById("settings-save-btn");
|
|
130
|
+
if (saveBtn) {
|
|
131
|
+
saveBtn.setAttribute("disabled", "true");
|
|
132
|
+
saveBtn.innerHTML = `<svg class="animate-spin -ml-1 mr-2 h-4 w-4 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>Saving...`;
|
|
133
|
+
saveBtn.classList.add("opacity-50", "cursor-wait");
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
window.addEventListener("kyro:global-save-end", () => {
|
|
138
|
+
const saveBtn = document.getElementById("settings-save-btn");
|
|
139
|
+
if (saveBtn) {
|
|
140
|
+
saveBtn.removeAttribute("disabled");
|
|
141
|
+
saveBtn.innerHTML = "Save Changes";
|
|
142
|
+
saveBtn.classList.remove("opacity-50", "cursor-wait");
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// @ts-ignore
|
|
146
|
+
window.__kyroSettingsGlobalListenersAttached = true;
|
|
147
|
+
}
|
|
133
148
|
</script>
|
|
134
149
|
</AdminLayout>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../../lib/i18n';
|
|
3
4
|
import { UsersList } from "../../components/users/UsersList";
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from "../../lib/paths";
|
|
@@ -25,7 +26,7 @@ try {
|
|
|
25
26
|
}
|
|
26
27
|
---
|
|
27
28
|
|
|
28
|
-
<AdminLayout title="Users">
|
|
29
|
+
<AdminLayout title={i18next.t("pages." + "Users".replace(/ /g, ""), { defaultValue: "Users" })}>
|
|
29
30
|
<UsersList
|
|
30
31
|
client:load
|
|
31
32
|
initialUsers={users}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../../lib/i18n';
|
|
3
4
|
import { UserForm } from "../../components/users/UserForm";
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from "../../lib/paths";
|
|
6
7
|
---
|
|
7
8
|
|
|
8
|
-
<AdminLayout title="New User">
|
|
9
|
+
<AdminLayout title={i18next.t("pages." + "New User".replace(/ /g, ""), { defaultValue: "New User" })}>
|
|
9
10
|
<UserForm
|
|
10
11
|
client:load
|
|
11
12
|
mode="create"
|
package/src/pages/webhooks.astro
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
import AdminLayout from "../layouts/AdminLayout.astro";
|
|
3
|
+
import i18next from '../lib/i18n';
|
|
3
4
|
import { WebhookManager } from "../components/WebhookManager";
|
|
4
5
|
|
|
5
6
|
import { adminPath, apiPath } from '../lib/paths';
|
|
6
7
|
|
|
7
8
|
---
|
|
8
9
|
|
|
9
|
-
<AdminLayout title="Webhooks">
|
|
10
|
+
<AdminLayout title={i18next.t("pages." + "Webhooks".replace(/ /g, ""), { defaultValue: "Webhooks" })}>
|
|
10
11
|
<WebhookManager client:only="react" />
|
|
11
12
|
</AdminLayout>
|