From 2cc009d66f9e50d90490255f3cdadbd03df67ba6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 01:44:59 +0000 Subject: [PATCH] Admin Discord studio: editor, live preview, live embeds --- panel/web/src/App.svelte | 3 + panel/web/src/components/EmbedEditor.svelte | 80 ++++++++ panel/web/src/components/EmbedPreview.svelte | 79 ++++++++ panel/web/src/components/Sidebar.svelte | 3 +- panel/web/src/lib/types.ts | 10 + panel/web/src/pages/DiscordStudio.svelte | 189 +++++++++++++++++++ 6 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 panel/web/src/components/EmbedEditor.svelte create mode 100644 panel/web/src/components/EmbedPreview.svelte create mode 100644 panel/web/src/pages/DiscordStudio.svelte diff --git a/panel/web/src/App.svelte b/panel/web/src/App.svelte index 954de30..207b7b8 100644 --- a/panel/web/src/App.svelte +++ b/panel/web/src/App.svelte @@ -18,6 +18,7 @@ import AchievementEditor from './pages/AchievementEditor.svelte'; import LevelingAdmin from './pages/LevelingAdmin.svelte'; import Progression from './pages/Progression.svelte'; + import DiscordStudio from './pages/DiscordStudio.svelte'; import GuildsAdmin from './pages/GuildsAdmin.svelte'; import { get } from './lib/api'; import { route } from './lib/router.svelte'; @@ -99,6 +100,8 @@ {:else if route.name === 'branding'} (brand = b)} /> + {:else if route.name === 'discord'} + {:else if route.name === 'landing-builder'} {:else if route.name === 'settings'} diff --git a/panel/web/src/components/EmbedEditor.svelte b/panel/web/src/components/EmbedEditor.svelte new file mode 100644 index 0000000..1db0261 --- /dev/null +++ b/panel/web/src/components/EmbedEditor.svelte @@ -0,0 +1,80 @@ + + +
+ + + {#if placeholders.length} +
+ Placeholders click to insert +
{#each placeholders as p}{/each}
+
+ {/if} + +
+ + + + + + + + + + + + + +
+ + +
+
Fields
+ {#each style.fields ?? [] as f, i} +
+ + + + +
+ {/each} +
+
+ + diff --git a/panel/web/src/components/EmbedPreview.svelte b/panel/web/src/components/EmbedPreview.svelte new file mode 100644 index 0000000..824f62d --- /dev/null +++ b/panel/web/src/components/EmbedPreview.svelte @@ -0,0 +1,79 @@ + + +
+
{#if body?.avatar_url}{:else}S{/if}
+
+
{body?.username ?? 'SCOPENET'}APPToday
+ {#if body?.content}
{@html md(body.content)}
{/if} + {#if e} +
+
+
+ {#if e.author}
{#if e.author.icon_url}{/if}{e.author.name}
{/if} + {#if e.title}
{e.title}
{/if} + {#if e.description}
{@html md(e.description)}
{/if} + {#if e.fields?.length} +
+ {#each e.fields as f}
{f.name}
{@html md(f.value)}
{/each} +
+ {/if} +
+ {#if e.thumbnail}{/if} +
+ {#if e.image}{/if} + {#if e.footer || e.timestamp} + + {/if} +
+ {/if} +
+
+ + diff --git a/panel/web/src/components/Sidebar.svelte b/panel/web/src/components/Sidebar.svelte index d834a8d..ca39ddd 100644 --- a/panel/web/src/components/Sidebar.svelte +++ b/panel/web/src/components/Sidebar.svelte @@ -1,5 +1,5 @@ + +
+
+
+

Discord

+

Customise the messages the panel posts, and keep live status boards in your channels.{#if data && !data.webhook_set} Add a webhook under Settings → Discord first.{/if}

+
+
+ +
+ + +
+ + {#if data && style} +
+ + +
+ {#if isLive} + {#key current}{/key} + {:else} + {#key current}{/key} + {/if} + + {#if isLive} + {@const c = data.live[current]} +
+

Live settings

+
+ + + {#if current !== 'status'}{/if} + {#if current === 'leaderboard'} + + {/if} + {#if current === 'baltop'} + + {/if} + +
+

{c.posted ? 'The embed is posted and is edited in place on every update.' : 'Not posted yet. Save and press Update now.'}

+
+ {/if} + +
+ + + {#if isLive && data.live[current].posted}{/if} +
+
+ +
+

Preview

+

Built from your real data{isLive ? '' : ' (sample names for announcements)'}.

+ {#if preview}{:else}

Loading preview…

{/if} +
+
+ {:else} +

Loading…

+ {/if} +
+ +