a6c3fbfe504aa02a73c321dbdd882854330b69bd
New card in admin.html/admin.js, above the old per-browser Usage logs
card (which T11.6 retires next). Filters (date range, project, user,
tool) drive GET /api/usage/summary; two export buttons call
GET /api/usage/export (raw / sanitized) and save the CSV via a Blob,
same download pattern wp-usage.js already uses.
Access: the card lives inside admin.html, already gated admin-only
client-side by gateByRole() (unchanged) - a non-admin never sees the
card. The underlying API is gated server-side by require_user_manager
regardless (admin or project_super_user on >=1 project), independent
of and stricter than the client-side gate, so a non-admin request is
refused even if someone reached the endpoint directly.
Accessibility (C1): every control is a real <input>/<select>/<button>,
keyboard-operable. Status/export banners use the existing '.banner' /
'*-banner' id convention, which console-util.js's MutationObserver
already turns into aria-live (role=status, or role=alert on a '.bad'
banner) - no new announcement plumbing needed. No new CSS: reuses
.toolbar/.banner/.card/.row/.kv/.users, so nothing here adds a second
token source (the token rule).
Verified so far:
- node --check html/admin.js: no syntax errors
- every id admin.js's new code references exists in admin.html
(scripted diff against the full getElementById/id= sets)
- live-server check: GET /api/usage/summary with the exact
(possibly-empty) query string _activityFilters() builds returns
the {active_users, per_user_last_active, by_tool, event_count}
shape renderActivity() expects; project_id filter narrows
correctly; GET /api/usage/export?sanitize=true returns
text/csv with the expected header row
- full smoke test + seed_demo.py still pass
NOT yet verified: rendering at 390px/1440px with before/after
screenshots (CLAUDE.md verification step). This sandbox has no
headless-capable browser (no chromium/msedge on PATH) and the
playwright/chromium download is blocked by this environment's
network allowlist, so tests/cdp.py's harness can't run here. Deferred
to T11.7, same as wave 10's browser checks — flagging rather than
skipping silently.
Description
No description provided
Languages
Python
49.3%
JavaScript
32.6%
CSS
8.9%
HTML
8.7%
Shell
0.4%