feat(ui): implement modern NaxOS Web Dashboard with Perses analytics and ZFS migration wizard
CI & Build NaxOS Web Dashboard / build (push) Failing after 1m29s

This commit is contained in:
Lukas Holzner
2026-09-03 23:59:06 +02:00
parent 155beec162
commit eaad4719eb
27 changed files with 5580 additions and 2 deletions
+93
View File
@@ -0,0 +1,93 @@
import React from 'react';
import {
LayoutDashboard,
HardDrive,
FolderSync,
Layers,
LineChart,
GitBranch,
FileTerminal,
Server,
Settings,
} from 'lucide-react';
interface SidebarProps {
currentTab: string;
onSelectTab: (tab: string) => void;
}
export const Sidebar: React.FC<SidebarProps> = ({ currentTab, onSelectTab }) => {
const navItems = [
{ id: 'overview', label: 'Dashboard', icon: LayoutDashboard },
{ id: 'storage', label: 'Storage & ZFS', icon: HardDrive, badge: 'ZFS' },
{ id: 'shares', label: 'File Shares', icon: FolderSync, badge: 'SMB/NFS' },
{ id: 'apps', label: 'App Store & Runtime', icon: Layers },
{ id: 'analytics', label: 'Perses Analytics', icon: LineChart, badge: 'Native' },
{ id: 'gitops', label: 'GitOps & Updates', icon: GitBranch },
{ id: 'logs', label: 'System Logs', icon: FileTerminal },
{ id: 'wizard', label: 'Setup Wizard', icon: Settings },
];
return (
<aside className="w-64 bg-slate-900/90 border-r border-slate-800 flex flex-col backdrop-blur-xl shrink-0">
{/* Brand Header */}
<div className="h-16 flex items-center px-6 gap-3 border-b border-slate-800">
<div className="h-9 w-9 rounded-xl bg-gradient-to-tr from-emerald-500 to-teal-400 p-0.5 shadow-lg shadow-emerald-500/20">
<div className="h-full w-full bg-slate-950 rounded-[10px] flex items-center justify-center">
<Server className="h-5 w-5 text-emerald-400" />
</div>
</div>
<div>
<div className="font-bold tracking-tight text-white flex items-center gap-1.5">
NaxOS <span className="text-xs px-1.5 py-0.5 rounded-full bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">v1.0</span>
</div>
<p className="text-[11px] text-slate-400">Declarative ZFS Appliance</p>
</div>
</div>
{/* Nav List */}
<nav className="flex-1 px-3 py-4 space-y-1">
{navItems.map((item) => {
const Icon = item.icon;
const isActive = currentTab === item.id;
return (
<button
key={item.id}
onClick={() => onSelectTab(item.id)}
className={`w-full flex items-center gap-3 px-3.5 py-2.5 rounded-xl text-sm font-medium transition-all ${
isActive
? 'bg-emerald-500/10 text-emerald-400 border border-emerald-500/20 shadow-sm'
: 'text-slate-400 hover:text-slate-200 hover:bg-slate-800/60'
}`}
>
<Icon className={`h-4 w-4 ${isActive ? 'text-emerald-400' : 'text-slate-400'}`} />
<span className="flex-1 text-left">{item.label}</span>
{item.badge && (
<span
className={`text-[10px] px-1.5 py-0.5 rounded font-mono font-semibold ${
isActive
? 'bg-emerald-500/20 text-emerald-300'
: 'bg-slate-800 text-slate-400'
}`}
>
{item.badge}
</span>
)}
</button>
);
})}
</nav>
{/* Appliance Status Footer */}
<div className="p-4 border-t border-slate-800 bg-slate-950/40">
<div className="flex items-center gap-2.5">
<div className="h-2.5 w-2.5 rounded-full bg-emerald-500 animate-pulse" />
<div className="text-xs">
<p className="text-slate-200 font-medium">System Protected</p>
<p className="text-slate-500 text-[11px]">GitOps Synchronized</p>
</div>
</div>
</div>
</aside>
);
};