diff --git a/services/web-ui/public/screens-home.jsx b/services/web-ui/public/screens-home.jsx
index 031155e..41ee679 100644
--- a/services/web-ui/public/screens-home.jsx
+++ b/services/web-ui/public/screens-home.jsx
@@ -1,97 +1,115 @@
-// screens-home.jsx - home dashboard
-
-const { ACTIVITY, RECORDERS, JOBS, ASSETS } = window.ZAMPP_DATA;
+// screens-home.jsx
function Home({ navigate }) {
- const sparkAssets = [12, 14, 13, 18, 16, 22, 25, 24, 28, 30, 32, 34, 38];
- const sparkIngest = [4, 6, 5, 8, 9, 12, 10, 14, 13, 18, 20, 22, 24];
- const sparkJobs = [8, 7, 10, 9, 14, 12, 16, 13, 18, 15, 12, 10, 11];
- const sparkStorage = [42, 44, 46, 47, 48, 50, 52, 54, 56, 58, 60, 62, 64];
+ const { RECORDERS, JOBS, ASSETS, NODES } = window.ZAMPP_DATA;
- const liveRecorders = RECORDERS.filter(r => r.status === "recording").slice(0, 4);
+ const liveRecorders = RECORDERS.filter(r => r.status === 'recording').slice(0, 4);
+ const runningJobs = JOBS.filter(j => j.status === 'running' || j.status === 'queued');
+ const failedJobs = JOBS.filter(j => j.status === 'failed').length;
+ const recentAssets = [...ASSETS].sort((a, b) => new Date(b.created_at) - new Date(a.created_at)).slice(0, 6);
+
+ const spark = (n, base = 10) => Array.from({ length: 13 }, (_, i) => base + Math.round(Math.sin(i * 0.7 + n) * base * 0.3));
return (
-
Good evening, Zach
-
4 recorders live · 3 jobs running · cluster healthy across 4 nodes
+
Dragonflight
+
+ {liveRecorders.length > 0 ? liveRecorders.length + ' live · ' : ''}
+ {runningJobs.length > 0 ? runningJobs.length + ' job' + (runningJobs.length > 1 ? 's running' : ' running') + ' · ' : ''}
+ {ASSETS.length.toLocaleString()} assets
+
Library
-
1,553
-
+38 today
-
+
{ASSETS.length.toLocaleString()}
+
Total assets
+
-
Ingest (24h)
-
412 GB
-
+82 GB last hr
-
+
Live feeds
+
{liveRecorders.length}
+
{RECORDERS.length} recorders configured
+
-
Jobs queued
-
3 / 247 done
-
avg 4.2 min
-
+
Jobs
+
{runningJobs.length} / {JOBS.filter(j => j.status === 'done').length} done
+
0 ? 'var(--warning)' : '' }}>{failedJobs > 0 ? failedJobs + ' failed' : 'All clear'}
+
-
Object store
-
64% of 18 TB
-
11.5 TB used
-
+
Cluster nodes
+
{NODES.filter(n => n.online).length} / {NODES.length} online
+
Last heartbeat <30s
+
-
navigate("recorders")} moreLabel="All recorders" />
-
- {liveRecorders.map((r, i) => (
-
navigate("recorders")}>
-
- REC
-
-
-
- {r.name}
- {r.elapsed}
-
+ {liveRecorders.length > 0 && (
+ <>
+
navigate('recorders')} moreLabel="All recorders" />
+
+ {liveRecorders.map(r => (
+
navigate('recorders')}>
+
REC
+
+
+ {r.name}
+ {r.elapsed}
+
+
+ ))}
- ))}
-
+
+ >
+ )}
-
-
-
+
navigate('library')} moreLabel="All assets" />
- {ACTIVITY.map(a => (
+ {recentAssets.length === 0 ? (
+
No assets yet.
+ ) : recentAssets.map(a => (
-
-
+
+
- {a.who} {a.what} {a.target}
+ {a.name}
+ {a.project && <> in {a.project}>}
-
{a.time}
+
{a.updated}
))}
-
navigate("jobs")} moreLabel="View all" />
+ navigate('jobs')} moreLabel="View all" />
- {JOBS.slice(0, 5).map(j => (
-
- ))}
+ {JOBS.length === 0
+ ?
No jobs.
+ : JOBS.slice(0, 5).map(j =>
)}
-
-
-
+
navigate('cluster')} moreLabel="View all" />
+
+ {NODES.length === 0
+ ?
No nodes found.
+ : NODES.slice(0, 4).map(n => (
+
+
+ {n.hostname}
+
+ {n.cpu_usage != null && CPU {n.cpu_usage}%}
+ {n.mem_used_mb != null && {Math.round(n.mem_used_mb / 1024)}GB RAM}
+
+ ))}
@@ -99,12 +117,12 @@ function Home({ navigate }) {
);
}
-function SectionHead({ title, onMore, moreLabel = "View all" }) {
+function SectionHead({ title, onMore, moreLabel = 'View all' }) {
return (
-
-
{title}
+
+
{title}
{onMore && (
-