Files
TDI-Dashboard/static/js/report.js
T
Luca Banfi ebafa611be init
2026-05-06 13:59:13 +02:00

234 lines
9.1 KiB
JavaScript

/* ── Filter + grouped view ─────────────────────────────────────────────── */
(function(){
var today = new Date().toISOString().slice(0,10);
var sevenAgo = new Date(Date.now() - 7*86400000).toISOString().slice(0,10);
document.getElementById('f-da').value = sevenAgo;
document.getElementById('f-a').value = today;
var table = document.querySelector('.tw table');
var tbody = table.querySelector('tbody');
var thead = table.querySelector('thead');
var allFlatRows = Array.prototype.slice.call(tbody.querySelectorAll('tr'));
var flatTheadHTML = thead.innerHTML;
var groupedTheadHTML = '<tr>'
+ '<th>Tipo</th><th>ID Sessione</th><th>Corso</th>'
+ '<th>Azienda</th><th>Articolo</th><th>Prima Lezione</th><th>Modifiche</th><th>Rilevato</th><th></th>'
+ '</tr>';
var isGrouped = false;
function esc(s) {
return String(s == null ? '' : s)
.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
function badgeHtml(tipo) {
if (tipo === 'nuovo') return '<span class="badge ok">Nuovo</span>';
if (tipo === 'modificato') return '<span class="badge warn">Modificato</span>';
return esc(tipo);
}
function getRowData(row) {
var c = row.cells;
return {
tipo: row.getAttribute('data-tipo') || '',
sessione_id: c[1] ? c[1].textContent.trim() : '',
corso: c[2] ? c[2].textContent.trim() : '',
azienda: c[3] ? c[3].textContent.trim() : '',
articolo: c[4] ? c[4].textContent.trim() : '',
prima_lezione: c[5] ? c[5].textContent.trim() : '',
campo: c[6] ? c[6].textContent.trim() : '',
valore_prec: c[7] ? c[7].textContent.trim() : '',
valore_nuovo: c[8] ? c[8].textContent.trim() : '',
rilevato: c[9] ? c[9].textContent.trim() : '',
};
}
function toIso(rilevato) {
var m = rilevato.match(/(\d{2})\/(\d{2})\/(\d{4})/);
return m ? m[3] + '-' + m[2] + '-' + m[1] : '';
}
function getFilters() {
var tipi = [];
document.querySelectorAll('.tipo-chk:checked').forEach(function(c){ tipi.push(c.value); });
return {
da: document.getElementById('f-da').value,
a: document.getElementById('f-a').value,
sid: document.getElementById('f-sid').value.trim(),
tipi: tipi,
};
}
function passes(d, f) {
var pd = toIso(d.prima_lezione);
return (!f.da || pd >= f.da)
&& (!f.a || pd <= f.a)
&& (!f.sid || d.sessione_id === f.sid)
&& f.tipi.indexOf(d.tipo) !== -1;
}
function updateCount(n) {
document.getElementById('visible-count').textContent = n + ' righe';
}
function applyFlat(f) {
tbody.innerHTML = '';
allFlatRows.forEach(function(r) { tbody.appendChild(r); });
var n = 0;
allFlatRows.forEach(function(row) {
var ok = passes(getRowData(row), f);
row.style.display = ok ? '' : 'none';
if (ok) n++;
});
updateCount(n);
}
function applyGrouped(f) {
var visible = allFlatRows.filter(function(r) { return passes(getRowData(r), f); });
var groups = {}, order = [];
visible.forEach(function(row) {
var d = getRowData(row);
var key = d.sessione_id || '__?__';
if (!groups[key]) {
groups[key] = { base: d, tipi: [], changes: [], latestIso: '', latestRilevato: '' };
order.push(key);
}
var g = groups[key];
if (g.tipi.indexOf(d.tipo) === -1) g.tipi.push(d.tipo);
var iso = toIso(d.rilevato);
if (iso > g.latestIso) { g.latestIso = iso; g.latestRilevato = d.rilevato; }
if (d.campo && d.campo !== '-') {
g.changes.push({ campo: d.campo, prec: d.valore_prec, nuovo: d.valore_nuovo });
}
});
var html = '';
order.forEach(function(key) {
var g = groups[key];
var b = g.base;
var tipiHtml = g.tipi.map(badgeHtml).join(' ');
var modHtml = g.changes.length
? g.changes.map(function(c) {
return '<div class="mod-row">'
+ '<span class="mod-campo">' + esc(c.campo) + '</span>: '
+ '<span class="val-prec">' + esc(c.prec) + '</span>'
+ ' &rarr; '
+ '<span class="val-nuovo">' + esc(c.nuovo) + '</span>'
+ '</div>';
}).join('')
: '<span class="mod-none">\u2014</span>';
html += '<tr>'
+ '<td>' + tipiHtml + '</td>'
+ '<td>' + esc(b.sessione_id) + '</td>'
+ '<td>' + esc(b.corso) + '</td>'
+ '<td>' + esc(b.azienda) + '</td>'
+ '<td>' + esc(b.articolo) + '</td>'
+ '<td class="col-prima-lez">' + esc(b.prima_lezione) + '</td>'
+ '<td class="mod-cell">' + modHtml + '</td>'
+ '<td>' + esc(g.latestRilevato) + '</td>'
+ '<td><button class="doc-btn" data-sid="' + esc(b.sessione_id) + '" data-corso="' + esc(b.corso) + '" title="Documenti caricati">📄</button></td>'
+ '</tr>';
});
tbody.innerHTML = html || '<tr><td colspan="9" class="empty">Nessun dato</td></tr>';
updateCount(order.length);
}
function applyFilters() {
var f = getFilters();
if (isGrouped) applyGrouped(f); else applyFlat(f);
}
document.getElementById('btn-toggle-view').addEventListener('click', function() {
isGrouped = !isGrouped;
this.textContent = isGrouped ? '\u229e Tabella' : '\u2a27 Raggruppa corso';
this.classList.toggle('active', isGrouped);
thead.innerHTML = isGrouped ? groupedTheadHTML : flatTheadHTML;
applyFilters();
});
document.getElementById('btn-filter').addEventListener('click', applyFilters);
document.getElementById('btn-reset').addEventListener('click', function(){
document.getElementById('f-da').value = sevenAgo;
document.getElementById('f-a').value = today;
document.getElementById('f-sid').value = '';
document.querySelectorAll('.tipo-chk').forEach(function(c){ c.checked = true; });
applyFilters();
});
document.querySelectorAll('.tipo-chk').forEach(function(c){
c.addEventListener('change', applyFilters);
});
applyFilters();
})();
/* ── Docs modal ────────────────────────────────────────────────────────── */
(function(){
var modal = document.getElementById('docs-modal');
var modalBody = document.getElementById('docs-modal-body');
var modalSid = document.getElementById('docs-modal-sid');
var modalCorso = document.getElementById('docs-modal-corso');
function esc(s) {
return String(s == null ? '' : s)
.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
function openDocsModal(sid, corso) {
modalSid.textContent = sid;
modalCorso.textContent = corso || '';
modalBody.innerHTML = '<p class="docs-loading">Caricamento\u2026</p>';
modal.style.display = 'flex';
fetch('/api/docs?sessione_id=' + encodeURIComponent(sid))
.then(function(r){ return r.json(); })
.then(function(docs) {
if (!docs || docs.length === 0) {
modalBody.innerHTML = '<p class="docs-empty">Nessun documento caricato.</p>';
return;
}
var rows = docs.map(function(d) {
var st = d.doc_status || '';
var badge = '<span class="doc-status-badge doc-status-' + esc(st) + '">' + esc(st) + '</span>';
var fn = d.filename || '';
var fnHtml = esc(fn);
if (fn.charAt(0) === '[' && fn.charAt(fn.length - 1) === ']')
fnHtml = '<span style="color:#f97316;">' + fnHtml + '</span>';
var name = d.sp_web_url
? '<a href="' + d.sp_web_url + '" target="_blank" rel="noopener">' + fnHtml + '</a>'
: fnHtml;
var ts = d.uploaded_at ? d.uploaded_at.slice(0,16).replace('T',' ') : '-';
return '<tr>'
+ '<td class="doc-subfolder">' + esc(d.subfolder) + '</td>'
+ '<td class="doc-filename">' + name + '</td>'
+ '<td>' + badge + '</td>'
+ '<td class="doc-date">' + ts + '</td>'
+ '</tr>';
}).join('');
modalBody.innerHTML =
'<table class="docs-table">'
+ '<thead><tr><th>Cartella</th><th>File</th><th>Doc</th><th>Caricato SP</th></tr></thead>'
+ '<tbody>' + rows + '</tbody>'
+ '</table>';
})
.catch(function(err) {
modalBody.innerHTML = '<p class="docs-error">Errore: ' + esc(String(err)) + '</p>';
});
}
function closeDocsModal() { modal.style.display = 'none'; }
document.getElementById('docs-modal-close').addEventListener('click', closeDocsModal);
modal.addEventListener('click', function(ev) { if (ev.target === modal) closeDocsModal(); });
document.addEventListener('keydown', function(ev) { if (ev.key === 'Escape') closeDocsModal(); });
document.querySelector('.tw').addEventListener('click', function(ev) {
var btn = ev.target.closest('.doc-btn');
if (btn) openDocsModal(btn.getAttribute('data-sid'), btn.getAttribute('data-corso'));
});
})();