fix: comprehensive dark mode support across all pages
Deploy Dashboard (Dev) / deploy-dev (push) Successful in 1m11s

- Fix body/html dark background to surface-950
- Add dark scrollbar styling
- Fix App.svelte wrapper to use Tailwind dark: classes instead of conditional strings
- Add dark:bg-surface-800 and dark:border-surface-700 to all cards in Dashboard, Docker, Files, Gitea
- Add dark text variants for headings, labels, and content text
- Add dark hover states for interactive elements
- Enable cross-category sidebar drag-and-drop
This commit is contained in:
Gan, Jimmy
2026-03-01 14:59:23 +08:00
parent a8debcfb4b
commit 62856c9343
8 changed files with 84 additions and 58 deletions
+2 -2
View File
@@ -123,12 +123,12 @@
{:else if !authorized}
<Login />
{:else}
<div class="flex h-screen overflow-hidden bg-surface-50 {dark ? 'dark bg-surface-900' : ''}">
<div class="flex h-screen overflow-hidden bg-surface-50 dark:bg-surface-900">
<Sidebar bind:page {dark} {toggleTheme} {logout} bind:sidebarOpen {allowedPages} {userRole} {sidebarOrder} onOrderChange={handleOrderChange} />
<main class="flex-1 overflow-auto">
<div class="max-w-[1400px] mx-auto p-6 lg:p-8">
<!-- Mobile hamburger -->
<button class="md:hidden mb-4 p-2 rounded-lg hover:bg-surface-200 {dark ? 'hover:bg-surface-700 text-surface-300' : 'text-surface-600'}" onclick={() => sidebarOpen = true} aria-label="Open menu">
<button class="md:hidden mb-4 p-2 rounded-lg text-surface-600 dark:text-surface-300 hover:bg-surface-200 dark:hover:bg-surface-700" onclick={() => sidebarOpen = true} aria-label="Open menu">
<svg class="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" /></svg>
</button>
{#if page === "dashboard" && hasPageAccess("dashboard")}
+6 -3
View File
@@ -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); }
@@ -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 "";
}
</script>
@@ -150,7 +173,7 @@
<!-- Nav Links -->
<nav class="flex-1 px-3 mt-2 overflow-y-auto">
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Main</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("main", e)} ondrop={(e) => handleCategoryDrop("main", e)}>Main</p>
{#each links as link, i}
{#if canAccess(link.id)}
<button
@@ -186,7 +209,7 @@
{/each}
<div class="my-4 border-t border-surface-200 {dark ? 'border-surface-700' : ''}"></div>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Media</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("media", e)} ondrop={(e) => handleCategoryDrop("media", e)}>Media</p>
{#each media as svc, i}
<a
href={extHref(svc)}
@@ -217,7 +240,7 @@
{/each}
<div class="my-4 border-t border-surface-200 {dark ? 'border-surface-700' : ''}"></div>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2">Tools</p>
<p class="text-[10px] font-semibold uppercase tracking-wider text-surface-400 px-3 mb-2" ondragover={(e) => handleCategoryDragOver("tools", e)} ondrop={(e) => handleCategoryDrop("tools", e)}>Tools</p>
{#each tools as item, i}
{#if canAccess(item.id)}
{#if item.external || item.port}
+16 -16
View File
@@ -40,21 +40,21 @@
<div class="space-y-8">
<div>
<h1 class="text-2xl font-bold text-surface-900 tracking-tight">Overview</h1>
<h1 class="text-2xl font-bold text-surface-900 dark:text-white tracking-tight">Overview</h1>
<p class="text-sm text-surface-400 mt-1">System status at a glance</p>
</div>
{#if loading}
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{#each Array(4) as _}
<div class="h-[120px] rounded-xl bg-surface-100 animate-pulse"></div>
<div class="h-[120px] rounded-xl bg-surface-100 dark:bg-surface-800 animate-pulse"></div>
{/each}
</div>
{:else}
<!-- Stats Cards -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- CPU -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold uppercase tracking-wider text-surface-400">CPU</p>
<div class="w-8 h-8 rounded-lg bg-sky-50 flex items-center justify-center">
@@ -66,7 +66,7 @@
</div>
<!-- Memory -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold uppercase tracking-wider text-surface-400">Memory</p>
<div class="w-8 h-8 rounded-lg bg-violet-50 flex items-center justify-center">
@@ -78,7 +78,7 @@
</div>
<!-- Disk -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold uppercase tracking-wider text-surface-400">Disk</p>
<div class="w-8 h-8 rounded-lg bg-amber-50 flex items-center justify-center">
@@ -90,14 +90,14 @@
</div>
<!-- Uptime -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm hover:shadow-md transition-shadow duration-200">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold uppercase tracking-wider text-surface-400">Uptime</p>
<div class="w-8 h-8 rounded-lg bg-emerald-50 flex items-center justify-center">
<svg class="w-4 h-4 text-emerald-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" /></svg>
</div>
</div>
<p class="text-2xl font-bold text-surface-800">{stats?.uptime || "—"}</p>
<p class="text-2xl font-bold text-surface-800 dark:text-surface-100">{stats?.uptime || "—"}</p>
<p class="text-xs text-surface-400 mt-1 truncate" title={stats?.platform}>{stats?.platform || "—"}</p>
</div>
</div>
@@ -105,9 +105,9 @@
<!-- Services Grid -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
<!-- Docker Summary -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-semibold text-surface-700">Docker Containers</h3>
<h3 class="text-sm font-semibold text-surface-700 dark:text-surface-200">Docker Containers</h3>
<span class="text-xs font-medium text-emerald-600 bg-emerald-50 px-2 py-0.5 rounded-full">{containers.filter(c => c.status === "running").length}/{containers.length} running</span>
</div>
<div class="space-y-2">
@@ -115,7 +115,7 @@
<div class="flex items-center justify-between py-1.5 text-sm">
<div class="flex items-center gap-2">
<span class="w-1.5 h-1.5 rounded-full {c.status !== 'running' ? 'bg-surface-300' : c.health === 'unhealthy' ? 'bg-rose-400' : c.health === 'healthy' ? 'bg-emerald-400' : 'bg-sky-400'}"></span>
<span class="font-medium text-surface-700">{c.name}</span>
<span class="font-medium text-surface-700 dark:text-surface-200">{c.name}</span>
</div>
<span class="text-xs text-surface-400 truncate max-w-[180px]">{c.image}</span>
</div>
@@ -127,9 +127,9 @@
</div>
<!-- Repos Summary -->
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm">
<div class="flex items-center justify-between mb-4">
<h3 class="text-sm font-semibold text-surface-700">Git Repositories</h3>
<h3 class="text-sm font-semibold text-surface-700 dark:text-surface-200">Git Repositories</h3>
<span class="text-xs font-medium text-primary-600 bg-primary-50 px-2 py-0.5 rounded-full">{repos.length} repos</span>
</div>
<div class="space-y-2">
@@ -137,7 +137,7 @@
<div class="flex items-center justify-between py-1.5 text-sm">
<div class="flex items-center gap-2">
<svg class="w-3.5 h-3.5 text-surface-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" /></svg>
<span class="font-medium text-surface-700">{r.name}</span>
<span class="font-medium text-surface-700 dark:text-surface-200">{r.name}</span>
</div>
<span class="text-xs text-surface-400">{r.language || "—"}</span>
</div>
@@ -151,8 +151,8 @@
<!-- Storage Usage -->
{#if stats?.volumes?.length}
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm">
<h3 class="text-sm font-semibold text-surface-700 mb-3">Storage Usage</h3>
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm">
<h3 class="text-sm font-semibold text-surface-700 dark:text-surface-200 mb-3">Storage Usage</h3>
<div class="space-y-3">
{#each stats.volumes as vol}
<div>
@@ -160,7 +160,7 @@
<span class="font-medium">{vol.mount}</span>
<span>{vol.percent}%</span>
</div>
<div class="w-full h-3 bg-surface-100 rounded-full overflow-hidden">
<div class="w-full h-3 bg-surface-100 dark:bg-surface-700 rounded-full overflow-hidden">
<div
class="h-full rounded-full transition-all duration-700 ease-out {vol.percent > 90 ? 'bg-gradient-to-r from-rose-400 to-rose-500' : vol.percent > 70 ? 'bg-gradient-to-r from-amber-400 to-amber-500' : 'bg-gradient-to-r from-emerald-400 to-emerald-500'}"
style="width: {vol.percent}%"
+7 -7
View File
@@ -36,7 +36,7 @@
<div class="space-y-6">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-surface-900 tracking-tight">Docker</h1>
<h1 class="text-2xl font-bold text-surface-900 dark:text-white tracking-tight">Docker</h1>
<p class="text-sm text-surface-400 mt-1">{containers.length} containers · {containers.filter(c => c.status === "running").length} running</p>
</div>
<button onclick={load} class="text-xs font-medium text-primary-600 bg-primary-50 hover:bg-primary-100 px-3 py-1.5 rounded-lg transition-colors">
@@ -47,13 +47,13 @@
{#if loading}
<div class="space-y-3">
{#each Array(5) as _}
<div class="h-[72px] rounded-xl bg-surface-100 animate-pulse"></div>
<div class="h-[72px] rounded-xl bg-surface-100 dark:bg-surface-800 animate-pulse"></div>
{/each}
</div>
{:else}
<div class="space-y-2">
{#each containers as c}
<div class="bg-white rounded-xl border border-surface-200 p-4 flex items-center justify-between shadow-sm hover:shadow-md transition-all duration-200 group">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-4 flex items-center justify-between shadow-sm hover:shadow-md transition-all duration-200 group">
<div class="flex items-center gap-3 min-w-0">
<span class="relative flex h-2.5 w-2.5 shrink-0">
{#if c.status === "running"}
@@ -64,7 +64,7 @@
{/if}
</span>
<div class="min-w-0">
<p class="text-sm font-semibold text-surface-800 truncate">{c.name}</p>
<p class="text-sm font-semibold text-surface-800 dark:text-surface-100 truncate">{c.name}</p>
<p class="text-xs text-surface-400 truncate mt-0.5">{c.image}</p>
</div>
</div>
@@ -108,10 +108,10 @@
<!-- Log Modal -->
{#if logTarget}
<div class="fixed inset-0 bg-black/40 backdrop-blur-sm flex items-center justify-center z-50" role="dialog" aria-modal="true" onclick={() => { logTarget = ""; logContent = ""; }} onkeydown={(e) => e.key === "Escape" && (logTarget = "", logContent = "")}>
<div class="bg-white rounded-2xl shadow-2xl w-[90vw] max-w-4xl max-h-[80vh] flex flex-col" role="document" onclick={(e) => e.stopPropagation()} onkeydown={(e) => e.stopPropagation()}>
<div class="flex items-center justify-between px-5 py-4 border-b border-surface-200">
<div class="bg-white dark:bg-surface-800 rounded-2xl shadow-2xl w-[90vw] max-w-4xl max-h-[80vh] flex flex-col" role="document" onclick={(e) => e.stopPropagation()} onkeydown={(e) => e.stopPropagation()}>
<div class="flex items-center justify-between px-5 py-4 border-b border-surface-200 dark:border-surface-700">
<div>
<h3 class="text-sm font-bold text-surface-800">Container Logs</h3>
<h3 class="text-sm font-bold text-surface-800 dark:text-surface-100">Container Logs</h3>
<p class="text-xs text-surface-400 mt-0.5">{logTarget}</p>
</div>
<button aria-label="Close logs" class="text-surface-400 hover:text-surface-600 transition-colors" onclick={() => { logTarget = ""; logContent = ""; }}>
+8 -8
View File
@@ -69,7 +69,7 @@
<div class="space-y-5">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-surface-900 tracking-tight">Files</h1>
<h1 class="text-2xl font-bold text-surface-900 dark:text-white tracking-tight">Files</h1>
<p class="text-sm text-surface-400 mt-1">/volume1{currentPath ? "/" + currentPath : ""}</p>
</div>
<div class="flex items-center gap-2">
@@ -96,7 +96,7 @@
{/each}
{#if currentPath}
<button
class="ml-auto text-xs font-medium text-surface-500 bg-surface-100 hover:bg-surface-200 px-2.5 py-1 rounded-lg transition-colors flex items-center gap-1"
class="ml-auto text-xs font-medium text-surface-500 bg-surface-100 dark:bg-surface-700 hover:bg-surface-200 dark:hover:bg-surface-600 px-2.5 py-1 rounded-lg transition-colors flex items-center gap-1"
onclick={goUp}
>
<svg class="w-3 h-3" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M5 10l7-7m0 0l7 7m-7-7v18" /></svg>
@@ -109,27 +109,27 @@
{#if loading}
<div class="space-y-1">
{#each Array(8) as _}
<div class="h-11 rounded-lg bg-surface-100 animate-pulse"></div>
<div class="h-11 rounded-lg bg-surface-100 dark:bg-surface-800 animate-pulse"></div>
{/each}
</div>
{:else}
<div class="bg-white rounded-xl border border-surface-200 shadow-sm overflow-hidden">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 shadow-sm overflow-hidden">
<!-- Header -->
<div class="grid grid-cols-[1fr_100px_100px] px-4 py-2 text-[11px] font-semibold uppercase tracking-wider text-surface-400 border-b border-surface-100">
<div class="grid grid-cols-[1fr_100px_100px] px-4 py-2 text-[11px] font-semibold uppercase tracking-wider text-surface-400 border-b border-surface-100 dark:border-surface-700">
<span>Name</span>
<span class="text-right">Size</span>
<span class="text-right">Actions</span>
</div>
<!-- Entries -->
{#each entries as e}
<div class="grid grid-cols-[1fr_100px_100px] items-center px-4 py-2.5 hover:bg-surface-50 border-b border-surface-100 last:border-0 transition-colors group">
<div class="grid grid-cols-[1fr_100px_100px] items-center px-4 py-2.5 hover:bg-surface-50 dark:hover:bg-surface-700 border-b border-surface-100 dark:border-surface-700 last:border-0 transition-colors group">
{#if e.is_dir}
<button class="flex items-center gap-2.5 text-sm font-medium text-surface-700 hover:text-primary-600 transition-colors text-left truncate" onclick={() => browse(currentPath ? `${currentPath}/${e.name}` : e.name)}>
<button class="flex items-center gap-2.5 text-sm font-medium text-surface-700 dark:text-surface-200 hover:text-primary-600 transition-colors text-left truncate" onclick={() => browse(currentPath ? `${currentPath}/${e.name}` : e.name)}>
<svg class="w-4 h-4 text-amber-400 shrink-0" fill="currentColor" viewBox="0 0 20 20"><path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" /></svg>
{e.name}
</button>
{:else}
<span class="flex items-center gap-2.5 text-sm text-surface-600 truncate">
<span class="flex items-center gap-2.5 text-sm text-surface-600 dark:text-surface-300 truncate">
<svg class="w-4 h-4 text-surface-300 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" /></svg>
{e.name}
</span>
+9 -9
View File
@@ -41,26 +41,26 @@
<div class="space-y-6">
<div>
<h1 class="text-2xl font-bold text-surface-900 tracking-tight">Repositories</h1>
<h1 class="text-2xl font-bold text-surface-900 dark:text-white tracking-tight">Repositories</h1>
<p class="text-sm text-surface-400 mt-1">{repos.length} repositories on Gitea</p>
</div>
{#if loading}
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
{#each Array(4) as _}
<div class="h-[100px] rounded-xl bg-surface-100 animate-pulse"></div>
<div class="h-[100px] rounded-xl bg-surface-100 dark:bg-surface-800 animate-pulse"></div>
{/each}
</div>
{:else}
<div class="grid grid-cols-1 md:grid-cols-2 gap-3">
{#each repos as r}
<button
class="bg-white rounded-xl border border-surface-200 p-4 text-left shadow-sm hover:shadow-md hover:border-primary-200 transition-all duration-200 group {selectedRepo === `${r.owner?.login}/${r.name}` ? 'ring-2 ring-primary-500 border-primary-300' : ''}"
class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-4 text-left shadow-sm hover:shadow-md hover:border-primary-200 dark:hover:border-primary-700 transition-all duration-200 group {selectedRepo === `${r.owner?.login}/${r.name}` ? 'ring-2 ring-primary-500 border-primary-300' : ''}"
onclick={() => showCommits(r.owner?.login, r.name)}
>
<div class="flex items-start justify-between">
<div class="min-w-0">
<p class="text-sm font-semibold text-surface-800 group-hover:text-primary-600 transition-colors truncate">{r.name}</p>
<p class="text-sm font-semibold text-surface-800 dark:text-surface-100 group-hover:text-primary-600 transition-colors truncate">{r.name}</p>
<p class="text-xs text-surface-400 mt-1 line-clamp-1">{r.description || "No description"}</p>
</div>
{#if r.language}
@@ -78,10 +78,10 @@
<!-- Commits Panel -->
{#if selectedRepo}
<div class="bg-white rounded-xl border border-surface-200 p-5 shadow-sm">
<div class="bg-white dark:bg-surface-800 rounded-xl border border-surface-200 dark:border-surface-700 p-5 shadow-sm">
<div class="flex items-center justify-between mb-4">
<div>
<h3 class="text-sm font-bold text-surface-800">Recent Commits</h3>
<h3 class="text-sm font-bold text-surface-800 dark:text-surface-100">Recent Commits</h3>
<p class="text-xs text-surface-400 mt-0.5">{selectedRepo}</p>
</div>
<button
@@ -101,7 +101,7 @@
{:else}
<div class="space-y-0">
{#each commits.slice(0, 15) as c, i}
<div class="flex gap-3 py-2.5 {i < commits.length - 1 ? 'border-b border-surface-100' : ''}">
<div class="flex gap-3 py-2.5 {i < commits.length - 1 ? 'border-b border-surface-100 dark:border-surface-700' : ''}">
<div class="flex flex-col items-center pt-1">
<div class="w-2 h-2 rounded-full bg-primary-400 shrink-0"></div>
{#if i < commits.length - 1}
@@ -109,12 +109,12 @@
{/if}
</div>
<div class="min-w-0 flex-1">
<p class="text-sm text-surface-700 truncate">{c.commit?.message?.split("\n")[0]}</p>
<p class="text-sm text-surface-700 dark:text-surface-200 truncate">{c.commit?.message?.split("\n")[0]}</p>
<p class="text-[11px] text-surface-400 mt-0.5">
<span class="font-medium">{c.commit?.author?.name}</span> · {timeAgo(c.commit?.author?.date)}
</p>
</div>
<span class="text-[10px] font-mono text-surface-400 bg-surface-50 px-1.5 py-0.5 rounded h-fit shrink-0">{c.sha?.slice(0, 7)}</span>
<span class="text-[10px] font-mono text-surface-400 bg-surface-50 dark:bg-surface-700 px-1.5 py-0.5 rounded h-fit shrink-0">{c.sha?.slice(0, 7)}</span>
</div>
{/each}
</div>
+1 -1
View File
@@ -18,7 +18,7 @@ services:
DB_PASSWORD: ${DB_PASSWORD}
DB_DATABASE_NAME: ${DB_DATABASE_NAME}
REDIS_HOSTNAME: immich-redis
IMMICH_MACHINE_LEARNING_ENABLED: "false"
MACHINE_LEARNING_URL: http://100.65.185.12:3003
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:2283/api/server/ping"]
interval: 30s