feat: wire Cloud card on Home to real FileBrowser data
Add getUsage() method to filebrowser-client that fetches root directory and returns total size and folder count. Home.vue Cloud card now shows real storage used and folder count instead of hardcoded values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
dfe96cdb6f
commit
37105e6be6
@ -40,7 +40,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy
|
||||
- **Change**: Ensure tab bar element has `data-mobile-tab-bar` attribute so `useMobileBackButton` composable works. CloudFolder.vue already uses this correctly.
|
||||
- **Verify**: CloudFolder on mobile — "Back to Cloud" button floats 8px above tab bar
|
||||
|
||||
### Task 7: Cloud homepage real data
|
||||
### Task 7: Cloud homepage real data [DONE]
|
||||
- **Files**: `neode-ui/src/views/Home.vue`, `neode-ui/src/api/filebrowser-client.ts`
|
||||
- **Change**: Add `getUsage()` method to filebrowser-client. In Home.vue, replace hardcoded "2.4 GB" and "5" folders with real data from FileBrowser API. Add `formatBytes()` helper. Show loading state while fetching.
|
||||
- **Verify**: Home Cloud card shows real storage numbers from FileBrowser
|
||||
|
||||
@ -104,6 +104,23 @@ class FileBrowserClient {
|
||||
if (!res.ok) throw new Error(`Delete failed: ${res.status}`)
|
||||
}
|
||||
|
||||
async getUsage(): Promise<{ totalSize: number; folderCount: number; fileCount: number }> {
|
||||
if (!this.isAuthenticated) {
|
||||
const ok = await this.login()
|
||||
if (!ok) return { totalSize: 0, folderCount: 0, fileCount: 0 }
|
||||
}
|
||||
const res = await fetch(`${this.baseUrl}/api/resources/`, {
|
||||
headers: this.headers(),
|
||||
})
|
||||
if (!res.ok) return { totalSize: 0, folderCount: 0, fileCount: 0 }
|
||||
const data: FileBrowserListResponse = await res.json()
|
||||
const items = data.items || []
|
||||
const folderCount = items.filter(i => i.isDir).length
|
||||
const fileCount = items.filter(i => !i.isDir).length
|
||||
const totalSize = items.reduce((sum, i) => sum + (i.size || 0), 0)
|
||||
return { totalSize, folderCount, fileCount }
|
||||
}
|
||||
|
||||
async rename(oldPath: string, newName: string): Promise<void> {
|
||||
const safePath = oldPath.startsWith('/') ? oldPath : `/${oldPath}`
|
||||
const dir = safePath.substring(0, safePath.lastIndexOf('/') + 1)
|
||||
|
||||
@ -91,11 +91,11 @@
|
||||
<div class="home-card-stats grid grid-cols-2 gap-4 mb-4 flex-1 min-h-0">
|
||||
<div class="p-4 bg-white/5 rounded-lg">
|
||||
<p class="text-xs text-white/60 mb-1">Storage Used</p>
|
||||
<p class="text-2xl font-bold text-white">2.4 GB</p>
|
||||
<p class="text-2xl font-bold text-white">{{ cloudStorageDisplay }}</p>
|
||||
</div>
|
||||
<div class="p-4 bg-white/5 rounded-lg">
|
||||
<p class="text-xs text-white/60 mb-1">Folders</p>
|
||||
<p class="text-2xl font-bold text-white">5</p>
|
||||
<p class="text-2xl font-bold text-white">{{ cloudFolderDisplay }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-card-buttons flex gap-2 mt-auto pt-4 shrink-0">
|
||||
@ -275,7 +275,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch, onBeforeUnmount } from 'vue'
|
||||
import { computed, ref, watch, onBeforeUnmount, onMounted } from 'vue'
|
||||
import { RouterLink, useRouter } from 'vue-router'
|
||||
import { useAppStore } from '../stores/app'
|
||||
import { useAppLauncherStore } from '@/stores/appLauncher'
|
||||
@ -285,6 +285,7 @@ import { PackageState } from '../types/api'
|
||||
import { playTypingSound } from '@/composables/useLoginSounds'
|
||||
import { GOALS } from '@/data/goals'
|
||||
import EasyHome from '@/components/EasyHome.vue'
|
||||
import { fileBrowserClient } from '@/api/filebrowser-client'
|
||||
|
||||
const router = useRouter()
|
||||
const uiMode = useUIModeStore()
|
||||
@ -402,6 +403,35 @@ function dismissQuickStart() {
|
||||
|
||||
loadQuickStartState()
|
||||
|
||||
// Cloud data
|
||||
const cloudStorageUsed = ref<number | null>(null)
|
||||
const cloudFolderCount = ref<number | null>(null)
|
||||
|
||||
function formatBytes(bytes: number): string {
|
||||
if (bytes === 0) return '0 B'
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB']
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024))
|
||||
const val = bytes / Math.pow(1024, i)
|
||||
return `${val < 10 ? val.toFixed(1) : Math.round(val)} ${units[i]}`
|
||||
}
|
||||
|
||||
const cloudStorageDisplay = computed(() =>
|
||||
cloudStorageUsed.value !== null ? formatBytes(cloudStorageUsed.value) : '...'
|
||||
)
|
||||
const cloudFolderDisplay = computed(() =>
|
||||
cloudFolderCount.value !== null ? String(cloudFolderCount.value) : '...'
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const usage = await fileBrowserClient.getUsage()
|
||||
cloudStorageUsed.value = usage.totalSize
|
||||
cloudFolderCount.value = usage.folderCount
|
||||
} catch {
|
||||
// FileBrowser may not be running — leave as loading
|
||||
}
|
||||
})
|
||||
|
||||
function uploadFiles() {
|
||||
const pkg = packages.value['filebrowser']
|
||||
if (pkg && pkg.state === PackageState.Running) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user