import { Label as MuLabel, StatusBadge } from "@unlocalhosted/metalui";
import { ConfirmButton } from "@/components/confirm-button";
import { ServerIcon } from "@/components/icons";
import { SettingsSection } from "@/components/metal";
import { ListRow, PlateSection, RowGlyph } from "@/components/settings-plate";
import { Blankslate, RefChip } from "@/components/ui";
import { timeAgo } from "@/lib/format";
import { RUNNER_TOKEN_PREFIX, type Runner } from "@/lib/runners";
/** Registered runners: online, busy or offline, with their labels and machine, each removable. */
export function RunnerList({ runners, deleteAction }: { runners: Runner[]; deleteAction: (runnerId: string) => Promise<void> }) {
if (runners.length === 0) {
return (
<PlateSection title="Runners">
<Blankslate icon={<ServerIcon />} title="No runners yet">
Register a runner below, then start it on the machine that should run your jobs.
</Blankslate>
</PlateSection>
);
}
return (
<SettingsSection title={`Runners · ${runners.length}`}>
{runners.map((r) => (
<ListRow
key={r.id}
lead={
<RowGlyph>
<ServerIcon />
</RowGlyph>
}
title={
<>
<span className="truncate">{r.name}</span>
{r.busy ? (
<StatusBadge led="waiting">Busy</StatusBadge>
) : r.online ? (
<StatusBadge led="live">Idle</StatusBadge>
) : (
<StatusBadge led="off">Offline</StatusBadge>
)}
<RefChip>
{RUNNER_TOKEN_PREFIX}…{r.hint}
</RefChip>
</>
}
meta={
<>
<span className="flex flex-wrap gap-1">
{[...r.systemLabels, ...r.labels].map((l) => (
<RefChip key={l} className="text-ink2">
{l}
</RefChip>
))}
</span>
<MuLabel variant="engraved">
{r.busy ? (
<>
Running <b>{r.busy.jobName}</b> in <b>{r.busy.repo}</b> #{r.busy.runNumber}
</>
) : r.lastSeenAt ? (
<>
{r.hostname && (
<>
<b>{r.hostname}</b> ·{" "}
</>
)}
Last seen <b>{timeAgo(r.lastSeenAt)}</b>
{r.version && <> · v{r.version}</>}
</>
) : (
"Never connected"
)}
</MuLabel>
</>
}
>
<ConfirmButton
action={deleteAction.bind(null, r.id)}
message={`Remove the runner “${r.name}”? It stops picking up jobs, and its token stops working.`}
variant="default"
>
Remove
</ConfirmButton>
</ListRow>
))}
</SettingsSection>
);
}