Add files via upload
This commit is contained in:
parent
8eda62fba0
commit
2d954a4c4c
1 changed files with 214 additions and 30 deletions
|
|
@ -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 main = document.querySelector("main");
|
||||
let progressElem = document.querySelector("progress");
|
||||
|
||||
const refreshData = () => {
|
||||
// console.log("Refreshing data...", progressElem.value, progressElem.max);
|
||||
if (progressElem.value !== progressElem.max) {
|
||||
fetch(`${webroot}/progress/${jobId}`, {
|
||||
method: "POST",
|
||||
})
|
||||
.then((res) => res.text())
|
||||
.then((html) => {
|
||||
// -----------------------------
|
||||
// Progress refresh
|
||||
// -----------------------------
|
||||
async function refreshData() {
|
||||
if (!main || !jobId) return;
|
||||
|
||||
const progressElem = main.querySelector("progress");
|
||||
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;
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
|
||||
setTimeout(refreshData, 1000);
|
||||
} catch (err) {
|
||||
console.error("[ConvertX] progress refresh failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
window.downloadAll = function () {
|
||||
// Get all download links
|
||||
const downloadLinks = document.querySelectorAll("tbody a[download]");
|
||||
// -----------------------------
|
||||
// Share modal helpers
|
||||
// -----------------------------
|
||||
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
|
||||
downloadLinks.forEach((link, index) => {
|
||||
// We add a delay for each download to prevent them from starting at the same time
|
||||
setTimeout(() => {
|
||||
const event = new MouseEvent("click");
|
||||
link.dispatchEvent(event);
|
||||
}, index * 300);
|
||||
});
|
||||
emailEl: document.getElementById("cxShareEmail"),
|
||||
nameEl: document.getElementById("cxShareName"),
|
||||
descEl: document.getElementById("cxShareDescription"),
|
||||
|
||||
linkBlock: document.getElementById("cxShareLinkBlock"),
|
||||
linkEl: document.getElementById("cxShareLink"),
|
||||
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();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue