defmodule Phoenix.LiveDashboard.PortInfoComponent do
use Phoenix.LiveDashboard.Web, :live_component
alias Phoenix.LiveDashboard.SystemInfo
@info_keys [
:name,
:links,
:id,
:connected,
:input,
:output,
:os_pid
]
@impl true
def render(assigns) do
~H"""
<%= if @alive do %>
<:elem label="Port Name"><%= @name %>
<:elem label="Id"><%= @id %>
<:elem label="Connected"><%= @connected %>
<:elem label="Input"><%= format_bytes(@input) %>
<:elem label="Output"><%= format_bytes(@output) %>
<:elem label="OS pid"><%= @os_pid %>
<:elem label="Links"><.info links={@links} />
<% else %>
Port was closed or does not exist.
<% end %>
"""
end
@impl true
def mount(socket) do
{:ok, Enum.reduce(@info_keys, socket, &assign(&2, &1, nil))}
end
@impl true
def update(%{id: "Port" <> _ = port, path: path}, socket) do
port = :erlang.list_to_port(String.to_charlist("#" <> port))
{:ok, socket |> assign(port: port, path: path) |> assign_info()}
end
defp assign_info(%{assigns: assigns} = socket) do
case SystemInfo.fetch_port_info(assigns.port) do
{:ok, info} ->
Enum.reduce(info, socket, fn {key, val}, acc ->
assign(acc, key, format_info(key, val, assigns.path))
end)
|> assign(alive: true)
:error ->
assign(socket, alive: false)
end
end
defp format_info(key, val, live_dashboard_path)
when key in [:links],
do: format_value(val, live_dashboard_path)
defp format_info(key, val, _live_dashboard_path)
when key in [:name, :id, :input, :output, :os_pid],
do: val
defp format_info(_key, val, live_dashboard_path), do: format_value(val, live_dashboard_path)
defp info(%{links: links} = assigns) when is_list(links) do
~H"""
<%= for info <- @links do %>
<%= info %>
<% end %>
"""
end
defp info(%{links: _links} = assigns), do: ~H|<%= @links %>|
end