diff --git a/dashboard/frontend/src/App.svelte b/dashboard/frontend/src/App.svelte index 7262c2e..e0dd134 100644 --- a/dashboard/frontend/src/App.svelte +++ b/dashboard/frontend/src/App.svelte @@ -123,12 +123,12 @@ {:else if !authorized} {:else} -
+
- {#if page === "dashboard" && hasPageAccess("dashboard")} diff --git a/dashboard/frontend/src/app.css b/dashboard/frontend/src/app.css index 28e114e..2b967ac 100644 --- a/dashboard/frontend/src/app.css +++ b/dashboard/frontend/src/app.css @@ -22,6 +22,7 @@ --color-surface-700: #334155; --color-surface-800: #1e293b; --color-surface-900: #0f172a; + --color-surface-950: #020617; --color-emerald-400: #34d399; --color-emerald-500: #10b981; @@ -57,8 +58,10 @@ body { ::-webkit-scrollbar-thumb:hover { background: var(--color-surface-400); } /* Dark mode overrides */ -.dark body, -.dark { - background: var(--color-surface-900); +html.dark body { + background: var(--color-surface-950); color: var(--color-surface-200); } + +html.dark ::-webkit-scrollbar-thumb { background: var(--color-surface-600); } +html.dark ::-webkit-scrollbar-thumb:hover { background: var(--color-surface-500); } diff --git a/dashboard/frontend/src/components/Sidebar.svelte b/dashboard/frontend/src/components/Sidebar.svelte index 95cc5ea..e932b35 100644 --- a/dashboard/frontend/src/components/Sidebar.svelte +++ b/dashboard/frontend/src/components/Sidebar.svelte @@ -69,6 +69,7 @@ // Drag-and-drop state let dragCategory = $state(null); let dragIndex = $state(-1); + let dropCategory = $state(null); let dropIndex = $state(-1); function handleDragStart(category, index, e) { @@ -79,26 +80,49 @@ } function handleDragOver(category, index, e) { - if (category !== dragCategory) return; e.preventDefault(); e.dataTransfer.dropEffect = "move"; + dropCategory = category; dropIndex = index; } function handleDragEnd() { dragCategory = null; dragIndex = -1; + dropCategory = null; dropIndex = -1; } function handleDrop(category, index, e) { e.preventDefault(); - if (category !== dragCategory || dragIndex === index) { handleDragEnd(); return; } + if (dragCategory === null) { handleDragEnd(); return; } + if (dragCategory === category && dragIndex === index) { handleDragEnd(); return; } const lists = { main: [...links], media: [...media], tools: [...tools] }; - const list = lists[category]; - const [moved] = list.splice(dragIndex, 1); - list.splice(index, 0, moved); - lists[category] = list; + const [moved] = lists[dragCategory].splice(dragIndex, 1); + lists[category].splice(index, 0, moved); + const newOrder = { + main: lists.main.map(itemKey), + media: lists.media.map(itemKey), + tools: lists.tools.map(itemKey), + }; + onOrderChange(newOrder); + handleDragEnd(); + } + + // Allow dropping at end of a category (on the section divider/header area) + function handleCategoryDragOver(category, e) { + e.preventDefault(); + e.dataTransfer.dropEffect = "move"; + dropCategory = category; + dropIndex = -1; + } + + function handleCategoryDrop(category, e) { + e.preventDefault(); + if (dragCategory === null) { handleDragEnd(); return; } + const lists = { main: [...links], media: [...media], tools: [...tools] }; + const [moved] = lists[dragCategory].splice(dragIndex, 1); + lists[category].push(moved); const newOrder = { main: lists.main.map(itemKey), media: lists.media.map(itemKey), @@ -124,9 +148,8 @@ } function dragClasses(category, index) { - if (dragCategory !== category) return ""; - if (index === dragIndex) return "opacity-30"; - if (index === dropIndex) return "border-t-2 border-primary-500"; + if (dragCategory === category && index === dragIndex) return "opacity-30"; + if (dropCategory === category && index === dropIndex) return "border-t-2 border-primary-500"; return ""; } @@ -150,7 +173,7 @@
-

Media

+

handleCategoryDragOver("media", e)} ondrop={(e) => handleCategoryDrop("media", e)}>Media

{#each media as svc, i}
-

Tools

+

handleCategoryDragOver("tools", e)} ondrop={(e) => handleCategoryDrop("tools", e)}>Tools

{#each tools as item, i} {#if canAccess(item.id)} {#if item.external || item.port} diff --git a/dashboard/frontend/src/routes/Dashboard.svelte b/dashboard/frontend/src/routes/Dashboard.svelte index 9fc7d66..ab712af 100644 --- a/dashboard/frontend/src/routes/Dashboard.svelte +++ b/dashboard/frontend/src/routes/Dashboard.svelte @@ -40,21 +40,21 @@
-

Overview

+

Overview

System status at a glance

{#if loading}
{#each Array(4) as _} -
+
{/each}
{:else}
-
+

CPU

@@ -66,7 +66,7 @@
-
+

Memory

@@ -78,7 +78,7 @@
-
+

Disk

@@ -90,14 +90,14 @@
-
+

Uptime

-

{stats?.uptime || "—"}

+

{stats?.uptime || "—"}

{stats?.platform || "—"}

@@ -105,9 +105,9 @@
-
+
-

Docker Containers

+

Docker Containers

{containers.filter(c => c.status === "running").length}/{containers.length} running
@@ -115,7 +115,7 @@
- {c.name} + {c.name}
{c.image}
@@ -127,9 +127,9 @@
-
+
-

Git Repositories

+

Git Repositories

{repos.length} repos
@@ -137,7 +137,7 @@
- {r.name} + {r.name}
{r.language || "—"}
@@ -151,8 +151,8 @@ {#if stats?.volumes?.length} -
-

Storage Usage

+
+

Storage Usage

{#each stats.volumes as vol}
@@ -160,7 +160,7 @@ {vol.mount} {vol.percent}%
-
+
-

Docker

+

Docker

{containers.length} containers · {containers.filter(c => c.status === "running").length} running

{:else} - + {e.name} diff --git a/dashboard/frontend/src/routes/Gitea.svelte b/dashboard/frontend/src/routes/Gitea.svelte index c97a5c5..85b7103 100644 --- a/dashboard/frontend/src/routes/Gitea.svelte +++ b/dashboard/frontend/src/routes/Gitea.svelte @@ -41,26 +41,26 @@
-

Repositories

+

Repositories

{repos.length} repositories on Gitea

{#if loading}
{#each Array(4) as _} -
+
{/each}
{:else}
{#each repos as r}