diff --git a/app/static/index.html b/app/static/index.html index a6f8034..66b86fa 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -173,6 +173,45 @@ .check-btn:hover { border-color: var(--accent); color: var(--accent); } .check-btn.checking { opacity: .5; cursor: default; } + /* Модальное окно истории проверок */ + .modal-overlay { + position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 2000; + display: flex; align-items: center; justify-content: center; + backdrop-filter: blur(2px); opacity: 0; pointer-events: none; transition: opacity .2s; + } + .modal-overlay.open { opacity: 1; pointer-events: auto; } + .modal-box { + background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; + width: 90%; max-width: 650px; max-height: 80vh; display: flex; flex-direction: column; + box-shadow: 0 10px 30px rgba(0,0,0,.5); overflow: hidden; + } + .modal-header { + padding: 14px 18px; border-bottom: 1px solid var(--border); + display: flex; align-items: center; justify-content: space-between; + } + .modal-header h3 { margin: 0; font-size: 15px; color: var(--text); } + .modal-close { + background: none; border: none; color: var(--text2); font-size: 18px; cursor: pointer; + } + .modal-close:hover { color: var(--text); } + .modal-body { + padding: 14px 18px; overflow-y: auto; font-size: 12px; + } + .check-log-item { + padding: 8px 10px; border-bottom: 1px solid var(--border); + display: flex; flex-direction: column; gap: 4px; + } + .check-log-item:last-child { border-bottom: none; } + .log-line1 { display: flex; align-items: center; justify-content: space-between; } + .log-status.ok { color: var(--green); } + .log-status.fail { color: var(--red); } + .log-meta { color: var(--text2); font-size: 11px; } + .log-err { + color: var(--red); font-family: Consolas, 'Fira Mono', monospace; + font-size: 11px; background: rgba(248,81,73,.1); padding: 4px 6px; + border-radius: 4px; white-space: pre-wrap; word-break: break-word; + } + .empty { padding: 40px 24px; color: var(--text2); text-align: center; } .loading { text-align: center; padding: 60px; color: var(--text2); } @@ -491,11 +530,48 @@ async function checkOne(modelId, btn) { async function openCheckHistory(modelId, btn) { const res = await fetch(`/api/checks/${encodeURIComponent(modelId)}`); const data = await res.json(); - const idx = allData.findIndex(m => m.id === modelId); - if (idx >= 0) { - allData[idx].history = (data.checks || []).map(c => ({ ok: c.ok, latency_ms: c.latency_ms, at: c.checked_at, error: c.error })); + const checks = data.checks || []; + + let modal = document.getElementById('history-modal'); + if (!modal) { + modal = document.createElement('div'); + modal.id = 'history-modal'; + modal.className = 'modal-overlay'; + modal.innerHTML = ` + + `; + modal.addEventListener('click', e => { if (e.target === modal) closeModal(); }); + document.body.appendChild(modal); } - applyFilters(); + + document.getElementById('modal-title').textContent = `Лог проверок: ${modelId}`; + const body = document.getElementById('modal-body'); + if (!checks.length) { + body.innerHTML = '
Нет данных о проверках
'; + } else { + body.innerHTML = checks.map(c => ` +
+
+ ${c.ok ? '✓ Успех' : '✗ Провал'} + ${fmtTime(c.checked_at)} · ${c.latency_ms !== null && c.latency_ms !== undefined ? c.latency_ms + ' мс' : '—'} +
+ ${c.error ? `
${escapeHtml(c.error)}
` : ''} +
+ `).join(''); + } + + modal.classList.add('open'); +} + +function closeModal() { + const modal = document.getElementById('history-modal'); + if (modal) modal.classList.remove('open'); } document.getElementById('btn-refresh').addEventListener('click', loadData);