github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/dashboard/frontend/src/pages/Network.tsx (about) 1 import React, { FC, useState, useEffect, useCallback, useRef } from 'react' 2 import prettyBytes from 'pretty-bytes' 3 import Grid from '@mui/material/Grid' 4 import Container from '@mui/material/Container' 5 import useApi from '../hooks/useApi' 6 import useLoadingErrorHandler from '../hooks/useLoadingErrorHandler' 7 import Box from '@mui/material/Box' 8 import Card from '@mui/material/Card' 9 import CardContent from '@mui/material/CardContent' 10 import Typography from '@mui/material/Typography' 11 import { 12 NodeInfo, 13 } from '../types' 14 import { 15 getShortId, 16 } from '../utils/job' 17 import { 18 formatFloat, 19 subtractFloat, 20 } from '../utils/format' 21 22 const Network: FC = () => { 23 const [ nodeData, setNodeData ] = useState<Record<string, NodeInfo>>({}) 24 const api = useApi() 25 const loadingErrorHandler = useLoadingErrorHandler() 26 27 const loadNodeData = useCallback(async () => { 28 const handler = loadingErrorHandler(async () => { 29 const nodeData = await api.get<Record<string, NodeInfo>>('/api/v1/nodes', {}) 30 if (nodeData) { 31 setNodeData(nodeData) 32 } 33 }) 34 await handler() 35 }, []) 36 37 38 useEffect(() => { 39 loadNodeData() 40 }, []) 41 42 return ( 43 <Container maxWidth={ 'xl' } sx={{ mt: 4, mb: 4 }}> 44 <Grid container spacing={3}> 45 <Grid item xs={12}> 46 <Box sx={{ 47 display: 'inline-block', 48 }}> 49 { 50 nodeData && Object.keys(nodeData).map((nodeId, i) => { 51 const node = nodeData[nodeId] 52 return ( 53 <Card sx={{ minWidth: 200, display: 'inline-block', m: 1 }} key={ i }> 54 <CardContent> 55 <Typography variant="h5" component="div"> 56 { getShortId(node.PeerInfo.ID) } 57 </Typography> 58 <ul> 59 <li> 60 <Typography variant="body2"> 61 <span style={{minWidth: '110px', display: 'inline-block'}}>CPU Usage:</span> 62 <strong>{ subtractFloat(node.ComputeNodeInfo.MaxCapacity.CPU, node.ComputeNodeInfo.AvailableCapacity.CPU) }</strong> 63 / 64 <strong>{ formatFloat(node.ComputeNodeInfo.MaxCapacity.CPU) }</strong> 65 </Typography> 66 </li> 67 <li> 68 <Typography variant="body2"> 69 <span style={{minWidth: '110px', display: 'inline-block'}}>Memory Usage:</span> 70 <strong>{ prettyBytes(subtractFloat(node.ComputeNodeInfo.MaxCapacity.Memory, node.ComputeNodeInfo.AvailableCapacity.Memory)) }</strong> 71 / 72 <strong>{ prettyBytes(node.ComputeNodeInfo.MaxCapacity.Memory || 0) }</strong> 73 </Typography> 74 </li> 75 <li> 76 <Typography variant="body2"> 77 <span style={{minWidth: '110px', display: 'inline-block'}}>Disk Usage:</span> 78 <strong>{ prettyBytes(subtractFloat(node.ComputeNodeInfo.MaxCapacity.Disk, node.ComputeNodeInfo.AvailableCapacity.Disk)) }</strong> 79 / 80 <strong>{ prettyBytes(node.ComputeNodeInfo.MaxCapacity.Disk || 0) }</strong> 81 </Typography> 82 </li> 83 <li> 84 <Typography variant="body2"> 85 <span style={{minWidth: '110px', display: 'inline-block'}}>GPU Usage:</span> 86 <strong>{ subtractFloat(node.ComputeNodeInfo.MaxCapacity.GPU, node.ComputeNodeInfo.AvailableCapacity.GPU) }</strong> 87 / 88 <strong>{ node.ComputeNodeInfo.MaxCapacity.GPU || 0 }</strong> 89 </Typography> 90 </li> 91 <li> 92 <Typography variant="body2"> 93 <span style={{minWidth: '110px', display: 'inline-block'}}>Running Jobs:</span> 94 <strong>{ node.ComputeNodeInfo.RunningExecutions || 0 }</strong> 95 </Typography> 96 </li> 97 <li> 98 <Typography variant="body2"> 99 <span style={{minWidth: '110px', display: 'inline-block'}}>Enqueued Jobs:</span> 100 <strong>{ node.ComputeNodeInfo.EnqueuedExecutions || 0 }</strong> 101 </Typography> 102 </li> 103 </ul> 104 </CardContent> 105 </Card> 106 ) 107 }) 108 } 109 </Box> 110 </Grid> 111 </Grid> 112 </Container> 113 ) 114 } 115 116 export default Network