a8dfbd5dc6
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).
119 lines
7.9 KiB
Markdown
119 lines
7.9 KiB
Markdown
# Slice 6 — ssh_tasks content tabs: Files + Actions (worker output)
|
|
|
|
## Files changed
|
|
|
|
| File | Status | Lines |
|
|
|------|--------|-------|
|
|
| `frontend/src/pages/service-tabs/FilesTab.tsx` | new | 528 |
|
|
| `frontend/src/pages/service-tabs/ActionsTab.tsx` | new | 308 |
|
|
| `frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx` | new | 63 |
|
|
| `frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx` | new | 49 |
|
|
| `frontend/src/pages/service-tabs/index.ts` | modified | +4/-4 (import real FilesTab/ActionsTab) |
|
|
| `frontend/src/pages/service-tabs/stubs.tsx` | modified | -8 (removed FilesTab/ActionsTab stubs) |
|
|
| `frontend/src/pages/service-tabs/MediaTab.tsx` | modified | +10/-1 (row-click nav fix) |
|
|
| `frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx` | modified | +4 (mock useServiceInstances) |
|
|
|
|
**Total: ~967 lines** (948 new + 27 modified diff). Over the 400-line budget; dominated by the verbatim lift of the FileBrowser content (~528 lines) and Actions content (~308 lines). The genuine new-logic delta is ~30 lines (instance wiring + row-click fix + tests).
|
|
|
|
## How instance.id is wired into hooks
|
|
|
|
**FilesTab**: `instance.id` replaces the old `machine_id` from search params. All hooks (`useDirectoryListing`, `useFfprobe`, `useRunJob`) receive `instance.id` directly as the machineId parameter. The machine-tab selector (`TabbedCard` + `useMonitoringSettings`), the machine_id search-param logic, and the "no file machines" fallback are all removed. The initial path is read from `?path=` search param for deep-link support.
|
|
|
|
**ActionsTab**: `instance.id` is used as the fixed `runServiceId` — the old `useServiceInstances("ssh_tasks")` call and the service selector dropdown are removed. Tasks run on this instance by default. The task editor dialog no longer has a "Default SSH task service" dropdown (the instance is implicit). The `services` prop on `TaskEditor`/`TaskDialog` is removed entirely since the instance is fixed.
|
|
|
|
## MediaTab row-click resolution (cross-slice fix from slice 5)
|
|
|
|
The old row-click navigated to `/files?path=...` (legacy route, now 404s). Fixed:
|
|
|
|
```tsx
|
|
const { data: sshServices = [] } = useServiceInstances("ssh_tasks");
|
|
|
|
const handleRowClick = (row: MediaItem) => {
|
|
const sshInstance = sshServices.find((s) => s.enabled);
|
|
const base = sshInstance
|
|
? `/services/ssh_tasks/${sshInstance.id}`
|
|
: "/services/ssh_tasks";
|
|
navigate(`${base}?path=${encodeURIComponent(row.path)}`);
|
|
};
|
|
```
|
|
|
|
If an enabled ssh_tasks instance exists, the link opens its service page with the path query param (FilesTab reads `?path=`). If none exists, the link goes to `/services/ssh_tasks` (ServiceTypePage empty state / resolver).
|
|
|
|
## Validation
|
|
|
|
```
|
|
npm run lint → 0 errors, 2 pre-existing warnings (UsersPage.impl.tsx, unrelated)
|
|
npm run build → ✓ built (tsc -b + vite)
|
|
npm run test → 29 files / 94 tests passed (was 90; +4 new)
|
|
```
|
|
|
|
## Deviations from design
|
|
|
|
1. **Over 400-line budget.** The FilesTab lift is ~528 lines because it includes all the ffprobe rendering helpers + component logic verbatim from FileBrowser.impl.tsx. ActionsTab is ~308 lines. Could not shrink without dropping features. The task explicitly acknowledged this: "FileBrowser.impl.tsx is large; the lift is mostly mechanical."
|
|
|
|
2. **ActionsTab simplified: no service-selector dropdown.** The old Actions page had a "Default SSH task service" dropdown in both the editor and the run pane, using `useServiceInstances("ssh_tasks")`. Since the tab is already on a specific instance, the run service is always `instance.id`. The dropdown and the `services` prop on TaskEditor/TaskDialog are removed. The `NONE` sentinel constant is also removed.
|
|
|
|
3. **No mobile layout.** This branch is based on main, NOT on mobile-responsive-parity. FilesTab lifts main's DataTable + column-visibility pattern (no MobileCardRow).
|
|
|
|
4. **Old page files kept.** FileBrowser.impl.tsx and Actions.tsx stay in the repo (cleanup is Slice 11). Their test files still pass since they render the page components directly.
|
|
|
|
## skill_resolution
|
|
|
|
`none` — no project/user SKILL.md paths were injected; no `.atl/skill-registry.md` found.
|
|
|
|
## Residual risks
|
|
|
|
- **FilesTab and ActionsTab duplicate code** from their old top-level pages. The duplicates are temporary (Slice 11 deletes the old pages).
|
|
- **ActionsTab removed the service-selector dropdown.** If users need to run a task on a DIFFERENT ssh_tasks instance (not the current one), they'd need to switch instances via the service page's instance switcher. This is consistent with the new IA (each instance has its own page).
|
|
- **MediaTab now depends on `useServiceInstances("ssh_tasks")`.** This adds a TanStack Query call but it's cache-shared with other ssh_tasks queries.
|
|
|
|
```acceptance-report
|
|
{
|
|
"criteriaSatisfied": [
|
|
{
|
|
"id": "criterion-1",
|
|
"status": "satisfied",
|
|
"evidence": "Slice 6 implements FilesTab (lift from FileBrowser.impl.tsx, instance-scoped hooks, ?path= deep-link), ActionsTab (lift from Actions.tsx, instance as default run service), resolves the MediaTab row-click cross-slice dependency (navigate to /services/ssh_tasks/<id>?path=...), and adds tests for both tabs. No scope widening: only service-tab files + MediaTab row-click + test mock touched. Old page files preserved for Slice 11. 94 tests pass; lint/build green."
|
|
}
|
|
],
|
|
"changedFiles": [
|
|
"frontend/src/pages/service-tabs/FilesTab.tsx",
|
|
"frontend/src/pages/service-tabs/ActionsTab.tsx",
|
|
"frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx",
|
|
"frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx",
|
|
"frontend/src/pages/service-tabs/index.ts",
|
|
"frontend/src/pages/service-tabs/stubs.tsx",
|
|
"frontend/src/pages/service-tabs/MediaTab.tsx",
|
|
"frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx"
|
|
],
|
|
"testsAddedOrUpdated": [
|
|
"frontend/src/pages/service-tabs/__tests__/FilesTab.test.tsx",
|
|
"frontend/src/pages/service-tabs/__tests__/ActionsTab.test.tsx",
|
|
"frontend/src/pages/service-tabs/__tests__/MediaTab.test.tsx"
|
|
],
|
|
"commandsRun": [
|
|
{ "command": "cd frontend && npm run lint", "result": "passed", "summary": "0 errors, 2 pre-existing warnings" },
|
|
{ "command": "cd frontend && npm run build", "result": "passed", "summary": "tsc -b + vite build clean" },
|
|
{ "command": "cd frontend && npm run test", "result": "passed", "summary": "29 files / 94 tests passed (was 90; +4 new)" }
|
|
],
|
|
"validationOutput": [
|
|
"FilesTab: instance.id wired into useDirectoryListing/useFfprobe/useRunJob; ?path= read from useSearchParams; machine selector removed.",
|
|
"ActionsTab: instance.id used as fixed runServiceId; service-selector dropdown removed; TaskEditor/TaskDialog simplified.",
|
|
"MediaTab row-click: navigates to /services/ssh_tasks/<first-enabled-id>?path=... (resolves slice 5 cross-slice flag).",
|
|
"stubs.tsx: FilesTab/ActionsTab stubs removed; index.ts imports real components.",
|
|
"MediaTab.test.tsx: useServiceInstances mock added to fix QueryClient error."
|
|
],
|
|
"residualRisks": [
|
|
"FilesTab/ActionsTab duplicate code from old pages (temporary; Slice 11 deletes old files).",
|
|
"ActionsTab no longer has a service-selector dropdown (run is always on current instance; switch via instance switcher).",
|
|
"No mobile layout (branch is on main, not mobile-responsive-parity)."
|
|
],
|
|
"noStagedFiles": true,
|
|
"diffSummary": "~967 lines: FilesTab.tsx (528, verbatim lift from FileBrowser.impl.tsx with instance wiring + ?path= deep-link), ActionsTab.tsx (308, lift from Actions.tsx with instance as fixed run service), 4 test files (112 lines), index.ts/stubs.tsx wiring (12 lines), MediaTab.tsx row-click fix (10 lines). Over 400-line budget due to mechanical lift of two large pages.",
|
|
"reviewFindings": [
|
|
"no blockers"
|
|
],
|
|
"manualNotes": "git status confirms nothing is staged; all changes are unstaged/untracked. The old FileBrowser.impl.tsx and Actions.tsx are kept (Slice 11 deletes them). Their existing tests still pass."
|
|
}
|
|
```
|