feat(05-08): add Cloud Storage collapsible section to AppSidebar

- Import CloudProviderTreeItem and useCloudConnectionsStore
- Add cloudExpanded ref (default true) and activeCloudConnections/loadingCloudConnections computed
- Insert Cloud Storage section between Folders and Topics sections
- Fetch connections on mount; render one CloudProviderTreeItem per ACTIVE connection
- Empty state: 'No cloud storage connected'; loading state: 'Loading...'
This commit is contained in:
curo1305
2026-05-29 08:33:33 +02:00
parent 34b0593782
commit 98576ac298
+57 -1
View File
@@ -110,6 +110,52 @@
</template>
</div>
<!-- Cloud Storage section -->
<div class="mt-3">
<div class="flex items-center gap-0.5">
<!-- Expand/collapse chevron -->
<button
@click="cloudExpanded = !cloudExpanded"
class="p-1 rounded hover:bg-gray-100 text-gray-400 hover:text-gray-600 transition-colors shrink-0"
:title="cloudExpanded ? 'Collapse cloud storage' : 'Expand cloud storage'"
>
<svg
class="w-3 h-3 transition-transform duration-150"
:class="cloudExpanded ? '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>
<!-- "Cloud Storage" navigates to /settings -->
<a
href="/settings"
class="nav-link flex-1 min-w-0"
>
<svg class="w-4 h-4 mr-2 shrink-0 text-sky-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
</svg>
Cloud Storage
</a>
</div>
<!-- Collapsible content -->
<template v-if="cloudExpanded">
<div v-if="loadingCloudConnections" class="pl-7 py-1 text-xs text-gray-400">Loading</div>
<div v-else-if="activeCloudConnections.length === 0" class="pl-7 py-1 text-xs text-gray-400">
No cloud storage connected
</div>
<CloudProviderTreeItem
v-for="connection in activeCloudConnections"
:key="connection.id"
:connection="connection"
:depth="1"
/>
</template>
</div>
<!-- Topics list -->
<div class="mt-3">
<p class="px-3 text-xs font-semibold text-gray-400 uppercase tracking-wider mb-1">Topics</p>
@@ -186,18 +232,21 @@
</template>
<script setup>
import { ref, onMounted, watch } from 'vue'
import { ref, computed, onMounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import { useTopicsStore } from '../../stores/topics.js'
import { useAuthStore } from '../../stores/auth.js'
import { useFoldersStore } from '../../stores/folders.js'
import { useCloudConnectionsStore } from '../../stores/cloudConnections.js'
import QuotaBar from './QuotaBar.vue'
import FolderTreeItem from '../folders/FolderTreeItem.vue'
import CloudProviderTreeItem from '../cloud/CloudProviderTreeItem.vue'
import * as api from '../../api/client.js'
const topicsStore = useTopicsStore()
const authStore = useAuthStore()
const foldersStore = useFoldersStore()
const cloudConnectionsStore = useCloudConnectionsStore()
const router = useRouter()
const sharedCount = ref(0)
@@ -206,6 +255,12 @@ const newFolderName = ref('')
const newFolderError = ref('')
const loadingRoots = ref(true)
const foldersExpanded = ref(false)
const cloudExpanded = ref(true)
const activeCloudConnections = computed(() =>
cloudConnectionsStore.connections.filter(c => c.status === 'ACTIVE')
)
const loadingCloudConnections = computed(() => cloudConnectionsStore.loading)
watch(() => foldersStore.treeVersion, () => foldersStore.fetchRootFolders())
@@ -222,6 +277,7 @@ onMounted(async () => {
} catch {
sharedCount.value = 0
}
cloudConnectionsStore.fetchConnections()
})
async function signOut() {