- useCloudConnectionsStore, 3-tab SettingsView, SettingsCloudTab, CloudCredentialModal - 61 Vitest tests passing, Vite build exits 0 - Fixed pre-existing build failure (top-level await) via build.target=esnext
11 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-cloud-storage-backends | 07 | ui |
|
|
|
|
|
|
|
|
|
14min | 2026-05-29 |
Phase 5 Plan 07: Cloud Storage Frontend UI Summary
Pinia cloudConnections store, 3-tab SettingsView with OAuth callback handling, SettingsCloudTab with 4 provider rows and status badges, and CloudCredentialModal for WebDAV/Nextcloud credential input
Performance
- Duration: 14 min
- Started: 2026-05-29T06:01:00Z
- Completed: 2026-05-29T06:15:23Z
- Tasks: 2
- Files modified: 11
Accomplishments
- Created
useCloudConnectionsStorePinia store withconnections,loading,errorstate andfetchConnections(),disconnect(id),disconnectAll()actions — follows same composition API pattern asuseFoldersStore - Added 4 cloud API functions to
frontend/src/api/client.js:listCloudConnections,disconnectCloud,connectWebDav,updateDefaultStorage - Rewrote
SettingsView.vueto a 3-tab layout (Preferences / AI Configuration / Cloud Storage) mirroringAdminView.vuetab strip verbatim;onMountedreads?cloud_connected=and?cloud_error=query params and shows toast/banner accordingly - Built
SettingsCloudTab.vueshowing all 4 providers (Google Drive, OneDrive, Nextcloud, WebDAV server) with inline status badges, per-status action buttons,REQUIRES_REAUTHyellow banner, inlineConfirmBlockfor remove confirmation, and "Disconnect all" action - Built
CloudCredentialModal.vuewith server URL, username,authMethodradio (app_password / account_password), and password fields; escape/overlay-click dismiss; spinner during save - Extracted
SettingsPreferencesTab.vueandSettingsAiTab.vuefrom the original flatSettingsView
Task Commits
- Task 1: cloudConnections store + API client -
612d542(feat) - Task 2: 3-tab SettingsView + all components -
63a6829(feat)
Files Created/Modified
frontend/src/stores/cloudConnections.js— Pinia store for cloud connections statefrontend/src/stores/__tests__/cloudConnections.test.js— 4 Vitest unit tests (W4)frontend/src/api/client.js— Added cloud storage section (listCloudConnections, disconnectCloud, connectWebDav, updateDefaultStorage)frontend/src/views/SettingsView.vue— Rewritten as 3-tab layout with OAuth callback handlingfrontend/src/components/settings/SettingsPreferencesTab.vue— Extracted from SettingsViewfrontend/src/components/settings/SettingsAiTab.vue— Extracted from SettingsViewfrontend/src/components/settings/SettingsCloudTab.vue— Provider card list with status badges, action buttons, modalsfrontend/src/components/settings/__tests__/SettingsCloudTab.test.js— 2 mount tests (W4)frontend/src/components/cloud/CloudCredentialModal.vue— WebDAV/Nextcloud credential modalfrontend/package.json— Added"test": "vitest run"scriptfrontend/vite.config.js— Addedbuild.target: 'esnext'to fix pre-existing top-level await build failure
Decisions Made
@pinia/testingis not installed and not inpackage.json. Usedvi.mock('../../../stores/cloudConnections.js', ...)to mock the store inSettingsCloudTab.test.js— same approach asfolders.test.jsusesvi.mockfor the API. No dependency installation needed.- Pre-existing
npm run buildfailure (top-levelawait router.isReady()inmain.jsincompatible with default esbuild targets). Fix:build.target = 'esnext'invite.config.js— esnext natively supports module-level await. Zero code change tomain.js. - OAuth initiation for Google Drive and OneDrive uses
window.location.href = /api/cloud/oauth/initiate/{provider}— no fetch call — matching the backend FastAPIRedirectResponsepattern.
Deviations from Plan
Auto-fixed Issues
1. [Rule 1 - Bug] Fixed pre-existing Vite build failure (top-level await)
- Found during: Task 2 verification (
npm run build) - Issue:
main.jsusesawait router.isReady()at module top-level, which esbuild's default target (chrome87/es2020) does not support. This caused every build to fail with "Top-level await is not available in the configured target environment". - Fix: Added
build: { target: 'esnext' }tofrontend/vite.config.js. No code changes tomain.jsrequired. - Files modified:
frontend/vite.config.js - Verification:
npm run buildexits 0, bundle output 185 kB. - Committed in:
63a6829(Task 2 commit)
Total deviations: 1 auto-fixed (Rule 1 — pre-existing bug)
Impact on plan: Fix was required for the plan's success criteria (npm run build exits 0). No scope creep.
Issues Encountered
@pinia/testingpackage is not installed — the plan'sSettingsCloudTab.test.jsspec usedcreateTestingPiniafrom it. Resolved by usingvi.mockon the store module (the same pattern already established infolders.test.js). No package install required.npm run testscript did not exist inpackage.json— the plan required running tests vianpm run test. Added"test": "vitest run"to the scripts block.
Known Stubs
None. All 4 provider rows are wired to the live useCloudConnectionsStore — fetchConnections() is called in onMounted. The "Not connected" state is the correct zero-state display (per UI-SPEC: "all 4 providers always shown").
Threat Surface Scan
No new network endpoints introduced. Client-side changes only.
| Flag | File | Description |
|---|---|---|
| T-05-07-02 mitigated | SettingsView.vue |
?cloud_error= decoded via decodeURIComponent and displayed via {{ oauthError }} template binding — Vue auto-escaping prevents HTML injection |
| T-05-07-03 accepted | CloudCredentialModal.vue |
Password lives in ref('') only during modal interaction; close() is called on @connected which unmounts the form; watch(props.show) resets all refs to empty on reopen |
Next Phase Readiness
- All frontend cloud storage management UI is complete and building.
- 61 Vitest tests pass (4 new store tests + 2 new component tests + 55 pre-existing).
- Plan 05-08 can proceed: AppSidebar cloud tree nodes (
CloudProviderTreeItem,CloudFolderTreeItem) depend onuseCloudConnectionsStore(now available).
Self-Check: PASSED
Files verified present:
frontend/src/stores/cloudConnections.js: FOUND (1045 chars)frontend/src/stores/__tests__/cloudConnections.test.js: FOUND (2129 chars)frontend/src/api/client.js: FOUND (with listCloudConnections, disconnectCloud, connectWebDav, updateDefaultStorage)frontend/src/views/SettingsView.vue: FOUND (with activeTab, oauthSuccessProvider, oauthError, SettingsPreferencesTab, SettingsCloudTab)frontend/src/components/settings/SettingsPreferencesTab.vue: FOUNDfrontend/src/components/settings/SettingsAiTab.vue: FOUNDfrontend/src/components/settings/SettingsCloudTab.vue: FOUND (with google_drive, onedrive, nextcloud, webdav, CloudCredentialModal, useCloudConnectionsStore)frontend/src/components/settings/__tests__/SettingsCloudTab.test.js: FOUNDfrontend/src/components/cloud/CloudCredentialModal.vue: FOUND (with authMethod)
Commits verified:
612d542: feat(05-07): cloud connections Pinia store + API client functions — FOUND63a6829: feat(05-07): 3-tab SettingsView, SettingsCloudTab, CloudCredentialModal — FOUND
Test verification: npm run test → 61 passed, 0 failed
Build verification: npm run build → exit 0, 185 kB bundle
Phase: 05-cloud-storage-backends Completed: 2026-05-29