connection-table.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import dayjs from "dayjs";
  2. import { useMemo, useState } from "react";
  3. import { DataGrid, GridColDef } from "@mui/x-data-grid";
  4. import { truncateStr } from "@/utils/truncate-str";
  5. import parseTraffic from "@/utils/parse-traffic";
  6. import { sortWithUnit, sortStringTime } from "@/utils/custom-comparator";
  7. interface Props {
  8. connections: IConnectionsItem[];
  9. onShowDetail: (data: IConnectionsItem) => void;
  10. }
  11. export const ConnectionTable = (props: Props) => {
  12. const { connections, onShowDetail } = props;
  13. const [columnVisible, setColumnVisible] = useState<
  14. Partial<Record<keyof IConnectionsItem, boolean>>
  15. >({});
  16. const columns: GridColDef[] = [
  17. { field: "host", headerName: "Host", flex: 220, minWidth: 220 },
  18. {
  19. field: "download",
  20. headerName: "Download",
  21. width: 88,
  22. align: "right",
  23. headerAlign: "right",
  24. sortComparator: sortWithUnit,
  25. },
  26. {
  27. field: "upload",
  28. headerName: "Upload",
  29. width: 88,
  30. align: "right",
  31. headerAlign: "right",
  32. sortComparator: sortWithUnit,
  33. },
  34. {
  35. field: "dlSpeed",
  36. headerName: "DL Speed",
  37. width: 88,
  38. align: "right",
  39. headerAlign: "right",
  40. sortComparator: sortWithUnit,
  41. },
  42. {
  43. field: "ulSpeed",
  44. headerName: "UL Speed",
  45. width: 88,
  46. align: "right",
  47. headerAlign: "right",
  48. sortComparator: sortWithUnit,
  49. },
  50. { field: "chains", headerName: "Chains", flex: 360, minWidth: 360 },
  51. { field: "rule", headerName: "Rule", flex: 300, minWidth: 250 },
  52. { field: "process", headerName: "Process", flex: 240, minWidth: 120 },
  53. {
  54. field: "time",
  55. headerName: "Time",
  56. flex: 120,
  57. minWidth: 100,
  58. align: "right",
  59. headerAlign: "right",
  60. sortComparator: sortStringTime,
  61. },
  62. { field: "source", headerName: "Source", flex: 200, minWidth: 130 },
  63. {
  64. field: "destinationIP",
  65. headerName: "Destination IP",
  66. flex: 200,
  67. minWidth: 130,
  68. },
  69. { field: "type", headerName: "Type", flex: 160, minWidth: 100 },
  70. ];
  71. const connRows = useMemo(() => {
  72. return connections.map((each) => {
  73. const { metadata, rulePayload } = each;
  74. const chains = [...each.chains].reverse().join(" / ");
  75. const rule = rulePayload ? `${each.rule}(${rulePayload})` : each.rule;
  76. return {
  77. id: each.id,
  78. host: metadata.host
  79. ? `${metadata.host}:${metadata.destinationPort}`
  80. : `${metadata.destinationIP}:${metadata.destinationPort}`,
  81. download: parseTraffic(each.download).join(" "),
  82. upload: parseTraffic(each.upload).join(" "),
  83. dlSpeed: parseTraffic(each.curDownload).join(" ") + "/s",
  84. ulSpeed: parseTraffic(each.curUpload).join(" ") + "/s",
  85. chains,
  86. rule,
  87. process: truncateStr(metadata.process || metadata.processPath),
  88. time: dayjs(each.start).fromNow(),
  89. source: `${metadata.sourceIP}:${metadata.sourcePort}`,
  90. destinationIP: metadata.destinationIP,
  91. type: `${metadata.type}(${metadata.network})`,
  92. connectionData: each,
  93. };
  94. });
  95. }, [connections]);
  96. return (
  97. <DataGrid
  98. hideFooter
  99. rows={connRows}
  100. columns={columns}
  101. onRowClick={(e) => onShowDetail(e.row.connectionData)}
  102. density="compact"
  103. sx={{ border: "none", "div:focus": { outline: "none !important" } }}
  104. columnVisibilityModel={columnVisible}
  105. onColumnVisibilityModelChange={(e) => setColumnVisible(e)}
  106. />
  107. );
  108. };