106 lines
2.9 KiB
Elixir
106 lines
2.9 KiB
Elixir
defmodule ToweropsWeb.NetworkMapLive do
|
|
@moduledoc false
|
|
use ToweropsWeb, :live_view
|
|
|
|
alias Towerops.Snmp
|
|
|
|
@impl true
|
|
def mount(_params, _session, socket) do
|
|
organization = socket.assigns.current_organization
|
|
|
|
# Subscribe to topology changes if connected
|
|
if connected?(socket) do
|
|
Phoenix.PubSub.subscribe(Towerops.PubSub, "topology:#{organization.id}")
|
|
end
|
|
|
|
# Default empty topology
|
|
default_topology = %{
|
|
nodes: [],
|
|
edges: [],
|
|
subnets: [],
|
|
stats: %{
|
|
total_devices: 0,
|
|
added_devices: 0,
|
|
discovered_devices: 0,
|
|
total_links: 0,
|
|
total_subnets: 0
|
|
},
|
|
last_updated: DateTime.utc_now()
|
|
}
|
|
|
|
{:ok,
|
|
socket
|
|
|> assign(:page_title, "Network Map")
|
|
|> assign(:loading, true)
|
|
|> assign(:topology, default_topology)
|
|
|> assign(:active_tab, "added")}
|
|
end
|
|
|
|
@impl true
|
|
def handle_params(params, _url, socket) do
|
|
tab = Map.get(params, "tab", "added")
|
|
organization = socket.assigns.current_organization
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(:active_tab, tab)
|
|
|> load_topology_data(organization.id, tab)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("refresh_topology", _params, socket) do
|
|
organization = socket.assigns.current_organization
|
|
|
|
{:noreply,
|
|
socket
|
|
|> assign(:loading, true)
|
|
|> load_topology_data(organization.id, socket.assigns.active_tab)
|
|
|> put_flash(:info, "Network map refreshed")}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("node_clicked", %{"node_id" => node_id}, socket) do
|
|
# Handle node click - could navigate to device detail page
|
|
{:noreply, assign(socket, :selected_node, node_id)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info({:topology_updated, _organization_id}, socket) do
|
|
# Real-time topology update
|
|
{:noreply, load_topology_data(socket, socket.assigns.current_organization.id, socket.assigns.active_tab)}
|
|
end
|
|
|
|
defp load_topology_data(socket, organization_id, tab) do
|
|
topology = Snmp.get_network_topology(organization_id)
|
|
|
|
# Filter topology based on active tab
|
|
filtered_topology =
|
|
case tab do
|
|
"all" ->
|
|
topology
|
|
|
|
_ ->
|
|
# "added" tab - show only added devices
|
|
%{
|
|
topology
|
|
| nodes: Enum.filter(topology.nodes, &(!&1.discovered)),
|
|
edges: filter_edges_for_nodes(topology.edges, topology.nodes, &(!&1.discovered))
|
|
}
|
|
end
|
|
|
|
socket
|
|
|> assign(:topology, filtered_topology)
|
|
|> assign(:loading, false)
|
|
|> push_event("update_topology", %{topology: filtered_topology})
|
|
end
|
|
|
|
# Filter edges to only include those where both source and target are in the filtered nodes
|
|
defp filter_edges_for_nodes(edges, all_nodes, filter_fn) do
|
|
filtered_node_ids = all_nodes |> Enum.filter(filter_fn) |> MapSet.new(& &1.id)
|
|
|
|
Enum.filter(edges, fn edge ->
|
|
MapSet.member?(filtered_node_ids, edge.source) and
|
|
MapSet.member?(filtered_node_ids, edge.target)
|
|
end)
|
|
end
|
|
end
|