diff --git a/job-tracker-ui/src/App.tsx b/job-tracker-ui/src/App.tsx
index e4a94d5a..ac441ee3 100644
--- a/job-tracker-ui/src/App.tsx
+++ b/job-tracker-ui/src/App.tsx
@@ -161,6 +161,10 @@ function titleFor(path: string, t: (k: any) => string): string {
}
function subtitleFor(path: string, t: (k: any) => string): string | undefined {
+ if (path.startsWith("/admin/audit")) return t("adminAuditSubtitle");
+ if (path.startsWith("/admin/users")) return t("adminUsersSubtitle");
+ if (path.startsWith("/admin/system")) return t("adminSystemSubtitle");
+ if (path.startsWith("/admin/processing")) return t("processingSubtitle");
if (/^\/settings\/?$/.test(path)) return t("settingsPageDescription");
if (path === "/dashboard") return t("dashboardPageSubtitle");
if (path.startsWith("/analytics")) return t("analyticsPageSubtitle");
diff --git a/job-tracker-ui/src/admin-audit-page.test.tsx b/job-tracker-ui/src/admin-audit-page.test.tsx
index 70279f2e..e0d7cd3a 100644
--- a/job-tracker-ui/src/admin-audit-page.test.tsx
+++ b/job-tracker-ui/src/admin-audit-page.test.tsx
@@ -37,8 +37,8 @@ test("[P7-10 audit] retains shared heading hierarchy and a named keyboard scroll
mockedApi.get.mockResolvedValue({ data: [row] } as any);
renderPage();
await screen.findByRole("button", { name: "Undo" });
- expect(screen.getByRole("heading", { name: "Audit log", level: 2 })).toBeInTheDocument();
- expect(screen.getByRole("heading", { name: translations.en.adminAuditEvents, level: 3 })).toBeInTheDocument();
+ expect(screen.queryByRole("heading", { name: /^Audit log$/ })).not.toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: translations.en.adminAuditEvents, level: 2 })).toBeInTheDocument();
const region = screen.getByRole("region", { name: "Audit log" });
expect(region).toHaveAttribute("tabindex", "0");
expect(within(region).getByRole("table")).toHaveAccessibleName("Audit log");
@@ -104,7 +104,7 @@ test("distinguishes an unavailable audit log from an empty audit log and retries
mockedApi.get.mockRejectedValueOnce(new Error("offline"));
renderPage();
- expect(screen.getByRole("heading", { name: "Audit log", level: 2 })).toBeInTheDocument();
+ expect(screen.getByRole("region", { name: /^Audit log$/ })).toBeInTheDocument();
expect(await screen.findByText("Unable to load audit events")).toBeInTheDocument();
expect(screen.queryByText("No events.")).not.toBeInTheDocument();
diff --git a/job-tracker-ui/src/admin-system-page.test.tsx b/job-tracker-ui/src/admin-system-page.test.tsx
index 77eab3d3..1be9f864 100644
--- a/job-tracker-ui/src/admin-system-page.test.tsx
+++ b/job-tracker-ui/src/admin-system-page.test.tsx
@@ -176,7 +176,8 @@ describe('AdminSystemPage', () => {
it('uses contextual system headings and keeps metric values out of heading navigation', async () => {
render();
await screen.findByText('Production');
- expect(screen.getByRole('heading', { name: 'System status', level: 2 })).toBeInTheDocument();
+ expect(screen.getByRole('region', { name: 'System status' })).toBeInTheDocument();
+ expect(screen.queryByRole('heading', { name: 'System status' })).not.toBeInTheDocument();
expect(screen.queryByRole('heading', { name: 'Production' })).not.toBeInTheDocument();
const levels = screen.getAllByRole('heading').map(heading => Number(heading.tagName.slice(1)));
let previous = 1;
diff --git a/job-tracker-ui/src/admin-users-page.test.tsx b/job-tracker-ui/src/admin-users-page.test.tsx
index c58cd982..13587088 100644
--- a/job-tracker-ui/src/admin-users-page.test.tsx
+++ b/job-tracker-ui/src/admin-users-page.test.tsx
@@ -96,7 +96,7 @@ test('disposed create acknowledgement cannot start a new private list read', asy
test("requires explicit confirmation before removing your own admin role", async () => {
renderPage([{ id: "me", email: "me@example.com", userName: "me", roles: ["Admin"], emailConfirmed: true, isCurrentUser: true, canRemoveAdmin: true }]);
- expect(screen.getByRole("heading", { name: "Users", level: 2 })).toBeInTheDocument();
+ expect(screen.getByRole("heading", { name: "Create user", level: 2 })).toBeInTheDocument();
fireEvent.click(await screen.findByRole("button", { name: "Remove admin" }));
expect(await screen.findByText(/you will immediately lose access/i)).toBeInTheDocument();
diff --git a/job-tracker-ui/src/views/AdminAuditPage.tsx b/job-tracker-ui/src/views/AdminAuditPage.tsx
index 860bb566..8540976f 100644
--- a/job-tracker-ui/src/views/AdminAuditPage.tsx
+++ b/job-tracker-ui/src/views/AdminAuditPage.tsx
@@ -18,7 +18,7 @@ import { useToast } from "../toast";
import { useI18n } from "../i18n/I18nProvider";
import { useViewResource } from "../hooks/useViewResource";
import ViewStateNotice from "../components/ViewStateNotice";
-import { PageHeader, PageSection } from "../layout/PageLayout";
+import { PageSection } from "../layout/PageLayout";
import { checkSessionCookie, getSessionContext, isSessionInvalidated } from "../sessionBoundary";
type AuditItem = {
@@ -86,8 +86,7 @@ export default function AdminAuditPage() {
return (
-
-
+
{ pausedRef.current = false; setPaused(false); setBefore(null); setRefresh(value => value + 1); };
const visibleListing = identity === getAuthUserKey() ? listing : null;
return
-
diff --git a/job-tracker-ui/src/views/AdminSystemPage.tsx b/job-tracker-ui/src/views/AdminSystemPage.tsx
index c3432229..24275e6b 100644
--- a/job-tracker-ui/src/views/AdminSystemPage.tsx
+++ b/job-tracker-ui/src/views/AdminSystemPage.tsx
@@ -17,7 +17,7 @@ import {
import { api, getApiErrorMessage } from "../api";
import { useI18n } from "../i18n/I18nProvider";
-import { PageHeader, PageSection } from "../layout/PageLayout";
+import { PageSection } from "../layout/PageLayout";
import type { TranslationKey } from "../i18n/translations";
import { checkSessionCookie, getSessionContext, isSessionInvalidated } from "../sessionBoundary";
@@ -250,7 +250,6 @@ export default function AdminSystemPage() {
const passwordRevision = useRef(0);
const savedRevision = useRef(0);
const bodyRef = useRef(null);
- const headingRef = useRef(null);
const restoreFocus = useRef(null);
const navigationId = useId();
@@ -302,7 +301,6 @@ export default function AdminSystemPage() {
restoreFocus.current = null;
if (document.activeElement !== bodyRef.current) return;
if (target.isConnected && !target.matches(":disabled")) target.focus();
- else headingRef.current?.focus();
}, [loading, action]);
const rememberFocus = () => {
@@ -422,21 +420,20 @@ export default function AdminSystemPage() {
return (
-
-
-
- } />
+
+
+
+
setTab(value)} variant="scrollable" scrollButtons="auto" allowScrollButtonsMobile>
@@ -484,7 +481,7 @@ export default function AdminSystemPage() {
-
+
@@ -501,7 +498,7 @@ export default function AdminSystemPage() {
-
+
@@ -518,7 +515,7 @@ export default function AdminSystemPage() {
-
+
@@ -529,7 +526,7 @@ export default function AdminSystemPage() {
-
+
@@ -550,7 +547,7 @@ export default function AdminSystemPage() {
-
+
{t("adminSystemRequests")}{status?.ai.requests ?? 0}
{t("adminSystemCacheHits")}{status?.ai.cacheHits ?? 0}
@@ -577,7 +574,7 @@ export default function AdminSystemPage() {
-
+
@@ -619,7 +616,7 @@ export default function AdminSystemPage() {
- {t("adminBenchmarkTopFindings")}
+ {t("adminBenchmarkTopFindings")}
{benchmarkFindings.length > 0 ? benchmarkFindings.map((finding) => (
@@ -631,7 +628,7 @@ export default function AdminSystemPage() {
- {t("adminBenchmarkWeakest")}
+ {t("adminBenchmarkWeakest")}
{weakestEntries.map((entry) => (
@@ -649,7 +646,7 @@ export default function AdminSystemPage() {
- {t("adminBenchmarkLatestSummary")}
+ {t("adminBenchmarkLatestSummary")}
{benchmarkStatus?.reportMarkdown || "-"}
@@ -668,7 +665,7 @@ export default function AdminSystemPage() {
{readNotice("email")}
- {emailSettings ?
+ {emailSettings ?
{t("adminSystemEmailSettingsBody")}
: null}
-
+
{t("adminSystemSmtpTestBody")}
diff --git a/job-tracker-ui/src/views/AdminUsersPage.tsx b/job-tracker-ui/src/views/AdminUsersPage.tsx
index c8966930..8423bc49 100644
--- a/job-tracker-ui/src/views/AdminUsersPage.tsx
+++ b/job-tracker-ui/src/views/AdminUsersPage.tsx
@@ -23,7 +23,7 @@ import { useDialogActions } from "../dialogs";
import { useI18n } from "../i18n/I18nProvider";
import { useViewResource } from "../hooks/useViewResource";
import ViewStateNotice from "../components/ViewStateNotice";
-import { PageHeader, PageSection } from "../layout/PageLayout";
+import { PageSection } from "../layout/PageLayout";
import { checkSessionCookie, getSessionContext, isSessionInvalidated } from "../sessionBoundary";
type UserDto = {
@@ -222,10 +222,9 @@ export default function AdminUsersPage() {
return (
-
{t("adminUsersSafetyNotice")}
-
+
{ event.preventDefault(); void createUser(); }}>
setNewEmail(e.target.value)} fullWidth />