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 user = event.context.user!;
|
||||||
const cameras = deps.repo.listCameras();
|
const cameras = deps.repo.listCameras();
|
||||||
const streamCounts = new Map<number, number>();
|
const streamCounts = new Map<number, number>();
|
||||||
|
const activeKiosks = new Map<number, number>(); // camera_id → count of kiosks rendering
|
||||||
for (const cam of cameras) {
|
for (const cam of cameras) {
|
||||||
streamCounts.set(cam.id, deps.repo.listCameraStreams(cam.id).length);
|
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) => {
|
app.get("/admin/cameras/new", (event) => {
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ interface CamerasProps {
|
||||||
user: string;
|
user: string;
|
||||||
cameras: Camera[];
|
cameras: Camera[];
|
||||||
streamCounts: Map<number, number>;
|
streamCounts: Map<number, number>;
|
||||||
|
activeKiosks: Map<number, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CamerasPage(props: CamerasProps) {
|
export function CamerasPage(props: CamerasProps) {
|
||||||
|
|
@ -137,19 +138,29 @@ export function CamerasPage(props: CamerasProps) {
|
||||||
{props.cameras.length === 0 ? (
|
{props.cameras.length === 0 ? (
|
||||||
<tr><td colspan="4" style="text-align:center; color:#999; padding:2rem">No cameras configured</td></tr>
|
<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) => {
|
||||||
<tr>
|
const streams = props.streamCounts.get(cam.id) ?? 0;
|
||||||
<td><a href={`/admin/cameras/${cam.id}`}><strong>{cam.name}</strong></a></td>
|
const active = props.activeKiosks.get(cam.id) ?? 0;
|
||||||
<td><span class="badge badge-blue">{cam.type.toUpperCase()}</span></td>
|
const health = !cam.enabled ? "gray"
|
||||||
<td>{String(props.streamCounts.get(cam.id) ?? 0)}</td>
|
: streams === 0 ? "red"
|
||||||
<td>
|
: active > 0 ? "green"
|
||||||
{cam.enabled
|
: "yellow";
|
||||||
? <span class="badge badge-green">Enabled</span>
|
const healthLabel = !cam.enabled ? "Disabled"
|
||||||
: <span class="badge badge-gray">Disabled</span>
|
: streams === 0 ? "No streams"
|
||||||
}
|
: active > 0 ? `Live (${active} kiosk${active > 1 ? "s" : ""})`
|
||||||
</td>
|
: "Idle";
|
||||||
</tr>
|
return (
|
||||||
))
|
<tr>
|
||||||
|
<td>
|
||||||
|
<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>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue