map debugging

This commit is contained in:
Graham McIntire 2025-06-16 14:35:04 -05:00
parent 210f866374
commit c5d7a32b60
No known key found for this signature in database
7 changed files with 125 additions and 524 deletions

View file

@ -4,20 +4,48 @@
/* This file is for your main application CSS */
/* Ensure full height layout for map pages */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
/* Main content container for map pages */
main {
height: 100vh;
overflow: hidden;
}
#map {
height: calc(100vh - 60px); /* Adjust based on header height */
width: 100%;
}
/* Full page map for APRS home page */
/* Full page map for APRS home page and callsign pages */
#aprs-map {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
position: fixed !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
height: 100vh !important;
width: 100vw !important;
z-index: 1 !important;
}
/* Ensure the map container div has proper dimensions */
.phx-main {
position: relative;
height: 100vh;
width: 100%;
overflow: hidden;
}
/* Fix for LiveView containers */
div[data-phx-main="true"] {
height: 100vh;
overflow: hidden;
}
/* Hide header on home page */

View file

@ -27,149 +27,9 @@ let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("
// Import minimal APRS map hook
import MinimalAPRSMap from "./minimal_map.js";
// Debug Map Hook
let DebugMap = {
mounted() {
console.log("DebugMap hook mounted");
window.liveSocket.pushEvent("debug_info", { hook_mounted: true });
// Check if Leaflet is available
if (typeof L === "undefined") {
console.error("Leaflet library not loaded!");
window.liveSocket.pushEvent("debug_info", {
leaflet_loaded: false,
errors: ["Leaflet not loaded"],
});
return;
}
window.liveSocket.pushEvent("debug_info", { leaflet_loaded: true });
// Get initial center and zoom from server-provided data attributes
let initialCenter, initialZoom;
try {
initialCenter = JSON.parse(this.el.dataset.center);
initialZoom = parseInt(this.el.dataset.zoom);
console.log("Parsed data - center:", initialCenter, "zoom:", initialZoom);
} catch (error) {
console.error("Error parsing map data attributes:", error);
window.liveSocket.pushEvent("debug_info", {
errors: ["Error parsing map data: " + error.message],
});
// Fallback values
initialCenter = { lat: 39.8283, lng: -98.5795 };
initialZoom = 5;
}
// Check element dimensions
const rect = this.el.getBoundingClientRect();
console.log("Map element dimensions:", rect);
// Initialize basic map
try {
this.map = L.map(this.el, {
zoomControl: true,
attributionControl: true,
closePopupOnClick: true,
}).setView([initialCenter.lat, initialCenter.lng], initialZoom);
console.log("Map initialized successfully");
window.liveSocket.pushEvent("debug_info", { map_initialized: true });
window.debugMapInstance = this.map;
} catch (error) {
console.error("Error initializing map:", error);
window.liveSocket.pushEvent("debug_info", {
map_initialized: false,
errors: ["Map init error: " + error.message],
});
return;
}
// Add OpenStreetMap tile layer
try {
const tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors | APRS.me',
maxZoom: 19,
});
tileLayer.addTo(this.map);
console.log("Tile layer added successfully");
// Listen for tile layer events
tileLayer.on("loading", () => console.log("Tiles loading..."));
tileLayer.on("load", () => console.log("Tiles loaded"));
tileLayer.on("tileerror", (e) => console.error("Tile error:", e));
} catch (error) {
console.error("Error adding tile layer:", error);
window.liveSocket.pushEvent("debug_info", {
errors: ["Tile layer error: " + error.message],
});
}
// Force initial size calculation
try {
this.map.invalidateSize();
console.log("Map size invalidated");
} catch (error) {
console.error("Error invalidating map size:", error);
}
// Track when map is ready
this.map.whenReady(() => {
console.log("Debug map is ready");
console.log("Map container size:", this.map.getSize());
console.log("Map zoom:", this.map.getZoom());
console.log("Map center:", this.map.getCenter());
try {
this.pushEvent("map_ready", {});
} catch (error) {
console.error("Error in map ready callback:", error);
}
});
// Handle resize
window.addEventListener("resize", () => {
console.log("Window resized, invalidating map size");
try {
this.map.invalidateSize();
} catch (error) {
console.error("Error invalidating map size on resize:", error);
}
});
// Add a delayed size check
setTimeout(() => {
console.log("Delayed map size check");
const rect = this.el.getBoundingClientRect();
console.log("Map element dimensions after delay:", rect);
if (this.map) {
try {
this.map.invalidateSize();
console.log("Map size re-invalidated after delay");
} catch (error) {
console.error("Error re-invalidating map size:", error);
}
}
}, 1000);
},
destroyed() {
console.log("DebugMap hook destroyed");
if (this.map) {
this.map.remove();
this.map = null;
}
if (window.debugMapInstance) {
window.debugMapInstance = null;
}
},
};
// APRS Map Hook
let Hooks = {};
Hooks.APRSMap = MinimalAPRSMap;
Hooks.DebugMap = DebugMap;
let liveSocket = new LiveSocket("/live", Socket, {
longPollFallbackMs: 2500,

View file

@ -265,15 +265,68 @@ let MinimalAPRSMap = {
// Zoom to location
this.handleEvent("zoom_to_location", (data) => {
console.log("Zoom to location event received:", data);
if (!this.map) {
console.error("Map not initialized, cannot zoom");
return;
}
if (data.lat && data.lng) {
const lat = parseFloat(data.lat);
const lng = parseFloat(data.lng);
const zoom = parseInt(data.zoom || 12);
this.map.setView([lat, lng], zoom, {
animate: true,
duration: 1,
});
// Validate coordinates
if (isNaN(lat) || isNaN(lng) || lat < -90 || lat > 90 || lng < -180 || lng > 180) {
console.error("Invalid coordinates for zoom:", lat, lng);
return;
}
if (isNaN(zoom) || zoom < 1 || zoom > 20) {
console.error("Invalid zoom level:", zoom);
return;
}
console.log("Zooming map to:", lat, lng, "at zoom level:", zoom);
try {
// Check element dimensions before zoom
const beforeRect = this.el.getBoundingClientRect();
console.log("Element dimensions before zoom:", beforeRect);
// Force map size recalculation before zoom
this.map.invalidateSize();
// Use a slight delay to ensure map is ready
setTimeout(() => {
if (this.map) {
this.map.setView([lat, lng], zoom, {
animate: true,
duration: 1,
});
console.log("Zoom completed successfully");
// Check element dimensions after zoom
setTimeout(() => {
const afterRect = this.el.getBoundingClientRect();
console.log("Element dimensions after zoom:", afterRect);
if (afterRect.width === 0 || afterRect.height === 0) {
console.error("Map element lost dimensions after zoom!");
// Try to restore dimensions
this.el.style.width = "100vw";
this.el.style.height = "100vh";
this.map.invalidateSize();
}
}, 1000);
}
}, 100);
} catch (error) {
console.error("Error during zoom operation:", error);
}
} else {
console.warn("Missing lat/lng data for zoom operation:", data);
}
});

View file

@ -86,84 +86,6 @@ defmodule AprsWeb.PageController do
})
end
def test_map(conn, _params) do
# Simple HTML test page for basic map functionality
html(conn, """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map Test - APRS.me</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
#map { height: 100vh; width: 100%; }
.status { position: fixed; top: 10px; left: 10px; z-index: 1000; background: white; padding: 10px; border-radius: 5px; border: 1px solid #ccc; }
</style>
</head>
<body>
<div class="status">
<strong>Map Test</strong><br>
Status: <span id="status">Initializing...</span><br>
<button onclick="testMarker()">Add Test Marker</button><br>
<a href="/"> Back to Main Map</a>
</div>
<div id="map"></div>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script>
let map;
let status = document.getElementById('status');
try {
status.textContent = 'Loading Leaflet...';
if (typeof L === 'undefined') {
throw new Error('Leaflet not loaded');
}
status.textContent = 'Initializing map...';
map = L.map('map').setView([39.8283, -98.5795], 5);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
status.textContent = 'Map loaded successfully!';
status.style.color = 'green';
// Add a default marker
L.marker([39.8283, -98.5795])
.addTo(map)
.bindPopup('Test marker - map is working!')
.openPopup();
} catch (error) {
status.textContent = 'Error: ' + error.message;
status.style.color = 'red';
console.error('Map initialization error:', error);
}
function testMarker() {
if (map) {
const lat = 39 + Math.random() * 10;
const lng = -100 + Math.random() * 10;
L.marker([lat, lng])
.addTo(map)
.bindPopup('Random test marker');
status.textContent = 'Added marker at ' + lat.toFixed(2) + ', ' + lng.toFixed(2);
}
}
</script>
</body>
</html>
""")
end
defp format_uptime(seconds) when seconds <= 0, do: "Not connected"
defp format_uptime(seconds) do

View file

@ -69,8 +69,8 @@ defmodule AprsWeb.MapLive.CallsignView do
# Schedule regular cleanup of old packets from the map
Process.send_after(self(), :cleanup_old_packets, 60_000)
# Auto-start replay after a short delay
Process.send_after(self(), :auto_start_replay, 2000)
# Auto-start replay after a short delay - TEMPORARILY DISABLED FOR DEBUGGING
# Process.send_after(self(), :auto_start_replay, 2000)
{:ok, socket}
else
@ -146,29 +146,32 @@ defmodule AprsWeb.MapLive.CallsignView do
IO.puts("CallsignView: Map ready event received")
socket = assign(socket, map_ready: true)
# Auto-start replay if it hasn't been started yet
# Auto-start replay if it hasn't been started yet - TEMPORARILY DISABLED FOR DEBUGGING
socket =
if socket.assigns.replay_started do
IO.puts("CallsignView: Replay already started")
socket
else
IO.puts("CallsignView: Starting historical replay")
socket = start_historical_replay(socket)
assign(socket, replay_started: true, replay_active: true)
IO.puts("CallsignView: Skipping replay start for debugging")
# socket = start_historical_replay(socket)
# assign(socket, replay_started: true, replay_active: true)
socket
end
# If we have a pending geolocation, zoom to it now
# If we have a pending geolocation, zoom to it after a delay
socket =
if socket.assigns.pending_geolocation do
location = socket.assigns.pending_geolocation
IO.puts("CallsignView: Zooming to pending geolocation: #{inspect(location)}")
push_event(socket, "zoom_to_location", %{lat: location.lat, lng: location.lng, zoom: 12})
IO.puts("CallsignView: Scheduling zoom to pending geolocation: #{inspect(location)}")
Process.send_after(self(), {:zoom_to_location, location.lat, location.lng, 12}, 1500)
socket
else
# If we have a last known position, zoom to it
# If we have a last known position, zoom to it after a delay
if socket.assigns.last_known_position do
pos = socket.assigns.last_known_position
IO.puts("CallsignView: Zooming to last known position: #{inspect(pos)}")
push_event(socket, "zoom_to_location", %{lat: pos.lat, lng: pos.lng, zoom: 12})
IO.puts("CallsignView: Scheduling zoom to last known position: #{inspect(pos)}")
Process.send_after(self(), {:zoom_to_location, pos.lat, pos.lng, 12}, 1500)
socket
else
IO.puts("CallsignView: No position data to zoom to")
socket
@ -202,6 +205,12 @@ defmodule AprsWeb.MapLive.CallsignView do
end
end
def handle_info({:zoom_to_location, lat, lng, zoom}, socket) do
IO.puts("CallsignView: Executing delayed zoom to #{lat}, #{lng} at zoom #{zoom}")
socket = push_event(socket, "zoom_to_location", %{lat: lat, lng: lng, zoom: zoom})
{:noreply, socket}
end
def handle_info(msg, socket) do
case msg do
{:delayed_zoom, %{lat: lat, lng: lng}} ->
@ -379,14 +388,18 @@ defmodule AprsWeb.MapLive.CallsignView do
<style>
#aprs-map {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100vw;
height: 100vh;
z-index: 1;
position: fixed !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
width: 100vw !important;
height: 100vh !important;
z-index: 1 !important;
min-width: 100vw !important;
min-height: 100vh !important;
max-width: 100vw !important;
max-height: 100vh !important;
}
/* Ensure the map container has a defined height */

View file

@ -1,273 +0,0 @@
defmodule AprsWeb.MapLive.Debug do
@moduledoc false
use AprsWeb, :live_view
@default_center %{lat: 39.8283, lng: -98.5795}
@default_zoom 5
def mount(_params, _session, socket) do
socket =
assign(socket,
page_title: "Map Debug",
map_center: @default_center,
map_zoom: @default_zoom,
debug_info: %{
leaflet_loaded: false,
map_initialized: false,
hook_mounted: false,
map_ready: false,
element_dimensions: nil,
errors: []
}
)
{:ok, socket}
end
def handle_event("debug_info", params, socket) do
debug_info = Map.merge(socket.assigns.debug_info, params)
{:noreply, assign(socket, debug_info: debug_info)}
end
def handle_event("map_ready", _params, socket) do
debug_info = Map.put(socket.assigns.debug_info, :map_ready, true)
{:noreply, assign(socket, debug_info: debug_info)}
end
def render(assigns) do
~H"""
<link
rel="stylesheet"
href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""
/>
<script
src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""
>
</script>
<style>
.debug-container {
display: flex;
height: 100vh;
}
.debug-panel {
width: 400px;
background: #f8f9fa;
border-right: 1px solid #dee2e6;
padding: 20px;
overflow-y: auto;
font-family: monospace;
font-size: 12px;
}
.map-container {
flex: 1;
position: relative;
}
#debug-map {
width: 100%;
height: 100%;
}
.status-item {
margin: 10px 0;
padding: 8px;
border-radius: 4px;
border: 1px solid #ccc;
}
.status-ok {
background: #d4edda;
border-color: #c3e6cb;
color: #155724;
}
.status-error {
background: #f8d7da;
border-color: #f5c6cb;
color: #721c24;
}
.status-pending {
background: #fff3cd;
border-color: #ffeaa7;
color: #856404;
}
.debug-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.test-button {
background: #007cba;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin: 5px 5px 5px 0;
font-size: 12px;
}
.test-button:hover {
background: #005a87;
}
</style>
<div class="debug-container">
<div class="debug-panel">
<div class="debug-title">Map Debug Panel</div>
<div class="status-item">
<strong>Map Dimensions:</strong> <br />
<span id="dimensions-info">Checking...</span>
</div>
<div class={"status-item #{if @debug_info.leaflet_loaded, do: "status-ok", else: "status-pending"}"}>
<strong>Leaflet Library:</strong> <br />
{if @debug_info.leaflet_loaded, do: "✓ Loaded", else: "⏳ Loading..."}
</div>
<div class={"status-item #{if @debug_info.hook_mounted, do: "status-ok", else: "status-pending"}"}>
<strong>Phoenix Hook:</strong> <br />
{if @debug_info.hook_mounted, do: "✓ Mounted", else: "⏳ Waiting..."}
</div>
<div class={"status-item #{if @debug_info.map_initialized, do: "status-ok", else: "status-pending"}"}>
<strong>Map Initialization:</strong> <br />
{if @debug_info.map_initialized, do: "✓ Initialized", else: "⏳ Waiting..."}
</div>
<div class={"status-item #{if @debug_info.map_ready, do: "status-ok", else: "status-pending"}"}>
<strong>Map Ready:</strong> <br />
{if @debug_info.map_ready, do: "✓ Ready", else: "⏳ Waiting..."}
</div>
<%= if length(@debug_info.errors) > 0 do %>
<div class="status-item status-error">
<strong>Errors:</strong>
<br />
<%= for error <- @debug_info.errors do %>
{error}<br />
<% end %>
</div>
<% end %>
<div class="status-item">
<strong>Test Actions:</strong> <br />
<button class="test-button" onclick="testLeaflet()">Test Leaflet</button>
<button class="test-button" onclick="testMapSize()">Test Map Size</button>
<button class="test-button" onclick="addTestMarker()">Add Marker</button>
<button class="test-button" onclick="clearConsole()">Clear Console</button>
</div>
<div class="status-item">
<strong>Console Output:</strong>
<br />
<div
id="console-output"
style="height: 200px; overflow-y: auto; background: white; padding: 10px; border: 1px solid #ccc; font-size: 10px;"
>
</div>
</div>
<div class="status-item">
<strong>Instructions:</strong>
<br /> 1. Open browser dev tools (F12)<br /> 2. Check Console tab for errors<br />
3. Watch this panel for status updates<br /> 4. Use test buttons to debug issues
</div>
</div>
<div class="map-container">
<div
id="debug-map"
phx-hook="DebugMap"
data-center={Jason.encode!(@map_center)}
data-zoom={@map_zoom}
>
</div>
</div>
</div>
<script>
// Capture console output
const originalLog = console.log;
const originalError = console.error;
const originalWarn = console.warn;
function addToConsoleOutput(message, type = 'log') {
const output = document.getElementById('console-output');
if (output) {
const timestamp = new Date().toLocaleTimeString();
const color = type === 'error' ? 'red' : type === 'warn' ? 'orange' : 'black';
output.innerHTML += `<div style="color: ${color};">[${timestamp}] ${message}</div>`;
output.scrollTop = output.scrollHeight;
}
}
console.log = function(...args) {
originalLog.apply(console, args);
addToConsoleOutput(args.join(' '), 'log');
};
console.error = function(...args) {
originalError.apply(console, args);
addToConsoleOutput(args.join(' '), 'error');
};
console.warn = function(...args) {
originalWarn.apply(console, args);
addToConsoleOutput(args.join(' '), 'warn');
};
function testLeaflet() {
if (typeof L !== 'undefined') {
console.log('✓ Leaflet is available, version:', L.version);
window.liveSocket.pushEvent('debug_info', {leaflet_loaded: true});
} else {
console.error('✗ Leaflet is not available');
window.liveSocket.pushEvent('debug_info', {leaflet_loaded: false, errors: ['Leaflet not loaded']});
}
}
function testMapSize() {
const mapEl = document.getElementById('debug-map');
if (mapEl) {
const rect = mapEl.getBoundingClientRect();
console.log('Map element dimensions:', rect);
document.getElementById('dimensions-info').textContent =
`${rect.width}x${rect.height} (${rect.left},${rect.top})`;
}
}
function addTestMarker() {
if (window.debugMapInstance) {
const marker = L.marker([39.8283, -98.5795])
.addTo(window.debugMapInstance)
.bindPopup('Test Marker');
console.log('✓ Test marker added');
} else {
console.error('✗ No map instance available');
}
}
function clearConsole() {
document.getElementById('console-output').innerHTML = '';
}
// Test Leaflet availability when page loads
setTimeout(testLeaflet, 1000);
setTimeout(testMapSize, 1000);
</script>
"""
end
end

View file

@ -31,8 +31,6 @@ defmodule AprsWeb.Router do
live "/enhanced", MapLive.Enhanced, :index
get "/old", PageController, :map
live "/status", StatusLive.Index, :index
live "/debug_map", MapLive.Debug, :index
get "/test_map", PageController, :test_map
live "/packets", PacketsLive.Index, :index
live "/:callsign", MapLive.CallsignView, :index