mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 20:16:35 +00:00
feat(cameras): health indicator on list page (green/yellow/red dot + status badge)
This commit is contained in:
parent
592bdad10b
commit
2d157e900d
2 changed files with 27 additions and 14 deletions
|
|
@ -489,10 +489,12 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
|||
const user = event.context.user!;
|
||||
const cameras = deps.repo.listCameras();
|
||||
const streamCounts = new Map<number, number>();
|
||||
const activeKiosks = new Map<number, number>(); // camera_id → count of kiosks rendering
|
||||
for (const cam of cameras) {
|
||||
streamCounts.set(cam.id, deps.repo.listCameraStreams(cam.id).length);
|
||||
activeKiosks.set(cam.id, deps.repo.listKiosksRenderingCamera(cam.id).length);
|
||||
}
|
||||
return htmlPage(CamerasPage({ user: user.username, cameras, streamCounts }));
|
||||
return htmlPage(CamerasPage({ user: user.username, cameras, streamCounts, activeKiosks }));
|
||||
});
|
||||
|
||||
app.get("/admin/cameras/new", (event) => {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ interface CamerasProps {
|
|||
user: string;
|
||||
cameras: Camera[];
|
||||
streamCounts: Map<number, number>;
|
||||
activeKiosks: Map<number, number>;
|
||||
}
|
||||
|
||||
export function CamerasPage(props: CamerasProps) {
|
||||
|
|
@ -137,19 +138,29 @@ export function CamerasPage(props: CamerasProps) {
|
|||
{props.cameras.length === 0 ? (
|
||||
<tr><td colspan="4" style="text-align:center; color:#999; padding:2rem">No cameras configured</td></tr>
|
||||
) : (
|
||||
props.cameras.map((cam) => (
|
||||
props.cameras.map((cam) => {
|
||||
const streams = props.streamCounts.get(cam.id) ?? 0;
|
||||
const active = props.activeKiosks.get(cam.id) ?? 0;
|
||||
const health = !cam.enabled ? "gray"
|
||||
: streams === 0 ? "red"
|
||||
: active > 0 ? "green"
|
||||
: "yellow";
|
||||
const healthLabel = !cam.enabled ? "Disabled"
|
||||
: streams === 0 ? "No streams"
|
||||
: active > 0 ? `Live (${active} kiosk${active > 1 ? "s" : ""})`
|
||||
: "Idle";
|
||||
return (
|
||||
<tr>
|
||||
<td><a href={`/admin/cameras/${cam.id}`}><strong>{cam.name}</strong></a></td>
|
||||
<td><span class="badge badge-blue">{cam.type.toUpperCase()}</span></td>
|
||||
<td>{String(props.streamCounts.get(cam.id) ?? 0)}</td>
|
||||
<td>
|
||||
{cam.enabled
|
||||
? <span class="badge badge-green">Enabled</span>
|
||||
: <span class="badge badge-gray">Disabled</span>
|
||||
}
|
||||
<span style={`display:inline-block;width:8px;height:8px;border-radius:50%;background:${health === "green" ? "#2a2" : health === "yellow" ? "#ca0" : health === "red" ? "#c22" : "#888"};margin-right:8px;vertical-align:middle`} />
|
||||
<a href={`/admin/cameras/${cam.id}`}><strong>{cam.name}</strong></a>
|
||||
</td>
|
||||
<td><span class="badge badge-blue">{cam.type.toUpperCase()}</span></td>
|
||||
<td>{String(streams)}</td>
|
||||
<td><span class={`badge badge-${health}`}>{healthLabel}</span></td>
|
||||
</tr>
|
||||
))
|
||||
);
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
|||
Loading…
Reference in a new issue