NodeListView.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { FC, useState, useEffect } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { makeStyles, Theme } from '@material-ui/core';
  4. import KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';
  5. import { DataGrid } from '@mui/x-data-grid';
  6. import { useNavigationHook } from '@/hooks';
  7. import { ALL_ROUTER_TYPES } from '@/router/Types';
  8. import MiniTopo from './MiniTopology';
  9. import { getByteString, formatByteSize } from '@/utils';
  10. import DataCard from './DataCard';
  11. import { NodeListViewProps, Node } from './Types';
  12. const getStyles = makeStyles((theme: Theme) => ({
  13. root: {
  14. margin: '14px 40px',
  15. display: 'grid',
  16. gridTemplateColumns: 'auto 400px',
  17. gridTemplateRows: '40px 400px auto',
  18. gridTemplateAreas: `"a a"
  19. "b ."
  20. "b d"`,
  21. },
  22. cardContainer: {
  23. display: 'grid',
  24. gap: '16px',
  25. gridTemplateColumns: 'repeat(4, minmax(300px, 1fr))',
  26. },
  27. contentContainer: {
  28. borderRadius: '8px',
  29. boxShadow: '3px 3px 10px rgba(0, 0, 0, 0.05)',
  30. display: 'grid',
  31. marginTop: '14px',
  32. },
  33. childView: {
  34. height: '100%',
  35. width: '100%',
  36. transition: 'all .25s',
  37. position: 'absolute',
  38. // zIndex: 1000,
  39. backgroundColor: 'white',
  40. },
  41. childCloseBtn: {
  42. border: 0,
  43. backgroundColor: 'white',
  44. gridArea: 'a',
  45. cursor: 'pointer',
  46. width: '100%',
  47. },
  48. gridContainer: {
  49. gridArea: 'b',
  50. display: 'flex',
  51. },
  52. dataCard: {
  53. gridArea: 'd',
  54. },
  55. }));
  56. const NodeListView: FC<NodeListViewProps> = props => {
  57. useNavigationHook(ALL_ROUTER_TYPES.SYSTEM);
  58. const { t } = useTranslation('systemView');
  59. const { t: commonTrans } = useTranslation();
  60. const capacityTrans: { [key in string]: string } = commonTrans('capacity');
  61. const classes = getStyles();
  62. const [selectedChildNode, setSelectedChildNode] = useState<
  63. Node | undefined
  64. >();
  65. const [rows, setRows] = useState<any[]>([]);
  66. const { selectedCord, childNodes, setCord } = props;
  67. const columns: any[] = [
  68. {
  69. field: 'name',
  70. headerName: t('thName'),
  71. flex: 1,
  72. },
  73. {
  74. field: 'ip',
  75. headerName: t('thIP'),
  76. flex: 1,
  77. },
  78. {
  79. field: 'cpuCore',
  80. headerName: t('thCPUCount'),
  81. flex: 1,
  82. },
  83. {
  84. field: 'cpuUsage',
  85. headerName: t('thCPUUsage'),
  86. flex: 1,
  87. },
  88. {
  89. field: 'diskUsage',
  90. headerName: t('thDiskUsage'),
  91. flex: 1,
  92. },
  93. {
  94. field: 'memUsage',
  95. headerName: t('thMemUsage'),
  96. flex: 1,
  97. },
  98. ];
  99. useEffect(() => {
  100. if (selectedCord) {
  101. const connectedIds = selectedCord.connected.map(
  102. node => node.connected_identifier
  103. );
  104. const newRows: any[] = [];
  105. childNodes.forEach(node => {
  106. if (connectedIds.includes(node.identifier)) {
  107. const memUsage = formatByteSize(
  108. node?.infos?.hardware_infos.memory_usage,
  109. capacityTrans
  110. );
  111. const dataRow = {
  112. id: node?.identifier,
  113. ip: node?.infos?.hardware_infos.ip,
  114. cpuCore: node?.infos?.hardware_infos.cpu_core_count,
  115. cpuUsage: Number(
  116. node?.infos?.hardware_infos.cpu_core_usage
  117. ).toFixed(2),
  118. diskUsage: getByteString(
  119. node?.infos?.hardware_infos.disk_usage,
  120. node?.infos?.hardware_infos.disk,
  121. capacityTrans
  122. ),
  123. // memUsage: getByteString(
  124. // node?.infos?.hardware_infos.memory_usage,
  125. // node?.infos?.hardware_infos.memory,
  126. // capacityTrans
  127. // ),
  128. memUsage: `${memUsage.value}${memUsage.unit}`,
  129. name: node?.infos?.name,
  130. };
  131. newRows.push(dataRow);
  132. }
  133. });
  134. setRows(newRows);
  135. }
  136. }, [selectedCord, childNodes, capacityTrans]);
  137. // select first node
  138. useEffect(() => {
  139. const timeoutID = window.setTimeout(() => {
  140. const el = document.querySelectorAll<HTMLElement>('.MuiDataGrid-row')[0];
  141. if (el instanceof HTMLElement) {
  142. el.click();
  143. }
  144. }, 300);
  145. return () => window.clearTimeout(timeoutID);
  146. }, [childNodes]);
  147. return (
  148. <div className={classes.root}>
  149. <button className={classes.childCloseBtn} onClick={() => setCord(null)}>
  150. <KeyboardArrowDown />
  151. </button>
  152. <div className={classes.gridContainer}>
  153. <DataGrid
  154. rows={rows}
  155. columns={columns}
  156. hideFooterPagination
  157. hideFooterSelectedRowCount
  158. onRowClick={rowData => {
  159. const selectedNode = childNodes.find(
  160. node => rowData.row.id === node.identifier
  161. );
  162. setSelectedChildNode(selectedNode);
  163. }}
  164. />
  165. </div>
  166. <MiniTopo
  167. selectedCord={selectedCord}
  168. setCord={setCord}
  169. selectedChildNode={selectedChildNode}
  170. />
  171. <DataCard className={classes.dataCard} node={selectedChildNode} />
  172. </div>
  173. );
  174. };
  175. export default NodeListView;