diff --git a/lib/towerops_web/live/trace_live/index.ex b/lib/towerops_web/live/trace_live/index.ex index ec85b227..ca155dd9 100644 --- a/lib/towerops_web/live/trace_live/index.ex +++ b/lib/towerops_web/live/trace_live/index.ex @@ -10,6 +10,27 @@ defmodule ToweropsWeb.TraceLive.Index do alias Towerops.Trace + attr :label, :string, required: true + attr :value, :string, required: true + attr :quality, :atom, default: :unknown + + defp metric_card(assigns) do + color = case assigns.quality do + :good -> "border-green-200 dark:border-green-800" + :warning -> "border-yellow-200 dark:border-yellow-800" + :bad -> "border-red-200 dark:border-red-800" + _ -> "border-base-200" + end + assigns = assign(assigns, :color, color) + + ~H""" +
+
{@label}
+
{@value}
+
+ """ + end + @impl true def mount(_params, _session, socket) do {:ok, @@ -88,6 +109,88 @@ defmodule ToweropsWeb.TraceLive.Index do defp type_badge_class(:access_point), do: "badge-info" defp type_badge_class(_), do: "badge-ghost" + defp type_badge_label(:account), do: "Account" + defp type_badge_label(:inventory_item), do: "Inventory" + defp type_badge_label(:device), do: "Device" + defp type_badge_label(:access_point), do: "AP" + defp type_badge_label(_), do: "Unknown" + + defp status_badge_class("active"), do: "badge-success" + defp status_badge_class("suspended"), do: "badge-warning" + defp status_badge_class("cancelled"), do: "badge-error" + defp status_badge_class(_), do: "badge-ghost" + + defp device_status_color(:up), do: "text-green-600 dark:text-green-400" + defp device_status_color(:down), do: "text-red-600 dark:text-red-400" + defp device_status_color(_), do: "text-gray-500" + + defp format_speed(nil), do: "—" + defp format_speed(speed) when is_number(speed) and speed >= 1000, do: "#{Float.round(speed / 1000, 1)} Gbps" + defp format_speed(speed) when is_number(speed), do: "#{speed} Mbps" + defp format_speed(speed), do: "#{speed}" + + defp format_relative_time(nil), do: "—" + defp format_relative_time(dt) do + diff = DateTime.diff(DateTime.utc_now(), dt, :second) + cond do + diff < 60 -> "just now" + diff < 3600 -> "#{div(diff, 60)}m ago" + diff < 86400 -> "#{div(diff, 3600)}h ago" + true -> "#{div(diff, 86400)}d ago" + end + end + + defp format_score(nil), do: "—" + defp format_score(score) when is_number(score), do: "#{Float.round(score * 1.0, 1)}" + defp format_score(score), do: "#{score}" + + defp format_pct(nil), do: "—" + defp format_pct(val) when is_number(val), do: "#{Float.round(val * 1.0, 1)}%" + defp format_pct(val), do: "#{val}" + + defp format_ms(nil), do: "—" + defp format_ms(val) when is_number(val), do: "#{Float.round(val * 1.0, 1)} ms" + defp format_ms(val), do: "#{val}" + + defp format_throughput(nil), do: "—" + defp format_throughput(val) when is_number(val) and val >= 1000, do: "#{Float.round(val / 1000, 1)} Gbps" + defp format_throughput(val) when is_number(val), do: "#{Float.round(val * 1.0, 1)} Mbps" + defp format_throughput(val), do: "#{val}" + + defp format_alert_type(nil), do: "—" + defp format_alert_type(type) when is_binary(type), do: type |> String.replace("_", " ") |> String.capitalize() + defp format_alert_type(type), do: "#{type}" + + defp score_quality(nil), do: :unknown + defp score_quality(s) when s >= 80, do: :good + defp score_quality(s) when s >= 50, do: :warning + defp score_quality(_), do: :bad + + defp score_color(nil), do: "text-gray-400" + defp score_color(s) when s >= 80, do: "text-green-600 dark:text-green-400" + defp score_color(s) when s >= 50, do: "text-yellow-600 dark:text-yellow-400" + defp score_color(_), do: "text-red-600 dark:text-red-400" + + defp latency_color(nil), do: "text-gray-400" + defp latency_color(v) when v <= 30, do: "text-green-600 dark:text-green-400" + defp latency_color(v) when v <= 80, do: "text-yellow-600 dark:text-yellow-400" + defp latency_color(_), do: "text-red-600 dark:text-red-400" + + defp jitter_color(nil), do: "text-gray-400" + defp jitter_color(v) when v <= 10, do: "text-green-600 dark:text-green-400" + defp jitter_color(v) when v <= 30, do: "text-yellow-600 dark:text-yellow-400" + defp jitter_color(_), do: "text-red-600 dark:text-red-400" + + defp loss_color(nil), do: "text-gray-400" + defp loss_color(v) when v <= 1, do: "text-green-600 dark:text-green-400" + defp loss_color(v) when v <= 5, do: "text-yellow-600 dark:text-yellow-400" + defp loss_color(_), do: "text-red-600 dark:text-red-400" + + defp airtime_quality(nil), do: :unknown + defp airtime_quality(v) when v <= 50, do: :good + defp airtime_quality(v) when v <= 80, do: :warning + defp airtime_quality(_), do: :bad + defp safe_type("account"), do: :account defp safe_type("inventory_item"), do: :inventory_item defp safe_type("device"), do: :device