add(ui/ux): clear finished rows after 15s and select just the visible page

This commit is contained in:
Steppenstreuner
2026-08-29 08:22:40 +02:00
parent af5fd5deba
commit 1b9ec2d5e7
3 changed files with 46 additions and 2 deletions
+39 -1
View File
@@ -666,6 +666,7 @@ $("#scan-btn").addEventListener("click", async () => {
api("/api/requests?status=missing"),
api("/api/requests?status=imported"),
]);
clearTimeout(cleanupTimer);
scanItems = scan.items;
// selection state lives here, not in the DOM, so it survives paging/filtering
scanItems.forEach((item) => {
@@ -841,6 +842,25 @@ $("#import-select-suggested").addEventListener("click", () => {
renderImportTable();
});
$("#import-select-page").addEventListener("click", () => {
applyImportView();
const start = importPage * IMPORT_PAGE_SIZE;
const pageIdx = viewIdx.slice(start, start + IMPORT_PAGE_SIZE);
// exclusive on purpose: "import what I see", not "add to what was selected"
scanItems.forEach((it) => (it.checked = false));
let n = 0;
pageIdx.forEach((i) => {
const item = scanItems[i];
const req = item.request_id || item.suggested_request_id;
if (!req) return;
item.request_id = req;
item.checked = true;
n += 1;
});
renderImportTable();
toast(n ? `${n} Einträge dieser Seite ausgewählt` : "Auf dieser Seite gibt es keine Zuordnung", !n);
});
$("#import-deselect-all").addEventListener("click", () => {
applyImportView();
viewIdx.forEach((i) => (scanItems[i].checked = false));
@@ -1141,6 +1161,10 @@ $("#quick-m-submit").addEventListener("click", () => {
// ---- import execution (batched, with progress) ----
const IMPORT_BATCH_SIZE = 20;
// finished rows disappear after a while: the result list below keeps the record,
// and a shrinking table makes the remaining work obvious
const IMPORT_DONE_CLEANUP_MS = 15000;
let cleanupTimer = null;
// several entries on one request means one audiobook split across folders:
// importing them one by one only imports the first and fails the rest
@@ -1294,6 +1318,19 @@ $("#import-btn").addEventListener("click", async () => {
.join("");
toast(failed.length ? `Import fertig, ${failed.length} Fehler` : "Import fertig", failed.length > 0);
refreshMissingBadge();
clearTimeout(cleanupTimer);
cleanupTimer = setTimeout(() => {
// only the successful ones go; failures and conflicts stay to be dealt with
const before = scanItems.length;
scanItems = scanItems.filter((it) => it.importState !== "done");
if (scanItems.length !== before) {
importPage = 0;
setImportProgress(0, 0);
renderImportTable();
$("#scan-info").textContent =
`${scanItems.length} Kandidat(en) übrig — für den aktuellen Stand erneut scannen`;
}
}, IMPORT_DONE_CLEANUP_MS);
// the list stays as it is, with its green and red rows - rescanning would
// wipe exactly the feedback the user just waited for
} finally {
@@ -1304,7 +1341,8 @@ $("#import-btn").addEventListener("click", async () => {
function setImportProgress(done, total) {
const box = $("#import-progress");
if (!total || done >= total) {
if (!total) { box.hidden = true; return; }
if (done >= total) {
box.hidden = done < total;
if (done >= total) {
box.querySelector("progress").value = total;
+4
View File
@@ -165,6 +165,10 @@
<button id="import-select-suggested" class="secondary">
Alle mit Vorschlag auswählen
</button>
<button id="import-select-page" class="secondary"
title="Nur die Einträge dieser Seite auswählen, alle anderen abwählen">
Diese Seite auswählen
</button>
<button id="import-deselect-all" class="secondary">
Alle abwählen
</button>