callsign page fixes
This commit is contained in:
parent
445c9899cf
commit
fd1708e791
3 changed files with 55 additions and 65 deletions
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="csrf-token" content={get_csrf_token()} />
|
<meta name="csrf-token" content={get_csrf_token()} />
|
||||||
<.live_title suffix=" · Phoenix Framework">
|
<.live_title suffix=" · aprs.me">
|
||||||
{assigns[:page_title] || "Aprs"}
|
{assigns[:page_title] || "Aprs"}
|
||||||
</.live_title>
|
</.live_title>
|
||||||
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,8 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
|
|
||||||
# Schedule regular cleanup of old packets from the map
|
# Schedule regular cleanup of old packets from the map
|
||||||
Process.send_after(self(), :cleanup_old_packets, 60_000)
|
Process.send_after(self(), :cleanup_old_packets, 60_000)
|
||||||
# Schedule initialization of replay after a short delay
|
# Auto-start replay after a short delay
|
||||||
Process.send_after(self(), :initialize_replay, 2000)
|
Process.send_after(self(), :auto_start_replay, 2000)
|
||||||
|
|
||||||
{:ok, socket}
|
{:ok, socket}
|
||||||
else
|
else
|
||||||
|
|
@ -109,33 +109,6 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("toggle_replay", _params, socket) do
|
|
||||||
if socket.assigns.replay_active do
|
|
||||||
# Stop replay
|
|
||||||
if socket.assigns.replay_timer_ref do
|
|
||||||
Process.cancel_timer(socket.assigns.replay_timer_ref)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Clear historical packets from map
|
|
||||||
socket = push_event(socket, "clear_historical_packets", %{})
|
|
||||||
|
|
||||||
socket =
|
|
||||||
assign(socket,
|
|
||||||
replay_active: false,
|
|
||||||
replay_paused: false,
|
|
||||||
replay_timer_ref: nil,
|
|
||||||
replay_index: 0,
|
|
||||||
historical_packets: %{}
|
|
||||||
)
|
|
||||||
|
|
||||||
{:noreply, socket}
|
|
||||||
else
|
|
||||||
# Start replay
|
|
||||||
socket = start_historical_replay(socket)
|
|
||||||
{:noreply, assign(socket, replay_active: true, replay_paused: false)}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("pause_replay", _params, socket) do
|
def handle_event("pause_replay", _params, socket) do
|
||||||
if socket.assigns.replay_timer_ref do
|
if socket.assigns.replay_timer_ref do
|
||||||
Process.cancel_timer(socket.assigns.replay_timer_ref)
|
Process.cancel_timer(socket.assigns.replay_timer_ref)
|
||||||
|
|
@ -166,6 +139,15 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
def handle_event("map_ready", _params, socket) do
|
def handle_event("map_ready", _params, socket) do
|
||||||
socket = assign(socket, map_ready: true)
|
socket = assign(socket, map_ready: true)
|
||||||
|
|
||||||
|
# Auto-start replay if it hasn't been started yet
|
||||||
|
socket =
|
||||||
|
if socket.assigns.replay_started do
|
||||||
|
socket
|
||||||
|
else
|
||||||
|
socket = start_historical_replay(socket)
|
||||||
|
assign(socket, replay_started: true, replay_active: true)
|
||||||
|
end
|
||||||
|
|
||||||
# If we have a pending geolocation, zoom to it now
|
# If we have a pending geolocation, zoom to it now
|
||||||
socket =
|
socket =
|
||||||
if socket.assigns.pending_geolocation do
|
if socket.assigns.pending_geolocation do
|
||||||
|
|
@ -214,12 +196,17 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
socket = push_event(socket, "zoom_to_location", %{lat: lat, lng: lng, zoom: 12})
|
socket = push_event(socket, "zoom_to_location", %{lat: lat, lng: lng, zoom: 12})
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
|
|
||||||
:initialize_replay ->
|
:auto_start_replay ->
|
||||||
# Only start replay if it hasn't been started yet
|
# Auto-start replay if it hasn't been started yet and map is ready
|
||||||
if not socket.assigns.replay_started and socket.assigns.map_ready do
|
if not socket.assigns.replay_started and socket.assigns.map_ready do
|
||||||
socket = start_historical_replay(socket)
|
socket = start_historical_replay(socket)
|
||||||
{:noreply, assign(socket, replay_started: true)}
|
{:noreply, assign(socket, replay_started: true, replay_active: true)}
|
||||||
else
|
else
|
||||||
|
# If map isn't ready yet, try again in a bit
|
||||||
|
if not socket.assigns.map_ready do
|
||||||
|
Process.send_after(self(), :auto_start_replay, 1000)
|
||||||
|
end
|
||||||
|
|
||||||
{:noreply, socket}
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -583,15 +570,8 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="replay-controls">
|
<%= if @replay_active do %>
|
||||||
<button
|
<div class="replay-controls">
|
||||||
class={"replay-button #{if @replay_active, do: "active", else: ""}"}
|
|
||||||
phx-click="toggle_replay"
|
|
||||||
>
|
|
||||||
{if @replay_active, do: "Stop Replay", else: "Start Replay"}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<%= if @replay_active do %>
|
|
||||||
<button class="replay-button" phx-click="pause_replay">
|
<button class="replay-button" phx-click="pause_replay">
|
||||||
{if @replay_paused, do: "Resume", else: "Pause"}
|
{if @replay_paused, do: "Resume", else: "Pause"}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -608,8 +588,8 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
name="speed"
|
name="speed"
|
||||||
/>x
|
/>x
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
</div>
|
||||||
</div>
|
<% end %>
|
||||||
|
|
||||||
<button class="locate-button" phx-click="locate_me" title="Find my location">
|
<button class="locate-button" phx-click="locate_me" title="Find my location">
|
||||||
🎯
|
🎯
|
||||||
|
|
@ -617,9 +597,9 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
|
|
||||||
<%= if map_size(@visible_packets) == 0 and not @replay_active do %>
|
<%= if map_size(@visible_packets) == 0 and not @replay_active do %>
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
<h3>No Recent Packets</h3>
|
<h3>Loading Historical Data</h3>
|
||||||
<p>
|
<p>
|
||||||
No packets found for {@callsign} in the last hour. Try starting a historical replay to see older data.
|
Loading packet history for {@callsign}...
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
@ -666,23 +646,23 @@ defmodule AprsWeb.MapLive.CallsignView do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp start_historical_replay(socket) do
|
defp start_historical_replay(socket) do
|
||||||
# Fetch historical packets for the specific callsign
|
# Fetch historical packets for the specific callsign from the last hour
|
||||||
one_hour_ago = DateTime.add(DateTime.utc_now(), -3600, :second)
|
now = DateTime.utc_now()
|
||||||
six_hours_ago = DateTime.add(DateTime.utc_now(), -21_600, :second)
|
one_hour_ago = DateTime.add(now, -3600, :second)
|
||||||
|
|
||||||
packets =
|
packets =
|
||||||
fetch_historical_packets_for_callsign(
|
fetch_historical_packets_for_callsign(
|
||||||
socket.assigns.callsign,
|
socket.assigns.callsign,
|
||||||
six_hours_ago,
|
one_hour_ago,
|
||||||
one_hour_ago
|
now
|
||||||
)
|
)
|
||||||
|
|
||||||
socket =
|
socket =
|
||||||
assign(socket,
|
assign(socket,
|
||||||
replay_packets: packets,
|
replay_packets: packets,
|
||||||
replay_index: 0,
|
replay_index: 0,
|
||||||
replay_start_time: six_hours_ago,
|
replay_start_time: one_hour_ago,
|
||||||
replay_end_time: one_hour_ago,
|
replay_end_time: now,
|
||||||
historical_packets: %{}
|
historical_packets: %{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ defmodule AprsWeb.MapLive.CallsignViewTest do
|
||||||
assert html =~ "📡 W5ISP-9"
|
assert html =~ "📡 W5ISP-9"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows empty state when no packets found", %{conn: conn} do
|
test "shows loading state when no packets found", %{conn: conn} do
|
||||||
{:ok, _view, html} = live(conn, "/TESTCALL-1")
|
{:ok, _view, html} = live(conn, "/TESTCALL-1")
|
||||||
|
|
||||||
assert html =~ "No Recent Packets"
|
assert html =~ "Loading Historical Data"
|
||||||
assert html =~ "No packets found for TESTCALL-1"
|
assert html =~ "Loading packet history for TESTCALL-1"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles callsign without SSID", %{conn: conn} do
|
test "handles callsign without SSID", %{conn: conn} do
|
||||||
|
|
@ -32,23 +32,33 @@ defmodule AprsWeb.MapLive.CallsignViewTest do
|
||||||
assert html =~ "📡 W5ISP"
|
assert html =~ "📡 W5ISP"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "has replay controls", %{conn: conn} do
|
test "auto-starts replay and has pause controls", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, "/W5ISP-9")
|
{:ok, view, _html} = live(conn, "/W5ISP-9")
|
||||||
|
|
||||||
assert has_element?(view, "button", "Start Replay")
|
# Simulate map ready event to trigger auto-replay
|
||||||
|
render_hook(view, "map_ready", %{})
|
||||||
|
|
||||||
|
# Should have pause controls but no start/stop replay button
|
||||||
|
assert has_element?(view, "button", "Pause")
|
||||||
|
refute has_element?(view, "button", "Start Replay")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "can start and stop replay", %{conn: conn} do
|
test "can pause and resume replay", %{conn: conn} do
|
||||||
{:ok, view, _html} = live(conn, "/W5ISP-9")
|
{:ok, view, _html} = live(conn, "/W5ISP-9")
|
||||||
|
|
||||||
# Start replay
|
# Trigger map ready to start auto-replay
|
||||||
view |> element("button", "Start Replay") |> render_click()
|
render_hook(view, "map_ready", %{})
|
||||||
assert has_element?(view, "button", "Stop Replay")
|
|
||||||
|
# Should have pause button available
|
||||||
assert has_element?(view, "button", "Pause")
|
assert has_element?(view, "button", "Pause")
|
||||||
|
|
||||||
# Stop replay
|
# Pause replay
|
||||||
view |> element("button", "Stop Replay") |> render_click()
|
view |> element("button", "Pause") |> render_click()
|
||||||
assert has_element?(view, "button", "Start Replay")
|
assert has_element?(view, "button", "Resume")
|
||||||
|
|
||||||
|
# Resume replay
|
||||||
|
view |> element("button", "Resume") |> render_click()
|
||||||
|
assert has_element?(view, "button", "Pause")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "handles locate me button", %{conn: conn} do
|
test "handles locate me button", %{conn: conn} do
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue