fix: detail pane shows clicked observation data, not parent packet

When expanding a grouped packet and clicking a child observation row,
the detail pane now shows that observation's observer, SNR/RSSI, path,
and timestamp instead of the parent packet's data.

Child rows use a new 'select-observation' action that builds a synthetic
packet object by overlaying observation-specific fields onto the parent
packet data (no extra API fetch needed).
This commit is contained in:
you
2026-03-21 22:47:01 +00:00
parent 40add85cc4
commit 6a8933d896
2 changed files with 13 additions and 2 deletions
+1 -1
View File
@@ -84,7 +84,7 @@
<script src="hop-resolver.js?v=1774126708"></script>
<script src="app.js?v=1774126708"></script>
<script src="home.js?v=1774042199"></script>
<script src="packets.js?v=1774132071"></script>
<script src="packets.js?v=1774166400"></script>
<script src="map.js?v=1774126708" onerror="console.error('Failed to load:', this.src)"></script>
<script src="channels.js?v=1774331200" onerror="console.error('Failed to load:', this.src)"></script>
<script src="nodes.js?v=1774126708" onerror="console.error('Failed to load:', this.src)"></script>
+12 -1
View File
@@ -581,6 +581,16 @@
if (hash) selectPacket(null, hash);
else selectPacket(Number(value));
}
else if (action === 'select-observation') {
const parentHash = row.dataset.parentHash;
const group = packets.find(p => p.hash === parentHash);
const child = group?._children?.find(c => String(c.id) === String(value));
if (child) {
const parentData = group._fetchedData;
const obsPacket = parentData ? {...parentData.packet, observer_id: child.observer_id, observer_name: child.observer_name, snr: child.snr, rssi: child.rssi, path_json: child.path_json, timestamp: child.timestamp, first_seen: child.timestamp} : child;
selectPacket(child.id, parentHash, {packet: obsPacket, breakdown: parentData?.breakdown, observations: parentData?.observations});
}
}
else if (action === 'select-hash') pktSelectHash(value);
else if (action === 'toggle-select') { pktToggleGroup(value); pktSelectHash(value); }
};
@@ -671,7 +681,7 @@
let childPath = [];
try { childPath = JSON.parse(c.path_json || '[]'); } catch {}
const childPathStr = renderPath(childPath);
html += `<tr class="group-child" data-id="${c.id}" data-hash="${c.hash || ''}" data-action="select" data-value="${c.id}" tabindex="0" role="row">
html += `<tr class="group-child" data-id="${c.id}" data-hash="${c.hash || ''}" data-action="select-observation" data-value="${c.id}" data-parent-hash="${p.hash}" tabindex="0" role="row">
<td></td><td class="col-region">${childRegion ? `<span class="badge-region">${childRegion}</span>` : '—'}</td>
<td class="col-time">${timeAgo(c.timestamp)}</td>
<td class="mono col-hash">${truncate(c.hash || '', 8)}</td>
@@ -1217,6 +1227,7 @@
const group = packets.find(p => p.hash === hash);
if (group && data.observations) {
group._children = data.observations.map(o => ({...pkt, ...o, _isObservation: true}));
group._fetchedData = data;
// Sort: group by observer, earliest-observer first, then by time within each observer
const earliest = {};
for (const c of group._children) {