mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
health service and panel
This commit is contained in:
@@ -13,6 +13,7 @@ export default function AdminPanel() {
|
||||
const { session, lockRover, setMode, requestControl } = useSession();
|
||||
const roster = useMemo(() => session?.roster ?? [], [session?.roster]);
|
||||
const [lockStates, setLockStates] = useState({});
|
||||
const health = session?.health || null;
|
||||
|
||||
const isAdmin =
|
||||
session?.role === 'admin' ||
|
||||
@@ -87,6 +88,69 @@ export default function AdminPanel() {
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<ReplaySnapshotHealth health={health} />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function ReplaySnapshotHealth({ health }) {
|
||||
if (!health) return null;
|
||||
const replay = health.replay || { sources: [], readyCount: 0, totalCount: 0 };
|
||||
const snapshots = health.snapshots || { rovers: [], rooms: [] };
|
||||
const replaySummary = `${replay.readyCount}/${replay.totalCount} sources ready`;
|
||||
const roverStale = snapshots.rovers.filter((entry) => entry.stale).length;
|
||||
const roomStale = snapshots.rooms.filter((entry) => entry.stale).length;
|
||||
return (
|
||||
<div className="space-y-0.5">
|
||||
<div className="panel-muted text-xs uppercase">Health</div>
|
||||
<div className="surface space-y-0.5 text-xs text-slate-200">
|
||||
<div className="flex items-center justify-between">
|
||||
<span>Replay segments</span>
|
||||
<span className="text-slate-400">{replaySummary}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>Rover snapshots</span>
|
||||
<span className={roverStale ? 'text-amber-300' : 'text-emerald-300'}>
|
||||
{snapshots.rovers.length - roverStale}/{snapshots.rovers.length} ok
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span>Room cameras</span>
|
||||
<span className={roomStale ? 'text-amber-300' : 'text-emerald-300'}>
|
||||
{snapshots.rooms.length - roomStale}/{snapshots.rooms.length} ok
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-0.25 text-xs text-slate-300">
|
||||
{replay.sources.map((source) => (
|
||||
<div key={`${source.type}:${source.id}`} className="flex items-center justify-between">
|
||||
<span>{source.label}</span>
|
||||
<span className={source.ready ? 'text-emerald-300' : 'text-amber-300'}>
|
||||
{source.recentCount}/{source.neededCount}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="space-y-0.25 text-xs text-slate-300">
|
||||
{snapshots.rovers.map((entry) => (
|
||||
<div key={`rover:${entry.id}`} className="flex items-center justify-between">
|
||||
<span>{entry.name}</span>
|
||||
<span className={entry.stale ? 'text-amber-300' : 'text-emerald-300'}>
|
||||
{entry.stale ? 'stale' : 'ok'}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="space-y-0.25 text-xs text-slate-300">
|
||||
{snapshots.rooms.map((entry) => (
|
||||
<div key={`room:${entry.id}`} className="flex items-center justify-between">
|
||||
<span>{entry.name}</span>
|
||||
<span className={entry.stale ? 'text-amber-300' : 'text-emerald-300'}>
|
||||
{entry.error ? 'error' : entry.stale ? 'stale' : 'ok'}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user