feat: Add persistent column width settings for connection table & process filtering

This commit is contained in:
wonfen 2025-02-18 11:04:22 +08:00
parent 94b75f463b
commit 0122e2bdcf
2 changed files with 80 additions and 17 deletions

View File

@ -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<Record<keyof IConnectionsItem, boolean>>
>({});
const [columnWidths, setColumnWidths] = useState<Record<string, number>>(
() => {
const saved = localStorage.getItem("connection-table-widths");
return saved ? JSON.parse(saved) : {};
},
);
const [columns] = useState<GridColDef[]>([
{ 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}
/>
);
};

View File

@ -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);