Add Import/Restore functionality for JSON backups
Build and Publish Docker Image / build-and-push-image (push) Successful in 49s

This commit is contained in:
Zed
2026-07-07 15:19:28 +02:00
parent a2dba84fb0
commit 574e0c8004
+95 -15
View File
@@ -4,6 +4,7 @@ import {
Monitor, Monitor,
Trash2, Trash2,
Download, Download,
Upload,
FileSpreadsheet, FileSpreadsheet,
} from "lucide-react"; } from "lucide-react";
import { useAppStore } from "../stores/appStore"; import { useAppStore } from "../stores/appStore";
@@ -35,6 +36,69 @@ export default function Settings() {
} }
}; };
const handleImportJson = () => {
const input = document.createElement("input");
input.type = "file";
input.accept = "application/json";
input.onchange = async (e) => {
const file = (e.target as HTMLInputElement).files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = async (event) => {
try {
const content = event.target?.result as string;
const data = JSON.parse(content);
if (!data.sessions || !data.settings || !data.players) {
throw new Error("Fichier de sauvegarde invalide ou corrompu.");
}
if (
window.confirm(
"Attention : L'importation va écraser vos données actuelles. Voulez-vous continuer ?",
)
) {
await db.transaction(
"rw",
db.sessions,
db.settings,
db.players,
async () => {
await db.sessions.clear();
await db.settings.clear();
await db.players.clear();
if (data.sessions.length > 0)
await db.sessions.bulkAdd(data.sessions);
if (data.settings.length > 0)
await db.settings.bulkAdd(data.settings);
if (data.players.length > 0)
await db.players.bulkAdd(data.players);
},
);
// Reload settings to apply any imported theme
const newSettings = await db.settings.get(1);
if (newSettings && newSettings.theme) {
setTheme(newSettings.theme);
}
alert("Restauration réussie !");
window.location.reload();
}
} catch (error) {
console.error(error);
alert(
"Échec de l'importation : Le fichier n'est pas un backup Skori valide.",
);
}
};
reader.readAsText(file);
};
input.click();
};
const handleExportCSV = async () => { const handleExportCSV = async () => {
try { try {
const sessions = await db.sessions.toArray(); const sessions = await db.sessions.toArray();
@@ -162,23 +226,39 @@ export default function Settings() {
</div> </div>
</Button> </Button>
<Button <div className="grid grid-cols-2 gap-3 mt-3">
variant="outline" <Button
className="w-full justify-start h-auto py-4 px-6 border-0 shadow-md bg-background/90 backdrop-blur-md rounded-[1.5rem] hover:scale-[1.02] transition-transform" variant="outline"
onClick={handleExportJson} className="w-full justify-start h-auto py-3 px-4 border-0 shadow-md bg-background/90 backdrop-blur-md rounded-2xl hover:scale-[1.02] transition-transform"
> onClick={handleExportJson}
<div className="flex flex-col items-start text-left w-full"> >
<span className="flex items-center font-black text-lg"> <div className="flex flex-col items-center text-center w-full">
<div className="w-10 h-10 rounded-full bg-blue-500/20 flex items-center justify-center mr-4"> <div className="w-10 h-10 rounded-full bg-blue-500/20 flex items-center justify-center mb-2">
<Download className="w-5 h-5 text-blue-600" /> <Download className="w-5 h-5 text-blue-600" />
</div> </div>
Sauvegarde complète (.json) <span className="font-bold text-sm">Sauvegarder</span>
</span> <span className="text-[10px] text-muted-foreground mt-0.5">
<span className="text-sm text-muted-foreground ml-14"> Format .json
Copie brute de l'application </span>
</span> </div>
</div> </Button>
</Button>
<Button
variant="outline"
className="w-full justify-start h-auto py-3 px-4 border-0 shadow-md bg-background/90 backdrop-blur-md rounded-2xl hover:scale-[1.02] transition-transform"
onClick={handleImportJson}
>
<div className="flex flex-col items-center text-center w-full">
<div className="w-10 h-10 rounded-full bg-purple-500/20 flex items-center justify-center mb-2">
<Upload className="w-5 h-5 text-purple-600" />
</div>
<span className="font-bold text-sm">Restaurer</span>
<span className="text-[10px] text-muted-foreground mt-0.5">
À partir d'un .json
</span>
</div>
</Button>
</div>
<Button <Button
variant="outline" variant="outline"