From d992e8fd97b6ac7a81685283d82cbd881e6336c6 Mon Sep 17 00:00:00 2001 From: Steppenstreuner Date: Fri, 28 Aug 2026 18:15:48 +0200 Subject: [PATCH] add(ui/ux): select all for bulk delete and edit for libraries --- static/app.js | 56 +++++++++++++++++++++++++++++++++++++++++++---- static/index.html | 9 ++++++-- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/static/app.js b/static/app.js index 4022f6f..6ba57e3 100644 --- a/static/app.js +++ b/static/app.js @@ -77,10 +77,16 @@ async function loadLibraries() { (l) => ` ${esc(l.name)}${esc(l.media_type)}${esc(l.root_path)} ${esc(l.folder_template)}${esc(l.file_template)} - + + + + ` ) .join(""); + tbody.querySelectorAll("[data-edit-lib]").forEach((b) => + b.addEventListener("click", () => startLibraryEdit(parseInt(b.dataset.editLib))) + ); tbody.querySelectorAll("[data-del-lib]").forEach((b) => b.addEventListener("click", async () => { if (!confirm("Library löschen?")) return; @@ -96,16 +102,48 @@ async function loadLibraries() { libraries.map((l) => ``).join(""); } +function startLibraryEdit(id) { + const lib = libraries.find((l) => l.id === id); + if (!lib) return; + const form = $("#lib-form"); + form.name.value = lib.name; + form.media_type.value = lib.media_type; + form.root_path.value = lib.root_path; + form.folder_template.value = lib.folder_template; + form.file_template.value = lib.file_template; + form.dataset.editId = lib.id; + $("#lib-form-title").textContent = `Library „${lib.name}“ bearbeiten`; + $("#lib-form-submit").textContent = "Speichern"; + $("#lib-form-cancel").hidden = false; + form.scrollIntoView({ behavior: "smooth" }); +} + +function endLibraryEdit() { + const form = $("#lib-form"); + form.reset(); + delete form.dataset.editId; + $("#lib-form-title").textContent = "Neue Library"; + $("#lib-form-submit").textContent = "Anlegen"; + $("#lib-form-cancel").hidden = true; +} +$("#lib-form-cancel").addEventListener("click", endLibraryEdit); + $("#lib-form").addEventListener("submit", async (e) => { e.preventDefault(); const data = Object.fromEntries(new FormData(e.target)); if (!data.folder_template) delete data.folder_template; if (!data.file_template) delete data.file_template; + const editId = e.target.dataset.editId; try { - await api("/api/libraries", { method: "POST", body: JSON.stringify(data) }); - e.target.reset(); + if (editId) { + await api("/api/libraries/" + editId, { method: "PUT", body: JSON.stringify(data) }); + toast("Library gespeichert — gilt für künftige Importe"); + } else { + await api("/api/libraries", { method: "POST", body: JSON.stringify(data) }); + toast("Library angelegt"); + } + endLibraryEdit(); loadLibraries(); - toast("Library angelegt"); } catch (err) { toast(err.message, true); } }); @@ -360,6 +398,16 @@ async function bulkDeleteRequests(status) { $("#imported-bulk-delete").addEventListener("click", () => bulkDeleteRequests("imported")); +function selectAllRequests(status) { + const box = status === "missing" ? $("#missing-list") : $("#imported-list"); + const checks = [...box.querySelectorAll("[data-sel-req]")]; + const allChecked = checks.length && checks.every((c) => c.checked); + checks.forEach((c) => (c.checked = !allChecked)); + if (checks.length) checks[0].dispatchEvent(new Event("change")); +} +$("#missing-select-all").addEventListener("click", () => selectAllRequests("missing")); +$("#imported-select-all").addEventListener("click", () => selectAllRequests("imported")); + $("#missing-filter-type").addEventListener("change", () => loadRequests("missing")); $("#missing-filter-library").addEventListener("change", () => loadRequests("missing")); $("#missing-search").addEventListener("input", () => renderRequests("missing")); diff --git a/static/index.html b/static/index.html index 555fe62..738650a 100644 --- a/static/index.html +++ b/static/index.html @@ -87,6 +87,7 @@ + @@ -102,6 +103,7 @@