forked from open-webui/open-webui
		
	feat: delete all user chats
This commit is contained in:
		
							parent
							
								
									ee8e7c300a
								
							
						
					
					
						commit
						d5dc36b2a9
					
				
					 3 changed files with 189 additions and 123 deletions
				
			
		|  | @ -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, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek