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