From 6c3ef9f57b3e1af8a6f0146faf86cb670bc87533 Mon Sep 17 00:00:00 2001 From: marvin Date: Sun, 13 Sep 2026 17:46:24 -0400 Subject: [PATCH] Fix Runtime panel reflow (broken selector after health-list rename) and light-theme chip backgrounds --- package.json | 2 +- src/public/app.js | 2 +- src/public/styles.css | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8608682..cdc2350 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "site-gateway", - "version": "0.11.54", + "version": "0.11.55", "private": true, "description": "Site Gateway: simple self-hosted website publishing, reverse proxying, and automatic HTTPS.", "type": "module", diff --git a/src/public/app.js b/src/public/app.js index ac4b443..1760170 100644 --- a/src/public/app.js +++ b/src/public/app.js @@ -498,5 +498,5 @@ document.querySelectorAll("#proxy-form,#settings-form").forEach(form => syncUpst document.addEventListener("click", event => { if (event.target.closest(".create-trigger,[data-action=edit],[data-card-action=edit]")) setTimeout(() => { syncUpstreamTlsControls(document.querySelector("#proxy-form")); syncUpstreamTlsControls(document.querySelector("#settings-form")); }, 0); }); document.addEventListener("click", event => { const trigger = event.target.closest("[data-action=settings],[data-card-action=settings]"); if (!trigger) return; setTimeout(() => { const item = (state.editing?.kind === "proxy" ? state.proxies : state.sites).find(value => value.id === state.editing?.id); if (!item) return; const scope = state.editing.kind === "proxy" ? "#settings-advanced" : "#settings-hosted-advanced"; const checkbox = document.querySelector(`${scope} [name="healthEnabled"]`); if (checkbox) checkbox.checked = !(item.healthEnabled === false || String(item.healthEnabled).toLowerCase() === "false"); }, 0); }); setInterval(() => { if (state.view !== 'access') return; const items = state.accessLists || []; const enabled = items.filter(item => item.enabled !== false).length; const disabled = items.length - enabled; $('#running-count').textContent = enabled; $('#disabled-count').textContent = disabled; $('#error-count').textContent = 0; $('#running-label').textContent = enabled ? 'Enabled' : 'None enabled'; $('#disabled-label').textContent = disabled ? 'Disabled' : 'None disabled'; $('#error-label').textContent = 'No issues'; $('#running-dot').className = `status-dot ${enabled ? 'running' : 'inactive'}`; $('#disabled-dot').className = `status-dot ${disabled ? 'disabled' : 'inactive'}`; $('#error-dot').className = 'status-dot inactive'; $('.port-note').classList.add('hidden'); }, 500); -function renderDashboardJobsSafe(system) { const columns = document.querySelector("#dashboard-view .dashboard-columns"); if (!columns) return; const health = document.querySelector("[data-dashboard-health]") || columns.querySelector(".health-list")?.closest("section"); if (health) { health.dataset.dashboardHealth = "true"; if (health.parentElement === columns) columns.parentElement.insertBefore(health, columns); } let panel = document.querySelector("#dashboard-jobs"); if (!panel) { panel = document.createElement("section"); panel.id = "dashboard-jobs"; panel.className = "dashboard-panel dashboard-jobs-panel"; columns.insertBefore(panel, columns.children[1] || null); } panel.innerHTML = `

Operations

Scheduled jobs

${(system.jobs || []).map(job => `
${escapeHtml(job.name)}${job.enabled ? `Active · ${escapeHtml(job.schedule)}` : "Disabled"}
`).join("")}
`; } +function renderDashboardJobsSafe(system) { const columns = document.querySelector("#dashboard-view .dashboard-columns"); if (!columns) return; const health = document.querySelector("[data-dashboard-health]") || document.querySelector("#health-panel"); if (health) { health.dataset.dashboardHealth = "true"; if (health.parentElement === columns) columns.parentElement.insertBefore(health, columns); } let panel = document.querySelector("#dashboard-jobs"); if (!panel) { panel = document.createElement("section"); panel.id = "dashboard-jobs"; panel.className = "dashboard-panel dashboard-jobs-panel"; columns.insertBefore(panel, columns.children[1] || null); } panel.innerHTML = `

Operations

Scheduled jobs

${(system.jobs || []).map(job => `
${escapeHtml(job.name)}${job.enabled ? `Active · ${escapeHtml(job.schedule)}` : "Disabled"}
`).join("")}
`; } document.addEventListener("submit", async event => { if (event.target?.id !== "settings-form" || state.editing?.kind !== "site") return; event.preventDefault(); event.stopImmediatePropagation(); const button = resolveSubmitter(event); button.disabled = true; const form = new FormData(event.target); try { await api(`/api/sites/${state.editing.id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ domain: form.get("domain"), domains: String(form.get("domainsText") || "").split(/[\n,]+/).map(value => value.trim()).filter(Boolean), tls: form.get("tls"), hsts: form.has("hsts"), accessListId: form.get("accessListId") || "", healthEnabled: form.has("healthEnabled"), healthPath: form.get("healthPath") || "/", healthMethod: form.get("healthMethod") || "GET", healthExpected: form.get("healthExpected") || "200-499", healthTimeoutSeconds: Number(form.get("healthTimeoutSeconds") || 4), healthRetries: Number(form.get("healthRetries") || 0), compression: form.get("compression") || "automatic", requestHeaders: parseHeaderLines(form.get("requestHeadersText")), responseHeaders: parseHeaderLines(form.get("responseHeadersText")), hstsSubdomains: form.has("hstsSubdomains"), customConfig: form.get("customConfig") || "" }) }); document.querySelector("#settings-dialog").close(); await refresh(); toast("Gateway settings applied."); } catch (error) { document.querySelector("#settings-error").textContent = error.message; } finally { button.disabled = false; } }, true); diff --git a/src/public/styles.css b/src/public/styles.css index ff18d87..3a6cb54 100644 --- a/src/public/styles.css +++ b/src/public/styles.css @@ -23,7 +23,7 @@ main{padding-top:24px}.utility-bar{display:flex;align-items:center;justify-conte /* Dashboard */ .mobile-nav{display:none}.dashboard-view{margin-top:38px}.metric-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.metric-card{min-width:0;padding:20px;border:1px solid var(--line);border-radius:15px;background:linear-gradient(145deg,rgba(20,33,54,.95),rgba(13,23,39,.95));color:var(--text);text-align:left;position:relative;overflow:hidden}.metric-card::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:var(--card-accent,var(--green));opacity:.85}.metric-card:focus{outline:none}.metric-card:focus-visible{outline:2px solid var(--green);outline-offset:-2px}.metric-card:is(button){cursor:pointer;transition:.2s}.metric-card:is(button):hover{transform:translateY(-2px);border-color:#3b5275;box-shadow:0 16px 40px rgba(0,0,0,.22)}.metric-card.accent-green{--card-accent:var(--green)}.metric-card.accent-blue{--card-accent:var(--blue)}.metric-card .metric-label,.metric-card>span:last-child{display:block}.metric-card .metric-label{color:var(--muted);font-size:.78rem;font-weight:700}.metric-card .metric-icon{position:absolute;top:16px;right:16px;width:32px;height:32px;display:grid;place-items:center;border-radius:9px;background:color-mix(in srgb,var(--card-accent,var(--muted)) 20%,transparent);color:var(--card-accent,var(--muted));font-size:.9rem;font-weight:800}.metric-card strong{display:block;margin:13px 0 7px;font-size:2rem;line-height:1}.metric-card>span:last-child{color:var(--muted);font-size:.76rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metric-card.attention strong{color:var(--warning)}.metric-strip{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:12px}.metric-chip{display:flex;align-items:center;gap:12px;min-width:0;padding:13px 16px;border:1px solid var(--line);border-radius:13px;background:rgba(16,26,43,.76);color:var(--text);text-align:left;position:relative;overflow:hidden;transition:.2s}.metric-chip::before{content:"";position:absolute;inset:0 auto 0 0;width:3px;background:var(--card-accent,var(--muted));opacity:.9}.metric-chip:is(button){cursor:pointer}.metric-chip:is(button):hover{transform:translateY(-1px);border-color:#3b5275}.metric-chip:focus{outline:none}.metric-chip:focus-visible{outline:2px solid var(--green);outline-offset:-2px}.metric-chip .chip-icon{flex:0 0 auto;width:32px;height:32px;display:grid;place-items:center;border-radius:9px;background:color-mix(in srgb,var(--card-accent,var(--muted)) 20%,transparent);color:var(--card-accent,var(--muted));font-size:.85rem;font-weight:800}.metric-chip .chip-copy{display:flex;flex-direction:column;gap:2px;min-width:0}.metric-chip .metric-label{color:var(--muted);font-size:.72rem;font-weight:700}.metric-chip strong{font-size:1.3rem;line-height:1.1}.metric-chip small{color:var(--muted);font-size:.68rem}.metric-chip.accent-amber{--card-accent:var(--warning)}.metric-chip.accent-purple{--card-accent:#b59cff}.metric-chip.accent-warning{--card-accent:var(--warning)}.metric-chip.accent-warning strong{color:var(--warning)}.metric-chip.accent-green{--card-accent:var(--green)}.metric-chip.accent-green strong{color:var(--green)}.dashboard-columns{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px}.dashboard-columns.lower{align-items:start}.dashboard-panel{min-width:0;padding:22px;border:1px solid var(--line);border-radius:16px;background:rgba(16,26,43,.76)}.panel-heading{display:flex;align-items:center;justify-content:space-between;gap:15px;margin-bottom:20px}.panel-heading .eyebrow{margin-bottom:5px}.panel-heading h2{margin:0;font-size:1.2rem}.health-badge{padding:6px 9px;border-radius:999px;font-size:.7rem;font-weight:800}.health-badge.healthy{background:rgba(98,230,167,.12);color:var(--green)}.health-badge.warning{background:rgba(255,191,105,.12);color:var(--warning)}.health-badge.error{background:rgba(255,113,133,.12);color:var(--danger)}.health-panel{position:relative;overflow:hidden}.health-panel::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;opacity:.9;transition:background-color .3s ease}.health-panel.status-healthy::before{background:var(--green)}.health-panel.status-warning::before{background:var(--warning)}.health-panel.status-error::before{background:var(--danger)}.health-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.health-tile{display:flex;align-items:center;gap:12px;min-width:0;padding:13px 14px;border:1px solid var(--line);border-radius:12px;background:rgba(8,16,29,.28);transition:.2s}.health-tile .status-dot{flex:0 0 auto}.health-tile-copy{display:grid;gap:3px;min-width:0}.health-tile-copy strong{font-size:.82rem}.health-tile-copy small{color:var(--muted);font-size:.72rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dashboard-list-item span:last-child{display:grid;gap:3px}.dashboard-list-item small{color:var(--muted);font-size:.75rem}.live-dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--green);margin-right:7px;vertical-align:middle;box-shadow:0 0 0 0 rgba(98,230,167,.6);animation:live-pulse 2.2s ease-in-out infinite}.live-dot.checking{background:var(--warning);animation-duration:.9s}@keyframes live-pulse{0%{box-shadow:0 0 0 0 rgba(98,230,167,.5)}70%{box-shadow:0 0 0 6px rgba(98,230,167,0)}100%{box-shadow:0 0 0 0 rgba(98,230,167,0)}}.system-panel{position:relative;overflow:hidden}.system-panel::before{content:"";position:absolute;inset:0 0 auto 0;height:3px;background:var(--blue);opacity:.85}.system-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0}.system-tile{min-width:0;padding:13px 14px;border:1px solid var(--line);border-radius:12px;background:rgba(8,16,29,.28)}.system-grid dt{color:var(--muted);font-size:.72rem}.system-grid dd{margin:6px 0 0;font-size:.9rem;font-weight:750;overflow:hidden;text-overflow:ellipsis}.dashboard-list{display:grid}.dashboard-list-item{display:flex;align-items:flex-start;gap:12px;padding:13px 3px;border-top:1px solid var(--line)}.dashboard-list-item:first-child{border-top:0}.dashboard-list-item strong{font-size:.82rem}.dashboard-list-item .status-dot{margin-top:4px;flex:0 0 auto}.activity-mark{display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:rgba(98,230,167,.12);color:var(--green);font-size:.7rem;font-weight:900}.quiet-state{color:var(--muted);font-size:.82rem;margin:3px 0} -:root[data-theme="light"] .metric-card{background:linear-gradient(145deg,#fff,#f6f9fc)}:root[data-theme="light"] .dashboard-panel{background:rgba(255,255,255,.82)}:root[data-theme="light"] .health-tile,:root[data-theme="light"] .system-tile{background:#f6f9fc} +:root[data-theme="light"] .metric-card{background:linear-gradient(145deg,#fff,#f6f9fc)}:root[data-theme="light"] .metric-chip{background:#f6f9fc}:root[data-theme="light"] .dashboard-panel{background:rgba(255,255,255,.82)}:root[data-theme="light"] .health-tile,:root[data-theme="light"] .system-tile{background:#f6f9fc} @media(max-width:1100px){.metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.system-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:1100px){.metric-strip{grid-template-columns:repeat(2,minmax(0,1fr))}} @media(max-width:760px){.mobile-nav{display:grid;grid-template-columns:repeat(5,1fr);gap:5px;margin:0 0 30px;padding:4px;border:1px solid var(--line);border-radius:12px;background:var(--panel)}.mobile-nav button{justify-content:center;text-align:center;padding:9px 5px;font-size:.72rem}.dashboard-view{margin-top:30px}.metric-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.metric-card{padding:16px}.metric-card strong{font-size:1.65rem}.dashboard-columns{grid-template-columns:1fr}.system-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.metric-strip{grid-template-columns:1fr}.metric-chip{padding:11px 14px}}