settings-site: phase 2 correctness fixes (proxy helper, /healthz, datetime-local min, health polling)

This commit is contained in:
2026-04-18 16:32:37 +00:00
parent 84c7a50cc3
commit 3e2bf919e9
2 changed files with 99 additions and 26 deletions

View File

@@ -224,7 +224,7 @@ async function saveConfig(mode) {
});
showToast('Restart initiated.', 'warning');
} else if (mode === 'restart' && hasErrors) {
showToast('Restart cancelled due to save errors.', 'warning');
showToast(`Restart cancelled — save returned errors: ${data.errors.join(', ')}`, 'warning');
}
} catch (e) {
showToast('Failed to save. Bot may be unreachable.', 'error');
@@ -233,11 +233,16 @@ async function saveConfig(mode) {
}
}
function formatLocalDateTime(d) {
const pad = n => String(n).padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
function openScheduleModal() {
const modal = document.getElementById('schedule-modal');
modal.classList.remove('hidden');
const dt = document.getElementById('schedule-datetime');
const min = new Date(Date.now() + 60000).toISOString().slice(0, 16);
const min = formatLocalDateTime(new Date(Date.now() + 60000));
dt.min = min;
dt.value = min;
}
@@ -550,10 +555,64 @@ function setupMobileNav() {
});
}
let healthPollHandle = null;
function setBotStatus(online) {
const dot = document.getElementById('bot-status-dot');
const text = document.getElementById('bot-status-text');
if (!dot || !text) return;
dot.className = online ? 'dot online' : 'dot offline';
text.textContent = online ? 'Connected' : 'Unreachable';
}
async function pollHealth() {
try {
const res = await fetch('/healthz', { credentials: 'same-origin' });
if (res.ok) {
const data = await res.json();
setBotStatus(Boolean(data.bot));
} else {
setBotStatus(false);
}
} catch (_) {
setBotStatus(false);
}
}
function scheduleNextHealthPoll() {
if (document.hidden) return;
healthPollHandle = setTimeout(async () => {
await pollHealth();
scheduleNextHealthPoll();
}, 20000);
}
function startHealthPolling() {
if (healthPollHandle) clearTimeout(healthPollHandle);
scheduleNextHealthPoll();
}
function stopHealthPolling() {
if (healthPollHandle) {
clearTimeout(healthPollHandle);
healthPollHandle = null;
}
}
function setupHealthPolling() {
document.addEventListener('visibilitychange', () => {
if (document.hidden) stopHealthPolling();
else startHealthPolling();
});
window.addEventListener('pagehide', stopHealthPolling);
startHealthPolling();
}
document.addEventListener('DOMContentLoaded', async () => {
setupSidebarRouting();
setupActionButtons();
setupMobileNav();
await init();
navigate(location.pathname, false);
setupHealthPolling();
});