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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { Baseline, typography } from '../../shared/composers'; import { Baseline, typography } from '../../../shared/composers';
import { colors } from '../../shared/constants'; import { colors } from '../../../shared/constants';
import { remcalc } from '../../shared/functions'; import { remcalc } from '../../../shared/functions';
import styled from 'styled-components'; import styled from 'styled-components';
//margin: ${remcalc(18)} ${remcalc(24)} !important; //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 whisker from 'chartjs-chart-box-plot';
import moment from 'moment'; import moment from 'moment';
import Chart from 'chart.js'; import Chart from 'chart.js';
import { colors } from '../../shared/constants';
import { Baseline } from '../../shared/composers'; import { Baseline } from '../../shared/composers';
whisker(Chart); whisker(Chart);
const Container = styled.div` const Container = styled.div`
position: relative; position: relative;
height: 100%;
width: 100%;
background-color: ${colors.base.white};
`; `;
class Graph extends React.Component { class Graph extends React.Component {
componentDidMount() { componentDidMount() {
const { const {
yMax = 100,
yMin = 0,
yMeasurement = '%' yMeasurement = '%'
} = this.props; } = this.props;
const { const {
axes,
data, data,
yMax,
yMin,
xMax, xMax,
xMin, xMin,
xUnitStepSize xUnitStepSize
@ -33,7 +30,7 @@ class Graph extends React.Component {
this._chart = new Chart(this._refs.component, { this._chart = new Chart(this._refs.component, {
type: 'whisker', type: 'whisker',
responsive: true, responsive: true,
maintainAspectRatio: true, maintainAspectRatio: false,
data: { data: {
datasets: [{ datasets: [{
data: data data: data
@ -46,7 +43,7 @@ class Graph extends React.Component {
}, },
scales: { scales: {
xAxes: [{ xAxes: [{
display: true, display: axes,
type: 'time', type: 'time',
time: { time: {
unit: 'minute', unit: 'minute',
@ -59,7 +56,7 @@ class Graph extends React.Component {
} }
}], }],
yAxes: [{ yAxes: [{
display: true, display: axes,
ticks: { ticks: {
min: yMin, min: yMin,
max: yMax, max: yMax,
@ -103,49 +100,33 @@ class Graph extends React.Component {
processData(props) { processData(props) {
const { const {
data = [], data = {},
duration = 360 axes = false
} = props; } = props;
// I'm going to assume that data will be structured in 10min intervals... const {
// And that newest data will be at the end... start,
// Let's rock and roll! end,
// All this shizzle below needs to be recalculated on new props, yay! interval,
const now = moment(); values,
// first time on scale x max,
const before = moment().subtract(duration, 'minutes'); min
// remove leading data before first time on scale x } = data;
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()
}
);
});
}
// set min and max // check whether chartjs needs actual dates...
const xMax = now.toDate(); const mappedValues = values.map((value) => ({
const xMin = before.toDate(); ...value,
// calculate stepsize x: moment(value.start).toDate()
const xUnitStepSize = duration/6; }));
return { return {
data: dataWithTime, axes,
xMax, data: mappedValues,
xMin, xMax: moment(end).toDate(),
xUnitStepSize xMin: moment(start).toDate(),
yMax: max,
yMin: min,
xUnitStepSize: interval // this is in milliseconds!!!
}; };
} }
@ -158,12 +139,18 @@ class Graph extends React.Component {
} }
render() { render() {
const {
width,
height
} = this.props;
return ( return (
<Container name='metric-body'> <Container name='metric-body'>
<canvas <canvas
height={262}
ref={this.ref('component')} ref={this.ref('component')}
width={940} width={width}
height={height}
/> />
</Container> </Container>
); );
@ -171,11 +158,10 @@ class Graph extends React.Component {
} }
Graph.propTypes = { Graph.propTypes = {
data: React.PropTypes.array, // eslint-disable-line react/no-unused-prop-types data: React.PropTypes.object, // eslint-disable-line react/no-unused-prop-types
duration: React.PropTypes.number, // eslint-disable-line react/no-unused-prop-types height: React.PropTypes.number,
yMax: React.PropTypes.number, width: React.PropTypes.number,
yMeasurement: React.PropTypes.string, yMeasurement: React.PropTypes.string
yMin: React.PropTypes.number
}; };
export default Baseline( 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'; export { default as MetricCloseButton } from './full/close-button';
import MetricCloseButton from './close-button'; export { default as MetricHeader } from './full/header';
import MetricHeader from './header'; export { default as MetricSelect } from './full/select';
import MetricSelect from './select'; export { default as MetricSettingsButton } from './full/settings-button';
import MetricSettingsButton from './settings-button'; export { default as MetricTitle } from './full/title';
import MetricTitle from './title';
import MetricView from './view';
export { export { default as MetricView } from './view';
MetricGraph, export { default as MetricGraph } from './graph';
MetricCloseButton,
MetricHeader,
MetricSelect,
MetricSettingsButton,
MetricTitle,
MetricView
};

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,30 +1,25 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components';
import { Baseline } from '../../shared/composers'; import { Baseline } from '../../shared/composers';
import { boxes, colors } from '../../shared/constants'; import { default as FullView } from './full/view';
import { remcalc } from '../../shared/functions'; import { default as MiniView } from './mini/view';
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};
`;
const View = ({ const View = ({
children, children,
mini,
...props ...props
}) => ( }) => mini ? (
<Container {...props}> <MiniView {...props}>
{children} {children}
</Container> </MiniView>
) : (
<FullView {...props}>
{children}
</FullView>
); );
View.propTypes = { View.propTypes = {
children: React.PropTypes.node children: React.PropTypes.node,
mini: React.PropTypes.bool
}; };
export default Baseline( 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
};