From 90a50e365f7b4479366cccb49071045c3c317845 Mon Sep 17 00:00:00 2001 From: Steppenstreuner Date: Fri, 28 Aug 2026 14:30:00 +0200 Subject: [PATCH] add(core): show less entries in download --- static/app.js | 82 ++++++++++++++++++++++++++++++++--------------- static/index.html | 5 +++ 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/static/app.js b/static/app.js index 154b23c..e28c374 100644 --- a/static/app.js +++ b/static/app.js @@ -265,7 +265,13 @@ $("#scan-btn").addEventListener("click", async () => { api("/api/requests?status=missing"), ]); scanItems = scan.items; + // selection state lives here, not in the DOM, so it survives paging + scanItems.forEach((item) => { + item.request_id = item.suggested_request_id; + item.checked = !!item.suggested_request_id; + }); missingReqs = reqs; + importPage = 0; $("#scan-info").textContent = `${scan.items.length} Kandidat(en) in ${scan.download_dir}`; renderImportTable(); } catch (err) { @@ -274,22 +280,36 @@ $("#scan-btn").addEventListener("click", async () => { } }); +let importPage = 0; +const IMPORT_PAGE_SIZE = 25; + function renderImportTable() { const table = $("#import-table"); const tbody = table.querySelector("tbody"); - if (!scanItems.length) { table.hidden = true; $("#import-btn").hidden = true; return; } - tbody.innerHTML = scanItems - .map((item, i) => { + if (!scanItems.length) { + table.hidden = true; + $("#import-btn").hidden = true; + $("#import-pager").hidden = true; + return; + } + const pages = Math.ceil(scanItems.length / IMPORT_PAGE_SIZE); + importPage = Math.min(importPage, pages - 1); + const start = importPage * IMPORT_PAGE_SIZE; + const pageItems = scanItems.slice(start, start + IMPORT_PAGE_SIZE); + + tbody.innerHTML = pageItems + .map((item, k) => { + const i = start + k; const opts = missingReqs .filter((r) => r.media_type === item.media_type) .map( (r) => - `` ) .join(""); return ` - + ${esc(item.name)}${item.is_dir ? " 📁" : ""} ${esc(item.media_type)} @@ -302,11 +322,34 @@ function renderImportTable() { .join(""); table.hidden = false; $("#import-btn").hidden = false; + tbody.querySelectorAll("[data-quick]").forEach((b) => b.addEventListener("click", () => openQuickDialog(parseInt(b.dataset.quick))) ); + tbody.querySelectorAll("[data-check]").forEach((c) => + c.addEventListener("change", () => (scanItems[c.dataset.check].checked = c.checked)) + ); + tbody.querySelectorAll("[data-select]").forEach((s) => + s.addEventListener("change", () => { + const item = scanItems[s.dataset.select]; + item.request_id = s.value ? parseInt(s.value) : null; + item.checked = !!item.request_id; + const check = tbody.querySelector(`[data-check="${s.dataset.select}"]`); + if (check) check.checked = item.checked; + }) + ); + + const selected = scanItems.filter((it) => it.checked && it.request_id).length; + $("#import-pager").hidden = false; + $("#import-page-info").textContent = + `Seite ${importPage + 1}/${pages} · ${scanItems.length} Einträge · ${selected} ausgewählt`; + $("#import-prev").disabled = importPage === 0; + $("#import-next").disabled = importPage >= pages - 1; } +$("#import-prev").addEventListener("click", () => { importPage--; renderImportTable(); }); +$("#import-next").addEventListener("click", () => { importPage++; renderImportTable(); }); + // ---- quick request from a scanned file ---- let quickItemIndex = null; @@ -381,32 +424,21 @@ async function pickQuickResult(r) { }), }); missingReqs.push(req); - // add the new request to every dropdown of the same media type, then link this row - const item = scanItems[i]; - scanItems.forEach((it, j) => { - if (it.media_type !== item.media_type) return; - const sel = document.querySelector(`[data-select="${j}"]`); - const opt = document.createElement("option"); - opt.value = req.id; - opt.textContent = `${req.title} — ${req.authors} (${req.library_name})`; - sel.appendChild(opt); - }); - document.querySelector(`[data-select="${i}"]`).value = req.id; - document.querySelector(`[data-check="${i}"]`).checked = true; + scanItems[i].request_id = req.id; + scanItems[i].checked = true; + renderImportTable(); $("#quick-dialog").close(); toast(`„${req.title}" angefragt und verbunden`); } catch (err) { toast(err.message, true); } } $("#import-btn").addEventListener("click", async () => { - const items = []; - scanItems.forEach((item, i) => { - const checked = document.querySelector(`[data-check="${i}"]`).checked; - const reqId = document.querySelector(`[data-select="${i}"]`).value; - if (checked && reqId) { - items.push({ path: item.path, is_dir: item.is_dir, files: item.files, request_id: parseInt(reqId) }); - } - }); + const items = scanItems + .filter((item) => item.checked && item.request_id) + .map((item) => ({ + path: item.path, is_dir: item.is_dir, files: item.files, + request_id: item.request_id, + })); if (!items.length) { toast("Nichts ausgewählt", true); return; } try { const res = await api("/api/import", { method: "POST", body: JSON.stringify({ items }) }); diff --git a/static/index.html b/static/index.html index 216288a..5714686 100644 --- a/static/index.html +++ b/static/index.html @@ -109,6 +109,11 @@ +