docs(10-06): create plan summary — skeleton/EmptyState/BreadcrumbBar/toast wired
- Documents 3 tasks (TDD RED→GREEN→Task3) - Records 164/164 tests passing, FolderBreadcrumb deleted - Captures dead-code hygiene deviation and decisions
This commit is contained in:
@@ -0,0 +1,152 @@
|
|||||||
|
---
|
||||||
|
phase: 10-ux-interaction
|
||||||
|
plan: "06"
|
||||||
|
subsystem: frontend/storage
|
||||||
|
tags: [wave-1, skeleton, empty-state, breadcrumb, toast, ux, vitest, tdd]
|
||||||
|
dependency_graph:
|
||||||
|
requires: [10-02, 10-03, 10-04, 10-05]
|
||||||
|
provides: [StorageBrowser-skeleton-UX-02, StorageBrowser-EmptyState-UX-01, BreadcrumbBar-wired-UX-12, toast-call-sites-UX-10]
|
||||||
|
affects: [FileManagerView, CloudFolderView, StorageBrowser]
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns: [TDD-red-green, skeleton-grid, EmptyState-discriminator, breadcrumb-label-mapping, toast-call-site]
|
||||||
|
key_files:
|
||||||
|
created: []
|
||||||
|
modified:
|
||||||
|
- frontend/src/components/storage/StorageBrowser.vue
|
||||||
|
- frontend/src/views/FileManagerView.vue
|
||||||
|
- frontend/src/views/CloudFolderView.vue
|
||||||
|
- frontend/src/components/storage/__tests__/StorageBrowser.skeleton.test.js
|
||||||
|
- frontend/src/views/__tests__/FileManagerView.test.js
|
||||||
|
deleted:
|
||||||
|
- frontend/src/components/folders/FolderBreadcrumb.vue
|
||||||
|
- frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js
|
||||||
|
decisions:
|
||||||
|
- "StorageBrowser uses breadcrumb.length > 0 as in-folder discriminator for EmptyState icon (folder vs document)"
|
||||||
|
- "BreadcrumbBar receives :root-label based on mode prop ('Cloud' for cloud, 'Home' for local)"
|
||||||
|
- "FolderBreadcrumb.vue deleted in same commit as BreadcrumbBar swap (no dead code per CLAUDE.md)"
|
||||||
|
- "FileManagerView.test.js FolderBreadcrumb mock replaced with BreadcrumbBar mock (dead-code hygiene)"
|
||||||
|
- "Toast wiring: useToastStore() called at call-site inside doMove/doDeleteDoc/onFilesSelected (no top-level const)"
|
||||||
|
metrics:
|
||||||
|
duration_minutes: 10
|
||||||
|
completed_date: "2026-06-15T20:26:00Z"
|
||||||
|
tasks_completed: 3
|
||||||
|
tasks_total: 3
|
||||||
|
files_created: 0
|
||||||
|
files_modified: 5
|
||||||
|
files_deleted: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 10 Plan 06: StorageBrowser Wire-up Summary
|
||||||
|
|
||||||
|
**One-liner:** StorageBrowser replaced Loading text with 5 animated skeleton rows, inline empty divs with three EmptyState variants, and FolderBreadcrumb with BreadcrumbBar; FileManagerView and CloudFolderView mapped breadcrumb segments to `{id, label}` and wired toast call sites for move/delete/upload.
|
||||||
|
|
||||||
|
## Tasks Completed
|
||||||
|
|
||||||
|
| Task | Name | Commit | Files |
|
||||||
|
|------|------|--------|-------|
|
||||||
|
| 1 | Promote UX-02 skeleton stubs to RED failing tests | 413d3f0 | `StorageBrowser.skeleton.test.js` |
|
||||||
|
| 2 | Update StorageBrowser — skeleton, EmptyState, BreadcrumbBar swap | d040e77 | `StorageBrowser.vue` |
|
||||||
|
| 3 | Update FileManagerView + CloudFolderView; delete FolderBreadcrumb | 9ea51d6 | `FileManagerView.vue`, `CloudFolderView.vue`, `FolderBreadcrumb.vue` (deleted), `FolderBreadcrumb.test.js` (deleted), `FileManagerView.test.js`, `StorageBrowser.skeleton.test.js` |
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
### Task 1: RED tests for UX-02 skeleton
|
||||||
|
|
||||||
|
Promoted 4 `it.todo` stubs in `StorageBrowser.skeleton.test.js` to real assertions:
|
||||||
|
- `renders 5 skeleton rows when loading=true and lists empty` — asserts `wrapper.findAll('.animate-pulse').length >= 5`
|
||||||
|
- `Loading… text is absent when loading=true` — asserts `wrapper.text()` does not contain `'Loading…'`
|
||||||
|
- `skeleton rows are NOT rendered when loading=false` — asserts zero `.animate-pulse` elements
|
||||||
|
- `skeleton row grid matches grid-cols-[2rem_1fr_6rem_8rem_6rem]` — asserts at least one matching grid container
|
||||||
|
|
||||||
|
Tests 1 and 2 were RED before Task 2. All 4 turn GREEN after Task 2.
|
||||||
|
|
||||||
|
### Task 2: StorageBrowser.vue updated (GREEN)
|
||||||
|
|
||||||
|
**Imports:** `FolderBreadcrumb` replaced by `BreadcrumbBar` + `EmptyState` added.
|
||||||
|
|
||||||
|
**Template — BreadcrumbBar:** Replaced `<FolderBreadcrumb :segments="breadcrumb" ...>` with:
|
||||||
|
```vue
|
||||||
|
<BreadcrumbBar
|
||||||
|
:segments="breadcrumb"
|
||||||
|
:root-label="mode === 'cloud' ? 'Cloud' : 'Home'"
|
||||||
|
@navigate="$emit('breadcrumb-navigate', $event)"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Template — Skeleton rows (lines 226-238):** Replaced `<div v-if="loading">Loading…</div>` with `<template v-if="loading">` containing 5 skeleton row divs using `animate-pulse` and `grid-cols-[2rem_1fr_6rem_8rem_6rem]`.
|
||||||
|
|
||||||
|
**Template — EmptyState (lines 240-264):** Replaced 2 inline empty divs with 3 `<EmptyState>` blocks:
|
||||||
|
- `v-else-if="searchQuery && ..."` with `icon="search"` and a CTA "Clear search" slot
|
||||||
|
- `v-else-if="breadcrumb.length > 0 && ..."` with `icon="document"` (in-folder)
|
||||||
|
- `v-else-if="..."` with `icon="folder"` (root)
|
||||||
|
|
||||||
|
### Task 3: FileManagerView + CloudFolderView wired; FolderBreadcrumb deleted
|
||||||
|
|
||||||
|
**FileManagerView.vue:**
|
||||||
|
- `import { useToastStore }` added
|
||||||
|
- `mappedBreadcrumb` computed added: `foldersStore.breadcrumb.map(f => ({ id: f.id, label: f.name }))`
|
||||||
|
- Template binding changed to `:breadcrumb="mappedBreadcrumb"`
|
||||||
|
- `doMove` updated: `toast.show('Document moved', 'success')` on success; `toast.show('Move failed: ...', 'error')` on catch
|
||||||
|
- `doDeleteDoc` updated: `toast.show('Document deleted', 'success')` on success; `toast.show('Delete failed: ...', 'error')` on catch
|
||||||
|
- `onFilesSelected` updated: summary toast after `Promise.allSettled` (success/warning/error based on succeeded count)
|
||||||
|
- `console.error` calls removed from doMove and doDeleteDoc (toast communicates errors to user)
|
||||||
|
|
||||||
|
**CloudFolderView.vue:**
|
||||||
|
- `mappedBreadcrumb` computed added: `breadcrumb.value.map(f => ({ id: f.id, label: f.name }))`
|
||||||
|
- Template binding changed to `:breadcrumb="mappedBreadcrumb"`
|
||||||
|
|
||||||
|
**Deleted files:**
|
||||||
|
- `frontend/src/components/folders/FolderBreadcrumb.vue` — replaced by BreadcrumbBar
|
||||||
|
- `frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js` — deleted in same commit (no dead code)
|
||||||
|
|
||||||
|
**Test hygiene:**
|
||||||
|
- `FileManagerView.test.js`: dead `FolderBreadcrumb` mock replaced with `BreadcrumbBar` mock
|
||||||
|
- `StorageBrowser.skeleton.test.js`: unused `FolderBreadcrumb` stub entry removed from globalStubs
|
||||||
|
|
||||||
|
## Verification Results
|
||||||
|
|
||||||
|
| Check | Result |
|
||||||
|
|-------|--------|
|
||||||
|
| `StorageBrowser.skeleton` — 4 UX-02 tests GREEN | PASS |
|
||||||
|
| `FileManagerView` — 20 tests | PASS |
|
||||||
|
| `BreadcrumbBar` — regression | PASS |
|
||||||
|
| `toast` — regression | PASS |
|
||||||
|
| Full suite: 164 tests, 0 failures, 7 skipped (todo-only files) | PASS |
|
||||||
|
| `grep -r "FolderBreadcrumb" frontend/src/` | 0 matches |
|
||||||
|
| `<EmptyState>` count in StorageBrowser.vue | 3 |
|
||||||
|
| `<BreadcrumbBar>` count in StorageBrowser.vue | 1 |
|
||||||
|
| `animate-pulse` count in StorageBrowser.vue | 5 |
|
||||||
|
| `Loading…` text in StorageBrowser.vue | 0 |
|
||||||
|
| `useToastStore` in FileManagerView.vue | 4 occurrences |
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug / Rule 2 - Dead Code] Replaced dead FolderBreadcrumb mock in FileManagerView.test.js**
|
||||||
|
- **Found during:** Task 3
|
||||||
|
- **Issue:** `vi.mock('../../components/folders/FolderBreadcrumb.vue', ...)` in FileManagerView.test.js was registering a mock for a deleted file, and the component was no longer imported anywhere in the codebase
|
||||||
|
- **Fix:** Replaced with `vi.mock('../../components/ui/BreadcrumbBar.vue', ...)` — the component now used by StorageBrowser; removed FolderBreadcrumb stub from StorageBrowser.skeleton.test.js globalStubs
|
||||||
|
- **Files modified:** `FileManagerView.test.js`, `StorageBrowser.skeleton.test.js`
|
||||||
|
- **Commit:** 9ea51d6
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
None. All behaviors are fully wired.
|
||||||
|
|
||||||
|
## Threat Flags
|
||||||
|
|
||||||
|
None. This plan modifies only frontend Vue components and test files. No new network endpoints, auth paths, file access patterns, or schema changes were introduced.
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
- `frontend/src/components/storage/StorageBrowser.vue` — exists with BreadcrumbBar, EmptyState, skeleton
|
||||||
|
- `frontend/src/views/FileManagerView.vue` — exists with mappedBreadcrumb, toast wiring
|
||||||
|
- `frontend/src/views/CloudFolderView.vue` — exists with mappedBreadcrumb
|
||||||
|
- `frontend/src/components/folders/FolderBreadcrumb.vue` — confirmed deleted
|
||||||
|
- `frontend/src/components/folders/__tests__/FolderBreadcrumb.test.js` — confirmed deleted
|
||||||
|
- Commit 413d3f0 — confirmed in git log (RED tests)
|
||||||
|
- Commit d040e77 — confirmed in git log (StorageBrowser GREEN)
|
||||||
|
- Commit 9ea51d6 — confirmed in git log (Task 3)
|
||||||
|
- No unexpected file deletions (only FolderBreadcrumb files intentionally deleted)
|
||||||
Reference in New Issue
Block a user