defmodule ToweropsWeb.SiteLive.Index do @moduledoc false use ToweropsWeb, :live_view alias Towerops.Dashboard alias Towerops.Preseem.Insights alias Towerops.Sites @impl true def mount(_params, _session, socket) do organization = socket.assigns.current_scope.organization sites = Sites.list_organization_sites(organization.id) site_summaries = Dashboard.get_site_impact_summaries(organization.id) insights = Insights.list_insights(organization.id, status: "active", limit: 10) # Index site summaries by site_id for easy lookup summary_map = Map.new(site_summaries, &{&1.site_id, &1}) {:ok, socket |> assign(:page_title, t("Sites")) |> assign(:sites, sites) |> assign(:summary_map, summary_map) |> assign(:insights, insights) |> assign(:timezone, socket.assigns.current_scope.timezone)} end @impl true def handle_params(params, _url, socket) do {:noreply, apply_action(socket, socket.assigns.live_action, params)} end @impl true def handle_event("dismiss_insight", %{"id" => insight_id}, socket) do case Towerops.Preseem.dismiss_insight(insight_id) do {:ok, _} -> org_id = socket.assigns.current_scope.organization.id insights = Insights.list_insights(org_id, status: "active", limit: 10) {:noreply, socket |> assign(:insights, insights) |> put_flash(:info, t("Insight dismissed"))} {:error, _} -> {:noreply, put_flash(socket, :error, t("Failed to dismiss insight"))} end end defp apply_action(socket, :index, _params) do assign(socket, :page_title, t("Sites")) end @doc false def format_qoe(nil), do: "—" def format_qoe(score), do: :erlang.float_to_binary(score / 1, decimals: 1) @doc false def qoe_color(nil), do: "text-gray-400 dark:text-gray-500" def qoe_color(score) when score < 2.0, do: "text-red-600 dark:text-red-400" def qoe_color(score) when score < 4.0, do: "text-yellow-600 dark:text-yellow-400" def qoe_color(_), do: "text-green-600 dark:text-green-400" @doc false def health_dot(nil), do: "bg-gray-400" def health_dot(:red), do: "bg-red-500" def health_dot(:yellow), do: "bg-yellow-500" def health_dot(_), do: "bg-green-500" @doc false def urgency_classes("critical"), do: "bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400" def urgency_classes("warning"), do: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400" def urgency_classes("info"), do: "bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400" def urgency_classes(_), do: "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400" @doc false def source_classes("preseem"), do: "bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400" def source_classes("snmp"), do: "bg-cyan-100 text-cyan-800 dark:bg-cyan-900/30 dark:text-cyan-400" def source_classes("gaiia"), do: "bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400" def source_classes(_), do: "bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400" end