Fix Leaflet library loading race condition and enable Redis-free development

- Fix race condition in map bundle loading by waiting for script to load before initializing map
- Ensure Leaflet is properly exposed as window.L in map bundle
- Add Leaflet availability check in map initialization function
- Disable Exq background jobs in development environment to remove Redis dependency
- Remove invalid TelemetryMetricsPrometheus plug from endpoint
- Application now starts successfully without Redis in development mode

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2025-07-27 12:20:23 -05:00
parent 863000d6b8
commit 8ddcb8000f
No known key found for this signature in database
5 changed files with 63 additions and 13 deletions

View file

@ -129,11 +129,27 @@ let Hooks = {};
Hooks.APRSMap = { Hooks.APRSMap = {
...MapAPRSMap, ...MapAPRSMap,
mounted() { mounted() {
if (window.VendorLoader) { const self = this;
window.VendorLoader.loadMap(); if (window.VendorLoader && !window.mapBundleLoaded) {
} // Load map bundle and wait for it to complete
if (MapAPRSMap.mounted) { const script = document.createElement('script');
MapAPRSMap.mounted.call(this); script.src = window.VendorLoader.mapBundleUrl;
script.onload = () => {
window.mapBundleLoaded = true;
// Now call the original mounted function
if (MapAPRSMap.mounted) {
MapAPRSMap.mounted.call(self);
}
};
script.onerror = () => {
console.error("Failed to load map bundle");
};
document.head.appendChild(script);
} else {
// Map bundle already loaded, proceed immediately
if (MapAPRSMap.mounted) {
MapAPRSMap.mounted.call(this);
}
} }
} }
}; };
@ -141,11 +157,27 @@ Hooks.APRSMap = {
Hooks.InfoMap = { Hooks.InfoMap = {
...InfoMap, ...InfoMap,
mounted() { mounted() {
if (window.VendorLoader) { const self = this;
window.VendorLoader.loadMap(); if (window.VendorLoader && !window.mapBundleLoaded) {
} // Load map bundle and wait for it to complete
if (InfoMap.mounted) { const script = document.createElement('script');
InfoMap.mounted.call(this); script.src = window.VendorLoader.mapBundleUrl;
script.onload = () => {
window.mapBundleLoaded = true;
// Now call the original mounted function
if (InfoMap.mounted) {
InfoMap.mounted.call(self);
}
};
script.onerror = () => {
console.error("Failed to load map bundle");
};
document.head.appendChild(script);
} else {
// Map bundle already loaded, proceed immediately
if (InfoMap.mounted) {
InfoMap.mounted.call(this);
}
} }
} }
}; };

View file

@ -2,5 +2,10 @@
import "../vendor/js/leaflet-minimal.js"; import "../vendor/js/leaflet-minimal.js";
import "../vendor/js/plugins-optimized.js"; import "../vendor/js/plugins-optimized.js";
// Ensure Leaflet is available as window.L (standard convention)
if (window.leaflet && !window.L) {
window.L = window.leaflet;
}
// Mark bundle as loaded // Mark bundle as loaded
window.mapBundleLoaded = true; window.mapBundleLoaded = true;

View file

@ -157,6 +157,17 @@ let MapAPRSMap = {
initializeMap(initialCenter: CenterData, initialZoom: number) { initializeMap(initialCenter: CenterData, initialZoom: number) {
const self = this as unknown as LiveViewHookContext; const self = this as unknown as LiveViewHookContext;
// Check if Leaflet is still available
if (typeof window.L === "undefined") {
console.error("Leaflet library not loaded!");
self.handleFatalError("Leaflet library not available");
return;
}
// Create a local reference to Leaflet for this function
const L = window.L;
// Ensure the element and its parent exist // Ensure the element and its parent exist
if (!self.el || !self.el.parentNode) { if (!self.el || !self.el.parentNode) {
console.warn("Map element or parent not found, retrying..."); console.warn("Map element or parent not found, retrying...");

View file

@ -72,6 +72,11 @@ config :aprsme, AprsmeWeb.Endpoint,
# Run `mix help phx.gen.cert` for more information. # Run `mix help phx.gen.cert` for more information.
config :aprsme, dev_routes: true config :aprsme, dev_routes: true
# Disable Exq in development (no Redis required)
# Jobs that would normally run in the background will be skipped
config :exq,
start_on_application: false
# Mailer configuration for development # Mailer configuration for development
# Using Swoosh.Adapters.Local from config.exs which stores emails locally # Using Swoosh.Adapters.Local from config.exs which stores emails locally
# Access sent emails at http://localhost:4000/dev/mailbox # Access sent emails at http://localhost:4000/dev/mailbox

View file

@ -56,8 +56,5 @@ defmodule AprsmeWeb.Endpoint do
# Health check endpoint # Health check endpoint
plug AprsmeWeb.Plugs.HealthCheck plug AprsmeWeb.Plugs.HealthCheck
# Prometheus metrics endpoint
plug TelemetryMetricsPrometheus
plug AprsmeWeb.Router plug AprsmeWeb.Router
end end