瀏覽代碼

enh: save isExpanded state

Timothy J. Baek 6 月之前
父節點
當前提交
d5bf32f240

+ 26 - 2
backend/open_webui/apps/webui/models/folders.py

@@ -8,7 +8,7 @@ from open_webui.apps.webui.internal.db import Base, get_db
 
 from open_webui.env import SRC_LOG_LEVELS
 from pydantic import BaseModel, ConfigDict
-from sqlalchemy import BigInteger, Column, Text, JSON, PrimaryKeyConstraint
+from sqlalchemy import BigInteger, Column, Text, JSON, Boolean
 
 log = logging.getLogger(__name__)
 log.setLevel(SRC_LOG_LEVELS["MODELS"])
@@ -34,6 +34,7 @@ class Folder(Base):
     name = Column(Text)
     items = Column(JSON, nullable=True)
     meta = Column(JSON, nullable=True)
+    is_expanded = Column(Boolean, default=False)
     created_at = Column(BigInteger)
     updated_at = Column(BigInteger)
 
@@ -45,6 +46,7 @@ class FolderModel(BaseModel):
     name: str
     items: Optional[FolderItems] = None
     meta: Optional[dict] = None
+    is_expanded: bool = False
     created_at: int
     updated_at: int
 
@@ -121,9 +123,11 @@ class FolderTable:
     ) -> Optional[FolderModel]:
         try:
             with get_db() as db:
+                # Check if folder exists
                 folder = (
                     db.query(Folder)
-                    .filter_by(parent_id=parent_id, user_id=user_id, name=name.lower())
+                    .filter_by(parent_id=parent_id, user_id=user_id)
+                    .filter(Folder.name.ilike(name))
                     .first()
                 )
 
@@ -198,6 +202,26 @@ class FolderTable:
             log.error(f"update_folder: {e}")
             return
 
+    def update_folder_is_expanded_by_id_and_user_id(
+        self, id: str, user_id: str, is_expanded: bool
+    ) -> Optional[FolderModel]:
+        try:
+            with get_db() as db:
+                folder = db.query(Folder).filter_by(id=id, user_id=user_id).first()
+
+                if not folder:
+                    return None
+
+                folder.is_expanded = is_expanded
+                folder.updated_at = int(time.time())
+
+                db.commit()
+
+                return FolderModel.model_validate(folder)
+        except Exception as e:
+            log.error(f"update_folder: {e}")
+            return
+
     def update_folder_items_by_id_and_user_id(
         self, id: str, user_id: str, items: FolderItems
     ) -> Optional[FolderModel]:

+ 36 - 1
backend/open_webui/apps/webui/routers/folders.py

@@ -115,6 +115,7 @@ async def update_folder_name_by_id(
             folder = Folders.update_folder_name_by_id_and_user_id(
                 id, user.id, form_data.name
             )
+
             return folder
         except Exception as e:
             log.exception(e)
@@ -131,7 +132,7 @@ async def update_folder_name_by_id(
 
 
 ############################
-# Update Folder Name By Id
+# Update Folder Parent Id By Id
 ############################
 
 
@@ -174,6 +175,40 @@ async def update_folder_parent_id_by_id(
         )
 
 
+############################
+# Update Folder Is Expanded By Id
+############################
+
+
+class FolderIsExpandedForm(BaseModel):
+    is_expanded: bool
+
+
+@router.post("/{id}/update/expanded")
+async def update_folder_is_expanded_by_id(
+    id: str, form_data: FolderIsExpandedForm, user=Depends(get_verified_user)
+):
+    folder = Folders.get_folder_by_id_and_user_id(id, user.id)
+    if folder:
+        try:
+            folder = Folders.update_folder_is_expanded_by_id_and_user_id(
+                id, user.id, form_data.is_expanded
+            )
+            return folder
+        except Exception as e:
+            log.exception(e)
+            log.error(f"Error updating folder: {id}")
+            raise HTTPException(
+                status_code=status.HTTP_400_BAD_REQUEST,
+                detail=ERROR_MESSAGES.DEFAULT("Error updating folder"),
+            )
+    else:
+        raise HTTPException(
+            status_code=status.HTTP_404_NOT_FOUND,
+            detail=ERROR_MESSAGES.NOT_FOUND,
+        )
+
+
 ############################
 # Update Folder Items By Id
 ############################

+ 1 - 0
backend/open_webui/migrations/versions/c69f45358db4_add_folder_table.py

@@ -24,6 +24,7 @@ def upgrade():
         sa.Column("name", sa.Text(), nullable=False),
         sa.Column("items", sa.JSON(), nullable=True),
         sa.Column("meta", sa.JSON(), nullable=True),
+        sa.Column("is_expanded", sa.Boolean(), default=False, nullable=False),
         sa.Column(
             "created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False
         ),

+ 38 - 0
src/lib/apis/folders/index.ts

@@ -126,6 +126,44 @@ export const updateFolderNameById = async (token: string, id: string, name: stri
 	return res;
 };
 
+export const updateFolderIsExpandedById = async (
+	token: string,
+	id: string,
+	isExpanded: boolean
+) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/folders/${id}/update/expanded`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			is_expanded: isExpanded
+		})
+	})
+		.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[];

+ 22 - 1
src/lib/components/layout/Sidebar/RecursiveFolder.svelte

@@ -11,7 +11,7 @@
 
 	import FolderOpen from '$lib/components/icons/FolderOpen.svelte';
 	import EllipsisHorizontal from '$lib/components/icons/EllipsisHorizontal.svelte';
-	import { updateFolderNameById } from '$lib/apis/folders';
+	import { updateFolderIsExpandedById, updateFolderNameById } from '$lib/apis/folders';
 	import { toast } from 'svelte-sonner';
 
 	export let open = true;
@@ -113,6 +113,7 @@
 	};
 
 	onMount(() => {
+		open = folders[folderId].is_expanded;
 		if (folderElement) {
 			folderElement.addEventListener('dragover', onDragOver);
 			folderElement.addEventListener('drop', onDrop);
@@ -166,6 +167,26 @@
 			folders[folderId].name = name;
 		}
 	};
+
+	const isExpandedUpdateHandler = async () => {
+		const res = await updateFolderIsExpandedById(localStorage.token, folderId, open).catch(
+			(error) => {
+				toast.error(error);
+				return null;
+			}
+		);
+	};
+
+	let isExpandedUpdateTimeout;
+
+	const isExpandedUpdateDebounceHandler = (open) => {
+		clearTimeout(isExpandedUpdateTimeout);
+		isExpandedUpdateTimeout = setTimeout(() => {
+			isExpandedUpdateHandler();
+		}, 500);
+	};
+
+	$: isExpandedUpdateDebounceHandler(open);
 </script>
 
 {#if dragged && x && y}