Commit graph

424 commits

Author SHA1 Message Date
FluxCD
cf2e91bd21 chore: update prop image to git.mcintire.me/graham/prop:main-1775661716-623a57b [skip ci] 2026-04-08 12:35:19 -05:00
FluxCD
5ae1fa2285 chore: update prop image to git.mcintire.me/graham/prop:main-1775657188-23b8dd0 [skip ci] 2026-04-08 12:35:19 -05:00
FluxCD
47f167b111 chore: update prop image to git.mcintire.me/graham/prop:main-1775601551-6cb6cf2 [skip ci] 2026-04-08 12:35:18 -05:00
2feedc0bd1 Dock map controls to right sidebar with collapsible panel
- Move controls (band selector, grid toggle, nav links) to a docked
  right sidebar on desktop, keep floating overlay on mobile
- Point detail panel floats over the map bottom-left instead of inside
  the narrow sidebar
- Add collapse/expand toggle for the sidebar
- Add auth links (login/logout/settings) to sidebar
- Wrap public live routes in live_session with UserAuth on_mount
- Use daisyUI menu lists for sidebar navigation
2026-04-08 12:34:36 -05:00
ddec874c38 Add /beacons CRUD and /users admin page
Beacons:
- Scaffolded with phx.gen.live then reworked so reads are public
  and mutations go through a live_session gated by the new
  :require_admin on_mount hook in UserAuth
- Beacon schema stores frequency (MHz), callsign, grid, lat/lon,
  power (W), and height above ground (m); grid auto-derives from
  lat/lon when left blank via Maidenhead.from_latlon
- Adds Maidenhead.from_latlon/3 so we can compute grids locally
  instead of hitting an external API

Users admin page:
- /users and /users/:id/edit (admin-only) for listing, editing
  (callsign/name/email/is_admin), and deleting other users
- Adds Accounts.list_users, admin_update_user, delete_user, and
  a dedicated admin_changeset on the User schema
- Nav gains a "Users" link for admins and a "Beacons" link for
  everyone
2026-04-08 12:01:34 -05:00
ea5fdd6479 Add is_admin flag, auto-grant to graham@mcintire.me
Adds a boolean is_admin column (default false) and has the
registration changeset auto-set it to true when the email matches
graham@mcintire.me (case-insensitive). The migration also backfills
the flag for an existing row with that email.
2026-04-08 11:41:43 -05:00
0a0154137d Add beacon monitor registration and fix prod SMTP
Users can now register beacon monitors on the settings page. Each
monitor gets a unique random token the remote program will use to
authenticate its reports. Name is the only user-supplied field for
now; more will be added as the monitor protocol is defined.

Also adds :gen_smtp to deps. Swoosh's SMTP adapter depends on
:mimemail which lives in that package, and production was 500'ing
when trying to send confirmation emails without it.
2026-04-08 11:29:50 -05:00
a8995bb43b Merge auth links into main nav and lower password min to 8
- Register/Log in (or callsign/Settings/Log out) now live next to
  the Map/Path/Rover links in the main header instead of a separate
  top menu bar
- Add on_mount in UserAuth to assign current_scope on LiveView mount,
  and pass current_scope through to Layouts.app from every LiveView
- Drop the old top <ul> from root.html.heex
- Password minimum lowered from 12 to 8 characters
2026-04-08 10:39:30 -05:00
adaa17719a Add password auth with callsign + email confirmation
Generated Accounts context, User schema, and controllers via
phx.gen.auth. Adapted it for password-only login with required
email confirmation:

- Users have callsign (unique, uppercased), name, email, password
- Registration form fields: callsign, name, email, password, confirm
- Magic-link login path removed; login is email + password only
- After register, a confirmation email is sent and login is blocked
  until the account is confirmed via the token URL
- Confirmation link logs the user in on first use
- SMTP2GO configured as the outgoing mailer in k8s prod
2026-04-08 10:21:16 -05:00
5d22a11091 Show grid squares by default on rover planner 2026-04-08 09:08:24 -05:00
b4594fa71f Add grid squares toggle to rover planner
Extract shared Maidenhead grid overlay into maidenhead_grid.js so both
the main map and rover planner use the same implementation. Wire up the
toggle_grid event and checkbox on the rover page matching the main map.
2026-04-08 09:04:44 -05:00
803516f0b0 Simplify rover planner: remove grid toggle and coverage calculation 2026-04-08 08:57:12 -05:00
cafa1c1a34 Add HRRR propagation overlay to rover planner map 2026-04-07 17:38:41 -05:00
FluxCD
0cb9583003 chore: update prop image to git.mcintire.me/graham/prop:main-1775600837-79a20d9 [skip ci] 2026-04-07 17:38:41 -05:00
FluxCD
13791b4c5a chore: update prop image to git.mcintire.me/graham/prop:main-1775600060-b84517b [skip ci] 2026-04-07 17:38:41 -05:00
f25055aa88 Render rover grid overlay above coverage using custom pane 2026-04-07 17:26:40 -05:00
FluxCD
dadd07846a chore: update prop image to git.mcintire.me/graham/prop:main-1775599523-c36abbe [skip ci] 2026-04-07 17:26:40 -05:00
b795544db0 Match rover grid toggle to main map's checkbox style 2026-04-07 17:14:01 -05:00
14f864c85d Show 'Press ESC to close' hint on map and weather pages
Subtle hint appears in top-right corner (desktop only) when the
detail panel is open. Fades in when panel shows, fades out on ESC.
Hidden on mobile where the X button is more appropriate.
2026-04-07 17:05:19 -05:00
FluxCD
b7e2bc7fe7 chore: update prop image to git.mcintire.me/graham/prop:main-1775599089-5777138 [skip ci] 2026-04-07 17:05:19 -05:00
db2ac29bb7 Use proper Maidenhead grid overlay on rover page
Extract GridSquare class and updateGridOverlay from propagation_map_hook
into shared maidenhead_grid.js module. Rover map now shows the same
zoom-adaptive Maidenhead grid overlay as the main /map page — red
rectangles with labels that switch between field (2-char) and square
(4-char) based on zoom level. Updates on pan/zoom.

Toggle button hides/shows the grid overlay.
2026-04-07 16:58:06 -05:00
FluxCD
da0443c127 chore: update prop image to git.mcintire.me/graham/prop:main-1775597973-82261a5 [skip ci] 2026-04-07 16:58:06 -05:00
dd8f5f69b9 Add 902-5760 MHz bands, centralize band options
New BandConfig entries for 902, 1296, 2304, 3456, 5760 MHz:
- All beneficial humidity effect (like 10 GHz)
- Near-zero gaseous absorption and rain attenuation
- Ranges: 902 MHz typical 400 km, 5760 MHz typical 220 km
- Same seasonal curves as 10 GHz (ducting-driven)

BandConfig.band_options/0 generates dropdown options from configs.
All pages (path, rover, submit) use centralized band_options instead
of hardcoded lists. Map page already used BandConfig.all_bands().
10 GHz remains the default on all pages.
2026-04-07 16:39:28 -05:00
FluxCD
70dafe5614 chore: update prop image to git.mcintire.me/graham/prop:main-1775597507-8d70606 [skip ci] 2026-04-07 16:39:28 -05:00
0c9e4ab749 Add grid toggle, use 0.25deg resolution for coverage scoring
- Toggle button for Maidenhead grid overlay (on by default)
- Coverage candidates now at 0.25° resolution (~28 km) instead of
  2°×1° Maidenhead grids, matching HRRR propagation grid density
- Coverage rectangles render as 0.25° cells for finer detail
- Grid overlay is separate from coverage coloring
2026-04-07 16:31:41 -05:00
FluxCD
1b0dc2d3c4 chore: update prop image to git.mcintire.me/graham/prop:main-1775596915-f06b219 [skip ci] 2026-04-07 16:31:41 -05:00
cd847b95b7 Fix rover: use length(@stations) instead of missing total_stations key 2026-04-07 16:21:50 -05:00
FluxCD
fd91819e0b chore: update prop image to git.mcintire.me/graham/prop:main-1775596089-d5e4702 [skip ci] 2026-04-07 16:21:50 -05:00
94c70b52d8 Extract Coverage module, fix computation, add tests
- Extract scoring logic to Microwaveprop.Rover.Coverage for testability
- Two-phase computation: fast pass (distance + propagation) for all grids,
  then SRTM terrain analysis for top 20 candidates only
- Cap search radius to 300 km to keep candidate count reasonable
- Run terrain analysis in Task with rescue/fallback for resilience
- Background Task doesn't block LiveView process
- 5 tests covering: ranked results, empty inputs, station details,
  band range differences, field presence
2026-04-07 16:08:05 -05:00
FluxCD
39364610dd chore: update prop image to git.mcintire.me/graham/prop:main-1775595241-0fe7800 [skip ci] 2026-04-07 16:08:05 -05:00
f185e67a89 Rename button to Find Best Roving Locations 2026-04-07 15:53:56 -05:00
8c88e0026e Fix rover planner: manual Calculate button, non-blocking computation
- Add explicit "Calculate Coverage" button instead of auto-triggering
- Move coverage computation to background Task so LV stays responsive
  (users can keep adding/removing stations while it computes)
- Remove all auto-compute triggers from station add/remove/band change
- URL loading resolves stations but doesn't auto-calculate
- Button shows "Finding best roving locations..." spinner while computing
2026-04-07 15:53:12 -05:00
FluxCD
b5d3f77b12 chore: update prop image to git.mcintire.me/graham/prop:main-1775594613-4031408 [skip ci] 2026-04-07 15:53:12 -05:00
9ee2b9dd1b Rover planner: auto-compute coverage areas with terrain + propagation
Rewrites rover planner to automatically color the map after stations
are entered. No manual stop selection needed — the system evaluates
every Maidenhead grid in range and scores them by:

- SRTM terrain analysis to each station (diffraction loss, LOS verdict)
- HRRR propagation forecast (ducting, refractivity, atmospheric conditions)
- Distance to stations vs band range limits
- Propagation boost: good conditions (score 80+) make blocked paths
  viable through ducting, matching the app's core beyond-LOS prediction

Coverage score formula: boosted path quality 30% + propagation 30%
+ distance 20% + station count 20%. Colored grid squares on the map
show best (green) to worst (red) operating positions.

Sidebar shows top 10 grids ranked with: workable station count,
propagation score, best operating hour, 18-hour forecast sparkline.
Click a grid for per-station detail: distance, terrain verdict,
diffraction loss.

URL stores stations + band for sharing: /rover?stations=W5ISP,K5TR&band=10000
2026-04-07 15:43:28 -05:00
FluxCD
902563510f chore: update prop image to git.mcintire.me/graham/prop:main-1775591085-4c0a4c0 [skip ci] 2026-04-07 15:43:28 -05:00
68b733b6d0 Throttle GPS updates on path page to once per minute
Switch from getCurrentPosition (which looped via push_patch) to
watchPosition with a 60-second throttle. Break the server-side
request_gps loop by skipping re-request when coords already exist.
2026-04-07 14:44:24 -05:00
7ffa20bee7 Add /rover planner for microwave contest rovers
Interactive map-based tool for planning rover operating positions.
Rovers enter stationary stations they want to work, then click the
map to evaluate candidate operating grids.

Features:
- Add stationary stations by callsign or grid square
- Click map to add operating positions (snaps to Maidenhead grid)
- Async SRTM terrain analysis: each stop computes terrain profile
  to every station, shows CLEAR/BLOCKED verdict + diffraction loss
- Terrain lines on map: green=workable, red=blocked, dashed=marginal
- Propagation score and 18-hour forecast sparkline per stop
- Route summary: driving distance, unique grid-station pairs
- Band selector affects range limits and propagation scores
- Numbered waypoint markers with score-colored backgrounds

New files:
- Geo module (shared haversine/bearing, used by PathLive too)
- RoverLive with fullscreen map + sidebar
- RoverMap JS hook with grid overlay, station/stop markers, route line
- Nav links in header and map control panel
2026-04-07 14:17:50 -05:00
FluxCD
2f2f73809c chore: update prop image to git.mcintire.me/graham/prop:main-1775588205-54b9a1f [skip ci] 2026-04-07 14:17:50 -05:00
92c013ab37 Keep source=gps in URL when GPS is used, single copy link, fix unicode
- GPS button sets source_is_gps flag, URL stays source=gps
- Form shows resolved coordinates but URL preserves gps intent
- Single "Copy Link" button copies current URL (includes gps if used)
- Fix unicode escapes in HEEx: use Elixir interpolation for subscripts
2026-04-07 13:56:39 -05:00
FluxCD
8f57a0b19f chore: update prop image to git.mcintire.me/graham/prop:main-1775587971-67fe71f [skip ci] 2026-04-07 13:56:39 -05:00
ba0d2541ca Improve path page UX: prominent GPS button, share links
- "My Location" button with text label (was just an icon)
- Two share buttons after results:
  - "Copy Link" — fixed coordinates, exact result
  - "Copy Link (use viewer's GPS)" — source=gps, dynamic per viewer
- CopyLink JS hook copies full URL to clipboard with "Copied!" feedback
2026-04-07 13:52:46 -05:00
FluxCD
024735009b chore: update prop image to git.mcintire.me/graham/prop:main-1775587689-be8e23c [skip ci] 2026-04-07 13:52:46 -05:00
5acaaa9fa1 Support source=gps in URL for dynamic GPS-based bookmarks
Bookmarking /path?source=gps&destination=K5TR&band=10000 will use
the viewer's device GPS to resolve the source location on load.
The LocateMe hook handles both button clicks and server-pushed
request_gps events. Once coords are resolved, the URL is updated
with actual lat,lon and calculation runs automatically.
2026-04-07 13:48:03 -05:00
FluxCD
8242ba682c chore: update prop image to git.mcintire.me/graham/prop:main-1775587563-40c1bb3 [skip ci] 2026-04-07 13:48:03 -05:00
e20fd27998 Add forecast timeline, shareable URLs, and real-time form updates to /path
- 18-hour propagation forecast bar chart from grid scores at path midpoint
  Shows best/worst score and time, color-coded bars
- URL query params: all form fields reflected in URL, auto-calculates
  when source+destination present. Bookmarkable/shareable links.
- phx-change on form updates assigns in real-time as user types
- Removed LiveStash in favor of URL-based state persistence
2026-04-07 13:46:00 -05:00
FluxCD
4f756e7e48 chore: update prop image to git.mcintire.me/graham/prop:main-1775587147-44fef0d [skip ci] 2026-04-07 13:46:00 -05:00
c5fdef2675 Add station parameters, GPS locate, and detailed budgets to /path
- TX/RX height in feet (converted to meters for terrain analysis)
- TX power in dBm with mW equivalent display
- TX gain and RX gain (dBi) inputs
- Power budget: TX power + TX gain - feed loss = EIRP - path loss
  + RX gain = RX power vs CW sensitivity = margin
- Loss budget: FSPL + gaseous (O2+H2O) + diffraction + rain
  with per-km gas rate detail
- GPS "Locate Me" button using browser geolocation API
- Lat,lon coordinate pairs accepted as input
- Weather displayed in F with C below
- LiveStash preserves form inputs across page reloads
- Terrain cross-section with beam line and Fresnel zone
2026-04-07 13:39:02 -05:00
FluxCD
c1e6d924eb chore: update prop image to git.mcintire.me/graham/prop:main-1775586313-259b9cd [skip ci] 2026-04-07 13:39:02 -05:00
c68774dd66 Add /path calculator page
LiveView page for analyzing microwave propagation between two points.
Features:
- Source/destination input: callsign (via gridmap.org API) or Maidenhead grid
- Band selector for all 8 microwave bands (10-241 GHz)
- Leaflet map showing path line (reuses ContactMap hook)
- Terrain elevation cross-section (reuses ElevationProfile hook)
- Link summary: distance, bearing, terrain verdict
- Loss budget: FSPL + O2 + H2O + rain + diffraction
- Propagation score with 10-factor breakdown
- Current atmospheric conditions from path-integrated HRRR

New CallsignClient for gridmap.org location lookup.
Navigation links added to main navbar and map control panel.
2026-04-07 13:25:07 -05:00
FluxCD
aaba91d5e3 chore: update prop image to git.mcintire.me/graham/prop:main-1775583477-ad44acb [skip ci] 2026-04-07 13:25:07 -05:00