chore(phase-4): UAT complete — Phase 4 marked done, sidebar collapse, duplicate-folder fix
UAT: 14/15 passed. Bug fixed: folders/rootFolders array alias in fetchFolders caused duplicate folder row on creation (rootFolders = [...list] breaks the shared reference). Sidebar: Folders section now has a collapse/expand chevron, collapsed by default. State: Phase 4 complete, Phase 5 (Cloud Storage Backends) is next. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,11 +43,26 @@
|
||||
|
||||
<!-- Folders root + collapsible tree -->
|
||||
<div class="mt-3">
|
||||
<!-- "Folders" is the root entry — clicking navigates to the root folder view -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-0.5">
|
||||
<!-- Expand/collapse chevron -->
|
||||
<button
|
||||
@click="foldersExpanded = !foldersExpanded"
|
||||
class="p-1 rounded hover:bg-gray-100 text-gray-400 hover:text-gray-600 transition-colors shrink-0"
|
||||
:title="foldersExpanded ? 'Collapse folders' : 'Expand folders'"
|
||||
>
|
||||
<svg
|
||||
class="w-3 h-3 transition-transform duration-150"
|
||||
:class="foldersExpanded ? 'rotate-90' : ''"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||
>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- "Folders" navigates to root file manager -->
|
||||
<router-link
|
||||
to="/"
|
||||
class="nav-link flex-1"
|
||||
class="nav-link flex-1 min-w-0"
|
||||
:class="{ 'nav-link-active': $route.path === '/' || $route.path.startsWith('/folders/') }"
|
||||
>
|
||||
<svg class="w-4 h-4 mr-2 shrink-0 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -56,6 +71,7 @@
|
||||
</svg>
|
||||
Folders
|
||||
</router-link>
|
||||
|
||||
<button
|
||||
@click="startNewFolder"
|
||||
class="text-xs text-indigo-600 hover:underline shrink-0 mr-1"
|
||||
@@ -65,30 +81,33 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Inline new root folder input -->
|
||||
<div v-if="showNewFolderInput" class="px-3 mb-2 mt-1">
|
||||
<input
|
||||
v-model="newFolderName"
|
||||
type="text"
|
||||
placeholder="Folder name"
|
||||
class="block w-full border border-gray-300 rounded-lg px-2 py-1 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
@keydown.enter="submitNewFolder"
|
||||
@keydown.escape="cancelNewFolder"
|
||||
autofocus
|
||||
/>
|
||||
<p v-if="newFolderError" class="text-red-500 text-xs mt-1">{{ newFolderError }}</p>
|
||||
</div>
|
||||
<!-- Collapsible content -->
|
||||
<template v-if="foldersExpanded">
|
||||
<!-- Inline new root folder input -->
|
||||
<div v-if="showNewFolderInput" class="px-3 mb-2 mt-1">
|
||||
<input
|
||||
v-model="newFolderName"
|
||||
type="text"
|
||||
placeholder="Folder name"
|
||||
class="block w-full border border-gray-300 rounded-lg px-2 py-1 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-500"
|
||||
@keydown.enter="submitNewFolder"
|
||||
@keydown.escape="cancelNewFolder"
|
||||
autofocus
|
||||
/>
|
||||
<p v-if="newFolderError" class="text-red-500 text-xs mt-1">{{ newFolderError }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Sub-folders tree (indented under Folders) -->
|
||||
<div v-if="loadingRoots" class="pl-7 py-1 text-xs text-gray-400">Loading…</div>
|
||||
<div v-else-if="foldersStore.rootFolders.length === 0 && !showNewFolderInput"
|
||||
class="pl-7 py-1 text-xs text-gray-400">No folders yet</div>
|
||||
<FolderTreeItem
|
||||
v-for="folder in foldersStore.rootFolders"
|
||||
:key="folder.id"
|
||||
:folder="folder"
|
||||
:depth="1"
|
||||
/>
|
||||
<!-- Sub-folders tree -->
|
||||
<div v-if="loadingRoots" class="pl-7 py-1 text-xs text-gray-400">Loading…</div>
|
||||
<div v-else-if="foldersStore.rootFolders.length === 0 && !showNewFolderInput"
|
||||
class="pl-7 py-1 text-xs text-gray-400">No folders yet</div>
|
||||
<FolderTreeItem
|
||||
v-for="folder in foldersStore.rootFolders"
|
||||
:key="folder.id"
|
||||
:folder="folder"
|
||||
:depth="1"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Topics list -->
|
||||
@@ -186,6 +205,7 @@ const showNewFolderInput = ref(false)
|
||||
const newFolderName = ref('')
|
||||
const newFolderError = ref('')
|
||||
const loadingRoots = ref(true)
|
||||
const foldersExpanded = ref(false)
|
||||
|
||||
watch(() => foldersStore.treeVersion, () => foldersStore.fetchRootFolders())
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export const useFoldersStore = defineStore('folders', () => {
|
||||
const data = await api.listFolders(parentId)
|
||||
const list = data.items ?? data
|
||||
folders.value = list
|
||||
if (parentId === null) rootFolders.value = list
|
||||
if (parentId === null) rootFolders.value = [...list]
|
||||
} catch (e) {
|
||||
error.value = e.message || 'Failed to load folders'
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user