fix(dashboard): clean speed display via fmtSpd() — 1.00G→1G, 400.00G→400G, 1600→1.6T

This commit is contained in:
Rene Fichtmueller 2026-06-05 22:38:13 +00:00
parent e103a99822
commit f2b26e3286

View File

@ -722,6 +722,19 @@
<!-- Auth guard — redirect to login if no valid token --> <!-- Auth guard — redirect to login if no valid token -->
<script> <script>
// fmtSpd: "1.00" → "1G", "10.00" → "10G", "2.5" → "2.5G", "1600" → "1.6T"
// 1.6 Tbit/s (1600 Gbps) behält die Dezimalstelle, alle ganzzahligen Speeds nicht.
function fmtSpd(gbps) {
if (gbps === null || gbps === undefined || gbps === '') return '?';
var n = parseFloat(gbps);
if (isNaN(n) || n === 0) return '?';
if (n >= 1000) {
var t = n / 1000;
return ((t * 10) % 10 === 0 ? Math.round(t) : t.toFixed(1)) + 'T';
}
return ((n * 10) % 10 === 0 ? Math.round(n) : n) + 'G';
}
// ── Token storage helpers — never store plaintext ────────────────────────── // ── Token storage helpers — never store plaintext ──────────────────────────
(function() { (function() {
var _K = 'tip_v3_tk'; var _K = 'tip_v3_tk';
@ -4642,7 +4655,7 @@ async function openTxDetail(id) {
+ '<td style="color:' + compColor + ';font-size:0.7rem;padding:2px 0">' + esc(compVal || '—') + '</td></tr>'; + '<td style="color:' + compColor + ';font-size:0.7rem;padding:2px 0">' + esc(compVal || '—') + '</td></tr>';
} }
var mySpeed = t.speed_gbps >= 1000 ? (t.speed_gbps / 1000).toFixed(1).replace('.0','') + 'T' : t.speed_gbps + 'G'; var mySpeed = t.speed_gbps >= 1000 ? (t.speed_gbps / 1000).toFixed(1).replace('.0','') + 'T' : fmtSpd(t.speed_gbps);
var compSpeed = p.comp_speed_gbps ? (p.comp_speed_gbps >= 1000 ? (p.comp_speed_gbps/1000).toFixed(1).replace('.0','')+'T' : p.comp_speed_gbps+'G') : null; var compSpeed = p.comp_speed_gbps ? (p.comp_speed_gbps >= 1000 ? (p.comp_speed_gbps/1000).toFixed(1).replace('.0','')+'T' : p.comp_speed_gbps+'G') : null;
h += '<div style="border:1px solid var(--border);border-radius:8px;margin-bottom:0.6rem;overflow:hidden">'; h += '<div style="border:1px solid var(--border);border-radius:8px;margin-bottom:0.6rem;overflow:hidden">';
@ -5438,12 +5451,7 @@ async function openSwitchDetail(id) {
fch += '<div style="font-size:0.72rem;color:var(--text-dim);margin-bottom:0.6rem">Passend für diesen Switch — FlexBox-Codierung möglich</div>'; fch += '<div style="font-size:0.72rem;color:var(--text-dim);margin-bottom:0.6rem">Passend für diesen Switch — FlexBox-Codierung möglich</div>';
// Format speed_gbps → "1.6T", "400G", "100G" etc. // Format speed_gbps → "1.6T", "400G", "100G" etc.
function fmtSpeed(gbps) { var fmtSpeed = fmtSpd; // use global
if (!gbps) return '?';
var n = parseFloat(gbps);
if (n >= 1000) return (n / 1000) + 'T';
return Math.round(n) + 'G';
}
// Group by speed class // Group by speed class
var foGroups = {}; var foGroups = {};
@ -6930,7 +6938,7 @@ async function runFinder() {
// Group by speed class // Group by speed class
var bySpeed = {}; var bySpeed = {};
for (var t of transceivers) { for (var t of transceivers) {
var key = t.speed_gbps + 'G ' + t.form_factor; var key = fmtSpd(t.speed_gbps) + ' ' + t.form_factor;
if (!bySpeed[key]) bySpeed[key] = []; if (!bySpeed[key]) bySpeed[key] = [];
bySpeed[key].push(t); bySpeed[key].push(t);
} }
@ -8259,7 +8267,7 @@ function renderSignals(filterSig) {
+ imgHtml + imgHtml
+ '<div style="flex:1;min-width:0">' + '<div style="flex:1;min-width:0">'
+ '<div style="font-weight:700;font-size:0.82rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + esc(productName) + (r.is_demo_data || r.is_demo ? demoBadgeHtml : '') + '</div>' + '<div style="font-weight:700;font-size:0.82rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">' + esc(productName) + (r.is_demo_data || r.is_demo ? demoBadgeHtml : '') + '</div>'
+ '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(r.form_factor || '') + (r.speed_gbps ? ' · ' + r.speed_gbps + 'G' : '') + (r.vendor_name ? ' · ' + esc(r.vendor_name) : '') + '</div>' + '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(r.form_factor || '') + (r.speed_gbps ? ' · ' + fmtSpd(r.speed_gbps) : '') + (r.vendor_name ? ' · ' + esc(r.vendor_name) : '') + '</div>'
+ '</div>' + '</div>'
+ '</div>' + '</div>'
+ '<div style="display:flex;gap:0.4rem;align-items:center;margin-bottom:0.6rem;flex-wrap:wrap">' + '<div style="display:flex;gap:0.4rem;align-items:center;margin-bottom:0.6rem;flex-wrap:wrap">'
@ -8472,7 +8480,7 @@ function filterVelocity(cls) {
+ '<td style="padding:7px 6px"><span style="font-size:1rem" title="' + esc(r.velocity_class) + '">' + velIcon + '</span></td>' + '<td style="padding:7px 6px"><span style="font-size:1rem" title="' + esc(r.velocity_class) + '">' + velIcon + '</span></td>'
+ '<td style="padding:7px 6px"><div style="font-weight:600;font-size:0.82rem">' + esc(productName || '—') + '</div>' + '<td style="padding:7px 6px"><div style="font-weight:600;font-size:0.82rem">' + esc(productName || '—') + '</div>'
+ '<div style="font-size:0.68rem;color:var(--text-dim)">' + esc(r.sku) + (r.vendor_name ? ' · ' + esc(r.vendor_name) : '') + '</div></td>' + '<div style="font-size:0.68rem;color:var(--text-dim)">' + esc(r.sku) + (r.vendor_name ? ' · ' + esc(r.vendor_name) : '') + '</div></td>'
+ '<td style="padding:7px 6px;font-size:0.75rem;color:var(--text-dim)">' + esc(r.form_factor || '—') + (r.speed_gbps ? ' ' + r.speed_gbps + 'G' : '') + '</td>' + '<td style="padding:7px 6px;font-size:0.75rem;color:var(--text-dim)">' + esc(r.form_factor || '—') + (r.speed_gbps ? ' ' + fmtSpd(r.speed_gbps) : '') + '</td>'
+ '<td style="padding:7px 6px;text-align:right;font-weight:700;color:' + velColor + '">' + (demand12 > 0 ? demand12.toLocaleString(undefined,{maximumFractionDigits:0}) : '—') + '</td>' + '<td style="padding:7px 6px;text-align:right;font-weight:700;color:' + velColor + '">' + (demand12 > 0 ? demand12.toLocaleString(undefined,{maximumFractionDigits:0}) : '—') + '</td>'
+ '<td style="padding:7px 6px;text-align:right;color:var(--text-dim)">' + (demand3 > 0 ? demand3.toLocaleString(undefined,{maximumFractionDigits:0}) : '—') + '</td>' + '<td style="padding:7px 6px;text-align:right;color:var(--text-dim)">' + (demand3 > 0 ? demand3.toLocaleString(undefined,{maximumFractionDigits:0}) : '—') + '</td>'
+ '<td style="padding:7px 6px;text-align:right">' + trendHtml + '</td>' + '<td style="padding:7px 6px;text-align:right">' + trendHtml + '</td>'
@ -9875,7 +9883,7 @@ async function loadStock() {
var momColor = momentum >= 1.05 ? '#22c55e' : momentum >= 0.95 ? '#f59e0b' : '#ef4444'; var momColor = momentum >= 1.05 ? '#22c55e' : momentum >= 0.95 ? '#f59e0b' : '#ef4444';
var trendArrow = momentum >= 1.1 ? '▲▲' : momentum >= 1.02 ? '▲' : momentum >= 0.98 ? '→' : momentum >= 0.9 ? '▼' : '▼▼'; var trendArrow = momentum >= 1.1 ? '▲▲' : momentum >= 1.02 ? '▲' : momentum >= 0.98 ? '→' : momentum >= 0.9 ? '▼' : '▼▼';
var trendColor = momentum >= 1.05 ? '#22c55e' : momentum >= 0.95 ? '#f59e0b' : '#ef4444'; var trendColor = momentum >= 1.05 ? '#22c55e' : momentum >= 0.95 ? '#f59e0b' : '#ef4444';
var tech = (r.speed_gbps || '?') + 'G ' + (r.form_factor || ''); var tech = fmtSpd(r.speed_gbps) + ' ' + (r.form_factor || '');
var fastBadge = Number(r.fast_movers || 0) > 0 var fastBadge = Number(r.fast_movers || 0) > 0
? '<span style="background:#6366f122;color:#818cf8;border-radius:10px;padding:1px 7px;font-size:0.65rem;font-weight:700">' + r.fast_movers + '</span>' ? '<span style="background:#6366f122;color:#818cf8;border-radius:10px;padding:1px 7px;font-size:0.65rem;font-weight:700">' + r.fast_movers + '</span>'
: '<span style="color:var(--text-dim)"></span>'; : '<span style="color:var(--text-dim)"></span>';
@ -11004,7 +11012,7 @@ function renderWatchlist() {
return '<div style="background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:0.7rem 0.85rem;margin-bottom:0.5rem;display:flex;align-items:center;gap:0.75rem">' return '<div style="background:var(--surface2);border:1px solid var(--border);border-radius:8px;padding:0.7rem 0.85rem;margin-bottom:0.5rem;display:flex;align-items:center;gap:0.75rem">'
+ '<div style="flex:1;cursor:pointer" onclick="openTxDetail(\'' + esc(String(t.id || t.transceiver_id)) + '\')">' + '<div style="flex:1;cursor:pointer" onclick="openTxDetail(\'' + esc(String(t.id || t.transceiver_id)) + '\')">'
+ '<div style="font-size:0.82rem;font-weight:600;color:var(--text-bright)">' + esc(t.part_number || t.model_name || String(t.id)) + '</div>' + '<div style="font-size:0.82rem;font-weight:600;color:var(--text-bright)">' + esc(t.part_number || t.model_name || String(t.id)) + '</div>'
+ (t.form_factor ? '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(t.form_factor) + (t.speed_gbps ? ' · ' + t.speed_gbps + 'G' : '') + '</div>' : '') + (t.form_factor ? '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(t.form_factor) + (t.speed_gbps ? ' · ' + fmtSpd(t.speed_gbps) : '') + '</div>' : '')
+ (t.street_price_usd ? '<div style="font-size:0.78rem;color:var(--green);font-family:var(--mono);font-weight:700">$' + parseFloat(t.street_price_usd).toFixed(2) + '</div>' : '') + (t.street_price_usd ? '<div style="font-size:0.78rem;color:var(--green);font-family:var(--mono);font-weight:700">$' + parseFloat(t.street_price_usd).toFixed(2) + '</div>' : '')
+ '</div>' + '</div>'
+ '<button onclick="toggleWatchlistItem(\'' + esc(String(t.id || t.transceiver_id)) + '\')" style="background:none;border:none;cursor:pointer;color:#f59e0b;font-size:1.1rem" title="Remove"></button>' + '<button onclick="toggleWatchlistItem(\'' + esc(String(t.id || t.transceiver_id)) + '\')" style="background:none;border:none;cursor:pointer;color:#f59e0b;font-size:1.1rem" title="Remove"></button>'
@ -11091,7 +11099,7 @@ async function runGlobalSearch() {
html += '<div onclick="closeGlobalSearch();openTxDetail(\'' + esc(String(t.id)) + '\')" style="cursor:pointer;padding:8px 10px;border-radius:7px;margin-bottom:3px;background:var(--surface2);border:1px solid var(--border);display:flex;align-items:center;gap:0.75rem">' html += '<div onclick="closeGlobalSearch();openTxDetail(\'' + esc(String(t.id)) + '\')" style="cursor:pointer;padding:8px 10px;border-radius:7px;margin-bottom:3px;background:var(--surface2);border:1px solid var(--border);display:flex;align-items:center;gap:0.75rem">'
+ '<span style="font-size:0.75rem;color:var(--text-dim)">🔌</span>' + '<span style="font-size:0.75rem;color:var(--text-dim)">🔌</span>'
+ '<div><div style="font-size:0.85rem;font-weight:600;color:var(--text-bright)">' + esc(t.part_number || t.model_name) + '</div>' + '<div><div style="font-size:0.85rem;font-weight:600;color:var(--text-bright)">' + esc(t.part_number || t.model_name) + '</div>'
+ '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(t.form_factor || '') + (t.speed_gbps ? ' · ' + t.speed_gbps + 'G' : '') + '</div></div>' + '<div style="font-size:0.7rem;color:var(--text-dim)">' + esc(t.form_factor || '') + (t.speed_gbps ? ' · ' + fmtSpd(t.speed_gbps) : '') + '</div></div>'
+ (t.street_price_usd ? '<div style="margin-left:auto;font-family:var(--mono);font-size:0.8rem;color:var(--green);font-weight:700">$' + parseFloat(t.street_price_usd).toFixed(2) + '</div>' : '') + (t.street_price_usd ? '<div style="margin-left:auto;font-family:var(--mono);font-size:0.8rem;color:var(--green);font-weight:700">$' + parseFloat(t.street_price_usd).toFixed(2) + '</div>' : '')
+ '</div>'; + '</div>';
}); });