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 {
+15 -12
View File
@@ -29,6 +29,7 @@
<button class="nav-btn" data-tab="quests" data-i18n="nav.quests">Quests</button>
<button class="nav-btn" data-tab="combat" data-i18n="nav.combat">Combat</button>
<button class="nav-btn" data-tab="history" data-i18n="nav.history">History</button>
<button class="nav-btn" data-tab="backup" data-i18n="nav.backup">Backup</button>
</nav>
<div class="sidebar-footer">
<label class="lang-label" for="locale-select">
@@ -43,18 +44,6 @@
<span data-i18n="actions.importBackup">Import game backup</span>
<input type="file" id="file-upload" accept=".json" hidden>
</label>
<div class="sidebar-backup-block">
<p class="sidebar-backup-label" data-i18n="viewerDb.title">Viewer backup</p>
<a class="upload-btn export-btn" id="export-viewer" href="#" data-i18n="actions.exportViewer">Export viewer</a>
<label class="upload-btn">
<span data-i18n="actions.importViewer">Import viewer</span>
<input type="file" id="viewer-db-upload" accept=".db,application/octet-stream" hidden>
</label>
<details class="sidebar-backup-help">
<summary data-i18n="viewerDb.helpTitle">What is this?</summary>
<p data-i18n="viewerDb.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).</p>
</details>
</div>
</div>
</aside>
@@ -90,6 +79,20 @@
<section class="tab-panel" id="tab-quests"></section>
<section class="tab-panel" id="tab-combat"></section>
<section class="tab-panel" id="tab-history"></section>
<section class="tab-panel" id="tab-backup">
<div class="card backup-tab-card">
<h3 data-i18n="viewerDb.title">Viewer backup</h3>
<p class="backup-tab-lead" data-i18n="viewerDb.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).</p>
<p class="backup-tab-note" data-i18n="viewerDb.gameBackupNote">To add a new game save snapshot, use Import game backup in the sidebar.</p>
<div class="backup-tab-actions">
<a class="upload-btn export-btn" id="export-viewer" href="#" data-i18n="actions.exportViewer">Export viewer</a>
<label class="upload-btn">
<span data-i18n="actions.importViewer">Import viewer</span>
<input type="file" id="viewer-db-upload" accept=".db,application/octet-stream" hidden>
</label>
</div>
</div>
</section>
</main>
</div>
<div id="goal-modal" class="goal-modal" hidden>