From 88769209e8ac330b16e003f062ed01d8d06ed914 Mon Sep 17 00:00:00 2001 From: maihemutimaimaiti Date: Wed, 13 May 2026 07:07:51 +0000 Subject: [PATCH] feat: add server list sorting and filtering --- .../_components/performance-server-list.tsx | 142 +++++++++++++++++- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/app/(dashboard)/_components/performance-server-list.tsx b/app/(dashboard)/_components/performance-server-list.tsx index a201046..9b84dad 100644 --- a/app/(dashboard)/_components/performance-server-list.tsx +++ b/app/(dashboard)/_components/performance-server-list.tsx @@ -1,9 +1,12 @@ "use client" +import * as React from "react" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion" +import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Progress } from "@/components/ui/progress" import { ScrollArea } from "@/components/ui/scroll-area" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { niceBytes } from "@/lib/functions" import { cn } from "@/lib/utils" import dayjs from "dayjs" @@ -20,7 +23,94 @@ function countOnlineNetworks(server: ServerInfo, type: string) { return Object.values(server?.network || {}).filter((state) => state === type).length } +type PerformanceServerSort = + | "default" + | "endpoint-asc" + | "endpoint-desc" + | "status-online" + | "status-offline" + | "uptime-desc" + | "uptime-asc" + +type PerformanceServerFilter = "all" | "online" | "offline" + +function isOnlineServer(server: ServerInfo) { + return (server.state ?? "").toLowerCase() === "online" +} + +function compareEndpoint(left: ServerInfo, right: ServerInfo, direction: "asc" | "desc") { + const normalizedLeft = left.endpoint?.trim() + const normalizedRight = right.endpoint?.trim() + + if (!normalizedLeft && !normalizedRight) return 0 + if (!normalizedLeft) return 1 + if (!normalizedRight) return -1 + + const result = normalizedLeft.localeCompare(normalizedRight, undefined, { + numeric: true, + sensitivity: "base", + }) + + return direction === "asc" ? result : -result +} + +function compareUptime(left: ServerInfo, right: ServerInfo, direction: "asc" | "desc") { + const hasLeft = Number.isFinite(left.uptime) + const hasRight = Number.isFinite(right.uptime) + + if (!hasLeft && !hasRight) return 0 + if (!hasLeft) return 1 + if (!hasRight) return -1 + + return direction === "asc" ? left.uptime! - right.uptime! : right.uptime! - left.uptime! +} + export function PerformanceServerList({ servers, t }: { servers: ServerInfo[]; t: (key: string) => string }) { + const [sortBy, setSortBy] = React.useState("default") + const [filterBy, setFilterBy] = React.useState("all") + const onlineCount = servers.filter((server) => isOnlineServer(server)).length + + const visibleServers = React.useMemo(() => { + const rows = servers + .map((server, originalIndex) => ({ + server, + originalIndex, + })) + .filter(({ server }) => { + if (filterBy === "online") return isOnlineServer(server) + if (filterBy === "offline") return !isOnlineServer(server) + return true + }) + + return rows.sort((left, right) => { + switch (sortBy) { + case "endpoint-asc": + return compareEndpoint(left.server, right.server, "asc") || left.originalIndex - right.originalIndex + case "endpoint-desc": + return compareEndpoint(left.server, right.server, "desc") || left.originalIndex - right.originalIndex + case "status-online": + return ( + Number(isOnlineServer(right.server)) - Number(isOnlineServer(left.server)) || + compareEndpoint(left.server, right.server, "asc") || + left.originalIndex - right.originalIndex + ) + case "status-offline": + return ( + Number(isOnlineServer(left.server)) - Number(isOnlineServer(right.server)) || + compareEndpoint(left.server, right.server, "asc") || + left.originalIndex - right.originalIndex + ) + case "uptime-desc": + return compareUptime(left.server, right.server, "desc") || left.originalIndex - right.originalIndex + case "uptime-asc": + return compareUptime(left.server, right.server, "asc") || left.originalIndex - right.originalIndex + case "default": + default: + return left.originalIndex - right.originalIndex + } + }) + }, [filterBy, servers, sortBy]) + return ( @@ -30,14 +120,56 @@ export function PerformanceServerList({ servers, t }: { servers: ServerInfo[]; t {t("Inspect individual server health, disk utilization, and network status.")} - - {t("Total")}: {servers.length} - +
+ + {t("Total")}: {visibleServers.length}/{servers.length} + +
+ + +
+
+ {t("Sort by")} + +
+
- {servers.map((server, index) => ( - + {visibleServers.map(({ server, originalIndex }) => ( +