diff --git a/lib/microwaveprop_web/components/layouts.ex b/lib/microwaveprop_web/components/layouts.ex
index 1e8d020b..0af5b7ee 100644
--- a/lib/microwaveprop_web/components/layouts.ex
+++ b/lib/microwaveprop_web/components/layouts.ex
@@ -100,16 +100,6 @@ defmodule MicrowavepropWeb.Layouts do
North Texas Microwave Society
-
<.link navigate="/privacy" class="link link-hover">Privacy
diff --git a/lib/microwaveprop_web/live/contact_live/show.ex b/lib/microwaveprop_web/live/contact_live/show.ex
index 5c07f0e1..f085883c 100644
--- a/lib/microwaveprop_web/live/contact_live/show.ex
+++ b/lib/microwaveprop_web/live/contact_live/show.ex
@@ -74,9 +74,6 @@ defmodule MicrowavepropWeb.ContactLive.Show do
socket =
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")
- Phoenix.PubSub.subscribe(Microwaveprop.PubSub, "contact_enrichment:solar")
kickoff_hydration(socket, contact)
else
@@ -91,19 +88,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do
# clauses below update the matching slot and re-run the derived analysis.
defp kickoff_hydration(socket, contact) do
socket
- |> assign(
- :hydration_pending,
- MapSet.new([
- :weather,
- :solar,
- :hrrr_path,
- :narr_path,
- :native_profile,
- :terrain,
- :iemre,
- :radar
- ])
- )
+ |> assign(:hydration_pending, pending_slots(contact))
|> start_async(:weather, fn -> load_weather(contact) end)
|> start_async(:solar, fn -> load_solar(contact) end)
|> start_async(:hrrr_path, fn -> Weather.hrrr_profiles_for_path(contact) end)
@@ -114,6 +99,25 @@ defmodule MicrowavepropWeb.ContactLive.Show do
|> start_async(:radar, fn -> load_radar(contact) end)
end
+ # A slot shows its loading spinner only while the corresponding enrichment
+ # column on the contact says the work is genuinely in flight. For contacts
+ # whose status is :complete (or :pending/:unavailable/:failed), the async
+ # query just returns whatever is cached without any intermediate flash.
+ defp pending_slots(contact) do
+ in_flight = [:queued, :processing]
+ slots = []
+ slots = if contact.weather_status in in_flight, do: [:weather | slots], else: slots
+
+ slots =
+ if contact.hrrr_status in in_flight,
+ do: [:hrrr_path, :narr_path, :native_profile | slots],
+ else: slots
+
+ slots = if contact.terrain_status in in_flight, do: [:terrain | slots], else: slots
+ slots = if contact.iemre_status in in_flight, do: [:iemre | slots], else: slots
+ MapSet.new(slots)
+ end
+
defp mark_hydrated(socket, slot) do
assign(socket, :hydration_pending, MapSet.delete(socket.assigns.hydration_pending, slot))
end
@@ -458,57 +462,6 @@ defmodule MicrowavepropWeb.ContactLive.Show do
)}
end
- def handle_info({:hrrr_ready, _info}, socket) do
- contact = socket.assigns.contact
- hrrr_path = Weather.hrrr_profiles_for_path(contact)
- hrrr = List.first(hrrr_path)
-
- if hrrr do
- contact = %{contact | hrrr_status: :complete}
- soundings = socket.assigns.soundings
- terrain = socket.assigns.terrain
- elevation_profile = compute_elevation_profile(contact, hrrr_path, soundings)
- propagation_analysis = build_propagation_analysis(contact, hrrr_path, terrain, elevation_profile, soundings)
-
- {:noreply,
- assign(socket,
- contact: contact,
- hrrr: hrrr,
- queue_counts: fetch_queue_counts(),
- elevation_profile: elevation_profile,
- propagation_analysis: propagation_analysis
- )}
- else
- {:noreply, socket}
- end
- end
-
- def handle_info({:weather_ready, _info}, socket) do
- contact = %{socket.assigns.contact | weather_status: :complete}
- weather = load_weather(contact)
- soundings = weather.soundings
-
- hrrr_path = Weather.hrrr_profiles_for_path(contact)
- terrain = socket.assigns.terrain
-
- elevation_profile = compute_elevation_profile(contact, hrrr_path, soundings)
- propagation_analysis = build_propagation_analysis(contact, hrrr_path, terrain, elevation_profile, soundings)
-
- {:noreply,
- assign(socket,
- contact: contact,
- surface_observations: weather.surface_observations,
- soundings: soundings,
- elevation_profile: elevation_profile,
- propagation_analysis: propagation_analysis
- )}
- end
-
- def handle_info({:solar_ready, _date}, socket) do
- solar = load_solar(socket.assigns.contact)
- {:noreply, assign(socket, solar: solar)}
- end
-
defp maybe_enqueue_weather(weather, contact) do
has_data = weather.surface_observations != [] or weather.soundings != []