From ab0ee858b73738c5b77d1d455e66e66bc61df1c4 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 14 May 2026 00:07:55 +0900 Subject: [PATCH] refac --- .../workspace/Knowledge/KnowledgeBase.svelte | 21 +++++++- .../KnowledgeBase/DirectoryRow.svelte | 36 ++++++++++--- .../Knowledge/KnowledgeBase/Files.svelte | 2 + .../KnowledgeBase/KnowledgeBreadcrumbs.svelte | 53 ++++++++++++++++++- 4 files changed, 100 insertions(+), 12 deletions(-) diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte index a1e54f8059..647da19568 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase.svelte @@ -653,6 +653,21 @@ } }; + const moveDirectoryHandler = async (dirId: string, targetParentId: string | null) => { + if (dirId === targetParentId) return; + const res = await updateKnowledgeDirectory(localStorage.token, knowledge.id, dirId, { + parent_id: targetParentId + }).catch((e) => { + toast.error(`${e}`); + return null; + }); + + if (res) { + toast.success($i18n.t('Directory moved.')); + getItemsPage(); + } + }; + const deleteFileHandler = async (fileId) => { try { console.log('Starting file deletion process for:', fileId); @@ -1092,7 +1107,7 @@ {#if currentDirectoryId !== null}
- navigateToDirectory(dirId)} /> + navigateToDirectory(dirId)} onMoveFile={(fileId, dirId) => moveFileToDirectoryHandler(fileId, dirId)} onMoveDir={(dirId, targetId) => moveDirectoryHandler(dirId, targetId)} />
{/if} @@ -1187,7 +1202,9 @@ onDeleteDirectory={(id) => confirmDeleteDirectory(id)} onMoveFileToDirectory={(fileId, dirId) => moveFileToDirectoryHandler(fileId, dirId)} - /> + onMoveDirectoryToDirectory={(dirId, targetId) => moveDirectoryHandler(dirId, targetId)} + /> + {#if fileItemsTotal > 30} diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte index 65a76aec48..70de8b5444 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte @@ -28,7 +28,7 @@ export let onRename: (id: string, name: string) => void = () => {}; export let onDelete: (id: string) => void = () => {}; export let onFileDrop: (fileId: string, directoryId: string) => void = () => {}; - + export let onDirDrop: (dirId: string, targetDirectoryId: string) => void = () => {}; let editing = false; let editName = ''; let editInput: HTMLInputElement; @@ -62,11 +62,20 @@ {dragOver ? 'bg-gray-100 dark:bg-gray-800 ring-1 ring-gray-300 dark:ring-gray-600' : 'hover:bg-gray-100 dark:hover:bg-gray-850'}" + draggable="true" + on:dragstart={(e) => { + e.dataTransfer?.setData( + 'application/x-kb-dir-move', + JSON.stringify({ dirId: directory.id }) + ); + }} on:dblclick={() => { if (writeAccess) startRename(); }} on:dragover={(e) => { - if (!e.dataTransfer?.types.includes('application/x-kb-file-move')) return; + const hasFile = e.dataTransfer?.types.includes('application/x-kb-file-move'); + const hasDir = e.dataTransfer?.types.includes('application/x-kb-dir-move'); + if (!hasFile && !hasDir) return; e.preventDefault(); e.stopPropagation(); dragOver = true; @@ -75,15 +84,26 @@ dragOver = false; }} on:drop={(e) => { - const raw = e.dataTransfer?.getData('application/x-kb-file-move'); - if (!raw) return; e.preventDefault(); e.stopPropagation(); dragOver = false; - try { - const data = JSON.parse(raw); - onFileDrop(data.fileId, directory.id); - } catch {} + const fileRaw = e.dataTransfer?.getData('application/x-kb-file-move'); + if (fileRaw) { + try { + const data = JSON.parse(fileRaw); + onFileDrop(data.fileId, directory.id); + } catch {} + return; + } + const dirRaw = e.dataTransfer?.getData('application/x-kb-dir-move'); + if (dirRaw) { + try { + const data = JSON.parse(dirRaw); + if (data.dirId !== directory.id) { + onDirDrop(data.dirId, directory.id); + } + } catch {} + } }} >
diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/Files.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/Files.svelte index 65a17bf1b4..fbe5082fe3 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase/Files.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/Files.svelte @@ -33,6 +33,7 @@ export let onRenameDirectory = (id: string, name: string) => {}; export let onDeleteDirectory = (id: string) => {}; export let onMoveFileToDirectory = (fileId: string, directoryId: string) => {}; + export let onMoveDirectoryToDirectory = (dirId: string, targetDirectoryId: string) => {};
@@ -45,6 +46,7 @@ onRename={(id, name) => onRenameDirectory(id, name)} onDelete={(id) => onDeleteDirectory(id)} onFileDrop={(fileId, directoryId) => onMoveFileToDirectory(fileId, directoryId)} + onDirDrop={(dirId, targetId) => onMoveDirectoryToDirectory(dirId, targetId)} /> {/each} diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/KnowledgeBreadcrumbs.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/KnowledgeBreadcrumbs.svelte index d3f152c214..f124acb2ff 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase/KnowledgeBreadcrumbs.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/KnowledgeBreadcrumbs.svelte @@ -7,12 +7,49 @@ export let rootLabel: string = 'Root'; export let breadcrumbs: { id: string; name: string }[] = []; export let onNavigate: (directoryId: string | null) => void = () => {}; + export let onMoveFile: (fileId: string, targetDirectoryId: string | null) => void = () => {}; + export let onMoveDir: (dirId: string, targetDirectoryId: string | null) => void = () => {}; let breadcrumbEl: HTMLDivElement; + let dragOverCrumb: number | null = null; afterUpdate(() => { if (breadcrumbEl) breadcrumbEl.scrollLeft = breadcrumbEl.scrollWidth; }); + + const handleDragOver = (e: DragEvent, index: number) => { + const hasFile = e.dataTransfer?.types.includes('application/x-kb-file-move'); + const hasDir = e.dataTransfer?.types.includes('application/x-kb-dir-move'); + if (!hasFile && !hasDir) return; + e.preventDefault(); + e.stopPropagation(); + dragOverCrumb = index; + }; + + const handleDragLeave = (index: number) => { + if (dragOverCrumb === index) dragOverCrumb = null; + }; + + const handleDrop = (e: DragEvent, targetDirId: string | null) => { + e.preventDefault(); + e.stopPropagation(); + dragOverCrumb = null; + const fileRaw = e.dataTransfer?.getData('application/x-kb-file-move'); + if (fileRaw) { + try { + const data = JSON.parse(fileRaw); + if (data.fileId) onMoveFile(data.fileId, targetDirId); + } catch {} + return; + } + const dirRaw = e.dataTransfer?.getData('application/x-kb-dir-move'); + if (dirRaw) { + try { + const data = JSON.parse(dirRaw); + if (data.dirId) onMoveDir(data.dirId, targetDirId); + } catch {} + } + };
onNavigate(null)} + on:dragover={(e) => handleDragOver(e, -1)} + on:dragleave={() => handleDragLeave(-1)} + on:drop={(e) => handleDrop(e, null)} > {rootLabel} @@ -35,8 +78,14 @@ class="text-xs shrink-0 py-0.5 hover:underline transition {i === breadcrumbs.length - 1 ? 'text-gray-700 dark:text-gray-300' - : 'text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-400'}" + : 'text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-400'} + {dragOverCrumb === i + ? 'bg-gray-100 dark:bg-gray-800 rounded-lg' + : ''}" on:click={() => onNavigate(crumb.id)} + on:dragover={(e) => handleDragOver(e, i)} + on:dragleave={() => handleDragLeave(i)} + on:drop={(e) => handleDrop(e, crumb.id)} > {crumb.name}