mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-08-29 01:18:55 +00:00
Time-travel map: filter nodes by replay timestamp
When scrubbing to a past time, only nodes that had advertised before that time appear on the map. Nodes that hadn't been seen yet are hidden. - Added 'before' param to /api/nodes (filters first_seen <= before) - loadNodes(beforeTs) accepts optional timestamp filter - clearNodeMarkers() removes all markers and data - vcrReplayFromTs clears and reloads nodes for replay time - vcrResumeLive reloads all nodes (no filter)
This commit is contained in:
+21
-2
@@ -92,6 +92,9 @@
|
||||
VCR.dragPct = null;
|
||||
VCR.scrubTs = null;
|
||||
vcrSetMode('LIVE');
|
||||
// Reload all nodes (no time filter)
|
||||
clearNodeMarkers();
|
||||
loadNodes();
|
||||
const prompt = document.getElementById('vcrPrompt');
|
||||
if (prompt) prompt.classList.add('hidden');
|
||||
}
|
||||
@@ -115,6 +118,11 @@
|
||||
const fetchTo = new Date(targetTs + 300000).toISOString(); // 5 min window
|
||||
stopReplay();
|
||||
vcrSetMode('REPLAY');
|
||||
|
||||
// Reload map nodes to match the replay time
|
||||
clearNodeMarkers();
|
||||
loadNodes(targetTs);
|
||||
|
||||
fetch(`/api/packets?limit=200&grouped=false&since=${encodeURIComponent(fetchFrom)}&until=${encodeURIComponent(fetchTo)}`)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
@@ -818,9 +826,12 @@
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
async function loadNodes() {
|
||||
async function loadNodes(beforeTs) {
|
||||
try {
|
||||
const resp = await fetch('/api/nodes?limit=500');
|
||||
const url = beforeTs
|
||||
? `/api/nodes?limit=500&before=${encodeURIComponent(new Date(beforeTs).toISOString())}`
|
||||
: '/api/nodes?limit=500';
|
||||
const resp = await fetch(url);
|
||||
const nodes = await resp.json();
|
||||
const list = Array.isArray(nodes) ? nodes : (nodes.nodes || []);
|
||||
list.forEach(n => {
|
||||
@@ -833,6 +844,14 @@
|
||||
} catch (e) { console.error('Failed to load nodes:', e); }
|
||||
}
|
||||
|
||||
function clearNodeMarkers() {
|
||||
for (const [key, marker] of Object.entries(nodeMarkers)) {
|
||||
if (map) map.removeLayer(marker);
|
||||
}
|
||||
nodeMarkers = {};
|
||||
nodeData = {};
|
||||
}
|
||||
|
||||
function addNodeMarker(n) {
|
||||
if (nodeMarkers[n.public_key]) return nodeMarkers[n.public_key];
|
||||
const color = ROLE_COLORS[n.role] || ROLE_COLORS.unknown;
|
||||
|
||||
@@ -455,13 +455,14 @@ app.post('/api/packets', (req, res) => {
|
||||
});
|
||||
|
||||
app.get('/api/nodes', (req, res) => {
|
||||
const { limit = 50, offset = 0, role, region, lastHeard, sortBy = 'lastSeen', search } = req.query;
|
||||
const { limit = 50, offset = 0, role, region, lastHeard, sortBy = 'lastSeen', search, before } = req.query;
|
||||
|
||||
let where = [];
|
||||
let params = {};
|
||||
|
||||
if (role) { where.push('role = @role'); params.role = role; }
|
||||
if (search) { where.push('name LIKE @search'); params.search = `%${search}%`; }
|
||||
if (before) { where.push('first_seen <= @before'); params.before = before; }
|
||||
if (lastHeard) {
|
||||
const durations = { '1h': 3600000, '6h': 21600000, '24h': 86400000, '7d': 604800000, '30d': 2592000000 };
|
||||
const ms = durations[lastHeard];
|
||||
|
||||
Reference in New Issue
Block a user