github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/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);