milestone 30: overview as a dashboard, explicit health contract, period aggregations
Gates / frontend (push) Successful in 1m32s
Gates / test (push) Successful in 1m54s
Gates / package (push) Successful in 5m28s
Gates / container (push) Successful in 14s
Gates / test-aarch64 (push) Failing after 3h10m0s
CI / gates (push) Failing after 3h11m55s

This commit is contained in:
2026-08-22 16:45:15 +02:00
parent 17422fac21
commit 648d9b4496
89 changed files with 7222 additions and 4239 deletions
+63 -20
View File
@@ -5,6 +5,7 @@ import {
createRoute,
createRouter,
lazyRouteComponent,
redirect,
useRouter,
type ErrorComponentProps,
type RouterHistory,
@@ -34,11 +35,15 @@ import {
queryDetailQuery,
rulesQuery,
settingsQuery,
statsClientsQuery,
statsQuery,
statsRoutesQuery,
statsTypesQuery,
timeseriesQuery,
upstreamHealthQuery,
upstreamsQuery,
} from "@/lib/queries";
import { DEFAULT_PERIOD, parsePeriod } from "@/features/overview/period";
import type { Period } from "@/lib/types";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
@@ -130,20 +135,51 @@ const shellRoute = createRoute({
component: AppShell,
});
const dashboardRoute = createRoute({
/**
* The landing default, not a compatibility alias: Overview is where the app
* opens, and `/` is spelled out rather than left as a second name for it.
*/
const indexRoute = createRoute({
getParentRoute: () => shellRoute,
path: "/",
// allSettled, not all: DashboardPage reads these with useQuery so each widget
// can render its own error. A rejecting loader would replace the whole page
// with RouteError and take the three healthy widgets down with the failed one.
loader: ({ context }) =>
Promise.allSettled([
context.queryClient.ensureQueryData(statsQuery("24h")),
context.queryClient.ensureQueryData(timeseriesQuery("24h")),
context.queryClient.ensureQueryData(healthQuery()),
context.queryClient.ensureQueryData(upstreamHealthQuery()),
]),
component: lazyRouteComponent(() => import("@/features/dashboard/DashboardPage")),
beforeLoad: () => {
throw redirect({ to: "/overview" });
},
});
/**
* Overview. The period is the whole of its applied state, so a view of the page
* is a link: a hand-typed or stale value falls back to the default rather than
* reaching the API as a parameter it answers 400 to.
*/
const overviewRoute = createRoute({
getParentRoute: () => shellRoute,
path: "/overview",
validateSearch: (search: Record<string, unknown>): { period?: Period } => ({
period: parsePeriod(search["period"]),
}),
loaderDeps: ({ search }): { period: Period } => ({ period: search.period ?? DEFAULT_PERIOD }),
/**
* Started here, awaited nowhere. Every panel reads these with `useQuery` and
* owns its own loading and error surface, so awaiting would trade that whole
* contract for one blocking navigation: the page would sit on the slowest of
* five requests and then appear complete, instead of the four that answered
* rendering beside the one still in flight. The rejections are caught only to
* keep them from going unhandled; the panels state them.
*/
loader: ({ context, deps }) => {
const start = (promise: Promise<unknown>) => void promise.catch(() => {});
start(context.queryClient.ensureQueryData(healthQuery()));
start(context.queryClient.ensureQueryData(statsQuery(deps.period)));
start(context.queryClient.ensureQueryData(timeseriesQuery(deps.period)));
start(context.queryClient.ensureQueryData(statsClientsQuery(deps.period)));
// The registered names the client chart labels its series with. Started here
// so the lookup is not a second round trip after the page chunk lands.
start(context.queryClient.ensureQueryData(clientsQuery()));
start(context.queryClient.ensureQueryData(statsTypesQuery(deps.period)));
start(context.queryClient.ensureQueryData(statsRoutesQuery(deps.period)));
},
component: lazyRouteComponent(() => import("@/features/overview/OverviewPage")),
});
/**
@@ -301,14 +337,20 @@ const diagnosticsRoute = createRoute({
since: search.since,
until: search.until,
}),
// allSettled: the two sections render their own state, and the resolved
// history failing must not replace the active list with the error page.
/**
* Started, not awaited, as Overview's is: the strip and the two lists each
* render their own loading and error state, and the health strip's whole
* contract begins with a visible loading state it would never reach if the
* route held the page back until the reading arrived.
*/
loader: ({ context, deps }) => {
const base = diagnosticsFilterOf(deps);
return Promise.allSettled([
context.queryClient.ensureInfiniteQueryData(diagnosticsInfiniteQuery({ ...base, state: "active" })),
context.queryClient.ensureInfiniteQueryData(diagnosticsInfiniteQuery({ ...base, state: "resolved" })),
]);
void context.queryClient.ensureQueryData(healthQuery()).catch(() => {});
for (const state of ["active", "resolved"] as const) {
void context.queryClient
.ensureInfiniteQueryData(diagnosticsInfiniteQuery({ ...base, state }))
.catch(() => {});
}
},
component: lazyRouteComponent(() => import("@/features/diagnostics/DiagnosticsPage")),
});
@@ -334,7 +376,8 @@ const settingsRoute = createRoute({
const routeTree = rootRoute.addChildren([
loginRoute,
shellRoute.addChildren([
dashboardRoute,
indexRoute,
overviewRoute,
activityRoute,
activityDetailRoute,
activityTestRoute,