diff --git a/public/packets.js b/public/packets.js
index 8ba70c8c..195f87d2 100644
--- a/public/packets.js
+++ b/public/packets.js
@@ -251,6 +251,10 @@
+
+
+
+
@@ -285,6 +289,50 @@
document.getElementById('fType').addEventListener('change', (e) => { filters.type = e.target.value !== '' ? e.target.value : undefined; loadPackets(); });
document.getElementById('fGroup').addEventListener('click', () => { groupByHash = !groupByHash; loadPackets(); });
+ // Column visibility toggle (#71)
+ const COL_DEFS = [
+ { key: 'region', label: 'Region' },
+ { key: 'time', label: 'Time' },
+ { key: 'hash', label: 'Hash' },
+ { key: 'size', label: 'Size' },
+ { key: 'type', label: 'Type' },
+ { key: 'observer', label: 'Observer' },
+ { key: 'path', label: 'Path' },
+ { key: 'rpt', label: 'Rpt' },
+ { key: 'details', label: 'Details' },
+ ];
+ const defaultHidden = ['region'];
+ let visibleCols;
+ try {
+ visibleCols = JSON.parse(localStorage.getItem('packets-visible-cols'));
+ } catch {}
+ if (!visibleCols) visibleCols = COL_DEFS.map(c => c.key).filter(k => !defaultHidden.includes(k));
+ const colMenu = document.getElementById('colToggleMenu');
+ const pktTable = document.getElementById('pktTable');
+ function applyColVisibility() {
+ COL_DEFS.forEach(c => {
+ pktTable.classList.toggle('hide-col-' + c.key, !visibleCols.includes(c.key));
+ });
+ localStorage.setItem('packets-visible-cols', JSON.stringify(visibleCols));
+ }
+ colMenu.innerHTML = COL_DEFS.map(c =>
+ ``
+ ).join('');
+ colMenu.addEventListener('change', (e) => {
+ const cb = e.target;
+ const col = cb.dataset.col;
+ if (!col) return;
+ if (cb.checked) { if (!visibleCols.includes(col)) visibleCols.push(col); }
+ else { visibleCols = visibleCols.filter(k => k !== col); }
+ applyColVisibility();
+ });
+ document.getElementById('colToggleBtn').addEventListener('click', (e) => {
+ e.stopPropagation();
+ colMenu.classList.toggle('open');
+ });
+ document.addEventListener('click', () => colMenu.classList.remove('open'));
+ applyColVisibility();
+
// Node name filter with autocomplete
const fNode = document.getElementById('fNode');
const fNodeDrop = document.getElementById('fNodeDropdown');
@@ -477,11 +525,11 @@
| ${timeAgo(p.timestamp)} |
${truncate(p.hash || String(p.id), 8)} |
${size}B |
- ${typeName} |
- ${truncate(p.observer_name || p.observer_id || '—', 16)} |
- ${pathStr} |
+ ${typeName} |
+ ${truncate(p.observer_name || p.observer_id || '—', 16)} |
+ ${pathStr} |
|
- ${detail} |
+ ${detail} |
`;
}).join('');
}