156 lines
4.4 KiB
JavaScript
156 lines
4.4 KiB
JavaScript
document.addEventListener("DOMContentLoaded", () => {
|
|
const modalContainer = document.createElement("div");
|
|
modalContainer.id = "export-modal-container";
|
|
document.body.appendChild(modalContainer);
|
|
|
|
async function loadModal(dataset) {
|
|
const response = await fetch(`/exports/modal/${dataset}`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load export modal (${response.status})`);
|
|
}
|
|
const html = await response.text();
|
|
modalContainer.innerHTML = html;
|
|
const modal = modalContainer.querySelector(".modal");
|
|
if (!modal) return;
|
|
modal.classList.add("is-active");
|
|
|
|
const closeButtons = modal.querySelectorAll("[data-dismiss='modal']");
|
|
closeButtons.forEach((btn) =>
|
|
btn.addEventListener("click", () => closeModal(modal))
|
|
);
|
|
|
|
const form = modal.querySelector("[data-export-form]");
|
|
if (form) {
|
|
form.addEventListener("submit", handleSubmit);
|
|
}
|
|
}
|
|
|
|
function closeModal(modal) {
|
|
modal.classList.remove("is-active");
|
|
setTimeout(() => {
|
|
modalContainer.innerHTML = "";
|
|
}, 200);
|
|
}
|
|
|
|
async function handleSubmit(event) {
|
|
event.preventDefault();
|
|
const form = event.currentTarget;
|
|
const submitUrl = form.action;
|
|
const formData = new FormData(form);
|
|
const format = formData.get("format") || "csv";
|
|
|
|
const submitBtn = form.querySelector("button[type='submit']");
|
|
if (submitBtn) {
|
|
submitBtn.disabled = true;
|
|
submitBtn.classList.add("loading");
|
|
}
|
|
|
|
let response;
|
|
try {
|
|
response = await fetch(submitUrl, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
format,
|
|
include_metadata: formData.get("include_metadata") === "true",
|
|
filters: null,
|
|
}),
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
NotificationCenter.show({
|
|
message: "Network error during export.",
|
|
level: "error",
|
|
});
|
|
const errorContainer = form.querySelector("[data-export-error]");
|
|
if (errorContainer) {
|
|
errorContainer.textContent = "Network error during export.";
|
|
errorContainer.classList.remove("hidden");
|
|
}
|
|
submitBtn?.classList.remove("loading");
|
|
submitBtn?.removeAttribute("disabled");
|
|
return;
|
|
}
|
|
|
|
if (!response.ok) {
|
|
let detail = "Export failed. Please try again.";
|
|
try {
|
|
const payload = await response.json();
|
|
if (payload?.detail) {
|
|
detail = Array.isArray(payload.detail)
|
|
? payload.detail.map((item) => item.msg || item).join("; ")
|
|
: payload.detail;
|
|
}
|
|
} catch (error) {
|
|
// ignore JSON parse issues
|
|
}
|
|
|
|
NotificationCenter.show({
|
|
message: detail,
|
|
level: "error",
|
|
});
|
|
|
|
const errorContainer = form.querySelector("[data-export-error]");
|
|
if (errorContainer) {
|
|
errorContainer.textContent = detail;
|
|
errorContainer.classList.remove("hidden");
|
|
}
|
|
|
|
submitBtn?.classList.remove("loading");
|
|
submitBtn?.removeAttribute("disabled");
|
|
return;
|
|
}
|
|
|
|
const blob = await response.blob();
|
|
const disposition = response.headers.get("Content-Disposition");
|
|
let filename = "export";
|
|
if (disposition) {
|
|
const match = disposition.match(/filename=([^;]+)/i);
|
|
if (match) {
|
|
filename = match[1].replace(/"/g, "");
|
|
}
|
|
}
|
|
|
|
const url = window.URL.createObjectURL(blob);
|
|
const link = document.createElement("a");
|
|
link.href = url;
|
|
link.download = filename;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
link.remove();
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
const modal = modalContainer.querySelector(".modal");
|
|
if (modal) {
|
|
closeModal(modal);
|
|
}
|
|
|
|
NotificationCenter.show({
|
|
message: `Export ready: ${filename}`,
|
|
level: "success",
|
|
});
|
|
|
|
submitBtn?.classList.remove("loading");
|
|
submitBtn?.removeAttribute("disabled");
|
|
}
|
|
|
|
document.querySelectorAll("[data-export-trigger]").forEach((button) => {
|
|
button.addEventListener("click", async (event) => {
|
|
event.preventDefault();
|
|
const dataset = button.getAttribute("data-export-target");
|
|
if (!dataset) return;
|
|
try {
|
|
await loadModal(dataset);
|
|
} catch (error) {
|
|
console.error(error);
|
|
NotificationCenter.show({
|
|
message: "Unable to open export dialog.",
|
|
level: "error",
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|