From 671b512917a56f2be9f19c8bb5eaffa706153fd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastjan=20Arti=C4=8D?= Date: Wed, 29 Apr 2026 13:39:04 +0000 Subject: [PATCH] Fix Preview button in jobs sidebar not opening modal Root cause: inline onclick with JSON.stringify(title) broke when title contained quotes, special chars, or was empty. The HTML attribute parser got confused by mismatched quotes, so click handler never fired. Fix: - Replaced inline onclick handlers with data-action attributes - Added single delegated click listener at document level - Title stored in element dataset (no HTML quoting issues) - Added escapeHtml() helper for safe rendering of titles/errors Now clicking Preview in the right sidebar opens the fullscreen modal correctly, regardless of filename characters. --- templates/index.html | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/templates/index.html b/templates/index.html index f7a8b08..2a2c647 100644 --- a/templates/index.html +++ b/templates/index.html @@ -769,19 +769,19 @@ const actions = []; if (job.status === "done") { - actions.push(``); - actions.push(``); + actions.push(``); + actions.push(``); } - actions.push(``); + actions.push(``); el.innerHTML = `
-
${title}
+
${escapeHtml(title)}
${statusLabel}
- ${job.current_step ? `
${job.current_step}
` : ""} + ${job.current_step ? `
${escapeHtml(job.current_step)}
` : ""} ${showBar} - ${job.error ? `
⚠ ${job.error}
` : ""} + ${job.error ? `
⚠ ${escapeHtml(job.error)}
` : ""}
${job.source_type === "youtube" ? "YouTube" : "Upload"} ${sizeStr ? `${sizeStr}` : ""} @@ -790,9 +790,40 @@
${actions.join("")}
`; + // Shrani naslov za preview modal + el.dataset.title = title; return el; } + function escapeHtml(s) { + if (s == null) return ""; + return String(s) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); + } + + // Globalno delegirano poslušanje za action gumbe (Download / Preview / Delete) + document.addEventListener("click", (e) => { + const btn = e.target.closest("button[data-action]"); + if (!btn) return; + const action = btn.dataset.action; + const id = btn.dataset.id; + if (!id) return; + const card = btn.closest(".job"); + const title = card?.dataset.title || ""; + + if (action === "download") { + window.open(`/api/download/${id}`); + } else if (action === "preview") { + previewJob(id, title); + } else if (action === "delete") { + deleteJob(id); + } + }); + async function deleteJob(id) { if (!confirm("Izbrišem ta job?")) return; await fetch(`/api/jobs/${id}`, { method: "DELETE" });