feat(app): real daemon health footer (live, uptime, version)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+23
-7
@@ -1,7 +1,16 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Plus, ChevronDown, ChevronRight } from "lucide-react";
|
||||
import { COLORS, FONT, STATE_COLOR } from "./theme";
|
||||
import type { Group, WorkspaceView, SurfaceState } from "./layoutTypes";
|
||||
import type { DaemonHealth } from "./socketBridge";
|
||||
|
||||
function fmtUptime(startedMs: number): string {
|
||||
const s = Math.max(0, Math.floor((Date.now() - startedMs) / 1000));
|
||||
if (s < 60) return `${s}s`;
|
||||
if (s < 3600) return `${Math.floor(s / 60)}m`;
|
||||
if (s < 86400) return `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`;
|
||||
return `${Math.floor(s / 86400)}d ${Math.floor((s % 86400) / 3600)}h`;
|
||||
}
|
||||
|
||||
function aggregate(w: WorkspaceView): SurfaceState | "stopped" {
|
||||
const order: SurfaceState[] = ["error", "wait", "work", "done", "idle"];
|
||||
@@ -14,15 +23,22 @@ function aggregate(w: WorkspaceView): SurfaceState | "stopped" {
|
||||
}
|
||||
|
||||
export function Sidebar({
|
||||
groups, workspaces, activeId, onSelect, onNew,
|
||||
groups, workspaces, activeId, onSelect, onNew, health, connected,
|
||||
}: {
|
||||
groups: Group[];
|
||||
workspaces: WorkspaceView[];
|
||||
activeId: string | null;
|
||||
onSelect: (id: string) => void;
|
||||
onNew: () => void;
|
||||
health: DaemonHealth | null;
|
||||
connected: boolean;
|
||||
}) {
|
||||
const [collapsed, setCollapsed] = useState<Record<string, boolean>>({});
|
||||
const [, setTick] = useState(0);
|
||||
useEffect(() => {
|
||||
const t = setInterval(() => setTick((n) => n + 1), 30000);
|
||||
return () => clearInterval(t);
|
||||
}, []);
|
||||
const byGroup = (gid: string | null) => workspaces.filter((w) => (w.group_id ?? null) === gid).sort((a, b) => a.order - b.order);
|
||||
const ungrouped = byGroup(null);
|
||||
|
||||
@@ -76,12 +92,12 @@ export function Sidebar({
|
||||
{ungrouped.length > 0 && <div style={{ marginTop: 4, display: "flex", flexDirection: "column", gap: 2 }}>{ungrouped.map(row)}</div>}
|
||||
</div>
|
||||
|
||||
{/* Daemon status footer — uptime is mocked until the daemon reports it. */}
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8, height: 30, marginTop: 10, padding: "0 6px", borderRadius: 6, background: COLORS.bgPanel }}>
|
||||
<span style={{ width: 7, height: 7, borderRadius: "50%", background: COLORS.stDone, flex: "0 0 7px" }} />
|
||||
<span style={{ fontFamily: FONT.mono, fontSize: 11, color: COLORS.textSecondary }}>spaceshd · live</span>
|
||||
<div title={health ? `spaceshd v${health.version} · pid ${health.pid}` : "daemon offline"}
|
||||
style={{ display: "flex", alignItems: "center", gap: 8, height: 30, marginTop: 10, padding: "0 6px", borderRadius: 6, background: COLORS.bgPanel }}>
|
||||
<span style={{ width: 7, height: 7, borderRadius: "50%", background: connected ? COLORS.stDone : COLORS.textMuted, flex: "0 0 7px" }} />
|
||||
<span style={{ fontFamily: FONT.mono, fontSize: 11, color: COLORS.textSecondary }}>{connected ? "spaceshd · live" : "spaceshd · offline"}</span>
|
||||
<span style={{ flex: 1 }} />
|
||||
<span style={{ fontFamily: FONT.mono, fontSize: 11, color: COLORS.textMuted }}>3d 4h</span>
|
||||
<span style={{ fontFamily: FONT.mono, fontSize: 11, color: COLORS.textMuted }}>{health ? fmtUptime(health.started_at_ms) : ""}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user