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.
This commit is contained in:
Graham McIntire 2026-04-11 09:44:41 -05:00
parent 9b5880f01b
commit 2c1c221398
7 changed files with 23 additions and 9 deletions

View file

@ -135,7 +135,7 @@ defmodule Microwaveprop.Beacons.Beacon do
field :lat, :float field :lat, :float
field :lon, :float field :lon, :float
field :power_mw, :float field :power_mw, :float
field :height_ft, :float field :height_ft, :integer
field :on_the_air, :boolean, default: true field :on_the_air, :boolean, default: true
field :approved, :boolean, default: false field :approved, :boolean, default: false
field :keying, :string, default: "on_off" field :keying, :string, default: "on_off"
@ -190,7 +190,8 @@ defmodule Microwaveprop.Beacons.Beacon do
defp round_coord(v), do: v defp round_coord(v), do: v
defp round_int(nil), do: nil 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 defp round_int(v), do: v
# If grid is blank but lat/lon are valid, derive it. # If grid is blank but lat/lon are valid, derive it.

View file

@ -41,7 +41,6 @@ defmodule MicrowavepropWeb.BeaconLive.Form do
field={@form[:height_ft]} field={@form[:height_ft]}
type="number" type="number"
label="Height above ground (ft)" label="Height above ground (ft)"
step="any"
required required
/> />
<.input <.input
@ -115,10 +114,15 @@ defmodule MicrowavepropWeb.BeaconLive.Form do
end end
defp strip_commas(params) do 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 when is_binary(v) -> String.replace(v, ",", "")
v -> v v -> v
end) end)
|> Map.update("height_ft", nil, fn
v when is_binary(v) -> v |> String.replace(~r/\.0*$/, "")
v -> v
end)
end end
defp save_beacon(socket, :edit, beacon_params) do defp save_beacon(socket, :edit, beacon_params) do

View file

@ -30,7 +30,7 @@ defmodule MicrowavepropWeb.BeaconLive.Index do
<:col :let={{_id, beacon}} label="Lat">{beacon.lat}</:col> <:col :let={{_id, beacon}} label="Lat">{beacon.lat}</:col>
<:col :let={{_id, beacon}} label="Lon">{beacon.lon}</:col> <:col :let={{_id, beacon}} label="Lon">{beacon.lon}</:col>
<:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)}</:col> <:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)}</:col>
<:col :let={{_id, beacon}} label="Height AGL (ft)">{if beacon.height_ft, do: round(beacon.height_ft)}</:col> <:col :let={{_id, beacon}} label="Height AGL (ft)">{beacon.height_ft}</:col>
<:col :let={{_id, beacon}} label="Keying">{Beacon.keying_label(beacon.keying)}</:col> <:col :let={{_id, beacon}} label="Keying">{Beacon.keying_label(beacon.keying)}</:col>
<:col :let={{_id, beacon}} label="On air"> <:col :let={{_id, beacon}} label="On air">
<span class={["badge badge-sm", (beacon.on_the_air && "badge-success") || "badge-ghost"]}> <span class={["badge badge-sm", (beacon.on_the_air && "badge-success") || "badge-ghost"]}>
@ -69,7 +69,7 @@ defmodule MicrowavepropWeb.BeaconLive.Index do
<:col :let={{_id, beacon}} label="Call">{beacon.callsign}</:col> <:col :let={{_id, beacon}} label="Call">{beacon.callsign}</:col>
<:col :let={{_id, beacon}} label="Grid">{beacon.grid}</:col> <:col :let={{_id, beacon}} label="Grid">{beacon.grid}</:col>
<:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)}</:col> <:col :let={{_id, beacon}} label="EIRP (mW)">{Beacon.format_mw(beacon.power_mw)}</:col>
<:col :let={{_id, beacon}} label="Height AGL (ft)">{if beacon.height_ft, do: round(beacon.height_ft)}</:col> <:col :let={{_id, beacon}} label="Height AGL (ft)">{beacon.height_ft}</:col>
<:col :let={{_id, beacon}} label="Submitted"> <:col :let={{_id, beacon}} label="Submitted">
{Calendar.strftime(beacon.inserted_at, "%Y-%m-%d %H:%M UTC")} {Calendar.strftime(beacon.inserted_at, "%Y-%m-%d %H:%M UTC")}
</:col> </:col>

View file

@ -118,7 +118,7 @@ defmodule MicrowavepropWeb.BeaconLive.Show do
<.stat_field label="Longitude">{format_coord(@beacon.lon)}</.stat_field> <.stat_field label="Longitude">{format_coord(@beacon.lon)}</.stat_field>
<.stat_field label="EIRP">{Beacon.format_mw(@beacon.power_mw)} mW</.stat_field> <.stat_field label="EIRP">{Beacon.format_mw(@beacon.power_mw)} mW</.stat_field>
<.stat_field label="Height AGL">{if @beacon.height_ft, do: round(@beacon.height_ft)} ft</.stat_field> <.stat_field label="Height AGL">{@beacon.height_ft} ft</.stat_field>
<.stat_field label="Bearing">{bearing_label(@beacon.bearing)}</.stat_field> <.stat_field label="Bearing">{bearing_label(@beacon.bearing)}</.stat_field>
<.stat_field :if={@beacon.beamwidth_deg} label="Beamwidth"> <.stat_field :if={@beacon.beamwidth_deg} label="Beamwidth">
{Beacon.format_mw(@beacon.beamwidth_deg)}° {Beacon.format_mw(@beacon.beamwidth_deg)}°

View file

@ -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

View file

@ -13,7 +13,7 @@ defmodule Microwaveprop.Beacons.RangeEstimateTest do
lat: 32.897, lat: 32.897,
lon: -97.038, lon: -97.038,
power_mw: 10_000.0, power_mw: 10_000.0,
height_ft: 100.0, height_ft: 100,
on_the_air: true on_the_air: true
} }

View file

@ -12,7 +12,7 @@ defmodule Microwaveprop.BeaconsFixtures do
lat: 32.897, lat: 32.897,
lon: -97.038, lon: -97.038,
power_mw: 10_000.0, power_mw: 10_000.0,
height_ft: 100.0 height_ft: 100
}) })
end end