towerops/lib/towerops_web/live/status_page_live.ex
Graham McIntire 91e3181bbc dialyzer: fix all unmatched_return warnings (154 → 0)
Prefix fire-and-forget calls (PubSub.broadcast, Oban enqueue, Logger,
update_*, etc.) with `_ =` so dialyzer knows the return value is
intentionally discarded. Wrap a few if/case expressions whose
branches produce mixed types the same way.

No behavior changes — only explicit acknowledgement of discarded
returns.

Warnings: 242 → 88.
2026-04-21 10:03:55 -05:00

101 lines
3.6 KiB
Elixir

defmodule ToweropsWeb.StatusPageLive do
@moduledoc """
Public unauthenticated status page.
Renders at /status/:slug with a standalone layout (no sidebar).
Mobile-responsive for customers checking during outages.
"""
use ToweropsWeb, :live_view
alias Towerops.StatusPages
@impl true
def mount(%{"slug" => slug}, _session, socket) do
case StatusPages.get_config_by_slug(slug) do
nil ->
{:ok,
socket
|> put_flash(:error, "Status page not found")
|> assign(:not_found, true)
|> assign(:page_title, "Not Found")}
config ->
_ =
if connected?(socket) do
_ = Phoenix.PubSub.subscribe(Towerops.PubSub, "status_page:#{config.id}")
end
components = StatusPages.list_components(config.id)
active_incidents = StatusPages.list_active_incidents(config.id)
recent_incidents = StatusPages.list_incidents(config.id, limit: 10)
overall = StatusPages.overall_status(components)
{:ok,
socket
|> assign(:config, config)
|> assign(:components, components)
|> assign(:active_incidents, active_incidents)
|> assign(:recent_incidents, recent_incidents)
|> assign(:overall_status, overall)
|> assign(:not_found, false)
|> assign(:page_title, "#{config.company_name || "Status"} — System Status"), layout: false}
end
end
@impl true
def handle_info({:status_updated, _}, socket) do
config = socket.assigns.config
components = StatusPages.list_components(config.id)
active_incidents = StatusPages.list_active_incidents(config.id)
overall = StatusPages.overall_status(components)
{:noreply,
assign(socket,
components: components,
active_incidents: active_incidents,
overall_status: overall
)}
end
def handle_info(_, socket), do: {:noreply, socket}
# -- Helpers --
defp overall_color(:operational), do: "bg-green-500"
defp overall_color(:degraded), do: "bg-yellow-500"
defp overall_color(:partial_outage), do: "bg-orange-500"
defp overall_color(:major_outage), do: "bg-red-500"
defp overall_color(:maintenance), do: "bg-blue-500"
defp overall_color(_), do: "bg-gray-500"
defp overall_text(:operational), do: "All Systems Operational"
defp overall_text(:degraded), do: "Degraded Performance"
defp overall_text(:partial_outage), do: "Partial System Outage"
defp overall_text(:major_outage), do: "Major System Outage"
defp overall_text(:maintenance), do: "Scheduled Maintenance"
defp overall_text(_), do: "Unknown"
defp component_color("operational"), do: "bg-green-500"
defp component_color("degraded"), do: "bg-yellow-500"
defp component_color("partial_outage"), do: "bg-orange-500"
defp component_color("major_outage"), do: "bg-red-500"
defp component_color("maintenance"), do: "bg-blue-500"
defp component_color(_), do: "bg-gray-400"
defp component_label("operational"), do: "Operational"
defp component_label("degraded"), do: "Degraded"
defp component_label("partial_outage"), do: "Partial Outage"
defp component_label("major_outage"), do: "Major Outage"
defp component_label("maintenance"), do: "Maintenance"
defp component_label(s), do: s
defp severity_color("critical"), do: "text-red-600"
defp severity_color("major"), do: "text-orange-600"
defp severity_color(_), do: "text-yellow-600"
defp incident_status_label("investigating"), do: "Investigating"
defp incident_status_label("identified"), do: "Identified"
defp incident_status_label("monitoring"), do: "Monitoring"
defp incident_status_label("resolved"), do: "Resolved"
defp incident_status_label(s), do: s
end