diff --git a/web/admin.html b/web/admin.html
index 2f9fd1b..a2957b0 100644
--- a/web/admin.html
+++ b/web/admin.html
@@ -180,6 +180,14 @@
class="px-4 py-2 bg-teal-600 hover:bg-teal-700 text-white text-sm font-medium rounded-lg transition-colors">
🔧 Maintenance
+
+
@@ -297,6 +305,40 @@
+
+
@@ -535,6 +577,8 @@
document.getElementById("statsBtn").addEventListener("click", () => this.showStats());
document.getElementById("diagnosticsBtn").addEventListener("click", () => this.showDiagnosticsModal());
document.getElementById("maintenanceBtn").addEventListener("click", () => this.showMaintenanceModal());
+ document.getElementById("backupBtn").addEventListener("click", () => this.backupDatabase());
+ document.getElementById("restoreBtn").addEventListener("click", () => this.showRestoreModal());
// Modals
this.bindModalEvents();
@@ -558,6 +602,10 @@
document.getElementById("confirmBulkCategory").addEventListener("click", () => this.confirmBulkCategory());
document.getElementById("cancelBulkCategory").addEventListener("click", () => this.hideModal("bulkCategoryModal"));
+ // Restore modal
+ document.getElementById("confirmRestore").addEventListener("click", () => this.confirmRestore());
+ document.getElementById("cancelRestore").addEventListener("click", () => this.hideModal("restoreModal"));
+
// Diagnostics modal
document.getElementById("runDiagnosticsBtn").addEventListener("click", () => this.runDiagnostics());
document.getElementById("testImageLinkBtn").addEventListener("click", () => this.testImageLink());
@@ -1755,6 +1803,118 @@
}
}
+ // Database backup and restore functionality
+ async backupDatabase() {
+ try {
+ const response = await fetch('/prompt_manager/backup');
+
+ if (response.ok) {
+ // Get the filename from the Content-Disposition header
+ const contentDisposition = response.headers.get('Content-Disposition');
+ let filename = 'prompts_backup.db';
+
+ if (contentDisposition) {
+ const filenameMatch = contentDisposition.match(/filename="(.+)"/);
+ if (filenameMatch) {
+ filename = filenameMatch[1];
+ }
+ }
+
+ // Create blob and download
+ const blob = await response.blob();
+ const url = window.URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = filename;
+ document.body.appendChild(a);
+ a.click();
+ window.URL.revokeObjectURL(url);
+ document.body.removeChild(a);
+
+ this.showNotification('💾 Database backup downloaded successfully!', 'success');
+ } else {
+ const errorData = await response.json();
+ throw new Error(errorData.error || 'Backup failed');
+ }
+ } catch (error) {
+ console.error('Backup error:', error);
+ this.showNotification(`❌ Backup failed: ${error.message}`, 'error');
+ }
+ }
+
+ showRestoreModal() {
+ // Clear previous file selection
+ document.getElementById('restoreFileInput').value = '';
+ this.showModal('restoreModal');
+ }
+
+ async confirmRestore() {
+ const fileInput = document.getElementById('restoreFileInput');
+ const file = fileInput.files[0];
+
+ if (!file) {
+ this.showNotification('Please select a database file to restore', 'warning');
+ return;
+ }
+
+ if (!file.name.endsWith('.db')) {
+ this.showNotification('Please select a valid .db file', 'warning');
+ return;
+ }
+
+ // Show confirmation
+ const confirmed = confirm(
+ `Are you sure you want to restore from "${file.name}"?\n\n` +
+ 'This will replace your current database. A backup will be created automatically.\n\n' +
+ 'This action cannot be undone.'
+ );
+
+ if (!confirmed) {
+ return;
+ }
+
+ try {
+ // Disable the restore button and show loading
+ const confirmBtn = document.getElementById('confirmRestore');
+ confirmBtn.disabled = true;
+ confirmBtn.innerHTML = '🔄 Restoring...';
+
+ // Create FormData for file upload
+ const formData = new FormData();
+ formData.append('database_file', file);
+
+ const response = await fetch('/prompt_manager/restore', {
+ method: 'POST',
+ body: formData
+ });
+
+ const data = await response.json();
+
+ if (response.ok && data.success) {
+ this.showNotification(
+ `✅ Database restored successfully! Found ${data.prompt_count} prompts.`,
+ 'success'
+ );
+ this.hideModal('restoreModal');
+
+ // Refresh the interface to show new data
+ setTimeout(() => {
+ window.location.reload();
+ }, 2000);
+ } else {
+ throw new Error(data.error || 'Restore failed');
+ }
+ } catch (error) {
+ console.error('Restore error:', error);
+ this.showNotification(`❌ Restore failed: ${error.message}`, 'error');
+ } finally {
+ // Re-enable the restore button
+ const confirmBtn = document.getElementById('confirmRestore');
+ confirmBtn.disabled = false;
+ confirmBtn.innerHTML = 'Restore Database';
+ }
+ }
+
// Copy prompt to clipboard functionality
async copyPromptToClipboard(promptId) {
// Find the prompt text from the prompts array