From fddf693dadeda134303bef10d13575312a46495e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 2 Jun 2024 21:39:09 -0700 Subject: [PATCH] feat: single chat export --- backend/apps/webui/models/chats.py | 9 ++++++ backend/apps/webui/routers/chats.py | 13 ++++++++ src/lib/apis/chats/index.ts | 31 +++++++++++++++++++ src/lib/components/layout/Navbar/Menu.svelte | 15 +++++++++ .../layout/Sidebar/ArchivedChatsModal.svelte | 8 ++++- 5 files changed, 75 insertions(+), 1 deletion(-) diff --git a/backend/apps/webui/models/chats.py b/backend/apps/webui/models/chats.py index d4597f16d..a6f1ae923 100644 --- a/backend/apps/webui/models/chats.py +++ b/backend/apps/webui/models/chats.py @@ -298,6 +298,15 @@ class ChatTable: # .limit(limit).offset(skip) ] + def get_archived_chats_by_user_id(self, user_id: str) -> List[ChatModel]: + return [ + ChatModel(**model_to_dict(chat)) + for chat in Chat.select() + .where(Chat.archived == True) + .where(Chat.user_id == user_id) + .order_by(Chat.updated_at.desc()) + ] + def delete_chat_by_id(self, id: str) -> bool: try: query = Chat.delete().where((Chat.id == id)) diff --git a/backend/apps/webui/routers/chats.py b/backend/apps/webui/routers/chats.py index e7d176fd2..49df3d284 100644 --- a/backend/apps/webui/routers/chats.py +++ b/backend/apps/webui/routers/chats.py @@ -113,6 +113,19 @@ async def get_user_chats(user=Depends(get_current_user)): ] +############################ +# GetArchivedChats +############################ + + +@router.get("/all/archived", response_model=List[ChatResponse]) +async def get_user_chats(user=Depends(get_current_user)): + return [ + ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)}) + for chat in Chats.get_archived_chats_by_user_id(user.id) + ] + + ############################ # GetAllChatsInDB ############################ diff --git a/src/lib/apis/chats/index.ts b/src/lib/apis/chats/index.ts index 648e3580e..b046f1b10 100644 --- a/src/lib/apis/chats/index.ts +++ b/src/lib/apis/chats/index.ts @@ -162,6 +162,37 @@ export const getAllChats = async (token: string) => { return res; }; +export const getAllArchivedChats = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/all/archived`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err; + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getAllUserChats = async (token: string) => { let error = null; diff --git a/src/lib/components/layout/Navbar/Menu.svelte b/src/lib/components/layout/Navbar/Menu.svelte index ae53a8872..0ba71a059 100644 --- a/src/lib/components/layout/Navbar/Menu.svelte +++ b/src/lib/components/layout/Navbar/Menu.svelte @@ -63,6 +63,13 @@ // Revoke the URL to release memory window.URL.revokeObjectURL(url); }; + + const downloadJSONExport = async () => { + let blob = new Blob([JSON.stringify([chat])], { + type: 'application/json' + }); + saveAs(blob, `chat-export-${Date.now()}.json`); + }; + { + downloadJSONExport(); + }} + > +
{$i18n.t('Export chat (.json)')}
+
{ diff --git a/src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte b/src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte index da5fc08a0..80e3f1579 100644 --- a/src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte +++ b/src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte @@ -8,7 +8,12 @@ const dispatch = createEventDispatcher(); import Modal from '$lib/components/common/Modal.svelte'; - import { archiveChatById, deleteChatById, getArchivedChatList } from '$lib/apis/chats'; + import { + archiveChatById, + deleteChatById, + getAllArchivedChats, + getArchivedChatList + } from '$lib/apis/chats'; import Tooltip from '$lib/components/common/Tooltip.svelte'; const i18n = getContext('i18n'); @@ -38,6 +43,7 @@ }; const exportChatsHandler = async () => { + const chats = await getAllArchivedChats(localStorage.token); let blob = new Blob([JSON.stringify(chats)], { type: 'application/json' });