fix(activity): an old audit/log link opens its tab, times read relative, one name for admin actions

Seen in the browser, not in the page's own tests: the navigation provider rewrites a retired page id
to `activity` before the page's chunk reads the URL, so `?page=audit` landed on the Runs tab. The
retired-page map now carries the params that open the successor's part (`at`), and the provider
writes them as it rewrites the page — on load and on Back alike.

A list time is relative with the exact second on hover (the DESIGN copy rule); a run moved over from
the audit log, whose start and end are one instant, shows no length instead of an invented "1 sec".
The audit log is called "admin actions" everywhere it is named (the clear button and its confirm, the
Configuration group, the cleanup job, which also prunes the run history its description left out).
This commit is contained in:
2026-10-18 04:00:38 +02:00
parent fe6308d844
commit c288ba147b
18 changed files with 133 additions and 92 deletions
+2 -8
View File
@@ -54,10 +54,6 @@ export const DEFAULT_ACTIVITY_STATE: ActivityUrlState = {
const OWN_KEYS = ["at", "aw", "au", "aq", "rjob", "rst", "aact"] as const;
export const ACTIVITY_KEYS = [...OWN_KEYS, ...LOGS_KEYS] as const;
// The pages this one replaced: a link or a bookmark to one opens its tab here (urlState's RETIRED
// sends the page id itself here).
const RETIRED_TAB: Readonly<Record<string, ActivityTab>> = { audit: "admin", logs: "logs" };
// The same shapes the API validates: a hand-edited link degrades to "no filter" here instead of to
// a 422 on every request the page makes.
const USER_RE = /^(none|\d{1,10})$/;
@@ -71,10 +67,8 @@ const oneOf = <T extends string>(value: string | null, list: readonly T[]): T |
export function activityParamsToState(params: URLSearchParams): ActivityUrlState {
return {
tab:
oneOf(params.get("at"), ACTIVITY_TABS) ??
RETIRED_TAB[params.get("page") ?? ""] ??
DEFAULT_ACTIVITY_STATE.tab,
// A link to a page this one replaced arrives with its tab already set (urlState's RETIRED).
tab: oneOf(params.get("at"), ACTIVITY_TABS) ?? DEFAULT_ACTIVITY_STATE.tab,
window: oneOf(params.get("aw"), ACTIVITY_WINDOWS) ?? DEFAULT_ACTIVITY_STATE.window,
user: pick(params.get("au"), USER_RE, 10),
q: (params.get("aq") ?? "").slice(0, Q_MAX),