From d283e8ab8c38d2a3e6993af150decb39dd6b82d7 Mon Sep 17 00:00:00 2001 From: Khalid MOUTAOUAKIL Date: Mon, 6 Apr 2026 16:32:07 +0200 Subject: [PATCH] Pagination 50/page, recherche hostname, filtre domaine Co-Authored-By: Claude Opus 4.6 (1M context) --- app/routers/audit_full.py | 62 ++++++++++++++++++++++-------- app/templates/audit_full_list.html | 39 ++++++++++++++++++- 2 files changed, 84 insertions(+), 17 deletions(-) diff --git a/app/routers/audit_full.py b/app/routers/audit_full.py index b2bf73b..7e17934 100644 --- a/app/routers/audit_full.py +++ b/app/routers/audit_full.py @@ -24,10 +24,13 @@ async def audit_full_list(request: Request, db=Depends(get_db)): if not can_view(perms, "audit"): return RedirectResponse(url="/dashboard") - audits = get_latest_audits(db) filtre = request.query_params.get("filter", "") + search = request.query_params.get("q", "").strip() + domain = request.query_params.get("domain", "") + page = int(request.query_params.get("page", "1")) + per_page = 50 - # KPIs + # KPIs (toujours sur tout le jeu) kpis = db.execute(text(""" SELECT COUNT(*) as total, @@ -42,43 +45,72 @@ async def audit_full_list(request: Request, db=Depends(get_db)): )) as disk_warning, COUNT(*) FILTER (WHERE uptime LIKE '%month%' OR uptime LIKE '%year%' - OR uptime LIKE '%week%' AND ( + OR (uptime LIKE '%week%' AND ( CASE WHEN uptime ~ '(\d+) week' THEN (substring(uptime from '(\d+) week'))::int ELSE 0 END >= 17 - ) + )) ) as uptime_long FROM server_audit_full WHERE status = 'ok' AND id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) """)).fetchone() - # Filtrer si demande + # Domaines pour le filtre + all_domains = db.execute(text( + "SELECT code, name FROM domains ORDER BY name" + )).fetchall() + + # Requete avec filtres + audits = get_latest_audits(db, limit=9999) + + # Filtre KPI if filtre == "reboot": audits = [a for a in audits if a.reboot_required] elif filtre == "disk_critical": - ids = db.execute(text(""" + ids = {r.id for r in db.execute(text(""" SELECT saf.id FROM server_audit_full saf WHERE saf.status = 'ok' AND EXISTS ( SELECT 1 FROM jsonb_array_elements(saf.disk_usage) d WHERE (d->>'pct')::int >= 90 ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) - """)).fetchall() - id_set = {r.id for r in ids} - audits = [a for a in audits if a.id in id_set] + """)).fetchall()} + audits = [a for a in audits if a.id in ids] elif filtre == "disk_warning": - ids = db.execute(text(""" + ids = {r.id for r in db.execute(text(""" SELECT saf.id FROM server_audit_full saf WHERE saf.status = 'ok' AND EXISTS ( SELECT 1 FROM jsonb_array_elements(saf.disk_usage) d WHERE (d->>'pct')::int >= 80 ) AND saf.id IN (SELECT DISTINCT ON (hostname) id FROM server_audit_full WHERE status = 'ok' ORDER BY hostname, audit_date DESC) - """)).fetchall() - id_set = {r.id for r in ids} - audits = [a for a in audits if a.id in id_set] + """)).fetchall()} + audits = [a for a in audits if a.id in ids] elif filtre == "uptime": audits = [a for a in audits if a.uptime and ("month" in a.uptime or "year" in a.uptime)] + # Filtre domaine + if domain: + domain_servers = {r.hostname for r in db.execute(text(""" + SELECT s.hostname FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN domains d ON de.domain_id = d.id + WHERE d.code = :dc + """), {"dc": domain}).fetchall()} + audits = [a for a in audits if a.hostname in domain_servers] + + # Recherche hostname + if search: + q = search.lower() + audits = [a for a in audits if q in a.hostname.lower()] + + # Pagination + total_filtered = len(audits) + total_pages = max(1, (total_filtered + per_page - 1) // per_page) + page = max(1, min(page, total_pages)) + audits_page = audits[(page - 1) * per_page : page * per_page] + ctx = base_context(request, db, user) ctx.update({ - "app_name": APP_NAME, "audits": audits, "kpis": kpis, - "filter": filtre, + "app_name": APP_NAME, "audits": audits_page, "kpis": kpis, + "filter": filtre, "search": search, "domain": domain, + "all_domains": all_domains, + "page": page, "total_pages": total_pages, "total_filtered": total_filtered, "msg": request.query_params.get("msg"), }) return templates.TemplateResponse("audit_full_list.html", ctx) diff --git a/app/templates/audit_full_list.html b/app/templates/audit_full_list.html index 74a5044..9813f3c 100644 --- a/app/templates/audit_full_list.html +++ b/app/templates/audit_full_list.html @@ -48,10 +48,25 @@ {% if filter %} -
Filtre actif : {{ filter }} ({{ audits|length }} serveurs) — Tout voir
+
Filtre actif : {{ filter }}Tout voir
{% endif %} {% endif %} + +
+
+ {% if filter %}{% endif %} + + + + {% if search or domain %}Reset{% endif %} +
+ {{ total_filtered }} serveur(s) +
+ {% if audits %}
@@ -84,11 +99,31 @@ {% endfor %}
+
+ + {% if total_pages > 1 %} +
+ Page {{ page }}/{{ total_pages }} ({{ total_filtered }} serveurs) +
+ {% if page > 1 %} + 1 + {% if page > 2 %}<{% endif %} + {% endif %} + {{ page }} + {% if page < total_pages %} + > + {{ total_pages }} + {% endif %} +
+
+ {% endif %} {% else %}
-

Aucun audit importe.

+

Aucun audit{% if search or domain or filter %} correspondant aux filtres{% endif %}.

+ {% if not search and not domain and not filter %}

Lancez le standalone sur vos serveurs puis importez le JSON ici.

+ {% endif %}
{% endif %} {% endblock %}