import React from "react"; import { formatDistanceToNow, parseISO, isValid } from "date-fns"; import { Member } from "@/types/cluster"; import StatusBadge from "@/components/nodes/status-badge"; import { ReadinessIndicator } from "@/components/nodes/readiness-indicator"; import { DataTableColumnHeader } from "@/components/common/data-table-column-header"; import { Button } from "@/components/ui/button"; import { ArrowRightCircle } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; type NodeSortField = "name" | "target" | "version" | "buildDate"; interface NodeListProps { nodes: { [key: string]: Member }; sortField: NodeSortField; sortDirection: "asc" | "desc"; onSort: (field: NodeSortField) => void; } interface NodeRowProps { name: string; node: Member; onNavigate: (name: string) => void; } const formatBuildDate = (dateStr: string) => { try { const date = parseISO(dateStr); if (!isValid(date)) { return "Invalid date"; } return formatDistanceToNow(date, { addSuffix: true }); } catch (error) { console.warn("Error parsing date:", dateStr, error); return "Invalid date"; } }; const NodeRow: React.FC = ({ name, node, onNavigate }) => { return ( onNavigate(name)} > {name} {node.target} {node.build.version} {formatBuildDate(node.build.buildDate)} ); }; const NodeList: React.FC = ({ nodes, sortField, sortDirection, onSort, }) => { const navigate = useNavigate(); const compareDates = (dateStrA: string, dateStrB: string) => { const dateA = parseISO(dateStrA); const dateB = parseISO(dateStrB); if (!isValid(dateA) && !isValid(dateB)) return 0; if (!isValid(dateA)) return 1; if (!isValid(dateB)) return -1; return dateA.getTime() - dateB.getTime(); }; const sortedNodes = Object.entries(nodes).sort(([aKey, a], [bKey, b]) => { let comparison = 0; switch (sortField) { case "name": comparison = aKey.localeCompare(bKey); break; case "target": comparison = a.target.localeCompare(b.target); break; case "version": comparison = a.build.version.localeCompare(b.build.version); break; case "buildDate": comparison = compareDates(a.build.buildDate, b.build.buildDate); break; } return sortDirection === "asc" ? comparison : -comparison; }); const handleNavigate = (name: string) => { navigate(`/nodes/${name}`); }; return (
title="Node Name" field="name" sortField={sortField} sortDirection={sortDirection} onSort={onSort} /> title="Target" field="target" sortField={sortField} sortDirection={sortDirection} onSort={onSort} /> title="Version" field="version" sortField={sortField} sortDirection={sortDirection} onSort={onSort} /> title="Build Date" field="buildDate" sortField={sortField} sortDirection={sortDirection} onSort={onSort} /> Status Ready Actions {sortedNodes.map(([name, node]) => ( ))} {sortedNodes.length === 0 && (
No nodes found
)}
); }; export default NodeList;