docs(12-03): add plan 03 execution summary
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
---
|
||||
phase: "12"
|
||||
plan: "03"
|
||||
subsystem: cloud-ui-foundation
|
||||
tags: [cloud, routing, capabilities, breadcrumb, freshness, accessibility, session-storage]
|
||||
dependency_graph:
|
||||
requires:
|
||||
- "12-02" # connection-ID browse API, CloudResourceAdapter, cloud_items metadata
|
||||
provides:
|
||||
- connection-ID routing (/cloud/:connectionId/:folderId)
|
||||
- capability-aware action rendering (StorageBrowser)
|
||||
- breadcrumb freshness indicators (BreadcrumbBar)
|
||||
- session-only folder memory (cloudConnections store)
|
||||
- display-name rename for cloud connections
|
||||
affects:
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/router/index.js
|
||||
- frontend/src/views/CloudStorageView.vue
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/components/settings/SettingsCloudTab.vue
|
||||
- frontend/src/components/storage/StorageBrowser.vue
|
||||
- frontend/src/components/ui/BreadcrumbBar.vue
|
||||
- frontend/src/components/ui/AppIcon.vue
|
||||
- frontend/src/utils/formatters.js
|
||||
- backend/main.py
|
||||
tech_stack:
|
||||
added:
|
||||
- CapabilityButton inline render-function component (StorageBrowser.vue)
|
||||
- formatRelativeTime (formatters.js)
|
||||
- saveLastFolder / loadLastFolder (cloudConnections.js session helpers)
|
||||
patterns:
|
||||
- capability-aware rendering (aria-disabled, not native disabled)
|
||||
- session-storage for navigation state only (never tokens/credentials)
|
||||
- connection UUID as routing identity (opaque, not provider slug)
|
||||
- immediate watcher for freshness state transitions
|
||||
key_files:
|
||||
created:
|
||||
- frontend/src/views/__tests__/CloudFolderView.test.js
|
||||
- frontend/src/views/__tests__/CloudStorageView.test.js
|
||||
- frontend/src/components/storage/__tests__/StorageBrowser.capabilities.test.js
|
||||
modified:
|
||||
- frontend/src/api/cloud.js
|
||||
- frontend/src/stores/cloudConnections.js
|
||||
- frontend/src/stores/__tests__/cloudConnections.test.js
|
||||
- frontend/src/router/index.js
|
||||
- frontend/src/views/CloudStorageView.vue
|
||||
- frontend/src/views/CloudFolderView.vue
|
||||
- frontend/src/components/settings/SettingsCloudTab.vue
|
||||
- frontend/src/components/settings/__tests__/SettingsCloudTab.test.js
|
||||
- frontend/src/components/storage/StorageBrowser.vue
|
||||
- frontend/src/components/ui/BreadcrumbBar.vue
|
||||
- frontend/src/components/ui/__tests__/BreadcrumbBar.test.js
|
||||
- frontend/src/components/ui/AppIcon.vue
|
||||
- frontend/src/utils/formatters.js
|
||||
- backend/main.py
|
||||
- frontend/package.json
|
||||
- AGENTS.md
|
||||
- README.md
|
||||
decisions:
|
||||
- "Connection identity is the connection UUID, never a provider slug, in routes and API calls"
|
||||
- "CapabilityButton uses aria-disabled (not native disabled) so controls remain keyboard-focusable"
|
||||
- "Local mode uses full capability defaults — no mode==='local' gates remain in action rendering"
|
||||
- "session-only folder memory stored under namespaced key docuvault:cloud:folder:{uuid}"
|
||||
- "Fresh indicator fades after 3s using immediate watcher + fake-timer-tested setTimeout"
|
||||
- "formatRelativeTime added to formatters.js — not duplicated inline"
|
||||
metrics:
|
||||
duration: "~45 minutes"
|
||||
completed: "2026-06-18"
|
||||
tasks: 3
|
||||
files: 18
|
||||
---
|
||||
|
||||
# Phase 12 Plan 03: Cloud UI Foundation Summary
|
||||
|
||||
## One-liner
|
||||
|
||||
Connection-UUID routing, CapabilityButton-based action rendering, and BreadcrumbBar freshness indicators unify cloud and local file navigation under one shared StorageBrowser.
|
||||
|
||||
## What was built
|
||||
|
||||
### Task 1: Route and store cloud navigation by connection identity
|
||||
|
||||
- `api/cloud.js`: added `getCloudFoldersByConnectionId(connectionId, folderId)` and `renameCloudConnection(id, displayName)`; deprecated provider-keyed `getCloudFolders`
|
||||
- `cloudConnections.js` store: added `rename`, `selectConnection`, `setBrowseState`, `defaultDisplayName` (4-char UUID suffix for duplicate same-provider connections), and `saveLastFolder`/`loadLastFolder` session helpers
|
||||
- Router: `/cloud/:provider/:folderId` → `/cloud/:connectionId/:folderId`
|
||||
- `CloudStorageView`: thin data provider — maps connections to folder-like items and passes them to `StorageBrowser`; no parallel grid markup
|
||||
- `CloudFolderView`: thin data provider — uses `connectionId` param, calls `getCloudFoldersByConnectionId`, saves last folder in sessionStorage on navigate
|
||||
- `SettingsCloudTab`: added inline rename input per ACTIVE connection with Rename / Save / Cancel flow
|
||||
|
||||
### Task 2: Replace mode-gated actions with accessible capability rendering
|
||||
|
||||
- `StorageBrowser`: removed all `mode === 'local'` action visibility gates
|
||||
- Added props: `capabilities`, `connectionRoot`, `folderFreshness`, `lastRefreshedAt`, `byteAvailability`
|
||||
- `LOCAL_CAPS` constant provides full-supported defaults so local mode unchanged
|
||||
- `CapabilityButton` inline component: `aria-disabled="true"` (never native `disabled`), click/Enter/Space/touchend all suppressed for non-supported states; emits `explain` → `capability-explain` event and shows inline dismissible notice
|
||||
- Gray styling for `unsupported`; amber for `temporarily_unavailable`
|
||||
- Cached-byte marker (`clock` icon) on size column when `byteAvailability === 'cached'`; no marker for `cloud_only`
|
||||
- `AppIcon`: added `info` and `clock` icons
|
||||
|
||||
### Task 3: Breadcrumb freshness and plan protocol
|
||||
|
||||
- `BreadcrumbBar`: optional `folderFreshness` and `lastRefreshedAt` props; refreshing spinner (animated SVG), fresh checkmark (fades 3s via immediate watcher), persistent stale warning banner
|
||||
- All freshness states have `role="status"` and `aria-label` for screen readers
|
||||
- `formatters.js`: `formatRelativeTime` — human-readable relative time, no inline duplication
|
||||
- Version bumped 0.1.5 → 0.1.6 in `backend/main.py` and `frontend/package.json`
|
||||
- `AGENTS.md` and `README.md` updated with new state, shared module map, and feature text
|
||||
|
||||
## Test results
|
||||
|
||||
- 323 frontend tests pass (39 test files)
|
||||
- Production build: `✓ built in 510ms`
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Threat surface scan
|
||||
|
||||
No new network endpoints introduced by this plan. Frontend adds:
|
||||
|
||||
| Flag | File | Description |
|
||||
|------|------|-------------|
|
||||
| threat_flag: sessionStorage-check | cloudConnections.js | `saveLastFolder` stores only folder path string under namespaced key; negative test asserts value is not `{` (not an object with credentials) |
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — StorageBrowser capability props are connected through CloudFolderView; default `LOCAL_CAPS` wires all local actions.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All key files found. All commits verified (bf9af11, 4424433, c6c0742). 323 tests pass. Production build clean.
|
||||
Reference in New Issue
Block a user