const downloadRangeButtons = Array.from(document.querySelectorAll("[data-download-range]")); const customDateFields = document.querySelector("[data-custom-date-fields]"); const customDateCollapse = customDateFields ? new bootstrap.Collapse(customDateFields, { toggle: false }) : null; const downloadFrom = document.querySelector("#download-from"); const downloadTo = document.querySelector("#download-to"); const errorBanner = document.querySelector("[data-downloads-error]"); const form = document.querySelector("form.downloads-form"); let submittedButton = null; downloadRangeButtons.forEach(option => { option.addEventListener("change", () => { const custom = option.value === "custom"; if (customDateCollapse) { custom ? customDateCollapse.show() : customDateCollapse.hide(); } if (custom) { downloadFrom?.focus(); return; } if (downloadFrom) { downloadFrom.value = option.dataset.from; } if (downloadTo) { downloadTo.value = option.dataset.to; } }); }); function showError(message) { if (!errorBanner) return; errorBanner.textContent = message; errorBanner.classList.remove("d-none"); } function clearError() { if (!errorBanner) return; errorBanner.textContent = ""; errorBanner.classList.add("d-none"); } function triggerDownload(blob, filename) { const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); link.remove(); URL.revokeObjectURL(url); } function filenameFromResponse(response) { const header = response.headers.get("Content-Disposition") || ""; const match = header.match(/filename="([^"]+)"/); return match ? match[1] : "readings.csv"; } function setDownloadPending(button, pending) { if (!button) return; button.disabled = pending; button.setAttribute("aria-busy", pending ? "true" : "false"); button.querySelector("[data-download-spinner]")?.classList.toggle("d-none", !pending); } if (form) { form.querySelectorAll("[data-download-button]").forEach(button => { button.addEventListener("click", () => { submittedButton = button; }); }); form.addEventListener("submit", async event => { event.preventDefault(); clearError(); const button = event.submitter || submittedButton || form.querySelector("[data-download-button]"); const params = new URLSearchParams(new FormData(form)); const action = button?.getAttribute("formaction") || form.action; const url = new URL(action, window.location.origin); url.search = params; setDownloadPending(button, true); try { const response = await fetch(url); if (!response.ok) { const text = await response.text(); showError(text || `Download failed (HTTP ${response.status}).`); return; } const blob = await response.blob(); triggerDownload(blob, filenameFromResponse(response)); } catch (err) { showError("Could not reach the server. Check your connection and try again."); } finally { setDownloadPending(button, false); submittedButton = null; } }); }