From 35dfc4e55fbe4aad38b9e2b6b74b7492b4c48853 Mon Sep 17 00:00:00 2001 From: Yan Xell Date: Wed, 13 May 2026 12:26:03 +0200 Subject: [PATCH] restored pagination + logs webpage --- Tool/pages.py | 51 ++++++++++++++++++++++++++---- Tool/queries/logs.py | 2 +- static/js/logs.js | 75 +++++++++++++++++++++++++++++++++++--------- templates/logs.html | 4 +-- 4 files changed, 108 insertions(+), 24 deletions(-) diff --git a/Tool/pages.py b/Tool/pages.py index a5748ea..be930a6 100644 --- a/Tool/pages.py +++ b/Tool/pages.py @@ -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 = ( - '
' - '
' - '
' + 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='

Nessun log trovato.

' + ) + 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'← Precedente' + if prev_id else '← Precedente') + next_btn = (f'Successivo →' + if next_id else 'Successivo →') + options = ''.join( + f'' + for rid in run_ids ) + current_name = run_names.get(run_id, 'unknown') + pagination = ( + f'
' + f'{prev_btn}' + f'' + f'{next_btn}' + f'' + f'
' + f'
' + ) + + run_info = f'{_e(current_name)} 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), ) diff --git a/Tool/queries/logs.py b/Tool/queries/logs.py index b27f280..a370d8f 100644 --- a/Tool/queries/logs.py +++ b/Tool/queries/logs.py @@ -42,7 +42,7 @@ def render_table(rows: list) -> str: return '

Nessun log trovato.

' 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) diff --git a/static/js/logs.js b/static/js/logs.js index e064817..c013b75 100644 --- a/static/js/logs.js +++ b/static/js/logs.js @@ -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(); })(); diff --git a/templates/logs.html b/templates/logs.html index 1c2b861..d6d34bf 100644 --- a/templates/logs.html +++ b/templates/logs.html @@ -1,7 +1,7 @@