From a8dfbd5dc631cdb1c4131ee158c406960eea2b55 Mon Sep 17 00:00:00 2001 From: Developer Date: Fri, 26 Jun 2026 20:11:02 +0000 Subject: [PATCH] Cleanup: delete dead top-level pages + update docs (Slice 11) Delete the old top-level page files whose content was migrated into service-page tabs in slices 5-9: - pages/Media.tsx, Applications.tsx (-> MediaTab) - pages/FileBrowser.tsx, FileBrowser.impl.tsx (-> FilesTab) - pages/Actions.tsx (-> ActionsTab) - pages/Users.tsx, UsersPage.impl.tsx (replaced by Authentik tabs) - components/BackupsPage.tsx (-> JobsTab) - components/ObservabilityPage.tsx (split into Alerts/Links/Metrics tabs) - hooks/useUsers.ts (orphaned after Users page deletion) - the corresponding page test files (Media, FileBrowser, Applications, Actions, UsersPage) that tested the deleted pages directly. The service-tab components are the live implementations; ServicePage renders them. No live code references the deleted files. Docs: append an Information Architecture section to REQUIREMENTS.md documenting the services-as-hub model (nav shape, service-page tabs, service type registry, Users->Authentik, Observability split, legacy route 404s, empty state). Add a CHANGELOG entry under [Unreleased]. 92 frontend tests pass (was 112; -20 deleted page tests); 271 backend tests pass; lint/build green. Refs openspec/changes/services-as-hub-ia/ (tasks slice 11). --- .pi-tmp/followup1-wiring-out.md | 88 ++ .pi-tmp/followup2-out.md | 46 + .pi-tmp/slice1-review.md | 186 ++++ .pi-tmp/slice1-worker-out.md | 63 ++ .pi-tmp/slice2-review.md | 192 ++++ .pi-tmp/slice2-worker-out.md | 70 ++ .pi-tmp/slice3-review.md | 142 +++ .pi-tmp/slice3-worker-out.md | 72 ++ .pi-tmp/slice4-worker-out.md | 72 ++ .pi-tmp/slice5-review.md | 189 ++++ .pi-tmp/slice5-worker-out.md | 95 ++ .pi-tmp/slice6-review.md | 120 +++ .pi-tmp/slice6-worker-out.md | 88 ++ .pi-tmp/slice7-worker-out.md | 126 +++ .pi-tmp/slice8-review.md | 179 ++++ .pi-tmp/slice8-worker-out.md | 73 ++ .pi-tmp/slice9-worker-out.md | 214 ++++ .pi-tmp/svc-hub-slice1-out.md | 112 ++ .pi-tmp/svc-hub-slice10-out.md | 119 +++ .pi-tmp/svc-hub-slice2-out.md | 143 +++ .pi-tmp/svc-hub-slice3-out.md | 132 +++ .pi-tmp/svc-hub-slice4-out.md | 133 +++ .pi-tmp/svc-hub-slice4-review.md | 191 ++++ .pi-tmp/svc-hub-slice5-out.md | 62 ++ .pi-tmp/svc-hub-slice6-out.md | 118 +++ .pi-tmp/svc-hub-slice7-out.md | 116 +++ .pi-tmp/svc-hub-slice8-out.md | 98 ++ .pi-tmp/svc-hub-slice9-out.md | 136 +++ CHANGELOG.md | 26 + docs/REQUIREMENTS.md | 40 + frontend/src/components/BackupsPage.tsx | 72 -- frontend/src/components/ObservabilityPage.tsx | 667 ------------ frontend/src/hooks/useUsers.ts | 11 - frontend/src/pages/Actions.tsx | 549 ---------- frontend/src/pages/Applications.tsx | 133 --- frontend/src/pages/FileBrowser.impl.tsx | 862 --------------- frontend/src/pages/FileBrowser.tsx | 1 - frontend/src/pages/Media.tsx | 564 ---------- frontend/src/pages/Users.tsx | 1 - frontend/src/pages/UsersPage.impl.tsx | 983 ------------------ frontend/src/pages/__tests__/Actions.test.tsx | 125 --- .../src/pages/__tests__/Applications.test.tsx | 75 -- .../src/pages/__tests__/FileBrowser.test.tsx | 120 --- frontend/src/pages/__tests__/Media.test.tsx | 263 ----- .../src/pages/__tests__/UsersPage.test.tsx | 285 ----- 45 files changed, 3441 insertions(+), 4711 deletions(-) create mode 100644 .pi-tmp/followup1-wiring-out.md create mode 100644 .pi-tmp/followup2-out.md create mode 100644 .pi-tmp/slice1-review.md create mode 100644 .pi-tmp/slice1-worker-out.md create mode 100644 .pi-tmp/slice2-review.md create mode 100644 .pi-tmp/slice2-worker-out.md create mode 100644 .pi-tmp/slice3-review.md create mode 100644 .pi-tmp/slice3-worker-out.md create mode 100644 .pi-tmp/slice4-worker-out.md create mode 100644 .pi-tmp/slice5-review.md create mode 100644 .pi-tmp/slice5-worker-out.md create mode 100644 .pi-tmp/slice6-review.md create mode 100644 .pi-tmp/slice6-worker-out.md create mode 100644 .pi-tmp/slice7-worker-out.md create mode 100644 .pi-tmp/slice8-review.md create mode 100644 .pi-tmp/slice8-worker-out.md create mode 100644 .pi-tmp/slice9-worker-out.md create mode 100644 .pi-tmp/svc-hub-slice1-out.md create mode 100644 .pi-tmp/svc-hub-slice10-out.md create mode 100644 .pi-tmp/svc-hub-slice2-out.md create mode 100644 .pi-tmp/svc-hub-slice3-out.md create mode 100644 .pi-tmp/svc-hub-slice4-out.md create mode 100644 .pi-tmp/svc-hub-slice4-review.md create mode 100644 .pi-tmp/svc-hub-slice5-out.md create mode 100644 .pi-tmp/svc-hub-slice6-out.md create mode 100644 .pi-tmp/svc-hub-slice7-out.md create mode 100644 .pi-tmp/svc-hub-slice8-out.md create mode 100644 .pi-tmp/svc-hub-slice9-out.md delete mode 100644 frontend/src/components/BackupsPage.tsx delete mode 100644 frontend/src/components/ObservabilityPage.tsx delete mode 100644 frontend/src/hooks/useUsers.ts delete mode 100644 frontend/src/pages/Actions.tsx delete mode 100644 frontend/src/pages/Applications.tsx delete mode 100644 frontend/src/pages/FileBrowser.impl.tsx delete mode 100644 frontend/src/pages/FileBrowser.tsx delete mode 100644 frontend/src/pages/Media.tsx delete mode 100644 frontend/src/pages/Users.tsx delete mode 100644 frontend/src/pages/UsersPage.impl.tsx delete mode 100644 frontend/src/pages/__tests__/Actions.test.tsx delete mode 100644 frontend/src/pages/__tests__/Applications.test.tsx delete mode 100644 frontend/src/pages/__tests__/FileBrowser.test.tsx delete mode 100644 frontend/src/pages/__tests__/Media.test.tsx delete mode 100644 frontend/src/pages/__tests__/UsersPage.test.tsx diff --git a/.pi-tmp/followup1-wiring-out.md b/.pi-tmp/followup1-wiring-out.md new file mode 100644 index 0000000..f64dc7e --- /dev/null +++ b/.pi-tmp/followup1-wiring-out.md @@ -0,0 +1,88 @@ +# Follow-up 1 — SheetForm isDirty wiring (worker output) + +## Task + +Wire the new `isDirty` prop of `SheetForm` into three remaining form consumers (Settings machine editor, message compose, WidgetConfigDialog) so unsaved edits trigger a "Discard changes?" confirm before closing. + +## Files changed (this worker's scope) + +| File | Status | Lines | +|------|--------|-------| +| `frontend/src/pages/Settings.tsx` | modified | +25 (isMachineDraftDirty helper + isDirty prop) | +| `frontend/src/pages/UsersPage.impl.tsx` | modified | +5 (isDirty prop on compose SheetForm) | +| `frontend/src/components/WidgetConfigDialog.tsx` | modified | +1 (isDirty prop) | +| `frontend/src/pages/__tests__/Settings.test.tsx` | modified | +23 (dirty guard test) | +| `frontend/src/pages/__tests__/UsersPage.test.tsx` | modified | +31 (compose dirty guard test) | +| `frontend/src/components/__tests__/WidgetConfigDialog.test.tsx` | modified | +14 (draft dirty guard test) | + +**Total: ~99 changed lines** — well under the 250-line budget. + +## isDirty expressions per consumer + +### 1. Settings machine editor (`Settings.tsx`) + +Helper function `isMachineDraftDirty(draft, editingMachine)`: + +- **Create mode** (`editingMachine === null`): always dirty (return `true`). +- **Edit mode**: field-by-field comparison of user-editable fields: + - `name`, `host`, `mode`, `port`, `username`, `ssh_key_id`, `enabled`, `notes` + - `services` array (sorted JSON.stringify comparison for order-insensitivity) + +```ts +function isMachineDraftDirty(draft, editingMachine): boolean { + if (!editingMachine) return true; + return ( + draft.name !== editingMachine.name || + draft.host !== editingMachine.host || + draft.mode !== editingMachine.mode || + draft.port !== editingMachine.port || + draft.username !== editingMachine.username || + draft.ssh_key_id !== editingMachine.ssh_key_id || + draft.enabled !== editingMachine.enabled || + draft.notes !== editingMachine.notes || + JSON.stringify([...draft.services].sort()) !== + JSON.stringify([...editingMachine.services].sort()) + ); +} +``` + +Note: `node_exporter_scrape_host` (mentioned in the task) does not exist in either `MonitoringMachine` or `MonitoringMachineInput` in this codebase. The comparable editable fields were used instead. Secret fields (`ssh_private_key`, `password`) are excluded because they're write-only (the original only has `*_set` booleans, not values). + +### 2. Message compose (`UsersPage.impl.tsx`) + +```ts +isDirty={ + subject.trim() !== "" || + htmlBody.trim() !== DEFAULT_HTML_BODY.trim() || + attachments.length > 0 +} +``` + +### 3. WidgetConfigDialog (`WidgetConfigDialog.tsx`) + +```ts +isDirty={draft !== null} +``` + +Dirty only in draft mode (when adding/editing a widget). In list mode, `draft === null` → `isDirty = false` (nothing to discard). In draft mode, `onCancel={reset}` returns to the list (does NOT close the sheet), so `isDirty` prompts before resetting the draft. + +## Validation + +``` +npm run lint → 0 errors, 2 pre-existing warnings (UsersPage.impl.tsx exhaustive-deps) +npm run build → ✓ built (tsc -b + vite) +npm run test → 28 files / 122 tests passed (was 119; +3 new dirty-guard tests) +``` + +## Deviations from task + +1. **`node_exporter_scrape_host` field**: mentioned in the task but does not exist in the type definitions. Used the actual editable fields that exist on both `MonitoringMachine` and `MonitoringMachineInput`. +2. **Secret fields excluded from dirty check**: `ssh_private_key`, `password`, `ssh_private_key_passphrase` are write-only on the draft and have no comparable value on `editingMachine` (which only has `*_set` booleans). Including them would make the form always dirty in edit mode. + +## skill_resolution + +`none` — no project/user SKILL.md paths were injected; no `.atl/skill-registry.md` found. + +## Residual risks + +- None for this worker's scope. The SheetForm primitive and ServicePage wiring were done by the parent and are not touched here. diff --git a/.pi-tmp/followup2-out.md b/.pi-tmp/followup2-out.md new file mode 100644 index 0000000..552cc97 --- /dev/null +++ b/.pi-tmp/followup2-out.md @@ -0,0 +1,46 @@ +# Follow-up 2 — Touch-target pass on default-size buttons + +## Task + +Apply `.mobile-touch-target` to default-size `