66 lines
1.5 KiB
Vue
66 lines
1.5 KiB
Vue
<template>
|
|
<div class="file-tree">
|
|
<div v-if="loading" class="tree-loading">Loading files...</div>
|
|
<div v-else-if="error" class="tree-error">{{ error }}</div>
|
|
<div v-else-if="!tree || tree.length === 0" class="tree-empty">
|
|
No files. Sync the repository first.
|
|
</div>
|
|
<TreeItem v-else v-model:expanded="expandedPaths" :items="tree" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import TreeItem from './TreeItem.vue'
|
|
|
|
const props = defineProps<{
|
|
siteId: string
|
|
}>()
|
|
|
|
const loading = ref(true)
|
|
const error = ref('')
|
|
const tree = ref<any[]>([])
|
|
const expandedPaths = ref<Set<string>>(new Set())
|
|
|
|
onMounted(async () => {
|
|
loading.value = true
|
|
try {
|
|
const API_BASE = window.location.origin
|
|
const res = await fetch(`${API_BASE}/api/sites/${encodeURIComponent(props.siteId)}/files`)
|
|
if (res.ok) {
|
|
const data = await res.json()
|
|
tree.value = data.tree || []
|
|
} else {
|
|
const errData = await res.json().catch(() => ({}))
|
|
error.value = errData.error || 'Failed to load files'
|
|
}
|
|
} catch {
|
|
error.value = 'Could not connect to server'
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.file-tree {
|
|
height: 100%;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.tree-loading,
|
|
.tree-error,
|
|
.tree-empty {
|
|
padding: 16px;
|
|
color: var(--text-muted);
|
|
text-align: center;
|
|
}
|
|
|
|
.tree-error {
|
|
color: #e53e3e;
|
|
}
|
|
</style>
|