milestone 30: overview as a dashboard, explicit health contract, period aggregations
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* The count beside the Diagnostics nav item.
|
||||
*
|
||||
* Three things have to be visible and only one of them is a number. Open
|
||||
* episodes are the count. A `degraded` rollup with no open episode still has to
|
||||
* show something, or a degraded box looks exactly like a healthy one. And a
|
||||
* health poll that failed is not evidence of health: it shows the same neutral
|
||||
* mark, because the alternative is an unbadged item claiming all is well on no
|
||||
* evidence at all.
|
||||
*
|
||||
* "Fresh" here means the latest poll succeeded, never TanStack's `isStale`:
|
||||
* healthQuery's `staleTime` is 0, so staleness is true in every gap between
|
||||
* polls and would badge the item permanently.
|
||||
*/
|
||||
|
||||
import type { Health } from "@/lib/types";
|
||||
|
||||
export interface NavBadge {
|
||||
/** What the badge shows. Shape and text, never colour alone. */
|
||||
text: string;
|
||||
/** What a screen reader hears in its place. */
|
||||
label: string;
|
||||
}
|
||||
|
||||
export function diagnosticsBadge(health: Health | undefined, pollFailed: boolean): NavBadge | null {
|
||||
// The one hidden unknown, and only because it is momentary: the first poll has
|
||||
// not answered yet, and there is nothing to be right or wrong about.
|
||||
if (health === undefined && !pollFailed) return null;
|
||||
if (pollFailed) return { text: "!", label: "Health unavailable" };
|
||||
if (health === undefined) return null;
|
||||
const open = health.diagnostics.active_warnings + health.diagnostics.active_errors;
|
||||
if (open > 0) {
|
||||
return { text: String(open), label: `${open} active diagnostic ${open === 1 ? "event" : "events"}` };
|
||||
}
|
||||
if (health.status === "degraded") return { text: "!", label: "Health degraded" };
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user