fix: sprechende Dateinamen fuer alle Exporte
Im Downloads-Ordner lagen "certain-finance-export_....json" und "certain-finance-backup_....json" nebeneinander, ohne dass man sah, welche Datei sich zurueckladen laesst. Alle Downloads heissen jetzt certain-finance_<art>_<datum>_<uhrzeit>.<endung>, wobei die Art es sagt: vollbackup, vollbackup-system, datenuebersicht, buchungen, datenbank. Das persoenliche Vollbackup traegt zusaetzlich den Benutzernamen. Den Namen vergibt jetzt allein der Server im Content-Disposition-Kopf; das Frontend liest ihn von dort. Vorher erfanden beide Seiten ihn getrennt und kamen auf unterschiedliche Ergebnisse (Bindestrich gegen Unterstrich, UTC gegen Ortszeit). Zeitstempel ist Ortszeit: wer abends um 20 Uhr exportiert, soll keine Datei von 18 Uhr finden. Passend dazu heisst der Knopf "Alle Daten (JSON)" nun "Datenuebersicht (JSON)", und der Hinweis darueber sagt ausdruecklich, dass sich diese Dateien nicht zurueckladen lassen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7fc8763d57
commit
e503baa8a6
+28
-9
@@ -85,8 +85,21 @@ function zeitstempel() {
|
||||
);
|
||||
}
|
||||
|
||||
/** Datei (mit Sitzungs-Cookie) laden und im Browser als Download anbieten. */
|
||||
export async function downloadFile(path, filename) {
|
||||
/** Dateiname aus dem Content-Disposition-Kopf, sonst der Rückfallwert. */
|
||||
function dateinameAusKopf(resp, rueckfall) {
|
||||
const kopf = resp.headers.get("content-disposition") || "";
|
||||
const treffer = /filename="([^"]+)"/.exec(kopf);
|
||||
return treffer ? treffer[1] : rueckfall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Datei (mit Sitzungs-Cookie) laden und im Browser als Download anbieten.
|
||||
*
|
||||
* Den Namen gibt der Server vor – sonst hiesse dieselbe Datei je nachdem, ob
|
||||
* man sie über die Oberfläche oder direkt über die API holt, anders. `rueckfall`
|
||||
* greift nur, wenn der Kopf fehlt.
|
||||
*/
|
||||
export async function downloadFile(path, rueckfall) {
|
||||
const resp = await fetch(`${API_BASE}${path}`, { credentials: "include" });
|
||||
if (!resp.ok) {
|
||||
throw new ApiError(`Download fehlgeschlagen (${resp.status})`, resp.status);
|
||||
@@ -95,7 +108,7 @@ export async function downloadFile(path, filename) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
link.download = dateinameAusKopf(resp, rueckfall);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
@@ -232,14 +245,20 @@ export const api = {
|
||||
documentPreview: (formData) => request("/documents/preview", { method: "POST", formData }),
|
||||
|
||||
// Backup & Export
|
||||
downloadDbBackup: () => downloadFile("/backup/db", `certain-finance-${zeitstempel()}.db`),
|
||||
exportTransactionsCsv: () => downloadFile("/export/transactions.csv", `transaktionen_${zeitstempel()}.csv`),
|
||||
exportTransactionsJson: () => downloadFile("/export/transactions.json", `transaktionen_${zeitstempel()}.json`),
|
||||
exportAllJson: () => downloadFile("/export/all.json", `certain-finance-export_${zeitstempel()}.json`),
|
||||
// Die Dateinamen kommen aus dem Content-Disposition-Kopf (backend/app/routers/
|
||||
// backup.py, _dateiname). Was hier steht, ist nur der Rückfall.
|
||||
downloadDbBackup: () =>
|
||||
downloadFile("/backup/db", `certain-finance_datenbank_${zeitstempel()}.db`),
|
||||
exportTransactionsCsv: () =>
|
||||
downloadFile("/export/transactions.csv", `certain-finance_buchungen_${zeitstempel()}.csv`),
|
||||
exportTransactionsJson: () =>
|
||||
downloadFile("/export/transactions.json", `certain-finance_buchungen_${zeitstempel()}.json`),
|
||||
exportAllJson: () =>
|
||||
downloadFile("/export/all.json", `certain-finance_datenuebersicht_${zeitstempel()}.json`),
|
||||
exportBackupJson: () =>
|
||||
downloadFile("/export/backup.json", `certain-finance-backup_${zeitstempel()}.json`),
|
||||
downloadFile("/export/backup.json", `certain-finance_vollbackup_${zeitstempel()}.json`),
|
||||
exportSystemBackupJson: () =>
|
||||
downloadFile("/export/system-backup.json", `certain-finance-system-backup_${zeitstempel()}.json`),
|
||||
downloadFile("/export/system-backup.json", `certain-finance_vollbackup-system_${zeitstempel()}.json`),
|
||||
restorePreview: (file) => {
|
||||
const fd = new FormData();
|
||||
fd.append("file", file);
|
||||
|
||||
@@ -80,10 +80,10 @@
|
||||
"languageDe": "Deutsch",
|
||||
"languageEn": "Englisch",
|
||||
"backup": "Backup & Export",
|
||||
"exportHint": "Exportiere deine eigenen Daten zum Archivieren oder Weiterverarbeiten.",
|
||||
"exportHint": "Zum Ansehen und Weiterverarbeiten, etwa in einer Tabellenkalkulation. Diese Dateien lassen sich nicht zurückladen.",
|
||||
"exportTxnCsv": "Buchungen (CSV)",
|
||||
"exportTxnJson": "Buchungen (JSON)",
|
||||
"exportAll": "Alle Daten (JSON)",
|
||||
"exportAll": "Datenübersicht (JSON)",
|
||||
"dbBackup": "Komplettes DB-Backup herunterladen",
|
||||
"dbBackupHint": "Vollständige Datenbank aller Nutzer (nur Admin) – zum Wiederherstellen sichern.",
|
||||
"keywordReview": "Schlagwörter prüfen",
|
||||
|
||||
@@ -80,10 +80,10 @@
|
||||
"languageDe": "German",
|
||||
"languageEn": "English",
|
||||
"backup": "Backup & export",
|
||||
"exportHint": "Export your own data for archiving or further processing.",
|
||||
"exportHint": "For reading and further processing, e.g. in a spreadsheet. These files cannot be restored.",
|
||||
"exportTxnCsv": "Transactions (CSV)",
|
||||
"exportTxnJson": "Transactions (JSON)",
|
||||
"exportAll": "All data (JSON)",
|
||||
"exportAll": "Data overview (JSON)",
|
||||
"dbBackup": "Download full DB backup",
|
||||
"dbBackupHint": "Complete database of all users (admin only) — keep it for restore.",
|
||||
"keywordReview": "Review keywords",
|
||||
|
||||
@@ -17,7 +17,7 @@ function codesSichern(codes, benutzer) {
|
||||
const url = URL.createObjectURL(new Blob([inhalt], { type: "text/plain;charset=utf-8" }));
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = `certain-finance-wiederherstellungscodes_${benutzer}.txt`;
|
||||
link.download = `certain-finance_wiederherstellungscodes_${benutzer}.txt`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
|
||||
Reference in New Issue
Block a user