fix(dashboard): hover infobulles, full-width layout, UX polish

- Fix doc tooltips: split CSS into <style type='text/tailwindcss'> for
  @apply directives + raw CSS for reliable doc panel rendering
- Convert doc panels from click-toggle to hover-based infobulles with
  arrow pointer, fade-in animation, and auto-dismiss on mobile
- Replace '?' icons with 'ⓘ' across all 11 templates (51 tooltips)
- Full-width layout: reduce padding on mobile (px-3), scale up on
  desktop (lg:px-5, xl:px-6) for maximum screen utilization
- Auto-collapse sidebar on narrow screens (<1024px)
- Keyboard shortcuts: Alt+1–9 for page navigation, Alt+B toggle sidebar
- Add LEGITIMATE_BROWSER filter button to detections page
- Sticky header with stronger blur (backdrop-blur-md)
- All 46 routes pass tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
toto
2026-04-09 13:30:16 +02:00
parent 63ba6d203c
commit 6babc55e3e
11 changed files with 115 additions and 68 deletions

View File

@ -2,7 +2,7 @@
{% block title %}JA4 SOC — Overview{% endblock %}
{% block page_title %}
Centre de commande
<span class="relative inline-block ml-1"><button onclick="docToggle(this)" class="doc-btn" aria-label="Aide">?</button><div class="doc-panel">
<span class="relative inline-block ml-1"><button onclick="docToggle(this)" class="doc-btn" aria-label="Aide"></button><div class="doc-panel">
<h4>Centre de commande SOC</h4>
<p>Vue d'ensemble temps réel de la posture de sécurité. Les KPI montrent les dernières 24h. La timeline et les alertes se rafraîchissent toutes les 60s.</p>
<p><strong>Workflow :</strong> Identifiez les pics → cliquez sur une alerte → investiguez l'IP → classifiez.</p>
@ -48,7 +48,7 @@
<span class="section-title">
<svg class="w-4 h-4 text-brand-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"/></svg>
Timeline détections (24h)
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Timeline des détections</h4>
<p>Courbes empilées par niveau de menace. Un pic soudain indique une attaque en cours ou un nouveau pattern détecté.</p>
<p><strong>Action :</strong> Cliquez sur un pic pour filtrer les détections de cette heure.</p>
@ -64,7 +64,7 @@
<span class="section-title">
<svg class="w-4 h-4 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"/></svg>
Alertes récentes
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Flux d'alertes temps réel</h4>
<p>Dernières détections HIGH/CRITICAL/KNOWN_BOT. Cliquez sur une IP pour démarrer l'investigation.</p>
<p class="doc-source">Source : ml_detected_anomalies ORDER BY detected_at DESC</p>
@ -82,7 +82,7 @@
<div class="section-card">
<div class="section-header">
<span class="section-title">Threat Levels
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Distribution des menaces</h4>
<p>Répartition des sessions par niveau : CRITICAL (score &gt;0.70), HIGH (&gt;0.40), MEDIUM (&gt;0.10), NORMAL, LEGITIMATE_BROWSER, KNOWN_BOT.</p>
<p><strong>Action :</strong> Cliquez sur un segment pour filtrer les détections.</p>
@ -95,7 +95,7 @@
<div class="section-card">
<div class="section-header">
<span class="section-title">Navigateurs
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Familles de navigateurs</h4>
<p>Identification via dictionnaire JA4 → browser_family. Les navigateurs légitimes sont exemptés du scoring ML.</p>
<p class="doc-source">Source : ml_all_scores.browser_family</p>
@ -107,7 +107,7 @@
<div class="lg:col-span-2 section-card">
<div class="section-header">
<span class="section-title">Top 10 IPs suspectes
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>IPs les plus détectées</h4>
<p>IPs avec le plus grand nombre de détections sur 24h. Le score indique le pire score observé.</p>
<p><strong>Action :</strong> Cliquez sur une IP pour l'investiguer en profondeur.</p>
@ -131,7 +131,7 @@
<div class="section-card">
<div class="section-header">
<span class="section-title">Top ASN
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Systèmes autonomes</h4>
<p>ASN les plus représentés. Couleur : <span class="text-green-400">ISP</span> (résidentiel), <span class="text-red-400">Datacenter</span>, <span class="text-orange-400">Hosting</span>.</p>
<p><strong>Action :</strong> Cliquez pour voir les détails réseau.</p>
@ -144,7 +144,7 @@
<div class="section-card">
<div class="section-header">
<span class="section-title">Géographie
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Répartition géographique</h4>
<p>Treemap par pays et type d'ASN. La taille indique le nombre de sessions.</p>
<p class="doc-source">Source : view_ai_features_1h.country_code</p>
@ -158,7 +158,7 @@
<span class="section-title">
<svg class="w-4 h-4 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
Campagnes bots
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn">?</button><div class="doc-panel">
<span class="relative inline-block"><button onclick="docToggle(this)" class="doc-btn"></button><div class="doc-panel">
<h4>Campagnes détectées (HDBSCAN)</h4>
<p>Groupes d'IPs présentant des patterns comportementaux similaires, identifiés par clustering HDBSCAN sur les features ML.</p>
<p><strong>Action :</strong> Une campagne multi-IP indique une attaque coordonnée (botnet, scraping distribué).</p>