Spaces:
Running
Running
Download app/static/app.js from Extrian/data-experiments: direct link, hf CLI and curl.
- Browser
- Download file 14.5 kB
-
https://huggingface.co/spaces/Extrian/data-experiments/resolve/main/app/static/app.js
- Command line
-
hf download hf://spaces/Extrian/data-experiments/app/static/app.js
-
curl -L -o app.js https://huggingface.co/spaces/Extrian/data-experiments/resolve/main/app/static/app.js
14.5 kB
| // Data Experiments page: rows, guides and SFT marks come from /api/* (the Space's server reading R2; every route needs | |
| // a signed-in, allow-listed viewer). The page polls every 60 s and on focus, so session writes show up within a minute. | |
| ; | |
| const STATUSES = [ | |
| ["prod_running", "Prod running"], ["prod_paused", "Prod paused"], ["pilot_ready", "Pilot ready"], ["building", "Building"], | |
| ["prod_done", "Prod done"]]; | |
| const LABEL = Object.fromEntries(STATUSES); | |
| const HINT = { | |
| prod_running: "Full-size generation is running now.", | |
| prod_paused: "Stopped before reaching its target; what it made so far is usable.", | |
| pilot_ready: "A small sample is ready to listen to and judge before scaling up.", | |
| building: "Code or scripts are being written; nothing to review yet.", | |
| prod_done: "Finished; the final data is ready to use.", | |
| sft: "Someone has marked it as already used in a training run." }; | |
| const $ = (id) => document.getElementById(id); | |
| const el = (tag, cls, text) => { const e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; }; | |
| let projects = [], docs = {}, sft = {}, me = null, filter = null, query = ""; | |
| let sftEditing = null, sftDraft = "", sftFocus = false, sftError = {}, loadedOnce = false; | |
| const docCache = {}; | |
| try { filter = localStorage.getItem("dx-filter") || null; } catch (e) {} | |
| function ago(iso) { | |
| const t = Date.parse(iso); if (!t) return ""; | |
| const m = Math.round((Date.now() - t) / 60000); | |
| if (m < 60) return m <= 1 ? "just now" : m + " min ago"; | |
| const h = Math.round(m / 60); if (h < 48) return h + " h ago"; | |
| return Math.round(h / 24) + " days ago"; | |
| } | |
| const num = (x) => typeof x === "number" ? x.toLocaleString("en-US", { maximumFractionDigits: 1 }) : String(x ?? ""); | |
| function copyBtn(text) { | |
| const b = el("button", null, "Copy"); b.type = "button"; | |
| b.addEventListener("click", async () => { | |
| try { await navigator.clipboard.writeText(text); b.textContent = "Copied"; } | |
| catch (e) { const r = document.createRange(); r.selectNodeContents(b.previousSibling); const s = getSelection(); s.removeAllRanges(); s.addRange(r); b.textContent = "Selected"; } | |
| setTimeout(() => (b.textContent = "Copy"), 1400); | |
| }); | |
| return b; | |
| } | |
| // Guides are written by sessions, so their markdown is untrusted: raw HTML in it is shown as text (never | |
| // parsed), and the rendered result still goes through DOMPurify. | |
| const escapeHtml = (s) => String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); | |
| if (window.marked) marked.use({ renderer: { html: (html) => escapeHtml(typeof html === "string" ? html : (html && html.text) || "") } }); | |
| function renderMarkdown(body, md) { | |
| if (window.marked && window.DOMPurify) { | |
| body.innerHTML = DOMPurify.sanitize(marked.parse(String(md)), { FORBID_TAGS: ["style", "form", "input", "iframe"] }); | |
| body.querySelectorAll("a[href]").forEach((a) => { | |
| if (!/^https?:\/\//i.test(a.getAttribute("href") || "")) { a.removeAttribute("href"); return; } | |
| a.target = "_blank"; a.rel = "noopener noreferrer"; | |
| }); | |
| } else { const pre = el("pre"); pre.textContent = String(md); body.append(pre); } | |
| } | |
| async function openDoc(id) { | |
| const meta = docs[id]; | |
| $("rtitle").textContent = meta ? (meta.title || id) : id; | |
| $("rpath").textContent = meta && meta.path ? meta.path : ""; | |
| const body = $("rbody"); body.textContent = ""; | |
| $("reader").hidden = false; body.scrollTop = 0; $("rclose").focus(); | |
| if (!meta) { body.append(el("p", null, "This guide hasn't been added to the page yet.")); return; } | |
| if (!meta.has_markdown) { body.append(el("p", null, "Only the file path is recorded for this guide. Open it in the repo: " + (meta.path || ""))); return; } | |
| body.append(el("p", "lede", "Loading…")); | |
| try { | |
| let d = docCache[id]; | |
| if (!d || d.updated_at !== meta.updated_at) { | |
| const r = await fetch("/api/doc/" + encodeURIComponent(id), { credentials: "same-origin", cache: "no-store" }); | |
| if (!r.ok) throw new Error(r.status); | |
| d = docCache[id] = await r.json(); | |
| } | |
| body.textContent = ""; renderMarkdown(body, d.markdown || ""); | |
| } catch (e) { body.textContent = ""; body.append(el("p", null, "Couldn't load this guide. Reload the page (your sign-in may have expired).")); } | |
| } | |
| $("rclose").addEventListener("click", () => ($("reader").hidden = true)); | |
| $("reader").addEventListener("click", (e) => { if (e.target === $("reader")) $("reader").hidden = true; }); | |
| document.addEventListener("keydown", (e) => { if (e.key === "Escape") $("reader").hidden = true; }); | |
| async function saveSft(id, done, note) { | |
| sftError[id] = ""; | |
| try { | |
| const r = await fetch("/api/sft/" + encodeURIComponent(id), { | |
| method: done ? "POST" : "DELETE", credentials: "same-origin", cache: "no-store", | |
| headers: { "Content-Type": "application/json", "X-Dashboard": "1" }, | |
| body: done ? JSON.stringify({ note: note.slice(0, 300) }) : undefined }); | |
| if (!r.ok) throw new Error(r.status); | |
| sft[id] = await r.json(); | |
| sftEditing = null; sftDraft = ""; | |
| } catch (e) { sftError[id] = "Couldn't save the mark. Reload the page (your sign-in may have expired) and try again."; } | |
| render(); | |
| } | |
| function sftRow(p) { | |
| const m = sft[p.id]; const row = el("div", "sftrow"); | |
| const editable = !!me; | |
| if (m && m.done) { | |
| row.append(el("span", "sftbadge", "SFT done")); | |
| const who = [m.by || "", m.at ? ago(m.at) : ""].filter(Boolean).join(" · "); | |
| if (who) row.append(el("span", "who", who)); | |
| if (editable) { const u = el("button", null, "Undo"); u.type = "button"; u.setAttribute("aria-label", "Undo SFT done for " + (p.title || p.id)); u.addEventListener("click", () => saveSft(p.id, false, "")); row.append(u); } | |
| if (m.note) row.append(el("span", "sftnote", m.note)); | |
| } else if (editable && sftEditing === p.id) { | |
| const inp = el("input"); inp.id = "sft-note-" + p.id; inp.placeholder = "Note (optional): run name or result"; inp.maxLength = 300; inp.value = sftDraft; | |
| inp.setAttribute("aria-label", "SFT note for " + (p.title || p.id)); | |
| inp.addEventListener("input", (e) => { sftDraft = e.target.value; }); | |
| const ok = el("button", null, "Save"); ok.type = "button"; ok.addEventListener("click", () => saveSft(p.id, true, inp.value.trim())); | |
| const no = el("button", null, "Cancel"); no.type = "button"; no.addEventListener("click", () => { sftEditing = null; sftDraft = ""; render(); }); | |
| inp.addEventListener("keydown", (e) => { if (e.key === "Enter") ok.click(); if (e.key === "Escape") no.click(); }); | |
| row.append(inp, ok, no); | |
| if (sftFocus) { sftFocus = false; setTimeout(() => inp.focus(), 0); } | |
| } else if (editable) { | |
| const b = el("button", null, "Mark SFT done"); b.type = "button"; b.setAttribute("aria-label", "Mark SFT done for " + (p.title || p.id)); | |
| b.addEventListener("click", () => { sftEditing = p.id; sftDraft = ""; sftFocus = true; render(); }); row.append(b); | |
| } | |
| if (sftError[p.id]) row.append(el("span", "err", sftError[p.id])); | |
| return row.childNodes.length ? row : null; | |
| } | |
| function card(p) { | |
| const c = el("article", "card"); c.id = "p-" + p.id; | |
| const top = el("div", "top"); | |
| top.append(el("h3", null, p.title || p.id)); | |
| const pill = el("span", "pill " + (p.status || "")); pill.append(el("span", "dot"), document.createTextNode(LABEL[p.status] || p.status || "Unknown")); | |
| top.append(pill); c.append(top); | |
| if (p.description) c.append(el("p", "desc", p.description)); | |
| if (p.data_type) c.append(el("p", "type", p.data_type)); | |
| if (p.progress && p.progress.target) { | |
| const pr = el("div", "prog"); const tr = el("div", "track"); const f = el("div", "fill"); | |
| f.style.width = Math.max(0, Math.min(100, 100 * (p.progress.done || 0) / p.progress.target)) + "%"; tr.append(f); | |
| pr.append(tr, el("span", "lbl", `${num(p.progress.done)} / ${num(p.progress.target)} ${p.progress.unit || ""}`.trim())); | |
| c.append(pr); | |
| } | |
| if (p.size) c.append(el("div", "size", p.size)); | |
| if (p.summary) c.append(el("p", null, p.summary)); | |
| const links = el("div", "links"); | |
| for (const l of p.links || []) { | |
| if (!l || !l.url || !/^https:\/\//.test(l.url)) continue; | |
| const a = el("a", null, l.label || "Open"); a.href = l.url; a.target = "_blank"; a.rel = "noopener noreferrer"; links.append(a); | |
| } | |
| for (const id of p.docs || []) { | |
| const b = el("button", null, (docs[id] && docs[id].title) ? docs[id].title : id); b.type = "button"; | |
| b.addEventListener("click", () => openDoc(id)); links.append(b); | |
| } | |
| if (links.childNodes.length) c.append(links); | |
| if (p.data_location) { const loc = el("div", "loc"); loc.append(el("code", null, p.data_location), copyBtn(p.data_location)); c.append(loc); } | |
| const kv = el("dl", "kv"); | |
| for (const [k, v] of [["Next", p.next_step], ["Code", p.code]]) { if (v) { kv.append(el("dt", null, k), el("dd", null, v)); } } | |
| if (kv.childNodes.length) c.append(kv); | |
| const sr = sftRow(p); if (sr) c.append(sr); | |
| const foot = [p.updated_at ? "Updated " + ago(p.updated_at) : "", p.updated_by ? "by " + p.updated_by : ""].filter(Boolean).join(" "); | |
| if (foot) c.append(el("div", "foot", foot)); | |
| return c; | |
| } | |
| function render() { | |
| const counts = Object.fromEntries(STATUSES.map(([k]) => [k, 0])); | |
| projects.forEach((p) => { if (p.status in counts) counts[p.status]++; }); | |
| const strip = $("strip"); strip.textContent = ""; | |
| for (const [k, label] of STATUSES) { | |
| const b = el("button", "stat " + k); b.type = "button"; b.setAttribute("aria-pressed", String(filter === k)); | |
| b.append(el("b", null, String(counts[k])), el("span", null, label), el("small", null, HINT[k])); | |
| b.addEventListener("click", () => { filter = filter === k ? null : k; try { filter ? localStorage.setItem("dx-filter", filter) : localStorage.removeItem("dx-filter"); } catch (e) {} render(); }); | |
| strip.append(b); | |
| } | |
| const nSft = projects.filter((p) => sft[p.id] && sft[p.id].done).length; | |
| const sb = el("button", "stat sft"); sb.type = "button"; sb.setAttribute("aria-pressed", String(filter === "sft")); | |
| sb.append(el("b", null, String(nSft)), el("span", null, "SFT done"), el("small", null, HINT.sft)); | |
| sb.addEventListener("click", () => { filter = filter === "sft" ? null : "sft"; try { filter ? localStorage.setItem("dx-filter", filter) : localStorage.removeItem("dx-filter"); } catch (e) {} render(); }); | |
| strip.append(sb); | |
| const q = query.trim().toLowerCase(); | |
| const inFilter = (p) => !filter || (filter === "sft" ? !!(sft[p.id] && sft[p.id].done) : p.status === filter); | |
| const match = (p) => inFilter(p) && (!q || [p.title, p.description, p.data_type, p.summary, p.data_location, p.size, p.group] | |
| .filter(Boolean).join(" ").toLowerCase().includes(q)); | |
| const host = $("sections"); host.textContent = ""; | |
| let shown = 0; | |
| for (const [k, label] of STATUSES) { | |
| const rows = projects.filter((p) => p.status === k && match(p)).sort((a, b) => (b.updated_at || "").localeCompare(a.updated_at || "")); | |
| if (!rows.length) continue; | |
| shown += rows.length; | |
| const s = el("section"); const h = el("h2"); const pill = el("span", "pill " + k); pill.append(el("span", "dot"), document.createTextNode(label)); | |
| h.append(pill, el("span", "count", rows.length + (rows.length === 1 ? " project" : " projects"))); s.append(h); | |
| const g = el("div", "grid"); rows.forEach((p) => g.append(card(p))); s.append(g); host.append(s); | |
| } | |
| const other = projects.filter((p) => !(p.status in counts) && match(p)); | |
| if (other.length) { const s = el("section"); s.append(el("h2", null, "Other")); const g = el("div", "grid"); other.forEach((p) => g.append(card(p))); s.append(g); host.append(s); shown += other.length; } | |
| if (!shown) host.append(el("div", "empty", projects.length ? (filter === "sft" ? "No project is marked SFT done yet." : "No project matches this filter.") : (loadedOnce ? "No projects yet. Each session adds its own row; see the instructions below." : "Loading…"))); | |
| } | |
| $("q").addEventListener("input", (e) => { query = e.target.value; render(); }); | |
| // Signed out (401) or not on the access list (403): show the sign-in card instead of the projects. Inside the | |
| // huggingface.co iframe the browser blocks the sign-in cookie, so the button opens the dashboard in its own tab. | |
| const framed = (() => { try { return window.top !== window.self; } catch (e) { return true; } })(); | |
| function showGate(status, body) { | |
| $("gate").hidden = false; $("strip").hidden = true; $("sections").hidden = true; | |
| document.querySelector(".bar").hidden = true; | |
| const a = $("signin"); | |
| if (framed) { a.href = location.origin + "/"; a.target = "_blank"; a.rel = "noopener"; a.textContent = "Open the dashboard in its own tab"; | |
| $("gtext").textContent = "Signing in doesn't work inside this embedded view. Open the dashboard in its own tab, then sign in with Hugging Face."; } | |
| if (status === 403) { | |
| $("gtitle").textContent = "You're signed in, but not on the access list"; | |
| $("gtext").textContent = "Signed in as " + ((body && body.who) || "an unlisted account") + ". Ask the dashboard owner to add your email or Hugging Face username, then sign in again."; | |
| $("signout").hidden = false; | |
| } | |
| } | |
| async function load() { | |
| try { | |
| const r = await fetch("/api/data", { credentials: "same-origin", cache: "no-store" }); | |
| if (r.status === 401 || r.status === 403) { showGate(r.status, await r.json().catch(() => null)); return; } | |
| if (!r.ok) throw new Error(r.status); | |
| const d = await r.json(); | |
| projects = Object.entries(d.projects || {}).map(([id, p]) => Object.assign({ id }, p)); | |
| docs = d.docs || {}; sft = d.sft || {}; me = d.me || null; loadedOnce = true; | |
| $("me").textContent = me ? "Signed in as " + me : ""; $("signout").hidden = !me; | |
| $("gate").hidden = true; $("strip").hidden = false; $("sections").hidden = false; document.querySelector(".bar").hidden = false; | |
| $("status").textContent = projects.length + " projects · refreshed " + new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); | |
| } catch (e) { | |
| $("status").textContent = loadedOnce ? "Couldn't refresh. Reload the page if this persists (your sign-in may have expired)." | |
| : "Couldn't load projects. Reload the page to sign in again."; | |
| } | |
| if (!sftEditing) render(); | |
| } | |
| load(); | |
| setInterval(() => { if (!document.hidden) load(); }, 60000); | |
| document.addEventListener("visibilitychange", () => { if (!document.hidden) load(); }); | |
| render(); | |