feat(backup): fold .picpeak restore into the Restore wizard's Upload source

Removes the redundant standalone .picpeak card. The wizard's 'Upload
Backup' source now splits into two kinds: '.picpeak backup' (the working
portable restore — renders the upload + destructive-confirm flow inline)
and 'Manifest + files' (legacy, still 'Manifest Upload functionality
coming soon'). en + de strings added.
This commit is contained in:
Luca
2026-07-02 21:38:48 +02:00
parent d4b143f313
commit 86324e7da7
4 changed files with 63 additions and 12 deletions
@@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { PicpeakRestoreCard } from './PicpeakBackupCard';
import { import {
RefreshCw, RefreshCw,
AlertTriangle, AlertTriangle,
@@ -283,14 +284,49 @@ export const RestoreWizard = ({ onVerifyIntegrity } = {}) => {
)} )}
{restoreData.source === 'upload' && ( {restoreData.source === 'upload' && (
<div className="space-y-4">
{/* Two upload kinds: the working portable .picpeak restore, and the
legacy manifest+files upload (still a stub). */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<button
onClick={() => setRestoreData(prev => ({ ...prev, uploadType: 'picpeak' }))}
className={`p-6 rounded-lg border-2 transition-all ${
restoreData.uploadType === 'picpeak'
? 'border-primary bg-accent-dark/15'
: 'border-neutral-200 dark:border-neutral-600 hover:border-neutral-300 dark:hover:border-neutral-500'
}`}
>
<FileArchive className={`h-10 w-10 mb-2 mx-auto ${restoreData.uploadType === 'picpeak' ? 'text-primary' : 'text-neutral-400'}`} />
<h4 className="font-medium text-neutral-900 dark:text-neutral-100">{t('backup.restore.source.upload.picpeak.name', '.picpeak backup')}</h4>
<p className="text-xs text-neutral-500 dark:text-neutral-400 mt-1">{t('backup.restore.source.upload.picpeak.description', 'Portable full backup — restores everything (full override, keeps your current account).')}</p>
</button>
<button
onClick={() => setRestoreData(prev => ({ ...prev, uploadType: 'manifest' }))}
className={`p-6 rounded-lg border-2 transition-all ${
restoreData.uploadType === 'manifest'
? 'border-primary bg-accent-dark/15'
: 'border-neutral-200 dark:border-neutral-600 hover:border-neutral-300 dark:hover:border-neutral-500'
}`}
>
<Upload className={`h-10 w-10 mb-2 mx-auto ${restoreData.uploadType === 'manifest' ? 'text-primary' : 'text-neutral-400'}`} />
<h4 className="font-medium text-neutral-900 dark:text-neutral-100">{t('backup.restore.source.upload.manifest.name', 'Manifest + files')}</h4>
<p className="text-xs text-neutral-500 dark:text-neutral-400 mt-1">{t('backup.restore.source.upload.manifest.description', 'Upload a manifest and its backup files (legacy format).')}</p>
</button>
</div>
{restoreData.uploadType === 'picpeak' && <PicpeakRestoreCard />}
{restoreData.uploadType === 'manifest' && (
<Card className="p-4"> <Card className="p-4">
<div className="text-center py-8"> <div className="text-center py-8">
<Upload className="h-12 w-12 mx-auto mb-3 text-neutral-400" /> <Upload className="h-12 w-12 mx-auto mb-3 text-neutral-400" />
<p className="text-sm text-neutral-600 dark:text-neutral-400">{t('backup.restore.source.upload.comingSoon')}</p> <p className="text-sm text-neutral-600 dark:text-neutral-400">{t('backup.restore.source.upload.manifestComingSoon', 'Manifest Upload functionality coming soon')}</p>
</div> </div>
</Card> </Card>
)} )}
</div> </div>
)}
</div>
); );
const renderBackupSelection = () => ( const renderBackupSelection = () => (
+10 -1
View File
@@ -634,7 +634,16 @@
"upload": { "upload": {
"name": "Backup hochladen", "name": "Backup hochladen",
"description": "Eine Backup-Datei hochladen", "description": "Eine Backup-Datei hochladen",
"comingSoon": "Upload-Funktion kommt bald" "comingSoon": "Upload-Funktion kommt bald",
"manifestComingSoon": "Manifest-Upload-Funktion kommt bald",
"picpeak": {
"name": ".picpeak-Backup",
"description": "Portables Voll-Backup — stellt alles wieder her (vollständige Überschreibung, Ihr aktuelles Konto bleibt erhalten)."
},
"manifest": {
"name": "Manifest + Dateien",
"description": "Ein Manifest und die zugehörigen Backup-Dateien hochladen (Legacy-Format)."
}
}, },
"configuration": { "configuration": {
"s3": "S3-Konfiguration", "s3": "S3-Konfiguration",
+10 -1
View File
@@ -3022,7 +3022,16 @@
"upload": { "upload": {
"name": "Upload Backup", "name": "Upload Backup",
"description": "Upload a backup file", "description": "Upload a backup file",
"comingSoon": "Upload functionality coming soon" "comingSoon": "Upload functionality coming soon",
"manifestComingSoon": "Manifest Upload functionality coming soon",
"picpeak": {
"name": ".picpeak backup",
"description": "Portable full backup — restores everything (full override, keeps your current account)."
},
"manifest": {
"name": "Manifest + files",
"description": "Upload a manifest and its backup files (legacy format)."
}
}, },
"configuration": { "configuration": {
"s3": "S3 Configuration", "s3": "S3 Configuration",
@@ -23,7 +23,7 @@ import { BackupDashboard } from '../../components/admin/BackupDashboard';
import { BackupConfiguration } from '../../components/admin/BackupConfiguration'; import { BackupConfiguration } from '../../components/admin/BackupConfiguration';
import { BackupHistory } from '../../components/admin/BackupHistory'; import { BackupHistory } from '../../components/admin/BackupHistory';
import { RestoreWizard } from '../../components/admin/RestoreWizard'; import { RestoreWizard } from '../../components/admin/RestoreWizard';
import { PicpeakExportCard, PicpeakRestoreCard } from '../../components/admin/PicpeakBackupCard'; import { PicpeakExportCard } from '../../components/admin/PicpeakBackupCard';
import { BackupIntegrityCard } from '../../components/admin/BackupIntegrityCard'; import { BackupIntegrityCard } from '../../components/admin/BackupIntegrityCard';
import { BackupCoverageCard } from '../../components/admin/BackupCoverageCard'; import { BackupCoverageCard } from '../../components/admin/BackupCoverageCard';
import { api } from '../../config/api'; import { api } from '../../config/api';
@@ -229,10 +229,7 @@ export const BackupManagement: React.FC = () => {
)} )}
{activeTab === 'restore' && ( {activeTab === 'restore' && (
<div className="space-y-6">
<PicpeakRestoreCard />
<RestoreWizard onVerifyIntegrity={() => setActiveTab('integrity')} /> <RestoreWizard onVerifyIntegrity={() => setActiveTab('integrity')} />
</div>
)} )}
{activeTab === 'integrity' && ( {activeTab === 'integrity' && (