A new "Rover sites" section between Stationary stations and Path
profiles lists the candidate rover locations the mission scores
against, with:
- An add form that takes the same flexible input as station inputs
(callsign, Maidenhead grid, or `lat,lon`); on submit it creates a
global :good rover-location and re-runs the path matrix.
- A per-row trash button visible to the location's owner / admins
that deletes the location and re-runs the matrix.
`RoverPlanning.candidate_rover_locations/1` is now public so the show
page can list exactly what the worker enqueues against. Add/remove
both call `replace_mission_paths/1` so the matrix stays consistent
with the rover-site set.
Anonymous visitors see a sign-in prompt instead of the form.
When a user types raw "lat,lon" coordinates into a station input,
LocationResolver populates only `lat` / `lon` — `callsign` and `grid`
stay blank. The path-profiles "Station" cell was falling through to
"33.189, -96.452" instead of showing a useful grid.
Now `station_label/1` (display) and `station_endpoint/1` (path-URL
destination) derive a 6-/8-char Maidenhead grid from the stored
lat/lon when no grid is on the row, matching the rest of the page's
grid-first presentation.
- Rows in each rover-location group are now phx-click handlers that
navigate to /path with source (rover-loc as 10-char Maidenhead grid),
destination (callsign > grid > coords), band, and rover/station
heights pre-filled — one click takes you to a ready-to-compute Path
Calculator screen.
- Station label now shows "AA5C · EM12kp" when both callsign and grid
resolved, instead of falling back to lat/lon. Bare-grid and
bare-coord stations keep their existing labels.
- Group heading uses Maidenhead.from_latlon(lat, lon, 10) so the
10-char grid is shown in full instead of being truncated to 6
characters.
The flat path table forced you to scan column 1 to mentally group rows
when standing at a specific rover spot. Each rover location now gets
its own card with a heading (grid + lat/lon + notes) and an inner
station-by-station table, so the paths to the fixed stations from the
spot you're at are read in one place.
Sorted by latitude (north → south) so the same location keeps the same
slot across re-renders. `rover_label/1` is removed (its content now
lives in the group heading).
- add_station no longer seeds `"input" => ""` in params, so used_input?/1
treats the new row as untouched and hides the validate_required error
until the user types.
- Show page's format_distance/format_db/format_meters helpers coerce with
`* 1.0` because JSONB returns bare zeros as integers, which crashed
Float.round/2 (FunctionClauseError on /rover-planning/:id render).
- Lat/lon row uses items-start + mt-6 trash so the inputs stay aligned
even when the callsign cell grows from validation feedback.
Renames the rover-location status enum and every label that referenced
it. Existing rows are migrated in place. Also touches the consumers:
- Rover.Location enum + default
- RoverLocationsLive index, status filter, form, show, badges
- Rover.Compute and rover_live (only_ideal_locations → only_good_locations)
- RoverPlanning context candidate filter (status == :good)
- RoverPlanning.Show / Form copy
- All rover-related tests
Adds a new globally-scoped, owner-mutable rover-mission tracker:
- /rover-planning paginated table (LiveTable) with View/Edit/Delete
- /rover-planning/new + /:id/edit form: name, band, antenna heights,
notes, "only check against known good locations" toggle (default on),
and a dynamic list of stationary stations entered as callsigns,
Maidenhead grids, or lat,lon pairs (Station changeset geocodes via
LocationResolver, lat/lon stays editable after add)
- /rover-planning/:id show page renders the station list, scope, and a
matrix of computed path profiles (distance, min clearance, diffraction,
verdict) populated as the worker completes each pairing
After save, RoverPlanning enqueues one RoverPathProfileWorker job per
(rover-location × station) pairing. The worker mirrors PathLive's
synchronous compute (ElevationClient + TerrainAnalysis at the mission's
band + heights) and stores the result on the matching path row.
PubSub broadcast on completion lets the show page live-refresh.
Admins can edit/delete any mission; owners can edit their own.