From e5b4c9fb180a0ff56a42bdce7a5ca3146903e546 Mon Sep 17 00:00:00 2001 From: Anton Roslund Date: Sun, 28 Sep 2025 21:18:08 +0200 Subject: [PATCH] update messages.js --- static/js/messages.js | 77 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/static/js/messages.js b/static/js/messages.js index 85298cc..4dc25f3 100644 --- a/static/js/messages.js +++ b/static/js/messages.js @@ -1,6 +1,7 @@ document.addEventListener("DOMContentLoaded", async function () { const messagesContainer = document.getElementById("messages"); const radioButtons = document.querySelectorAll("input[name='btnradio']"); + const channelRadioButtons = document.querySelectorAll("input[name='btnchannel']"); const loadingDiv = document.getElementById("loading"); const messagesList = document.createElement("div"); messagesList.style="max-height:70vh;overflow: auto;" @@ -15,36 +16,64 @@ document.addEventListener("DOMContentLoaded", async function () { radio.addEventListener("change", fetchMessages); }); + channelRadioButtons.forEach(radio => { + radio.addEventListener("change", fetchMessages); + }); + async function fetchMessages() { try { - let url = "https://map.sthlm-mesh.se/api/v1/text-messages?order=desc"; + let url = "https://map.sthlm-mesh.se/api/v1/text-messages?order=desc&count=300"; const selectedRadio = document.querySelector("input[name='btnradio']:checked"); + const selectedChannel = document.querySelector("input[name='btnchannel']:checked"); - //If all is not selected we fetch 30 messages. If not we fetch 100 due to duplicates - if (selectedRadio.id !== "all") { - url += `&gateway_id=${selectedRadio.id}`; - url += `&count=30`; - } else { - url += `&count=100`; + if (selectedChannel) { + const channelId = selectedChannel.getAttribute('data-channel'); + if (channelId) { + url += `&channel_id=${encodeURIComponent(channelId)}`; + } } const response = await fetch(url); const data = await response.json(); - - //Filter duplicate messages - state.messages = Array.from( - new Map(data.text_messages.map(msg => [msg.packet_id, msg])).values() - ); + + // Group by packet_id and collect all gateways that heard the packet + const byPacket = new Map(); + for (const msg of data.text_messages) { + let entry = byPacket.get(msg.packet_id); + if (!entry) { + entry = { message: msg, gatewayIds: new Set() }; + byPacket.set(msg.packet_id, entry); + } + entry.gatewayIds.add(msg.gateway_id); + } + + // Build aggregated messages with gateway_ids array + let aggregated = Array.from(byPacket.values()).map(entry => ({ + ...entry.message, + gateway_ids: Array.from(entry.gatewayIds) + })); + + // If a specific gateway is selected, filter to messages heard by that gateway + if (selectedRadio && selectedRadio.id !== "all") { + const selectedGatewayId = selectedRadio.id; + aggregated = aggregated.filter(m => m.gateway_ids && m.gateway_ids.some(id => id?.toString() === selectedGatewayId)); + } + + state.messages = aggregated; // Sort the messages, for some reason with multiple mqtt gateways they are unsorted. state.messages.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); // fetch node info - for(const message of state.messages){ + for (const message of state.messages) { await fetchNodeInfo(message.to); await fetchNodeInfo(message.from); - await fetchNodeInfo(message.gateway_id); + if (Array.isArray(message.gateway_ids)) { + for (const gid of message.gateway_ids) { + await fetchNodeInfo(gid); + } + } } updateUI(); @@ -100,7 +129,10 @@ document.addEventListener("DOMContentLoaded", async function () {
${escapeMessageText(message.text)}
-
${formatMessageTimestamp(message.created_at)} ${message.channel_id}
+
+ ${formatMessageTimestamp(message.created_at)} ${message.channel_id} + ${renderGatewayShortNames(message.gateway_ids)} +
`; @@ -143,6 +175,21 @@ document.addEventListener("DOMContentLoaded", async function () { return date.toLocaleString('sv-SE', { hour12: false }).slice(0, 16); } + function renderGatewayShortNames(gatewayIds) { + if (!Array.isArray(gatewayIds) || gatewayIds.length === 0) { + return ""; + } + const names = gatewayIds + .map(id => state.nodesById[id]?.short_name) + .filter(Boolean) + .map(n => `[${n}]`) + .join(' '); + if (!names) { + return ""; + } + return ` Gated by: ${names}`; + } + await fetchMessages(); setInterval(fetchMessages, 30000); });