From 2a249e16d411bf19bb3a2d5767be817eb70a5e1f Mon Sep 17 00:00:00 2001 From: Francesco Picone Date: Wed, 18 Mar 2026 17:22:33 +0100 Subject: [PATCH] ++ fix grafico --- app/static/style.css | 76 ++++++++++++++++++++++++++++++++++++++++ app/templates/index.html | 64 +++++++++++++++++++++++++-------- 2 files changed, 125 insertions(+), 15 deletions(-) diff --git a/app/static/style.css b/app/static/style.css index aa65efc..b70698f 100644 --- a/app/static/style.css +++ b/app/static/style.css @@ -124,6 +124,37 @@ body { padding: 0.55rem 0.7rem; min-height: 42px; word-break: break-word; + display: flex; + flex-wrap: wrap; + gap: 0.4rem 0.6rem; + align-items: center; +} + +.summary-kv { + display: inline-flex; + align-items: center; + gap: 0.25rem; + background: rgba(255, 255, 255, 0.06); + border-radius: 6px; + padding: 0.15rem 0.45rem; + font-size: 0.78rem; +} + +.summary-key { + color: #8ecae6; + font-size: 0.72rem; + text-transform: uppercase; + letter-spacing: 0.4px; +} + +.sync-in-progress { + color: #ffe2a3; + animation: pulse-text 1.4s ease-in-out infinite alternate; +} + +@keyframes pulse-text { + from { opacity: 0.6; } + to { opacity: 1; } } .status-chip { @@ -182,12 +213,57 @@ body { .table thead { border-bottom: 1px solid var(--border); + position: sticky; + top: 0; + z-index: 1; + background: #0b1e2d; } .table tbody tr { border-bottom: 1px solid rgba(255, 255, 255, 0.06); } +.log-scroll { + max-height: 420px; + overflow-y: auto; + overflow-x: auto; + border-radius: 10px; + scrollbar-width: thin; + scrollbar-color: rgba(255,255,255,0.2) transparent; +} + +.log-scroll::-webkit-scrollbar { + width: 6px; +} + +.log-scroll::-webkit-scrollbar-thumb { + background: rgba(255,255,255,0.2); + border-radius: 4px; +} + +@keyframes flash-row { + 0% { background: rgba(255, 183, 3, 0.25); } + 100% { background: transparent; } +} + +.row-new { + animation: flash-row 1.8s ease forwards; +} + +.live-dot { + width: 9px; + height: 9px; + border-radius: 50%; + background: #2ec4b6; + flex-shrink: 0; + animation: dot-pulse 1.2s ease-in-out infinite; +} + +@keyframes dot-pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.4; transform: scale(0.75); } +} + @media (max-width: 768px) { .hero-panel, .log-panel { diff --git a/app/templates/index.html b/app/templates/index.html index 4cb21c8..9fc6054 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -35,16 +35,22 @@
-

Attivita Recenti

- UTC +
+

Attivita Recenti

+ +
+
+ 0 eventi + UTC +
-
+
- - - + + + @@ -69,15 +75,20 @@ return new Date(value).toLocaleString(); } - function fmtSummary(summary) { - if (!summary || Object.keys(summary).length === 0) { - return 'Nessuna esecuzione'; + function fmtSummary(summary, running) { + if (running) { + return '▶ Sincronizzazione in corso…'; } + if (!summary || Object.keys(summary).length === 0) { + return 'Nessuna esecuzione ancora'; + } + const labels = { downloaded: 'scaricati', kept: 'invariati', deleted: 'eliminati', errors: 'errori', trigger: 'avviato da', error: 'errore' }; const parts = []; for (const [key, val] of Object.entries(summary)) { - parts.push(`${key}: ${val}`); + const label = labels[key] || key; + parts.push(`${label} ${val}`); } - return parts.join(' | '); + return parts.join(''); } function statusClass(status, running) { @@ -112,7 +123,7 @@
Ultima fine: ${fmtDate(job.last_end)}
-
${fmtSummary(job.last_summary)}
+
${fmtSummary(job.last_summary, job.running)}
@@ -135,21 +146,37 @@ }); } + let prevLogTime = null; + function renderLogs(logs) { const tbody = document.querySelector('#logsTable tbody'); - tbody.innerHTML = ''; + const entries = logs.slice(0, 200); + const newTopTime = entries.length > 0 ? entries[0].time : null; + const hasNew = newTopTime && newTopTime !== prevLogTime; + prevLogTime = newTopTime; - logs.slice(0, 120).forEach((entry) => { + tbody.innerHTML = ''; + entries.forEach((entry, i) => { const tr = document.createElement('tr'); + if (hasNew && i < 3) tr.classList.add('row-new'); tr.innerHTML = `
- + `; tbody.appendChild(tr); }); + + document.getElementById('logCount').textContent = entries.length + ' eventi'; + + if (hasNew) { + const scroll = document.querySelector('.log-scroll'); + scroll.scrollTop = 0; + } } async function reload() { @@ -158,6 +185,13 @@ document.getElementById('serverTime').textContent = `Server UTC: ${fmtDate(data.server_time)}`; renderJobs(data.jobs || []); renderLogs(data.logs || []); + const anyRunning = (data.jobs || []).some(j => j.running); + const dot = document.getElementById('liveIndicator'); + if (anyRunning) { + dot.classList.remove('d-none'); + } else { + dot.classList.add('d-none'); + } } catch (err) { document.getElementById('serverTime').textContent = `Errore: ${err.message}`; }
OraLivelloJobOraLivelloJob Messaggio Dettagli
${fmtDate(entry.time)} ${entry.level} ${entry.job || '-'} ${entry.message}${JSON.stringify(entry.details || {})}` + + JSON.stringify(entry.details || {}) + + `