feat(ui): show the history in an activity view

This commit is contained in:
Steppenstreuner committed 2026-10-25 19:22:30 +01:00
1 parent 0c504790df
commit 40a829c80c
3 files changed
+71 -1

No files matched your search

+36 -1
View File
@@ -93,7 +93,7 @@ async function refreshMissingBadge() {
// ---- navigation ---- // ---- navigation ----
// the view lives in the hash so reload, back button and links keep it // the view lives in the hash so reload, back button and links keep it
const VIEWS = ["search", "missing", "imported", "import", "settings"]; const VIEWS = ["search", "missing", "imported", "import", "activity", "settings"];
function showView() { function showView() {
const hash = location.hash.slice(1); const hash = location.hash.slice(1);
@@ -101,6 +101,7 @@ function showView() {
$$("nav button[data-view]").forEach((b) => b.classList.toggle("active", b.dataset.view === name)); $$("nav button[data-view]").forEach((b) => b.classList.toggle("active", b.dataset.view === name));
$$("main > section").forEach((s) => (s.hidden = s.id !== "view-" + name)); $$("main > section").forEach((s) => (s.hidden = s.id !== "view-" + name));
if (name === "missing" || name === "imported") loadRequests(name); if (name === "missing" || name === "imported") loadRequests(name);
if (name === "activity") loadHistory();
if (name === "settings") loadLibraries().catch((err) => toast(err.message, true)); if (name === "settings") loadLibraries().catch((err) => toast(err.message, true));
} }
@@ -622,6 +623,39 @@ $("#imported-search").addEventListener("input", () => renderRequests("imported")
$("#missing-bulk-delete").addEventListener("click", () => bulkDeleteRequests("missing")); $("#missing-bulk-delete").addEventListener("click", () => bulkDeleteRequests("missing"));
// ---- activity ----
let historyRows = [];
const HISTORY_STATE = { imported: "done", appended: "done", failed: "failed" };
async function loadHistory() {
try {
historyRows = await api("/api/history");
} catch (err) {
toast(err.message, true);
}
renderHistory();
}
function renderHistory() {
const tbody = $("#history-table tbody");
if (!historyRows.length) {
tbody.innerHTML = `<tr><td colspan="4" class="muted">${t("common.nothingHere")}</td></tr>`;
return;
}
const locale = lang === "de" ? "de-DE" : "en-GB";
tbody.innerHTML = historyRows
.map((h) => {
const where = h.message || (h.source && h.dest ? `${h.source} → ${h.dest}` : h.dest || h.source);
return `<tr>
<td class="state">${esc(new Date(h.at).toLocaleString(locale))}</td>
<td class="state ${HISTORY_STATE[h.event] || ""}">${esc(t("history." + h.event))}</td>
<td>${esc(h.title)} <span class="tag fmt">${esc(h.media_type)}</span></td>
<td class="muted mono">${esc(where)}</td>
</tr>`;
})
.join("");
}
// ---- request detail dialog ---- // ---- request detail dialog ----
let detailRequest = null; let detailRequest = null;
@@ -1758,6 +1792,7 @@ function onLangChange() {
renderSearchResults(); renderSearchResults();
renderRequests("missing"); renderRequests("missing");
renderRequests("imported"); renderRequests("imported");
renderHistory();
if (libraries.length) loadLibraries(); if (libraries.length) loadLibraries();
const editId = $("#lib-form").dataset.editId; const editId = $("#lib-form").dataset.editId;
editId ? startLibraryEdit(parseInt(editId)) : endLibraryEdit(); editId ? startLibraryEdit(parseInt(editId)) : endLibraryEdit();
+18
View File
@@ -46,7 +46,16 @@ const STRINGS = {
"nav.imported": "Importiert", "nav.imported": "Importiert",
"nav.import": "Import", "nav.import": "Import",
"nav.settings": "Libraries", "nav.settings": "Libraries",
"nav.activity": "Aktivität",
"nav.langToggle": "Switch to English", "nav.langToggle": "Switch to English",
"history.time": "Zeit",
"history.event": "Ereignis",
"history.imported": "importiert",
"history.appended": "ergänzt",
"history.relocated": "verschoben",
"history.retagged": "neu getaggt",
"history.deleted": "gelöscht",
"history.failed": "fehlgeschlagen",
"search.languageTitle": "Sprache der Ausgabe — filtert Ebook- und Audiobook-Suche", "search.languageTitle": "Sprache der Ausgabe — filtert Ebook- und Audiobook-Suche",
"search.allLanguages": "Alle Sprachen", "search.allLanguages": "Alle Sprachen",
@@ -270,7 +279,16 @@ const STRINGS = {
"nav.imported": "Imported", "nav.imported": "Imported",
"nav.import": "Import", "nav.import": "Import",
"nav.settings": "Libraries", "nav.settings": "Libraries",
"nav.activity": "Activity",
"nav.langToggle": "Auf Deutsch umschalten", "nav.langToggle": "Auf Deutsch umschalten",
"history.time": "Time",
"history.event": "Event",
"history.imported": "imported",
"history.appended": "appended",
"history.relocated": "relocated",
"history.retagged": "retagged",
"history.deleted": "deleted",
"history.failed": "failed",
"search.languageTitle": "Edition language — filters the ebook and audiobook search", "search.languageTitle": "Edition language — filters the ebook and audiobook search",
"search.allLanguages": "All languages", "search.allLanguages": "All languages",
+17
View File
@@ -20,6 +20,7 @@
</button> </button>
<button data-view="imported" data-i18n="nav.imported"></button> <button data-view="imported" data-i18n="nav.imported"></button>
<button data-view="import" data-i18n="nav.import"></button> <button data-view="import" data-i18n="nav.import"></button>
<button data-view="activity" data-i18n="nav.activity"></button>
<button data-view="settings" data-i18n="nav.settings"></button> <button data-view="settings" data-i18n="nav.settings"></button>
<button id="lang-toggle" class="secondary" data-i18n-title="nav.langToggle"></button> <button id="lang-toggle" class="secondary" data-i18n-title="nav.langToggle"></button>
</nav> </nav>
@@ -269,6 +270,22 @@
</dialog> </dialog>
</section> </section>
<section id="view-activity" hidden>
<div class="table-scroll">
<table id="history-table">
<thead>
<tr>
<th data-i18n="history.time"></th>
<th data-i18n="history.event"></th>
<th data-i18n="common.title"></th>
<th data-i18n="common.path"></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</section>
<section id="view-settings" hidden> <section id="view-settings" hidden>
<h3 data-i18n="lib.heading"></h3> <h3 data-i18n="lib.heading"></h3>
<div class="table-scroll"> <div class="table-scroll">