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
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:
+63
-20
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user