// Logs page (status/logs.html) — dedicated admin log viewer. // Two tabs: Error log (calls /api/v1/error-logs) + Container (calls // /api/v1/logs/containers + /api/v1/logs/container/:id). Mirrors the // /api/v1/error-logs parser fix from DC-051 — U+2500 separator, capped // tail, level filter. (function() { 'use strict'; function escapeHtml(s) { if (s === null || s === undefined) return ''; return String(s).replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); } function formatBytes(n) { if (!Number.isFinite(n) || n <= 0) return '0 B'; if (n < 1024) return n + ' B'; if (n < 1024 * 1024) return (n / 1024).toFixed(1) + ' KiB'; return (n / 1024 / 1024).toFixed(2) + ' MiB'; } const out = document.getElementById('output'); const meta = document.getElementById('meta'); const tabError = document.getElementById('tab-error'); const tabContainer = document.getElementById('tab-container'); const errorCtrls = document.getElementById('error-controls'); const containerCtrls = document.getElementById('container-controls'); let activeTab = 'error'; let containers = []; function switchTab(tab) { activeTab = tab; tabError.classList.toggle('active', tab === 'error'); tabContainer.classList.toggle('active', tab === 'container'); errorCtrls.style.display = tab === 'error' ? 'flex' : 'none'; containerCtrls.style.display = tab === 'container' ? 'flex' : 'none'; if (tab === 'error') loadErrorLog(); else loadContainerList(); } async function fetchJson(url, opts) { const r = await fetch(url, opts); const data = await r.json().catch(() => ({})); if (!r.ok || (data && data.success === false)) { throw new Error((data && (data.error || data.message)) || `HTTP ${r.status}`); } return data; } async function loadErrorLog() { const tailEl = /** @type {HTMLSelectElement} */ (document.getElementById('tail')); const levelEl = /** @type {HTMLSelectElement} */ (document.getElementById('level')); const tail = tailEl.value; const level = levelEl.value; let qs = `tail=${encodeURIComponent(tail)}`; if (level) qs += '&level=' + encodeURIComponent(level); out.innerHTML = '