Commit graph

106 commits

Author SHA1 Message Date
52716da109
Remove Node.js from Docker build
- Phoenix uses standalone ESBuild and Tailwind binaries
- No npm dependencies needed (package.json was empty)
- Removes ~150MB from Docker image
- Speeds up build time by removing Node.js installation step

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-26 16:03:49 -05:00
0b1e0b85f0
Fix map loading error with dynamic vendor bundles
- Fixed "Leaflet library failed to load" error by deferring window.L access
- Changed map.ts to access window.L dynamically instead of at module load time
- Added const L = window.L; inside functions that use Leaflet
- This allows the vendor bundle to load asynchronously before map initialization

The issue was that the TypeScript module was trying to access window.L
immediately when imported, before the vendor bundle had loaded Leaflet.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 14:25:05 -05:00
f7cf0d0d47
Implement advanced JavaScript optimization with conditional loading
- Created minimal, tree-shaken vendor bundles:
  * Core bundle (3KB): Always loaded utilities and theme management
  * Map bundle (255KB): Leaflet + plugins, loaded only for map pages
  * Chart bundle (205KB): Chart.js, loaded only for chart pages
  * Date adapter (50KB): Chart.js time scale support
- Total optimized size: 513KB JS + 12KB CSS (was 547KB + 17KB)
- Implemented conditional loading via VendorLoader utility
- Bundle loading triggered by LiveView hooks when needed
- Fixed Chart.js date adapter dependency loading
- Eliminated unused JavaScript from being sent to browsers
- Created separate esbuild configs for each optimized bundle

Performance improvements:
- Map pages: Core + Map bundles = 258KB (47% of original)
- Chart pages: Core + Chart + Adapter = 258KB (47% of original)
- Other pages: Core bundle only = 3KB (0.5% of original)
- Reduced initial page load by 94% for non-map/chart pages

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 14:05:18 -05:00
f4bc55ed39
Optimize JavaScript delivery by creating local vendor bundles
- Download external libraries locally to reduce CDN dependencies
- Create combined vendor bundles for JavaScript and CSS
- Replace CDN script tags with local bundles in layout template
- Add build scripts for vendor bundle creation and optimization
- Configure esbuild to process vendor bundles separately
- Total bundle size: ~512KB JS + 17KB CSS (optimized)

Benefits:
- Reduced external requests and CDN dependencies
- Better caching control and reliability
- Eliminated CORS and SRI integrity issues
- Faster page loads with bundled resources

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-25 13:56:12 -05:00
31bd5f5749
Switch back to raster map tiles
Disabled vector tiles by setting useVectorTiles to false.
The application will now use OpenStreetMap raster tiles instead.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-24 20:19:01 -05:00
9e45ffbf9a
ts tweak 2025-07-24 15:05:41 -05:00
206adb6b7d
back to raster 2025-07-24 12:02:28 -05:00
ae8c74afbe
try vector tiles 2025-07-24 10:54:31 -05:00
688fc6ba95
Implement mobile web optimization and fix sidebar clipping
- Add comprehensive mobile viewport meta tags for better mobile experience
- Implement touch gesture support with long-press to show station info
- Create mobile-specific CSS with touch target optimization (44px minimum)
- Add safe area insets support for notched devices
- Position zoom controls at bottom-right on mobile for thumb accessibility
- Optimize map performance on mobile with canvas renderer
- Fix desktop sidebar toggle button clipping when slideover is open
- Improve responsive design for slideover panels and popups
- Add landscape mode and high DPI screen optimizations

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 14:31:49 -05:00
44ae82eb9b
Improve map tile loading reliability
- Add retry logic with exponential backoff for failed tiles (up to 3 attempts)
- Configure tile layer with optimized settings (keepBuffer, updateInterval)
- Add support for alternative tile providers (OSM DE, CartoDB)
- Update CSP to allow alternative tile providers
- Add error tile placeholder to prevent broken images

This should help with partial tile loading issues by retrying failed requests
and providing fallback options.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 13:22:45 -05:00
63a87f3be1
Fix Docker build JavaScript import errors with vendor bundle
Fixed the esbuild errors during Docker build where npm packages couldn't
be resolved. The issue was caused by node_modules being excluded from
the Docker build context in .dockerignore.

Implemented a proper vendor bundle strategy following Phoenix 1.7+ patterns:

- Created vendor.js that bundles all npm dependencies (Leaflet, Chart.js,
  topbar) and their CSS files into a single pre-built bundle
- Added vendor esbuild profile in config.exs with proper CSS/image loaders
- Updated mix.exs to build vendor bundle before app bundle in assets.deploy
- Modified JavaScript imports to use globally loaded libraries from vendor
  bundle instead of importing from node_modules
- Added vendor.js script tag to root.html.heex before app.js

This approach avoids Docker build failures by pre-bundling all vendor
dependencies, eliminating the need for node_modules during production builds.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 12:32:39 -05:00
53ce452cdf
Fix Docker build CSS import errors
Moved CSS imports from Tailwind config to JavaScript to let ESBuild handle them.
This fixes the Docker build error where Tailwind couldn't resolve node_modules paths.

- Removed CSS @import statements from app.css
- Added CSS imports to map.ts where Leaflet is used
- Configured ESBuild to handle CSS and image files
- Added missing topbar package to package.json
- Updated both dev and prod ESBuild configs

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 11:59:04 -05:00
9b034cd211
vendor all js 2025-07-21 11:09:14 -05:00
493805706f
Fix Chart.js adapter dynamic require error with CommonJS shim
Fixed "Dynamic require of 'chart.js' is not supported" error that occurred
when the Chart.js date adapter tried to use require() in the browser.

The issue was caused by marking chart.js as external in esbuild, which
prevented the bundler from resolving the require() call. The date adapter
uses UMD format and expects to find Chart.js via require() in CommonJS
environments.

Solution:
- Added a temporary window.require shim before loading the date adapter
- The shim returns window.Chart when require('chart.js') is called
- Cleaned up the shim after the adapter loads to avoid polluting globals
- This allows the adapter to find Chart.js and register itself properly

The weather charts now load without errors in both development and production.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 10:21:32 -05:00
e7852e6201
Fix Chart.js date adapter loading error in vendor bundle
Fixed "This method is not implemented: Check that a complete date adapter
is provided" error that occurred when loading weather charts.

The issue was caused by the Chart.js date adapter trying to register
itself before Chart.js was fully loaded in the browser. Updated the
vendor.js bundle to ensure proper loading order and added verification
logging to confirm all libraries and adapters are loaded correctly.

Changes:
- Updated import order in vendor.js to ensure Chart.js loads first
- Added comments explaining the critical loading order requirements
- Added verification logging to check Chart.js adapters are registered

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 10:02:30 -05:00
7dc6c616a2
Bundle all vendor JavaScript files locally instead of loading from CDNs
This change eliminates all external CDN dependencies by bundling JavaScript
libraries locally using esbuild. All vendor files are now served from the
application's own assets, improving reliability and privacy.

Changes:
- Created assets/js/vendor.js to bundle all external libraries
- Added vendor bundle configuration to esbuild in config files
- Updated all templates to use local vendor.js instead of CDN scripts
- Created download-vendor-files.sh script to fetch vendor libraries
- Added vendor files to .gitignore (they're downloaded during setup)
- Updated CSS imports to include vendor stylesheets
- Added vendor build step to assets.deploy mix task

Bundled libraries:
- Leaflet 1.9.4 (mapping library)
- Leaflet.heat 0.2.0 (heatmap plugin)
- Leaflet.markercluster 1.5.3 (marker clustering)
- OverlappingMarkerSpiderfier 0.2.6 (overlapping marker handling)
- Chart.js 4.5.0 (charting library)
- chartjs-adapter-date-fns 3.0.0 (date adapter for Chart.js)

All functionality tested and working correctly with local bundles.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 09:52:39 -05:00
529b0790d6
Improve type safety for getTrailId function
- Update function signature to accept id as string | number
- Ensure consistent string conversion for all return paths
- Add test coverage for numeric ID cases
- Maintain backward compatibility with existing code

This fixes potential type mismatches where marker IDs can be either
strings or numbers throughout the codebase.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 08:36:38 -05:00
cf78298f46
Fix trail lines not connecting historical positions
When changing trail duration and historical data settings, historical positions
would show up on the map but trail lines wouldn't connect them. This was caused
by a mismatch between trail ID generation and callsign extraction.

## Changes

- Fix getTrailId() to properly extract base callsigns from historical marker IDs
- Add setTrailDuration() method to TrailManager for dynamic duration updates
- Add LiveView event to synchronize trail duration changes with client
- Add comprehensive tests for historical ID handling

## Problem
Historical markers have IDs like "hist_CALLSIGN_123" but getTrailId() was
returning the full ID while TrailManager.extractBaseCallsign() extracted just
"CALLSIGN", creating separate trails instead of connected ones.

## Solution
Updated getTrailId() to extract base callsigns from historical IDs using the
same logic as TrailManager, ensuring all positions from the same station use
the same trail ID and connect properly.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 08:31:16 -05:00
15f3e8fcfe
Fix JavaScript error when navigating from map to weather page
Fixed "can't access property 'invalidateSize', e.map is undefined" error
that occurred when navigating away from the map page while a setTimeout
was still trying to access the destroyed map.

Changes:
- Added check for self.map and self.isDestroyed before invalidating map size
- Stored timeout references in a cleanupTimeouts array
- Added cleanup code in destroyed() function to clear all pending timeouts
- Updated TypeScript type definition to include cleanupTimeouts property

This prevents attempting to access the map object after it has been
destroyed during page navigation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-20 08:19:51 -05:00
0d46b89c68
Use Sentry Loader script to handle CORS errors gracefully
- Replaced direct Sentry SDK script tag with the Sentry Loader
- The loader handles CORS/network failures gracefully without breaking the app
- Moved Sentry configuration to use the onLoad callback
- Maintains the same configuration (100% sampling, BrowserTracing, etc.)

The Sentry Loader is a small inline script that:
1. Captures errors immediately (even before SDK loads)
2. Loads the SDK asynchronously
3. Handles load failures gracefully
4. Replays captured errors once SDK is loaded

This approach avoids CORS errors breaking the page load while still
providing error tracking when the SDK is accessible.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:51:21 -05:00
1da12cf665
Remove debug console.log statements from JavaScript files
- Removed all console.log debugging statements from app.js (theme changes, chart rendering)
- Removed all console.log statements from map.ts (map initialization, data processing)
- Removed all console.debug statements from map_helpers.ts
- Removed all console.debug statements from map_fixes.ts
- Kept essential console.error and console.warn statements for error handling
- Reduced bundle size by ~1.4kb

This cleanup removes unnecessary debug output while maintaining error reporting
for production debugging via console.error and Sentry.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:37:05 -05:00
3c1aa29f82
Configure Sentry to sample 100% of errors and transactions
- Set tracesSampleRate to 1.0 for 100% transaction sampling
- Set sampleRate to 1.0 for 100% error sampling
- Ensures all JavaScript errors and performance data are captured

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:18:19 -05:00
dade93ee5c
Implement Sentry JavaScript integration with proper CSP configuration
- Restored Sentry JavaScript SDK script tag
- Created custom ContentSecurityPolicy plug to allow Sentry domains
- Added proper CSP headers allowing:
  - js.sentry-cdn.com for the SDK
  - *.ingest.sentry.io and *.sentry.io for error reporting
- Initialized Sentry in app.js with:
  - Proper DSN configuration
  - Browser tracing integration
  - 10% transaction sampling rate
  - Filter for non-critical ResizeObserver errors
- Added CSP plug to router pipeline after put_secure_browser_headers

This properly integrates Sentry for JavaScript error tracking while
maintaining security through explicit CSP configuration.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:17:35 -05:00
420d7ab57b
Remove debug console.log statements for hover handlers
- Removed console.log for "Adding hover handlers for RF packet"
- Removed console.log for "Marker hover start"
- Removed console.log for "Marker hover end"

These were debug statements that are no longer needed.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:12:26 -05:00
4af0f4a421
Fix JavaScript context binding issues in map component
- Fix "this.__view is undefined" error when calling pushEvent in event handlers
- Bind pushEvent context properly in all marker click and hover handlers
- Replace undefined sendBoundsToServer calls with saveMapState
- Ensure all event handlers check for pushEvent availability and type
- Use .bind(self) to preserve LiveView hook context in callbacks

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-18 15:05:15 -05:00
4b159ba0b7
cleanup 2025-07-18 14:44:52 -05:00
af4ab270e2
Replace any types with specific TypeScript types
- Add comprehensive type definitions for Leaflet plugins (heatmap, marker clustering, overlapping marker spiderfier)
- Create event payload interfaces for all LiveView events
- Add marker extension types for APRS-specific properties
- Define Chart.js dataset and configuration types
- Replace 74 instances of 'any' type across all TypeScript files
- Improve type safety for event handlers and state management
- Add proper typing for external library integrations

This refactoring enhances type safety throughout the codebase, making it easier to catch errors at compile time and improving IDE support for autocompletion and refactoring.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-17 17:55:27 -05:00
a31d38ec6a
different trail colors 2025-07-16 09:36:49 -05:00
1d1195ae87
js refactor 2025-07-16 09:23:33 -05:00
fa89712587
main map improvements 2025-07-13 14:58:13 -05:00
76c871ff39
make marker come to front view when clicked 2025-07-12 09:24:59 -05:00
b71ae879e9
debug cleanup 2025-07-11 14:05:42 -05:00
55b1a771e2
geolocation debug 2025-07-11 13:57:32 -05:00
1b428cbf78
add spider cluster 2025-07-11 13:00:32 -05:00
13ac1731fd
wip 2025-07-10 17:49:38 -05:00
f5e0f33ac2
fix geolocation hopefully 2025-07-10 17:12:49 -05:00
b1ee1f92f9
dont parse device identifiers on each insert 2025-07-10 15:16:01 -05:00
aaf92d9045
add heatmap on zoom out 2025-07-10 14:26:01 -05:00
d45aed256d
fix historical packet loading 2025-07-10 13:15:16 -05:00
c6169efe2a
fix js error 2025-07-09 16:56:31 -05:00
8eb1e90622
use postgis for testing 2025-07-09 16:48:55 -05:00
eb3e30abd6
tweaks 2025-07-09 16:37:30 -05:00
514d1b66d5
fix all the main map display issues 2025-07-09 16:20:29 -05:00
57fe2b0182
Remove all delays from historical packet loading for maximum speed
Server-side optimizations:
- Remove all Process.send_after delays - use immediate send()
- High zoom (10+): Load everything in single batch (up to 500 packets)
- Low zoom: Load all batches immediately without delays
- Remove debug logging for performance

Client-side optimizations:
- Remove chunking delays and requestAnimationFrame
- Process all packets immediately without setTimeout
- Remove 10-packet chunk limit - process everything at once

Result: Historical packets now load as fast as possible
without artificial delays or chunking bottlenecks.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-09 09:33:21 -05:00
a9414823f1
Fix spurious bounds_changed events and event loops
Key fixes:
- Combine bounds_changed and update_map_state into single event
- Remove duplicate sendBoundsToServer() calls
- Add programmaticMove flag to prevent event loops
- Only process bounds updates when bounds actually change
- Debounce events with 300ms timeout

This eliminates:
- Duplicate server events for same user action
- Event loops when server updates URL
- Unnecessary bounds processing
- Excessive server load

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-09 09:30:05 -05:00
052e131400
Add URL updating and restoration for map state (zoom/pan)
Features implemented:
- Parse URL parameters on mount (lat, lng, z)
- Update URL when map moves or zooms
- Restore map state from URL parameters
- Handle URL changes via handle_params
- Validate and clamp coordinate values

URL format: /?lat=40.7128&lng=-74.0060&z=12

Benefits:
- Shareable map links with exact position
- Browser back/forward navigation support
- Bookmarkable map locations
- Deep linking to specific map views

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-09 09:23:54 -05:00
1932f63b91
Implement progressive loading for historical packets to improve map performance
- Add progressive loading system that splits 200 packets into 4 batches of 50 each
- Implement client-side chunked rendering to prevent UI blocking
- Add caching layer using Aprsme.CachedQueries for better database performance
- Maintain proper chronological ordering for trail drawing
- Use LiveView's efficient update mechanisms for smooth user experience

Performance improvements:
- Faster initial load with immediate visual feedback
- Reduced memory pressure through smaller batch sizes
- Better caching with automatic cache invalidation
- Smooth, non-blocking UI updates using requestAnimationFrame

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-09 09:08:10 -05:00
41eaec5c8e
add user auth 2025-07-09 08:53:50 -05:00
5820400052
fix page layout when navigating between pages 2025-07-08 15:30:04 -05:00
bcaef2d118
pause extra map popups when user clicks on one 2025-07-08 10:18:07 -05:00