diff --git a/lib/towerops/trace.ex b/lib/towerops/trace.ex index df140eea..a6543270 100644 --- a/lib/towerops/trace.ex +++ b/lib/towerops/trace.ex @@ -19,6 +19,7 @@ defmodule Towerops.Trace do alias Towerops.Preseem.Insight alias Towerops.Preseem.SubscriberMetric alias Towerops.Repo + alias Towerops.Sites.Site # --------------------------------------------------------------------------- # Search @@ -38,10 +39,11 @@ defmodule Towerops.Trace do accounts = search_accounts(organization_id, pattern) inventory = search_inventory(organization_id, pattern) + sites = search_sites(organization_id, pattern) devices = search_devices(organization_id, pattern) access_points = search_access_points(organization_id, pattern) - Enum.take(accounts ++ inventory ++ devices ++ access_points, 25) + Enum.take(accounts ++ inventory ++ sites ++ devices ++ access_points, 25) end end @@ -77,6 +79,19 @@ defmodule Towerops.Trace do end) end + defp search_sites(organization_id, pattern) do + Site + |> where(organization_id: ^organization_id) + |> where([s], ilike(s.name, ^pattern) or ilike(s.location, ^pattern) or ilike(s.address, ^pattern)) + |> limit(10) + |> Repo.all() + |> Enum.map(fn s -> + sublabel = Enum.join(Enum.reject([s.location, s.address], &is_nil/1), " ยท ") + + %{type: :site, id: s.id, label: s.name, sublabel: sublabel, data: s} + end) + end + defp search_devices(organization_id, pattern) do Device |> where(organization_id: ^organization_id) @@ -119,6 +134,7 @@ defmodule Towerops.Trace do case type do :account -> trace_from_account(organization_id, id) :inventory_item -> trace_from_inventory(organization_id, id) + :site -> trace_from_site(organization_id, id) :device -> trace_from_device(organization_id, id) :access_point -> trace_from_access_point(organization_id, id) _ -> nil @@ -166,6 +182,31 @@ defmodule Towerops.Trace do :not_found -> nil end + defp trace_from_site(organization_id, site_id) do + site = + Site + |> where(id: ^site_id, organization_id: ^organization_id) + |> Repo.one() + + if !site, do: throw(:not_found) + + devices = + Device + |> where(organization_id: ^organization_id, site_id: ^site_id) + |> preload(:site) + |> Repo.all() + + alerts = load_site_alerts(devices) + + %{ + site: site, + devices: devices, + alerts: alerts + } + catch + :not_found -> nil + end + defp trace_from_device(organization_id, device_id) do device = Device @@ -313,6 +354,19 @@ defmodule Towerops.Trace do } end + defp load_site_alerts([]), do: [] + + defp load_site_alerts(devices) do + device_ids = Enum.map(devices, & &1.id) + + Alert + |> where([a], a.device_id in ^device_ids) + |> order_by(desc: :triggered_at) + |> limit(10) + |> preload([:device, :acknowledged_by]) + |> Repo.all() + end + defp load_device_alerts(nil), do: [] defp load_device_alerts(device_id) do diff --git a/lib/towerops_web/live/trace_live/index.ex b/lib/towerops_web/live/trace_live/index.ex index 255670a3..599f4aed 100644 --- a/lib/towerops_web/live/trace_live/index.ex +++ b/lib/towerops_web/live/trace_live/index.ex @@ -140,12 +140,14 @@ defmodule ToweropsWeb.TraceLive.Index do defp type_badge_class(:account), do: "badge-primary" defp type_badge_class(:inventory_item), do: "badge-secondary" + defp type_badge_class(:site), do: "badge-warning" defp type_badge_class(:device), do: "badge-accent" 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(:site), do: "Site" defp type_badge_label(:device), do: "Device" defp type_badge_label(:access_point), do: "AP" defp type_badge_label(_), do: "Unknown" @@ -244,6 +246,7 @@ defmodule ToweropsWeb.TraceLive.Index do defp safe_type("account"), do: :account defp safe_type("inventory_item"), do: :inventory_item + defp safe_type("site"), do: :site defp safe_type("device"), do: :device defp safe_type("access_point"), do: :access_point defp safe_type(_), do: :account diff --git a/lib/towerops_web/live/trace_live/index.html.heex b/lib/towerops_web/live/trace_live/index.html.heex index 3e148b06..3076a739 100644 --- a/lib/towerops_web/live/trace_live/index.html.heex +++ b/lib/towerops_web/live/trace_live/index.html.heex @@ -5,7 +5,11 @@ > <.breadcrumb items={ [%{label: "Dashboard", navigate: ~p"/dashboard"}, %{label: "Trace"}] ++ - if(@trace && @trace.subscriber, do: [%{label: @trace.subscriber.name}], else: []) + cond do + @trace && @trace[:subscriber] -> [%{label: @trace.subscriber.name}] + @trace && @trace[:site] -> [%{label: @trace.site.name}] + true -> [] + end } />
No results found
- {t("Try searching by customer name, IP address, account ID, or device name")} + {t("Try searching by customer name, IP address, account ID, site name, or device name")}
+ Location: + {@trace.site.location} +
++ Address: + {@trace.site.address} +
++ Devices: + {length(@trace.devices)} +
+| {t("Name")} | +{t("IP Address")} | +{t("Status")} | +
|---|---|---|
| + <.link + navigate={~p"/devices/#{device.id}"} + class="font-medium text-blue-600 dark:text-blue-400 hover:underline" + > + {device.name || device.ip_address} + + | +{device.ip_address} | ++ + + + + {device.status || "unknown"} + + + | +
+ {alert.message} +
+ + {format_relative_time(alert.triggered_at)} + +{t( - "Search for a customer by name, IP address, account ID, or device name to see their full network status at a glance." + "Search for a customer by name, IP address, account ID, site name, or device name to see their full network status at a glance." )}