5.4 KiB
5.4 KiB
Phase 5: Frontend — Activity tab + smart filtering + live updates
Status: ⬜ Not Started
Parent plan: PLAN.md
Domain: frontend · uses the frontend-design skill
Objective
Build the dedicated top-level Activity tab: a read-only, smart-filterable, keyset-paginated log viewer with an entry detail view, live-append of new events, and export. This is a viewer (Dashboard-style), NOT a CRUD card section.
Tasks
core/ui.ts: addformatTimestamp(isoOrMs)(Today/Yesterday/Date · HH:MM, i18n-aware) andformatRelativeTime(isoOrMs)("2m ago"), withtabular-numsstyling guidance for the list. Reuse existingtime.*i18n key conventions.features/activity-log.ts:export async function loadActivityLog()— fetch first page fromGET /activity-log(viafetchWithAuth), render the toolbar + list into the panel.- Smart filter toolbar: category (multi, IconSelect/chips), severity (chips), actor (EntitySelect/text), entity type, date range, free-text search (debounced). Quick presets: Today / Errors / Auth / Devices. Filters drive server-side query params (no client-side filtering of a partial page). Re-query on change; reset cursor.
- List: one row per entry — severity icon, category badge, relative time (title=absolute),
actor, message, entity crosslink (use
navigateToCard(...)when the referenced entity is resolvable). Keyset "load more" (or infinite scroll) usingnext_before_seq. - Detail: expandable row / drawer showing full metadata JSON, exact timestamp, ids.
- Live append:
document.addEventListener('server:activity_logged', e => …)— prepend the new entry if it passes the active filters; show a subtle "new" affordance. (Depends on the Phase 2 allowlist entry — already shipped.) - Export button: triggers
GET /activity-log/export?format=…with current filters via an authed blob download (usefetchWithAuth→ blob URL, per frontend.md auth rules). - Empty / loading / error states; re-render on
languageChanged.
- Tab wiring:
core/tab-registry.ts: addactivity_log: { loadFnName: 'loadActivityLog', autoRefresh: false }.templates/index.html: sidebar tab button (data-tab,switchTab('activity_log'), history/clock SVG icon,data-i18n) +<div class="tab-panel" id="tab-activity_log">.app.ts: import +Object.assign(window, { loadActivityLog, … });global.d.tsdecls.
- Icons: add a history/audit icon to
core/icon-paths.ts+core/icons.ts; severity icons (info/warning/error) reuse existing constants where possible. - i18n: add
activity_log.*keys tostatic/locales/{en,ru,zh}.json(title, filter labels, category/severity names, column labels, presets, empty/error, export, "N entries"). - Tutorials: add an Activity-tab step to the getting-started tour in
features/tutorials.ts+tour.*keys in all 3 locales.
Files to Modify/Create
server/src/ledgrab/static/js/core/ui.ts— modify: timestamp/relative-time formattersserver/src/ledgrab/static/js/features/activity-log.ts— new: the viewerserver/src/ledgrab/static/js/core/tab-registry.ts— modify: register tabserver/src/ledgrab/templates/index.html— modify: tab button + panelserver/src/ledgrab/static/js/app.ts— modify: import + window globalsserver/src/ledgrab/static/js/global.d.ts— modify: window declsserver/src/ledgrab/static/js/core/icon-paths.ts/core/icons.ts— modify: iconsserver/src/ledgrab/static/locales/{en,ru,zh}.json— modify: i18n keysserver/src/ledgrab/static/js/features/tutorials.ts— modify: tour stepserver/src/ledgrab/static/css/*— modify/new: list + toolbar styling (follow base.css vars)
Acceptance Criteria
- New Activity tab loads, lists entries, and paginates via keyset "load more".
- Filters hit server-side query params; quick presets work; free-text is debounced.
- New events append live via
server:activity_loggedand respect active filters. - Export downloads CSV/JSON with auth, honoring current filters.
- Fully localized (en/ru/zh); empty/loading/error states; re-renders on language change.
- No plain
<select>(use IconSelect/EntitySelect/chips); SVG icons only (no emoji). npx tsc --noEmitclean;npm run buildsucceeds.
Notes
- Use the
frontend-designskill for the viewer layout, filter toolbar, and detail design — aim for a polished, distinctive result consistent with the app's design language and CSS variables instatic/css/base.css(--primary-color,--card-bg, etc.). - Models to mirror:
features/dashboard.ts(non-card live viewer + load pattern),core/events-ws.ts(server:<type>dispatch),core/entity-palette.ts(EntitySelect),core/icon-select.ts(IconSelect). Auth/blob download rules:contexts/frontend.md. - Frontend-only phase → run
tsc --noEmit+npm run build; do NOT run pytest/ruff.
Review Checklist
- All tasks completed
- Code follows frontend conventions (i18n ×3, icons, selectors, auth fetch, CSS vars)
- No unintended side effects
- Build passes (
tsc --noEmit+npm run build) - Manual smoke: tab loads, filters query server, live append, export