milestone 27: diagnostics — operational failures land in one curated log, resolved history purgeable
Gates / frontend (push) Successful in 1m33s
Gates / test (push) Successful in 1m48s
Gates / test-aarch64 (push) Successful in 7m10s
Gates / package (push) Successful in 5m31s
Gates / container (push) Successful in 15s
CI / gates (push) Successful in 14m51s
Gates / frontend (push) Successful in 1m33s
Gates / test (push) Successful in 1m48s
Gates / test-aarch64 (push) Successful in 7m10s
Gates / package (push) Successful in 5m31s
Gates / container (push) Successful in 15s
CI / gates (push) Successful in 14m51s
This commit is contained in:
@@ -12,10 +12,13 @@ import {
|
||||
import AppShell from "@/shell/AppShell";
|
||||
import { ApiError } from "@/lib/api";
|
||||
import { createQueryClient } from "@/lib/queryClient";
|
||||
import type { DiagnosticSeverity, DiagnosticState, DiagnosticsFilter } from "@/lib/types";
|
||||
import {
|
||||
blocklistsQuery,
|
||||
clientPrefixesQuery,
|
||||
clientsQuery,
|
||||
diagnosticQuery,
|
||||
diagnosticsInfiniteQuery,
|
||||
forwardZonesQuery,
|
||||
groupsQuery,
|
||||
healthQuery,
|
||||
@@ -214,6 +217,52 @@ const lookupRoute = createRoute({
|
||||
component: lazyRouteComponent(() => import("@/features/lookup/LookupPage")),
|
||||
});
|
||||
|
||||
/**
|
||||
* The three filters live in the url so an episode can be linked to as it was
|
||||
* read. Anything else in the search object is dropped: an unknown value would
|
||||
* reach the api as a query parameter the handler rejects with a 400.
|
||||
*/
|
||||
const diagnosticsRoute = createRoute({
|
||||
getParentRoute: () => shellRoute,
|
||||
path: "/diagnostics",
|
||||
validateSearch: (
|
||||
search: Record<string, unknown>,
|
||||
): { state?: DiagnosticState; severity?: DiagnosticSeverity; component?: string } => {
|
||||
const state = search["state"];
|
||||
const severity = search["severity"];
|
||||
const component = search["component"];
|
||||
return {
|
||||
state: state === "active" || state === "resolved" ? state : undefined,
|
||||
severity: severity === "warning" || severity === "error" ? severity : undefined,
|
||||
component: typeof component === "string" && component !== "" ? component : undefined,
|
||||
};
|
||||
},
|
||||
loaderDeps: ({ search }) => search,
|
||||
// allSettled: the two sections render their own state, and the resolved
|
||||
// history failing must not replace the active list with the error page.
|
||||
loader: ({ context, deps }) => {
|
||||
const base: DiagnosticsFilter = {};
|
||||
if (deps.severity !== undefined) base.severity = deps.severity;
|
||||
if (deps.component !== undefined) base.component = deps.component;
|
||||
return Promise.allSettled([
|
||||
context.queryClient.ensureInfiniteQueryData(diagnosticsInfiniteQuery({ ...base, state: "active" })),
|
||||
context.queryClient.ensureInfiniteQueryData(diagnosticsInfiniteQuery({ ...base, state: "resolved" })),
|
||||
]);
|
||||
},
|
||||
component: lazyRouteComponent(() => import("@/features/diagnostics/DiagnosticsPage")),
|
||||
});
|
||||
|
||||
const diagnosticDetailRoute = createRoute({
|
||||
getParentRoute: () => shellRoute,
|
||||
path: "/diagnostics/$id",
|
||||
// Swallowed on purpose: an event retention has removed is a 404 the page
|
||||
// itself explains, with the way back to the list. The whole-page error
|
||||
// component would state it as a request failure instead.
|
||||
loader: ({ context, params }) =>
|
||||
context.queryClient.ensureQueryData(diagnosticQuery(Number(params.id))).catch(() => undefined),
|
||||
component: lazyRouteComponent(() => import("@/features/diagnostics/DiagnosticDetailPage")),
|
||||
});
|
||||
|
||||
const settingsRoute = createRoute({
|
||||
getParentRoute: () => shellRoute,
|
||||
path: "/settings",
|
||||
@@ -234,6 +283,8 @@ const routeTree = rootRoute.addChildren([
|
||||
localDnsRoute,
|
||||
upstreamsRoute,
|
||||
lookupRoute,
|
||||
diagnosticsRoute,
|
||||
diagnosticDetailRoute,
|
||||
settingsRoute,
|
||||
]),
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user