import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core'; import { Api } from '../../core/api'; import { Feedback } from '../../core/feedback'; import { errorMessage, formatBytes, formatDateTime, formatRelative } from '../../core/format'; import type { BackupFile, BackupSchedule } from '../../core/models'; import { Icon } from '../../shared/icon'; import { JobConsole } from '../../shared/job-console'; @Component({ selector: 'app-backups', imports: [Icon, JobConsole], template: `
@if (error()) { }

Les sauvegardes restent sur le VPS ({{ dir() }}). Télécharge-les régulièrement : si le serveur est perdu, elles le sont aussi.

@if (jobId(); as id) { }
Sauvegarde automatique {{ schedule()?.dailyAt ? 'Chaque jour à ' + schedule()!.dailyAt : 'Désactivée' }} Variable BACKUP_DAILY_AT
Conservation {{ schedule()?.keep ?? '–' }} de chaque type Les plus anciennes sont supprimées
Dernière sauvegarde {{ files()[0] ? relative(files()[0].createdAt) : 'Aucune' }} {{ files()[0] ? dateTime(files()[0].createdAt) : '' }}
@for (file of files(); track file.name) { } @empty { }
Fichier Contenu Taille Date Actions
{{ file.name }} {{ file.type === 'db' ? 'Bases de données' : 'Dossier /srv' }} {{ bytes(file.size) }} {{ dateTime(file.createdAt) }} Télécharger
Aucune sauvegarde pour l’instant.
`, styles: ` .tile-value.small { font-size: 18px; } `, changeDetection: ChangeDetectionStrategy.OnPush, }) export class BackupsPage { protected api = inject(Api); private feedback = inject(Feedback); protected readonly files = signal([]); protected readonly schedule = signal(null); protected readonly dir = signal(''); protected readonly error = signal(null); protected readonly starting = signal(false); protected readonly jobId = signal(null); protected readonly bytes = formatBytes; protected readonly dateTime = formatDateTime; protected readonly relative = formatRelative; constructor() { this.load(); } async load() { try { const result = await this.api.backups(); this.files.set(result.files); this.schedule.set(result.schedule); this.dir.set(result.dir); this.error.set(null); } catch (error) { this.error.set(errorMessage(error)); } } protected async run() { this.starting.set(true); try { const { jobId } = await this.api.runBackup(); this.jobId.set(jobId); } catch (error) { this.feedback.error(errorMessage(error)); } finally { this.starting.set(false); } } protected async remove(file: BackupFile) { const ok = await this.feedback.confirm({ title: 'Supprimer cette sauvegarde ?', message: `${file.name} sera supprimé du serveur. C’est définitif.`, confirmLabel: 'Supprimer', danger: true, }); if (!ok) return; try { await this.api.deleteBackup(file.name); this.feedback.success('Sauvegarde supprimée.'); await this.load(); } catch (error) { this.feedback.error(errorMessage(error)); } } }