Quellcode durchsuchen

feat: archive all

Timothy J. Baek vor 11 Monaten
Ursprung
Commit
83107c8ea5

+ 1 - 1
backend/apps/webui/routers/chats.py

@@ -148,7 +148,7 @@ async def get_archived_session_user_chat_list(
 ############################
 
 
-@router.get("/archive/all", response_model=List[ChatTitleIdResponse])
+@router.post("/archive/all", response_model=List[ChatTitleIdResponse])
 async def archive_all_chats(user=Depends(get_current_user)):
     return Chats.archive_all_chats_by_user_id(user.id)
 

+ 32 - 0
src/lib/apis/chats/index.ts

@@ -654,3 +654,35 @@ export const deleteAllChats = async (token: string) => {
 
 	return res;
 };
+
+export const archiveAllChats = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/chats/archive/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.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};

+ 164 - 63
src/lib/components/chat/Settings/Chats.svelte

@@ -5,6 +5,7 @@
 	import { chats, user, config } from '$lib/stores';
 
 	import {
+		archiveAllChats,
 		createNewChat,
 		deleteAllChats,
 		getAllChats,
@@ -22,7 +23,10 @@
 	// Chats
 	let saveChatHistory = true;
 	let importFiles;
+
+	let showArchiveConfirm = false;
 	let showDeleteConfirm = false;
+
 	let chatImportInputElement: HTMLInputElement;
 
 	$: if (importFiles) {
@@ -68,6 +72,14 @@
 		saveAs(blob, `chat-export-${Date.now()}.json`);
 	};
 
+	const archiveAllChatsHandler = async () => {
+		await goto('/');
+		await archiveAllChats(localStorage.token).catch((error) => {
+			toast.error(error);
+		});
+		await chats.set(await getChatList(localStorage.token));
+	};
+
 	const deleteAllChatsHandler = async () => {
 		await goto('/');
 		await deleteAllChats(localStorage.token).catch((error) => {
@@ -210,88 +222,177 @@
 
 		<hr class=" dark:border-gray-700" />
 
-		{#if showDeleteConfirm}
-			<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
-				<div class="flex items-center space-x-3">
-					<svg
-						xmlns="http://www.w3.org/2000/svg"
-						viewBox="0 0 16 16"
-						fill="currentColor"
-						class="w-4 h-4"
-					>
-						<path 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" />
-						<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>
-					<span>{$i18n.t('Are you sure?')}</span>
+		<div class="flex flex-col">
+			{#if showArchiveConfirm}
+				<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
+					<div class="flex items-center space-x-3">
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 16 16"
+							fill="currentColor"
+							class="w-4 h-4"
+						>
+							<path 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" />
+							<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>
+						<span>{$i18n.t('Are you sure?')}</span>
+					</div>
+
+					<div class="flex space-x-1.5 items-center">
+						<button
+							class="hover:text-white transition"
+							on:click={() => {
+								archiveAllChatsHandler();
+								showArchiveConfirm = false;
+							}}
+						>
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									fill-rule="evenodd"
+									d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
+									clip-rule="evenodd"
+								/>
+							</svg>
+						</button>
+						<button
+							class="hover:text-white transition"
+							on:click={() => {
+								showArchiveConfirm = false;
+							}}
+						>
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+								/>
+							</svg>
+						</button>
+					</div>
 				</div>
+			{:else}
+				<button
+					class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
+					on:click={() => {
+						showArchiveConfirm = true;
+					}}
+				>
+					<div class=" self-center mr-3">
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 24 24"
+							fill="currentColor"
+							class="size-4"
+						>
+							<path
+								d="M3.375 3C2.339 3 1.5 3.84 1.5 4.875v.75c0 1.036.84 1.875 1.875 1.875h17.25c1.035 0 1.875-.84 1.875-1.875v-.75C22.5 3.839 21.66 3 20.625 3H3.375Z"
+							/>
+							<path
+								fill-rule="evenodd"
+								d="m3.087 9 .54 9.176A3 3 0 0 0 6.62 21h10.757a3 3 0 0 0 2.995-2.824L20.913 9H3.087Zm6.163 3.75A.75.75 0 0 1 10 12h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1-.75-.75Z"
+								clip-rule="evenodd"
+							/>
+						</svg>
+					</div>
+					<div class=" self-center text-sm font-medium">{$i18n.t('Archive All Chats')}</div>
+				</button>
+			{/if}
 
-				<div class="flex space-x-1.5 items-center">
-					<button
-						class="hover:text-white transition"
-						on:click={() => {
-							deleteAllChatsHandler();
-							showDeleteConfirm = false;
-						}}
-					>
+			{#if showDeleteConfirm}
+				<div class="flex justify-between rounded-md items-center py-2 px-3.5 w-full transition">
+					<div class="flex items-center space-x-3">
 						<svg
 							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 20 20"
+							viewBox="0 0 16 16"
 							fill="currentColor"
 							class="w-4 h-4"
 						>
+							<path 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" />
 							<path
 								fill-rule="evenodd"
-								d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
+								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>
-					</button>
-					<button
-						class="hover:text-white transition"
-						on:click={() => {
-							showDeleteConfirm = false;
-						}}
-					>
+						<span>{$i18n.t('Are you sure?')}</span>
+					</div>
+
+					<div class="flex space-x-1.5 items-center">
+						<button
+							class="hover:text-white transition"
+							on:click={() => {
+								deleteAllChatsHandler();
+								showDeleteConfirm = false;
+							}}
+						>
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									fill-rule="evenodd"
+									d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
+									clip-rule="evenodd"
+								/>
+							</svg>
+						</button>
+						<button
+							class="hover:text-white transition"
+							on:click={() => {
+								showDeleteConfirm = false;
+							}}
+						>
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+								/>
+							</svg>
+						</button>
+					</div>
+				</div>
+			{:else}
+				<button
+					class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
+					on:click={() => {
+						showDeleteConfirm = true;
+					}}
+				>
+					<div class=" self-center mr-3">
 						<svg
 							xmlns="http://www.w3.org/2000/svg"
-							viewBox="0 0 20 20"
+							viewBox="0 0 16 16"
 							fill="currentColor"
 							class="w-4 h-4"
 						>
 							<path
-								d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
+								fill-rule="evenodd"
+								d="M4 2a1.5 1.5 0 0 0-1.5 1.5v9A1.5 1.5 0 0 0 4 14h8a1.5 1.5 0 0 0 1.5-1.5V6.621a1.5 1.5 0 0 0-.44-1.06L9.94 2.439A1.5 1.5 0 0 0 8.878 2H4Zm7 7a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1 0-1.5h4.5A.75.75 0 0 1 11 9Z"
+								clip-rule="evenodd"
 							/>
 						</svg>
-					</button>
-				</div>
-			</div>
-		{:else}
-			<button
-				class=" flex rounded-md py-2 px-3.5 w-full hover:bg-gray-200 dark:hover:bg-gray-800 transition"
-				on:click={() => {
-					showDeleteConfirm = true;
-				}}
-			>
-				<div class=" self-center mr-3">
-					<svg
-						xmlns="http://www.w3.org/2000/svg"
-						viewBox="0 0 16 16"
-						fill="currentColor"
-						class="w-4 h-4"
-					>
-						<path
-							fill-rule="evenodd"
-							d="M4 2a1.5 1.5 0 0 0-1.5 1.5v9A1.5 1.5 0 0 0 4 14h8a1.5 1.5 0 0 0 1.5-1.5V6.621a1.5 1.5 0 0 0-.44-1.06L9.94 2.439A1.5 1.5 0 0 0 8.878 2H4Zm7 7a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1 0-1.5h4.5A.75.75 0 0 1 11 9Z"
-							clip-rule="evenodd"
-						/>
-					</svg>
-				</div>
-				<div class=" self-center text-sm font-medium">{$i18n.t('Delete All Chats')}</div>
-			</button>
-		{/if}
+					</div>
+					<div class=" self-center text-sm font-medium">{$i18n.t('Delete All Chats')}</div>
+				</button>
+			{/if}
+		</div>
 	</div>
 </div>

+ 90 - 86
src/lib/components/layout/Sidebar/ArchivedChatsModal.svelte

@@ -101,95 +101,99 @@
 			<hr class=" dark:border-gray-850 my-2" />
 			<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
 				{#if chats.length > 0}
-					<div class="text-left text-sm w-full mb-3 max-h-[22rem] overflow-y-scroll">
-						<div class="relative overflow-x-auto">
-							<table class="w-full text-sm text-left text-gray-600 dark:text-gray-400 table-auto">
-								<thead
-									class="text-xs text-gray-700 uppercase bg-transparent dark:text-gray-200 border-b-2 dark:border-gray-800"
-								>
-									<tr>
-										<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
-										<th scope="col" class="px-3 py-2 hidden md:flex"> {$i18n.t('Created At')} </th>
-										<th scope="col" class="px-3 py-2 text-right" />
-									</tr>
-								</thead>
-								<tbody>
-									{#each chats.filter((c) => searchValue === '' || c.title
-												.toLowerCase()
-												.includes(searchValue.toLowerCase())) as chat, idx}
-										<tr
-											class="bg-transparent {idx !== chats.length - 1 &&
-												'border-b'} dark:bg-gray-900 dark:border-gray-850 text-xs"
-										>
-											<td class="px-3 py-1 w-2/3">
-												<a href="/c/{chat.id}" target="_blank">
-													<div class=" underline line-clamp-1">
-														{chat.title}
+					<div>
+						<div class="text-left text-sm w-full mb-3 max-h-[22rem] overflow-y-scroll">
+							<div class="relative overflow-x-auto">
+								<table class="w-full text-sm text-left text-gray-600 dark:text-gray-400 table-auto">
+									<thead
+										class="text-xs text-gray-700 uppercase bg-transparent dark:text-gray-200 border-b-2 dark:border-gray-800"
+									>
+										<tr>
+											<th scope="col" class="px-3 py-2"> {$i18n.t('Name')} </th>
+											<th scope="col" class="px-3 py-2 hidden md:flex">
+												{$i18n.t('Created At')}
+											</th>
+											<th scope="col" class="px-3 py-2 text-right" />
+										</tr>
+									</thead>
+									<tbody>
+										{#each chats.filter((c) => searchValue === '' || c.title
+													.toLowerCase()
+													.includes(searchValue.toLowerCase())) as chat, idx}
+											<tr
+												class="bg-transparent {idx !== chats.length - 1 &&
+													'border-b'} dark:bg-gray-900 dark:border-gray-850 text-xs"
+											>
+												<td class="px-3 py-1 w-2/3">
+													<a href="/c/{chat.id}" target="_blank">
+														<div class=" underline line-clamp-1">
+															{chat.title}
+														</div>
+													</a>
+												</td>
+
+												<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
+													<div class="my-auto">
+														{dayjs(chat.created_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
 													</div>
-												</a>
-											</td>
-
-											<td class=" px-3 py-1 hidden md:flex h-[2.5rem]">
-												<div class="my-auto">
-													{dayjs(chat.created_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
-												</div>
-											</td>
-
-											<td class="px-3 py-1 text-right">
-												<div class="flex justify-end w-full">
-													<Tooltip content="Unarchive Chat">
-														<button
-															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
-															on:click={async () => {
-																unarchiveChatHandler(chat.id);
-															}}
-														>
-															<svg
-																xmlns="http://www.w3.org/2000/svg"
-																fill="none"
-																viewBox="0 0 24 24"
-																stroke-width="1.5"
-																stroke="currentColor"
-																class="size-4"
+												</td>
+
+												<td class="px-3 py-1 text-right">
+													<div class="flex justify-end w-full">
+														<Tooltip content="Unarchive Chat">
+															<button
+																class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
+																on:click={async () => {
+																	unarchiveChatHandler(chat.id);
+																}}
 															>
-																<path
-																	stroke-linecap="round"
-																	stroke-linejoin="round"
-																	d="M9 8.25H7.5a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 0 0 2.25 2.25h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25H15m0-3-3-3m0 0-3 3m3-3V15"
-																/>
-															</svg>
-														</button>
-													</Tooltip>
-
-													<Tooltip content="Delete Chat">
-														<button
-															class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
-															on:click={async () => {
-																deleteChatHandler(chat.id);
-															}}
-														>
-															<svg
-																xmlns="http://www.w3.org/2000/svg"
-																fill="none"
-																viewBox="0 0 24 24"
-																stroke-width="1.5"
-																stroke="currentColor"
-																class="w-4 h-4"
+																<svg
+																	xmlns="http://www.w3.org/2000/svg"
+																	fill="none"
+																	viewBox="0 0 24 24"
+																	stroke-width="1.5"
+																	stroke="currentColor"
+																	class="size-4"
+																>
+																	<path
+																		stroke-linecap="round"
+																		stroke-linejoin="round"
+																		d="M9 8.25H7.5a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 0 0 2.25 2.25h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25H15m0-3-3-3m0 0-3 3m3-3V15"
+																	/>
+																</svg>
+															</button>
+														</Tooltip>
+
+														<Tooltip content="Delete Chat">
+															<button
+																class="self-center w-fit text-sm px-2 py-2 hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
+																on:click={async () => {
+																	deleteChatHandler(chat.id);
+																}}
 															>
-																<path
-																	stroke-linecap="round"
-																	stroke-linejoin="round"
-																	d="m14.74 9-.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 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
-																/>
-															</svg>
-														</button>
-													</Tooltip>
-												</div>
-											</td>
-										</tr>
-									{/each}
-								</tbody>
-							</table>
+																<svg
+																	xmlns="http://www.w3.org/2000/svg"
+																	fill="none"
+																	viewBox="0 0 24 24"
+																	stroke-width="1.5"
+																	stroke="currentColor"
+																	class="w-4 h-4"
+																>
+																	<path
+																		stroke-linecap="round"
+																		stroke-linejoin="round"
+																		d="m14.74 9-.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 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
+																	/>
+																</svg>
+															</button>
+														</Tooltip>
+													</div>
+												</td>
+											</tr>
+										{/each}
+									</tbody>
+								</table>
+							</div>
 						</div>
 
 						<div class="flex flex-wrap text-sm font-medium gap-1.5 mt-2 m-1">