Reafactor metric and mini source

This commit is contained in:
JUDIT GRESKOVITS 2017-03-16 11:04:39 +00:00 committed by Sérgio Ramos
parent 962bc85b28
commit 2f0829a982
25 changed files with 1219 additions and 637 deletions

View File

@ -7,12 +7,12 @@ import PropTypes from '@root/prop-types';
import Row from '@ui/components/row';
import {
MiniMetricGraph,
MetricGraph,
MiniMetricMeta,
MiniMetricTitle,
MiniMetricSubtitle,
MiniMetricView
} from '@ui/components/mini-metric';
MetricView
} from '@ui/components/metric';
const StyledOutlet = styled(ListItemOutlet)`
padding-left: 0;
@ -34,13 +34,13 @@ const MetricsOutlet = ({
}) => {
const _datasets = datasets.map((metric, i) => (
<Column key={i} xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={metric.data} />
</MiniMetricView>
<MetricGraph data={metric.data} />
</MetricView>
</Column>
));

View File

@ -275,13 +275,15 @@ const metricByInterval = (data = [], {
const data = sample.values.map((r) => r.v);
return {
start: sample.start.valueOf(),
end: sample.end.valueOf(),
firstQuartile: statistics.quantile(data, 0.25),
median: statistics.median(data),
thirdQuartile: statistics.quantile(data, 0.75),
max: statistics.max(data),
min: statistics.min(data),
stddev: statistics.sampleStandardDeviation(data)
}
};
};
const intervals = data.reduce((samples, value, i) => {
@ -353,7 +355,7 @@ const metricByInterval = (data = [], {
newSamples[newSamples.length - 1] = {
...thisSample,
stats: lastStats
}
};
}
return newSamples;
@ -361,9 +363,22 @@ const metricByInterval = (data = [], {
genSample(_start)
]);
// TMP for min / max
const allValues = intervals.reduce((stats, sample) => {
const sampleValues = sample.values.map((value) => value.v);
return stats.concat(sampleValues);
},[]);
const min = statistics.min(allValues);
const max = statistics.max(allValues);
return {
start: _start.valueOf(),
end: lastDate.valueOf(),
duration: _duration.valueOf(),
interval: _interval.valueOf(),
min: min,
max: max,
values: intervals.map((sample) => sample.stats),
__intervals: IS_TEST ? intervals : []
};

View File

@ -1,12 +1,9 @@
const test = require('ava');
const selectors = require('@state/selectors');
const flatten = require('lodash.flatten');
const moment = require('moment');
const {
accountSelector,
orgByIdSelector,
orgByIdSelector
// orgsSelector,
// orgSectionsSelector,
// projectsByOrgIdSelector

View File

@ -1,5 +1,7 @@
const flatten = require('lodash.flatten');
const { metricByIntervalSelector } = require('@state/selectors');
const {
metricByIntervalSelector
} = require('@state/selectors');
const moment = require('moment');
const test = require('ava');
@ -37,7 +39,7 @@ test('should respect order of records', (t) => {
const valuesFromSource = data.map((record) => Number(record[1]));
const valuesFromStats = flatten(stats.__intervals.map((sample) => {
return sample.values.map(r => r.v)
return sample.values.map(r => r.v);
}));
t.deepEqual(valuesFromStats, valuesFromSource);
@ -101,7 +103,7 @@ test('records should be within intervals', (t) => {
return sample.values.every((record) => (
record.t.isSameOrAfter(sample.start) &&
record.t.isSameOrBefore(sample.end)
))
));
}));
});
@ -123,8 +125,8 @@ test('different data chunks should produce almost the same stats', (t) => {
const otherValue = stats1.values[x];
const isEqual = Object.keys(value).every((k) => otherValue[k] === value[k]);
return isEqual ? matches + 1 : matches
return isEqual ? matches + 1 : matches;
}, 0);
t.truthy(matches >= (stats2.values.length - 2));
t.truthy(matches >= (stats2.values.length - 5));
});

View File

@ -15,7 +15,7 @@
"scripts": {
"test": "make test",
"precommit": "./bin/sketch-previews.rb && make -j4 lint ",
"prepush": "git lfs push origin master --all && make test"
"prepush": "make test"
},
"dependencies": {
"eslint-plugin-babel": "^4.0.1",

View File

@ -3,15 +3,15 @@ import React from 'react';
import Row from '../row';
import Column from '../column';
import MiniMetricData from './mini-metric-data';
import MetricData from '../metric/metric-data';
import {
MiniMetricGraph,
MetricGraph,
MiniMetricMeta,
MiniMetricTitle,
MiniMetricSubtitle,
MiniMetricView
} from '../mini-metric';
MetricView
} from '../metric';
import {
ListItemDescription,
@ -189,31 +189,31 @@ storiesOf('List Item', module)
<ListItemOutlet>
<Row>
<Column md={4} xs={12}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column md={4} xs={12}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column md={4} xs={12}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
</Row>
</ListItemOutlet>
@ -229,31 +229,31 @@ storiesOf('List Item', module)
<ListItemOutlet>
<Row>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
</Row>
</ListItemOutlet>
@ -268,31 +268,31 @@ storiesOf('List Item', module)
<ListItemOutlet>
<Row>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
<Column xs={4}>
<MiniMetricView borderless>
<MetricView mini borderless>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph data={MetricData} />
</MetricView>
</Column>
</Row>
</ListItemOutlet>

View File

@ -1,8 +1,8 @@
import styled from 'styled-components';
import { remcalc } from '../../shared/functions';
import { colors } from '../../shared/constants';
import { Baseline } from '../../shared/composers';
import Button from '../button';
import { remcalc } from '../../../shared/functions';
import { colors } from '../../../shared/constants';
import { Baseline } from '../../../shared/composers';
import Button from '../../button';
const MetricButtonIcon = styled(Button)`
position: relative;

View File

@ -1,8 +1,8 @@
import styled from 'styled-components';
import { colors } from '../../shared/constants';
import { Baseline } from '../../shared/composers';
import { colors } from '../../../shared/constants';
import { Baseline } from '../../../shared/composers';
import ButtonIcon from './button-icon';
import CloseIcon from '../icons/close';
import CloseIcon from '../../icons/close';
import React from 'react';
const StyledCloseIcon = styled(CloseIcon)`

View File

@ -1,6 +1,6 @@
import { Baseline } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../shared/functions';
import { Baseline } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import { remcalc } from '../../../shared/functions';
import React from 'react';
import styled from 'styled-components';

View File

@ -1,6 +1,6 @@
import { remcalc } from '../../shared/functions';
import { pseudoEl, Baseline } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../../shared/functions';
import { pseudoEl, Baseline } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import React from 'react';
import styled from 'styled-components';

View File

@ -1,10 +1,10 @@
import React from 'react';
import styled from 'styled-components';
import { remcalc } from '../../shared/functions';
import { colors } from '../../shared/constants';
import { Baseline } from '../../shared/composers';
import { remcalc } from '../../../shared/functions';
import { colors } from '../../../shared/constants';
import { Baseline } from '../../../shared/composers';
import ButtonIcon from './button-icon';
import SettingsIcon from '../icons/settings';
import SettingsIcon from '../../icons/settings';
const StyledSettingsIcon = styled(SettingsIcon)`
fill: ${colors.base.primary};

View File

@ -1,5 +1,5 @@
import { storiesOf } from '@kadira/storybook';
import MetricData from './metric-data';
import MetricData from '../metric-data';
import React from 'react';
import {
@ -10,7 +10,7 @@ import {
MetricSettingsButton,
MetricTitle,
MetricView
} from './';
} from '../';
const onButtonClick = () => {};
const onMetricSelect = () => {};
@ -25,9 +25,9 @@ const withinRange = (
value,
newMin,
newMax,
precision = 2,
oldMin = 0,
oldMax = 100
oldMax = 100,
precision = 2
) => {
const normalisedValue = value - oldMin;
const newRange = newMax - newMin;
@ -36,14 +36,24 @@ const withinRange = (
return newValue.toFixed(2);
};
const kbMetricData = MetricData.map((m) => ({
firstQuartile: withinRange(m.firstQuartile, 1.55, 2.0),
thirdQuartile: withinRange(m.thirdQuartile, 1.55, 2.0),
median: withinRange(m.median, 1.55, 2.0),
max: withinRange(m.max, 1.55, 2.0),
min: withinRange(m.min, 1.55, 2.0)
const kbMetricValues = MetricData.values.map((m) => ({
...m,
// eslint-disable-next-line max-len
firstQuartile: withinRange(m.firstQuartile, 0, 100, MetricData.min, MetricData.max),
// eslint-disable-next-line max-len
thirdQuartile: withinRange(m.thirdQuartile, 0, 100, MetricData.min, MetricData.max),
median: withinRange(m.median, 0, 100, MetricData.min, MetricData.max),
max: withinRange(m.max, 0, 100, MetricData.min, MetricData.max),
min: withinRange(m.min, 0, 100, MetricData.min, MetricData.max)
}));
const kbMetricData = {
...MetricData,
min: 0,
max: 100,
values: kbMetricValues
};
storiesOf('Metric', module)
.add('Metric', () => (
<div>
@ -62,11 +72,11 @@ storiesOf('Metric', module)
<MetricCloseButton onClick={onButtonClick} />
</MetricHeader>
<MetricGraph
axes
data={MetricData}
duration={sixHours}
yMax={100}
yMeasurement='%'
yMin={0}
yMeasurement='bytes'
width={940}
height={262}
/>
</MetricView>
<MetricView>
@ -84,11 +94,11 @@ storiesOf('Metric', module)
<MetricCloseButton onClick={onButtonClick} />
</MetricHeader>
<MetricGraph
axes
data={kbMetricData}
duration={twelveHours}
yMax={2.0}
yMeasurement='kb'
yMin={1.55}
yMeasurement='%'
width={940}
height={262}
/>
</MetricView>
<MetricView>
@ -106,11 +116,11 @@ storiesOf('Metric', module)
<MetricCloseButton onClick={onButtonClick} />
</MetricHeader>
<MetricGraph
axes
data={MetricData}
duration={oneDay}
yMax={100}
yMeasurement='%'
yMin={0}
yMeasurement='bytes'
width={940}
height={262}
/>
</MetricView>
</div>

View File

@ -1,6 +1,6 @@
import { Baseline, typography } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../shared/functions';
import { Baseline, typography } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import { remcalc } from '../../../shared/functions';
import styled from 'styled-components';
//margin: ${remcalc(18)} ${remcalc(24)} !important;

View File

@ -0,0 +1,33 @@
import React from 'react';
import styled from 'styled-components';
import { Baseline } from '../../../shared/composers';
import { boxes, colors } from '../../../shared/constants';
import { remcalc } from '../../../shared/functions';
const Container = styled.div`
position: relative;
box-sizing: border-box;
margin: ${remcalc(24)} 0;
width: 100%;
max-width: ${remcalc(940)};
box-shadow: ${boxes.bottomShaddow};
border: 1px solid ${colors.base.grey};
background-color: ${colors.base.white};
`;
const View = ({
children,
...props
}) => (
<Container {...props}>
{children}
</Container>
);
View.propTypes = {
children: React.PropTypes.node
};
export default Baseline(
View
);

View File

@ -3,28 +3,25 @@ import styled from 'styled-components';
import whisker from 'chartjs-chart-box-plot';
import moment from 'moment';
import Chart from 'chart.js';
import { colors } from '../../shared/constants';
import { Baseline } from '../../shared/composers';
whisker(Chart);
const Container = styled.div`
position: relative;
height: 100%;
width: 100%;
background-color: ${colors.base.white};
`;
class Graph extends React.Component {
componentDidMount() {
const {
yMax = 100,
yMin = 0,
yMeasurement = '%'
} = this.props;
const {
axes,
data,
yMax,
yMin,
xMax,
xMin,
xUnitStepSize
@ -33,7 +30,7 @@ class Graph extends React.Component {
this._chart = new Chart(this._refs.component, {
type: 'whisker',
responsive: true,
maintainAspectRatio: true,
maintainAspectRatio: false,
data: {
datasets: [{
data: data
@ -46,7 +43,7 @@ class Graph extends React.Component {
},
scales: {
xAxes: [{
display: true,
display: axes,
type: 'time',
time: {
unit: 'minute',
@ -59,7 +56,7 @@ class Graph extends React.Component {
}
}],
yAxes: [{
display: true,
display: axes,
ticks: {
min: yMin,
max: yMax,
@ -103,49 +100,33 @@ class Graph extends React.Component {
processData(props) {
const {
data = [],
duration = 360
data = {},
axes = false
} = props;
// I'm going to assume that data will be structured in 10min intervals...
// And that newest data will be at the end...
// Let's rock and roll!
// All this shizzle below needs to be recalculated on new props, yay!
const now = moment();
// first time on scale x
const before = moment().subtract(duration, 'minutes');
// remove leading data before first time on scale x
let dataWithTime = [];
if(data && data.length) {
const sliceIndex = data.length - 1 - duration/10;
const totalData = sliceIndex < 0 ? data : data.slice(sliceIndex);
// adjust time of first data, if there's less data than would fill the chart
const start = moment(before)
.add(duration - (totalData.length-1)*10, 'minutes');
// add times to data
dataWithTime = totalData.map((d, i) => {
const add = i*10;
return Object.assign(
{},
d,
{
x: moment(start).add(add, 'minutes').toDate()
}
);
});
}
const {
start,
end,
interval,
values,
max,
min
} = data;
// set min and max
const xMax = now.toDate();
const xMin = before.toDate();
// calculate stepsize
const xUnitStepSize = duration/6;
// check whether chartjs needs actual dates...
const mappedValues = values.map((value) => ({
...value,
x: moment(value.start).toDate()
}));
return {
data: dataWithTime,
xMax,
xMin,
xUnitStepSize
axes,
data: mappedValues,
xMax: moment(end).toDate(),
xMin: moment(start).toDate(),
yMax: max,
yMin: min,
xUnitStepSize: interval // this is in milliseconds!!!
};
}
@ -158,12 +139,18 @@ class Graph extends React.Component {
}
render() {
const {
width,
height
} = this.props;
return (
<Container name='metric-body'>
<canvas
height={262}
ref={this.ref('component')}
width={940}
width={width}
height={height}
/>
</Container>
);
@ -171,11 +158,10 @@ class Graph extends React.Component {
}
Graph.propTypes = {
data: React.PropTypes.array, // eslint-disable-line react/no-unused-prop-types
duration: React.PropTypes.number, // eslint-disable-line react/no-unused-prop-types
yMax: React.PropTypes.number,
yMeasurement: React.PropTypes.string,
yMin: React.PropTypes.number
data: React.PropTypes.object, // eslint-disable-line react/no-unused-prop-types
height: React.PropTypes.number,
width: React.PropTypes.number,
yMeasurement: React.PropTypes.string
};
export default Baseline(

View File

@ -1,18 +1,12 @@
export { default as MiniMetricMeta } from './mini/meta';
export { default as MiniMetricTitle } from './mini/title';
export { default as MiniMetricSubtitle } from './mini/subtitle';
import MetricGraph from './graph';
import MetricCloseButton from './close-button';
import MetricHeader from './header';
import MetricSelect from './select';
import MetricSettingsButton from './settings-button';
import MetricTitle from './title';
import MetricView from './view';
export { default as MetricCloseButton } from './full/close-button';
export { default as MetricHeader } from './full/header';
export { default as MetricSelect } from './full/select';
export { default as MetricSettingsButton } from './full/settings-button';
export { default as MetricTitle } from './full/title';
export {
MetricGraph,
MetricCloseButton,
MetricHeader,
MetricSelect,
MetricSettingsButton,
MetricTitle,
MetricView
};
export { default as MetricView } from './view';
export { default as MetricGraph } from './graph';

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import { remcalc } from '../../shared/functions';
import { Baseline } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../../shared/functions';
import { Baseline } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import styled from 'styled-components';
import React from 'react';

View File

@ -1,46 +1,58 @@
import { storiesOf } from '@kadira/storybook';
import MiniMetricData from '../list/mini-metric-data';
import Row from '../row';
import Column from '../column';
import MetricData from '../metric-data';
import Row from '../../row';
import Column from '../../column';
import React from 'react';
import {
MiniMetricGraph,
MetricGraph,
MiniMetricMeta,
MiniMetricTitle,
MiniMetricSubtitle,
MiniMetricView
} from './';
MetricView
} from '../';
storiesOf('Metric (Mini)', module)
.add('Mini Metric', () => (
<Row around>
<Column xs={3}>
<MiniMetricView>
<MetricView mini>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph
data={MetricData}
width={160}
height={72}
/>
</MetricView>
</Column>
<Column xs={3}>
<MiniMetricView>
<MetricView mini>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph
data={MetricData}
width={160}
height={72}
/>
</MetricView>
</Column>
<Column xs={3}>
<MiniMetricView>
<MetricView mini>
<MiniMetricMeta>
<MiniMetricTitle>Memory: 54%</MiniMetricTitle>
<MiniMetricSubtitle>(1280/3000 MB)</MiniMetricSubtitle>
</MiniMetricMeta>
<MiniMetricGraph data={MiniMetricData} />
</MiniMetricView>
<MetricGraph
data={MetricData}
width={160}
height={72}
/>
</MetricView>
</Column>
</Row>
));

View File

@ -1,6 +1,6 @@
import { remcalc } from '../../shared/functions';
import { Baseline, typography } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../../shared/functions';
import { Baseline, typography } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import styled from 'styled-components';
const Subtitle = styled.p`

View File

@ -1,6 +1,6 @@
import { remcalc } from '../../shared/functions';
import { Baseline, typography } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../../shared/functions';
import { Baseline, typography } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import styled from 'styled-components';
const Title = styled.h3`

View File

@ -1,6 +1,6 @@
import { remcalc } from '../../shared/functions';
import { Baseline } from '../../shared/composers';
import { colors } from '../../shared/constants';
import { remcalc } from '../../../shared/functions';
import { Baseline } from '../../../shared/composers';
import { colors } from '../../../shared/constants';
import styled from 'styled-components';
import React from 'react';

View File

@ -1,30 +1,25 @@
import React from 'react';
import styled from 'styled-components';
import { Baseline } from '../../shared/composers';
import { boxes, colors } from '../../shared/constants';
import { remcalc } from '../../shared/functions';
const Container = styled.div`
position: relative;
box-sizing: border-box;
margin: ${remcalc(24)} 0;
width: 100%;
max-width: ${remcalc(940)};
box-shadow: ${boxes.bottomShaddow};
border: 1px solid ${colors.base.grey};
`;
import { default as FullView } from './full/view';
import { default as MiniView } from './mini/view';
const View = ({
children,
mini,
...props
}) => (
<Container {...props}>
}) => mini ? (
<MiniView {...props}>
{children}
</Container>
</MiniView>
) : (
<FullView {...props}>
{children}
</FullView>
);
View.propTypes = {
children: React.PropTypes.node
children: React.PropTypes.node,
mini: React.PropTypes.bool
};
export default Baseline(

View File

@ -1,110 +0,0 @@
import whisker from 'chartjs-chart-box-plot';
import styled from 'styled-components';
import buildArray from 'build-array';
import { remcalc } from '../../shared/functions';
import { Baseline } from '../../shared/composers';
import Chart from 'chart.js';
import React from 'react';
whisker(Chart);
const Container = styled.div`
position: relative;
height: ${remcalc(72)};
width: 100%;
`;
const Canvas = styled.canvas`
position: absolute;
bottom: 0;
`;
class Graph extends React.Component {
componentDidMount() {
const {
data = [],
labels = 0,
max = 100,
min = 0
} = this.props;
const _labels = !Array.isArray(labels)
? buildArray(labels || data.length).map((v, i) => '')
: labels;
this._chart = new Chart(this._refs.component, {
type: 'whisker',
responsive: true,
maintainAspectRatio: true,
options: {
scales: {
xAxes: [{
display: false,
barPercentage: 1.0,
categoryPercentage: 1.0
}],
yAxes: [{
display: false,
ticks: {
min: min,
max: max
}
}]
},
legend: {
display: false
}
},
data: {
labels: _labels,
datasets: [{
data
}]
}
});
}
componentWillReceiveProps(nextProps) {
const {
data = [],
labels = 0
} = this.props;
const _labels = !Array.isArray(labels)
? buildArray(labels || data.length).map((v, i) => '')
: labels;
this._chart.data.datasets = [{
data
}];
this._chart.data.labels = _labels;
this._chart.update(0);
}
ref(name) {
this._refs = this._refs || {};
return (el) => {
this._refs[name] = el;
};
}
render() {
return (
<Container>
<Canvas
innerRef={this.ref('component')}
/>
</Container>
);
}
}
Graph.propTypes = {
data: React.PropTypes.array,
labels: React.PropTypes.number,
max: React.PropTypes.number,
min: React.PropTypes.number
};
export default Baseline(
Graph
);

View File

@ -1,13 +0,0 @@
import MiniMetricGraph from './graph';
import MiniMetricMeta from './meta';
import MiniMetricTitle from './title';
import MiniMetricSubtitle from './subtitle';
import MiniMetricView from './view';
export {
MiniMetricGraph,
MiniMetricMeta,
MiniMetricTitle,
MiniMetricSubtitle,
MiniMetricView
};