towerops/lib/towerops_web/live/admin/agent_live/index.html.heex
Graham McIntire c6caa81850
Group cloud pollers and org agents separately on admin agents page
Cloud pollers render in their own table at the top, org agents
below with the organization name shown under each agent name.
2026-02-10 11:07:41 -06:00

155 lines
6.4 KiB
Text

<Layouts.admin flash={@flash} timezone={@timezone}>
<div class="space-y-6">
<div>
<h1 class="text-2xl font-bold text-gray-900 dark:text-white">All Agents</h1>
<p class="text-gray-600 dark:text-gray-400">
Agents across all organizations and cloud pollers
</p>
</div>
<%!-- Cloud Pollers --%>
<%= if @has_cloud_pollers do %>
<div>
<h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3">
<.icon name="hero-cloud" class="w-5 h-5 inline mr-1" /> Cloud Pollers
</h2>
<.table id="cloud-pollers-table" rows={@streams.cloud_pollers}>
<:col :let={{_id, agent}} label="Name">
<div class="flex items-center gap-2">
<.link
navigate={~p"/agents/#{agent.id}"}
class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
{agent.name}
</.link>
<%= if agent.allow_remote_debug do %>
<span class="inline-flex items-center gap-1 rounded-full bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-300 ring-1 ring-inset ring-amber-600/20 dark:ring-amber-400/30">
<.icon name="hero-bug-ant" class="h-3 w-3" /> Debug
</span>
<% end %>
</div>
</:col>
<:col :let={{_id, agent}} label="Status">
<% {status, label} = agent_status(agent) %>
<span class={"inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium #{status_badge_class(status)}"}>
<span class={"h-1.5 w-1.5 rounded-full #{status_dot_class(status)}"} />
{label}
</span>
</:col>
<:col :let={{_id, agent}} label="Devices">
<% counts = Map.get(@device_counts, agent.id, %{direct: 0, total: 0}) %>
<div class="text-sm text-gray-900 dark:text-white">
{counts.total} total
</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
{counts.direct} direct
<%= if counts.total > counts.direct do %>
· {counts.total - counts.direct} inherited
<% end %>
</div>
</:col>
<:col :let={{_id, agent}} label="Last Seen">
<div class="text-sm text-gray-900 dark:text-white">
<.timestamp datetime={agent.last_seen_at} timezone={@timezone} now={@now} />
</div>
<%= if agent.last_seen_at do %>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
<.timestamp
datetime={agent.last_seen_at}
timezone={@timezone}
format="absolute"
/>
</div>
<% end %>
</:col>
<:col :let={{_id, agent}} label="Version">
<%= if agent.metadata["version"] do %>
<div class="text-sm text-gray-600 dark:text-gray-400 font-mono">
{format_agent_version(agent.metadata["version"])}
</div>
<% end %>
</:col>
</.table>
</div>
<% end %>
<%!-- Organization Agents --%>
<%= if @has_org_agents do %>
<div>
<h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3">
<.icon name="hero-server" class="w-5 h-5 inline mr-1" /> Organization Agents
</h2>
<.table id="org-agents-table" rows={@streams.org_agents}>
<:col :let={{_id, agent}} label="Name">
<div>
<div class="flex items-center gap-2">
<.link
navigate={~p"/agents/#{agent.id}"}
class="font-medium text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
{agent.name}
</.link>
<%= if agent.allow_remote_debug do %>
<span class="inline-flex items-center gap-1 rounded-full bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 text-xs font-medium text-amber-700 dark:text-amber-300 ring-1 ring-inset ring-amber-600/20 dark:ring-amber-400/30">
<.icon name="hero-bug-ant" class="h-3 w-3" /> Debug
</span>
<% end %>
</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
{agent.organization && agent.organization.name}
</div>
</div>
</:col>
<:col :let={{_id, agent}} label="Status">
<% {status, label} = agent_status(agent) %>
<span class={"inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium #{status_badge_class(status)}"}>
<span class={"h-1.5 w-1.5 rounded-full #{status_dot_class(status)}"} />
{label}
</span>
</:col>
<:col :let={{_id, agent}} label="Devices">
<% counts = Map.get(@device_counts, agent.id, %{direct: 0, total: 0}) %>
<div class="text-sm text-gray-900 dark:text-white">
{counts.total} total
</div>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
{counts.direct} direct
<%= if counts.total > counts.direct do %>
· {counts.total - counts.direct} inherited
<% end %>
</div>
</:col>
<:col :let={{_id, agent}} label="Last Seen">
<div class="text-sm text-gray-900 dark:text-white">
<.timestamp datetime={agent.last_seen_at} timezone={@timezone} now={@now} />
</div>
<%= if agent.last_seen_at do %>
<div class="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
<.timestamp
datetime={agent.last_seen_at}
timezone={@timezone}
format="absolute"
/>
</div>
<% end %>
</:col>
<:col :let={{_id, agent}} label="Version">
<%= if agent.metadata["version"] do %>
<div class="text-sm text-gray-600 dark:text-gray-400 font-mono">
{format_agent_version(agent.metadata["version"])}
</div>
<% end %>
</:col>
</.table>
</div>
<% end %>
</div>
</Layouts.admin>