Endpoints table improvements / sort

This commit is contained in:
lda
2026-05-28 14:55:25 +07:00 Verified
parent 59fc4ffdc1
commit cf515527af
2 changed files with 28 additions and 72 deletions
-57
View File
@@ -1,57 +0,0 @@
# lda rambling
currently the collection of fleetwakeroutes doesnt make much sense.
it goes deep. Read code, then this again.
## big fleet shows everything.
all the IPs, offline or not. I at least want to hide the offline/unknown IPs into a drawer somewhere. its too cluttered.
i do need offline IPs, because, a failed / dhcp-rotated IP may be of use. but what use? copying only. You cant even send shit to it, its FAILED.
so not all the IPs should be immediately invisible.
## big fleet DOESNT show everything
yea showing all the offline IP but only ONE online ip per mac for wake routes.
BRING This BACK. i need ALL the routes. Color coded (already has that with disabled wake button)
## big collect collects everything
at wakey, collection makes no sense; a device saves all IPs without saying which of them is not real.
oh you do have to search again for the observations because they are unknown ahh hints,
## logics are misleading
also IPs without macs are unknown, (should be OFFLINE? ips without macs? what do you think it is)
while macs without ips are offline (pulled straight from the Big Mac Name cache)
what is this ahh logic
## struct names are misleading
Big Device over here, collected (fresh AND old) From the router ITSELF. Is BY MAC.
but the Device struct was designed to take multiple MACs, Why. This is very misleading.
The migration was from Observations, which is a string fest, to Device, which
1. give up the very cool observations based design, which fundamentally is just tracking identifing pairs of (ip, mac, maybe hostname)
2. doesnt solve the confusing ahh mac-keyed Devices. Why is the deviceid optional? What!
## big code needs a rewrite
i think we need to have a very clear model. And such model is ALREADY PRESENT! fleet wake route MIGHT be the coolest thing ever, solves everything.
Should type instead of free string construction. For example. alot of the keys are currently freehanded. You need a struct with Display or ToString or a dedicated method.
hopefully those keys can have a helper contructor. HOPEFULLY NOONE PULLS INFO OUT OF THE STRING BY SLICING IT.
If you want to keep just device.macs, device.ips, you can, we need to collect the Wake routes! which goes deep,
but is reasonable, because there are two sources that give us identifiers, neighbors and observations. We flatten this to device, at the router its keyed by mac or failed ip.
At the fleet idfk, i dont control that part of the code; its all AI.
So, if we can collect wake targets directly from device. Saves a whole plane of problems. suddenly wakey-cc is like 6 million times slimmer, because this is a wakey or wakey-core problem.
+28 -15
View File
@@ -34,6 +34,7 @@ import {
agentLabel,
formatSeen,
identifiersFor,
presenceRank,
routeLabel,
} from "@/pages/fleet/utils";
@@ -189,7 +190,7 @@ export function FleetDeviceDetailsDialog({
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-h-[92vh] overflow-auto sm:max-w-3xl">
<DialogContent className="max-h-[92vh] overflow-auto sm:max-w-4xl">
<DialogHeader>
<div className="flex min-w-0 items-start justify-between gap-3 pr-8">
<div className="min-w-0">
@@ -237,14 +238,26 @@ export function FleetDeviceDetailsDialog({
<Badge variant="outline">{device.endpoints.length}</Badge>
</div>
{device.endpoints.length ? (
<div className="divide-y overflow-hidden rounded-md border">
{device.endpoints.map((endpoint, index) => (
<EndpointRow
key={`${endpoint.agent_id}:${endpoint.source}:${endpoint.mac ?? ""}:${endpoint.ip ?? ""}:${index}`}
endpoint={endpoint}
onCopy={onCopy}
/>
))}
<div className="grid gap-1.5">
<div className="hidden grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)_8rem_2rem] items-center gap-2 px-3 py-1.5 text-xs font-medium text-muted-foreground sm:grid">
<span>Source</span>
<span>Target</span>
<span className="text-right">Last seen</span>
<span />
</div>
{[...device.endpoints]
.sort((a, b) => {
const p = presenceRank(b.presence) - presenceRank(a.presence);
if (p !== 0) return p;
return (b.last_seen_unix ?? 0) - (a.last_seen_unix ?? 0);
})
.map((endpoint, index) => (
<EndpointRow
key={`${endpoint.agent_id}:${endpoint.source}:${endpoint.mac ?? ""}:${endpoint.ip ?? ""}:${index}`}
endpoint={endpoint}
onCopy={onCopy}
/>
))}
</div>
) : (
<p className="rounded-md border bg-muted/30 p-3 text-sm text-muted-foreground">
@@ -557,7 +570,7 @@ function EndpointRow({
.join(" / ");
return (
<div className="grid gap-2 p-3 text-sm sm:grid-cols-[minmax(0,1.35fr)_minmax(0,1fr)_auto] sm:items-center">
<div className="grid gap-3 rounded-md border bg-card px-3 py-2.5 text-sm sm:grid-cols-[minmax(0,1.3fr)_minmax(0,1fr)_8rem_2rem] sm:items-center sm:gap-2">
<div className="min-w-0">
<div className="flex min-w-0 flex-wrap items-center gap-1.5">
<PresenceBadge presence={endpoint.presence} />
@@ -570,14 +583,14 @@ function EndpointRow({
</div>
<div className="min-w-0">
<p className="truncate font-mono text-xs">{target || "-"}</p>
<p className="truncate text-xs text-muted-foreground">
<p className="mt-0.5 truncate text-xs text-muted-foreground">
{location || "No interface or hostname"}
</p>
</div>
<div className="flex items-center justify-between gap-2 sm:justify-end">
<span className="text-xs text-muted-foreground">
{formatSeen(endpoint.last_seen_unix)}
</span>
<span className="whitespace-nowrap text-right text-xs text-muted-foreground">
{formatSeen(endpoint.last_seen_unix)}
</span>
<div className="flex justify-end">
{target && (
<Button
variant="ghost"