Update Database.svelte

This commit is contained in:
Classic298 2025-08-22 16:16:31 +02:00 committed by GitHub
parent 544f8b72dc
commit 7abcc7bc59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -17,6 +17,10 @@
export let saveHandler: Function; export let saveHandler: Function;
let showPruneDataDialog = false; let showPruneDataDialog = false;
let showPreviewResults = false;
let previewResults = null;
let lastPruneSettings = null;
const exportAllUserChats = async () => { const exportAllUserChats = async () => {
let blob = new Blob([JSON.stringify(await getAllUserChats(localStorage.token))], { let blob = new Blob([JSON.stringify(await getAllUserChats(localStorage.token))], {
type: 'application/json' type: 'application/json'
@ -24,48 +28,70 @@
saveAs(blob, `all-chats-export-${Date.now()}.json`); saveAs(blob, `all-chats-export-${Date.now()}.json`);
}; };
const handlePruneDataConfirm = async (event) => { const handlePruneDataPreview = async (event) => {
const { const settings = event.detail;
days, lastPruneSettings = settings;
exempt_archived_chats,
exempt_chats_in_folders,
delete_orphaned_chats,
delete_orphaned_tools,
delete_orphaned_functions,
delete_orphaned_prompts,
delete_orphaned_knowledge_bases,
delete_orphaned_models,
delete_orphaned_notes,
delete_orphaned_folders,
audio_cache_max_age_days,
delete_inactive_users_days,
exempt_admin_users,
exempt_pending_users
} = event.detail;
const res = await pruneData( const res = await pruneData(
localStorage.token, localStorage.token,
days, settings.days,
exempt_archived_chats, settings.exempt_archived_chats,
exempt_chats_in_folders, settings.exempt_chats_in_folders,
delete_orphaned_chats, settings.delete_orphaned_chats,
delete_orphaned_tools, settings.delete_orphaned_tools,
delete_orphaned_functions, settings.delete_orphaned_functions,
delete_orphaned_prompts, settings.delete_orphaned_prompts,
delete_orphaned_knowledge_bases, settings.delete_orphaned_knowledge_bases,
delete_orphaned_models, settings.delete_orphaned_models,
delete_orphaned_notes, settings.delete_orphaned_notes,
delete_orphaned_folders, settings.delete_orphaned_folders,
audio_cache_max_age_days, settings.audio_cache_max_age_days,
delete_inactive_users_days, settings.delete_inactive_users_days,
exempt_admin_users, settings.exempt_admin_users,
exempt_pending_users settings.exempt_pending_users,
true // dry_run = true for preview
).catch((error) => { ).catch((error) => {
toast.error(`${error}`); toast.error(`${error}`);
return null; return null;
}); });
if (res) {
previewResults = res;
showPreviewResults = true;
}
};
const handleConfirmPrune = async () => {
if (!lastPruneSettings) return;
const res = await pruneData(
localStorage.token,
lastPruneSettings.days,
lastPruneSettings.exempt_archived_chats,
lastPruneSettings.exempt_chats_in_folders,
lastPruneSettings.delete_orphaned_chats,
lastPruneSettings.delete_orphaned_tools,
lastPruneSettings.delete_orphaned_functions,
lastPruneSettings.delete_orphaned_prompts,
lastPruneSettings.delete_orphaned_knowledge_bases,
lastPruneSettings.delete_orphaned_models,
lastPruneSettings.delete_orphaned_notes,
lastPruneSettings.delete_orphaned_folders,
lastPruneSettings.audio_cache_max_age_days,
lastPruneSettings.delete_inactive_users_days,
lastPruneSettings.exempt_admin_users,
lastPruneSettings.exempt_pending_users,
false // dry_run = false for actual pruning
).catch((error) => {
toast.error(`${error}`);
return null;
});
if (res) { if (res) {
toast.success('Data pruned successfully'); toast.success('Data pruned successfully');
showPreviewResults = false;
previewResults = null;
lastPruneSettings = null;
} }
}; };
@ -97,7 +123,151 @@
}); });
</script> </script>
<PruneDataDialog bind:show={showPruneDataDialog} on:confirm={handlePruneDataConfirm} /> <!-- Preview Results Modal -->
{#if showPreviewResults && previewResults}
<div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 max-w-2xl w-full mx-4 max-h-[80vh] overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{$i18n.t('Pruning Preview Results')}
</h3>
<button
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
on:click={() => (showPreviewResults = false)}
>
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="space-y-4">
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
<h4 class="text-sm font-medium text-blue-800 dark:text-blue-200 mb-2">
{$i18n.t('The following items would be deleted:')}
</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 text-sm">
{#if previewResults.inactive_users > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Inactive users')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.inactive_users}</span>
</div>
{/if}
{#if previewResults.old_chats > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Old chats')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.old_chats}</span>
</div>
{/if}
{#if previewResults.orphaned_chats > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned chats')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_chats}</span>
</div>
{/if}
{#if previewResults.orphaned_files > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned files')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_files}</span>
</div>
{/if}
{#if previewResults.orphaned_tools > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned tools')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_tools}</span>
</div>
{/if}
{#if previewResults.orphaned_functions > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned functions')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_functions}</span>
</div>
{/if}
{#if previewResults.orphaned_prompts > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned prompts')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_prompts}</span>
</div>
{/if}
{#if previewResults.orphaned_knowledge_bases > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned knowledge bases')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_knowledge_bases}</span>
</div>
{/if}
{#if previewResults.orphaned_models > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned models')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_models}</span>
</div>
{/if}
{#if previewResults.orphaned_notes > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned notes')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_notes}</span>
</div>
{/if}
{#if previewResults.orphaned_folders > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned folders')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_folders}</span>
</div>
{/if}
{#if previewResults.orphaned_uploads > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned upload files')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_uploads}</span>
</div>
{/if}
{#if previewResults.orphaned_vector_collections > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Orphaned vector collections')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.orphaned_vector_collections}</span>
</div>
{/if}
{#if previewResults.audio_cache_files > 0}
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">{$i18n.t('Audio cache files')}:</span>
<span class="font-medium text-red-600 dark:text-red-400">{previewResults.audio_cache_files}</span>
</div>
{/if}
</div>
{#if Object.values(previewResults).every(count => count === 0)}
<div class="text-center py-4">
<div class="text-green-600 dark:text-green-400 font-medium">
{$i18n.t('No items would be deleted with current settings')}
</div>
<div class="text-sm text-gray-500 dark:text-gray-400 mt-1">
{$i18n.t('Your system is already clean or no cleanup options are enabled')}
</div>
</div>
{/if}
</div>
<!-- Action buttons -->
<div class="flex justify-end gap-3 pt-4">
<button
class="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700 transition-colors"
on:click={() => (showPreviewResults = false)}
>
{$i18n.t('Cancel')}
</button>
{#if !Object.values(previewResults).every(count => count === 0)}
<button
class="px-4 py-2 text-sm font-medium text-white bg-red-600 border border-transparent rounded-lg hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 transition-colors"
on:click={handleConfirmPrune}
>
{$i18n.t('Prune Data')}
</button>
{/if}
</div>
</div>
</div>
</div>
{/if}
<PruneDataDialog bind:show={showPruneDataDialog} on:preview={handlePruneDataPreview} />
<form <form
class="flex flex-col h-full justify-between space-y-3 text-sm" class="flex flex-col h-full justify-between space-y-3 text-sm"
on:submit|preventDefault={async () => { on:submit|preventDefault={async () => {