store only status-change events; UI client-side polling refactor

This commit is contained in:
Stanislav Rossovskii
2026-05-27 14:58:46 +04:00
parent 71f0035b0b
commit d5f312f200
48 changed files with 2247 additions and 753 deletions

View File

@@ -6,9 +6,13 @@ import { useMemo, useState } from "react";
import { AgentFeatures } from "@/components/AgentFeatures";
import { LabelChips } from "@/components/Labels";
import { DateTime } from "@/components/TimeZoneControls";
import type { Agent, CheckState } from "@/lib/api";
import type { components } from "@/lib/api-types";
import { statusBadgeClass } from "@/lib/format";
import { usePolling } from "@/lib/usePolling";
import type { InventoryData } from "@/lib/view-types";
type Agent = components["schemas"]["Agent"];
type CheckState = components["schemas"]["CheckState"];
type CheckStatus = CheckState["status"];
type CheckCounts = Record<CheckStatus, number>;
type SortField = "host" | "status" | "last_seen_at";
@@ -20,10 +24,12 @@ const checkStatuses: CheckStatus[] = ["ok", "warning", "critical", "unknown"];
const statusRank: Record<Agent["status"], number> = { alive: 0, stale: 1, dead: 2 };
const checkSortStatuses: CheckStatus[] = ["critical", "warning", "unknown", "ok"];
export function AgentsBrowser({ rows: initialRows }: { rows: AgentRow[] }) {
export function AgentsBrowser({ initialData }: { initialData: InventoryData }) {
const { data } = usePolling(initialData, "/api/poll/inventory");
const [query, setQuery] = useState("");
const [sort, setSort] = useState<SortField>("status");
const [dir, setDir] = useState<SortDir>("desc");
const initialRows = useMemo(() => rowsFromInventory(data), [data]);
const rows = useMemo(
() => sortAgents(filterAgents(initialRows, query), sort, dir),
@@ -239,6 +245,19 @@ function emptyCheckCounts(): CheckCounts {
return { ok: 0, warning: 0, critical: 0, unknown: 0 };
}
function rowsFromInventory(data: InventoryData): AgentRow[] {
const checksByAgent = new Map<string, CheckCounts>();
for (const c of data.checks) {
const counts = checksByAgent.get(c.agent_id) ?? emptyCheckCounts();
counts[c.status] += 1;
checksByAgent.set(c.agent_id, counts);
}
return data.agents.map((agent) => ({
agent,
checks: checksByAgent.get(agent.agent_id) ?? emptyCheckCounts(),
}));
}
function shortStatus(status: CheckStatus): string {
switch (status) {
case "ok":