enh: drag and drop folders

This commit is contained in:
Timothy J. Baek 2024-10-16 23:06:53 -07:00
parent d5bf32f240
commit 36a541d6b0
5 changed files with 104 additions and 9 deletions

View File

@ -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")

View File

@ -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) => {

View File

@ -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 @@
<div class=" flex-1 flex flex-col overflow-y-auto scrollbar-hidden">
{#if !search && folders}
<Folders {folders} />
<Folders
{folders}
on:update={async (e) => {
await initFolders();
}}
/>
{/if}
<Folder
@ -677,6 +682,21 @@
initChatList();
}
}
} else if (type === 'folder') {
if (folders[id].parent_id === null) {
return;
}
const res = await updateFolderParentIdById(localStorage.token, id, null).catch(
(error) => {
toast.error(error);
return null;
}
);
if (res) {
await initFolders();
}
}
}}
>

View File

@ -1,4 +1,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
import RecursiveFolder from './RecursiveFolder.svelte';
export let folders = {};
@ -15,5 +18,12 @@
</script>
{#each folderList as folderId (folderId)}
<RecursiveFolder className="px-2" {folders} {folderId} />
<RecursiveFolder
className="px-2"
{folders}
{folderId}
on:update={(e) => {
dispatch('update', e.detail);
}}
/>
{/each}

View File

@ -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}`)}
<svelte:self {folders} folderId={childId} parentDragged={dragged} />
<svelte:self
{folders}
folderId={childId}
parentDragged={dragged}
on:update={(e) => {
dispatch('update', e.detail);
}}
/>
{/each}
{/if}