feat(ui): integrate official Homarr dashboard-icons for workloads and services hub
CI & Build NaxOS Web Dashboard / build (push) Successful in 7m59s

This commit is contained in:
Lukas Holzner
2026-09-04 12:16:42 +02:00
parent cb7a7e3e43
commit 7ae0b3aad4
36 changed files with 371 additions and 24 deletions
+165 -3
View File
@@ -9,6 +9,7 @@ import {
ArrowUpRight,
TrendingUp,
} from 'lucide-react';
import { AppIcon } from '../components/AppIcon.js';
import type { SystemStatus, ZfsPool, InstalledApp } from '../types/index.js';
interface OverviewViewProps {
@@ -112,9 +113,20 @@ export const OverviewView: React.FC<OverviewViewProps> = ({
<div className="text-2xl font-bold text-white tracking-tight">
{apps.length || 2} <span className="text-xs text-slate-400 font-normal">Active Services</span>
</div>
<p className="text-xs text-slate-400 mt-1">
Immich (Systemd), Jellyfin (Docker)
</p>
<div className="flex items-center gap-1.5 mt-2.5">
<div className="p-1 rounded-lg bg-slate-950 border border-slate-800" title="Immich Photo Hub">
<AppIcon name="immich" className="h-5 w-5" />
</div>
<div className="p-1 rounded-lg bg-slate-950 border border-slate-800" title="Jellyfin Media Server">
<AppIcon name="jellyfin" className="h-5 w-5" />
</div>
<div className="p-1 rounded-lg bg-slate-950 border border-slate-800" title="CNCF Perses Telemetry">
<AppIcon name="grafana" className="h-5 w-5" />
</div>
<div className="p-1 rounded-lg bg-slate-950 border border-slate-800" title="Docker Engine">
<AppIcon name="docker" className="h-5 w-5" />
</div>
</div>
</div>
<div className="mt-3 text-[11px] text-slate-400">
Runtime Engine: <span className="text-slate-200">Docker + Systemd</span>
@@ -141,6 +153,156 @@ export const OverviewView: React.FC<OverviewViewProps> = ({
</div>
</div>
{/* Homarr-Style Active Services & Workloads Hub */}
<div className="p-6 rounded-2xl bg-slate-900/70 border border-slate-800">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-2">
<Layers className="h-4 w-4 text-emerald-400" />
<h3 className="text-sm font-semibold text-white">Appliance Services & Workloads</h3>
<span className="px-2 py-0.5 rounded-full text-[10px] font-semibold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
Homarr Dashboard
</span>
</div>
<button
onClick={() => onNavigate('apps')}
className="text-xs text-emerald-400 hover:text-emerald-300 font-medium flex items-center gap-1"
>
<span>App Store & Workload Engine</span>
<ArrowUpRight className="h-3.5 w-3.5" />
</button>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{/* Workload 1: Immich Photo Hub */}
<div className="p-4 rounded-xl bg-slate-950/70 border border-slate-800/90 hover:border-slate-700 transition flex flex-col justify-between group">
<div>
<div className="flex items-start justify-between">
<div className="p-2.5 rounded-xl bg-slate-900 border border-slate-800 shadow-inner group-hover:scale-105 transition-transform">
<AppIcon name="immich" className="h-8 w-8" />
</div>
<div className="flex items-center gap-1.5">
<span className="h-2 w-2 rounded-full bg-emerald-400 animate-pulse" />
<span className="text-[10px] font-mono text-emerald-400 font-medium">ONLINE</span>
</div>
</div>
<h4 className="text-sm font-bold text-white mt-3">Immich Photo Hub</h4>
<p className="text-xs text-slate-400 mt-0.5 line-clamp-2">
Hardware-accelerated photo & video backup with Intel QuickSync ML
</p>
</div>
<div className="mt-4 pt-3 border-t border-slate-800/80 flex items-center justify-between">
<span className="text-[11px] font-mono text-slate-400 bg-slate-900 px-2 py-0.5 rounded border border-slate-800">
:2283
</span>
<a
href="http://naxos.local:2283"
target="_blank"
rel="noreferrer"
className="flex items-center gap-1 text-xs text-emerald-400 hover:text-emerald-300 font-medium"
>
<span>Launch</span>
<ArrowUpRight className="h-3 w-3" />
</a>
</div>
</div>
{/* Workload 2: Jellyfin Media Server */}
<div className="p-4 rounded-xl bg-slate-950/70 border border-slate-800/90 hover:border-slate-700 transition flex flex-col justify-between group">
<div>
<div className="flex items-start justify-between">
<div className="p-2.5 rounded-xl bg-slate-900 border border-slate-800 shadow-inner group-hover:scale-105 transition-transform">
<AppIcon name="jellyfin" className="h-8 w-8" />
</div>
<div className="flex items-center gap-1.5">
<span className="h-2 w-2 rounded-full bg-emerald-400 animate-pulse" />
<span className="text-[10px] font-mono text-emerald-400 font-medium">ONLINE</span>
</div>
</div>
<h4 className="text-sm font-bold text-white mt-3">Jellyfin Media Server</h4>
<p className="text-xs text-slate-400 mt-0.5 line-clamp-2">
4K HDR media streaming with hardware transcoding & DLNA
</p>
</div>
<div className="mt-4 pt-3 border-t border-slate-800/80 flex items-center justify-between">
<span className="text-[11px] font-mono text-slate-400 bg-slate-900 px-2 py-0.5 rounded border border-slate-800">
:8096
</span>
<a
href="http://naxos.local:8096"
target="_blank"
rel="noreferrer"
className="flex items-center gap-1 text-xs text-emerald-400 hover:text-emerald-300 font-medium"
>
<span>Launch</span>
<ArrowUpRight className="h-3 w-3" />
</a>
</div>
</div>
{/* Workload 3: CNCF Perses Analytics */}
<div className="p-4 rounded-xl bg-slate-950/70 border border-slate-800/90 hover:border-slate-700 transition flex flex-col justify-between group">
<div>
<div className="flex items-start justify-between">
<div className="p-2.5 rounded-xl bg-slate-900 border border-slate-800 shadow-inner group-hover:scale-105 transition-transform">
<AppIcon name="grafana" className="h-8 w-8" />
</div>
<div className="flex items-center gap-1.5">
<span className="h-2 w-2 rounded-full bg-emerald-400 animate-pulse" />
<span className="text-[10px] font-mono text-emerald-400 font-medium">ONLINE</span>
</div>
</div>
<h4 className="text-sm font-bold text-white mt-3">CNCF Perses Telemetry</h4>
<p className="text-xs text-slate-400 mt-0.5 line-clamp-2">
Declarative visualization for ZFS I/O, ARC caching, and host metrics
</p>
</div>
<div className="mt-4 pt-3 border-t border-slate-800/80 flex items-center justify-between">
<span className="text-[11px] font-mono text-slate-400 bg-slate-900 px-2 py-0.5 rounded border border-slate-800">
:8080
</span>
<button
onClick={() => onNavigate('analytics')}
className="flex items-center gap-1 text-xs text-emerald-400 hover:text-emerald-300 font-medium"
>
<span>Open</span>
<ArrowUpRight className="h-3 w-3" />
</button>
</div>
</div>
{/* Workload 4: Nextcloud Hub */}
<div className="p-4 rounded-xl bg-slate-950/70 border border-slate-800/90 hover:border-slate-700 transition flex flex-col justify-between group">
<div>
<div className="flex items-start justify-between">
<div className="p-2.5 rounded-xl bg-slate-900 border border-slate-800 shadow-inner group-hover:scale-105 transition-transform">
<AppIcon name="nextcloud" className="h-8 w-8" />
</div>
<div className="flex items-center gap-1.5">
<span className="h-2 w-2 rounded-full bg-slate-500" />
<span className="text-[10px] font-mono text-slate-400 font-medium">READY</span>
</div>
</div>
<h4 className="text-sm font-bold text-white mt-3">Nextcloud Hub</h4>
<p className="text-xs text-slate-400 mt-0.5 line-clamp-2">
Collaborative office, encrypted file sync, and calendar sharing
</p>
</div>
<div className="mt-4 pt-3 border-t border-slate-800/80 flex items-center justify-between">
<span className="text-[11px] font-mono text-slate-400 bg-slate-900 px-2 py-0.5 rounded border border-slate-800">
Catalog
</span>
<button
onClick={() => onNavigate('apps')}
className="flex items-center gap-1 text-xs text-sky-400 hover:text-sky-300 font-medium"
>
<span>Deploy</span>
<ArrowUpRight className="h-3 w-3" />
</button>
</div>
</div>
</div>
</div>
{/* Embedded Native Perses Analytics Panel */}
<div className="p-6 rounded-2xl bg-slate-900/70 border border-slate-800">
<div className="flex items-center justify-between mb-4">