ci/woodpecker/push/tests Pipeline was successful
Expose /jobs, /dedup, and /events routes backed by a new EventBus that broadcasts job lifecycle and per-job progress over SSE. Serve a static dashboard from front/ that lists pending and in-progress jobs, streams agent activity, and shows completed reviews. Also add migrate-apply/migrate-generate scripts that load .env, update the Containerfile to ship the front assets and use the apply script, and refresh the roadmap.
60 lines
1.9 KiB
JavaScript
60 lines
1.9 KiB
JavaScript
// Bascule de thème, identique à celle du site public (même clé localStorage,
|
|
// même rendu), empaquetée en web component.
|
|
|
|
const STORAGE_KEY = "steep-theme";
|
|
|
|
export function currentTheme() {
|
|
return document.documentElement.dataset.theme === "light" ? "light" : "dark";
|
|
}
|
|
|
|
export function applyTheme(theme, persist = true) {
|
|
document.documentElement.dataset.theme = theme;
|
|
|
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
if (meta) meta.content = theme === "dark" ? "#0b1520" : "#f7f8f5";
|
|
|
|
if (persist) {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, theme);
|
|
} catch (_) {
|
|
// stockage indisponible : on garde juste le thème en mémoire.
|
|
}
|
|
}
|
|
|
|
window.dispatchEvent(new CustomEvent("steep:theme", { detail: theme }));
|
|
}
|
|
|
|
class ThemeToggle extends HTMLElement {
|
|
connectedCallback() {
|
|
this.innerHTML = `
|
|
<button class="theme-toggle" type="button" role="switch" aria-label="Toggle color theme">
|
|
<span class="theme-icon" aria-hidden="true"></span><span class="theme-label"></span>
|
|
</button>`;
|
|
|
|
this._button = this.querySelector("button");
|
|
this._icon = this.querySelector(".theme-icon");
|
|
this._label = this.querySelector(".theme-label");
|
|
this._onTheme = () => this.render();
|
|
|
|
this._button.addEventListener("click", () => {
|
|
applyTheme(currentTheme() === "dark" ? "light" : "dark");
|
|
});
|
|
window.addEventListener("steep:theme", this._onTheme);
|
|
|
|
this.render();
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
window.removeEventListener("steep:theme", this._onTheme);
|
|
}
|
|
|
|
render() {
|
|
const theme = currentTheme();
|
|
this._icon.textContent = theme === "dark" ? "☾" : "☀";
|
|
this._label.textContent = theme === "dark" ? "Dark theme" : "Light theme";
|
|
this._button.setAttribute("aria-checked", String(theme === "dark"));
|
|
}
|
|
}
|
|
|
|
customElements.define("steep-theme-toggle", ThemeToggle);
|