feat(backup): "keep every backup" option — timestamped files per exit
Sub-option of "back up on every exit": when on, backup.Run/RunADIF stamp the filename with the time (opslog-YYYY-MM-DD-HHMMSS.db) so each run is a distinct file instead of overwriting the day's snapshot. Rotation still trims to the newest N (raise Rotation for a longer history). Threaded as a `unique` flag through runConfiguredBackup/backupLogADIF from BackupSettings.KeepAll (keyBackupKeepAll); UI sub-checkbox shown only when EveryExit is on.
This commit is contained in:
@@ -4368,13 +4368,26 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
/>
|
||||
<span>{t('bk.zip')}</span>
|
||||
</label>
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer pb-2">
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox
|
||||
checked={!!(backupCfg as any).every_exit}
|
||||
onCheckedChange={(c) => setBackupCfg((b) => ({ ...b, every_exit: !!c } as any))}
|
||||
/>
|
||||
<span>{t('bk.everyExit')}</span>
|
||||
</label>
|
||||
{!!(backupCfg as any).every_exit && (
|
||||
<label className="flex items-start gap-2 text-sm cursor-pointer pl-6 pb-2">
|
||||
<Checkbox
|
||||
className="mt-0.5"
|
||||
checked={!!(backupCfg as any).keep_all}
|
||||
onCheckedChange={(c) => setBackupCfg((b) => ({ ...b, keep_all: !!c } as any))}
|
||||
/>
|
||||
<span>
|
||||
{t('bk.keepAll')}
|
||||
<span className="block text-xs text-muted-foreground mt-0.5">{t('bk.keepAllHint')}</span>
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border/60 pt-3 flex items-center gap-3">
|
||||
|
||||
@@ -269,7 +269,7 @@ const en: Dict = {
|
||||
'bk.hintMysql': 'On close (once/day) OpsLog snapshots the local SQLite (config) AND exports the shared MySQL log to ADIF — opslog-log-<date>.adi — so your contacts are protected even though they live on the server. Rotation keeps the last N of each.',
|
||||
'bk.hint': 'OpsLog can copy the SQLite database to a folder of your choice when you close it, once per day. Rotation keeps the last N copies and deletes older ones.',
|
||||
'bk.auto': 'Automatic backup when closing OpsLog (max once per day)', 'bk.folder': 'Backup folder', 'bk.folderPh': 'leave empty for default', 'bk.browse': 'Browse…',
|
||||
'bk.effective': 'Effective folder:', 'bk.defaultUse': 'If empty, OpsLog uses the default:', 'bk.rotation': 'Rotation (copies to keep)', 'bk.zip': 'ZIP backup (smaller file)', 'bk.everyExit': 'Back up on every exit (not just once a day)',
|
||||
'bk.effective': 'Effective folder:', 'bk.defaultUse': 'If empty, OpsLog uses the default:', 'bk.rotation': 'Rotation (copies to keep)', 'bk.zip': 'ZIP backup (smaller file)', 'bk.everyExit': 'Back up on every exit (not just once a day)', 'bk.keepAll': 'Keep every backup (timestamped files)', 'bk.keepAllHint': 'Each exit writes a separate opslog-YYYY-MM-DD-HHMMSS.db instead of overwriting the day’s file. Rotation still keeps the newest N — raise it for more history.',
|
||||
'bk.lastRun': 'Last run:', 'bk.never': 'never', 'bk.backupNow': 'Back up now', 'bk.backingUp': 'Backing up…', 'bk.writtenTo': 'Backup written to',
|
||||
// Section hints (hardware/software panel headers)
|
||||
'autostart.hint': 'Launch external programs (WSJT-X, JTAlert, rotator control…) when OpsLog starts. A program already running is not started again. Saved per profile.',
|
||||
@@ -681,7 +681,7 @@ const fr: Dict = {
|
||||
'bk.hintMysql': "À la fermeture (1×/jour) OpsLog sauvegarde le SQLite local (config) ET exporte le log MySQL partagé en ADIF — opslog-log-<date>.adi — pour protéger tes contacts même s'ils sont sur le serveur. La rotation garde les N derniers de chaque.",
|
||||
'bk.hint': "OpsLog peut copier la base SQLite dans un dossier de ton choix à la fermeture, une fois par jour. La rotation garde les N dernières copies et supprime les plus anciennes.",
|
||||
'bk.auto': 'Sauvegarde auto à la fermeture d\'OpsLog (max 1×/jour)', 'bk.folder': 'Dossier de sauvegarde', 'bk.folderPh': 'vide = dossier par défaut', 'bk.browse': 'Parcourir…',
|
||||
'bk.effective': 'Dossier effectif :', 'bk.defaultUse': 'Si vide, OpsLog utilise le défaut :', 'bk.rotation': 'Rotation (copies à garder)', 'bk.zip': 'Sauvegarde ZIP (fichier plus petit)', 'bk.everyExit': 'Sauvegarder à chaque fermeture (pas une fois par jour)',
|
||||
'bk.effective': 'Dossier effectif :', 'bk.defaultUse': 'Si vide, OpsLog utilise le défaut :', 'bk.rotation': 'Rotation (copies à garder)', 'bk.zip': 'Sauvegarde ZIP (fichier plus petit)', 'bk.everyExit': 'Sauvegarder à chaque fermeture (pas une fois par jour)', 'bk.keepAll': 'Garder chaque sauvegarde (fichiers horodatés)', 'bk.keepAllHint': 'Chaque fermeture écrit un opslog-AAAA-MM-JJ-HHMMSS.db distinct au lieu d’écraser le fichier du jour. La rotation garde les N plus récents — augmente-la pour plus d’historique.',
|
||||
'bk.lastRun': 'Dernière exécution :', 'bk.never': 'jamais', 'bk.backupNow': 'Sauvegarder maintenant', 'bk.backingUp': 'Sauvegarde…', 'bk.writtenTo': 'Sauvegarde écrite dans',
|
||||
'autostart.hint': "Lance des programmes externes (WSJT-X, JTAlert, contrôle rotator…) au démarrage d'OpsLog. Un programme déjà lancé n'est pas relancé. Enregistré par profil.",
|
||||
'cat.hint': "Lit la fréquence / bande / mode du poste et les injecte dans le bandeau de saisie en temps réel. Utilise OmniRig (gratuit, tout poste) ou — pour FlexRadio — l'API native SmartSDR (sans OmniRig, temps réel, sans le bug du mode au 2ᵉ clic).",
|
||||
|
||||
Reference in New Issue
Block a user