// app.js — entry point. Routes hash changes to view renderers, keeps // the top-nav active state in sync, and re-renders chrome strings when // the locale changes. import { onRoute } from "./state.js?v=recurring-jobs-5"; import { t, currentLocale, setLocale, onLocale } from "./i18n.js?v=recurring-jobs-5"; import { renderRemotes } from "./views/remotes.js?v=recurring-jobs-5"; import { renderBrowse } from "./views/browser.js?v=recurring-jobs-5"; import { renderJobs, renderNewJob, stopJobPolling } from "./views/jobs.js?v=recurring-jobs-5"; import { renderConfigureNew, renderConfigureEdit, } from "./views/configure.js?v=recurring-jobs-5"; const views = { remotes: renderRemotes, browse: renderBrowse, jobs: renderJobs, "jobs-new": renderNewJob, "configure-new": renderConfigureNew, "configure-edit": renderConfigureEdit, }; let currentRoute = { name: "remotes", params: {} }; function setActiveNav(routeName) { const links = document.querySelectorAll("#nav-links a"); for (const a of links) { const target = a.dataset.route; let isActive = target === routeName; if (target === "configure" && routeName.startsWith("configure-")) { isActive = true; } a.classList.toggle("active", isActive); } } function applyChromeStrings() { // nav links document.querySelectorAll("#nav-links a").forEach((a) => { const key = a.dataset.route === "configure" ? "nav.configure" : `nav.${a.dataset.route}`; a.textContent = t(key); }); const newJobBtn = document.querySelector(".nav-new-job"); if (newJobBtn) newJobBtn.textContent = t("nav.new_job"); const lt = document.getElementById("loading-title"); if (lt) lt.textContent = t("loading.title"); const lb = document.getElementById("loading-body"); if (lb) lb.innerHTML = t("loading.connecting"); // Anything with data-i18n attribute (footer) document.querySelectorAll("[data-i18n]").forEach((el) => { el.textContent = t(el.dataset.i18n); }); // lang buttons const locale = currentLocale(); document.querySelectorAll(".lang-btn").forEach((btn) => { btn.classList.toggle("active", btn.dataset.lang === locale); }); } function wireLangSwitcher() { document.querySelectorAll(".lang-btn").forEach((btn) => { btn.addEventListener("click", () => setLocale(btn.dataset.lang)); }); } onRoute((route) => { currentRoute = route; setActiveNav(route.name); if (route.name !== "jobs") { stopJobPolling(); } const renderer = views[route.name] || renderRemotes; renderer(route.params).catch((e) => { console.error("view error", e); const app = document.getElementById("app"); if (app) { app.innerHTML = `
${escapeHtml(e.message)}