feat: модальное окно для логов проверок без сброса табличных фильтров
Build and deploy / build-deploy (push) Has been cancelled
Build and deploy / build-deploy (push) Has been cancelled
This commit is contained in:
+80
-4
@@ -173,6 +173,45 @@
|
|||||||
.check-btn:hover { border-color: var(--accent); color: var(--accent); }
|
.check-btn:hover { border-color: var(--accent); color: var(--accent); }
|
||||||
.check-btn.checking { opacity: .5; cursor: default; }
|
.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; }
|
.empty { padding: 40px 24px; color: var(--text2); text-align: center; }
|
||||||
.loading { text-align: center; padding: 60px; color: var(--text2); }
|
.loading { text-align: center; padding: 60px; color: var(--text2); }
|
||||||
|
|
||||||
@@ -491,11 +530,48 @@ async function checkOne(modelId, btn) {
|
|||||||
async function openCheckHistory(modelId, btn) {
|
async function openCheckHistory(modelId, btn) {
|
||||||
const res = await fetch(`/api/checks/${encodeURIComponent(modelId)}`);
|
const res = await fetch(`/api/checks/${encodeURIComponent(modelId)}`);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
const idx = allData.findIndex(m => m.id === modelId);
|
const checks = data.checks || [];
|
||||||
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 }));
|
let modal = document.getElementById('history-modal');
|
||||||
|
if (!modal) {
|
||||||
|
modal = document.createElement('div');
|
||||||
|
modal.id = 'history-modal';
|
||||||
|
modal.className = 'modal-overlay';
|
||||||
|
modal.innerHTML = `
|
||||||
|
<div class="modal-box">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3 id="modal-title">Лог проверок</h3>
|
||||||
|
<button class="modal-close" onclick="closeModal()">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" id="modal-body"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
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 = '<div class="no-data" style="text-align:center;padding:20px;">Нет данных о проверках</div>';
|
||||||
|
} else {
|
||||||
|
body.innerHTML = checks.map(c => `
|
||||||
|
<div class="check-log-item">
|
||||||
|
<div class="log-line1">
|
||||||
|
<span class="log-status ${c.ok ? 'ok' : 'fail'}">${c.ok ? '✓ Успех' : '✗ Провал'}</span>
|
||||||
|
<span class="log-meta">${fmtTime(c.checked_at)} · ${c.latency_ms !== null && c.latency_ms !== undefined ? c.latency_ms + ' мс' : '—'}</span>
|
||||||
|
</div>
|
||||||
|
${c.error ? `<div class="log-err">${escapeHtml(c.error)}</div>` : ''}
|
||||||
|
</div>
|
||||||
|
`).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);
|
document.getElementById('btn-refresh').addEventListener('click', loadData);
|
||||||
|
|||||||
Reference in New Issue
Block a user