github.com/isti4github/eth-ecc@v0.0.0-20201227085832-c337f2d99319/dashboard/assets/components/Footer.jsx (about) 1 // @flow 2 3 // Copyright 2017 The go-ethereum Authors 4 // This file is part of the go-ethereum library. 5 // 6 // The go-ethereum library is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU Lesser General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // The go-ethereum library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU Lesser General Public License for more details. 15 // 16 // You should have received a copy of the GNU Lesser General Public License 17 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 18 19 import React, {Component} from 'react'; 20 21 import withStyles from '@material-ui/core/styles/withStyles'; 22 import Typography from '@material-ui/core/Typography'; 23 import Grid from '@material-ui/core/Grid'; 24 import ResponsiveContainer from 'recharts/es6/component/ResponsiveContainer'; 25 import AreaChart from 'recharts/es6/chart/AreaChart'; 26 import Area from 'recharts/es6/cartesian/Area'; 27 import ReferenceLine from 'recharts/es6/cartesian/ReferenceLine'; 28 import Label from 'recharts/es6/component/Label'; 29 import Tooltip from 'recharts/es6/component/Tooltip'; 30 31 import ChartRow from 'ChartRow'; 32 import CustomTooltip, {bytePlotter, bytePerSecPlotter, percentPlotter, multiplier} from 'CustomTooltip'; 33 import {chartStrokeWidth, styles as commonStyles} from '../common'; 34 import type {General, System} from '../types/content'; 35 36 const FOOTER_SYNC_ID = 'footerSyncId'; 37 38 const CPU = 'cpu'; 39 const MEMORY = 'memory'; 40 const DISK = 'disk'; 41 const TRAFFIC = 'traffic'; 42 43 const TOP = 'Top'; 44 const BOTTOM = 'Bottom'; 45 46 const cpuLabelTop = 'Process load'; 47 const cpuLabelBottom = 'System load'; 48 const memoryLabelTop = 'Active memory'; 49 const memoryLabelBottom = 'Virtual memory'; 50 const diskLabelTop = 'Disk read'; 51 const diskLabelBottom = 'Disk write'; 52 const trafficLabelTop = 'Download'; 53 const trafficLabelBottom = 'Upload'; 54 55 // styles contains the constant styles of the component. 56 const styles = { 57 footer: { 58 maxWidth: '100%', 59 flexWrap: 'nowrap', 60 margin: 0, 61 }, 62 chartRowWrapper: { 63 height: '100%', 64 padding: 0, 65 }, 66 doubleChartWrapper: { 67 height: '100%', 68 width: '99%', 69 }, 70 link: { 71 color: 'inherit', 72 textDecoration: 'none', 73 }, 74 }; 75 76 // themeStyles returns the styles generated from the theme for the component. 77 const themeStyles: Object = (theme: Object) => ({ 78 footer: { 79 backgroundColor: theme.palette.grey[900], 80 color: theme.palette.getContrastText(theme.palette.grey[900]), 81 zIndex: theme.zIndex.appBar, 82 height: theme.spacing.unit * 10, 83 }, 84 }); 85 86 export type Props = { 87 classes: Object, // injected by withStyles() 88 theme: Object, 89 general: General, 90 system: System, 91 shouldUpdate: Object, 92 }; 93 94 type State = {}; 95 96 // Footer renders the footer of the dashboard. 97 class Footer extends Component<Props, State> { 98 shouldComponentUpdate(nextProps: Readonly<Props>, nextState: Readonly<State>, nextContext: any) { 99 return typeof nextProps.shouldUpdate.general !== 'undefined' || typeof nextProps.shouldUpdate.system !== 'undefined'; 100 } 101 102 // halfHeightChart renders an area chart with half of the height of its parent. 103 halfHeightChart = (chartProps, tooltip, areaProps, label, position) => ( 104 <ResponsiveContainer width='100%' height='50%'> 105 <AreaChart {...chartProps}> 106 {!tooltip || (<Tooltip cursor={false} content={<CustomTooltip tooltip={tooltip} />} />)} 107 <Area isAnimationActive={false} strokeWidth={chartStrokeWidth} type='monotone' {...areaProps} /> 108 <ReferenceLine x={0} strokeWidth={0}> 109 <Label fill={areaProps.fill} value={label} position={position} /> 110 </ReferenceLine> 111 </AreaChart> 112 </ResponsiveContainer> 113 ); 114 115 // doubleChart renders a pair of charts separated by the baseline. 116 doubleChart = (syncId, chartKey, topChart, bottomChart) => { 117 if (!Array.isArray(topChart.data) || !Array.isArray(bottomChart.data)) { 118 return null; 119 } 120 const topDefault = topChart.default || 0; 121 const bottomDefault = bottomChart.default || 0; 122 const topKey = `${chartKey}${TOP}`; 123 const bottomKey = `${chartKey}${BOTTOM}`; 124 const topColor = '#8884d8'; 125 const bottomColor = '#82ca9d'; 126 127 return ( 128 <div style={styles.doubleChartWrapper}> 129 {this.halfHeightChart( 130 { 131 syncId, 132 data: topChart.data.map(({value}) => ({[topKey]: value || topDefault})), 133 margin: {top: 5, right: 5, bottom: 0, left: 5}, 134 }, 135 topChart.tooltip, 136 {dataKey: topKey, stroke: topColor, fill: topColor}, 137 topChart.label, 138 'insideBottomLeft', 139 )} 140 {this.halfHeightChart( 141 { 142 syncId, 143 data: bottomChart.data.map(({value}) => ({[bottomKey]: -value || -bottomDefault})), 144 margin: {top: 0, right: 5, bottom: 5, left: 5}, 145 }, 146 bottomChart.tooltip, 147 {dataKey: bottomKey, stroke: bottomColor, fill: bottomColor}, 148 bottomChart.label, 149 'insideTopLeft', 150 )} 151 </div> 152 ); 153 }; 154 155 render() { 156 const {general, system} = this.props; 157 158 return ( 159 <Grid container className={this.props.classes.footer} direction='row' alignItems='center' style={styles.footer}> 160 <Grid item xs style={styles.chartRowWrapper}> 161 <ChartRow> 162 {this.doubleChart( 163 FOOTER_SYNC_ID, 164 CPU, 165 {data: system.processCPU, tooltip: percentPlotter(cpuLabelTop), label: cpuLabelTop}, 166 {data: system.systemCPU, tooltip: percentPlotter(cpuLabelBottom, multiplier(-1)), label: cpuLabelBottom}, 167 )} 168 {this.doubleChart( 169 FOOTER_SYNC_ID, 170 MEMORY, 171 {data: system.activeMemory, tooltip: bytePlotter(memoryLabelTop), label: memoryLabelTop}, 172 {data: system.virtualMemory, tooltip: bytePlotter(memoryLabelBottom, multiplier(-1)), label: memoryLabelBottom}, 173 )} 174 {this.doubleChart( 175 FOOTER_SYNC_ID, 176 DISK, 177 {data: system.diskRead, tooltip: bytePerSecPlotter(diskLabelTop), label: diskLabelTop}, 178 {data: system.diskWrite, tooltip: bytePerSecPlotter(diskLabelBottom, multiplier(-1)), label: diskLabelBottom}, 179 )} 180 {this.doubleChart( 181 FOOTER_SYNC_ID, 182 TRAFFIC, 183 {data: system.networkIngress, tooltip: bytePerSecPlotter(trafficLabelTop), label: trafficLabelTop}, 184 {data: system.networkEgress, tooltip: bytePerSecPlotter(trafficLabelBottom, multiplier(-1)), label: trafficLabelBottom}, 185 )} 186 </ChartRow> 187 </Grid> 188 <Grid item> 189 <Typography type='caption' color='inherit'> 190 <span style={commonStyles.light}>Geth</span> {general.version} 191 </Typography> 192 {general.commit && ( 193 <Typography type='caption' color='inherit'> 194 <span style={commonStyles.light}>{'Commit '}</span> 195 <a 196 href={`https://github.com/ethereum/go-ethereum/commit/${general.commit}`} 197 target='_blank' 198 rel='noopener noreferrer' 199 style={styles.link} 200 > 201 {general.commit.substring(0, 8)} 202 </a> 203 </Typography> 204 )} 205 </Grid> 206 </Grid> 207 ); 208 } 209 } 210 211 export default withStyles(themeStyles)(Footer);