Merge pull request #1805 from influxdata/fix/graph-fixes
Graph Fixes for Bar Graphs and Add Hash-based Colorspull/10616/head
commit
a7d16c8514
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
### UI Improvements
|
### UI Improvements
|
||||||
1. [#1796](https://github.com/influxdata/chronograf/pull/1796): Add spinner to indicate data is being written
|
1. [#1796](https://github.com/influxdata/chronograf/pull/1796): Add spinner to indicate data is being written
|
||||||
|
1. [#1800](https://github.com/influxdata/chronograf/pull/1796): Embiggen text area for line protocol manual entry in Data Explorer's Write Data overlay
|
||||||
|
1. [#1805](https://github.com/influxdata/chronograf/pull/1805): Fix bar graphs overlapping
|
||||||
|
1. [#1805](https://github.com/influxdata/chronograf/pull/1805): Add series names hashing so that graph colors should stay the same for the same series across charts
|
||||||
1. [#1800](https://github.com/influxdata/chronograf/pull/1800): Embiggen text area for line protocol manual entry in Data Explorer's Write Data overlay
|
1. [#1800](https://github.com/influxdata/chronograf/pull/1800): Embiggen text area for line protocol manual entry in Data Explorer's Write Data overlay
|
||||||
1. [#1812](https://github.com/influxdata/chronograf/pull/1812): Improve error message when request for Status Page News Feed fails
|
1. [#1812](https://github.com/influxdata/chronograf/pull/1812): Improve error message when request for Status Page News Feed fails
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,12 @@ import {LINE_COLORS, multiColumnBarPlotter} from 'src/shared/graphs/helpers'
|
||||||
import DygraphLegend from 'src/shared/components/DygraphLegend'
|
import DygraphLegend from 'src/shared/components/DygraphLegend'
|
||||||
import {buildYLabel} from 'shared/presenters'
|
import {buildYLabel} from 'shared/presenters'
|
||||||
|
|
||||||
|
const hasherino = (str, len) =>
|
||||||
|
str
|
||||||
|
.split('')
|
||||||
|
.map(char => char.charCodeAt(0))
|
||||||
|
.reduce((hash, code) => hash + code, 0) % len
|
||||||
|
|
||||||
export default class Dygraph extends Component {
|
export default class Dygraph extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -80,21 +86,29 @@ export default class Dygraph extends Component {
|
||||||
|
|
||||||
const graphRef = this.graphRef
|
const graphRef = this.graphRef
|
||||||
const legendRef = this.legendRef
|
const legendRef = this.legendRef
|
||||||
let finalLineColors = overrideLineColors
|
const finalLineColors = [...(overrideLineColors || LINE_COLORS)]
|
||||||
|
|
||||||
if (finalLineColors === null) {
|
const hashColorDygraphSeries = {}
|
||||||
finalLineColors = LINE_COLORS
|
const {length} = finalLineColors
|
||||||
|
|
||||||
|
for (const seriesName in dygraphSeries) {
|
||||||
|
const series = dygraphSeries[seriesName]
|
||||||
|
const hashIndex = hasherino(seriesName, length)
|
||||||
|
const color = finalLineColors[hashIndex]
|
||||||
|
hashColorDygraphSeries[seriesName] = {...series, color}
|
||||||
}
|
}
|
||||||
|
|
||||||
const yAxis = _.get(axes, ['y', 'bounds'], [null, null])
|
const yAxis = _.get(axes, ['y', 'bounds'], [null, null])
|
||||||
const y2Axis = _.get(axes, ['y2', 'bounds'], undefined)
|
const y2Axis = _.get(axes, ['y2', 'bounds'], undefined)
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
plugins: [
|
plugins: isBarGraph
|
||||||
new Dygraphs.Plugins.Crosshair({
|
? []
|
||||||
direction: 'vertical',
|
: [
|
||||||
}),
|
new Dygraphs.Plugins.Crosshair({
|
||||||
],
|
direction: 'vertical',
|
||||||
|
}),
|
||||||
|
],
|
||||||
labelsSeparateLines: false,
|
labelsSeparateLines: false,
|
||||||
labelsKMB: true,
|
labelsKMB: true,
|
||||||
rightGap: 0,
|
rightGap: 0,
|
||||||
|
@ -103,12 +117,11 @@ export default class Dygraph extends Component {
|
||||||
fillGraph: isGraphFilled,
|
fillGraph: isGraphFilled,
|
||||||
axisLineWidth: 2,
|
axisLineWidth: 2,
|
||||||
gridLineWidth: 1,
|
gridLineWidth: 1,
|
||||||
highlightCircleSize: 3,
|
highlightCircleSize: isBarGraph ? 0 : 3,
|
||||||
animatedZooms: true,
|
animatedZooms: true,
|
||||||
hideOverlayOnMouseOut: false,
|
hideOverlayOnMouseOut: false,
|
||||||
colors: finalLineColors,
|
colors: finalLineColors,
|
||||||
series: dygraphSeries,
|
series: hashColorDygraphSeries,
|
||||||
ylabel: this.getLabel('y'),
|
|
||||||
axes: {
|
axes: {
|
||||||
y: {
|
y: {
|
||||||
valueRange: getRange(timeSeries, yAxis, ruleValues),
|
valueRange: getRange(timeSeries, yAxis, ruleValues),
|
||||||
|
@ -119,7 +132,7 @@ export default class Dygraph extends Component {
|
||||||
},
|
},
|
||||||
highlightSeriesOpts: {
|
highlightSeriesOpts: {
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
highlightCircleSize: 5,
|
highlightCircleSize: isBarGraph ? 0 : 5,
|
||||||
},
|
},
|
||||||
legendFormatter: legend => {
|
legendFormatter: legend => {
|
||||||
if (!legend.x) {
|
if (!legend.x) {
|
||||||
|
@ -259,6 +272,7 @@ export default class Dygraph extends Component {
|
||||||
dygraphSeries,
|
dygraphSeries,
|
||||||
ruleValues,
|
ruleValues,
|
||||||
isBarGraph,
|
isBarGraph,
|
||||||
|
overrideLineColors,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const dygraph = this.dygraph
|
const dygraph = this.dygraph
|
||||||
|
@ -272,6 +286,17 @@ export default class Dygraph extends Component {
|
||||||
const y2 = _.get(axes, ['y2', 'bounds'], undefined)
|
const y2 = _.get(axes, ['y2', 'bounds'], undefined)
|
||||||
const timeSeries = this.getTimeSeries()
|
const timeSeries = this.getTimeSeries()
|
||||||
const ylabel = this.getLabel('y')
|
const ylabel = this.getLabel('y')
|
||||||
|
const finalLineColors = [...(overrideLineColors || LINE_COLORS)]
|
||||||
|
|
||||||
|
const hashColorDygraphSeries = {}
|
||||||
|
const {length} = finalLineColors
|
||||||
|
|
||||||
|
for (const seriesName in dygraphSeries) {
|
||||||
|
const series = dygraphSeries[seriesName]
|
||||||
|
const hashIndex = hasherino(seriesName, length)
|
||||||
|
const color = finalLineColors[hashIndex]
|
||||||
|
hashColorDygraphSeries[seriesName] = {...series, color}
|
||||||
|
}
|
||||||
|
|
||||||
const updateOptions = {
|
const updateOptions = {
|
||||||
labels,
|
labels,
|
||||||
|
@ -288,7 +313,8 @@ export default class Dygraph extends Component {
|
||||||
stepPlot: options.stepPlot,
|
stepPlot: options.stepPlot,
|
||||||
stackedGraph: options.stackedGraph,
|
stackedGraph: options.stackedGraph,
|
||||||
underlayCallback: options.underlayCallback,
|
underlayCallback: options.underlayCallback,
|
||||||
series: dygraphSeries,
|
colors: finalLineColors,
|
||||||
|
series: hashColorDygraphSeries,
|
||||||
plotter: isBarGraph ? multiColumnBarPlotter : null,
|
plotter: isBarGraph ? multiColumnBarPlotter : null,
|
||||||
visibility: this.visibility(),
|
visibility: this.visibility(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ export const darkenColor = colorStr => {
|
||||||
return `rgb(${color.r},${color.g},${color.b})`
|
return `rgb(${color.r},${color.g},${color.b})`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bar Graph code below is from http://dygraphs.com/tests/plotters.html
|
// Bar Graph code below is adapted from http://dygraphs.com/tests/plotters.html
|
||||||
export const multiColumnBarPlotter = e => {
|
export const multiColumnBarPlotter = e => {
|
||||||
// We need to handle all the series simultaneously.
|
// We need to handle all the series simultaneously.
|
||||||
if (e.seriesIndex !== 0) {
|
if (e.seriesIndex !== 0) {
|
||||||
|
@ -51,24 +51,34 @@ export const multiColumnBarPlotter = e => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const barWidth = Math.floor(2.0 / 3 * minSep)
|
// calculate bar width using some graphics math while
|
||||||
|
// ensuring a bar is never smaller than one px, so it is always rendered
|
||||||
|
const barWidth = Math.max(Math.floor(2.0 / 3.0 * minSep), 1.0)
|
||||||
|
|
||||||
const fillColors = []
|
const fillColors = []
|
||||||
const strokeColors = g.getColors()
|
const strokeColors = g.getColors()
|
||||||
|
|
||||||
|
let selPointX
|
||||||
|
if (g.selPoints_ && g.selPoints_.length) {
|
||||||
|
selPointX = g.selPoints_[0].canvasx
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < strokeColors.length; i++) {
|
for (let i = 0; i < strokeColors.length; i++) {
|
||||||
fillColors.push(darkenColor(strokeColors[i]))
|
fillColors.push(darkenColor(strokeColors[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.lineWidth = 2
|
||||||
|
|
||||||
for (let j = 0; j < sets.length; j++) {
|
for (let j = 0; j < sets.length; j++) {
|
||||||
ctx.fillStyle = fillColors[j]
|
|
||||||
ctx.strokeStyle = strokeColors[j]
|
ctx.strokeStyle = strokeColors[j]
|
||||||
for (let i = 0; i < sets[j].length; i++) {
|
for (let i = 0; i < sets[j].length; i++) {
|
||||||
const p = sets[j][i]
|
const p = sets[j][i]
|
||||||
const centerX = p.canvasx
|
const centerX = p.canvasx
|
||||||
|
ctx.fillStyle = fillColors[j]
|
||||||
const xLeft =
|
const xLeft =
|
||||||
sets.length === 1
|
sets.length === 1
|
||||||
? centerX - barWidth / 2
|
? centerX - barWidth
|
||||||
: centerX - barWidth / 2 * (1 - j / (sets.length - 1))
|
: centerX - barWidth * (1 - j / sets.length)
|
||||||
|
|
||||||
ctx.fillRect(
|
ctx.fillRect(
|
||||||
xLeft,
|
xLeft,
|
||||||
|
@ -77,12 +87,15 @@ export const multiColumnBarPlotter = e => {
|
||||||
yBottom - p.canvasy
|
yBottom - p.canvasy
|
||||||
)
|
)
|
||||||
|
|
||||||
ctx.strokeRect(
|
// hover highlighting
|
||||||
xLeft,
|
if (selPointX === centerX) {
|
||||||
p.canvasy,
|
ctx.strokeRect(
|
||||||
barWidth / sets.length,
|
xLeft,
|
||||||
yBottom - p.canvasy
|
p.canvasy,
|
||||||
)
|
barWidth / sets.length,
|
||||||
|
yBottom - p.canvasy
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue