feat: delete all user chats

This commit is contained in:
Timothy J. Baek 2023-12-30 00:15:37 -08:00
parent ee8e7c300a
commit d5dc36b2a9
3 changed files with 189 additions and 123 deletions

View file

@ -159,3 +159,23 @@ async def delete_chat_by_id(id: str, cred=Depends(bearer_scheme)):
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.INVALID_TOKEN, detail=ERROR_MESSAGES.INVALID_TOKEN,
) )
############################
# DeleteAllChats
############################
@router.delete("/", response_model=bool)
async def delete_all_user_chats(cred=Depends(bearer_scheme)):
token = cred.credentials
user = Users.get_user_by_token(token)
if user:
result = Chats.delete_chats_by_user_id(user.id)
return result
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.INVALID_TOKEN,
)

View file

@ -191,3 +191,35 @@ export const deleteChatById = async (token: string, id: string) => {
return res; return res;
}; };
export const deleteAllChats = async (token: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/chats/`, {
method: 'DELETE',
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;
};

View file

@ -8,7 +8,7 @@
import { splitStream, getGravatarURL } from '$lib/utils'; import { splitStream, getGravatarURL } from '$lib/utils';
import { getOllamaVersion } from '$lib/apis/ollama'; import { getOllamaVersion } from '$lib/apis/ollama';
import { createNewChat, getAllChats, getChatList } from '$lib/apis/chats'; import { createNewChat, deleteAllChats, getAllChats, getChatList } from '$lib/apis/chats';
import { import {
WEB_UI_VERSION, WEB_UI_VERSION,
OLLAMA_API_BASE_URL, OLLAMA_API_BASE_URL,
@ -19,6 +19,7 @@
import Advanced from './Settings/Advanced.svelte'; import Advanced from './Settings/Advanced.svelte';
import Modal from '../common/Modal.svelte'; import Modal from '../common/Modal.svelte';
import { updateUserPassword } from '$lib/apis/auths'; import { updateUserPassword } from '$lib/apis/auths';
import { goto } from '$app/navigation';
export let show = false; export let show = false;
@ -83,7 +84,7 @@
// Chats // Chats
let importFiles; let importFiles;
let showDeleteHistoryConfirm = false; let showDeleteConfirm = false;
const importChats = async (_chats) => { const importChats = async (_chats) => {
for (const chat of _chats) { for (const chat of _chats) {
@ -114,6 +115,12 @@
reader.readAsText(importFiles[0]); reader.readAsText(importFiles[0]);
} }
const deleteChats = async () => {
await goto('/');
await deleteAllChats(localStorage.token);
await chats.set(await getChatList(localStorage.token));
};
// Auth // Auth
let authEnabled = false; let authEnabled = false;
let authType = 'Basic'; let authType = 'Basic';
@ -1618,6 +1625,7 @@
</form> </form>
{:else if selectedTab === 'chats'} {:else if selectedTab === 'chats'}
<div class="flex flex-col h-full justify-between space-y-3 text-sm"> <div class="flex flex-col h-full justify-between space-y-3 text-sm">
<div class=" space-y-2">
<div class="flex flex-col"> <div class="flex flex-col">
<input <input
id="chat-import-input" id="chat-import-input"
@ -1671,23 +1679,27 @@
<div class=" self-center text-sm font-medium">Export Chats</div> <div class=" self-center text-sm font-medium">Export Chats</div>
</button> </button>
</div> </div>
<!-- {#if showDeleteHistoryConfirm}
<hr class=" dark:border-gray-700" />
{#if showDeleteConfirm}
<div <div
class="flex justify-between rounded-md items-center py-3 px-3.5 w-full transition" class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition"
> >
<div class="flex items-center"> <div class="flex items-center space-x-3">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 16 16"
viewBox="0 0 24 24" fill="currentColor"
stroke-width="1.5" class="w-4 h-4"
stroke="currentColor"
class="w-5 h-5 mr-3"
> >
<path <path
stroke-linecap="round" d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z"
stroke-linejoin="round" />
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" <path
fill-rule="evenodd"
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM5.72 7.47a.75.75 0 0 1 1.06 0L8 8.69l1.22-1.22a.75.75 0 1 1 1.06 1.06L9.06 9.75l1.22 1.22a.75.75 0 1 1-1.06 1.06L8 10.81l-1.22 1.22a.75.75 0 0 1-1.06-1.06l1.22-1.22-1.22-1.22a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
/> />
</svg> </svg>
<span>Are you sure?</span> <span>Are you sure?</span>
@ -1697,8 +1709,8 @@
<button <button
class="hover:text-white transition" class="hover:text-white transition"
on:click={() => { on:click={() => {
deleteChatHistory(); deleteChats();
showDeleteHistoryConfirm = false; showDeleteConfirm = false;
}} }}
> >
<svg <svg
@ -1717,7 +1729,7 @@
<button <button
class="hover:text-white transition" class="hover:text-white transition"
on:click={() => { on:click={() => {
showDeleteHistoryConfirm = false; showDeleteConfirm = false;
}} }}
> >
<svg <svg
@ -1735,30 +1747,32 @@
</div> </div>
{:else} {:else}
<button <button
class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition" class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
on:click={() => { on:click={() => {
showDeleteHistoryConfirm = true; showDeleteConfirm = true;
}} }}
> >
<div class="mr-3"> <div class=" self-center mr-3">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 16 16"
viewBox="0 0 24 24" fill="currentColor"
stroke-width="1.5" class="w-4 h-4"
stroke="currentColor"
class="w-5 h-5"
> >
<path <path
stroke-linecap="round" d="M2 3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3Z"
stroke-linejoin="round" />
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" <path
fill-rule="evenodd"
d="M13 6H3v6a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V6ZM5.72 7.47a.75.75 0 0 1 1.06 0L8 8.69l1.22-1.22a.75.75 0 1 1 1.06 1.06L9.06 9.75l1.22 1.22a.75.75 0 1 1-1.06 1.06L8 10.81l-1.22 1.22a.75.75 0 0 1-1.06-1.06l1.22-1.22-1.22-1.22a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"
/> />
</svg> </svg>
</div> </div>
<span>Clear conversations</span> <div class=" self-center text-sm font-medium">Delete All Chats</div>
</button> </button>
{/if} --> {/if}
</div>
</div> </div>
{:else if selectedTab === 'auth'} {:else if selectedTab === 'auth'}
<form <form