import { ChevronDown, Copy } from "lucide-react"; import { useMemo } from "react"; import Chip from "~/components/Chip"; import Link from "~/components/link"; import { Menu, MenuContent, MenuItem, MenuTrigger } from "~/components/menu"; import StatusCircle from "~/components/StatusCircle"; import { ExitNodeTag } from "~/components/tags/ExitNode"; import { ExpiryTag } from "~/components/tags/Expiry"; import { HeadplaneAgentTag } from "~/components/tags/HeadplaneAgent"; import { SubnetTag } from "~/components/tags/Subnet"; import { TailscaleSSHTag } from "~/components/tags/TailscaleSSH"; import type { User } from "~/types"; import cn from "~/utils/cn"; import * as hinfo from "~/utils/host-info"; import type { PopulatedNode } from "~/utils/node-info"; import { formatTimeDelta } from "~/utils/time"; import toast from "~/utils/toast"; import { getUserDisplayName } from "~/utils/user"; import MenuOptions from "./menu"; interface Props { node: PopulatedNode; users: User[]; isAgent?: boolean; magic?: string; isDisabled?: boolean; existingTags?: string[]; supportsNodeOwnerChange: boolean; } export default function MachineRow({ node, users, isAgent, magic, isDisabled, existingTags, supportsNodeOwnerChange, }: Props) { const uiTags = useMemo(() => uiTagsForNode(node, isAgent), [node, isAgent]); const ipOptions = useMemo(() => { if (magic) { return [...node.ipAddresses, `${node.givenName}.${magic}`]; } return node.ipAddresses; }, [magic, node.ipAddresses]); return (
{node.givenName}
{node.user ? getUserDisplayName(node.user) : "Tag-owned"}
{hinfo.getTSVersion(node.hostInfo)}
{hinfo.getOSInfo(node.hostInfo)}
> ) : (Unknown
)}{node.online && !node.expired ? "Connected" : new Date(node.lastSeen).toLocaleString()}
{!(node.online && !node.expired) && ({formatTimeDelta(new Date(node.lastSeen))}
)}