fix: missing closing brace in renderNetworkMap broke all JS

renderNetworkMap() was missing its closing } after the setTimeout(50)
callback. This caused a SyntaxError that prevented the entire script
from parsing — doLookup was undefined, Lookup button did nothing.

Also added deploy.sh backup script on Erik (auto-backup before restart,
keeps last 20 versions of server.js + index.html).
This commit is contained in:
Rene Fichtmueller 2026-03-28 01:00:51 +13:00
parent 404aef5085
commit d1825fe327
2 changed files with 74 additions and 69 deletions

View File

@ -431,7 +431,7 @@ a{color:var(--blue);text-decoration:none;transition:color .2s}a:hover{color:var(
</div>
<!-- Network Footprint Map -->
<div class="card full hidden" id="mapCard">
<div class="card full" id="mapCard" style="display:none">
<div class="card-title" style="cursor:pointer" onclick="toggleExpand(this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="10" r="3"/><path d="M12 21.7C17.3 17 20 13 20 10a8 8 0 10-16 0c0 3 2.7 7 8 11.7z"/></svg>
Network Footprint Map
@ -1242,10 +1242,11 @@ function renderDashboard(d) {
var _pcMap = null;
function renderNetworkMap(d) {
var mapEl = document.getElementById('mapCard');
var mapCard = document.getElementById('mapCard');
var mapDiv = document.getElementById('networkMap');
if (!mapEl || !mapDiv || typeof L === 'undefined') return;
if (!mapCard || !mapDiv || typeof L === 'undefined') return;
// Collect all markers
var markers = [];
var facs = (d.facilities && d.facilities.list) || [];
facs.forEach(function(f) {
@ -1253,12 +1254,10 @@ function renderNetworkMap(d) {
markers.push({ lat: f.latitude, lng: f.longitude, type: 'fac', name: f.name, detail: f.city + (f.country ? ', ' + f.country : '') });
}
});
var ixLocs = d.ix_locations || [];
var ixConns = (d.ix_presence && d.ix_presence.connections) || [];
var ixSpeedMap = {};
ixConns.forEach(function(c) { if (c.ix_id) ixSpeedMap[c.ix_id] = (ixSpeedMap[c.ix_id] || 0) + (c.speed_mbps || 0); });
ixLocs.forEach(function(ix) {
if (ix.latitude && ix.longitude) {
var spd = ixSpeedMap[ix.ix_id] || 0;
@ -1266,21 +1265,23 @@ function renderNetworkMap(d) {
}
});
if (markers.length === 0) { mapEl.classList.add('hidden'); return; }
mapEl.classList.remove('hidden');
if (markers.length === 0) { mapCard.style.display = 'none'; return; }
// Defer map init to next frame so container has real dimensions after display:none removal
window._pcMapMarkers = markers;
window._pcMapFacs = facs;
requestAnimationFrame(function() {
requestAnimationFrame(function() {
_initLeafletMap(mapDiv, window._pcMapMarkers, window._pcMapFacs);
});
});
}
// KEY FIX: Set display + explicit pixel dimensions BEFORE creating Leaflet map
mapCard.style.display = 'block';
var cardWidth = mapCard.getBoundingClientRect().width;
mapDiv.style.width = (cardWidth - 40) + 'px';
mapDiv.style.height = '450px';
function _initLeafletMap(mapDiv, markers, facs) {
// Destroy previous map
if (_pcMap) { _pcMap.remove(); _pcMap = null; }
// Use setTimeout to let the browser fully lay out the container
setTimeout(function() {
// Re-measure after layout
var w = mapDiv.getBoundingClientRect().width;
if (w < 100) { mapDiv.style.width = '100%'; }
_pcMap = L.map(mapDiv, { scrollWheelZoom: false, attributionControl: false });
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
maxZoom: 18, subdomains: 'abcd'
@ -1290,7 +1291,7 @@ function _initLeafletMap(mapDiv, markers, facs) {
var bounds = L.latLngBounds();
markers.forEach(function(m) {
var color = m.type === 'fac' ? '#7dcfff' : '#ff9e64';
var radius = m.type === 'fac' ? 6 : 5;
var radius = m.type === 'fac' ? 7 : 6;
var circle = L.circleMarker([m.lat, m.lng], {
radius: radius, fillColor: color, fillOpacity: 0.85, color: color, weight: 1, opacity: 0.6
}).addTo(_pcMap);
@ -1300,8 +1301,7 @@ function _initLeafletMap(mapDiv, markers, facs) {
nameEl.textContent = m.name;
popupDiv.appendChild(nameEl);
if (m.detail) {
var br = document.createElement('br');
popupDiv.appendChild(br);
popupDiv.appendChild(document.createElement('br'));
var detailEl = document.createElement('span');
detailEl.textContent = m.detail;
popupDiv.appendChild(detailEl);
@ -1310,7 +1310,7 @@ function _initLeafletMap(mapDiv, markers, facs) {
bounds.extend([m.lat, m.lng]);
});
// Draw faint lines between facilities in the same country
// Faint lines between facilities in same country
var facByCountry = {};
facs.forEach(function(f) {
if (f.latitude && f.longitude && f.country) {
@ -1318,8 +1318,8 @@ function _initLeafletMap(mapDiv, markers, facs) {
facByCountry[f.country].push([f.latitude, f.longitude]);
}
});
Object.keys(facByCountry).forEach(function(c) {
var pts = facByCountry[c];
Object.keys(facByCountry).forEach(function(cc) {
var pts = facByCountry[cc];
if (pts.length >= 2 && pts.length <= 15) {
for (var i = 0; i < pts.length - 1; i++) {
L.polyline([pts[i], pts[i + 1]], { color: '#bb9af7', weight: 1, opacity: 0.3 }).addTo(_pcMap);
@ -1327,16 +1327,16 @@ function _initLeafletMap(mapDiv, markers, facs) {
}
});
if (bounds.isValid()) {
_pcMap.fitBounds(bounds, { padding: [30, 30], maxZoom: 6 });
// Fix tile rendering in initially-hidden containers
setTimeout(function() {
if (_pcMap) {
_pcMap.invalidateSize();
_pcMap.fitBounds(bounds, { padding: [30, 30], maxZoom: 6 });
}
}, 500);
}
// Final invalidateSize after everything is rendered
setTimeout(function() {
if (_pcMap) _pcMap.invalidateSize();
}, 300);
}, 50);
}
function renderAtlas(atlas) {
if (!atlas) {

View File

@ -931,7 +931,12 @@ async function fetchWhois(resource) {
// ============================================================
const server = http.createServer(async (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Origin", "https://peercortex.org");
res.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("X-Frame-Options", "DENY");
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
res.setHeader("Permissions-Policy", "camera=(), microphone=(), geolocation=()");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");