From 2c1c221398f8d19c610f8aee5ad9a9ef04cb7011 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 11 Apr 2026 09:44:41 -0500 Subject: [PATCH] Change beacon height_ft from float to integer Height in feet doesn't need decimal precision. Migrates the DB column, updates schema type, and strips trailing .0 from form input so the integer cast succeeds. --- lib/microwaveprop/beacons/beacon.ex | 5 +++-- lib/microwaveprop_web/live/beacon_live/form.ex | 8 ++++++-- lib/microwaveprop_web/live/beacon_live/index.ex | 4 ++-- lib/microwaveprop_web/live/beacon_live/show.ex | 2 +- ...20260411144239_change_beacon_height_ft_to_integer.exs | 9 +++++++++ test/microwaveprop/beacons/range_estimate_test.exs | 2 +- test/support/fixtures/beacons_fixtures.ex | 2 +- 7 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 priv/repo/migrations/20260411144239_change_beacon_height_ft_to_integer.exs diff --git a/lib/microwaveprop/beacons/beacon.ex b/lib/microwaveprop/beacons/beacon.ex index 73927947..27264f33 100644 --- a/lib/microwaveprop/beacons/beacon.ex +++ b/lib/microwaveprop/beacons/beacon.ex @@ -135,7 +135,7 @@ defmodule Microwaveprop.Beacons.Beacon do field :lat, :float field :lon, :float field :power_mw, :float - field :height_ft, :float + field :height_ft, :integer field :on_the_air, :boolean, default: true field :approved, :boolean, default: false field :keying, :string, default: "on_off" @@ -190,7 +190,8 @@ defmodule Microwaveprop.Beacons.Beacon do defp round_coord(v), do: v defp round_int(nil), do: nil - defp round_int(v) when is_float(v), do: Float.round(v, 0) + defp round_int(v) when is_float(v), do: round(v) + defp round_int(v) when is_integer(v), do: v defp round_int(v), do: v # If grid is blank but lat/lon are valid, derive it. diff --git a/lib/microwaveprop_web/live/beacon_live/form.ex b/lib/microwaveprop_web/live/beacon_live/form.ex index 1374d12b..e6fe0541 100644 --- a/lib/microwaveprop_web/live/beacon_live/form.ex +++ b/lib/microwaveprop_web/live/beacon_live/form.ex @@ -41,7 +41,6 @@ defmodule MicrowavepropWeb.BeaconLive.Form do field={@form[:height_ft]} type="number" label="Height above ground (ft)" - step="any" required /> <.input @@ -115,10 +114,15 @@ defmodule MicrowavepropWeb.BeaconLive.Form do end defp strip_commas(params) do - Map.update(params, "frequency_mhz", nil, fn + params + |> Map.update("frequency_mhz", nil, fn v when is_binary(v) -> String.replace(v, ",", "") v -> v end) + |> Map.update("height_ft", nil, fn + v when is_binary(v) -> v |> String.replace(~r/\.0*$/, "") + v -> v + end) end defp save_beacon(socket, :edit, beacon_params) do diff --git a/lib/microwaveprop_web/live/beacon_live/index.ex b/lib/microwaveprop_web/live/beacon_live/index.ex index 0ccfec83..2c9bea74 100644 --- a/lib/microwaveprop_web/live/beacon_live/index.ex +++ b/lib/microwaveprop_web/live/beacon_live/index.ex @@ -30,7 +30,7 @@ defmodule MicrowavepropWeb.BeaconLive.Index do <:col :let={{_id, beacon}} label="Lat">{beacon.lat} <:col :let={{_id, beacon}} label="Lon">{beacon.lon} <:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)} - <:col :let={{_id, beacon}} label="Height AGL (ft)">{if beacon.height_ft, do: round(beacon.height_ft)} + <:col :let={{_id, beacon}} label="Height AGL (ft)">{beacon.height_ft} <:col :let={{_id, beacon}} label="Keying">{Beacon.keying_label(beacon.keying)} <:col :let={{_id, beacon}} label="On air"> @@ -69,7 +69,7 @@ defmodule MicrowavepropWeb.BeaconLive.Index do <:col :let={{_id, beacon}} label="Call">{beacon.callsign} <:col :let={{_id, beacon}} label="Grid">{beacon.grid} <:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)} - <:col :let={{_id, beacon}} label="Height AGL (ft)">{if beacon.height_ft, do: round(beacon.height_ft)} + <:col :let={{_id, beacon}} label="Height AGL (ft)">{beacon.height_ft} <:col :let={{_id, beacon}} label="Submitted"> {Calendar.strftime(beacon.inserted_at, "%Y-%m-%d %H:%M UTC")} diff --git a/lib/microwaveprop_web/live/beacon_live/show.ex b/lib/microwaveprop_web/live/beacon_live/show.ex index 7d9a9e01..229b9be6 100644 --- a/lib/microwaveprop_web/live/beacon_live/show.ex +++ b/lib/microwaveprop_web/live/beacon_live/show.ex @@ -118,7 +118,7 @@ defmodule MicrowavepropWeb.BeaconLive.Show do <.stat_field label="Longitude">{format_coord(@beacon.lon)} <.stat_field label="EIRP">{Beacon.format_mw(@beacon.power_mw)} mW - <.stat_field label="Height AGL">{if @beacon.height_ft, do: round(@beacon.height_ft)} ft + <.stat_field label="Height AGL">{@beacon.height_ft} ft <.stat_field label="Bearing">{bearing_label(@beacon.bearing)} <.stat_field :if={@beacon.beamwidth_deg} label="Beamwidth"> {Beacon.format_mw(@beacon.beamwidth_deg)}° diff --git a/priv/repo/migrations/20260411144239_change_beacon_height_ft_to_integer.exs b/priv/repo/migrations/20260411144239_change_beacon_height_ft_to_integer.exs new file mode 100644 index 00000000..00fe3495 --- /dev/null +++ b/priv/repo/migrations/20260411144239_change_beacon_height_ft_to_integer.exs @@ -0,0 +1,9 @@ +defmodule Microwaveprop.Repo.Migrations.ChangeBeaconHeightFtToInteger do + use Ecto.Migration + + def change do + alter table(:beacons) do + modify :height_ft, :integer, from: :float + end + end +end diff --git a/test/microwaveprop/beacons/range_estimate_test.exs b/test/microwaveprop/beacons/range_estimate_test.exs index d34b5f53..11562dc5 100644 --- a/test/microwaveprop/beacons/range_estimate_test.exs +++ b/test/microwaveprop/beacons/range_estimate_test.exs @@ -13,7 +13,7 @@ defmodule Microwaveprop.Beacons.RangeEstimateTest do lat: 32.897, lon: -97.038, power_mw: 10_000.0, - height_ft: 100.0, + height_ft: 100, on_the_air: true } diff --git a/test/support/fixtures/beacons_fixtures.ex b/test/support/fixtures/beacons_fixtures.ex index 2a2c56cd..0324d367 100644 --- a/test/support/fixtures/beacons_fixtures.ex +++ b/test/support/fixtures/beacons_fixtures.ex @@ -12,7 +12,7 @@ defmodule Microwaveprop.BeaconsFixtures do lat: 32.897, lon: -97.038, power_mw: 10_000.0, - height_ft: 100.0 + height_ft: 100 }) end