mirror of
https://github.com/calesthio/OpenMontage.git
synced 2026-08-15 21:16:38 +08:00
92 lines
3.5 KiB
JavaScript
92 lines
3.5 KiB
JavaScript
import { el, fmtAgo, getJSON, subscribe, thumbURL } from "/ui/lib.js";
|
|
|
|
const grid = document.getElementById("grid");
|
|
const THEME_KEY = "backlot.theme";
|
|
let currentTheme = localStorage.getItem(THEME_KEY) === "light" ? "light" : "dark";
|
|
|
|
function applyTheme(theme) {
|
|
currentTheme = theme === "light" ? "light" : "dark";
|
|
document.documentElement.dataset.theme = currentTheme;
|
|
localStorage.setItem(THEME_KEY, currentTheme);
|
|
}
|
|
|
|
function renderThemeToggle() {
|
|
const next = currentTheme === "light" ? "dark" : "light";
|
|
return el("button", {
|
|
class: "theme-toggle",
|
|
type: "button",
|
|
title: `Switch to ${next} theme`,
|
|
"aria-label": `Switch to ${next} theme`,
|
|
"aria-pressed": currentTheme === "light" ? "true" : "false",
|
|
onclick: () => {
|
|
applyTheme(next);
|
|
const replacement = renderThemeToggle();
|
|
document.querySelector(".theme-toggle").replaceWith(replacement);
|
|
},
|
|
}, el("span", { class: "theme-toggle-icon", "aria-hidden": "true" }, currentTheme === "light" ? "☾" : "☀"));
|
|
}
|
|
|
|
applyTheme(currentTheme);
|
|
document.getElementById("liveBadge").before(renderThemeToggle());
|
|
|
|
function miniRail(states) {
|
|
const rail = el("div", { class: "mini-rail" });
|
|
for (const s of states) {
|
|
const cls = s.status === "completed" ? "d"
|
|
: s.status === "in_progress" ? "a"
|
|
: s.status === "awaiting_human" ? "w" : "";
|
|
rail.append(el("i", { class: cls, title: `${s.name}: ${s.status}` }));
|
|
}
|
|
return rail;
|
|
}
|
|
|
|
function card(p) {
|
|
const poster = el("div", { class: "lib-poster" });
|
|
if (p.poster) {
|
|
poster.append(el("img", { src: thumbURL(p.project_id, p.poster, 640), loading: "lazy", alt: "" }));
|
|
} else {
|
|
poster.append(el("span", { class: "lp-txt" }, "NO MEDIA YET"));
|
|
}
|
|
if (p.live && p.active_stage) {
|
|
poster.append(el("span", { class: "lp-live" },
|
|
el("span", { class: "dot" }),
|
|
p.awaiting_human ? "◈ AWAITING YOU" : `LIVE · ${p.active_stage.toUpperCase()}`));
|
|
} else if (p.awaiting_human) {
|
|
poster.append(el("span", { class: "lp-live" }, "◈ AWAITING YOU"));
|
|
}
|
|
|
|
const meta = el("div", { class: "lb-meta" },
|
|
el("span", { class: "chip" }, p.pipeline_type || "unknown"),
|
|
p.scene_count ? el("span", { class: "chip" }, `${p.scene_count} scenes`) : null,
|
|
p.render_count ? el("span", { class: "chip" }, `${p.render_count} renders`) : null,
|
|
el("span", { class: "when" }, fmtAgo(p.last_activity)),
|
|
);
|
|
|
|
const staticSuffix = new URLSearchParams(location.search).has("static") ? "?static=1" : "";
|
|
return el("a", { class: `lib-card${p.live ? " live-card" : ""}`, href: `/p/${p.project_id}${staticSuffix}`, style: "text-decoration:none;color:inherit" },
|
|
poster,
|
|
el("div", { class: "lib-body" },
|
|
el("h3", {}, (p.title || p.project_id).toUpperCase()),
|
|
meta,
|
|
p.stage_states.length ? miniRail(p.stage_states) : null,
|
|
),
|
|
);
|
|
}
|
|
|
|
async function render() {
|
|
const projects = await getJSON("/api/projects");
|
|
document.getElementById("count").textContent = `${projects.length} projects`;
|
|
const liveCount = projects.filter((p) => p.live).length;
|
|
const badge = document.getElementById("liveBadge");
|
|
badge.classList.toggle("idle", liveCount === 0);
|
|
document.getElementById("liveText").textContent = liveCount ? `${liveCount} LIVE` : "IDLE";
|
|
grid.innerHTML = "";
|
|
document.getElementById("empty").style.display = projects.length ? "none" : "block";
|
|
for (const p of projects) grid.append(card(p));
|
|
}
|
|
|
|
render().catch(console.error);
|
|
if (!new URLSearchParams(location.search).has("static")) {
|
|
subscribe("/api/library/events", () => render().catch(console.error));
|
|
}
|