mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-09 06:43:24 +00:00
112 lines
3.0 KiB
JavaScript
112 lines
3.0 KiB
JavaScript
import TranslatedComponent from './TranslatedComponent';
|
|
import React, { PropTypes } from 'react';
|
|
import Measure from 'react-measure';
|
|
import { BarChart, Bar, XAxis, YAxis } from 'recharts';
|
|
|
|
const CORIOLIS_COLOURS = ['#FF8C0D', '#1FB0FF', '#71A052', '#D5D54D'];
|
|
const LABEL_COLOUR = '#000000';
|
|
const AXIS_COLOUR = '#C06400';
|
|
|
|
const ASPECT = 1;
|
|
|
|
const merge = function(one, two) {
|
|
return Object.assign({}, one, two);
|
|
};
|
|
|
|
/**
|
|
* A vertical bar chart
|
|
*/
|
|
export default class VerticalBarChart extends TranslatedComponent {
|
|
|
|
static propTypes = {
|
|
data : PropTypes.array.isRequired,
|
|
yMax : PropTypes.number
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
* @param {Object} props React Component properties
|
|
* @param {Object} context React Component context
|
|
*/
|
|
constructor(props, context) {
|
|
super(props);
|
|
|
|
this._termtip = this._termtip.bind(this);
|
|
|
|
this.state = {
|
|
dimensions: {
|
|
width: 300,
|
|
height: 300
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Render the bar chart
|
|
* @returns {Object} the markup
|
|
*/
|
|
render() {
|
|
const { width, height } = this.state.dimensions;
|
|
const { tooltip, termtip } = this.context;
|
|
|
|
// Calculate maximum for Y
|
|
let dataMax = Math.max(...this.props.data.map(d => d.value));
|
|
if (dataMax == -Infinity) dataMax = 0;
|
|
let yMax = this.props.yMax ? Math.round(this.props.yMax) : 0;
|
|
const localMax = Math.max(dataMax, yMax);
|
|
|
|
return (
|
|
<Measure whitelist={['width', 'top']} onMeasure={ (dimensions) => this.setState({ dimensions }) }>
|
|
<div width='100%'>
|
|
<BarChart width={width} height={width * ASPECT} data={this.props.data} margin={{ top: 5, right: 5, left: 5, bottom: 5 }}>
|
|
<XAxis interval={0} fontSize='0.8em' stroke={AXIS_COLOUR} dataKey='label' />
|
|
<YAxis interval={'preserveStart'} tickCount={11} fontSize='0.8em' stroke={AXIS_COLOUR} type='number' domain={[0, localMax]}/>
|
|
<Bar dataKey='value' label={<ValueLabel />} fill={CORIOLIS_COLOURS[0]} isAnimationActive={false} onMouseOver={this._termtip} onMouseOut={tooltip.bind(null, null)}/>
|
|
</BarChart>
|
|
</div>
|
|
</Measure>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Generate a term tip
|
|
* @param {Object} d the data
|
|
* @param {number} i the index
|
|
* @param {Object} e the event
|
|
* @returns {Object} termtip markup
|
|
*/
|
|
_termtip(d, i, e) {
|
|
if (this.props.data[i].tooltip) {
|
|
return this.context.termtip(this.props.data[i].tooltip, e);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A label that displays the value within the bar of the chart
|
|
*/
|
|
class ValueLabel extends React.Component {
|
|
static propTypes = {
|
|
x: PropTypes.number,
|
|
y: PropTypes.number,
|
|
payload: PropTypes.object,
|
|
value: PropTypes.number
|
|
};
|
|
|
|
/**
|
|
* Render offence
|
|
* @return {React.Component} contents
|
|
*/
|
|
render() {
|
|
const { x, y, payload, value } = this.props;
|
|
|
|
const em = value < 1000 ? '1em' : value < 1000 ? '0.8em' : '0.7em';
|
|
|
|
return (
|
|
<text x={x} y={y} fill="#000000" textAnchor="middle" dy={20} style={{ fontSize: em }}>{value}</text>
|
|
);
|
|
}
|
|
};
|