Files
kite/frontend/src/views/CloudFolderView.vue
T
curo1305 9ea51d6401 feat(10-06): wire breadcrumb mapping + toast call sites; delete FolderBreadcrumb
- FileManagerView: add mappedBreadcrumb computed ({id,label} from foldersStore.breadcrumb)
- FileManagerView: import useToastStore; add toast.show() to doMove, doDeleteDoc, onFilesSelected
- FileManagerView: remove console.error from doMove/doDeleteDoc (toast communicates errors)
- CloudFolderView: add mappedBreadcrumb computed; pass to StorageBrowser :breadcrumb
- Delete FolderBreadcrumb.vue + FolderBreadcrumb.test.js (no dead code per CLAUDE.md)
- FileManagerView.test.js: replace dead FolderBreadcrumb mock with BreadcrumbBar mock
- StorageBrowser.skeleton.test.js: remove unused FolderBreadcrumb stub
- Full suite: 164/164 pass, 0 failures
2026-06-15 20:26:06 +02:00

98 lines
3.2 KiB
Vue

<template>
<StorageBrowser
mode="cloud"
:folders="folders"
:files="files"
:breadcrumb="mappedBreadcrumb"
:upload-queue="uploadQueue"
:loading="loading"
:empty-message="error || 'This folder is empty'"
:empty-hint="error ? '' : 'Files stored here are managed by ' + providerLabel(provider)"
@breadcrumb-navigate="handleBreadcrumbNavigate"
@upload="onFilesSelected"
@folder-navigate="item => navigateTo(item)"
@file-open="file => {}"
/>
</template>
<script setup>
import { ref, computed, watch, onMounted, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import * as api from '../api/client.js'
import StorageBrowser from '../components/storage/StorageBrowser.vue'
import { providerLabel } from '../utils/formatters.js'
const route = useRoute()
const router = useRouter()
const items = ref([])
const loading = ref(false)
const error = ref('')
const provider = computed(() => route.params.provider)
const folderId = computed(() => route.params.folderId)
const folders = computed(() => items.value.filter(i => i.is_dir))
const files = computed(() => items.value.filter(i => !i.is_dir))
/** Breadcrumb built from the folder path segments. */
const breadcrumb = computed(() => {
if (!folderId.value || folderId.value === 'root') return []
const parts = folderId.value.replace(/\/$/, '').split('/')
return parts.map((seg, idx) => ({
id: parts.slice(0, idx + 1).join('/'),
name: seg,
}))
})
const mappedBreadcrumb = computed(() =>
breadcrumb.value.map(f => ({ id: f.id, label: f.name }))
)
async function load() {
loading.value = true
error.value = ''
try {
const data = await api.getCloudFolders(provider.value, folderId.value ?? 'root')
items.value = data.items ?? []
} catch (e) {
const msg = e.message || ''
if (msg.toLowerCase().includes('no active connection') || msg.includes('404') || msg.toLowerCase().includes('not found')) {
error.value = 'No cloud provider connected. Go to Settings to connect a cloud storage account.'
} else {
error.value = msg || 'Failed to load folder contents.'
}
} finally {
loading.value = false
}
}
function navigateTo(item) {
router.push(`/cloud/${provider.value}/${item.id}`)
}
function handleBreadcrumbNavigate(id) {
if (id == null) router.push(`/cloud/${provider.value}/root`)
else router.push(`/cloud/${provider.value}/${id}`)
}
// ── Upload ────────────────────────────────────────────────────────────────────
const uploadQueue = ref([])
async function onFilesSelected({ files: selectedFiles }) {
const promises = selectedFiles.map(file => {
const item = reactive({ name: file.name, done: false, error: null, status: 'Uploading…' })
uploadQueue.value.unshift(item)
return api.uploadToCloud(file, provider.value, folderId.value || null)
.then(() => { item.done = true; item.status = null })
.catch(e => { item.error = e.message || 'Upload failed' })
})
await Promise.allSettled(promises)
await load()
}
onMounted(load)
watch([provider, folderId], load)
</script>