From bebead0fb04764ffeac106970cca6a64f4734789 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 4 Jul 2025 09:55:22 -0500 Subject: [PATCH] fix icons on pages --- lib/aprsme_web/live/info_live/show.html.heex | 445 +++++++++++++----- .../live/weather_live/callsign_view.ex | 14 + .../live/weather_live/callsign_view.html.heex | 306 ++++++------ 3 files changed, 492 insertions(+), 273 deletions(-) diff --git a/lib/aprsme_web/live/info_live/show.html.heex b/lib/aprsme_web/live/info_live/show.html.heex index d44f7be..2434296 100644 --- a/lib/aprsme_web/live/info_live/show.html.heex +++ b/lib/aprsme_web/live/info_live/show.html.heex @@ -16,133 +16,334 @@ <% _symbol_img = "/aprs-symbols/aprs-symbols-24-#{symbol_table_num}@2x.png" %> <% _symbol_index = symbol_code_ord - 33 %> -
-

- APRS station {@callsign} +
+ +
+
+
+
+
+

+ APRS Station +

+
+ + {@callsign} + + <%= if @packet do %> + <% {symbol_table_id, symbol_code} = + AprsmeWeb.MapLive.PacketUtils.get_symbol_info(@packet) %> + <% symbol_table = + if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> + <% symbol_code = symbol_code || ">" %> + <% table_id = + if symbol_table == "/", + do: "0", + else: if(symbol_table == "]", do: "2", else: "1") %> + <% symbol_code_ord = + symbol_code + |> String.to_charlist() + |> List.first() + |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> + <% index = symbol_code_ord - 33 %> + <% safe_index = max(0, min(index, 93)) %> + <% column = rem(safe_index, 16) %> + <% row = div(safe_index, 16) %> + <% x = -column * 128 %> + <% y = -row * 128 %> + <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> +
+
+ <% end %> +
+
+
+
+
+ <.link + navigate={~p"/packets/#{@callsign}"} + class="inline-flex items-center rounded-md bg-white px-3 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50" + > + View packets + + <%= if AprsmeWeb.MapLive.PacketUtils.has_weather_packets?(@callsign) do %> + <.link + navigate={~p"/weather/#{@callsign}"} + class="inline-flex items-center rounded-md bg-blue-600 px-3 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600" + > + Weather charts + + <% end %> +
+
+
+
+
+ +
<%= if @packet do %> - <% {symbol_table_id, symbol_code} = AprsmeWeb.MapLive.PacketUtils.get_symbol_info(@packet) %> - <% symbol_table = if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> - <% symbol_code = symbol_code || ">" %> - <% table_id = - if symbol_table == "/", do: "0", else: if(symbol_table == "]", do: "2", else: "1") %> - <% symbol_code_ord = - symbol_code - |> String.to_charlist() - |> List.first() - |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> - <% index = symbol_code_ord - 33 %> - <% safe_index = max(0, min(index, 93)) %> - <% column = rem(safe_index, 16) %> - <% row = div(safe_index, 16) %> - <% x = -column * 128 %> - <% y = -row * 128 %> - <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> -
-
- <% end %> - <.link navigate={~p"/packets/#{@callsign}"} class="ml-2 text-sm text-blue-600 hover:underline"> - View packets - - <%= if AprsmeWeb.MapLive.PacketUtils.has_weather_packets?(@callsign) do %> - <.link - navigate={~p"/weather/#{@callsign}"} - class="ml-2 text-sm text-blue-600 hover:underline" - > - Weather charts - - <% end %> -

- <%= if @packet do %> -
- {@packet.comment || ""} -
-
-
-
- Location: {@packet.lat || ""}, {@packet.lon || ""} + + <%= if @packet.comment && @packet.comment != "" do %> +
+
+
+
+ +
+
+

+ {@packet.comment} +

+
+
+
-
- Last position: {AprsmeWeb.MapLive.PacketUtils.get_timestamp( - @packet - )} + <% end %> + + +
+ +
+
+
+
+ + + + +
+
+

Position Information

+
+
+
+
+
Location
+
+ {@packet.lat || ""}, {@packet.lon || ""} +
+
+
+
Last Position
+
+ {AprsmeWeb.MapLive.PacketUtils.get_timestamp(@packet)} +
+
+
+
Altitude
+
{@packet.altitude} ft
+
+
+
Course
+
{@packet.course}°
+
+
+
Speed
+
{@packet.speed} MPH
+
+
+
-
Altitude: {@packet.altitude} ft
-
Course: {@packet.course}°
-
Speed: {@packet.speed} MPH
-
-
-
- Device: {@packet.manufacturer || ""} {@packet.equipment_type || - ""} -
-
Path: {@packet.path || ""}
-
- Raw: - <%= if is_binary(@packet.raw_packet) do %> - {Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)} - <% else %> - {@packet.raw_packet || ""} - <% end %> + + +
+
+
+
+ + + +
+
+

Device Information

+
+
+
+
+
Device
+
+ {@packet.manufacturer || ""} {@packet.equipment_type || ""} +
+
+
+
Path
+
{@packet.path || ""}
+
+
+
Raw Packet
+
+ <%= if is_binary(@packet.raw_packet) do %> + {Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)} + <% else %> + {@packet.raw_packet || ""} + <% end %> +
+
+
+
-
-

Stations near current position

-
- - - - - - - - - - <%= for neighbor <- @neighbors do %> - - +
CallsignDistanceLast heard
- <.link navigate={~p"/info/#{neighbor.callsign}"} class="hover:underline"> - {neighbor.callsign} - - <%= if neighbor.packet do %> - <% {symbol_table_id, symbol_code} = - AprsmeWeb.MapLive.PacketUtils.get_symbol_info(neighbor.packet) %> - <% symbol_table = - if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> - <% symbol_code = symbol_code || ">" %> - <% table_id = - if symbol_table == "/", - do: "0", - else: if(symbol_table == "]", do: "2", else: "1") %> - <% symbol_code_ord = - symbol_code - |> String.to_charlist() - |> List.first() - |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> - <% index = symbol_code_ord - 33 %> - <% safe_index = max(0, min(index, 93)) %> - <% column = rem(safe_index, 16) %> - <% row = div(safe_index, 16) %> - <% x = -column * 128 %> - <% y = -row * 128 %> - <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> -
+
+
+
+
+ + + +
+
+

Stations Near Current Position

+
+
+
+ + + + + + + + + + <%= for neighbor <- @neighbors do %> + + + + + <% end %> - - - - - <% end %> - -
- + Callsign + + Distance + + Last Heard +
+
+ <.link + navigate={~p"/info/#{neighbor.callsign}"} + class="text-blue-600 hover:text-blue-900" + > + {neighbor.callsign} + + <%= if neighbor.packet do %> + <% {symbol_table_id, symbol_code} = + AprsmeWeb.MapLive.PacketUtils.get_symbol_info(neighbor.packet) %> + <% symbol_table = + if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> + <% symbol_code = symbol_code || ">" %> + <% table_id = + if symbol_table == "/", + do: "0", + else: if(symbol_table == "]", do: "2", else: "1") %> + <% symbol_code_ord = + symbol_code + |> String.to_charlist() + |> List.first() + |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> + <% index = symbol_code_ord - 33 %> + <% safe_index = max(0, min(index, 93)) %> + <% column = rem(safe_index, 16) %> + <% row = div(safe_index, 16) %> + <% x = -column * 128 %> + <% y = -row * 128 %> + <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> +
+
+ <% end %> +
+
+ {neighbor.distance || ""} + + {neighbor.last_heard || ""} +
{neighbor.distance || ""}{neighbor.last_heard || ""}
-
- <% else %> -
No recent packet data available for this callsign.
- <% end %> +
+
+
+
+ <% else %> +
+ +

No data available

+

+ No recent packet data available for this callsign. +

+
+ <% end %> +
diff --git a/lib/aprsme_web/live/weather_live/callsign_view.ex b/lib/aprsme_web/live/weather_live/callsign_view.ex index cc808b6..99ef422 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.ex +++ b/lib/aprsme_web/live/weather_live/callsign_view.ex @@ -68,4 +68,18 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do end defp calc_dew_point(_, _), do: nil + + @doc """ + Gets weather field value, returning "0" instead of "N/A" for missing numeric data. + """ + def get_weather_field_zero(packet, key) do + value = PacketUtils.get_weather_field(packet, key) + + # Return "0" for missing numeric fields, keep other values as-is + case value do + "N/A" -> "0" + nil -> "0" + _ -> value + end + end end diff --git a/lib/aprsme_web/live/weather_live/callsign_view.html.heex b/lib/aprsme_web/live/weather_live/callsign_view.html.heex index 7ab65f8..e546bc1 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.html.heex +++ b/lib/aprsme_web/live/weather_live/callsign_view.html.heex @@ -1,160 +1,164 @@ <%= if @weather_packet do %> -
-

- Weather for {@callsign} - <%= if @weather_packet do %> - <% {symbol_table_id, symbol_code} = - AprsmeWeb.MapLive.PacketUtils.get_symbol_info(@weather_packet) %> - <% symbol_table = if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> - <% symbol_code = symbol_code || ">" %> - <% table_id = - if symbol_table == "/", do: "0", else: if(symbol_table == "]", do: "2", else: "1") %> - <% symbol_code_ord = - symbol_code - |> String.to_charlist() - |> List.first() - |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> - <% index = symbol_code_ord - 33 %> - <% safe_index = max(0, min(index, 93)) %> - <% column = rem(safe_index, 16) %> - <% row = div(safe_index, 16) %> - <% x = -column * 128 %> - <% y = -row * 128 %> - <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> +
+
+

+ Weather for {@callsign} + <%= if @weather_packet do %> + <% {symbol_table_id, symbol_code} = + AprsmeWeb.MapLive.PacketUtils.get_symbol_info(@weather_packet) %> + <% symbol_table = if symbol_table_id in ["/", "\\", "]"], do: symbol_table_id, else: "/" %> + <% symbol_code = symbol_code || ">" %> + <% table_id = + if symbol_table == "/", do: "0", else: if(symbol_table == "]", do: "2", else: "1") %> + <% symbol_code_ord = + symbol_code + |> String.to_charlist() + |> List.first() + |> (fn c -> if is_integer(c), do: c, else: 63 end).() %> + <% index = symbol_code_ord - 33 %> + <% safe_index = max(0, min(index, 93)) %> + <% column = rem(safe_index, 16) %> + <% row = div(safe_index, 16) %> + <% x = -column * 128 %> + <% y = -row * 128 %> + <% symbol_img = "/aprs-symbols/aprs-symbols-128-#{table_id}@2x.png" %> +
+
+ <% end %> + <.link + navigate={~p"/info/#{@callsign}"} + class="ml-2 text-blue-600 hover:underline text-base font-normal" + > + info + + <.link + navigate={~p"/#{@callsign}"} + class="ml-2 text-blue-600 hover:underline text-base font-normal" + > + view on map + +

+
+ {PacketUtils.get_timestamp(@weather_packet)} +
+
+
+ Temperature: + {PacketUtils.get_weather_field(@weather_packet, :temperature)}°F +
+
+ Humidity: + {PacketUtils.get_weather_field(@weather_packet, :humidity)}% +
+
+ Wind: + {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {PacketUtils.get_weather_field( + @weather_packet, + :wind_speed + )} mph +
+
+ Gusts: + {PacketUtils.get_weather_field(@weather_packet, :wind_gust)} mph +
+
+ Pressure: + {PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa +
+
+ Rain (1h): + {get_weather_field_zero(@weather_packet, :rain_1h)} in +
+
+ Rain (24h): + {get_weather_field_zero(@weather_packet, :rain_24h)} in +
+
+ Rain (since midnight): + {get_weather_field_zero(@weather_packet, :rain_since_midnight)} in +
+
+
+ Raw comment: {@weather_packet.comment || @weather_packet["comment"]} +
+
+
+

Weather History Graphs

+ <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :temperature, nil)))) do %>
<% end %> - <.link - navigate={~p"/info/#{@callsign}"} - class="ml-2 text-blue-600 hover:underline text-base font-normal" - > - info - - <.link - navigate={~p"/#{@callsign}"} - class="ml-2 text-blue-600 hover:underline text-base font-normal" - > - view on map - -

-
- {PacketUtils.get_timestamp(@weather_packet)} -
-
-
- Temperature: - {PacketUtils.get_weather_field(@weather_packet, :temperature)}°F -
-
- Humidity: - {PacketUtils.get_weather_field(@weather_packet, :humidity)}% -
-
- Wind: - {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {PacketUtils.get_weather_field( - @weather_packet, - :wind_speed - )} mph -
-
- Gusts: - {PacketUtils.get_weather_field(@weather_packet, :wind_gust)} mph -
-
- Pressure: - {PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa -
-
- Rain (1h): - {PacketUtils.get_weather_field(@weather_packet, :rain_1h)} in -
-
- Rain (24h): - {PacketUtils.get_weather_field(@weather_packet, :rain_24h)} in -
-
- Rain (since midnight): - {PacketUtils.get_weather_field(@weather_packet, :rain_since_midnight)} in -
-
-
- Raw comment: {@weather_packet.comment || @weather_packet["comment"]} -
-
-
-

Weather History Graphs

- <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :temperature, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :humidity, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :pressure, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :wind_direction, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :wind_speed, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_1h, nil)))) or Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_24h, nil)))) or Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_since_midnight, nil)))) do %> -
-
- <% end %> - <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :luminosity, nil)))) do %> -
-
- <% end %> - + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :humidity, nil)))) do %> +
+
+ <% end %> + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :pressure, nil)))) do %> +
+
+ <% end %> + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :wind_direction, nil)))) do %> +
+
+ <% end %> + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :wind_speed, nil)))) do %> +
+
+ <% end %> + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_1h, nil)))) or Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_24h, nil)))) or Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :rain_since_midnight, nil)))) do %> +
+
+ <% end %> + <%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :luminosity, nil)))) do %> +
+
+ <% end %> + +
<% else %> -
-

Weather for {@callsign}

-
No recent weather data available for this callsign.
+
+
+

Weather for {@callsign}

+
No recent weather data available for this callsign.
+
<% end %>