Add files via upload

This commit is contained in:
Kosztyk 2026-01-05 21:27:34 +02:00 committed by GitHub
parent 8eda62fba0
commit 2d954a4c4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,38 +1,222 @@
const webroot = document.querySelector("meta[name='webroot']").content; // public/results.js
//
// Handles live progress updates for /results/:jobId and Share via Erugo modal actions.
// IMPORTANT: /progress/:jobId re-renders the <main> content, so we must not keep stale
// element references. Use event delegation + (re)query elements when needed.
(function () {
const webrootMeta = document.querySelector("meta[name='webroot']");
const webroot = webrootMeta ? webrootMeta.content : "";
const jobId = window.location.pathname.split("/").pop(); const jobId = window.location.pathname.split("/").pop();
const main = document.querySelector("main"); const main = document.querySelector("main");
let progressElem = document.querySelector("progress");
const refreshData = () => { // -----------------------------
// console.log("Refreshing data...", progressElem.value, progressElem.max); // Progress refresh
if (progressElem.value !== progressElem.max) { // -----------------------------
fetch(`${webroot}/progress/${jobId}`, { async function refreshData() {
method: "POST", if (!main || !jobId) return;
})
.then((res) => res.text()) const progressElem = main.querySelector("progress");
.then((html) => { if (!progressElem) return;
const max = Number(progressElem.getAttribute("max") || "0");
const val = Number(progressElem.getAttribute("value") || "0");
// Only refresh while still processing
if (max > 0 && val >= max) return;
try {
const res = await fetch(`${webroot}/progress/${jobId}`, { method: "POST", cache: "no-store" });
const html = await res.text();
main.innerHTML = html; main.innerHTML = html;
}) } catch (err) {
.catch((err) => console.log(err)); console.error("[ConvertX] progress refresh failed", err);
}
setTimeout(refreshData, 1000);
} }
progressElem = document.querySelector("progress"); // Poll every second while job is running
}; setInterval(refreshData, 1000);
// Run once immediately so the page updates without waiting 1s.
refreshData(); refreshData();
window.downloadAll = function () { // -----------------------------
// Get all download links // Share modal helpers
const downloadLinks = document.querySelectorAll("tbody a[download]"); // -----------------------------
function getEls() {
return {
modal: document.getElementById("cxShareModal"),
closeBtn: document.getElementById("cxShareClose"),
cancelBtn: document.getElementById("cxShareCancel"),
submitBtn: document.getElementById("cxShareSubmit"),
statusEl: document.getElementById("cxShareStatus"),
// Trigger download for each link emailEl: document.getElementById("cxShareEmail"),
downloadLinks.forEach((link, index) => { nameEl: document.getElementById("cxShareName"),
// We add a delay for each download to prevent them from starting at the same time descEl: document.getElementById("cxShareDescription"),
setTimeout(() => {
const event = new MouseEvent("click"); linkBlock: document.getElementById("cxShareLinkBlock"),
link.dispatchEvent(event); linkEl: document.getElementById("cxShareLink"),
}, index * 300); copyBtn: document.getElementById("cxShareCopy"),
});
}; };
}
let currentJobId = null;
let currentFileName = null;
function openModal(jobIdValue, fileNameValue) {
const els = getEls();
if (!els.modal) return;
currentJobId = jobIdValue;
currentFileName = fileNameValue;
if (els.nameEl) els.nameEl.value = fileNameValue || "";
if (els.emailEl) els.emailEl.value = "";
if (els.descEl) els.descEl.value = "";
if (els.linkBlock) els.linkBlock.classList.add("hidden");
if (els.linkEl) els.linkEl.value = "";
if (els.statusEl) els.statusEl.textContent = "";
els.modal.classList.remove("hidden");
els.modal.classList.add("flex");
if (els.emailEl) els.emailEl.focus();
}
function closeModal() {
const els = getEls();
if (!els.modal) return;
els.modal.classList.add("hidden");
els.modal.classList.remove("flex");
currentJobId = null;
currentFileName = null;
}
async function shareFile(jobIdValue, fileNameValue) {
const els = getEls();
if (!els.submitBtn || !els.statusEl) return;
const recipientEmail = (els.emailEl && els.emailEl.value ? els.emailEl.value.trim() : "") || undefined;
const shareName = (els.nameEl && els.nameEl.value ? els.nameEl.value.trim() : "") || undefined;
const description = (els.descEl && els.descEl.value ? els.descEl.value.trim() : "") || undefined;
els.submitBtn.disabled = true;
els.submitBtn.setAttribute("aria-busy", "true");
els.statusEl.textContent = "Sending...";
try {
const payload = { fileName: fileNameValue, recipientEmail, shareName, description };
const res = await fetch(`${webroot}/share-to-erugo/${jobIdValue}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const text = await res.text();
let json = null;
try {
json = text ? JSON.parse(text) : null;
} catch {
json = { raw: text };
}
if (!res.ok) {
console.error("[ConvertX] share-to-erugo failed", res.status, json);
els.statusEl.textContent = "Failed. See logs.";
return;
}
const url =
(json && (json.share_url || json.share_link)) ||
(json && json.data && json.data.url) ||
(json && json.data && json.data.share && json.data.share.url) ||
null;
if (url && els.linkEl && els.linkBlock) {
els.linkEl.value = url;
els.linkBlock.classList.remove("hidden");
}
if (recipientEmail) {
els.statusEl.textContent = url ? "Sent. Link also shown below." : "Sent.";
} else {
els.statusEl.textContent = url ? "Created. Copy the link below." : "Created.";
}
} catch (err) {
console.error(err);
els.statusEl.textContent = "Failed. See logs.";
} finally {
els.submitBtn.disabled = false;
els.submitBtn.removeAttribute("aria-busy");
}
}
// -----------------------------
// Global event handlers (delegated)
// -----------------------------
document.addEventListener("click", async (event) => {
const target = event.target;
// Share icon buttons inside the table
const shareBtn = target && target.closest ? target.closest("button[data-share='true']") : null;
if (shareBtn) {
const jobIdAttr = shareBtn.getAttribute("data-job-id");
const fileNameAttr = shareBtn.getAttribute("data-file-name");
if (!jobIdAttr || !fileNameAttr) return;
openModal(jobIdAttr, fileNameAttr);
return;
}
// Modal close/cancel
if (target && target.id === "cxShareClose") {
closeModal();
return;
}
if (target && target.id === "cxShareCancel") {
closeModal();
return;
}
// Click outside modal (on overlay)
const els = getEls();
if (els.modal && target === els.modal) {
closeModal();
return;
}
// Submit
if (target && target.id === "cxShareSubmit") {
if (!currentJobId || !currentFileName) return;
await shareFile(currentJobId, currentFileName);
return;
}
// Copy
if (target && target.id === "cxShareCopy") {
const e = getEls();
if (!e.linkEl || !e.statusEl) return;
try {
await navigator.clipboard.writeText(e.linkEl.value);
e.statusEl.textContent = "Copied.";
} catch {
e.linkEl.focus();
e.linkEl.select();
e.statusEl.textContent = "Select + copy (Ctrl/Cmd+C).";
}
return;
}
});
document.addEventListener("keydown", (event) => {
if (event.key !== "Escape") return;
const els = getEls();
if (els.modal && !els.modal.classList.contains("hidden")) {
closeModal();
}
});
})();