ref: app UI

This commit is contained in:
2026-08-26 00:11:45 +07:00
parent 8fe5e44f52
commit 5f52a6c554
16 changed files with 634 additions and 309 deletions
+49 -4
View File
@@ -31,14 +31,19 @@
@delete="confirmDelete"
/>
<Dialog v-model:visible="createDialog" :header="`New ${createType}`" :modal="true" style="width: min(420px, 92vw)">
<Dialog v-model:visible="createDialog" :header="`New ${createType}`" :modal="true" style="width: min(480px, 92vw)">
<div class="field">
<label>Title</label>
<label>Path</label>
<InputText v-model.trim="createPath" class="w-full font-mono" placeholder="/folder/file.md" @keyup.enter="onCreate" />
<small class="muted-note">Folders in the path will be created if they don't exist.</small>
</div>
<div class="field">
<label>Name</label>
<InputText v-model.trim="createTitle" class="w-full" autofocus @keyup.enter="onCreate" />
</div>
<template #footer>
<Button label="Cancel" severity="secondary" text @click="createDialog = false" />
<Button label="Create" @click="onCreate" />
<Button label="Create" :loading="creating" @click="onCreate" />
</template>
</Dialog>
@@ -109,6 +114,8 @@ const searchMode = ref(false)
const createDialog = ref(false)
const createType = ref<DocumentType>('Document')
const createTitle = ref('')
const createPath = ref('/')
const creating = ref(false)
const renameDialog = ref(false)
const renameTitle = ref('')
const moveDialog = ref(false)
@@ -221,16 +228,52 @@ async function onSave() {
function openCreate(type: DocumentType) {
createType.value = type
createTitle.value = ''
const currentFolder = doc.value?.type === 'Folder' ? doc.value.title : ''
createPath.value = currentFolder ? `/${currentFolder}/` : '/'
createDialog.value = true
}
function findFolderByPath(segments: string[]): string | null {
let nodes = tree.value
let parentId: string | null = null
for (const seg of segments) {
const folder = nodes.find((n) => n.type === 'Folder' && n.title.toLowerCase() === seg.toLowerCase())
if (!folder) return parentId
parentId = folder.id
nodes = folder.children
}
return parentId
}
async function onCreate() {
if (!createTitle.value) {
toast.add({ severity: 'warn', summary: 'Title is required', life: 3000 })
return
}
const parentId = doc.value?.type === 'Folder' ? doc.value.id : null
creating.value = true
try {
const rawPath = createPath.value.trim()
const segments = rawPath.split('/').filter(Boolean)
let parentId = findFolderByPath(segments)
// Create missing folders from path
let nodes = tree.value
for (const seg of segments) {
const existing = nodes.find((n) => n.type === 'Folder' && n.title.toLowerCase() === seg.toLowerCase())
if (existing) {
nodes = existing.children
} else {
const created = await createDocument(projectId, {
title: seg,
type: 'Folder',
parentId,
content: null,
})
parentId = created.id
nodes = []
}
}
const created = await createDocument(projectId, {
title: createTitle.value,
type: createType.value,
@@ -244,6 +287,8 @@ async function onCreate() {
}
} catch (e) {
toast.add({ severity: 'error', summary: 'Error', detail: errorMessage(e), life: 4000 })
} finally {
creating.value = false
}
}