Skip to content

Commit eb26f2e

Browse files
committed
feat: add in-app glossary with contextual help popovers (#158)
Add clickable info icons next to DOCSIS technical terms (SNR, Power, Errors, SC-QAM/OFDM, modulation) that show popover explanations. All 4 languages (EN/DE/FR/ES) supported including modulation module.
1 parent 3acf8ff commit eb26f2e

File tree

12 files changed

+254
-15
lines changed

12 files changed

+254
-15
lines changed

app/i18n/de.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,5 +655,14 @@
655655
"connection_failed": "Verbindung fehlgeschlagen",
656656
"theme_toggle": "Design",
657657
"invalid_backup": "Ungültige Backup-Datei",
658-
"restore_failed": "Wiederherstellung fehlgeschlagen"
658+
"restore_failed": "Wiederherstellung fehlgeschlagen",
659+
"glossary_snr": "Signal-Rausch-Abstand: misst die Signalklarheit in Dezibel. Hoher SNR bedeutet sauberen Empfang. Niedriger SNR verursacht Paketverluste und langsame Geschwindigkeiten.",
660+
"glossary_power": "Signalstärke gemessen in dBmV. Zu hoch oder zu niedrig beeinträchtigt die Verbindung. Der ideale Bereich hängt vom Anbieter ab.",
661+
"glossary_correctable": "Datenpakete, die beschädigt ankamen aber automatisch repariert wurden. Viele korrigierbare Fehler sind ein Warnsignal für Kabelprobleme.",
662+
"glossary_uncorrectable": "Datenpakete, die verloren gingen und nicht wiederhergestellt werden konnten. Diese verursachen Ruckeln, Abbrüche und langsame Geschwindigkeiten.",
663+
"glossary_scqam": "SC-QAM (Single-Carrier QAM): traditionelle DOCSIS 3.0-Technologie mit schmalen 6-8 MHz-Kanälen für einzelne Datenströme.",
664+
"glossary_ofdm": "OFDM/OFDMA: DOCSIS 3.1-Technologie mit breiten Kanälen und tausenden Subträgern. Ermöglicht höhere Geschwindigkeiten, ist aber störungsempfindlicher.",
665+
"glossary_modulation": "Modulation (QAM-Stufe): höhere Stufen wie 256QAM oder 4096QAM übertragen mehr Daten pro Signal. Niedrige Modulation deutet auf Signalprobleme hin.",
666+
"glossary_docsis": "DOCSIS 3.0 nutzt SC-QAM-Kanäle. DOCSIS 3.1 ergänzt OFDM/OFDMA für höhere Geschwindigkeiten. Die meisten Modems nutzen beides gleichzeitig (Mixed Mode).",
667+
"glossary_gaming_index": "Gaming-Qualitätsindex: bewertet die Verbindung für Echtzeit-Gaming anhand von Latenz, Jitter und Paketverlust. A/B = super, C = spielbar, D/F = problematisch."
659668
}

app/i18n/en.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,5 +655,14 @@
655655
"connection_failed": "Connection failed",
656656
"theme_toggle": "Theme",
657657
"invalid_backup": "Invalid backup file",
658-
"restore_failed": "Restore failed"
658+
"restore_failed": "Restore failed",
659+
"glossary_snr": "Signal-to-Noise Ratio: measures signal clarity in decibels. Higher is better. Low SNR causes packet loss and slow speeds.",
660+
"glossary_power": "Signal strength measured in dBmV. Too high or too low degrades your connection. The ideal range depends on your ISP.",
661+
"glossary_correctable": "Data packets that arrived damaged but were automatically repaired. Many correctable errors are a warning sign for cable issues.",
662+
"glossary_uncorrectable": "Data packets that were lost and could not be recovered. These cause buffering, dropouts, and slow speeds.",
663+
"glossary_scqam": "SC-QAM (Single-Carrier QAM): traditional DOCSIS 3.0 technology using narrow 6-8 MHz channels for individual data streams.",
664+
"glossary_ofdm": "OFDM/OFDMA: DOCSIS 3.1 technology using wide channels with thousands of subcarriers. Enables higher speeds but is more sensitive to interference.",
665+
"glossary_modulation": "Modulation (QAM level): higher levels like 256QAM or 4096QAM carry more data per signal. Lower modulation indicates signal degradation.",
666+
"glossary_docsis": "DOCSIS 3.0 uses SC-QAM channels. DOCSIS 3.1 adds OFDM/OFDMA for higher speeds. Most modems use both simultaneously (mixed mode).",
667+
"glossary_gaming_index": "Gaming Quality Index: rates your connection for real-time gaming based on latency, jitter, and packet loss. A/B = great, C = playable, D/F = problematic."
659668
}

app/i18n/es.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,5 +650,14 @@
650650
"connection_failed": "Error de conexión",
651651
"theme_toggle": "Tema",
652652
"invalid_backup": "Archivo de respaldo no válido",
653-
"restore_failed": "Error en la restauración"
653+
"restore_failed": "Error en la restauración",
654+
"glossary_snr": "Relación señal/ruido: mide la claridad de la señal en decibelios. Un SNR alto significa recepción limpia. Un SNR bajo causa pérdida de paquetes y velocidades lentas.",
655+
"glossary_power": "Potencia de la señal medida en dBmV. Demasiado alta o baja degrada la conexión. El rango ideal depende del proveedor.",
656+
"glossary_correctable": "Paquetes de datos que llegaron dañados pero se repararon automáticamente. Muchos errores corregibles son una señal de alerta de problemas de cableado.",
657+
"glossary_uncorrectable": "Paquetes de datos perdidos que no pudieron recuperarse. Causan interrupciones, cortes y velocidades lentas.",
658+
"glossary_scqam": "SC-QAM (Single-Carrier QAM): tecnología tradicional DOCSIS 3.0 que usa canales estrechos de 6-8 MHz para flujos de datos individuales.",
659+
"glossary_ofdm": "OFDM/OFDMA: tecnología DOCSIS 3.1 con canales anchos y miles de subportadoras. Permite mayores velocidades pero es más sensible a interferencias.",
660+
"glossary_modulation": "Modulación (nivel QAM): niveles altos como 256QAM o 4096QAM transportan más datos por señal. Una modulación baja indica degradación de la señal.",
661+
"glossary_docsis": "DOCSIS 3.0 usa canales SC-QAM. DOCSIS 3.1 agrega OFDM/OFDMA para mayores velocidades. La mayoría de los módems usan ambos simultáneamente (modo mixto).",
662+
"glossary_gaming_index": "Índice de calidad gaming: evalúa la conexión para juegos en tiempo real según latencia, jitter y pérdida de paquetes. A/B = excelente, C = jugable, D/F = problemático."
654663
}

app/i18n/fr.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,5 +647,14 @@
647647
"connection_failed": "Échec de la connexion",
648648
"theme_toggle": "Thème",
649649
"invalid_backup": "Fichier de sauvegarde invalide",
650-
"restore_failed": "Échec de la restauration"
650+
"restore_failed": "Échec de la restauration",
651+
"glossary_snr": "Rapport signal/bruit : mesure la clarté du signal en décibels. Un SNR élevé signifie une réception propre. Un SNR faible cause des pertes de paquets.",
652+
"glossary_power": "Puissance du signal mesurée en dBmV. Trop élevée ou trop faible, elle dégrade la connexion. La plage idéale dépend du fournisseur.",
653+
"glossary_correctable": "Paquets de données endommagés mais réparés automatiquement. De nombreuses erreurs corrigibles sont un signal d'alerte pour des problèmes de câble.",
654+
"glossary_uncorrectable": "Paquets de données perdus et non récupérables. Ils causent des saccades, des coupures et des vitesses réduites.",
655+
"glossary_scqam": "SC-QAM (Single-Carrier QAM) : technologie DOCSIS 3.0 traditionnelle utilisant des canaux étroits de 6-8 MHz pour des flux de données individuels.",
656+
"glossary_ofdm": "OFDM/OFDMA : technologie DOCSIS 3.1 avec des canaux larges et des milliers de sous-porteuses. Permet des vitesses plus élevées mais plus sensible aux interférences.",
657+
"glossary_modulation": "Modulation (niveau QAM) : des niveaux élevés comme 256QAM ou 4096QAM transportent plus de données par signal. Une modulation basse indique une dégradation du signal.",
658+
"glossary_docsis": "DOCSIS 3.0 utilise des canaux SC-QAM. DOCSIS 3.1 ajoute OFDM/OFDMA pour des vitesses supérieures. La plupart des modems utilisent les deux simultanément (mode mixte).",
659+
"glossary_gaming_index": "Indice de qualité gaming : évalue la connexion pour le jeu en temps réel selon la latence, le jitter et la perte de paquets. A/B = excellent, C = jouable, D/F = problématique."
651660
}

app/modules/modulation/i18n/de.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
"click_day_hint": "Klicken Sie auf einen Tagesbalken für Kanaldetails",
2222
"no_degradation": "Keine Degradation beobachtet",
2323
"channel_summary": "Kanalzusammenfassung",
24-
"protocol_group_label": "Protokollgruppe"
24+
"protocol_group_label": "Protokollgruppe",
25+
"glossary_health_index": "Gesundheitsindex: ein Gesamtwert (0-100), der die Modulationsqualität aller Kanäle widerspiegelt. Höher bedeutet weniger Signaldegradation.",
26+
"glossary_low_qam": "Low-QAM-Anteil: Anteil der Zeit, in der Kanäle auf niedrige Modulationsstufen (QPSK, 16QAM) fallen. Hoher Anteil deutet auf anhaltende Signalprobleme hin.",
27+
"glossary_sample_density": "Messabdeckung: Anzahl der gesammelten Polling-Messungen im gewählten Zeitraum. Mehr Messungen bedeuten genauere Statistiken."
2528
}

app/modules/modulation/i18n/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
"click_day_hint": "Click a day bar to view per-channel details",
2222
"no_degradation": "No degradation observed",
2323
"channel_summary": "Channel Summary",
24-
"protocol_group_label": "Protocol Group"
24+
"protocol_group_label": "Protocol Group",
25+
"glossary_health_index": "Health Index: an aggregate score (0-100) reflecting overall modulation quality across all channels. Higher means less signal degradation.",
26+
"glossary_low_qam": "Low-QAM Exposure: percentage of time channels drop to low modulation levels (QPSK, 16QAM). High exposure indicates persistent signal problems.",
27+
"glossary_sample_density": "Sample Density: number of polling samples collected for the selected period. More samples mean more accurate statistics."
2528
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"title": "Rendimiento de modulación",
3+
"upstream": "Upstream",
4+
"downstream": "Downstream",
5+
"today": "Hoy",
6+
"days_label": "Días",
7+
"health_index": "Índice de salud",
8+
"low_qam_exposure": "Exposición Low-QAM",
9+
"low_qam_pct": "Low-QAM %",
10+
"sample_density": "Densidad de muestras",
11+
"samples": "muestras",
12+
"distribution_chart": "Distribución de modulación",
13+
"trend_chart": "Tendencia salud & Low-QAM",
14+
"no_data": "No hay datos de modulación disponibles para el período seleccionado.",
15+
"back_to_overview": "Volver al resumen",
16+
"intraday_title": "Detalle del canal",
17+
"channels_label": "Canales",
18+
"dominant_modulation": "Dominante",
19+
"degraded_channels": "degradados",
20+
"disclaimer": "Los índices de salud y las estadísticas de modulación son estimaciones basadas en muestras periódicas.",
21+
"click_day_hint": "Haga clic en una barra de día para ver los detalles por canal",
22+
"no_degradation": "No se observó degradación",
23+
"channel_summary": "Resumen de canales",
24+
"protocol_group_label": "Grupo de protocolo",
25+
"glossary_health_index": "Índice de salud: puntuación global (0-100) que refleja la calidad de modulación en todos los canales. Mayor significa menos degradación.",
26+
"glossary_low_qam": "Exposición Low-QAM: porcentaje de tiempo en que los canales caen a niveles bajos de modulación (QPSK, 16QAM). Alta exposición indica problemas de señal persistentes.",
27+
"glossary_sample_density": "Densidad de muestras: número de mediciones recopiladas para el período seleccionado. Más muestras significan estadísticas más precisas."
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"title": "Performance de modulation",
3+
"upstream": "Upstream",
4+
"downstream": "Downstream",
5+
"today": "Aujourd'hui",
6+
"days_label": "Jours",
7+
"health_index": "Indice de santé",
8+
"low_qam_exposure": "Exposition Low-QAM",
9+
"low_qam_pct": "Low-QAM %",
10+
"sample_density": "Densité d'échantillons",
11+
"samples": "échantillons",
12+
"distribution_chart": "Distribution de modulation",
13+
"trend_chart": "Tendance santé & Low-QAM",
14+
"no_data": "Aucune donnée de modulation disponible pour la période sélectionnée.",
15+
"back_to_overview": "Retour à l'aperçu",
16+
"intraday_title": "Détail du canal",
17+
"channels_label": "Canaux",
18+
"dominant_modulation": "Dominante",
19+
"degraded_channels": "dégradés",
20+
"disclaimer": "Les indices de santé et les statistiques de modulation sont des estimations basées sur des échantillons périodiques.",
21+
"click_day_hint": "Cliquez sur une barre de jour pour voir les détails par canal",
22+
"no_degradation": "Aucune dégradation observée",
23+
"channel_summary": "Résumé des canaux",
24+
"protocol_group_label": "Groupe de protocole",
25+
"glossary_health_index": "Indice de santé : score global (0-100) reflétant la qualité de modulation sur tous les canaux. Plus élevé signifie moins de dégradation.",
26+
"glossary_low_qam": "Exposition Low-QAM : pourcentage de temps où les canaux passent en modulation basse (QPSK, 16QAM). Une exposition élevée indique des problèmes de signal persistants.",
27+
"glossary_sample_density": "Densité d'échantillons : nombre de mesures collectées pour la période sélectionnée. Plus de mesures signifie des statistiques plus précises."
28+
}

app/modules/modulation/templates/modulation_tab.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,17 @@ <h2 style="margin:0; flex:1;">{{ t.get('docsight.modulation.title', 'Modulation
1818
<!-- KPI Cards (aggregate) -->
1919
<div class="modulation-kpi-row" id="modulation-kpis">
2020
<div class="chart-card modulation-kpi-card">
21-
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.health_index', 'Health Index') }}</div>
21+
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.health_index', 'Health Index') }} <span class="glossary-hint"><i data-lucide="info"></i><div class="glossary-popover">{{ t.get('docsight.modulation.glossary_health_index', '') }}</div></span></div>
2222
<div class="modulation-kpi-value" id="mod-kpi-health"></div>
2323
<div class="modulation-kpi-sub" id="mod-kpi-health-delta"></div>
2424
</div>
2525
<div class="chart-card modulation-kpi-card">
26-
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.low_qam_exposure', 'Low-QAM Exposure') }}</div>
26+
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.low_qam_exposure', 'Low-QAM Exposure') }} <span class="glossary-hint"><i data-lucide="info"></i><div class="glossary-popover">{{ t.get('docsight.modulation.glossary_low_qam', '') }}</div></span></div>
2727
<div class="modulation-kpi-value" id="mod-kpi-lowqam"></div>
2828
<div class="modulation-kpi-sub" id="mod-kpi-lowqam-hint"></div>
2929
</div>
3030
<div class="chart-card modulation-kpi-card">
31-
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.sample_density', 'Sample Density') }}</div>
31+
<div class="modulation-kpi-label">{{ t.get('docsight.modulation.sample_density', 'Sample Density') }} <span class="glossary-hint"><i data-lucide="info"></i><div class="glossary-popover">{{ t.get('docsight.modulation.glossary_sample_density', '') }}</div></span></div>
3232
<div class="modulation-kpi-value" id="mod-kpi-density"></div>
3333
<div class="modulation-kpi-sub" id="mod-kpi-density-hint"></div>
3434
</div>

app/static/css/glossary.css

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/* glossary.css — Contextual help popovers for DOCSIS terms */
2+
3+
.glossary-hint {
4+
display: inline-flex;
5+
align-items: center;
6+
cursor: pointer;
7+
position: relative;
8+
margin-left: 4px;
9+
vertical-align: middle;
10+
}
11+
12+
.glossary-hint > i,
13+
.glossary-hint > svg {
14+
width: 13px;
15+
height: 13px;
16+
color: var(--text-muted);
17+
opacity: 0.6;
18+
transition: opacity 0.2s, color 0.2s;
19+
}
20+
21+
.glossary-hint:hover > i,
22+
.glossary-hint:hover > svg {
23+
opacity: 1;
24+
color: var(--amethyst-light);
25+
}
26+
27+
.glossary-popover {
28+
display: none;
29+
position: absolute;
30+
left: 50%;
31+
top: calc(100% + 8px);
32+
transform: translateX(-50%);
33+
width: max-content;
34+
max-width: 320px;
35+
padding: 12px 16px;
36+
background: var(--surface);
37+
border: 1px solid var(--glass-border);
38+
border-radius: var(--radius-sm);
39+
box-shadow: var(--shadow-md);
40+
color: var(--text-secondary);
41+
font-size: 0.8rem;
42+
font-weight: 400;
43+
line-height: 1.5;
44+
z-index: 500;
45+
pointer-events: auto;
46+
white-space: normal;
47+
}
48+
49+
/* Flip above when near bottom */
50+
.glossary-popover.above {
51+
top: auto;
52+
bottom: calc(100% + 8px);
53+
}
54+
55+
/* Arrow */
56+
.glossary-popover::before {
57+
content: '';
58+
position: absolute;
59+
left: 50%;
60+
top: -5px;
61+
transform: translateX(-50%) rotate(45deg);
62+
width: 8px;
63+
height: 8px;
64+
background: var(--surface);
65+
border-left: 1px solid var(--glass-border);
66+
border-top: 1px solid var(--glass-border);
67+
}
68+
69+
.glossary-popover.above::before {
70+
top: auto;
71+
bottom: -5px;
72+
border-left: none;
73+
border-top: none;
74+
border-right: 1px solid var(--glass-border);
75+
border-bottom: 1px solid var(--glass-border);
76+
}
77+
78+
/* Open state */
79+
.glossary-hint.open .glossary-popover {
80+
display: block;
81+
}
82+
83+
/* Mobile: full width */
84+
@media (max-width: 768px) {
85+
.glossary-popover {
86+
position: fixed;
87+
left: 16px;
88+
right: 16px;
89+
top: auto;
90+
bottom: calc(var(--bottom-nav-h) + 16px);
91+
transform: none;
92+
width: auto;
93+
max-width: none;
94+
}
95+
.glossary-popover::before {
96+
display: none;
97+
}
98+
}

0 commit comments

Comments
 (0)