From 36a541d6b0162af59b085a38c9be9ed43e7c130e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Wed, 16 Oct 2024 23:06:53 -0700 Subject: [PATCH] enh: drag and drop folders --- .../open_webui/apps/webui/routers/folders.py | 2 +- src/lib/apis/folders/index.ts | 35 +++++++++++++++- src/lib/components/layout/Sidebar.svelte | 24 ++++++++++- .../components/layout/Sidebar/Folders.svelte | 12 +++++- .../layout/Sidebar/RecursiveFolder.svelte | 40 +++++++++++++++++-- 5 files changed, 104 insertions(+), 9 deletions(-) diff --git a/backend/open_webui/apps/webui/routers/folders.py b/backend/open_webui/apps/webui/routers/folders.py index 90276131f..cb96eec03 100644 --- a/backend/open_webui/apps/webui/routers/folders.py +++ b/backend/open_webui/apps/webui/routers/folders.py @@ -137,7 +137,7 @@ async def update_folder_name_by_id( class FolderParentIdForm(BaseModel): - parent_id: str + parent_id: Optional[str] = None @router.post("/{id}/update/parent") diff --git a/src/lib/apis/folders/index.ts b/src/lib/apis/folders/index.ts index f0912f780..f1a1f5b48 100644 --- a/src/lib/apis/folders/index.ts +++ b/src/lib/apis/folders/index.ts @@ -164,10 +164,43 @@ export const updateFolderIsExpandedById = async ( return res; }; +export const updateFolderParentIdById = async (token: string, id: string, parentId?: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/folders/${id}/update/parent`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + parent_id: parentId + }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + type FolderItems = { chat_ids: string[]; file_ids: string[]; - folder_ids: string[]; }; export const updateFolderItemsById = async (token: string, id: string, items: FolderItems) => { diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index 7df48ccba..8b38e8181 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -43,7 +43,7 @@ import Folder from '../common/Folder.svelte'; import Plus from '../icons/Plus.svelte'; import Tooltip from '../common/Tooltip.svelte'; - import { createNewFolder, getFolders } from '$lib/apis/folders'; + import { createNewFolder, getFolders, updateFolderParentIdById } from '$lib/apis/folders'; import Folders from './Sidebar/Folders.svelte'; const BREAKPOINT = 768; @@ -656,7 +656,12 @@
{#if !search && folders} - + { + await initFolders(); + }} + /> {/if} { + toast.error(error); + return null; + } + ); + + if (res) { + await initFolders(); + } } }} > diff --git a/src/lib/components/layout/Sidebar/Folders.svelte b/src/lib/components/layout/Sidebar/Folders.svelte index e675c609e..67152a98d 100644 --- a/src/lib/components/layout/Sidebar/Folders.svelte +++ b/src/lib/components/layout/Sidebar/Folders.svelte @@ -1,4 +1,7 @@ {#each folderList as folderId (folderId)} - + { + dispatch('update', e.detail); + }} + /> {/each} diff --git a/src/lib/components/layout/Sidebar/RecursiveFolder.svelte b/src/lib/components/layout/Sidebar/RecursiveFolder.svelte index de4cc0f37..b2b3eaadd 100644 --- a/src/lib/components/layout/Sidebar/RecursiveFolder.svelte +++ b/src/lib/components/layout/Sidebar/RecursiveFolder.svelte @@ -11,7 +11,11 @@ import FolderOpen from '$lib/components/icons/FolderOpen.svelte'; import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte'; - import { updateFolderIsExpandedById, updateFolderNameById } from '$lib/apis/folders'; + import { + updateFolderIsExpandedById, + updateFolderNameById, + updateFolderParentIdById + } from '$lib/apis/folders'; import { toast } from 'svelte-sonner'; export let open = true; @@ -41,7 +45,7 @@ draggedOver = true; }; - const onDrop = (e) => { + const onDrop = async (e) => { e.preventDefault(); e.stopPropagation(); if (dragged || parentDragged) { @@ -56,7 +60,28 @@ const dataTransfer = e.dataTransfer.getData('text/plain'); const data = JSON.parse(dataTransfer); console.log(data); - dispatch('drop', data); + + const { type, id } = data; + + if (type === 'folder') { + if (id === folderId) { + return; + } + // Move the folder + const res = await updateFolderParentIdById(localStorage.token, id, folderId).catch( + (error) => { + toast.error(error); + return null; + } + ); + + if (res) { + dispatch('update'); + } + } else if (type === 'chat') { + // Move the chat + console.log('Move the chat'); + } } catch (error) { console.error(error); } @@ -285,7 +310,14 @@ > {#if folders[folderId]?.childrenIds} {#each folders[folderId]?.childrenIds as childId (`${folderId}-${childId}`)} - + { + dispatch('update', e.detail); + }} + /> {/each} {/if}