connection-table.tsx 3.8 KB

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