TaskCLIP / webui /static /main.js
HanningChen
Initial HF Space: FastAPI + HTML (no weights yet)
f2f112a
raw
history blame
4.94 kB
window.addEventListener("error", (e) => {
const log = document.querySelector("#statusLog");
if (log) log.textContent = "JS error: " + (e.message || e.error) + "\n" + log.textContent;
});
const $ = (sel) => document.querySelector(sel);
const form = $("#runForm");
const runBtn = $("#runBtn");
const runBtnText = $("#runBtnText");
const spinner = $("#spinner");
const resetBtn = $("#resetBtn");
const fileInput = $("#fileInput");
const dropzone = $("#dropzone");
const fileMeta = $("#fileMeta");
const previewWrap = $("#previewWrap");
const previewImg = $("#previewImg");
const statusDot = $("#statusDot");
const statusText = $("#statusText");
const statusLog = $("#statusLog");
const jobPill = $("#jobPill");
const imgInput = $("#imgInput");
const imgYolo = $("#imgYolo");
const imgSelected = $("#imgSelected");
const meta = $("#meta");
const dlInput = $("#dlInput");
const dlYolo = $("#dlYolo");
const dlSelected = $("#dlSelected");
const copyMetaBtn = $("#copyMetaBtn");
function setStatus(kind, text, logLine) {
// kind: idle | run | ok | bad
statusDot.className = `dot ${kind}`;
statusText.textContent = text;
if (logLine) statusLog.textContent = logLine + "\n" + statusLog.textContent;
}
function setRunning(isRunning) {
runBtn.disabled = isRunning;
spinner.classList.toggle("hidden", !isRunning);
runBtnText.textContent = isRunning ? "Running…" : "Run";
}
function clearResults() {
imgInput.removeAttribute("src");
imgYolo.removeAttribute("src");
imgSelected.removeAttribute("src");
meta.textContent = "";
jobPill.textContent = "job: —";
[dlInput, dlYolo, dlSelected].forEach(a => {
a.classList.add("hidden");
a.removeAttribute("href");
});
}
function setPreview(file) {
if (!file) {
previewWrap.classList.add("hidden");
previewImg.removeAttribute("src");
fileMeta.textContent = "No file selected";
return;
}
fileMeta.textContent = `${file.name}${(file.size / 1024).toFixed(1)} KB`;
const url = URL.createObjectURL(file);
previewImg.src = url;
previewWrap.classList.remove("hidden");
}
dropzone.addEventListener("click", () => fileInput.click());
dropzone.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") fileInput.click();
});
fileInput.addEventListener("change", () => {
const file = fileInput.files && fileInput.files[0];
setPreview(file);
});
["dragenter", "dragover"].forEach(evt => {
dropzone.addEventListener(evt, (e) => {
e.preventDefault();
e.stopPropagation();
dropzone.classList.add("drag");
});
});
["dragleave", "drop"].forEach(evt => {
dropzone.addEventListener(evt, (e) => {
e.preventDefault();
e.stopPropagation();
dropzone.classList.remove("drag");
});
});
dropzone.addEventListener("drop", (e) => {
const file = e.dataTransfer.files && e.dataTransfer.files[0];
if (!file) return;
// Set preview
setPreview(file);
// Safely assign to input (works across browsers)
const dt = new DataTransfer();
dt.items.add(file);
fileInput.files = dt.files;
});
resetBtn.addEventListener("click", () => {
form.reset();
fileInput.value = "";
setPreview(null);
clearResults();
statusLog.textContent = "Waiting for input…";
setStatus("idle", "Idle", "Reset UI.");
});
copyMetaBtn.addEventListener("click", async () => {
const text = meta.textContent || "";
if (!text) return;
await navigator.clipboard.writeText(text);
setStatus("ok", "Done", "Copied metadata to clipboard.");
});
form.addEventListener("submit", async (e) => {
e.preventDefault();
const file = fileInput.files && fileInput.files[0];
if (!file) {
setStatus("bad", "Error", "No file selected.");
return;
}
setRunning(true);
setStatus("run", "Running", "Submitting request to /api/run …");
const fd = new FormData(form);
try {
const resp = await fetch("/api/run", { method: "POST", body: fd });
const data = await resp.json();
if (!resp.ok || !data.ok) {
throw new Error(data?.error || `HTTP ${resp.status}`);
}
jobPill.textContent = `job: ${data.job_id}`;
setStatus("ok", "Done", `Inference finished. job_id=${data.job_id}`);
// Update images (cache-bust)
const bust = `t=${Date.now()}`;
imgInput.src = `${data.image_urls.input}?${bust}`;
imgYolo.src = `${data.image_urls.yolo}?${bust}`;
imgSelected.src = `${data.image_urls.selected}?${bust}`;
// Open links
dlInput.href = data.image_urls.input;
dlYolo.href = data.image_urls.yolo;
dlSelected.href = data.image_urls.selected;
[dlInput, dlYolo, dlSelected].forEach(a => a.classList.remove("hidden"));
// Meta
meta.textContent = JSON.stringify({
task_id: data.task_id,
task_name: data.task_name,
selected_indices: data.selected_indices,
job_id: data.job_id,
}, null, 2);
} catch (err) {
setStatus("bad", "Error", String(err));
} finally {
setRunning(false);
}
});