restored pagination + logs webpage
This commit is contained in:
+45
-6
@@ -101,14 +101,53 @@ def _page_pec(db_path: str) -> str:
|
||||
|
||||
|
||||
def _page_logs(db_path: str, run_id: int = None) -> str:
|
||||
logs = q_logs.get_logs(db_path)
|
||||
pagination = (
|
||||
'<div class="log-pagination">'
|
||||
'<div id="filter-process-names" class="pg-process-filter"></div>'
|
||||
'</div>'
|
||||
runs = q_logs.get_last_run_ids(db_path)
|
||||
run_ids = [r['rpa_process_id'] for r in runs]
|
||||
run_names = {r['rpa_process_id']: r.get('process_name', 'unknown') for r in runs}
|
||||
run_dates = {r['rpa_process_id']: str(r.get('start_run', ''))[:10] for r in runs}
|
||||
|
||||
if not run_ids:
|
||||
content = _tmpl('logs.html').substitute(
|
||||
run_info='nessun log', pagination='', tbl_logs='<p class="empty">Nessun log trovato.</p>'
|
||||
)
|
||||
return _base('Log DB', content, 'nav_logs', db_path, _page_css('logs'), _page_js('logs'))
|
||||
|
||||
if run_id is None or run_id not in run_ids:
|
||||
run_id = run_ids[0]
|
||||
|
||||
idx = run_ids.index(run_id)
|
||||
prev_id = run_ids[idx + 1] if idx + 1 < len(run_ids) else None
|
||||
next_id = run_ids[idx - 1] if idx > 0 else None
|
||||
|
||||
prev_btn = (f'<a class="pg-btn" href="/logs?run={prev_id}">← Precedente</a>'
|
||||
if prev_id else '<span class="pg-btn disabled">← Precedente</span>')
|
||||
next_btn = (f'<a class="pg-btn" href="/logs?run={next_id}">Successivo →</a>'
|
||||
if next_id else '<span class="pg-btn disabled">Successivo →</span>')
|
||||
options = ''.join(
|
||||
f'<option value="{rid}"'
|
||||
f' data-process-name="{_e(run_names.get(rid, ""))}"'
|
||||
f' data-date="{_e(run_dates.get(rid, ""))}"'
|
||||
f' style="color:#1d4ed8"'
|
||||
f'{" selected" if rid == run_id else ""}>'
|
||||
f'Run #{rid} — {_e(run_names.get(rid, ""))}</option>'
|
||||
for rid in run_ids
|
||||
)
|
||||
current_name = run_names.get(run_id, 'unknown')
|
||||
pagination = (
|
||||
f'<div class="log-pagination">'
|
||||
f'{prev_btn}'
|
||||
f'<select id="pg-run-select" class="pg-select" onchange="location.href=\'/logs?run=\'+this.value">{options}</select>'
|
||||
f'{next_btn}'
|
||||
f'<span class="pg-sep"></span>'
|
||||
f'<div id="filter-process-names" class="pg-process-filter"></div>'
|
||||
f'</div>'
|
||||
)
|
||||
|
||||
run_info = f'<span class="proc-name-badge">{_e(current_name)}</span> Run #{run_id}'
|
||||
|
||||
logs = q_logs.get_logs_by_run(db_path, run_id)
|
||||
content = _tmpl('logs.html').substitute(
|
||||
run_info='',
|
||||
run_info=run_info,
|
||||
pagination=pagination,
|
||||
tbl_logs=q_logs.render_table(logs),
|
||||
)
|
||||
|
||||
@@ -42,7 +42,7 @@ def render_table(rows: list) -> str:
|
||||
return '<p class="empty">Nessun log trovato.</p>'
|
||||
|
||||
def _badge(tipo):
|
||||
m = {'log': ('log', 'Log'), 'warning': ('warn', 'Warning'), 'error': ('err', 'Error')}
|
||||
m = {'info': ('log', 'Info'), 'warning': ('warn', 'Warning'), 'error': ('err', 'Error')}
|
||||
cls, lbl = m.get(tipo, ('', ''))
|
||||
return badge(cls, lbl) if cls else e(tipo)
|
||||
|
||||
|
||||
+60
-15
@@ -2,6 +2,7 @@
|
||||
var search = document.getElementById('log-search');
|
||||
var typeChecks = document.querySelectorAll('.type-filter');
|
||||
var pnContainer = document.getElementById('filter-process-names');
|
||||
var pgSelect = document.getElementById('pg-run-select');
|
||||
var dateFrom = document.getElementById('filter-date-from');
|
||||
var dateTo = document.getElementById('filter-date-to');
|
||||
var filterBtn = document.getElementById('filter-date-btn');
|
||||
@@ -41,13 +42,15 @@
|
||||
if (dateTo) dateTo.value = toIsoDate(today);
|
||||
}
|
||||
|
||||
// ── Process-name checkboxes (built from table rows) ───────────────────────
|
||||
// ── Process-name checkboxes (built from pagination select options) ─────────
|
||||
var names = [];
|
||||
document.querySelectorAll('tbody tr[data-process-name]').forEach(function(tr) {
|
||||
var n = tr.getAttribute('data-process-name');
|
||||
if (n && names.indexOf(n) === -1) names.push(n);
|
||||
});
|
||||
names.sort();
|
||||
if (pgSelect) {
|
||||
Array.from(pgSelect.options).forEach(function(opt) {
|
||||
var n = opt.getAttribute('data-process-name');
|
||||
if (n && names.indexOf(n) === -1) names.push(n);
|
||||
});
|
||||
names.sort();
|
||||
}
|
||||
|
||||
function loadSaved() {
|
||||
try { return JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}'); } catch(e) { return {}; }
|
||||
@@ -66,7 +69,7 @@
|
||||
var chk = document.createElement('input');
|
||||
chk.type = 'checkbox';
|
||||
chk.checked = (saved[name] !== undefined) ? saved[name] : true;
|
||||
chk.addEventListener('change', function(){ saveState(); applyFilter(); });
|
||||
chk.addEventListener('change', function(){ console.log('[logs] process filter changed:', name, this.checked); saveState(); filterSelect(); });
|
||||
pnChecks[name] = chk;
|
||||
lbl.appendChild(chk);
|
||||
lbl.appendChild(document.createTextNode(' ' + name));
|
||||
@@ -74,7 +77,38 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ── Table row filter (type + search + date + process_name) ────────────────
|
||||
// Store all options once at init — source of truth for rebuilding the select
|
||||
var allOptions = pgSelect
|
||||
? Array.from(pgSelect.options).map(function(o) { return o; })
|
||||
: [];
|
||||
|
||||
// ── Pagination select filter (process_name + date) ────────────────────────
|
||||
function filterSelect() {
|
||||
if (!pgSelect) return;
|
||||
var from = dateActive && dateFrom ? dateFrom.value : '';
|
||||
var to = dateActive && dateTo ? dateTo.value : '';
|
||||
var currentVal = pgSelect.value;
|
||||
|
||||
while (pgSelect.options.length) pgSelect.remove(0);
|
||||
|
||||
var currentVisible = false;
|
||||
allOptions.forEach(function(opt) {
|
||||
var pn = opt.getAttribute('data-process-name') || '';
|
||||
var date = opt.getAttribute('data-date') || '';
|
||||
var pnOk = pnChecks[pn] ? pnChecks[pn].checked : true;
|
||||
var dateOk = (!from || !date || (date >= from && date <= to));
|
||||
if (pnOk && dateOk) {
|
||||
pgSelect.appendChild(opt);
|
||||
if (opt.value === currentVal) currentVisible = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!currentVisible && pgSelect.options.length > 0) {
|
||||
location.href = '/logs?run=' + pgSelect.options[0].value;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Table row filter (type + search + date) ───────────────────────────────
|
||||
function applyFilter() {
|
||||
var q = search ? search.value.toLowerCase() : '';
|
||||
var from = dateActive && dateFrom ? dateFrom.value : '';
|
||||
@@ -83,27 +117,38 @@
|
||||
typeChecks.forEach(function(c){ if (c.checked) active[c.value] = 1; });
|
||||
document.querySelectorAll('tbody tr').forEach(function(tr) {
|
||||
var type = tr.dataset.type || '';
|
||||
var pn = tr.getAttribute('data-process-name') || '';
|
||||
var text = tr.textContent.toLowerCase();
|
||||
var date = tr.getAttribute('data-date') || '';
|
||||
var dateOk = (!from || date >= from) && (!to || date <= to);
|
||||
var pnOk = pnChecks[pn] ? pnChecks[pn].checked : true;
|
||||
tr.style.display = (active[type] && pnOk && text.indexOf(q) >= 0 && dateOk) ? '' : 'none';
|
||||
tr.style.display = (active[type] && text.indexOf(q) >= 0 && dateOk) ? '' : 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// ── Filter button — saves dates then applies filter ───────────────────────
|
||||
// ── Filter button — saves dates then applies both filters ─────────────────
|
||||
if (filterBtn) {
|
||||
filterBtn.addEventListener('click', function() {
|
||||
console.log('[logs] filtra clicked — from:', dateFrom && dateFrom.value, 'to:', dateTo && dateTo.value);
|
||||
dateActive = true;
|
||||
saveDates();
|
||||
applyFilter();
|
||||
filterSelect();
|
||||
});
|
||||
}
|
||||
|
||||
if (search) search.addEventListener('input', applyFilter);
|
||||
typeChecks.forEach(function(c){ c.addEventListener('change', applyFilter); });
|
||||
if (search) search.addEventListener('input', function() {
|
||||
console.log('[logs] search input:', search.value);
|
||||
applyFilter();
|
||||
});
|
||||
typeChecks.forEach(function(c){ c.addEventListener('change', function() {
|
||||
console.log('[logs] type filter changed:', c.value, '->', c.checked);
|
||||
applyFilter();
|
||||
}); });
|
||||
|
||||
// Initial apply
|
||||
if (pgSelect) pgSelect.addEventListener('change', function() {
|
||||
console.log('[logs] run selected:', pgSelect.value);
|
||||
});
|
||||
|
||||
// Initial apply (uses restored dates)
|
||||
applyFilter();
|
||||
filterSelect();
|
||||
})();
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<section class="page-header">
|
||||
<div class="page-filter-wrap">
|
||||
<div class="page-filter-header">
|
||||
<h2>Log DB</h2>
|
||||
<h2>Log DB — ${run_info}</h2>
|
||||
<button id="btn-toggle-filters" class="btn-toggle-filters" title="Mostra/nascondi filtri">
|
||||
<svg id="filters-arrow" class="filters-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 6 15 12 9 18"/></svg>
|
||||
<span class="filters-btn-text">Filtri</span>
|
||||
@@ -17,7 +17,7 @@
|
||||
<hr class="filter-hr" />
|
||||
<div class="log-filters">
|
||||
<input type="search" id="log-search" placeholder="Cerca in questo log…" />
|
||||
<label><input type="checkbox" class="type-filter" value="log" checked> Log</label>
|
||||
<label><input type="checkbox" class="type-filter" value="info" checked> Info</label>
|
||||
<label><input type="checkbox" class="type-filter" value="warning" checked> Warning</label>
|
||||
<label><input type="checkbox" class="type-filter" value="error" checked> Error</label>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user