Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified tools/server/public/index.html.gz
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<script lang="ts">
import { Download, Upload } from '@lucide/svelte';
import { Download, Upload, Trash2 } from '@lucide/svelte';
import { Button } from '$lib/components/ui/button';
import { DialogConversationSelection } from '$lib/components/app';
import { createMessageCountMap } from '$lib/utils';
import { conversationsStore, conversations } from '$lib/stores/conversations.svelte';
import { toast } from 'svelte-sonner';
import DialogConfirmation from '$lib/components/app/dialogs/DialogConfirmation.svelte';

let exportedConversations = $state<DatabaseConversation[]>([]);
let importedConversations = $state<DatabaseConversation[]>([]);
Expand All @@ -18,11 +20,14 @@
[]
);

// Delete functionality state
let showDeleteDialog = $state(false);

async function handleExportClick() {
try {
const allConversations = conversations();
if (allConversations.length === 0) {
alert('No conversations to export');
toast.info('No conversations to export');
return;
}

Expand Down Expand Up @@ -145,6 +150,36 @@
alert('Failed to import conversations. Please check the file format.');
}
}

async function handleDeleteAllClick() {
try {
const allConversations = conversations();

if (allConversations.length === 0) {
toast.info('No conversations to delete');
return;
}

showDeleteDialog = true;
} catch (err) {
console.error('Failed to load conversations for deletion:', err);
toast.error('Failed to load conversations');
}
}

async function handleDeleteAllConfirm() {
try {
await conversationsStore.deleteAll();

showDeleteDialog = false;
} catch (err) {
console.error('Failed to delete conversations:', err);
}
}

function handleDeleteAllCancel() {
showDeleteDialog = false;
}
</script>

<div class="space-y-6">
Expand Down Expand Up @@ -229,6 +264,25 @@
</div>
{/if}
</div>

<div class="grid border-t border-border/30 pt-4">
<h4 class="mb-2 text-sm font-medium text-destructive">Delete All Conversations</h4>

<p class="mb-4 text-sm text-muted-foreground">
Permanently delete all conversations and their messages. This action cannot be undone.
Consider exporting your conversations first if you want to keep a backup.
</p>

<Button
class="text-destructive-foreground w-full justify-start justify-self-start bg-destructive hover:bg-destructive/80 md:w-auto"
onclick={handleDeleteAllClick}
variant="destructive"
>
<Trash2 class="mr-2 h-4 w-4" />

Delete all conversations
</Button>
</div>
</div>
</div>

Expand All @@ -249,3 +303,15 @@
onCancel={() => (showImportDialog = false)}
onConfirm={handleImportConfirm}
/>

<DialogConfirmation
bind:open={showDeleteDialog}
title="Delete all conversations"
description="Are you sure you want to delete all conversations? This action cannot be undone and will permanently remove all your conversations and messages."
confirmText="Delete All"
cancelText="Cancel"
variant="destructive"
icon={Trash2}
onConfirm={handleDeleteAllConfirm}
onCancel={handleDeleteAllCancel}
/>
26 changes: 24 additions & 2 deletions tools/server/webui/src/lib/stores/conversations.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,37 @@ class ConversationsStore {
this.conversations = this.conversations.filter((c) => c.id !== convId);

if (this.activeConversation?.id === convId) {
this.activeConversation = null;
this.activeMessages = [];
this.clearActiveConversation();
await goto(`?new_chat=true#/`);
}
} catch (error) {
console.error('Failed to delete conversation:', error);
}
}

/**
* Deletes all conversations and their messages
*/
async deleteAll(): Promise<void> {
try {
const allConversations = await DatabaseService.getAllConversations();

for (const conv of allConversations) {
await DatabaseService.deleteConversation(conv.id);
}

this.clearActiveConversation();
this.conversations = [];

toast.success('All conversations deleted');

await goto(`?new_chat=true#/`);
} catch (error) {
console.error('Failed to delete all conversations:', error);
toast.error('Failed to delete conversations');
}
}

// ─────────────────────────────────────────────────────────────────────────────
// Import/Export
// ─────────────────────────────────────────────────────────────────────────────
Expand Down