Merge pull request #2749 from open-webui/dev

feat: single chat export
This commit is contained in:
Timothy Jaeryang Baek 2024-06-02 21:39:36 -07:00 committed by GitHub
commit 4b459e372f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 75 additions and 1 deletions

View File

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

View File

@ -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
############################

View File

@ -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;

View File

@ -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`);
};
</script>
<Dropdown
@ -164,6 +171,14 @@
transition={flyAndScale}
sideOffset={8}
>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
on:click={() => {
downloadJSONExport();
}}
>
<div class="flex items-center line-clamp-1">{$i18n.t('Export chat (.json)')}</div>
</DropdownMenu.Item>
<DropdownMenu.Item
class="flex gap-2 items-center px-3 py-2 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md"
on:click={() => {

View File

@ -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'
});