towerops/lib/towerops_web/live/site_live/show.ex
Graham McIntire 89a076fb67
feat: migrate equipment features to gettext and fix sudo mode tests
Migrates all equipment-related flash messages to gettext for internationalization:
- DeviceLive.Index: device discovery, reordering, error messages
- DeviceLive.Show: backup messages, permission errors
- DeviceLive.Form: device CRUD operations
- AlertLive.Index: alert acknowledgment messages
- SiteLive.Show: site discovery messages
- SiteLive.Form: site CRUD and SNMP/agent propagation

Fixes sudo mode test suite issues:
- Updates Accounts.sudo_mode?/2 test to check last_sudo_at instead of authenticated_at
- Adds register_and_log_in_user_with_sudo/1 helper to ConnCase
- Fixes UserAuth sudo mode tests to use session-based authentication
- Updates MyData tests to use sudo mode (now required per router config)
- Removes obsolete UserSettingsLive "without sudo mode" test
- Fixes grant_sudo_mode/1 DateTime truncation to seconds

All equipment module tests passing. Ready for Phase 3 (Admin Features).
2026-02-02 12:41:58 -06:00

97 lines
2.7 KiB
Elixir

defmodule ToweropsWeb.SiteLive.Show do
@moduledoc false
use ToweropsWeb, :live_view
alias Towerops.Devices
alias Towerops.Monitoring
alias Towerops.Sites
alias Towerops.Snmp
alias Towerops.Workers.DiscoveryWorker
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
organization = socket.assigns.current_scope.organization
site = Sites.get_organization_site!(organization.id, id)
device = Devices.list_site_devices(site.id)
latency_chart_data = load_site_latency_chart_data(device)
{:noreply,
socket
|> assign(:page_title, site.name)
|> assign(:site, site)
|> assign(:device, device)
|> assign(:latency_chart_data, latency_chart_data)}
end
@impl true
def handle_event("force_rediscover_all", _params, socket) do
devices = socket.assigns.device
snmp_devices = Enum.filter(devices, & &1.snmp_enabled)
if Enum.empty?(snmp_devices) do
{:noreply, put_flash(socket, :error, t_equipment("No SNMP-enabled devices at this site"))}
else
# Enqueue discovery for all SNMP-enabled devices
Enum.each(snmp_devices, fn device ->
enqueue_discovery(device.id)
end)
count = length(snmp_devices)
message = t_equipment("Discovery started for %{count} device", count: count) <> if count == 1, do: "", else: "s"
{:noreply, put_flash(socket, :info, message)}
end
end
defp load_site_latency_chart_data(devices) do
if Enum.empty?(devices) do
nil
else
twenty_four_hours_ago = DateTime.add(DateTime.utc_now(), -24, :hour)
datasets =
devices
|> Enum.map(fn device ->
checks =
device.id
|> Monitoring.get_latency_data(since: twenty_four_hours_ago, limit: 1000)
|> Enum.reverse()
%{
label: device.name,
data: Enum.map(checks, &latency_check_to_data_point/1)
}
end)
|> Enum.reject(fn dataset -> Enum.empty?(dataset.data) end)
if Enum.empty?(datasets) do
nil
else
Jason.encode!(%{datasets: datasets})
end
end
end
defp latency_check_to_data_point(check) do
%{
x: DateTime.to_unix(check.checked_at, :millisecond),
y: check.response_time_ms
}
end
# Enqueue discovery job - safe to call in test environment
defp enqueue_discovery(device_id) do
if Application.get_env(:towerops, :env) == :test do
# In test, run synchronously
_ = Task.start(fn -> Snmp.discover_device(Devices.get_device!(device_id)) end)
else
# In dev/prod, enqueue to Oban
DiscoveryWorker.enqueue(device_id)
end
end
end