From a30d6b821923ac16881853183ad7428a70d95f5b Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sun, 25 Jan 2026 13:59:09 -0600 Subject: [PATCH] unit fixes --- lib/towerops_web/live/graph_live/show.ex | 67 +++++++++++++++++++ .../live/graph_live/show.html.heex | 16 +++++ 2 files changed, 83 insertions(+) diff --git a/lib/towerops_web/live/graph_live/show.ex b/lib/towerops_web/live/graph_live/show.ex index 2aa49f42..3e7a7b57 100644 --- a/lib/towerops_web/live/graph_live/show.ex +++ b/lib/towerops_web/live/graph_live/show.ex @@ -84,6 +84,9 @@ defmodule ToweropsWeb.GraphLive.Show do chart_title = if title_suffix, do: "#{title} - #{title_suffix}", else: title show_zero_line = sensor_type == "traffic" + # Calculate max/min values from chart data + {max_value, min_value} = calculate_chart_stats(chart_data) + socket |> assign(:device, device) |> assign(:page_title, "#{device.name} - #{chart_title}") @@ -92,6 +95,8 @@ defmodule ToweropsWeb.GraphLive.Show do |> assign(:unit, unit) |> assign(:auto_scale, auto_scale) |> assign(:show_zero_line, show_zero_line) + |> assign(:max_value, max_value) + |> assign(:min_value, min_value) end defp load_chart_data_for_type(%{sensor_type: "latency", device_id: device_id}, range) do @@ -320,6 +325,39 @@ defmodule ToweropsWeb.GraphLive.Show do } end + # Calculate max and min values from chart data + defp calculate_chart_stats(nil), do: {nil, nil} + + defp calculate_chart_stats(chart_data) when is_binary(chart_data) do + case Jason.decode(chart_data) do + {:ok, %{"datasets" => datasets}} -> + extract_min_max_from_datasets(datasets) + + _ -> + {nil, nil} + end + end + + defp calculate_chart_stats(_), do: {nil, nil} + + defp extract_min_max_from_datasets(datasets) do + values = Enum.flat_map(datasets, &extract_values_from_dataset/1) + + case values do + [] -> {nil, nil} + _ -> {Enum.max(values), Enum.min(values)} + end + end + + defp extract_values_from_dataset(%{"data" => data}) when is_list(data) do + Enum.flat_map(data, &extract_y_value/1) + end + + defp extract_values_from_dataset(_), do: [] + + defp extract_y_value(%{"y" => y}) when is_number(y), do: [y] + defp extract_y_value(_), do: [] + defp build_traffic_chart_json(device, range) do if Enum.empty?(device.interfaces), do: nil, else: build_traffic_datasets(device, range) end @@ -420,4 +458,33 @@ defmodule ToweropsWeb.GraphLive.Show do } end) end + + # Format value with unit for display + defp format_value(value, "bps") do + abs_value = abs(value) + + cond do + abs_value >= 1_000_000_000 -> + "#{Float.round(abs_value / 1_000_000_000, 2)} Gbps" + + abs_value >= 1_000_000 -> + "#{Float.round(abs_value / 1_000_000, 2)} Mbps" + + abs_value >= 1_000 -> + "#{Float.round(abs_value / 1_000, 2)} Kbps" + + true -> + "#{Float.round(abs_value, 2)} bps" + end + end + + # For counts (empty unit), format as integer + defp format_value(value, "") do + "#{round(value)}" + end + + # For other units, format with one decimal place + defp format_value(value, unit) do + "#{Float.round(value, 1)}#{unit}" + end end diff --git a/lib/towerops_web/live/graph_live/show.html.heex b/lib/towerops_web/live/graph_live/show.html.heex index cf65a8d4..65b9245f 100644 --- a/lib/towerops_web/live/graph_live/show.html.heex +++ b/lib/towerops_web/live/graph_live/show.html.heex @@ -59,6 +59,22 @@ > + <%= if @max_value && @min_value do %> +
+
+ Max: + + {format_value(@max_value, @unit)} + +
+
+ Min: + + {format_value(@min_value, @unit)} + +
+
+ <% end %> <% else %>