diff --git a/CHANGELOG.md b/CHANGELOG.md index 057c73bf8..88fc0ea0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Hide sidebar after opening, in Customize Sidebar, closes the host list once you open a host +- Sort the dashboard's Host Status card by name, IP address or status ### Fixed diff --git a/src/ui/dashboard/DashboardTab.tsx b/src/ui/dashboard/DashboardTab.tsx index 892140fa4..1c0e75bbd 100644 --- a/src/ui/dashboard/DashboardTab.tsx +++ b/src/ui/dashboard/DashboardTab.tsx @@ -53,6 +53,8 @@ import { } from "@/lib/ServerStatusContext"; import { withLiveHostStatus } from "@/sidebar/live-host-status"; import { sshHostToHost } from "@/sidebar/HostManagerData"; +import { sortHostTree, type SortKey } from "@/sidebar/host-sort"; +import { Select2 } from "@/components/select2"; import { CountersStrip, HostStatusList, @@ -66,6 +68,17 @@ import { docsUrl } from "@/lib/docs"; export { HostStatusList as HostStatusCard } from "./dashboard-core-cards"; +const HOST_STATUS_SORT_LABELS: Partial> = { + default: "hosts.sortDefault", + "name-asc": "hosts.sortNameAsc", + "name-desc": "hosts.sortNameDesc", + "ip-asc": "hosts.sortIpAsc", + "ip-desc": "hosts.sortIpDesc", + "status-online": "hosts.sortOnlineFirst", + "status-offline": "hosts.sortOfflineFirst", +}; +const HOST_STATUS_SORTS = Object.keys(HOST_STATUS_SORT_LABELS) as SortKey[]; + // ─── Types ──────────────────────────────────────────────────────────────────── type PanelId = "main" | "side"; @@ -460,7 +473,20 @@ export function DashboardTab({ const [dbHealth, setDbHealth] = useState<"healthy" | "error">("healthy"); const [credentialCount, setCredentialCount] = useState(0); const [activity, setActivity] = useState([]); - const statusCheckHosts = hosts.filter(isStatusCheckEnabled); + const [hostStatusSort, setHostStatusSort] = useState(() => { + try { + const saved = localStorage.getItem("dashboardTab.hostStatusSort"); + return HOST_STATUS_SORTS.includes(saved as SortKey) + ? (saved as SortKey) + : "default"; + } catch { + return "default"; + } + }); + const statusCheckHosts = sortHostTree( + { name: "", children: hosts.filter(isStatusCheckEnabled) }, + hostStatusSort, + ).children as Host[]; useEffect(() => { let mounted = true; @@ -580,7 +606,28 @@ export function DashboardTab({ icon: core.icon, frame: core.frame, action: - id === "recent_activity" && activity.length > 0 ? ( + id === "host_status" && statusCheckHosts.length > 1 ? ( + { + const key = e.target.value as SortKey; + setHostStatusSort(key); + try { + localStorage.setItem("dashboardTab.hostStatusSort", key); + } catch { + /* ignore */ + } + }} + className="h-6 border border-border bg-background px-1.5 text-[10px] outline-none focus:ring-1 focus:ring-ring" + > + {HOST_STATUS_SORTS.map((key) => ( + + ))} + + ) : id === "recent_activity" && activity.length > 0 ? (