(() => {
const operationCard = document.querySelector("[data-operation-url]");
if (operationCard) {
const stageNode = document.getElementById("operation-stage");
const detailNode = document.getElementById("operation-detail");
const errorNode = document.getElementById("operation-error");
const logNode = document.getElementById("operation-log");
const statusUrl = operationCard.dataset.operationUrl;
const successUrl = operationCard.dataset.operationSuccess;
const poll = async () => {
const response = await fetch(statusUrl, { headers: { Accept: "application/json" } });
if (!response.ok) {
return;
}
const payload = await response.json();
const op = payload.operation || {};
if (stageNode) stageNode.textContent = op.stage || "queued";
if (detailNode) detailNode.textContent = op.detail || "";
if (errorNode) errorNode.textContent = op.error || "";
if (logNode && op.build_log_path) logNode.textContent = op.build_log_path;
if (op.done && op.success && successUrl) {
window.location.assign(successUrl);
return;
}
if (!op.done) {
window.setTimeout(poll, 1000);
}
};
window.setTimeout(poll, 800);
}
const copyButtons = document.querySelectorAll("[data-copy-text]");
copyButtons.forEach((button) => {
button.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(button.dataset.copyText || "");
button.textContent = "Copied";
window.setTimeout(() => { button.textContent = "Copy"; }, 1000);
} catch (_) {}
});
});
document.querySelectorAll("form[data-confirm]").forEach((form) => {
form.addEventListener("submit", (event) => {
const message = form.dataset.confirm || "Are you sure?";
if (!window.confirm(message)) {
event.preventDefault();
}
});
});
const logToggle = document.getElementById("log-auto-refresh");
if (logToggle) {
const schedule = () => {
if (!logToggle.checked) return;
window.setTimeout(() => {
if (logToggle.checked) {
window.location.reload();
}
}, 4000);
};
logToggle.addEventListener("change", schedule);
schedule();
}
const dialog = document.getElementById("path-picker");
if (!dialog) return;
const listNode = document.getElementById("picker-list");
const currentPathNode = document.getElementById("picker-current-path");
const closeButton = document.getElementById("picker-close");
const selectCurrentButton = document.getElementById("picker-select-current");
let currentInput = null;
let currentKind = "file";
let currentPath = "/";
const loadListing = async (path) => {
const response = await fetch(`/api/fs?path=${encodeURIComponent(path)}&kind=${encodeURIComponent(currentKind)}`, {
headers: { Accept: "application/json" }
});
if (!response.ok) return;
const payload = await response.json();
currentPath = payload.path;
currentPathNode.textContent = payload.path;
listNode.innerHTML = "";
payload.entries.forEach((entry) => {
const button = document.createElement("button");
button.type = "button";
button.className = "picker-entry";
button.dataset.kind = entry.kind;
button.dataset.path = entry.path;
button.innerHTML = `${entry.name}${entry.kind}`;
button.addEventListener("click", () => {
if (entry.kind === "dir" || entry.kind === "up") {
loadListing(entry.path);
return;
}
if (currentInput) {
currentInput.value = entry.path;
dialog.close();
}
});
listNode.appendChild(button);
});
};
document.querySelectorAll("[data-picker-target]").forEach((button) => {
button.addEventListener("click", () => {
const fieldName = button.dataset.pickerTarget;
currentKind = button.dataset.pickerKind || "file";
currentInput = document.querySelector(`input[name="${fieldName}"]`);
if (!currentInput) return;
const initialPath = currentInput.value || "/";
dialog.showModal();
loadListing(initialPath);
});
});
document.querySelectorAll("[data-picker-root]").forEach((button) => {
button.addEventListener("click", () => loadListing(button.dataset.pickerRoot || "/"));
});
closeButton.addEventListener("click", () => dialog.close());
selectCurrentButton.addEventListener("click", () => {
if (!currentInput) return;
currentInput.value = currentPath;
dialog.close();
});
})();