docs(10): add root causes from diagnosis — 8 gaps diagnosed
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
---
|
||||
status: complete
|
||||
status: diagnosed
|
||||
phase: 10-ux-interaction
|
||||
source: 10-01-SUMMARY.md, 10-02-SUMMARY.md, 10-03-SUMMARY.md, 10-04-SUMMARY.md, 10-06-SUMMARY.md, 10-07-SUMMARY.md, 10-08-SUMMARY.md, 10-09-SUMMARY.md, 10-10-SUMMARY.md, 10-11-SUMMARY.md, 10-12-SUMMARY.md
|
||||
started: 2026-06-16T00:00:00Z
|
||||
@@ -127,9 +127,12 @@ blocked: 0
|
||||
reason: "User reported: Local storage too fast to see any loading. Nextcloud sidebar section does nothing until folder loads — no skeleton or feedback visible during load."
|
||||
severity: major
|
||||
test: 4
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "TreeItem.vue lines 48-52 render <div class='text-xs text-gray-400 py-1'>Loading…</div> instead of animate-pulse shimmer rows. The loading state ref is tracked correctly but the visual treatment does not match the shimmer pattern used elsewhere in AppSidebar."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/ui/TreeItem.vue"
|
||||
issue: "v-if='loading' branch renders plain text instead of animated skeleton rows (lines 48-52)"
|
||||
missing:
|
||||
- "Replace plain Loading… div with 3 shimmer rows using animate-pulse pattern matching AppSidebar lines 60-64"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Admin views show admin-specific layout (no user sidebar) with breadcrumb bar"
|
||||
@@ -137,9 +140,12 @@ blocked: 0
|
||||
reason: "User reported: Admin views still show the normal user sidebar."
|
||||
severity: major
|
||||
test: 8
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "App.vue renders <AppSidebar> in a v-else branch with no admin exemption. When /admin/* routes render, Vue Router places AdminLayout.vue into <router-view> but AppSidebar is outside it — unconditionally rendered for all non-auth routes. Both sidebars appear simultaneously."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "v-else branch (lines 3-8) renders <AppSidebar> without checking route.meta.requiresAdmin"
|
||||
missing:
|
||||
- "Add third branch in App.vue: when route.matched.some(r => r.meta.requiresAdmin), render only <router-view> with no AppSidebar"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Pressing '/' while in the file manager (with search bar visible) focuses the search input"
|
||||
@@ -147,9 +153,14 @@ blocked: 0
|
||||
reason: "User reported: pressing '/' does nothing when search bar is visible inside a folder."
|
||||
severity: major
|
||||
test: 11
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "Shared root cause with tests 12 and 13: ref='routeViewRef' on <router-view> in App.vue resolves to the RouterView component proxy, not the FileManagerView instance. RouterView.setup() never calls expose(), so routeViewRef.value has no focusSearch/triggerUpload/startNewFolder properties. All calls silently no-op via optional chaining ?."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "ref='routeViewRef' on <router-view> (line 6); shortcut handlers use routeViewRef.value?.focusSearch?.() etc. (lines 37, 43, 46) which are unreachable"
|
||||
- path: "frontend/src/views/FileManagerView.vue"
|
||||
issue: "defineExpose({ focusSearch, triggerUpload, startNewFolder }) is correct (lines 190-196) but unreachable via routeViewRef"
|
||||
missing:
|
||||
- "Replace routeViewRef approach with router.currentRoute.value.matched[0].instances.default to reach actual FileManagerView instance, or use a Pinia store / event bus for keyboard action dispatch"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Pressing 'U' while in the file manager opens the file-picker dialog"
|
||||
@@ -157,9 +168,12 @@ blocked: 0
|
||||
reason: "User reported: pressing U does not open the file picker."
|
||||
severity: major
|
||||
test: 12
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "Same root cause as test 11: routeViewRef resolves to RouterView proxy, not FileManagerView. triggerUpload?.() is a no-op."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "routeViewRef.value?.triggerUpload?.() (line 43) silently no-ops"
|
||||
missing:
|
||||
- "Fixed by the same routeViewRef fix as test 11"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Pressing 'N' while in the file manager triggers the new-folder inline input"
|
||||
@@ -167,9 +181,12 @@ blocked: 0
|
||||
reason: "User reported: pressing N does not trigger new folder input."
|
||||
severity: major
|
||||
test: 13
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "Same root cause as test 11: routeViewRef resolves to RouterView proxy, not FileManagerView. startNewFolder?.() is a no-op."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "routeViewRef.value?.startNewFolder?.() (line 46) silently no-ops"
|
||||
missing:
|
||||
- "Fixed by the same routeViewRef fix as test 11"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "After pressing Escape to clear search, the search field remains functional for new queries"
|
||||
@@ -177,9 +194,14 @@ blocked: 0
|
||||
reason: "User reported: field clears on Escape but search no longer works afterwards — cannot type a new query."
|
||||
severity: major
|
||||
test: 14
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "SearchBar.vue uses type='search' on the input (line 6) and handles @keydown.escape without .prevent. Browsers treat Escape on type='search' as native clear+blur — the field loses focus and the user cannot type without clicking first. Event also bubbles to App.vue global handler (no .stop) causing a redundant clearSearch call."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/documents/SearchBar.vue"
|
||||
issue: "@keydown.escape handler (line 11) lacks .prevent and .stop — browser native blur fires after Vue handler"
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "Global Escape handler (line 39) may fire redundantly after input blurs"
|
||||
missing:
|
||||
- "Change @keydown.escape to @keydown.escape.prevent.stop in SearchBar.vue to suppress native blur and prevent bubbling"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Dropping a file from OS onto the drag overlay starts the upload"
|
||||
@@ -187,9 +209,14 @@ blocked: 0
|
||||
reason: "User reported: overlay appears but dropping the file does not start the upload."
|
||||
severity: major
|
||||
test: 15
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "OsDragOverlay registers window 'drop' listener in bubble phase. StorageBrowser registers @drop.prevent on every folder row (line 79), which consumes the native drop event before it bubbles to window. OsDragOverlay has pointer-events-none so drops land on underlying DOM elements (folder rows) which intercept them first. The window listener never fires."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/layout/OsDragOverlay.vue"
|
||||
issue: "window.addEventListener('drop', this.onDrop) registered in bubble phase (line 56) — consumed by folder rows first"
|
||||
- path: "frontend/src/components/storage/StorageBrowser.vue"
|
||||
issue: "@drop.prevent on folder rows (line 79) intercepts OS drops; onDropDocOnFolder guard (line 364) exits early for OS drags (draggingFile is null)"
|
||||
missing:
|
||||
- "Register OsDragOverlay window listener in capture phase: window.addEventListener('drop', this.onDrop, true) so it runs before element-level handlers"
|
||||
debug_session: ""
|
||||
|
||||
- truth: "Search bar and sorting controls are visible at the root level of the file manager and cloud file browser (currently hidden behind breadcrumb.length > 0 guard)"
|
||||
@@ -197,7 +224,10 @@ blocked: 0
|
||||
reason: "User reported: search bar and sorting controls not visible at the root of the cloud and local file browser."
|
||||
severity: major
|
||||
test: 5
|
||||
root_cause: ""
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "StorageBrowser.vue line 287: showSearch computed is props.mode === 'local' && props.breadcrumb.length > 0. Both conditions must be true — breadcrumb is [] at root so showSearch is false there; cloud mode also always false because mode guard requires 'local'. SearchBar (line 12) and SortControls (line 14) both share v-if='showSearch' so both disappear."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/storage/StorageBrowser.vue"
|
||||
issue: "showSearch computed (line 287) has breadcrumb.length > 0 and mode === 'local' guards; both incorrect"
|
||||
missing:
|
||||
- "Change showSearch to computed(() => props.mode === 'local' || props.mode === 'cloud') — remove breadcrumb depth guard entirely"
|
||||
debug_session: ""
|
||||
|
||||
Reference in New Issue
Block a user