From ccfbfd194a2f654fa9b06f752ae16e63e36cd7ba Mon Sep 17 00:00:00 2001 From: Saravana Kumar Date: Sat, 30 May 2026 19:53:16 +0000 Subject: [PATCH] feat(tracker-web): add admin settings page --- dashboards/tracker-web/e2e/tracker.spec.ts | 19 +++ .../tracker-web/src/app/dashboard/layout.tsx | 1 + .../src/app/dashboard/settings/page.tsx | 109 ++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 dashboards/tracker-web/src/app/dashboard/settings/page.tsx diff --git a/dashboards/tracker-web/e2e/tracker.spec.ts b/dashboards/tracker-web/e2e/tracker.spec.ts index abb0d282..6b11ecab 100644 --- a/dashboards/tracker-web/e2e/tracker.spec.ts +++ b/dashboards/tracker-web/e2e/tracker.spec.ts @@ -275,6 +275,25 @@ test.describe('Tracker — Authenticated dashboard', () => { await expect(page.getByText('42')).toBeVisible(); await expect(page.getByText('admin@example.com')).toBeVisible(); }); + + test('renders settings for admin configuration', async ({ page }) => { + await page.route('**/api/auth/me', (route: Route) => + route.fulfill({ + json: { id: 'u1', email: 'admin@example.com', role: 'admin', displayName: 'Admin' }, + }) + ); + + await page.addInitScript(() => localStorage.setItem('tracker_token', 'fake-e2e-token')); + await page.goto('/dashboard/settings'); + await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Product context' })).toBeVisible(); + await expect(page.getByLabel('Default product ID')).toBeVisible(); + await expect(page.getByText('/api/tracker/[...path]')).toBeVisible(); + await expect(page.getByRole('link', { name: /open public roadmap/i })).toHaveAttribute( + 'href', + '/roadmap' + ); + }); }); // ── Public roadmap (mocked) ───────────────────────────────────────── diff --git a/dashboards/tracker-web/src/app/dashboard/layout.tsx b/dashboards/tracker-web/src/app/dashboard/layout.tsx index 664bdbf1..9411d969 100644 --- a/dashboards/tracker-web/src/app/dashboard/layout.tsx +++ b/dashboards/tracker-web/src/app/dashboard/layout.tsx @@ -24,6 +24,7 @@ const NAV_ITEMS = [ { href: '/dashboard/items', label: 'Items' }, { href: '/dashboard/board', label: 'Board' }, { href: '/dashboard/fleet', label: 'Fleet' }, + { href: '/dashboard/settings', label: 'Settings' }, ]; /** Open the ⌘K command palette by replaying the global hotkey. */ diff --git a/dashboards/tracker-web/src/app/dashboard/settings/page.tsx b/dashboards/tracker-web/src/app/dashboard/settings/page.tsx new file mode 100644 index 00000000..33b714f0 --- /dev/null +++ b/dashboards/tracker-web/src/app/dashboard/settings/page.tsx @@ -0,0 +1,109 @@ +'use client'; + +import Link from 'next/link'; +import { useEffect, useState } from 'react'; + +const DEFAULT_PRODUCT = 'tracker'; + +export default function SettingsPage() { + const [productId, setProductId] = useState(DEFAULT_PRODUCT); + const [saved, setSaved] = useState(false); + + useEffect(() => { + const selected = localStorage.getItem('tracker_selected_product'); + if (selected) setProductId(selected); + }, []); + + function saveProductContext() { + localStorage.setItem('tracker_selected_product', productId.trim() || DEFAULT_PRODUCT); + window.dispatchEvent(new Event('tracker:product-changed')); + setSaved(true); + window.setTimeout(() => setSaved(false), 2500); + } + + return ( +
+
+

+ Admin +

+

Settings

+

+ Configure the tracker dashboard context, public roadmap links, and integration surfaces + used by humans, agents, and external systems. +

+
+ +
+
+

Product context

+

+ Tracker is product-aware. This value is sent as the selected product context for + internal tracker calls. +

+ + setProductId(event.target.value)} + className="mt-2 w-full rounded-lg border border-border bg-background px-3 py-2 text-sm" + placeholder="tracker" + /> + + {saved ?

Saved product context.

: null} +
+ +
+

Public roadmap

+

+ Share the roadmap and submission status pages with public users without requiring a + login. +

+
+
+ Roadmap: /roadmap +
+
+ Submission status: /status/<itemId> +
+
+ + Open public roadmap + +
+
+ +
+

Integration surfaces

+

+ These are the web-facing route groups that connect the dashboard to platform-service. +

+
+ {[ + ['/api/tracker/[...path]', 'Authenticated tracker and public roadmap proxy'], + ['/api/fleet/[...path]', 'Agent/fleet control-plane proxy'], + ['/api/auth/*', 'Login, MFA, OAuth, and session lookup'], + ['/api/telemetry/ingest', 'Client telemetry ingestion'], + ['/api/health', 'Readiness and platform-service dependency probe'], + ].map(([route, description]) => ( +
+ {route} +

{description}

+
+ ))} +
+
+
+ ); +}