`;
GoingsOn.ui.openModal('Manage Backups', content);
}
/**
* Restore data from a backup file after confirmation.
* @param {string} filePath - Absolute path to the backup file
*/
async function restoreFromBackup(filePath) {
const confirmed = await GoingsOn.ui.confirmDelete(
'Restore from Backup',
'This will import data from the backup. Existing items with the same IDs will be skipped. Do you want to continue?'
);
if (!confirmed) return;
try {
const result = await GoingsOn.api.export.restoreBackup(filePath, { replaceAll: false });
const total = result.projectsRestored + result.tasksRestored + result.eventsRestored + result.emailsRestored;
GoingsOn.ui.showToast(`Restored ${total} items from backup`);
GoingsOn.ui.closeModal();
// Reload data
GoingsOn.projects.load();
GoingsOn.tasks.load();
GoingsOn.events.load();
GoingsOn.emails.load();
} catch (err) {
GoingsOn.ui.showToast('Restore failed: ' + GoingsOn.utils.getErrorMessage(err), 'error');
}
}
/**
* Delete a backup file after confirmation.
* @param {string} filePath - Absolute path to the backup file
*/
async function deleteBackup(filePath) {
const confirmed = await GoingsOn.ui.confirmDelete(
'Delete Backup',
'Are you sure you want to delete this backup? This cannot be undone.'
);
if (!confirmed) return;
try {
await GoingsOn.api.export.deleteBackup(filePath);
GoingsOn.ui.showToast('Backup deleted');
// Refresh the backups list
openBackupsModal();
} catch (err) {
GoingsOn.ui.showToast('Delete failed: ' + GoingsOn.utils.getErrorMessage(err), 'error');
}
}
/**
* Format a byte count as a human-readable size string.
* @param {number} bytes - Number of bytes
* @returns {string} Formatted string (e.g., "1.5 MB", "256 KB")
*/
function formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}
// ============ Backup Settings ============
/**
* Opens the automatic backup settings modal.
*/
async function openBackupSettingsModal() {
let settings = null;
try {
settings = await GoingsOn.api.export.getBackupSettings();
} catch (err) {
console.error('Failed to load backup settings:', err);
settings = {
autoBackupEnabled: true,
backupFrequencyMinutes: 15,
maxBackupsToKeep: 1,
lastBackupAt: null,
};
}
const lastBackupText = settings.lastBackupAt
? `Last backup: ${new Date(settings.lastBackupAt).toLocaleString()}`
: 'No backups yet';
const frequencyOptions = [
{ value: 15, label: 'Every 15 minutes (Recommended)' },
{ value: 30, label: 'Every 30 minutes' },
{ value: 60, label: 'Every hour' },
{ value: 360, label: 'Every 6 hours' },
{ value: 1440, label: 'Daily' },
];
const retentionOptions = [
{ value: 1, label: 'Keep 1 backup (Recommended)' },
{ value: 3, label: 'Keep 3 backups' },
{ value: 7, label: 'Keep 7 backups' },
{ value: 14, label: 'Keep 14 backups' },
{ value: 0, label: 'Keep all backups' },
];
const ff = GoingsOn.ui.renderFormField;
const content = `
Automatic backups protect your data by creating compressed snapshots on a schedule.
Once cloud sync is configured, backups will also sync to your cloud provider.