feat(ui): sort request lists and move selected requests to another library
This commit is contained in:
1 parent
07c988c443
commit
46b88e2fd5
3 files changed
+74
-8
No files matched your search
+47
-8
@@ -84,10 +84,10 @@ function libOptions(mediaType) {
|
||||
// ---- missing badge ----
|
||||
async function refreshMissingBadge() {
|
||||
try {
|
||||
const reqs = await api("/api/requests?status=missing");
|
||||
const { count } = await api("/api/requests/count?status=missing");
|
||||
const badge = $("#missing-badge");
|
||||
badge.textContent = reqs.length;
|
||||
badge.hidden = reqs.length === 0;
|
||||
badge.textContent = count;
|
||||
badge.hidden = count === 0;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
@@ -519,6 +519,22 @@ function requestMatchesFilter(r, text) {
|
||||
return hay.includes(text.toLowerCase());
|
||||
}
|
||||
|
||||
// the server already sends newest first
|
||||
const SORTS = {
|
||||
title: (a, b) => a.title.localeCompare(b.title, undefined, { numeric: true }),
|
||||
author: (a, b) => a.authors.localeCompare(b.authors) || SORTS.title(a, b),
|
||||
series: (a, b) => (a.series || a.title).localeCompare(b.series || b.title)
|
||||
|| (a.volume ?? 0) - (b.volume ?? 0) || SORTS.title(a, b),
|
||||
};
|
||||
for (const status of ["missing", "imported"]) {
|
||||
const sel = $(`#${status}-sort`);
|
||||
try { sel.value = localStorage.getItem("wordarr.sort." + status) || "newest"; } catch {}
|
||||
sel.addEventListener("change", () => {
|
||||
try { localStorage.setItem("wordarr.sort." + status, sel.value); } catch {}
|
||||
renderRequests(status);
|
||||
});
|
||||
}
|
||||
|
||||
async function loadRequests(status) {
|
||||
const params = new URLSearchParams({ status });
|
||||
if (status === "missing") {
|
||||
@@ -543,11 +559,15 @@ async function loadRequests(status) {
|
||||
function renderRequests(status) {
|
||||
const text = status === "missing" ? $("#missing-search").value : $("#imported-search").value;
|
||||
const reqs = currentRequests[status].filter((r) => requestMatchesFilter(r, text));
|
||||
const sort = SORTS[$(`#${status}-sort`).value];
|
||||
if (sort) reqs.sort(sort);
|
||||
const box = status === "missing" ? $("#missing-list") : $("#imported-list");
|
||||
const bulkBtn = status === "missing" ? $("#missing-bulk-delete") : $("#imported-bulk-delete");
|
||||
const moveSel = status === "missing" ? $("#missing-move-library") : null;
|
||||
if (!reqs.length) {
|
||||
box.innerHTML = `<p class='muted'>${t("common.nothingHere")}</p>`;
|
||||
bulkBtn.hidden = true;
|
||||
if (moveSel) moveSel.hidden = true;
|
||||
return;
|
||||
}
|
||||
box.innerHTML = reqs
|
||||
@@ -582,6 +602,10 @@ function renderRequests(status) {
|
||||
const n = box.querySelectorAll("[data-sel-req]:checked").length;
|
||||
bulkBtn.hidden = n === 0;
|
||||
bulkBtn.textContent = t("common.removeSelectedN", { n });
|
||||
if (!moveSel) return;
|
||||
moveSel.hidden = n === 0;
|
||||
moveSel.innerHTML = `<option value="">${esc(t("list.moveTo", { n }))}</option>` +
|
||||
libraries.map((l) => `<option value="${l.id}">${esc(l.name)} (${esc(l.media_type)})</option>`).join("");
|
||||
};
|
||||
box.querySelectorAll("[data-sel-req]").forEach((c) =>
|
||||
c.addEventListener("change", updateBulkBtn)
|
||||
@@ -596,14 +620,29 @@ async function bulkDeleteRequests(status) {
|
||||
const hint = t(status === "imported" ? "list.confirmDeleteImported" : "list.confirmDeleteRequests",
|
||||
{ n: ids.length });
|
||||
if (!confirm(hint)) return;
|
||||
for (const id of ids) {
|
||||
try { await api("/api/requests/" + id, { method: "DELETE" }); }
|
||||
catch (err) { toast(err.message, true); }
|
||||
}
|
||||
toast(t("list.deletedN", { n: ids.length }));
|
||||
try {
|
||||
const res = await api("/api/requests/bulk", {
|
||||
method: "DELETE", body: JSON.stringify({ ids: ids.map(Number) }),
|
||||
});
|
||||
toast(t("list.deletedN", { n: res.deleted }));
|
||||
} catch (err) { toast(err.message, true); }
|
||||
loadRequests(status);
|
||||
}
|
||||
|
||||
$("#missing-move-library").addEventListener("change", async (ev) => {
|
||||
const lib = libraries.find((l) => String(l.id) === ev.target.value);
|
||||
if (!lib) return;
|
||||
const ids = [...$("#missing-list").querySelectorAll("[data-sel-req]:checked")]
|
||||
.map((c) => Number(c.dataset.selReq));
|
||||
try {
|
||||
const res = await api("/api/requests/bulk", {
|
||||
method: "PUT", body: JSON.stringify({ ids, library_id: lib.id }),
|
||||
});
|
||||
toast(t("list.movedN", { n: res.updated, library: lib.name }));
|
||||
} catch (err) { toast(err.message, true); }
|
||||
loadRequests("missing");
|
||||
});
|
||||
|
||||
$("#imported-bulk-delete").addEventListener("click", () => bulkDeleteRequests("imported"));
|
||||
|
||||
function selectAllRequests(status) {
|
||||
|
||||
Reference in new issue
Block a user