callsign map improvement and navbar fix
This commit is contained in:
parent
d70f47a708
commit
d0d4c543f2
4 changed files with 125 additions and 76 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<.header />
|
<!-- Remove the <.header /> component from this template -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 bg-white shadow-sm rounded-lg overflow-hidden">
|
<div class="mt-6 bg-white shadow-sm rounded-lg overflow-hidden">
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
alias AprsWeb.Endpoint
|
alias AprsWeb.Endpoint
|
||||||
alias AprsWeb.MapLive.MapHelpers
|
alias AprsWeb.MapLive.MapHelpers
|
||||||
alias AprsWeb.MapLive.PacketUtils
|
alias AprsWeb.MapLive.PacketUtils
|
||||||
|
alias AprsWeb.TimeHelpers
|
||||||
|
|
||||||
@default_center %{lat: 39.0, lng: -98.0}
|
@default_center %{lat: 39.0, lng: -98.0}
|
||||||
@default_zoom 4
|
@default_zoom 4
|
||||||
|
|
@ -713,78 +714,105 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
now
|
now
|
||||||
)
|
)
|
||||||
|
|
||||||
if Enum.empty?(packets) do
|
# Always fetch the latest packet with a position, regardless of age
|
||||||
# No historical packets found
|
latest_packet =
|
||||||
|
%{callsign: socket.assigns.callsign}
|
||||||
|
|> Packets.get_recent_packets()
|
||||||
|
|> Enum.filter(&MapHelpers.has_position_data?/1)
|
||||||
|
|> Enum.sort_by(& &1.received_at, {:desc, DateTime})
|
||||||
|
|> List.first()
|
||||||
|
|
||||||
|
# Sort packets by inserted_at to identify the most recent
|
||||||
|
sorted_packets =
|
||||||
|
Enum.sort_by(
|
||||||
|
packets,
|
||||||
|
fn packet ->
|
||||||
|
case packet.inserted_at do
|
||||||
|
%NaiveDateTime{} = naive_dt ->
|
||||||
|
DateTime.from_naive!(naive_dt, "Etc/UTC")
|
||||||
|
|
||||||
|
%DateTime{} = dt ->
|
||||||
|
dt
|
||||||
|
|
||||||
|
_other ->
|
||||||
|
DateTime.utc_now()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
{:desc, DateTime}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Filter out packets with unchanged positions (only keep if lat/lon changed)
|
||||||
|
unique_position_packets = filter_unique_positions(sorted_packets)
|
||||||
|
|
||||||
|
# Build packet data for all positions, marking which is the most recent
|
||||||
|
packet_data_list =
|
||||||
|
unique_position_packets
|
||||||
|
|> Enum.with_index()
|
||||||
|
|> Enum.map(fn {packet, index} ->
|
||||||
|
case build_packet_data(packet) do
|
||||||
|
nil ->
|
||||||
|
nil
|
||||||
|
|
||||||
|
packet_data ->
|
||||||
|
# Generate a unique ID for this historical packet
|
||||||
|
packet_id =
|
||||||
|
"hist_#{if Map.has_key?(packet, :id), do: packet.id, else: System.unique_integer([:positive])}_#{index}"
|
||||||
|
|
||||||
|
is_most_recent = index == 0
|
||||||
|
callsign = socket.assigns.callsign
|
||||||
|
|
||||||
|
packet_data
|
||||||
|
|> Map.put("id", packet_id)
|
||||||
|
|> Map.put("is_historical", true)
|
||||||
|
|> Map.put("is_most_recent_for_callsign", is_most_recent)
|
||||||
|
|> Map.put("callsign_group", callsign)
|
||||||
|
|> Map.put(
|
||||||
|
"timestamp",
|
||||||
|
case packet.inserted_at do
|
||||||
|
%NaiveDateTime{} = naive_dt ->
|
||||||
|
DateTime.to_unix(DateTime.from_naive!(naive_dt, "Etc/UTC"), :millisecond)
|
||||||
|
|
||||||
|
%DateTime{} = dt ->
|
||||||
|
DateTime.to_unix(dt, :millisecond)
|
||||||
|
|
||||||
|
_other ->
|
||||||
|
DateTime.to_unix(DateTime.utc_now(), :millisecond)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|
||||||
|
# Check if the latest_packet is present in the historical trail
|
||||||
|
latest_packet_id =
|
||||||
|
if latest_packet do
|
||||||
|
PacketUtils.generate_callsign(latest_packet)
|
||||||
|
end
|
||||||
|
|
||||||
|
historical_callsigns = MapSet.new(unique_position_packets, &PacketUtils.generate_callsign/1)
|
||||||
|
|
||||||
|
socket =
|
||||||
|
if latest_packet && !MapSet.member?(historical_callsigns, latest_packet_id) do
|
||||||
|
# Push the latest marker as a regular marker (not historical)
|
||||||
|
packet_data = build_packet_data(latest_packet)
|
||||||
|
|
||||||
|
if packet_data do
|
||||||
|
push_event(socket, "add_markers", %{markers: [packet_data]})
|
||||||
|
else
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
else
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
|
||||||
|
if Enum.empty?(packet_data_list) do
|
||||||
|
# No historical packets found (but latest marker may have been pushed above)
|
||||||
socket
|
socket
|
||||||
else
|
else
|
||||||
# Clear any previous historical packets from the map
|
# Clear any previous historical packets from the map
|
||||||
socket = push_event(socket, "clear_historical_packets", %{})
|
socket = push_event(socket, "clear_historical_packets", %{})
|
||||||
|
|
||||||
# Sort packets by inserted_at to identify the most recent
|
|
||||||
# Convert NaiveDateTime to DateTime if needed for proper comparison
|
|
||||||
sorted_packets =
|
|
||||||
Enum.sort_by(
|
|
||||||
packets,
|
|
||||||
fn packet ->
|
|
||||||
case packet.inserted_at do
|
|
||||||
%NaiveDateTime{} = naive_dt ->
|
|
||||||
DateTime.from_naive!(naive_dt, "Etc/UTC")
|
|
||||||
|
|
||||||
%DateTime{} = dt ->
|
|
||||||
dt
|
|
||||||
|
|
||||||
_other ->
|
|
||||||
DateTime.utc_now()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
{:desc, DateTime}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Filter out packets with unchanged positions (only keep if lat/lon changed)
|
|
||||||
unique_position_packets = filter_unique_positions(sorted_packets)
|
|
||||||
|
|
||||||
# Build packet data for all positions, marking which is the most recent
|
|
||||||
packet_data_list =
|
|
||||||
unique_position_packets
|
|
||||||
|> Enum.with_index()
|
|
||||||
|> Enum.map(fn {packet, index} ->
|
|
||||||
case build_packet_data(packet) do
|
|
||||||
nil ->
|
|
||||||
nil
|
|
||||||
|
|
||||||
packet_data ->
|
|
||||||
# Generate a unique ID for this historical packet
|
|
||||||
packet_id =
|
|
||||||
"hist_#{if Map.has_key?(packet, :id), do: packet.id, else: System.unique_integer([:positive])}_#{index}"
|
|
||||||
|
|
||||||
is_most_recent = index == 0
|
|
||||||
callsign = socket.assigns.callsign
|
|
||||||
|
|
||||||
packet_data
|
|
||||||
|> Map.put("id", packet_id)
|
|
||||||
|> Map.put("is_historical", true)
|
|
||||||
|> Map.put("is_most_recent_for_callsign", is_most_recent)
|
|
||||||
|> Map.put("callsign_group", callsign)
|
|
||||||
|> Map.put(
|
|
||||||
"timestamp",
|
|
||||||
case packet.inserted_at do
|
|
||||||
%NaiveDateTime{} = naive_dt ->
|
|
||||||
DateTime.to_unix(DateTime.from_naive!(naive_dt, "Etc/UTC"), :millisecond)
|
|
||||||
|
|
||||||
%DateTime{} = dt ->
|
|
||||||
DateTime.to_unix(dt, :millisecond)
|
|
||||||
|
|
||||||
_other ->
|
|
||||||
DateTime.to_unix(DateTime.utc_now(), :millisecond)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Enum.filter(& &1)
|
|
||||||
|
|
||||||
# Send all historical packets at once
|
# Send all historical packets at once
|
||||||
socket = push_event(socket, "add_historical_packets", %{packets: packet_data_list})
|
socket = push_event(socket, "add_historical_packets", %{packets: packet_data_list})
|
||||||
|
|
||||||
# Store historical packets in assigns for reference
|
# Store historical packets in assigns for reference
|
||||||
historical_packets_map =
|
historical_packets_map =
|
||||||
packet_data_list
|
packet_data_list
|
||||||
|
|
@ -857,6 +885,33 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp format_popup_timestamp(ts) do
|
||||||
|
dt =
|
||||||
|
cond do
|
||||||
|
is_binary(ts) ->
|
||||||
|
case DateTime.from_iso8601(ts) do
|
||||||
|
{:ok, dt, _} -> dt
|
||||||
|
_ -> DateTime.utc_now()
|
||||||
|
end
|
||||||
|
|
||||||
|
is_integer(ts) ->
|
||||||
|
DateTime.from_unix!(ts, :millisecond)
|
||||||
|
|
||||||
|
match?(%DateTime{}, ts) ->
|
||||||
|
ts
|
||||||
|
|
||||||
|
match?(%NaiveDateTime{}, ts) ->
|
||||||
|
DateTime.from_naive!(ts, "Etc/UTC")
|
||||||
|
|
||||||
|
true ->
|
||||||
|
DateTime.utc_now()
|
||||||
|
end
|
||||||
|
|
||||||
|
ago = TimeHelpers.time_ago_in_words(dt)
|
||||||
|
abs_time = Calendar.strftime(dt, "%Y-%m-%d %H:%M UTC")
|
||||||
|
{ago, abs_time}
|
||||||
|
end
|
||||||
|
|
||||||
defp build_packet_map(packet, lat, lng, data_extended) do
|
defp build_packet_map(packet, lat, lng, data_extended) do
|
||||||
data_extended = data_extended || %{}
|
data_extended = data_extended || %{}
|
||||||
callsign = PacketUtils.generate_callsign(packet)
|
callsign = PacketUtils.generate_callsign(packet)
|
||||||
|
|
@ -864,13 +919,15 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
timestamp = PacketUtils.get_timestamp(packet)
|
timestamp = PacketUtils.get_timestamp(packet)
|
||||||
comment = PacketUtils.get_packet_field(packet, :comment, "")
|
comment = PacketUtils.get_packet_field(packet, :comment, "")
|
||||||
|
|
||||||
|
{ago, abs_time} = format_popup_timestamp(timestamp)
|
||||||
|
|
||||||
popup = """
|
popup = """
|
||||||
<div class=\"aprs-popup\">
|
<div class=\"aprs-popup\">
|
||||||
<div class=\"aprs-callsign\"><strong><a href=\"/#{callsign}\">#{callsign}</a></strong></div>
|
<div class=\"aprs-callsign\"><strong><a href=\"/#{callsign}\">#{callsign}</a></strong></div>
|
||||||
<div class=\"aprs-symbol-info\">Symbol: #{symbol_table_id}#{symbol_code}</div>
|
<div class=\"aprs-symbol-info\">Symbol: #{symbol_table_id}#{symbol_code}</div>
|
||||||
#{if comment == "", do: "", else: "<div class=\\\"aprs-comment\\\">#{comment}</div>"}
|
#{if comment == "", do: "", else: "<div class=\\\"aprs-comment\\\">#{comment}</div>"}
|
||||||
<div class=\"aprs-coords\">#{Float.round(PacketUtils.to_float(lat), 4)}, #{Float.round(PacketUtils.to_float(lng), 4)}</div>
|
<div class=\"aprs-coords\">#{Float.round(PacketUtils.to_float(lat), 4)}, #{Float.round(PacketUtils.to_float(lng), 4)}</div>
|
||||||
<div class=\"aprs-time\">#{timestamp}</div>
|
<div class=\"aprs-timestamp\"><div>#{ago}</div><div>#{abs_time}</div></div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
||||||
<div class="mb-8">
|
|
||||||
<.header />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= if @error do %>
|
<%= if @error do %>
|
||||||
<div class="mt-6 bg-red-50 border border-red-200 rounded-md p-4">
|
<div class="mt-6 bg-red-50 border border-red-200 rounded-md p-4">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 my-8">
|
||||||
<div class="mb-8">
|
|
||||||
<.header />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6 bg-white shadow-sm rounded-lg overflow-hidden">
|
<div class="mt-6 bg-white shadow-sm rounded-lg overflow-hidden">
|
||||||
<.table id="packets" rows={@packets}>
|
<.table id="packets" rows={@packets}>
|
||||||
<:col :let={packet} label="Sender">
|
<:col :let={packet} label="Sender">
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue