diff --git a/lib/microwaveprop_web/live/rover_planning_live/show.ex b/lib/microwaveprop_web/live/rover_planning_live/show.ex index df906f6c..d7773899 100644 --- a/lib/microwaveprop_web/live/rover_planning_live/show.ex +++ b/lib/microwaveprop_web/live/rover_planning_live/show.ex @@ -253,6 +253,27 @@ defmodule MicrowavepropWeb.RoverPlanningLive.Show do defp station_grid(_), do: nil + # Inline label for the "Stationary stations" summary list. Prefers the + # callsign (uppercased — legacy data was stored mixed-case), then the + # grid, then the input string when neither is set. Bare lat/lon + # coordinates are intentionally NOT used as a label here — the grid + # half (via `stationary_grid/1`) carries that location info. + defp stationary_label(%{callsign: c}) when is_binary(c) and c != "", do: String.upcase(c) + defp stationary_label(%{grid: g}) when is_binary(g) and g != "", do: g + + defp stationary_label(%{input: i}) when is_binary(i) and i != "" do + if LocationResolver.coordinate_pair?(i), do: nil, else: String.upcase(i) + end + + defp stationary_label(_), do: nil + + defp stationary_grid(%{grid: g}) when is_binary(g) and g != "", do: g + + defp stationary_grid(%{lat: lat, lon: lon}) when is_number(lat) and is_number(lon), + do: Maidenhead.from_latlon(lat, lon, 6) + + defp stationary_grid(_), do: nil + # Endpoint string used for /path?destination=…. Prefers callsign, then # any stored or derived grid (PathLive's LocationResolver re-resolves # both back to the same point), falling back to bare coordinates only @@ -331,10 +352,11 @@ defmodule MicrowavepropWeb.RoverPlanningLive.Show do

Stationary stations

diff --git a/test/microwaveprop_web/live/rover_planning_live_test.exs b/test/microwaveprop_web/live/rover_planning_live_test.exs index 2bbf215c..fe9e28d2 100644 --- a/test/microwaveprop_web/live/rover_planning_live_test.exs +++ b/test/microwaveprop_web/live/rover_planning_live_test.exs @@ -231,6 +231,34 @@ defmodule MicrowavepropWeb.RoverPlanningLiveTest do assert html =~ "Propagation" end + test "stationary stations list shows uppercase callsign + grid, not bare lat/lon", %{conn: conn} do + import Ecto.Query, only: [from: 2] + + user = AccountsFixtures.user_fixture() + mission = create_mission(user, "Stationary label mission") + + # Backdate the station to mimic legacy data: callsign persisted in + # lowercase, no stored grid. The display should still render the + # callsign uppercase and synthesize a grid from lat/lon. + mission_id = mission.id + + [s1] = + Repo.all(from s in Microwaveprop.RoverPlanning.Station, where: s.mission_id == ^mission_id) + + {:ok, _} = + s1 + |> Ecto.Changeset.change(%{callsign: "aa5c", grid: nil, lat: 33.1889, lon: -96.4517}) + |> Repo.update() + + {:ok, _lv, html} = live(conn, ~p"/rover-planning/#{mission.id}") + + assert html =~ "AA5C" + # Bare lat/lon must not appear in the stationary-stations list. + refute html =~ "33.1889, -96.4517" + # A grid (derived from lat/lon when none is stored) IS shown. + assert html =~ Maidenhead.from_latlon(33.1889, -96.4517, 6) + end + test "rover-location group heading links to /rover-locations/:id", %{conn: conn} do user = AccountsFixtures.user_fixture() mission = create_mission(user, "Linked heading mission")