Move viewer export/import into a dedicated Backup tab.

Keeps game save import in the sidebar while grouping viewer database
backup actions with their explanation in the main navigation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-20 10:03:04 +02:00
parent 3314de829d
commit dc42727f34
5 changed files with 48 additions and 39 deletions
+3
View File
@@ -113,6 +113,8 @@ function applyStaticI18n() {
document.querySelectorAll("[data-i18n]").forEach((el) => {
el.textContent = t(el.dataset.i18n);
});
const exportEl = document.getElementById("export-viewer");
if (exportEl) exportEl.title = t("viewerDb.exportHint");
}
function setupLanguage() {
@@ -146,6 +148,7 @@ function activateTab(tab) {
document.getElementById(`tab-${tab}`).classList.add("active");
if (tab === "history") loadHistoryTab();
if (tab === "goals") trackEvent("Goals Tab");
if (tab === "backup") trackEvent("Backup Tab");
}
function setupNav() {
+3 -1
View File
@@ -12,7 +12,8 @@
"equipment": "Ausrüstung",
"quests": "Quests",
"combat": "Kampf",
"history": "Verlauf"
"history": "Verlauf",
"backup": "Backup"
},
"settings": {
"language": "Sprache",
@@ -229,6 +230,7 @@
"title": "Viewer-Backup",
"helpTitle": "Was ist das?",
"helpBody": "Der Viewer speichert importierte Spiel-Backups, Verlaufsdiagramme und Ziele in einer SQLite-Datenbank auf dem Server. Export lädt diese Datenbank als Backup herunter. Import stellt sie wieder her und ersetzt alle aktuellen Viewer-Daten. Das ist nicht dasselbe wie ein Spiel-Backup (.json) importieren.",
"gameBackupNote": "Um einen neuen Spielstand hinzuzufügen, nutze in der Sidebar „Spiel-Backup importieren“.",
"exportHint": "SQLite-Datenbank mit allen Snapshots, Verläufen und Zielen herunterladen",
"importConfirm": "Alle aktuellen Viewer-Daten (Snapshots, Verlauf, Ziele) werden durch die importierte .db-Datei ersetzt. Fortfahren?",
"importSuccess": "Viewer wiederhergestellt: {snapshots} Snapshot(s), {goals} Ziel(e).",
+3 -1
View File
@@ -12,7 +12,8 @@
"equipment": "Equipment",
"quests": "Quests",
"combat": "Combat",
"history": "History"
"history": "History",
"backup": "Backup"
},
"settings": {
"language": "Language",
@@ -229,6 +230,7 @@
"title": "Viewer backup",
"helpTitle": "What is this?",
"helpBody": "The viewer stores imported game backups, history charts, and goals in a SQLite database on the server. Export downloads that database as a backup. Import restores it and replaces all current viewer data. This is not the same as importing a game save (.json).",
"gameBackupNote": "To add a new game save snapshot, use Import game backup in the sidebar.",
"exportHint": "Download the SQLite database with all snapshots, history, and goals",
"importConfirm": "All current viewer data (snapshots, history, goals) will be replaced by the imported .db file. Continue?",
"importSuccess": "Viewer restored: {snapshots} snapshot(s), {goals} goal(s).",
+24 -25
View File
@@ -1028,35 +1028,34 @@ tr.has-goal td:first-child { font-weight: 600; }
text-decoration: none;
}
.sidebar-backup-block {
margin-top: 4px;
padding-top: 14px;
border-top: 1px solid var(--border);
.backup-tab-card {
max-width: 560px;
}
.backup-tab-card h3 {
margin: 0 0 12px;
font-size: 1.1rem;
}
.backup-tab-lead,
.backup-tab-note {
margin: 0 0 12px;
font-size: 0.9rem;
color: var(--text-muted);
line-height: 1.5;
}
.backup-tab-note {
padding: 10px 12px;
border-radius: 8px;
background: var(--bg-hover);
border: 1px solid var(--border);
}
.backup-tab-actions {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 16px;
}
.sidebar-backup-label {
margin: 0;
font-size: 0.72rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--text-muted);
}
.sidebar-backup-help {
margin-top: 2px;
font-size: 0.78rem;
color: var(--text-muted);
}
.sidebar-backup-help summary {
cursor: pointer;
color: var(--accent);
font-weight: 600;
}
.sidebar-backup-help p {
margin: 8px 0 0;
line-height: 1.45;
.backup-tab-actions .upload-btn {
width: 100%;
}
.goal-modal {