mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 04:15:25 +00:00
feat: add backend handling for unarchiving all chats
The previous implementation for unarchiving all chats in `ArchivedChatsModal.svelte` was inefficient, as it sent a separate request for each chat, which could potentially overload the server. This commit introduces a new backend endpoint, `/chats/unarchive/all`, to handle the bulk unarchiving of all chats for a user with a single API call. The frontend has been updated to use this new endpoint, resolving the performance issue by minimizing the number of requests to the server.
This commit is contained in:
parent
4aa41aa139
commit
a572cf4842
4 changed files with 77 additions and 9 deletions
|
|
@ -366,6 +366,15 @@ class ChatTable:
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def unarchive_all_chats_by_user_id(self, user_id: str) -> bool:
|
||||||
|
try:
|
||||||
|
with get_db() as db:
|
||||||
|
db.query(Chat).filter_by(user_id=user_id).update({"archived": False})
|
||||||
|
db.commit()
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
def update_chat_share_id_by_id(
|
def update_chat_share_id_by_id(
|
||||||
self, id: str, share_id: Optional[str]
|
self, id: str, share_id: Optional[str]
|
||||||
) -> Optional[ChatModel]:
|
) -> Optional[ChatModel]:
|
||||||
|
|
|
||||||
|
|
@ -361,6 +361,16 @@ async def archive_all_chats(user=Depends(get_verified_user)):
|
||||||
return Chats.archive_all_chats_by_user_id(user.id)
|
return Chats.archive_all_chats_by_user_id(user.id)
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# UnarchiveAllChats
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/unarchive/all", response_model=bool)
|
||||||
|
async def unarchive_all_chats(user=Depends(get_verified_user)):
|
||||||
|
return Chats.unarchive_all_chats_by_user_id(user.id)
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# GetSharedChatById
|
# GetSharedChatById
|
||||||
############################
|
############################
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,38 @@ export const createNewChat = async (token: string, chat: object, folderId: strin
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const unarchiveAllChats = async (token: string) => {
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/unarchive/all`, {
|
||||||
|
method: 'POST',
|
||||||
|
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.detail;
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export const importChat = async (
|
export const importChat = async (
|
||||||
token: string,
|
token: string,
|
||||||
chat: object,
|
chat: object,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,26 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import fileSaver from 'file-saver';
|
import fileSaver from 'file-saver';
|
||||||
const { saveAs } = fileSaver;
|
const { saveAs } = fileSaver;
|
||||||
|
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { getContext } from 'svelte';
|
import { getContext } from 'svelte';
|
||||||
import { archiveChatById, getAllArchivedChats, getArchivedChatList } from '$lib/apis/chats';
|
import {
|
||||||
|
archiveChatById,
|
||||||
|
getAllArchivedChats,
|
||||||
|
getArchivedChatList,
|
||||||
|
unarchiveAllChats
|
||||||
|
} from '$lib/apis/chats';
|
||||||
|
|
||||||
import ChatsModal from './ChatsModal.svelte';
|
import ChatsModal from './ChatsModal.svelte';
|
||||||
import UnarchiveAllConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
import UnarchiveAllConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';
|
||||||
|
import Spinner from '../common/Spinner.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
export let show = false;
|
export let show = false;
|
||||||
export let onUpdate = () => {};
|
export let onUpdate = () => {};
|
||||||
|
|
||||||
|
let loading = false;
|
||||||
let chatList = null;
|
let chatList = null;
|
||||||
let page = 1;
|
let page = 1;
|
||||||
|
|
||||||
|
|
@ -105,13 +112,17 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const unarchiveAllHandler = async () => {
|
const unarchiveAllHandler = async () => {
|
||||||
const chats = await getAllArchivedChats(localStorage.token);
|
loading = true;
|
||||||
for (const chat of chats) {
|
try {
|
||||||
await archiveChatById(localStorage.token, chat.id);
|
await unarchiveAllChats(localStorage.token);
|
||||||
|
toast.success($i18n.t('All chats have been unarchived.'));
|
||||||
|
onUpdate();
|
||||||
|
await init();
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(`${error}`);
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpdate();
|
|
||||||
init();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
|
|
@ -152,15 +163,21 @@
|
||||||
<div class="flex flex-wrap text-sm font-medium gap-1.5 mt-2 m-1 justify-end w-full">
|
<div class="flex flex-wrap text-sm font-medium gap-1.5 mt-2 m-1 justify-end w-full">
|
||||||
<button
|
<button
|
||||||
class=" px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-100 dark:outline-gray-800 rounded-3xl"
|
class=" px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-100 dark:outline-gray-800 rounded-3xl"
|
||||||
|
disabled={loading}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
showUnarchiveAllConfirmDialog = true;
|
showUnarchiveAllConfirmDialog = true;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{$i18n.t('Unarchive All Archived Chats')}
|
{#if loading}
|
||||||
|
<Spinner className="size-4" />
|
||||||
|
{:else}
|
||||||
|
{$i18n.t('Unarchive All Archived Chats')}
|
||||||
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-100 dark:outline-gray-800 rounded-3xl"
|
class="px-3.5 py-1.5 font-medium hover:bg-black/5 dark:hover:bg-white/5 outline outline-1 outline-gray-100 dark:outline-gray-800 rounded-3xl"
|
||||||
|
disabled={loading}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
exportChatsHandler();
|
exportChatsHandler();
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue