fix: minor visual details

This commit is contained in:
Claude 2026-02-13 21:39:44 +07:00
parent 982d82776d
commit 0f5c739337
2 changed files with 68 additions and 38 deletions

View file

@ -60,7 +60,7 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
.panel {
background: #161822; border: 1px solid #2a2d3e; border-radius: 6px;
padding: 14px; overflow: hidden;
padding: 14px; overflow: visible;
}
.panel h2 { font-size: 12px; color: #888; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 10px; }
@ -75,7 +75,7 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
.stat-card .value { font-size: 22px; font-weight: 700; color: #fff; }
.stat-card .label { font-size: 10px; color: #888; text-transform: uppercase; margin-top: 2px; }
canvas { width: 100%; height: 200px; }
canvas { width: 100%; height: 220px; }
.search-wrap { margin-bottom: 10px; display: flex; align-items: center; gap: 12px; }
.search-input {
@ -109,7 +109,12 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
tr.clickable { cursor: pointer; }
tr.clickable:hover { background: #1a1d2c; }
.detail-panel { display: none; }
.detail-panel {
display: none; position: fixed; bottom: 12px; right: 12px;
width: 420px; max-height: 320px; overflow-y: auto;
background: #161822; border: 1px solid #2a2d3e; border-radius: 6px;
padding: 14px; z-index: 100; box-shadow: 0 4px 24px rgba(0,0,0,0.5);
}
.detail-panel.visible { display: block; }
.detail-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.detail-close {
@ -118,17 +123,17 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
}
.detail-close:hover { color: #e0e0e0; border-color: #555; }
.detail-grid {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 12px;
display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 10px;
}
.detail-item { background: #1c1f2e; border-radius: 4px; padding: 8px 10px; }
.detail-item { background: #1c1f2e; border-radius: 4px; padding: 6px 8px; }
.detail-item .d-label { font-size: 10px; color: #888; text-transform: uppercase; }
.detail-item .d-value { font-size: 14px; font-weight: 700; color: #fff; margin-top: 2px; word-break: break-all; }
.detail-item .d-value { font-size: 13px; font-weight: 700; color: #fff; margin-top: 2px; word-break: break-all; }
.poisoned-badge {
background: #f44336; color: #fff; font-size: 10px; font-weight: 700;
padding: 2px 6px; border-radius: 3px; letter-spacing: 0.5px;
}
.healthy-badge { color: #4caf50; font-size: 12px; }
canvas.sparkline { width: 100%; height: 60px; }
canvas.sparkline { width: 100%; height: 50px; }
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: #0f1117; }
@ -216,23 +221,25 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
</div>
</div>
<!-- Actor detail panel -->
<div id="detailPanel" class="panel full-width detail-panel">
</div>
<!-- Actor detail overlay (fixed position, doesn't affect grid layout) -->
<div id="detailPanel" class="detail-panel">
<div class="detail-header">
<h2>Actor Detail <span id="detailAddr" style="color:#aaa;font-weight:400;"></span></h2>
<button class="detail-close" id="detailClose">Close</button>
<h2 style="font-size:12px;color:#888;text-transform:uppercase;letter-spacing:1px;">Actor <span id="detailAddr" style="color:#aaa;font-weight:400;"></span></h2>
<button class="detail-close" id="detailClose">&times;</button>
</div>
<div class="detail-grid">
<div class="detail-item"><div class="d-label">Full Address</div><div class="d-value" id="detailFullAddr" style="font-size:11px;"></div></div>
<div class="detail-item"><div class="d-label">Address</div><div class="d-value" id="detailFullAddr" style="font-size:10px;"></div></div>
<div class="detail-item"><div class="d-label">Worker</div><div class="d-value" id="detailWorker"></div></div>
<div class="detail-item"><div class="d-label">Mailbox Depth</div><div class="d-value" id="detailMailbox"></div></div>
<div class="detail-item"><div class="d-label">Messages Processed</div><div class="d-value" id="detailMsgCount"></div></div>
<div class="detail-item"><div class="d-label">Last Message Type</div><div class="d-value" id="detailLastMsg"></div></div>
<div class="detail-item"><div class="d-label">Mailbox</div><div class="d-value" id="detailMailbox"></div></div>
<div class="detail-item"><div class="d-label">Messages</div><div class="d-value" id="detailMsgCount"></div></div>
<div class="detail-item"><div class="d-label">Last Type</div><div class="d-value" id="detailLastMsg"></div></div>
<div class="detail-item"><div class="d-label">Status</div><div class="d-value" id="detailStatus"></div></div>
</div>
<h2>Mailbox Depth History</h2>
<div style="font-size:10px;color:#888;text-transform:uppercase;letter-spacing:1px;margin-bottom:4px;">Mailbox History</div>
<canvas id="sparkline" class="sparkline"></canvas>
</div>
</div>
<script>
@ -383,11 +390,12 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
var maxCount = Math.max(1, Math.max.apply(null, counts));
var barW = Math.max(12, Math.floor((W - 40) / buckets.length) - 8);
var topPad = 20;
var chartH = H - 35;
for (var i = 0; i < buckets.length; i++) {
var x = 20 + i * (barW + 8);
var h = (counts[i] / maxCount) * (chartH - 10);
var h = (counts[i] / maxCount) * (chartH - topPad);
depthCtx.fillStyle = bucketColors[i];
depthCtx.globalAlpha = 0.85;
depthCtx.fillRect(x, chartH - h, barW, h);
@ -433,11 +441,12 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
var maxCount = Math.max(1, Math.max.apply(null, entries.map(function(e) { return e.count; })));
var barW = Math.max(12, Math.floor((W - 40) / entries.length) - 8);
var topPad = 20;
var chartH = H - 35;
for (var i = 0; i < entries.length; i++) {
var x = 20 + i * (barW + 8);
var h = (entries[i].count / maxCount) * (chartH - 10);
var h = (entries[i].count / maxCount) * (chartH - topPad);
workerCtx.fillStyle = colors[entries[i].id % colors.length];
workerCtx.globalAlpha = 0.85;
workerCtx.fillRect(x, chartH - h, barW, h);
@ -556,14 +565,14 @@ pub const ACTORS_HTML: &str = r##"<!DOCTYPE html>
// ── Focus / detail panel ───────────────────────────────
function focusActor(fullHex) {
focusedAddrHex = fullHex;
document.getElementById('detailPanel').className = 'panel full-width detail-panel visible';
document.getElementById('detailPanel').className = 'detail-panel visible';
updateDetailPanel();
renderActorTable();
}
function clearFocus() {
focusedAddrHex = null;
document.getElementById('detailPanel').className = 'panel full-width detail-panel';
document.getElementById('detailPanel').className = 'detail-panel';
renderActorTable();
}

View file

@ -40,9 +40,9 @@ pub const DISTRIBUTION_HTML: &str = r##"<!DOCTYPE html>
.graph-panel {
grid-row: 1 / 3; border-right: 1px solid #2a2d3e; position: relative;
min-height: 0;
min-height: 0; overflow: hidden;
}
.graph-panel canvas { width: 100%; height: 100%; display: block; }
.graph-panel canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: block; }
.side-panel { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
@ -176,8 +176,17 @@ pub const DISTRIBUTION_HTML: &str = r##"<!DOCTYPE html>
</div>
</div>
<div class="bottom-section">
<h2>Recent Probes</h2>
<div class="scroll-wrap" id="probesWrap"></div>
<h2>Recent Probes <span id="probeCount" style="color:#555;font-weight:400;"></span></h2>
<div class="scroll-wrap">
<table style="width:100%;border-collapse:collapse;">
<thead><tr>
<th style="color:#888;font-weight:500;font-size:11px;">State</th>
<th style="color:#888;font-weight:500;font-size:11px;">Node</th>
<th style="color:#888;font-weight:500;font-size:11px;">Address</th>
</tr></thead>
<tbody id="probesBody"></tbody>
</table>
</div>
</div>
<div class="bottom-section">
<h2>Routing Buckets</h2>
@ -653,14 +662,26 @@ pub const DISTRIBUTION_HTML: &str = r##"<!DOCTYPE html>
cacheBody.appendChild(tr);
}
// Recent probes
var probesWrap = document.getElementById('probesWrap');
probesWrap.innerHTML = '';
// Recent probes — cross-reference with members for state + address
var memberMap = {};
for (var i = 0; i < d.members.length; i++) {
memberMap[d.members[i].node_id] = d.members[i];
}
var probesBody = document.getElementById('probesBody');
probesBody.innerHTML = '';
document.getElementById('probeCount').textContent = '(' + d.recent_probe_targets.length + ')';
for (var i = d.recent_probe_targets.length - 1; i >= 0; i--) {
var div = document.createElement('div');
div.style.cssText = 'padding:2px 0;color:#aaa;font-size:11px;border-bottom:1px solid #1c1f2e;';
div.textContent = d.recent_probe_targets[i].substring(0, 16) + '\u2026';
probesWrap.appendChild(div);
var pid = d.recent_probe_targets[i];
var mem = memberMap[pid];
var state = mem ? mem.state : 'unknown';
var addr = mem ? mem.addr : '\u2014';
var cls = 'state-' + state;
var tr = document.createElement('tr');
tr.innerHTML =
'<td class="' + cls + '" style="font-size:10px;">' + state + '</td>' +
'<td style="color:#aaa;font-size:10px;">' + pid.substring(0, 12) + '\u2026</td>' +
'<td style="font-size:10px;">' + addr + '</td>';
probesBody.appendChild(tr);
}
// Routing bucket histogram