Skip to content

Commit e4eb993

Browse files
committed
refactor: align BNetzA page with app design system
Replace all Unicode emojis with Lucide SVG icons (expand, complaint, PDF, delete, refresh, verdict). Move inline JS styles to CSS classes in the BNetzA module stylesheet, matching Speedtest patterns. - Expand arrow: chevron-right with CSS rotate animation - Verdict: circle-check (green) / triangle-alert (red) icons with i18n tooltip - Action buttons: file-pen, file-down, trash-2 with hover effects - Detail tables: CSS classes replace inline grid/font/border styles - Complaint textarea: use var(--font-mono) instead of hardcoded fonts - Promote val-good/val-warn/val-crit to global utilities (fixes existing broken color coding in Speedtest table)
1 parent 621c4c3 commit e4eb993

File tree

4 files changed

+105
-42
lines changed

4 files changed

+105
-42
lines changed

app/modules/bnetz/static/style.css

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,70 @@
11
/* BNetzA — Module Styles */
22

3-
.bnetz-expand-arrow {
4-
display: inline-block;
5-
font-size: 0.7em;
6-
transition: transform 0.2s;
7-
color: var(--text-secondary);
8-
margin-right: 4px;
3+
/* Expand/collapse button (mirrors .st-expand-btn from Speedtest) */
4+
.bnetz-expand-btn {
5+
background: none; border: none; cursor: pointer; padding: 4px;
6+
color: var(--text-muted); display: inline-flex; align-items: center; justify-content: center;
7+
transition: transform 0.2s ease, color 0.2s ease;
8+
vertical-align: middle;
9+
}
10+
.bnetz-expand-btn:hover { color: var(--text-primary); }
11+
.bnetz-expand-btn.open { transform: rotate(90deg); color: var(--accent); }
12+
.bnetz-expand-btn i { width: 14px; height: 14px; }
13+
14+
/* Refresh button (mirrors #speedtest-refresh-btn) */
15+
.bnetz-refresh-btn {
16+
background: none; border: none; cursor: pointer; padding: 6px;
17+
color: var(--text-muted); display: inline-flex; align-items: center; justify-content: center;
18+
border-radius: var(--radius-sm); transition: color 0.2s ease, background 0.2s ease;
19+
}
20+
.bnetz-refresh-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.06); }
21+
.bnetz-refresh-btn i { width: 16px; height: 16px; }
22+
23+
/* Inline action icons (complaint, PDF, delete) */
24+
.bnetz-actions-cell { white-space: nowrap; }
25+
.bnetz-action-btn {
26+
display: inline-flex; align-items: center; justify-content: center;
27+
padding: 4px; margin-right: 4px; border-radius: var(--radius-sm, 4px);
28+
color: var(--text-muted); text-decoration: none;
29+
transition: color 0.2s ease, background 0.2s ease;
30+
}
31+
.bnetz-action-btn:hover { color: var(--accent); background: rgba(168,85,247,0.1); }
32+
.bnetz-action-btn i { width: 15px; height: 15px; }
33+
.bnetz-action-delete:hover { color: var(--crit); background: rgba(239,68,68,0.1); }
34+
35+
/* Verdict icon */
36+
.bnetz-verdict { text-align: center; }
37+
.bnetz-verdict i { width: 18px; height: 18px; }
38+
39+
/* Detail expand cell */
40+
.bnetz-detail-cell { padding: 0 8px 12px 24px; }
41+
42+
/* Detail grid (Download / Upload side-by-side) */
43+
.bnetz-detail-grid {
44+
display: grid; grid-template-columns: 1fr 1fr;
45+
gap: 16px; margin-top: 8px;
46+
}
47+
48+
/* Section label (Download / Upload) */
49+
.bnetz-detail-label {
50+
font-size: 0.85em; font-weight: 600; color: var(--text-secondary);
51+
display: block; margin-bottom: 4px;
52+
}
53+
54+
/* Compact measurement table */
55+
.bnetz-detail-table {
56+
width: 100%; font-size: 0.8em; border-collapse: collapse;
57+
}
58+
.bnetz-detail-table th {
59+
text-align: left; padding: 3px 6px; font-weight: 600;
60+
color: var(--text-secondary); border-bottom: 1px solid var(--card-border);
61+
}
62+
.bnetz-detail-table td {
63+
padding: 3px 6px;
64+
}
65+
.bnetz-detail-table tr + tr { border-bottom: 1px solid var(--card-border); }
66+
.bnetz-detail-speed-col { text-align: right; }
67+
68+
@media (max-width: 600px) {
69+
.bnetz-detail-grid { grid-template-columns: 1fr; }
970
}

app/static/css/main.css

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -613,9 +613,10 @@ body.is-offline .offline-banner { display: flex; }
613613
}
614614
.channel-table tbody tr { min-height: 44px; }
615615
.channel-table tbody tr:active { background: rgba(255,255,255,0.04); }
616-
.channel-table .val-good { color: var(--good); }
617-
.channel-table .val-warn { color: var(--warn); }
618-
.channel-table .val-crit { color: var(--crit); }
616+
/* Value color utilities (used across channel, BNetzA, speedtest tables) */
617+
.val-good { color: var(--good); }
618+
.val-warn { color: var(--warn); }
619+
.val-crit { color: var(--crit); }
619620

620621
.channel-table th:first-child,
621622
.channel-table td:first-child {

app/static/js/integrations.js

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ function loadBnetzData() {
2121
tbody.innerHTML = '';
2222
data.forEach(function(m, idx) {
2323
var hasDeviation = m.verdict_download === 'deviation' || m.verdict_upload === 'deviation';
24+
var verdictIcon = hasDeviation
25+
? '<i data-lucide="triangle-alert"></i>'
26+
: '<i data-lucide="circle-check"></i>';
2427
var verdictText = hasDeviation ? T.bnetz_verdict_deviation : T.bnetz_verdict_ok;
2528
var verdictClass = hasDeviation ? 'val-crit' : 'val-good';
2629
var dlPct = m.download_max_tariff ? Math.round(m.download_measured_avg / m.download_max_tariff * 100) : 0;
@@ -36,21 +39,21 @@ function loadBnetzData() {
3639
}
3740
var complaintBtn = '';
3841
if (hasDeviation) {
39-
complaintBtn = '<a href="javascript:void(0)" onclick="generateBnetzComplaint(' + m.id + ')" ' +
40-
'title="' + (T.bnetz_generate_complaint || 'Generate complaint') + '" ' +
41-
'style="margin-right:8px;">&#9998;</a>';
42+
complaintBtn = '<a href="javascript:void(0)" class="bnetz-action-btn" onclick="generateBnetzComplaint(' + m.id + ')" ' +
43+
'title="' + (T.bnetz_generate_complaint || 'Generate complaint') + '">' +
44+
'<i data-lucide="file-pen"></i></a>';
4245
}
43-
tr.innerHTML = '<td>' + (hasMeasurements ? '<span class="bnetz-expand-arrow" id="bnetz-arrow-' + idx + '">&#9654;</span> ' : '') + m.date + '</td>' +
46+
tr.innerHTML = '<td>' + (hasMeasurements ? '<button class="bnetz-expand-btn" id="bnetz-arrow-' + idx + '"><i data-lucide="chevron-right"></i></button> ' : '') + m.date + '</td>' +
4447
'<td>' + (m.provider || '-') + '</td>' +
4548
'<td>' + Math.round(m.download_max_tariff || 0) + ' Mbit/s</td>' +
4649
'<td>' + Math.round(m.download_measured_avg || 0) + ' Mbit/s (' + dlPct + '%)</td>' +
4750
'<td>' + Math.round(m.upload_max_tariff || 0) + ' Mbit/s</td>' +
4851
'<td>' + Math.round(m.upload_measured_avg || 0) + ' Mbit/s (' + ulPct + '%)</td>' +
49-
'<td class="' + verdictClass + '">' + verdictText + '</td>' +
50-
'<td style="white-space:nowrap;" onclick="event.stopPropagation();">' +
52+
'<td class="bnetz-verdict ' + verdictClass + '" title="' + verdictText + '">' + verdictIcon + '</td>' +
53+
'<td class="bnetz-actions-cell" onclick="event.stopPropagation();">' +
5154
complaintBtn +
52-
(m.source !== 'csv_import' ? '<a href="/api/bnetz/pdf/' + m.id + '" title="PDF" style="margin-right:8px;">&#128196;</a>' : '') +
53-
'<a href="javascript:void(0)" onclick="deleteBnetzFromView(' + m.id + ')" title="' + (T.delete_incident || 'Delete') + '">&#128465;</a>' +
55+
(m.source !== 'csv_import' ? '<a href="/api/bnetz/pdf/' + m.id + '" class="bnetz-action-btn" title="PDF"><i data-lucide="file-down"></i></a>' : '') +
56+
'<a href="javascript:void(0)" class="bnetz-action-btn bnetz-action-delete" onclick="deleteBnetzFromView(' + m.id + ')" title="' + (T.delete_incident || 'Delete') + '"><i data-lucide="trash-2"></i></a>' +
5457
'</td>';
5558
tbody.appendChild(tr);
5659
// Detail expand row (hidden by default)
@@ -60,7 +63,7 @@ function loadBnetzData() {
6063
detailTr.style.display = 'none';
6164
var detailTd = document.createElement('td');
6265
detailTd.colSpan = 8;
63-
detailTd.style.padding = '0 8px 12px 24px';
66+
detailTd.className = 'bnetz-detail-cell';
6467
detailTd.innerHTML = buildBnetzDetailHtml(m);
6568
detailTr.appendChild(detailTd);
6669
tbody.appendChild(detailTr);
@@ -103,51 +106,49 @@ function toggleBnetzDetail(idx) {
103106
if (!row) return;
104107
var isOpen = row.style.display !== 'none';
105108
row.style.display = isOpen ? 'none' : 'table-row';
106-
if (arrow) arrow.innerHTML = isOpen ? '&#9654;' : '&#9660;';
109+
if (arrow) arrow.classList.toggle('open', !isOpen);
107110
}
108111

109112
function buildBnetzDetailHtml(m) {
110113
var ms = m.measurements || {};
111114
var dlList = ms.download || [];
112115
var ulList = ms.upload || [];
113-
var html = '<div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:8px;">';
116+
var html = '<div class="bnetz-detail-grid">';
114117
// Download measurements
115118
if (dlList.length > 0) {
116-
html += '<div><strong style="font-size:0.85em;color:var(--text-secondary);">' + (T.download || 'Download') + '</strong>';
117-
html += '<table style="width:100%;font-size:0.8em;border-collapse:collapse;margin-top:4px;">';
118-
html += '<tr style="color:var(--text-secondary);border-bottom:1px solid var(--card-border);">' +
119-
'<th style="text-align:left;padding:3px 6px;">' + (T.bnetz_measurement_nr || 'Nr.') + '</th>' +
120-
'<th style="text-align:left;padding:3px 6px;">' + (T.bnetz_measurement_time || 'Time') + '</th>' +
121-
'<th style="text-align:right;padding:3px 6px;">' + (T.bnetz_measurement_speed || 'Speed') + '</th></tr>';
119+
html += '<div><span class="bnetz-detail-label">' + (T.download || 'Download') + '</span>';
120+
html += '<table class="bnetz-detail-table">';
121+
html += '<tr><th>' + (T.bnetz_measurement_nr || 'Nr.') + '</th>' +
122+
'<th>' + (T.bnetz_measurement_time || 'Time') + '</th>' +
123+
'<th class="bnetz-detail-speed-col">' + (T.bnetz_measurement_speed || 'Speed') + '</th></tr>';
122124
dlList.forEach(function(meas, i) {
123125
var speed = meas.speed || meas.value || 0;
124126
var color = 'var(--text)';
125127
if (m.download_min_tariff && speed < m.download_min_tariff) color = 'var(--crit)';
126128
else if (m.download_normal_tariff && speed < m.download_normal_tariff) color = 'var(--warn, orange)';
127-
html += '<tr style="border-bottom:1px solid var(--card-border);">' +
128-
'<td style="padding:3px 6px;">' + (i + 1) + '</td>' +
129-
'<td style="padding:3px 6px;">' + (meas.date || '') + ' ' + (meas.time || '') + '</td>' +
130-
'<td style="text-align:right;padding:3px 6px;color:' + color + ';">' + (typeof speed === 'number' ? speed.toFixed(1) : speed) + ' Mbit/s</td></tr>';
129+
html += '<tr>' +
130+
'<td>' + (i + 1) + '</td>' +
131+
'<td>' + (meas.date || '') + ' ' + (meas.time || '') + '</td>' +
132+
'<td class="bnetz-detail-speed-col" style="color:' + color + ';">' + (typeof speed === 'number' ? speed.toFixed(1) : speed) + ' Mbit/s</td></tr>';
131133
});
132134
html += '</table></div>';
133135
}
134136
// Upload measurements
135137
if (ulList.length > 0) {
136-
html += '<div><strong style="font-size:0.85em;color:var(--text-secondary);">' + (T.upload || 'Upload') + '</strong>';
137-
html += '<table style="width:100%;font-size:0.8em;border-collapse:collapse;margin-top:4px;">';
138-
html += '<tr style="color:var(--text-secondary);border-bottom:1px solid var(--card-border);">' +
139-
'<th style="text-align:left;padding:3px 6px;">' + (T.bnetz_measurement_nr || 'Nr.') + '</th>' +
140-
'<th style="text-align:left;padding:3px 6px;">' + (T.bnetz_measurement_time || 'Time') + '</th>' +
141-
'<th style="text-align:right;padding:3px 6px;">' + (T.bnetz_measurement_speed || 'Speed') + '</th></tr>';
138+
html += '<div><span class="bnetz-detail-label">' + (T.upload || 'Upload') + '</span>';
139+
html += '<table class="bnetz-detail-table">';
140+
html += '<tr><th>' + (T.bnetz_measurement_nr || 'Nr.') + '</th>' +
141+
'<th>' + (T.bnetz_measurement_time || 'Time') + '</th>' +
142+
'<th class="bnetz-detail-speed-col">' + (T.bnetz_measurement_speed || 'Speed') + '</th></tr>';
142143
ulList.forEach(function(meas, i) {
143144
var speed = meas.speed || meas.value || 0;
144145
var color = 'var(--text)';
145146
if (m.upload_min_tariff && speed < m.upload_min_tariff) color = 'var(--crit)';
146147
else if (m.upload_normal_tariff && speed < m.upload_normal_tariff) color = 'var(--warn, orange)';
147-
html += '<tr style="border-bottom:1px solid var(--card-border);">' +
148-
'<td style="padding:3px 6px;">' + (i + 1) + '</td>' +
149-
'<td style="padding:3px 6px;">' + (meas.date || '') + ' ' + (meas.time || '') + '</td>' +
150-
'<td style="text-align:right;padding:3px 6px;color:' + color + ';">' + (typeof speed === 'number' ? speed.toFixed(1) : speed) + ' Mbit/s</td></tr>';
148+
html += '<tr>' +
149+
'<td>' + (i + 1) + '</td>' +
150+
'<td>' + (meas.date || '') + ' ' + (meas.time || '') + '</td>' +
151+
'<td class="bnetz-detail-speed-col" style="color:' + color + ';">' + (typeof speed === 'number' ? speed.toFixed(1) : speed) + ' Mbit/s</td></tr>';
151152
});
152153
html += '</table></div>';
153154
}

app/templates/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,7 +1676,7 @@ <h3 class="gaming-section-title">{{ t.gaming_genres_title }}</h3>
16761676
<i data-lucide="upload" style="width:14px;height:14px;vertical-align:-2px;"></i> {{ t.bnetz_upload }}
16771677
<input type="file" accept=".pdf,.csv" id="bnetz-file-input" style="display:none;" onchange="uploadBnetzFromView(this)">
16781678
</label>
1679-
<button class="refresh-btn" title="{{ t.refresh }}" onclick="loadBnetzData()">&#x1F504;</button>
1679+
<button class="refresh-btn bnetz-refresh-btn" title="{{ t.refresh }}" onclick="loadBnetzData()"><i data-lucide="refresh-cw"></i></button>
16801680
</div>
16811681
</div>
16821682
<div id="bnetz-watcher-status" style="display:none;padding:8px 14px;margin-bottom:10px;border-radius:8px;background:var(--card-bg);border:1px solid var(--input-border);font-size:0.85em;color:var(--text-muted);align-items:center;gap:8px;">
@@ -1864,7 +1864,7 @@ <h2>{{ t.incident_report }}</h2>
18641864
<!-- Step 2: Generated complaint text (hidden initially) -->
18651865
<div id="report-step2" style="display:none;">
18661866
<p style="font-size:13px; color:var(--muted); margin-bottom:8px;">{{ t.report_edit_hint }}</p>
1867-
<textarea id="report-complaint-text" style="width:100%; min-height:320px; background:var(--bg); color:var(--text); border:1px solid var(--border); border-radius:6px; padding:12px; font-size:0.85em; font-family:'Consolas','Monaco',monospace; resize:vertical; line-height:1.5;"></textarea>
1867+
<textarea id="report-complaint-text" style="width:100%; min-height:320px; background:var(--bg); color:var(--text); border:1px solid var(--border); border-radius:6px; padding:12px; font-size:0.85em; font-family:var(--font-mono); resize:vertical; line-height:1.5;"></textarea>
18681868
</div>
18691869
</div>
18701870
<div class="modal-footer">

0 commit comments

Comments
 (0)