Et voíla. Bar charts.

pull/10616/head
Hunter Trujillo 2017-06-12 12:59:51 -06:00
parent 796a0b495b
commit a4e6195b6e
5 changed files with 102 additions and 20 deletions

View File

@ -63,6 +63,7 @@ const VisView = ({
activeQueryIndex={activeQueryIndex}
isInDataExplorer={isInDataExplorer}
showSingleStat={cellType === 'line-plus-single-stat'}
isBarChart={cellType === 'bar'}
displayOptions={displayOptions}
editQueryStatus={editQueryStatus}
/>

View File

@ -23,6 +23,71 @@ const LINE_COLORS = [
'#a0725b',
]
const darkenColor = colorStr => {
// Defined in dygraph-utils.js
const color = Dygraphs.toRGB_(colorStr)
color.r = Math.floor((255 + color.r) / 2)
color.g = Math.floor((255 + color.g) / 2)
color.b = Math.floor((255 + color.b) / 2)
return `rgb(${color.r},${color.g},${color.b})`
}
const multiColumnBarPlotter = e => {
// We need to handle all the series simultaneously.
if (e.seriesIndex !== 0) {
return
}
const g = e.dygraph
const ctx = e.drawingContext
const sets = e.allSeriesPoints
const yBottom = e.dygraph.toDomYCoord(0)
// Find the minimum separation between x-values.
// This determines the bar width.
let minSep = Infinity
for (let j = 0; j < sets.length; j++) {
const points = sets[j]
for (let i = 1; i < points.length; i++) {
const sep = points[i].canvasx - points[i - 1].canvasx
if (sep < minSep) {
minSep = sep
}
}
}
const barWidth = Math.floor(2.0 / 3 * minSep)
const fillColors = []
const strokeColors = g.getColors()
for (let i = 0; i < strokeColors.length; i++) {
fillColors.push(darkenColor(strokeColors[i]))
}
for (let j = 0; j < sets.length; j++) {
ctx.fillStyle = fillColors[j]
ctx.strokeStyle = strokeColors[j]
for (let i = 0; i < sets[j].length; i++) {
const p = sets[j][i]
const centerX = p.canvasx
const xLeft = centerX - barWidth / 2 * (1 - j / (sets.length - 1))
ctx.fillRect(
xLeft,
p.canvasy,
barWidth / sets.length,
yBottom - p.canvasy
)
ctx.strokeRect(
xLeft,
p.canvasy,
barWidth / sets.length,
yBottom - p.canvasy
)
}
}
}
export default class Dygraph extends Component {
constructor(props) {
super(props)
@ -61,6 +126,7 @@ export default class Dygraph extends Component {
ruleValues,
overrideLineColors,
isGraphFilled,
isBarChart,
options,
} = this.props
@ -155,6 +221,10 @@ export default class Dygraph extends Component {
},
}
if (isBarChart) {
defaultOptions.plotter = multiColumnBarPlotter
}
this.dygraph = new Dygraphs(graphContainerNode, timeSeries, {
...defaultOptions,
...options,
@ -189,7 +259,14 @@ export default class Dygraph extends Component {
}
componentDidUpdate() {
const {labels, ranges, options, dygraphSeries, ruleValues} = this.props
const {
labels,
ranges,
options,
dygraphSeries,
ruleValues,
isBarChart,
} = this.props
const dygraph = this.dygraph
if (!dygraph) {
throw new Error(
@ -217,6 +294,7 @@ export default class Dygraph extends Component {
stackedGraph: options.stackedGraph,
underlayCallback: options.underlayCallback,
series: dygraphSeries,
plotter: isBarChart ? multiColumnBarPlotter : null,
})
// part of optional workaround for preventing updateOptions from breaking legend
// if (this.lastMouseMoveEvent) {
@ -265,6 +343,7 @@ Dygraph.propTypes = {
options: shape({}),
containerStyle: shape({}),
isGraphFilled: bool,
isBarChart: bool,
overrideLineColors: array,
dygraphSeries: shape({}).isRequired,
ruleValues: shape({

View File

@ -110,6 +110,7 @@ export const LayoutRenderer = React.createClass({
timeRange={timeRange}
autoRefresh={autoRefresh}
showSingleStat={type === 'line-plus-single-stat'}
isBarChart={type === 'bar'}
displayOptions={displayOptions}
synchronizer={synchronizer}
/>

View File

@ -22,6 +22,7 @@ export default React.createClass({
isRefreshing: bool,
underlayCallback: func,
isGraphFilled: bool,
isBarChart: bool,
overrideLineColors: array,
queries: arrayOf(shape({}).isRequired).isRequired,
showSingleStat: bool,
@ -80,6 +81,7 @@ export default React.createClass({
isFetchingInitially,
isRefreshing,
isGraphFilled,
isBarChart,
overrideLineColors,
title,
underlayCallback,
@ -101,25 +103,22 @@ export default React.createClass({
)
}
const options = Object.assign(
{},
{
labels,
connectSeparatedPoints: true,
labelsKMB: true,
axisLineColor: '#383846',
gridLineColor: '#383846',
title,
rightGap: 0,
yRangePad: 10,
axisLabelWidth: 38,
drawAxesAtZero: true,
underlayCallback,
ylabel: _.get(queries, ['0', 'label'], ''),
y2label: _.get(queries, ['1', 'label'], ''),
},
displayOptions
)
const options = {
labels,
connectSeparatedPoints: true,
labelsKMB: true,
axisLineColor: '#383846',
gridLineColor: '#383846',
title,
rightGap: 0,
yRangePad: 10,
axisLabelWidth: 38,
drawAxesAtZero: true,
underlayCallback,
ylabel: _.get(queries, ['0', 'label'], ''),
y2label: _.get(queries, ['1', 'label'], ''),
...displayOptions,
}
let roundedValue
if (showSingleStat) {
@ -141,6 +140,7 @@ export default React.createClass({
containerStyle={{width: '100%', height: '100%'}}
overrideLineColors={overrideLineColors}
isGraphFilled={isGraphFilled}
isBarChart={isBarChart}
timeSeries={timeSeries}
labels={labels}
options={options}

View File

@ -4,4 +4,5 @@
{type: "line-stepplot", menuOption: "Step-Plot"},
{type: "single-stat", menuOption: "SingleStat"},
{type: "line-plus-single-stat", menuOption: "Line + Stat"},
{type: "bar", menuOption: "Bar"},
]