From 17b66d690359c3949061948b6d419ad66aa17c3e Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 2 Apr 2026 08:22:43 -0500 Subject: [PATCH] Live-update soundings and surface observations on contact page - WeatherFetchWorker broadcasts on ASOS and RAOB completion - Contact show page subscribes and reloads weather data on receipt - Loading spinners for soundings and surface observations when queued - Propagation analysis recomputed with new sounding duct data --- .../workers/weather_fetch_worker.ex | 13 ++++ .../live/contact_live/show.ex | 62 ++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/lib/microwaveprop/workers/weather_fetch_worker.ex b/lib/microwaveprop/workers/weather_fetch_worker.ex index ab0ae3c1..1a1886ba 100644 --- a/lib/microwaveprop/workers/weather_fetch_worker.ex +++ b/lib/microwaveprop/workers/weather_fetch_worker.ex @@ -39,6 +39,12 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do if row.observed_at, do: Weather.upsert_surface_observation(station, row) end) + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:weather", + {:weather_ready, %{station_id: station_id}} + ) + :ok {:error, reason} -> @@ -96,6 +102,13 @@ defmodule Microwaveprop.Workers.WeatherFetchWorker do end Weather.upsert_sounding(station, sounding_attrs) + + Phoenix.PubSub.broadcast( + Microwaveprop.PubSub, + "contact_enrichment:weather", + {:weather_ready, %{station_id: station_id}} + ) + :ok {:ok, []} -> diff --git a/lib/microwaveprop_web/live/contact_live/show.ex b/lib/microwaveprop_web/live/contact_live/show.ex index cec5aae2..27342a72 100644 --- a/lib/microwaveprop_web/live/contact_live/show.ex +++ b/lib/microwaveprop_web/live/contact_live/show.ex @@ -24,6 +24,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do if connected?(socket) do Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:#{contact.id}") Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:hrrr") + Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:weather") end weather = load_weather(contact) @@ -42,6 +43,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do contact: contact, surface_observations: weather.surface_observations, soundings: weather.soundings, + weather_status: weather_status(weather, contact), solar: solar, hrrr: hrrr, hrrr_status: hrrr_status, @@ -154,6 +156,44 @@ defmodule MicrowavepropWeb.ContactLive.Show do end end + def handle_info({:weather_ready, _info}, socket) do + contact = socket.assigns.contact + weather = load_weather(contact) + soundings = weather.soundings + + hrrr_path = Weather.hrrr_profiles_for_path(contact) + hrrr = List.first(hrrr_path) + terrain = socket.assigns.terrain + elevation_profile = socket.assigns.elevation_profile + + # Recompute propagation analysis with new sounding data (duct detection) + propagation_analysis = + if elevation_profile || hrrr do + build_propagation_analysis(contact, hrrr, terrain, elevation_profile, soundings) + else + socket.assigns.propagation_analysis + end + + {:noreply, + assign(socket, + surface_observations: weather.surface_observations, + soundings: soundings, + weather_status: :loaded, + propagation_analysis: propagation_analysis + )} + end + + defp weather_status(weather, contact) do + has_data = weather.surface_observations != [] or weather.soundings != [] + + cond do + has_data -> :loaded + contact.weather_queued -> :queued + contact.pos1 -> :queued + true -> :unavailable + end + end + defp toggle_sort(current_field, current_order, new_field) do if current_field == new_field && current_order == "asc", do: {new_field, "desc"}, @@ -494,7 +534,16 @@ defmodule MicrowavepropWeb.ContactLive.Show do

Soundings

<%= if @soundings == [] do %> -

No soundings found nearby.

+
+ <%= if @weather_status == :queued do %> + + + Fetching sounding data from nearby stations... + + <% else %> + No soundings found nearby. + <% end %> +
<% else %> <%= for s <- @soundings do %>
@@ -660,7 +709,16 @@ defmodule MicrowavepropWeb.ContactLive.Show do

Surface Observations

<%= if @surface_observations == [] do %> -

No surface observations found nearby.

+
+ <%= if @weather_status == :queued do %> + + + Fetching surface observations from nearby stations... + + <% else %> + No surface observations found nearby. + <% end %> +
<% else %>