New charts added to stats as we have access not to nodes via API

This commit is contained in:
Pablo Revilla
2025-09-12 17:42:19 -07:00
parent 93bad96268
commit 8dec274045
3 changed files with 33 additions and 53 deletions
+9 -19
View File
@@ -6,20 +6,6 @@
margin: 0 auto;
}
/* Removed .packet-fade-in animation CSS */
/*
.packet-fade-in {
animation: fadeIn 0.5s ease forwards;
opacity: 0;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
*/
#pause-button {
white-space: nowrap;
padding: 2px 8px;
@@ -58,8 +44,12 @@ let lastTime = null;
let portnum = "{{ portnum if portnum is not none else '' }}";
let updatesPaused = false;
// Use firehose_interval from config (seconds), default to 3s if not set
const firehoseInterval = {{ site_config["site"]["firehose_interal"] | default(3) }};
if (firehoseInterval < 0) firehoseInterval = 0;
function fetchUpdates() {
if (updatesPaused) return;
if (updatesPaused || firehoseInterval === 0) return;
const url = new URL("/firehose/updates", window.location.origin);
if (lastTime) url.searchParams.set("last_time", lastTime);
@@ -74,7 +64,6 @@ function fetchUpdates() {
for (const html of data.packets.reverse()) {
list.insertAdjacentHTML("afterbegin", html);
// No animation here anymore
}
}
})
@@ -86,7 +75,6 @@ function fetchUpdates() {
document.addEventListener("DOMContentLoaded", () => {
const pauseBtn = document.getElementById("pause-button");
// Assuming you have a portnum selector somewhere (not shown in your snippet)
const portnumSelector = document.querySelector('select[name="portnum"]');
if (portnumSelector) {
portnumSelector.addEventListener("change", (e) => {
@@ -102,9 +90,11 @@ document.addEventListener("DOMContentLoaded", () => {
pauseBtn.textContent = updatesPaused ? "Resume" : "Pause";
});
// Start fetching updates
// Start fetching updates with configurable interval
fetchUpdates();
setInterval(fetchUpdates, 1000);
if (firehoseInterval > 0) {
setInterval(fetchUpdates, firehoseInterval * 1000);
}
});
</script>
+16 -32
View File
@@ -46,11 +46,9 @@
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>
<!-- Leaflet PolylineDecorator for arrowheads -->
<script src="https://unpkg.com/leaflet-polylinedecorator@1.6.0/dist/leaflet.polylinedecorator.js"
<script src="https://unpkg.com/leaflet-polylinedecorator@1.6.0/dist/leaflet.polylinedecorator.js"
integrity="sha384-FhPn/2P/fJGhQLeNWDn9B/2Gml2bPOrKJwFqJXgR3xOPYxWg5mYQ5XZdhUSugZT0"
crossorigin=""></script>
crossorigin></script>
<script>
// ---- Map Setup ----
@@ -199,13 +197,8 @@
let checkbox = document.getElementById(`filter-${category.replace(/\s+/g,'-').toLowerCase()}`);
let shouldShow = checkbox.checked && (!showRoutersOnly || node.isRouter);
let marker = markerById[node.id];
if (shouldShow) map.addLayer(marker);
else {
map.removeLayer(marker);
if (marker.tooltip) {
map.removeLayer(marker.tooltip);
marker.tooltip = null;
}
if (marker) {
marker.setStyle({ fillOpacity: shouldShow ? 1 : 0 });
}
});
}
@@ -219,7 +212,6 @@
var edgesData = null;
let selectedNodeId = null;
// Preload edges on page load
fetch('/api/edges')
.then(res => res.json())
.then(data => { edgesData = data.edges; })
@@ -229,34 +221,26 @@
if (selectedNodeId != node.id) {
selectedNodeId = node.id;
edgeLayer.clearLayers();
console.log(`Clicked node: ${node.long_name}`);
if (!edgesData) {
console.log("Edges not loaded yet");
return;
}
if (!edgesData) return;
if (!map.hasLayer(edgeLayer)) edgeLayer.addTo(map);
edgesData.forEach(edge => {
if (edge.from !== node.id && edge.to !== node.id) return;
const fromNode = nodeMap.get(edge.from);
const toNode = nodeMap.get(edge.to);
if (!fromNode || !toNode) return;
if (isInvalidCoord(fromNode) || isInvalidCoord(toNode)) return;
const lineColor = edge.type === "neighbor" ? "darkred" : "black"; //different than the node category colors
const lineColor = edge.type === "neighbor" ? "darkred" : "black";
const dash = edge.type === "traceroute" ? "5,5" : null;
const weight = edge.type === "neighbor" ? 3 : 2;
const polyline = L.polyline(
[[fromNode.lat, fromNode.long], [toNode.lat, toNode.long]],
{ color: lineColor, weight, opacity: 1, dashArray: dash }
)
.addTo(edgeLayer)
.bringToFront();
).addTo(edgeLayer).bringToFront();
// Add arrowhead
if (edge.type === "traceroute") {
L.polylineDecorator(polyline, {
patterns: [
@@ -264,13 +248,10 @@
]
}).addTo(edgeLayer);
}
console.log(`Edge type: To: ${toNode.long_name} (${toNode.lat},${toNode.long})`);
});
}
}
// Clear edges only if the click was not on a marker
map.on('click', function(e) {
if (!e.originalEvent.target.classList.contains('leaflet-interactive')) {
edgeLayer.clearLayers();
@@ -278,8 +259,6 @@
}
});
// ---- Blinking Nodes ----
var lastFetchTime = null;
const activeBlinks = new Map();
@@ -296,7 +275,6 @@
function blinkNode(marker, longName, portnum) {
if (!map.hasLayer(marker)) return;
if (activeBlinks.has(marker)) {
clearInterval(activeBlinks.get(marker));
marker.setStyle({ fillColor: marker.originalColor });
@@ -352,10 +330,13 @@
// ---- Polling Control ----
let packetInterval = null;
const mapInterval = {{ site_config["site"]["map_interval"] | default(3) }}; // seconds
function startPacketFetcher() {
if (mapInterval <= 0) return; // Don't fetch if interval is 0
if (!packetInterval) {
fetchLatestPacket();
packetInterval = setInterval(fetchNewPackets, 1000);
packetInterval = setInterval(fetchNewPackets, mapInterval * 1000);
}
}
@@ -372,7 +353,10 @@
});
// Init
fetchLatestPacket();
startPacketFetcher();
if (mapInterval > 0) {
fetchLatestPacket();
startPacketFetcher();
}
</script>
{% endblock %}
+8 -2
View File
@@ -178,10 +178,16 @@ env.filters["node_id_to_hex"] = node_id_to_hex
env.filters["format_timestamp"] = format_timestamp
routes = web.RouteTableDef()
# Make the Map the home page
@routes.get("/")
async def index(request):
raise web.HTTPFound(location="/map")
"""
Redirect root URL '/' to the page specified in CONFIG['site']['starting'].
Defaults to '/map' if not set.
"""
# Get the starting page from config
starting_url = CONFIG["site"].get("starting", "/map") # default to /map if not set
raise web.HTTPFound(location=starting_url)
def generate_response(request, body, raw_node_id="", node=None):