From 0122e2bdcfbe7b857efe81908d6e0feeb4f1a212 Mon Sep 17 00:00:00 2001 From: wonfen Date: Tue, 18 Feb 2025 11:04:22 +0800 Subject: [PATCH] feat: Add persistent column width settings for connection table & process filtering --- .../connection/connection-table.tsx | 87 ++++++++++++++++--- src/pages/connections.tsx | 10 ++- 2 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/components/connection/connection-table.tsx b/src/components/connection/connection-table.tsx index adf10505..ce389ec9 100644 --- a/src/components/connection/connection-table.tsx +++ b/src/components/connection/connection-table.tsx @@ -1,6 +1,6 @@ import dayjs from "dayjs"; -import { useMemo, useState } from "react"; -import { DataGrid, GridColDef } from "@mui/x-data-grid"; +import { useMemo, useState, useEffect } from "react"; +import { DataGrid, GridColDef, GridColumnResizeParams } from "@mui/x-data-grid"; import { useThemeMode } from "@/services/states"; import { truncateStr } from "@/utils/truncate-str"; import parseTraffic from "@/utils/parse-traffic"; @@ -21,12 +21,24 @@ export const ConnectionTable = (props: Props) => { Partial> >({}); + const [columnWidths, setColumnWidths] = useState>( + () => { + const saved = localStorage.getItem("connection-table-widths"); + return saved ? JSON.parse(saved) : {}; + }, + ); + const [columns] = useState([ - { field: "host", headerName: t("Host"), flex: 220, minWidth: 220 }, + { + field: "host", + headerName: t("Host"), + width: columnWidths["host"] || 220, + minWidth: 180, + }, { field: "download", headerName: t("Downloaded"), - width: 88, + width: columnWidths["download"] || 88, align: "right", headerAlign: "right", valueFormatter: (value: number) => parseTraffic(value).join(" "), @@ -34,7 +46,7 @@ export const ConnectionTable = (props: Props) => { { field: "upload", headerName: t("Uploaded"), - width: 88, + width: columnWidths["upload"] || 88, align: "right", headerAlign: "right", valueFormatter: (value: number) => parseTraffic(value).join(" "), @@ -42,7 +54,7 @@ export const ConnectionTable = (props: Props) => { { field: "dlSpeed", headerName: t("DL Speed"), - width: 88, + width: columnWidths["dlSpeed"] || 88, align: "right", headerAlign: "right", valueFormatter: (value: number) => parseTraffic(value).join(" ") + "/s", @@ -50,18 +62,33 @@ export const ConnectionTable = (props: Props) => { { field: "ulSpeed", headerName: t("UL Speed"), - width: 88, + width: columnWidths["ulSpeed"] || 88, align: "right", headerAlign: "right", valueFormatter: (value: number) => parseTraffic(value).join(" ") + "/s", }, - { field: "chains", headerName: t("Chains"), flex: 360, minWidth: 360 }, - { field: "rule", headerName: t("Rule"), flex: 300, minWidth: 250 }, - { field: "process", headerName: t("Process"), flex: 240, minWidth: 120 }, + { + field: "chains", + headerName: t("Chains"), + width: columnWidths["chains"] || 340, + minWidth: 180, + }, + { + field: "rule", + headerName: t("Rule"), + width: columnWidths["rule"] || 280, + minWidth: 180, + }, + { + field: "process", + headerName: t("Process"), + width: columnWidths["process"] || 220, + minWidth: 180, + }, { field: "time", headerName: t("Time"), - flex: 120, + width: columnWidths["time"] || 120, minWidth: 100, align: "right", headerAlign: "right", @@ -69,16 +96,43 @@ export const ConnectionTable = (props: Props) => { new Date(v2).getTime() - new Date(v1).getTime(), valueFormatter: (value: number) => dayjs(value).fromNow(), }, - { field: "source", headerName: t("Source"), flex: 200, minWidth: 130 }, + { + field: "source", + headerName: t("Source"), + width: columnWidths["source"] || 200, + minWidth: 130, + }, { field: "remoteDestination", headerName: t("Destination"), - flex: 200, + width: columnWidths["remoteDestination"] || 200, minWidth: 130, }, - { field: "type", headerName: t("Type"), flex: 160, minWidth: 100 }, + { + field: "type", + headerName: t("Type"), + width: columnWidths["type"] || 160, + minWidth: 100, + }, ]); + useEffect(() => { + console.log("Saving column widths:", columnWidths); + localStorage.setItem( + "connection-table-widths", + JSON.stringify(columnWidths), + ); + }, [columnWidths]); + + const handleColumnResize = (params: GridColumnResizeParams) => { + const { colDef, width } = params; + console.log("Column resize:", colDef.field, width); + setColumnWidths((prev) => ({ + ...prev, + [colDef.field]: width, + })); + }; + const connRows = useMemo(() => { return connections.map((each) => { const { metadata, rulePayload } = each; @@ -115,9 +169,14 @@ export const ConnectionTable = (props: Props) => { sx={{ border: "none", "div:focus": { outline: "none !important" }, + "& .MuiDataGrid-columnHeader": { + userSelect: "none", + }, }} columnVisibilityModel={columnVisible} onColumnVisibilityModelChange={(e) => setColumnVisible(e)} + onColumnResize={handleColumnResize} + disableColumnMenu={false} /> ); }; diff --git a/src/pages/connections.tsx b/src/pages/connections.tsx index 874ab4a8..a827b389 100644 --- a/src/pages/connections.tsx +++ b/src/pages/connections.tsx @@ -129,9 +129,13 @@ const ConnectionsPage = () => { const [filterConn, download, upload] = useMemo(() => { const orderFunc = orderOpts[curOrderOpt]; - let connections = displayData.connections.filter((conn) => - match(conn.metadata.host || conn.metadata.destinationIP || ""), - ); + + let connections = displayData.connections.filter((conn) => { + const { host, destinationIP, process } = conn.metadata; + return ( + match(host || "") || match(destinationIP || "") || match(process || "") + ); + }); if (orderFunc) connections = orderFunc(connections);