github.com/anthdm/go-ethereum@v1.8.4-0.20180412101906-60516c83b011/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/styles/withStyles'; 22 import Typography from 'material-ui/Typography'; 23 import Grid from 'material-ui/Grid'; 24 import {ResponsiveContainer, AreaChart, Area, Tooltip} from 'recharts'; 25 26 import ChartRow from './ChartRow'; 27 import CustomTooltip, {bytePlotter, bytePerSecPlotter, percentPlotter, multiplier} from './CustomTooltip'; 28 import {styles as commonStyles} from '../common'; 29 import type {General, System} from '../types/content'; 30 31 const FOOTER_SYNC_ID = 'footerSyncId'; 32 33 const CPU = 'cpu'; 34 const MEMORY = 'memory'; 35 const DISK = 'disk'; 36 const TRAFFIC = 'traffic'; 37 38 const TOP = 'Top'; 39 const BOTTOM = 'Bottom'; 40 41 // styles contains the constant styles of the component. 42 const styles = { 43 footer: { 44 maxWidth: '100%', 45 flexWrap: 'nowrap', 46 margin: 0, 47 }, 48 chartRowWrapper: { 49 height: '100%', 50 padding: 0, 51 }, 52 doubleChartWrapper: { 53 height: '100%', 54 width: '99%', 55 }, 56 }; 57 58 // themeStyles returns the styles generated from the theme for the component. 59 const themeStyles: Object = (theme: Object) => ({ 60 footer: { 61 backgroundColor: theme.palette.grey[900], 62 color: theme.palette.getContrastText(theme.palette.grey[900]), 63 zIndex: theme.zIndex.appBar, 64 height: theme.spacing.unit * 10, 65 }, 66 }); 67 68 export type Props = { 69 classes: Object, // injected by withStyles() 70 theme: Object, 71 general: General, 72 system: System, 73 shouldUpdate: Object, 74 }; 75 76 // Footer renders the footer of the dashboard. 77 class Footer extends Component<Props> { 78 shouldComponentUpdate(nextProps) { 79 return typeof nextProps.shouldUpdate.general !== 'undefined' || typeof nextProps.shouldUpdate.system !== 'undefined'; 80 } 81 82 // halfHeightChart renders an area chart with half of the height of its parent. 83 halfHeightChart = (chartProps, tooltip, areaProps) => ( 84 <ResponsiveContainer width='100%' height='50%'> 85 <AreaChart {...chartProps} > 86 {!tooltip || (<Tooltip cursor={false} content={<CustomTooltip tooltip={tooltip} />} />)} 87 <Area isAnimationActive={false} type='monotone' {...areaProps} /> 88 </AreaChart> 89 </ResponsiveContainer> 90 ); 91 92 // doubleChart renders a pair of charts separated by the baseline. 93 doubleChart = (syncId, chartKey, topChart, bottomChart) => { 94 if (!Array.isArray(topChart.data) || !Array.isArray(bottomChart.data)) { 95 return null; 96 } 97 const topDefault = topChart.default || 0; 98 const bottomDefault = bottomChart.default || 0; 99 const topKey = `${chartKey}${TOP}`; 100 const bottomKey = `${chartKey}${BOTTOM}`; 101 const topColor = '#8884d8'; 102 const bottomColor = '#82ca9d'; 103 104 return ( 105 <div style={styles.doubleChartWrapper}> 106 {this.halfHeightChart( 107 { 108 syncId, 109 data: topChart.data.map(({value}) => ({[topKey]: value || topDefault})), 110 margin: {top: 5, right: 5, bottom: 0, left: 5}, 111 }, 112 topChart.tooltip, 113 {dataKey: topKey, stroke: topColor, fill: topColor}, 114 )} 115 {this.halfHeightChart( 116 { 117 syncId, 118 data: bottomChart.data.map(({value}) => ({[bottomKey]: -value || -bottomDefault})), 119 margin: {top: 0, right: 5, bottom: 5, left: 5}, 120 }, 121 bottomChart.tooltip, 122 {dataKey: bottomKey, stroke: bottomColor, fill: bottomColor}, 123 )} 124 </div> 125 ); 126 }; 127 128 render() { 129 const {general, system} = this.props; 130 131 return ( 132 <Grid container className={this.props.classes.footer} direction='row' alignItems='center' style={styles.footer}> 133 <Grid item xs style={styles.chartRowWrapper}> 134 <ChartRow> 135 {this.doubleChart( 136 FOOTER_SYNC_ID, 137 CPU, 138 {data: system.processCPU, tooltip: percentPlotter('Process load')}, 139 {data: system.systemCPU, tooltip: percentPlotter('System load', multiplier(-1))}, 140 )} 141 {this.doubleChart( 142 FOOTER_SYNC_ID, 143 MEMORY, 144 {data: system.activeMemory, tooltip: bytePlotter('Active memory')}, 145 {data: system.virtualMemory, tooltip: bytePlotter('Virtual memory', multiplier(-1))}, 146 )} 147 {this.doubleChart( 148 FOOTER_SYNC_ID, 149 DISK, 150 {data: system.diskRead, tooltip: bytePerSecPlotter('Disk read')}, 151 {data: system.diskWrite, tooltip: bytePerSecPlotter('Disk write', multiplier(-1))}, 152 )} 153 {this.doubleChart( 154 FOOTER_SYNC_ID, 155 TRAFFIC, 156 {data: system.networkIngress, tooltip: bytePerSecPlotter('Download')}, 157 {data: system.networkEgress, tooltip: bytePerSecPlotter('Upload', multiplier(-1))}, 158 )} 159 </ChartRow> 160 </Grid> 161 <Grid item > 162 <Typography type='caption' color='inherit'> 163 <span style={commonStyles.light}>Geth</span> {general.version} 164 </Typography> 165 {general.commit && ( 166 <Typography type='caption' color='inherit'> 167 <span style={commonStyles.light}>{'Commit '}</span> 168 <a href={`https://github.com/ethereum/go-ethereum/commit/${general.commit}`} target='_blank' style={{color: 'inherit', textDecoration: 'none'}} > 169 {general.commit.substring(0, 8)} 170 </a> 171 </Typography> 172 )} 173 </Grid> 174 </Grid> 175 ); 176 } 177 } 178 179 export default withStyles(themeStyles)(Footer);