Skip to content

Commit

Permalink
feat(charts): data props for columns, pies, stackedColumns, sparkline…
Browse files Browse the repository at this point in the history
…s, donuts (#43)

* start integration steps for pies

* integrate data props for percentage type stacked column chart

* integrate non percentage stacked column and update docs

* empower line charts to know about data

* updates deploy socs for line

* update data api for sparklines

* fixes legend data

* integrate donuts with data; add donut example;

* smplify sparkline

* document sparklines
  • Loading branch information
elisechant authored Apr 13, 2017
1 parent 565932c commit 9f35d11
Show file tree
Hide file tree
Showing 19 changed files with 361 additions and 286 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@
"docs-build": "styleguidist build",
"docs-deploy": "npm run docs-build && surge -p $npm_package_config_styleguideDir -d https://datavizkit.surge.sh",
"commit": "git-cz",
"commitmsg": "validate-commit-msg",
"semantic-release": "semantic-release pre && npm publish && semantic-release post"
},
"config": {
Expand Down
3 changes: 1 addition & 2 deletions src/components/customLegend/customLegend.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import React from 'react';
import styled from 'styled-components';


const Legend = (props) => {
const {data, className} = props;
const Legend = ({data, className}) => {
return (
<div className={className}>
{data.map((d, idx) => {
Expand Down
83 changes: 41 additions & 42 deletions src/components/trendLegend/trendLegend.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
import React, {PureComponent} from 'react';
import styled from 'styled-components';

const TrendLegendDiv = styled.div`
width: 100%;
text-align:center;
`
// TODO remove the implicit fontawesome dependency

class TrendLegend extends PureComponent {
render() {
const trend = this.getTrend();
const volume = this.getVolume();
const date = this.getPreviousDate();

//TODO avoid fontawesome dependency; maybe inject somehow?
const iconClass = `metric-trend fa fa-arrow-${trend}`
import React, {PureComponent} from 'react';
import styled from 'styled-components';

return (
<TrendLegendDiv>
<span className={iconClass}></span>
<span className='summary-text'>{trend} {volume} since {date}</span>
</TrendLegendDiv>
)
}

getPreviousDate() {
return this.props.previousDate;
}
const getPreviousDate = (data) => {
const secondLastDatum = data[data.length - 2];

getVolume() {
let diff = this.getDifference();
if (secondLastDatum && secondLastDatum.category) {
return secondLastDatum.category;
}
return null;
};

switch(diff) {
const getVolume = (diff) => {
switch(diff) {
case 0:
return '';
default:
return Math.abs(diff);
}
}
};

getTrend() {
let diff = this.getDifference();

switch(true) {
const getTrend = (diff) => {
switch(true) {
case diff > 0:
return 'up';
case diff < 0:
return 'down';
default:
return 'unchanged';
}
}
};

getDifference() {
let data = this.getData();
let lastVal = data[data.length - 1].y
let previousVal = data[data.length -2].y
return lastVal - previousVal
}
const getDifference = (data) => {
const lastVal = data[data.length - 1].y;
const previousVal = data[data.length -2].y;
return lastVal - previousVal;
};


const TrendLegend = ({data}) => {
const difference = getDifference(data);
const date = getPreviousDate(data);
const trend = getTrend(difference);
const volume = getVolume(difference);
return (
<div className="trend-legend">
<i className={`metric-trend fa fa-arrow-${trend}`}></i>
{date && <span className='summary-text'>{trend} {volume} since {date}</span>}
</div>
)
};

getData() {
return this.props.data;
const StyledTrendLegend = styled(TrendLegend)`
.trend-legend {
width: 100%;
text-align:center;
}
}
`;

export default TrendLegend;
export default StyledTrendLegend;
24 changes: 11 additions & 13 deletions src/components/widgets/column/column_dataHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const makeChartOptions = ({
units,
type,
dateLastUpdated,
minimumValue = 0
minimumValue = 0,
}) => {

const config = merge({
Expand All @@ -20,7 +20,7 @@ export const makeChartOptions = ({
events: {
load: function() { // equivalent to constructor callback

var seriesData = this.series[0].data;//this is series data
var seriesData = this.series[0].data;//this is series data // todo - this will be different for differnt dimensions of data
seriesData.forEach((d, idx) => {
if (d.y === null) { //find null value in series
// adds plot band
Expand All @@ -35,9 +35,8 @@ export const makeChartOptions = ({
let customLegendData = this.series.map(s => {
const lastData = last(s.data);
return {
key: lastData.category,
key: s.name,
y: lastData.y,
seriesName: s.name,
color: lastData.color,
}
});
Expand Down Expand Up @@ -68,13 +67,12 @@ export const makeChartOptions = ({
events: {
mouseOver: function() {
const sliceIdx = this.index;
// todo - identify all data permutations
// todo - verify this works for all data permutations
const customLegendData = this.series.chart.series.map(s => {
const sliceData = s.data[sliceIdx];
return {
key: sliceData.category,
key: s.name,
y: sliceData.y,
seriesName: s.name,
color: sliceData.color
}
});
Expand All @@ -93,10 +91,13 @@ export const makeChartOptions = ({
allowPointSelect: false
},
},
tooltip: {
enabled: false,
},

// instance props
xAxis: {
categories: [], // is replaced by localConfig
categories: [], // replaced by chartConfig

// labels: {
// formatter: function () {
Expand All @@ -108,12 +109,9 @@ export const makeChartOptions = ({
title: {
text: null
},
min: minimumValue
min: minimumValue,
},
series: [], // is replaced by localConfig
tooltip: {
enabled: false,
}
series: [], // replaced by chartConfig
}, chartConfig);

return config;
Expand Down
11 changes: 3 additions & 8 deletions src/components/widgets/column/column_widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,16 @@ class ColumnWidget extends PureComponent {

render() {
const {customLegend} = this.state;
const {title, units, type, dateLastUpdated, minimumValue,
chartConfig} = this.props;
const {chartConfig, ...restProps} = this.props;

const chartOptions = makeChartOptions({
emitSetState: this.proxiedSetState,
chartConfig,
title,
units,
type,
dateLastUpdated,
minimumValue
...restProps
});

return (
<article className={`chart--column`} role="article">
<article className="chart--column" role="article">
<section>
<Chart ref={el => this.chartInstance = el}
options={chartOptions}>
Expand Down
12 changes: 10 additions & 2 deletions src/components/widgets/column/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@
type='column'
dateLastUpdated='22 Feb 2016'
minimumValue="20000"
chartConfig={{"xAxis":{"categories":["May","Jun","Jul","Aug","Sep","Oct","Nov"]},"series":[{"name":"Time to clear","data":[84807,48317,51420,62400,48060,37560,39300]}]}}
singleCategory="false" singleSection="true" />
chartConfig={{
"xAxis":{
"categories":["May","Jun","Jul","Aug","Sep","Oct","Nov"]
},
"series":[
{"name":"Time to clear","data":[84807,48317,51420,62400,48060,37560,39300]}
]
}}
singleCategory={false}
singleSection={true} />

### Many Category Single Slice:
Expand Down
53 changes: 25 additions & 28 deletions src/components/widgets/donut/donut_dataHelpers.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@

import Highcharts from 'highcharts';
import merge from 'lodash/merge';


export const makeChartOptions = ({
emitSetState = () => {},
widget,
chartConfig = {},
title,
units,
type,
dateLastUpdated
}) => {
return {

const config = merge({
// default pie options
chart: {
type: 'pie',
events: {

load: function() {
const customLegendData = this.series[0].data.map(d => {
return {
key: d.name,
y: Highcharts.numberFormat(d.percentage, 2) + '%',
seriesName: this.series[0].name,
color: d.color
}
});
Expand All @@ -24,12 +31,12 @@ export const makeChartOptions = ({
},
},
title: {
text: widget.title,
text: title,
align: 'left',
},
subtitle: {
useHTML: true,
text: `<span>Last updated <time dateTime="${widget.dateUpdated}">${widget.dateUpdated}</time></span>`,
text: `<span>Last updated <time dateTime="${dateLastUpdated}">${dateLastUpdated}</time></span>`,
align: 'left',
},
plotOptions: {
Expand All @@ -54,29 +61,19 @@ export const makeChartOptions = ({
},

// instance props
series: [{
name: 'Brands',
series: [], // replaced by chartConfig
}, chartConfig);

chartConfig.series = chartConfig.series.map(s => {
return {...s,
colorByPoint: true,
innerSize: '50%',
data: [{
name: 'Microsoft Internet Explorer',
y: 123
}, {
name: 'Chrome',
y: 23
}, {
name: 'Firefox',
y: 105
}, {
name: 'Safari',
y: 45
}, {
name: 'Opera',
y: 10
}, {
name: 'Proprietary or Undetectable',
y: 87
}]
}],
};
}
});

return config;

};



9 changes: 3 additions & 6 deletions src/components/widgets/donut/donut_widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ import Legend from './../../customLegend';

/**
* Renders a Donut Widget with it's surrounding state.
*
* Technically multiple series of data can be plotted on polar
* charts, but this widget should only accept a single series of
* data.
*
*/
class DonutWidget extends PureComponent {

Expand All @@ -50,10 +45,12 @@ class DonutWidget extends PureComponent {

render() {
const {customLegend} = this.state;
const {chartConfig, ...restProps} = this.props;

const chartOptions = makeChartOptions({
emitSetState: this.proxiedSetState,
widget: this.props.widget,
chartConfig,
...restProps
});

return (
Expand Down
34 changes: 29 additions & 5 deletions src/components/widgets/donut/readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
Basic Donut Widget:
### Multiple Category Singular Slice:

<DonutWidget widget={{
title: 'Devices used',
dateUpdated: '22 Feb 2016',
}} />
Renders slice data to each of its sectors.

<DonutWidget chartConfig={{
"series":[{
name: "Jan",
data: [
{"name":"Mobile","y":183},
{"name":"Tablet","y":30},
{"name":"Desktop","y":200}
]
}]
}}
title="Devices used"
units="percentage"
type="donut"
dateLastUpdated="2017-02-01T01:02:02.240Z"
_singleCategory={true}
_singleSection={false}
minimumValue="30" />


### Multiple Category Multiple Slices (shown as aggregate over time (many slices)):

`@todo - new feature`


### Multiple Category Multiple Slices (multiple pies)

`@todo - new feature - as example: http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/pie-donut/`
Loading

0 comments on commit 9f35d11

Please sign in to comment.