Browse Source

Update system view (#540)

* part1

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* part2

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* finish refactor

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* remove @mui/x-data-grid

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

* update

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>

---------

Signed-off-by: shanghaikid <jiangruiyi@gmail.com>
ryjiang 1 year ago
parent
commit
4480c2d35c

+ 0 - 1
client/package.json

@@ -19,7 +19,6 @@
     "@material-ui/icons": "^4.11.3",
     "@material-ui/lab": "4.0.0-alpha.61",
     "@material-ui/pickers": "^3.3.10",
-    "@mui/x-data-grid": "^4.0.0",
     "axios": "^1.7.2",
     "codemirror": "^6.0.1",
     "d3": "^7.8.5",

+ 11 - 1
client/src/components/grid/Table.tsx

@@ -65,6 +65,12 @@ const useStyles = makeStyles(theme => ({
       },
     },
   },
+  selected: {
+    backgroundColor: '#f3fcfe !important',
+    '& td': {
+      background: 'inherit',
+    },
+  },
   cell: {
     borderBottom: '1px solid #e9e9ed',
 
@@ -168,6 +174,10 @@ const EnhancedTable: FC<TableType> = props => {
                       selected={isItemSelected && !disableSelect}
                       classes={{
                         hover: classes.rowHover,
+                        selected:
+                          isItemSelected && !disableSelect
+                            ? classes.selected
+                            : undefined,
                       }}
                     >
                       {openCheckBox && (
@@ -241,7 +251,7 @@ const EnhancedTable: FC<TableType> = props => {
                                     </Button>
                                   ) : colDef.formatter ? (
                                     colDef.formatter(row, row[colDef.id], i)
-                                    ) : (
+                                  ) : (
                                     <Typography title={row[colDef.id]}>
                                       {row[colDef.id]}
                                     </Typography>

+ 2 - 0
client/src/i18n/cn/common.ts

@@ -41,6 +41,8 @@ const commonTrans = {
     partitions: '分区',
     property: '属性',
     properties: '属性',
+    node: '节点',
+    nodes: '节点',
     results: '结果',
     of: '的',
     nextLabel: '下一页',

+ 2 - 0
client/src/i18n/en/common.ts

@@ -42,6 +42,8 @@ const commonTrans = {
     partitions: 'Partitions',
     property: 'Property',
     properties: 'Properties',
+    node: 'Node',
+    nodes: 'Nodes',
     results: 'results',
     of: 'of',
     nextLabel: 'next page',

+ 3 - 3
client/src/i18n/en/systemView.ts

@@ -7,10 +7,10 @@ const systemViewTrans = {
   configTitle: 'Config',
   valueTitle: 'Value',
   systemTitle: 'System',
-  thName: 'Node Name',
+  thName: 'Node',
   thIP: 'IP',
-  thCPUCount: 'CPU Core Count',
-  thCPUUsage: 'CPU Core Usage',
+  thCPUCount: 'CPU Core',
+  thCPUUsage: 'CPU Usage',
   thDiskUsage: 'Disk Usage',
   thMemUsage: 'Memory Usage',
   thVersion: 'version',

+ 12 - 11
client/src/pages/system/DataCard.tsx

@@ -8,9 +8,9 @@ import { DataProgressProps, DataSectionProps, DataCardProps } from './Types';
 const getStyles = makeStyles(theme => ({
   root: {
     backgroundColor: '#F6F6F6',
-    height: '100%',
     padding: theme.spacing(1.5, 2),
     boxSizing: 'border-box',
+    flexGrow: 1,
   },
 
   title: {
@@ -46,14 +46,14 @@ const getStyles = makeStyles(theme => ({
 
   ip: {
     color: theme.palette.attuDark.main,
-    fontSize: '16px',
+    fontSize: '11px',
     lineHeight: '24px',
   },
 
   sectionRoot: {
     borderSpacing: '0 1px',
     display: 'table',
-    marginTop: theme.spacing(2.5),
+    marginTop: theme.spacing(0.5),
     width: '100%',
   },
 
@@ -66,7 +66,7 @@ const getStyles = makeStyles(theme => ({
     color: theme.palette.attuGrey.dark,
     fontSize: '12px',
     lineHeight: '24px',
-    padding: theme.spacing(1, 2),
+    padding: theme.spacing(0.5, 1),
     textTransform: 'uppercase',
     width: '50%',
   },
@@ -76,8 +76,7 @@ const getStyles = makeStyles(theme => ({
     color: theme.palette.attuDark.main,
     display: 'table-cell',
     fontSize: '14px',
-    lineHeight: '24px',
-    padding: theme.spacing(1.5, 2),
+    padding: theme.spacing(1, 1),
     textTransform: 'capitalize',
     verticalAlign: 'middle',
     width: '50%',
@@ -138,13 +137,14 @@ const DataCard: FC<DataCardProps & React.HTMLAttributes<HTMLDivElement>> =
     const capacityTrans: { [key in string]: string } = commonTrans('capacity');
     const { node, extend } = props;
 
-    // const hardwareTitle = [t('hardwareTitle'), t('valueTitle')];
+    const hardwareTitle = [t('hardwareTitle'), t('valueTitle')];
     const hardwareContent = [];
 
     const configTitle = [t('configTitle'), t('valueTitle')];
     const systemConfig: { label: string; value: any }[] = [];
 
     const systemTitle = [t('systemTitle'), t('valueTitle')];
+
     const systemContent = [];
 
     const {
@@ -210,12 +210,13 @@ const DataCard: FC<DataCardProps & React.HTMLAttributes<HTMLDivElement>> =
             <span className={classes.rootName}>Milvus / </span>
             <span className={classes.childName}>{node?.infos?.name}</span>
           </div>
-          {/* <div className={classes.ip}>{`${t('thIP')}:${infos?.ip || ''}`}</div> */}
+          <div className={classes.ip}>{`${t('thIP')}:${infos?.ip || ''}`}</div>
         </div>
-        {/* {extend && (
-          <DataSection titles={hardwareTitle} contents={hardwareContent} />
-        )} */}
         <DataSection titles={systemTitle} contents={systemContent} />
+        {extend && (
+          <DataSection titles={hardwareTitle} contents={hardwareContent} />
+        )}
+
         {systemConfig.length ? (
           <DataSection titles={configTitle} contents={systemConfig} />
         ) : null}

+ 5 - 8
client/src/pages/system/MiniTopology.tsx

@@ -3,10 +3,7 @@ import { makeStyles, Theme, useTheme } from '@material-ui/core';
 import { MiniTopoProps } from './Types';
 
 const getStyles = makeStyles((theme: Theme) => ({
-  container: {
-    height: '100%',
-    width: 'auto',
-  },
+  container: {},
   childNode: {
     transition: 'all .25s',
     cursor: 'pointer',
@@ -52,10 +49,10 @@ const capitalize = (s: string) => {
 const MiniTopo: FC<MiniTopoProps> = props => {
   const classes = getStyles();
   const theme = useTheme();
-  const { selectedCord, selectedChildNode, setCord } = props;
+  const { selectedCord, selectedChildNode, setCord, setShowChildView } = props;
 
-  const WIDTH = 400; // width for svg
-  const HEIGHT = 400; // height for svg
+  const WIDTH = 300; // width for svg
+  const HEIGHT = 300; // height for svg
   const LINE = 80; // line lenght from lv2 node
   const ANGLE = 10; // angle offset for lv2 node
   const R1 = 45; // root node radius
@@ -85,7 +82,7 @@ const MiniTopo: FC<MiniTopoProps> = props => {
       <g
         className={classes.childNode}
         onClick={() => {
-          setCord(null);
+          setShowChildView(false);
         }}
       >
         <circle

+ 167 - 104
client/src/pages/system/NodeListView.tsx

@@ -2,178 +2,241 @@ import { FC, useState, useEffect } from 'react';
 import { useTranslation } from 'react-i18next';
 import { makeStyles, Theme } from '@material-ui/core';
 import KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDown';
-import { DataGrid } from '@mui/x-data-grid';
+import AttuGrid from '@/components/grid/Grid';
+import { ColDefinitionsType } from '@/components/grid/Types';
 import { useNavigationHook } from '@/hooks';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import MiniTopo from './MiniTopology';
 import { getByteString, formatByteSize } from '@/utils';
 import DataCard from './DataCard';
+import { usePaginationHook } from '@/hooks';
+import { getLabelDisplayedRows } from '@/pages/search/Utils';
 import { NodeListViewProps, Node } from './Types';
 
 const getStyles = makeStyles((theme: Theme) => ({
   root: {
-    margin: '14px 40px',
-    display: 'grid',
-    gridTemplateColumns: 'auto 400px',
-    gridTemplateRows: '40px 400px auto',
-    gridTemplateAreas: `"a a"
-       "b ."
-       "b d"`,
-  },
-  cardContainer: {
-    display: 'grid',
-    gap: '16px',
-    gridTemplateColumns: 'repeat(4, minmax(300px, 1fr))',
-  },
-  contentContainer: {
-    display: 'grid',
-    marginTop: '14px',
-  },
-  childView: {
-    height: '100%',
-    width: '100%',
-    transition: 'all .25s',
-    position: 'absolute',
-    // zIndex: 1000,
-    backgroundColor: 'white',
+    overflow: 'hidden',
+    padding: '0 16px',
+    display: 'flex',
+    flexDirection: 'column',
+    border: '1px solid #e9e9ed',
   },
-  childCloseBtn: {
+  childCloseBtnContainer: {
     border: 0,
     backgroundColor: 'white',
-    gridArea: 'a',
     cursor: 'pointer',
     width: '100%',
+    height: '28px',
   },
   gridContainer: {
-    gridArea: 'b',
+    height: `calc(100vh - 120px)`,
     display: 'flex',
+    gap: 8,
+  },
+  leftContainer: {
+    height: '100%',
+    width: '70%',
   },
-  dataCard: {
-    gridArea: 'd',
+  rightContainer: {
+    width: '30%',
+    overflow: 'scroll',
   },
+  dataCard: {},
 }));
 
+type GridNode = {
+  id: string;
+  ip: string;
+  cpuCore: number;
+  cpuUsage: number;
+  disk: number;
+  diskUsage: number;
+  memUsage: number;
+  name: string;
+  node: Node;
+};
+
 const NodeListView: FC<NodeListViewProps> = props => {
   useNavigationHook(ALL_ROUTER_TYPES.SYSTEM);
   const { t } = useTranslation('systemView');
   const { t: commonTrans } = useTranslation();
   const capacityTrans: { [key in string]: string } = commonTrans('capacity');
 
+  const gridTrans = commonTrans('grid');
+
   const classes = getStyles();
-  const [selectedChildNode, setSelectedChildNode] = useState<
-    Node | undefined
-  >();
+  const [selectedChildNode, setSelectedChildNode] = useState<GridNode[]>([]);
   const [rows, setRows] = useState<any[]>([]);
-  const { selectedCord, childNodes, setCord } = props;
+  const { selectedCord, childNodes, setCord, setShowChildView } = props;
 
-  const columns: any[] = [
+  const colDefinitions: ColDefinitionsType[] = [
     {
-      field: 'name',
-      headerName: t('thName'),
-      flex: 1,
+      id: 'name',
+      label: t('thName'),
+      disablePadding: true,
+      sortBy: 'name',
+      sortType: 'string',
     },
     {
-      field: 'ip',
-      headerName: t('thIP'),
-      flex: 1,
+      id: 'ip',
+      label: t('thIP'),
+      disablePadding: true,
+      notSort: true,
+      needCopy: true,
     },
     {
-      field: 'cpuCore',
-      headerName: t('thCPUCount'),
-      flex: 1,
+      id: 'cpuCore',
+      label: t('thCPUCount'),
+      disablePadding: true,
     },
     {
-      field: 'cpuUsage',
-      headerName: t('thCPUUsage'),
-      flex: 1,
+      id: 'cpuUsage',
+      label: t('thCPUUsage'),
+      formatter(_, cellData) {
+        // -> 0.00%
+        return `${cellData.toFixed(2)}%`;
+      },
+      disablePadding: true,
     },
     {
-      field: 'diskUsage',
-      headerName: t('thDiskUsage'),
-      flex: 1,
+      id: 'diskUsage',
+      label: t('thDiskUsage'),
+      disablePadding: true,
+      notSort: true,
+      formatter(rowData) {
+        return getByteString(rowData.diskUsage, rowData.disk, capacityTrans);
+      },
     },
     {
-      field: 'memUsage',
-      headerName: t('thMemUsage'),
-      flex: 1,
+      id: 'memUsage',
+      label: t('thMemUsage'),
+      disablePadding: true,
+      formatter(_, cellData) {
+        const memUsage = formatByteSize(cellData, capacityTrans);
+
+        return `${memUsage.value}${memUsage.unit}`;
+      },
     },
   ];
 
+  const {
+    pageSize,
+    handlePageSize,
+    currentPage,
+    handleCurrentPage,
+    total,
+    data,
+    order,
+    orderBy,
+    handleGridSort,
+  } = usePaginationHook(rows);
+
   useEffect(() => {
     if (selectedCord) {
-      const connectedIds = selectedCord.connected.map(
-        node => node.connected_identifier
+      const connectedTypes = selectedCord.connected.map(
+        node => node.target_type
       );
       const newRows: any[] = [];
       childNodes.forEach(node => {
-        if (connectedIds.includes(node.identifier)) {
-          const memUsage = formatByteSize(
-            node?.infos?.hardware_infos.memory_usage,
-            capacityTrans
-          );
+        if (connectedTypes.includes(node.infos.type)) {
           const dataRow = {
+            _id: `${node?.identifier}-${node?.infos?.type}`,
             id: node?.identifier,
             ip: node?.infos?.hardware_infos.ip,
             cpuCore: node?.infos?.hardware_infos.cpu_core_count,
-            cpuUsage: Number(
-              node?.infos?.hardware_infos.cpu_core_usage
-            ).toFixed(2),
-            diskUsage: getByteString(
-              node?.infos?.hardware_infos.disk_usage,
-              node?.infos?.hardware_infos.disk,
-              capacityTrans
-            ),
-            // memUsage: getByteString(
-            //   node?.infos?.hardware_infos.memory_usage,
-            //   node?.infos?.hardware_infos.memory,
-            //   capacityTrans
-            // ),
-            memUsage: `${memUsage.value}${memUsage.unit}`,
+            cpuUsage: node?.infos?.hardware_infos.cpu_core_usage,
+            disk: node?.infos?.hardware_infos.disk,
+            diskUsage: node?.infos?.hardware_infos.disk_usage,
+            memUsage: node?.infos?.hardware_infos.memory_usage,
             name: node?.infos?.name,
+            node: node,
           };
           newRows.push(dataRow);
         }
       });
+
+      // create mock rows 100 times to test pagination
+      // const mockRows: any = [...newRows];
+      // for (let i = 0; i < 100; i++) {
+      //   mockRows.push({
+      //     ...newRows[0],
+      //     id: 'mock' + i,
+      //     memUsage: i * 1000 * Math.floor(Math.random() * 100000000),
+      //   });
+      // }
+
       setRows(newRows);
+      // make first row selected
+      if (newRows.length > 0) {
+        setSelectedChildNode([newRows[0]]);
+      }
     }
-  }, [selectedCord, childNodes, capacityTrans]);
+  }, [selectedCord, childNodes]);
 
-  // select first node
-  useEffect(() => {
-    const timeoutID = window.setTimeout(() => {
-      const el = document.querySelectorAll<HTMLElement>('.MuiDataGrid-row')[0];
-      if (el instanceof HTMLElement) {
-        el.click();
-      }
-    }, 300);
-    return () => window.clearTimeout(timeoutID);
-  }, [childNodes]);
+  const handlePageChange = (e: any, page: number) => {
+    handleCurrentPage(page);
+  };
+
+  const handleSelectChange = (value: GridNode[]) => {
+    // only select one row, filter out the rest
+    if (value.length > 1) {
+      value = [value[value.length - 1]];
+    }
+    setSelectedChildNode(value);
+  };
+
+  const infoNode = selectedChildNode[0] && selectedChildNode[0].node;
 
   return (
     <div className={classes.root}>
-      <button className={classes.childCloseBtn} onClick={() => setCord(null)}>
+      <button
+        className={classes.childCloseBtnContainer}
+        onClick={() => setShowChildView(false)}
+      >
         <KeyboardArrowDown />
       </button>
       <div className={classes.gridContainer}>
-        <DataGrid
-          rows={rows}
-          columns={columns}
-          hideFooterPagination
-          hideFooterSelectedRowCount
-          onRowClick={rowData => {
-            const selectedNode = childNodes.find(
-              node => rowData.row.id === node.identifier
-            );
-            setSelectedChildNode(selectedNode);
-          }}
-        />
+        <div className={classes.leftContainer}>
+          <AttuGrid
+            toolbarConfigs={[]}
+            colDefinitions={colDefinitions}
+            rows={data}
+            rowCount={total}
+            primaryKey="_id"
+            page={currentPage}
+            onPageChange={handlePageChange}
+            rowsPerPage={pageSize}
+            setRowsPerPage={handlePageSize}
+            isLoading={false}
+            order={order}
+            orderBy={orderBy}
+            handleSort={handleGridSort}
+            openCheckBox={false}
+            selected={selectedChildNode}
+            setSelected={handleSelectChange}
+            labelDisplayedRows={getLabelDisplayedRows(
+              gridTrans[data.length > 1 ? 'nodes' : 'node']
+            )}
+          />
+        </div>
+        <div className={classes.rightContainer}>
+          {infoNode && (
+            <>
+              <MiniTopo
+                selectedCord={selectedCord}
+                setCord={setCord}
+                selectedChildNode={infoNode}
+                setShowChildView={setShowChildView}
+              />
+              <DataCard
+                className={classes.dataCard}
+                node={infoNode}
+                extend={true}
+              />
+            </>
+          )}
+        </div>
       </div>
-      <MiniTopo
-        selectedCord={selectedCord}
-        setCord={setCord}
-        selectedChildNode={selectedChildNode}
-      />
-      <DataCard className={classes.dataCard} node={selectedChildNode} />
     </div>
   );
 };

+ 26 - 28
client/src/pages/system/SystemView.tsx

@@ -1,5 +1,4 @@
 import { useState, useEffect, useRef } from 'react';
-// import { useTranslation } from 'react-i18next';
 import { makeStyles, Theme } from '@material-ui/core';
 import clsx from 'clsx';
 import { useNavigationHook, useInterval } from '@/hooks';
@@ -16,25 +15,22 @@ const getStyles = makeStyles((theme: Theme) => ({
   root: {
     margin: '16px',
     position: 'relative',
-    height: 'fit-content',
     display: 'flex',
-    flexDirection: 'column',
-  },
-  cardContainer: {
-    display: 'grid',
-    gap: '16px',
-    gridTemplateColumns: 'repeat(4, minmax(300px, 1fr))',
+    height: 'calc(100vh - 80px)',
+    overflow: 'hidden',
   },
   transparent: {
     opacity: 0,
     transition: 'opacity .5s',
   },
   contentContainer: {
-    display: 'grid',
-    gridTemplateColumns: '1fr auto',
-    marginTop: '14px',
-    height: '100%',
+    display: 'flex',
+    border: '1px solid #e9e9ed',
+    gap: 8,
+    width: '100%',
   },
+  left: { width: '70%', background: '#fff' },
+  right: { width: '30%' },
   childView: {
     height: '100%',
     width: '100%',
@@ -45,12 +41,11 @@ const getStyles = makeStyles((theme: Theme) => ({
   },
   showChildView: {
     top: 0,
-    minHeight: '100%',
-    height: 'fit-content',
+    opacity: 1,
   },
   hideChildView: {
-    top: '1500px',
-    maxHeight: 0,
+    top: 1600,
+    opacity: 0,
   },
   childCloseBtn: {
     border: 0,
@@ -59,10 +54,6 @@ const getStyles = makeStyles((theme: Theme) => ({
   },
 }));
 
-/**
- * Todo: Milvus V2.0.0 Memory data is not ready for now, open it after Milvus ready.
- * @returns
- */
 const SystemView: any = () => {
   useNavigationHook(ALL_ROUTER_TYPES.SYSTEM);
   // const { t } = useTranslation('systemView');
@@ -77,6 +68,7 @@ const SystemView: any = () => {
   }>({ nodes: [], childNodes: [], system: {} });
   const [selectedNode, setNode] = useState<any>();
   const [selectedCord, setCord] = useState<any>();
+  const [showChildView, setShowChildView] = useState(false);
   const { nodes, childNodes } = data;
 
   useInterval(async () => {
@@ -101,20 +93,25 @@ const SystemView: any = () => {
   return (
     <div className={classes.root}>
       <div className={classes.contentContainer}>
-        <Topo
-          nodes={nodes}
-          childNodes={childNodes}
-          setNode={setNode}
-          setCord={setCord}
-        />
-        <DataCard node={selectedNode} extend />
+        <div className={classes.left}>
+          <Topo
+            nodes={nodes}
+            childNodes={childNodes}
+            setNode={setNode}
+            setCord={setCord}
+            setShowChildView={setShowChildView}
+          />
+        </div>
+        <div className={classes.right}>
+          <DataCard node={selectedNode} extend={true} />
+        </div>
       </div>
 
       <div
         ref={childView}
         className={clsx(
           classes.childView,
-          selectedCord ? classes.showChildView : classes.hideChildView
+          showChildView ? classes.showChildView : classes.hideChildView
         )}
       >
         {selectedCord && (
@@ -122,6 +119,7 @@ const SystemView: any = () => {
             selectedCord={selectedCord}
             childNodes={childNodes}
             setCord={setCord}
+            setShowChildView={setShowChildView}
           />
         )}
       </div>

+ 10 - 9
client/src/pages/system/Topology.tsx

@@ -126,7 +126,7 @@ const setSelected = (el: any) => {
 const Topo = (props: any) => {
   const classes = getStyles();
   const theme = useTheme();
-  const { nodes, setNode, setCord } = props;
+  const { nodes, setNode, setCord, setShowChildView } = props;
 
   useEffect(() => {
     const center = document.getElementById('center');
@@ -144,15 +144,15 @@ const Topo = (props: any) => {
 
   const WIDTH = 800; // width for svg
   const HEIGHT = 600; // height for svg
-  const LINE1 = 160; // line lenght from lv1 node
-  const LINE2 = 270; // line lenght from lv2 node
-  const ANGLE2 = 10; // angle offset for lv2 node
-  const R1 = 68; // root node radius
+  const LINE1 = 180; // line lenght from lv1 node
+  const LINE2 = 290; // line lenght from lv2 node
+  const ANGLE2 = 20; // angle offset for lv2 node
+  const R1 = 78; // root node radius
   const R2 = 45; // lv1 node radius
   const R3 = 30; // lv2 node radius
   const LIMIT = 10; // limit to show lv1 node
   const BOUNDARY_ANGLE = 45; // boundary angle
-  const START_DRAW_Y = HEIGHT / 4; // where we start to draw y axis
+  const START_DRAW_Y = HEIGHT / 3; // where we start to draw y axis
   const START_DRAW_X = WIDTH / 2; // where we start to draw x axis
 
   let steps = 0; // angle step to avoid graph out of boundary
@@ -168,7 +168,7 @@ const Topo = (props: any) => {
       >
         <rect width="100%" height="100%" fill="white" />
         {nodes.map((node: any, index: number) => {
-          if (node?.infos?.type?.toLowerCase() === 'rootcoord') {
+          if (node?.infos?.type?.toLowerCase() === 'proxy') {
             centerNode = node;
             return null;
           }
@@ -405,6 +405,7 @@ const Topo = (props: any) => {
                       className={classes.subChild}
                       onClick={() => {
                         setCord(node);
+                        setShowChildView(true);
                       }}
                     >
                       <circle
@@ -543,11 +544,11 @@ const Topo = (props: any) => {
             alignmentBaseline="middle"
             fill={theme.palette.primary.main}
             fontWeight="700"
-            fontSize="24"
+            fontSize="20"
             x={`${START_DRAW_X}`}
             y={`${START_DRAW_Y}`}
           >
-            Milvus
+            Milvus Proxy
           </text>
         </g>
       </svg>

+ 5 - 0
client/src/pages/system/Types.ts

@@ -8,9 +8,12 @@ export interface Node {
     created_time: string,
     updated_time: string,
     system_configurations: any,
+    type: string,
   },
   connected: {
     connected_identifier: number,
+    target_type: string,
+    type: string,
   }[],
   identifier: number,
 }
@@ -65,10 +68,12 @@ export interface MiniTopoProps {
   selectedCord: Node,
   selectedChildNode: Node | undefined,
   setCord: SetCord,
+  setShowChildView: (arg1: boolean) => void,
 }
 
 export interface NodeListViewProps {
   selectedCord: Node,
   childNodes: Node[],
   setCord: SetCord,
+  setShowChildView: (arg1: boolean) => void,
 }

+ 2 - 1
client/src/utils/Format.ts

@@ -138,7 +138,7 @@ export const formatPrometheusAddress = (address: string): string => {
 export const formatByteSize = (
   size: number,
   capacityTrans: { [key in string]: string }
-): { value: string; unit: string; power: number } => {
+) => {
   const power = Math.round(Math.log(size) / Math.log(1024));
   let unit = '';
   switch (power) {
@@ -166,6 +166,7 @@ export const formatByteSize = (
     value: byteValue.toFixed(2),
     unit,
     power,
+    originValue: size,
   };
 };
 

+ 11 - 1
client/src/utils/Metric.ts

@@ -19,6 +19,13 @@ export const parseJson = (jsonData: any) => {
 
   const allNodes = jsonData?.response?.nodes_info;
 
+  console.log(workingNodes,
+    // workingNodes.map((d: any) => ({
+    //   name: d.infos.name,
+    //   ip: d.infos.hardware_infos.ip,
+    // }))
+  );
+
   workingNodes.forEach((node: any) => {
     const type = node?.infos?.type;
     if (node.connected) {
@@ -29,7 +36,10 @@ export const parseJson = (jsonData: any) => {
       );
     }
     // coordinator node
-    if (type?.toLowerCase().includes('coord')) {
+    if (
+      type?.toLowerCase().includes('coord') ||
+      type?.toLowerCase().includes('proxy')
+    ) {
       nodes.push(node);
       // other nodes
     } else {

+ 4 - 37
client/yarn.lock

@@ -321,7 +321,7 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.22.5"
 
-"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
   version "7.20.1"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
   integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==
@@ -873,27 +873,6 @@
     prop-types "^15.7.2"
     react-is "^16.8.0 || ^17.0.0"
 
-"@material-ui/utils@^5.0.0-beta.4":
-  version "5.0.0-beta.5"
-  resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-5.0.0-beta.5.tgz#de492037e1f1f0910fda32e6f11b66dfcde2a1c2"
-  integrity sha512-wtJ3ovXWZdTAz5eLBqvMpYH/IBJb3qMQbGCyL1i00+sf7AUlAuv4QLx+QtX/siA6L7IpxUQVfqpoCpQH1eYRpQ==
-  dependencies:
-    "@babel/runtime" "^7.14.8"
-    "@types/prop-types" "^15.7.4"
-    "@types/react-is" "^16.7.1 || ^17.0.0"
-    prop-types "^15.7.2"
-    react-is "^17.0.2"
-
-"@mui/x-data-grid@^4.0.0":
-  version "4.0.2"
-  resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-4.0.2.tgz#5345e74630dff2efcb9a1efa04c6c8facfd8c80a"
-  integrity sha512-8FSupNcHgq4tu+27hxal1EK2r/3WeBYuMT++RXkOebm8XW1EmY+RVW6Gz/YSb6dpEyoTJH6gbHzAA/VrajdIXQ==
-  dependencies:
-    "@material-ui/utils" "^5.0.0-beta.4"
-    clsx "^1.1.1"
-    prop-types "^15.7.2"
-    reselect "^4.0.0"
-
 "@remix-run/router@1.16.1":
   version "1.16.1"
   resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.16.1.tgz#73db3c48b975eeb06d0006481bde4f5f2d17d1cd"
@@ -1459,7 +1438,7 @@
   dependencies:
     "@types/node" "*"
 
-"@types/prop-types@*", "@types/prop-types@^15.7.4":
+"@types/prop-types@*":
   version "15.7.4"
   resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
   integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
@@ -1478,13 +1457,6 @@
   dependencies:
     "@types/react" "*"
 
-"@types/react-is@^16.7.1 || ^17.0.0":
-  version "17.0.3"
-  resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a"
-  integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==
-  dependencies:
-    "@types/react" "*"
-
 "@types/react-router-dom@^5.3.3":
   version "5.3.3"
   resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
@@ -1919,7 +1891,7 @@ cliui@^7.0.2:
     strip-ansi "^6.0.0"
     wrap-ansi "^7.0.0"
 
-clsx@^1.0.2, clsx@^1.0.4, clsx@^1.1.1:
+clsx@^1.0.2, clsx@^1.0.4:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
   integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
@@ -3951,7 +3923,7 @@ react-is@^16.7.0, react-is@^16.8.1:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 
-"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2:
+"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1:
   version "17.0.2"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
   integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
@@ -4060,11 +4032,6 @@ requires-port@^1.0.0:
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
   integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
 
-reselect@^4.0.0:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.2.tgz#7bf642992d143d4f3b0f2dca8aa52018808a1d51"
-  integrity sha512-wg60ebcPOtxcptIUfrr7Jt3h4BR86cCW3R7y4qt65lnNb4yz4QgrXcbSioVsIOYguyz42+XTHIyJ5TEruzkFgQ==
-
 resolve-from@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"