defmodule ServerWeb.AdminHostsLive do use ServerWeb, :live_view alias Server.{Hosts, Repo, Schema.Host} @impl true def mount(_params, _session, socket) do {:ok, socket |> assign( hosts: Hosts.list_all(), form: to_form(%{"name" => ""}, as: :host), new_token: nil, error: nil, page_title: "Admin" )} end @impl true def handle_event("create", %{"host" => %{"name" => name}}, socket) do case Hosts.create_host(name) do {:ok, {host, token}} -> {:noreply, socket |> assign( hosts: Hosts.list_all(), form: to_form(%{"name" => ""}, as: :host), new_token: %{name: host.name, token: token}, error: nil )} {:error, cs} -> {:noreply, assign(socket, :error, changeset_message(cs))} end end def handle_event("rotate", %{"id" => id}, socket) do %Host{} = host = Repo.get!(Host, id) {:ok, {_, token}} = Hosts.rotate_token(host) {:noreply, socket |> assign(hosts: Hosts.list_all(), new_token: %{name: host.name, token: token})} end def handle_event("delete", %{"id" => id}, socket) do %Host{} = host = Repo.get!(Host, id) {:ok, _} = Hosts.delete_host(host) {:noreply, assign(socket, :hosts, Hosts.list_all())} end defp changeset_message(cs) do cs.errors |> Enum.map_join(", ", fn {k, {msg, _}} -> "#{k}: #{msg}" end) end @impl true def render(assigns) do ~H"""

Admin · Hosts

{length(@hosts)} registered
Register a host
<.form for={@form} phx-submit="create" class="form-row">

{@error}

Token for {@new_token.name} — shown once:
{@new_token.token}
All hosts
Name Status Agent Last seen Actions
<.link navigate={~p"/hosts/#{h.name}"}>{h.name} {h.status} {h.agent_version || "—"} {format_seen(h.last_seen_at)}
No hosts yet.
""" end defp format_seen(nil), do: "never" defp format_seen(%DateTime{} = dt), do: Calendar.strftime(dt, "%Y-%m-%d %H:%M UTC") end