- rover_planning_live/show.ex: use pre-loaded @rover_sites assign instead of Repo.all(Location) on every keystroke - rover_locations_live/map.ex: cache locations query with 30s TTL (was loading + JSON-encoding all good locations in every mount) - status_live.ex: consolidate 5 separate stat fetches into single cached blob, so PubSub-triggered refreshes hit cache instead of running 10+ DB queries each time
77 lines
1.9 KiB
Elixir
77 lines
1.9 KiB
Elixir
defmodule MicrowavepropWeb.RoverLocationsLive.Map do
|
|
@moduledoc """
|
|
`/rover-locations/map` — full-screen map of every rover-location
|
|
marked Good. Each marker links to its detail page.
|
|
"""
|
|
use MicrowavepropWeb, :live_view
|
|
|
|
import Ecto.Query
|
|
|
|
alias Microwaveprop.Cache
|
|
alias Microwaveprop.Radio.Maidenhead
|
|
alias Microwaveprop.Repo
|
|
alias Microwaveprop.Rover.Location
|
|
|
|
@cache_key {__MODULE__, :points}
|
|
@cache_ttl_ms 30_000
|
|
|
|
@impl true
|
|
def mount(_params, _session, socket) do
|
|
points = cached_points()
|
|
|
|
{:ok,
|
|
assign(socket,
|
|
page_title: "Rover Locations Map",
|
|
points: points,
|
|
points_json: Jason.encode!(points)
|
|
)}
|
|
end
|
|
|
|
defp cached_points do
|
|
Cache.fetch_or_store(@cache_key, @cache_ttl_ms, fn ->
|
|
Location
|
|
|> where([l], l.status == :good)
|
|
|> Repo.all()
|
|
|> Enum.map(&point_payload/1)
|
|
end)
|
|
end
|
|
|
|
defp point_payload(%Location{} = loc) do
|
|
%{
|
|
id: loc.id,
|
|
lat: loc.lat,
|
|
lon: loc.lon,
|
|
grid: Maidenhead.from_latlon(loc.lat, loc.lon, 6),
|
|
notes: loc.notes
|
|
}
|
|
end
|
|
|
|
@impl true
|
|
def render(assigns) do
|
|
~H"""
|
|
<Layouts.app flash={@flash} current_scope={@current_scope} max_width="max-w-7xl">
|
|
<.header>
|
|
Rover Locations Map
|
|
<:subtitle>
|
|
{length(@points)} good location{if length(@points) == 1, do: "", else: "s"} —
|
|
click a marker for details.
|
|
</:subtitle>
|
|
<:actions>
|
|
<.link navigate={~p"/rover-locations"} class="btn btn-ghost btn-sm">
|
|
<.icon name="hero-list-bullet" class="w-4 h-4" /> List
|
|
</.link>
|
|
</:actions>
|
|
</.header>
|
|
|
|
<div
|
|
id="rover-locations-map"
|
|
phx-hook="RoverLocationsMap"
|
|
phx-update="ignore"
|
|
data-points={@points_json}
|
|
class="h-[75vh] rounded border border-base-300 z-0"
|
|
>
|
|
</div>
|
|
</Layouts.app>
|
|
"""
|
|
end
|
|
end
|