<.header> {@page_title} <:subtitle>Monitor and manage all your network devices
<% percent = if @device_quota.limit != :unlimited and @device_quota.limit > 0 do (@device_quota.current / @device_quota.limit * 100) |> trunc() else 0 end %> <% badge_class = cond do @current_scope.user.is_superuser -> "bg-blue-50 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400" @device_quota.limit != :unlimited and @device_quota.current >= @device_quota.limit -> "bg-red-50 text-red-800 border-red-200 dark:bg-red-900/20 dark:text-red-400 dark:border-red-800" percent >= 90 -> "bg-orange-50 text-orange-800 border-orange-200 dark:bg-orange-900/20 dark:text-orange-400 dark:border-orange-800" percent >= 75 -> "bg-yellow-50 text-yellow-800 border-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-400 dark:border-yellow-800" @device_quota.limit == :unlimited -> "bg-blue-50 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400" true -> "bg-green-50 text-green-800 border-green-200 dark:bg-green-900/20 dark:text-green-400 dark:border-green-800" end %>
<%= cond do %> <% @current_scope.user.is_superuser -> %> {@device_quota.current} devices <% @device_quota.limit == :unlimited -> %> {@device_quota.current} devices <% true -> %> {@device_quota.current}/{@device_quota.limit} devices <% end %>
<%= if @has_devices do %> <%= if @reorder_mode do %> <.button type="button" phx-click="reset_order" data-confirm="Reset all sites and devices to alphabetical order?" > <.icon name="hero-arrow-path" class="h-4 w-4" /> Reset Order <.button type="button" phx-click="toggle_reorder_mode" variant="primary" > <.icon name="hero-check" class="h-4 w-4" /> Done <% else %> <.button type="button" phx-click="toggle_reorder_mode" > <.icon name="hero-bars-3" class="h-4 w-4" /> Reorder <% end %> <% end %> <.button :if={!@sites_enabled || @has_sites} navigate={~p"/devices/new"} variant="primary" > <.icon name="hero-plus" class="h-5 w-5" /> New Device <%= if @has_devices and not @reorder_mode do %> <.button type="button" phx-click="force_rediscover_all" data-confirm="This will trigger SNMP discovery for all SNMP-enabled devices. Continue?" > <.icon name="hero-magnifying-glass" class="h-4 w-4" /> Force Rediscover All <% end %>
<%= case @active_tab do %> <% "existing" -> %> <%= if @sites_enabled && !@has_sites && @has_devices do %>
<.icon name="hero-information-circle" class="h-5 w-5 text-blue-400" />

Organize your devices with sites

Sites help you organize devices by physical location. Create a site to assign your devices and keep things organized.

<.button navigate={~p"/sites/new"}> <.icon name="hero-plus" class="h-4 w-4" /> Create Your First Site
<% end %> <%= if !@has_devices do %>
<.icon name="hero-server" class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" />

No devices

Get started by adding your first device.

<.button navigate={~p"/devices/new"} variant="primary"> <.icon name="hero-plus" class="h-5 w-5" /> New Device
<% else %>
<%= for {dom_id, row} <- @streams.device_rows do %> <%= if row.type == :site_header do %> <% else %> <% end %> <% end %>
Drag handle Name IP Address Status Last Seen Response Subscribers
<%= if row.site do %> <.link navigate={~p"/sites/#{row.site.id}"} class="text-sm font-semibold text-gray-900 dark:text-white hover:text-blue-600 dark:hover:text-blue-400" > {row.site.name} <% else %> {if @sites_enabled, do: "Unassigned Devices", else: "All Devices"} <% end %> ยท {row.stats.total} {if row.stats.total == 1, do: "device", else: "devices"} 0} class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" > {row.stats.up} up 0} class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200" > {row.stats.down} down <%= if row.site && @site_subscribers[row.site.id] do %> <.icon name="hero-users" class="h-3 w-3" /> {@site_subscribers[row.site.id].account_count} subscribers <% end %>

<.icon name="hero-map-pin" class="inline h-3 w-3" /> {row.site.location}

<.link navigate={~p"/devices/#{row.device.id}"} class={[ "flex items-center gap-2 py-4 pr-3 text-inherit no-underline", @reorder_mode && "pl-2", !@reorder_mode && "pl-4 sm:pl-3" ]} > {row.device.name} <.link navigate={~p"/devices/#{row.device.id}"} class="block px-3 py-4 text-inherit no-underline" > {row.device.ip_address} <.link navigate={~p"/devices/#{row.device.id}"} class="block px-3 py-4 text-inherit no-underline" > {row.device.status |> to_string() |> String.upcase()} <.link navigate={~p"/devices/#{row.device.id}"} class="block px-3 py-4 text-inherit no-underline" > <% {text, color} = last_seen_text(row.device.last_seen_at) %> {text} <.link navigate={~p"/devices/#{row.device.id}"} class="block px-3 py-4 text-inherit no-underline" > <% {rt_text, rt_color} = response_time_badge(row.response) %> {rt_text} <.link navigate={~p"/devices/#{row.device.id}"} class="block px-3 py-4 text-inherit no-underline" > <%= if sub_text = format_subscriber_count(row.subscribers) do %> <.icon name="hero-users" class="h-3 w-3" /> {sub_text} <% else %> - <% end %>
<% end %> <% "discovered" -> %> <%= if @discovered_devices == [] do %>
<.icon name="hero-magnifying-glass" class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500" />

No discovered devices

Devices will appear here as they are discovered via LLDP/CDP.

<% else %>
Showing {(@pagination.page - 1) * @pagination.per_page + 1}-{min( @pagination.page * @pagination.per_page, @pagination.total_count )} of {@pagination.total_count} discovered devices
<.table id="discovered-devices" rows={@discovered_devices} > <:col :let={discovered} label="Identifier"> <%= case discovered.identifier.type do %> <% :mac -> %>
MAC {discovered.identifier.value}
<% :ip -> %>
IP {discovered.identifier.value}
<% :hostname -> %>
HOST {discovered.identifier.value}
<% _ -> %> Unknown <% end %> <:col :let={discovered} label="Hostname"> <%= if discovered.hostname do %> {discovered.hostname} <% else %> - <% end %> <:col :let={discovered} label="Type">
<.icon name={device_type_icon(discovered.device_type)} class="h-4 w-4 text-gray-500" /> {device_type_label(discovered.device_type)}
<:col :let={discovered} label="Manufacturer"> <%= if discovered.manufacturer do %> {discovered.manufacturer} <% else %> - <% end %> <:col :let={discovered} label="Discovered By">
<%= if length(discovered.discovered_by) == 1 do %> <% [first] = discovered.discovered_by %> <.link navigate={~p"/devices/#{first.device_id}"} class="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300" > {first.device_name} ({first.interface}) <% else %> {length(discovered.discovered_by)} devices <% end %>
<:col :let={discovered} label="Last Seen"> <.timestamp datetime={discovered.last_seen} class="text-sm text-gray-600 dark:text-gray-400" /> <:col :let={discovered} label="Actions"> <.button phx-click="add_discovered_device" phx-value-identifier={Jason.encode!(discovered.identifier)} variant="primary" > <.icon name="hero-plus" class="h-3 w-3" /> Add Device <%= if @pagination.total_pages > 1 do %>
<.link :if={@pagination.page > 1} patch={~p"/devices?tab=discovered&page=#{@pagination.page - 1}"} class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-white/10 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700" > Previous <.link :if={@pagination.page < @pagination.total_pages} patch={~p"/devices?tab=discovered&page=#{@pagination.page + 1}"} class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-white/10 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700" > Next
<% end %> <% end %> <% end %>