chore(web): library-admin inline script moves to admin.ts; rendering guardrail
The library admin page carried an inline <script> block of global functions (toggleLibraryPanel, openEditModal, openDeleteModal, openFolderBrowser plus the delete-modal close listener). They move into the admin Alpine component as typed methods; the page body gains x-data="admin" and the call sites switch onclick= -> @click. Behavior unchanged. Guardrail: make lint-rendering (wired into make test) fails when a web/src file builds more HTML template literals than its recorded baseline (web/src/rendering-allowlist.txt, seeded at 18 sites across 9 files post-twin-deletion) or when a .templ file gains an inline script block. theme_flash_guard.templ is the only sanctioned inline script; web/src/reader is a sanctioned island. theme.ts: Array.from(classList) — DOMTokenList spread needs lib.dom.iterable, which the tsconfig does not include.
This commit is contained in:
1 parent
f1844591b4
commit
506a04b55d
6 files changed
+164
-94
No files matched your search
@@ -450,10 +450,86 @@ export {
|
||||
stopScanStatusPolling,
|
||||
};
|
||||
|
||||
// Library admin page helpers (rendering-ownership: these orchestrate htmx
|
||||
// swaps and modal visibility on server-rendered DOM; they render nothing).
|
||||
function toggleLibraryPanel(btn: HTMLElement): void {
|
||||
const libId = btn.dataset.libId || "";
|
||||
const panel = document.getElementById(`library-panel-${libId}`);
|
||||
if (!panel) return;
|
||||
if (panel.innerHTML.trim() !== "") {
|
||||
panel.innerHTML = "";
|
||||
} else {
|
||||
window.htmx.ajax("GET", `/admin/library/${libId}/panel`, {
|
||||
target: `#library-panel-${libId}`,
|
||||
swap: "innerHTML",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function openEditModal(id: string, name: string, description: string): void {
|
||||
const form = document.getElementById("edit-library-form");
|
||||
if (!form) return;
|
||||
form.setAttribute("hx-put", `/admin/library/${id}`);
|
||||
const nameInput = document.getElementById("edit-library-name");
|
||||
if (nameInput) (nameInput as HTMLInputElement).value = name;
|
||||
const descInput = document.getElementById("edit-library-desc");
|
||||
if (descInput) (descInput as HTMLInputElement).value = description;
|
||||
window.htmx.process(form);
|
||||
document.getElementById("edit-library-modal")?.classList.remove("hidden");
|
||||
}
|
||||
|
||||
function openDeleteModal(id: string, name: string): void {
|
||||
const btn = document.getElementById("delete-library-confirm");
|
||||
if (!btn) return;
|
||||
btn.setAttribute("hx-delete", `/admin/library/${id}`);
|
||||
btn.setAttribute("hx-target", "#libraries-container");
|
||||
btn.setAttribute("hx-swap", "innerHTML");
|
||||
const nameEl = document.getElementById("delete-library-name");
|
||||
if (nameEl) nameEl.textContent = name;
|
||||
window.htmx.process(btn);
|
||||
document.getElementById("delete-library-modal")?.classList.remove("hidden");
|
||||
}
|
||||
|
||||
function openFolderBrowser(targetInputId: string, libraryId: string): void {
|
||||
const content = document.getElementById("folder-browser-content");
|
||||
if (!content) return;
|
||||
content.setAttribute("hx-get", "/admin/library/browse");
|
||||
content.setAttribute(
|
||||
"hx-vals",
|
||||
JSON.stringify({ target_input: targetInputId, library_id: libraryId }),
|
||||
);
|
||||
content.setAttribute("hx-trigger", "load");
|
||||
window.htmx.process(content);
|
||||
document.getElementById("folder-browser-modal")?.classList.remove("hidden");
|
||||
}
|
||||
|
||||
// Close the delete-library modal after a successful delete: the htmx swap
|
||||
// already removes the deleted row from the libraries list, but the modal
|
||||
// lives outside the swapped container and would otherwise stay open.
|
||||
function bindDeleteLibraryModalClose(): void {
|
||||
document
|
||||
.getElementById("delete-library-confirm")
|
||||
?.addEventListener("htmx:afterRequest", function (evt) {
|
||||
const detail = (evt as CustomEvent).detail as { successful?: boolean };
|
||||
if (detail.successful) {
|
||||
document
|
||||
.getElementById("delete-library-modal")
|
||||
?.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Alpine.data("admin", () => ({
|
||||
init() {
|
||||
bindDeleteLibraryModalClose();
|
||||
},
|
||||
checkActiveScans,
|
||||
hideScanProgress,
|
||||
loadWatchStatus,
|
||||
scanAllLibraries,
|
||||
stopScanStatusPolling,
|
||||
openDeleteModal,
|
||||
openEditModal,
|
||||
openFolderBrowser,
|
||||
toggleLibraryPanel,
|
||||
}));
|
||||
Reference in new issue
Block a user