Merge pull request #2055 from influxdata/chore/refactor-line-graph
REFACTOR: LineGraph, SingleStat, and LineGraph+SingleStatpull/10616/head
commit
f1fc9640d8
|
@ -1,67 +1,20 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React, {PropTypes, Component} from 'react'
|
||||
import Dygraph from 'shared/components/Dygraph'
|
||||
import classnames from 'classnames'
|
||||
import shallowCompare from 'react-addons-shallow-compare'
|
||||
|
||||
import SingleStat from 'src/shared/components/SingleStat'
|
||||
import timeSeriesToDygraph from 'utils/timeSeriesToDygraph'
|
||||
import lastValues from 'shared/parsing/lastValues'
|
||||
|
||||
const {array, arrayOf, bool, func, number, shape, string} = PropTypes
|
||||
import {SINGLE_STAT_LINE_COLORS} from 'src/shared/graphs/helpers'
|
||||
|
||||
const SMALL_CELL_HEIGHT = 1
|
||||
|
||||
export default React.createClass({
|
||||
displayName: 'LineGraph',
|
||||
propTypes: {
|
||||
data: arrayOf(shape({}).isRequired).isRequired,
|
||||
axes: shape({
|
||||
y: shape({
|
||||
bounds: array,
|
||||
label: string,
|
||||
}),
|
||||
y2: shape({
|
||||
bounds: array,
|
||||
label: string,
|
||||
}),
|
||||
}),
|
||||
title: string,
|
||||
isFetchingInitially: bool,
|
||||
isRefreshing: bool,
|
||||
underlayCallback: func,
|
||||
isGraphFilled: bool,
|
||||
isBarGraph: bool,
|
||||
overrideLineColors: array,
|
||||
queries: arrayOf(shape({}).isRequired).isRequired,
|
||||
showSingleStat: bool,
|
||||
displayOptions: shape({
|
||||
stepPlot: bool,
|
||||
stackedGraph: bool,
|
||||
}),
|
||||
activeQueryIndex: number,
|
||||
ruleValues: shape({}),
|
||||
timeRange: shape({
|
||||
lower: string.isRequired,
|
||||
}),
|
||||
isInDataExplorer: bool,
|
||||
synchronizer: func,
|
||||
setResolution: func,
|
||||
cellHeight: number,
|
||||
cell: shape({}),
|
||||
onZoom: func,
|
||||
resizeCoords: shape(),
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
underlayCallback: () => {},
|
||||
isGraphFilled: true,
|
||||
overrideLineColors: null,
|
||||
}
|
||||
},
|
||||
class LineGraph extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return shallowCompare(this, nextProps, nextState)
|
||||
},
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {data, activeQueryIndex, isInDataExplorer} = this.props
|
||||
|
@ -70,7 +23,7 @@ export default React.createClass({
|
|||
activeQueryIndex,
|
||||
isInDataExplorer
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps) {
|
||||
const {data, activeQueryIndex} = this.props
|
||||
|
@ -84,132 +37,144 @@ export default React.createClass({
|
|||
nextProps.isInDataExplorer
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
data,
|
||||
axes,
|
||||
cell,
|
||||
isFetchingInitially,
|
||||
isRefreshing,
|
||||
isGraphFilled,
|
||||
isBarGraph,
|
||||
overrideLineColors,
|
||||
title,
|
||||
onZoom,
|
||||
queries,
|
||||
underlayCallback,
|
||||
showSingleStat,
|
||||
displayOptions,
|
||||
ruleValues,
|
||||
synchronizer,
|
||||
timeRange,
|
||||
cellHeight,
|
||||
onZoom,
|
||||
ruleValues,
|
||||
isBarGraph,
|
||||
resizeCoords,
|
||||
synchronizer,
|
||||
isRefreshing,
|
||||
isGraphFilled,
|
||||
showSingleStat,
|
||||
displayOptions,
|
||||
underlayCallback,
|
||||
overrideLineColors,
|
||||
isFetchingInitially,
|
||||
} = this.props
|
||||
|
||||
const {labels, timeSeries, dygraphSeries} = this._timeSeries
|
||||
|
||||
// If data for this graph is being fetched for the first time, show a graph-wide spinner.
|
||||
if (isFetchingInitially) {
|
||||
return (
|
||||
<div className="graph-fetching">
|
||||
<div className="graph-spinner" />
|
||||
</div>
|
||||
)
|
||||
return <GraphSpinner />
|
||||
}
|
||||
|
||||
const options = {
|
||||
labels,
|
||||
connectSeparatedPoints: true,
|
||||
labelsKMB: true,
|
||||
axisLineColor: '#383846',
|
||||
gridLineColor: '#383846',
|
||||
...displayOptions,
|
||||
title,
|
||||
labels,
|
||||
rightGap: 0,
|
||||
yRangePad: 10,
|
||||
labelsKMB: true,
|
||||
underlayCallback,
|
||||
axisLabelWidth: 60,
|
||||
drawAxesAtZero: true,
|
||||
underlayCallback,
|
||||
...displayOptions,
|
||||
}
|
||||
|
||||
const singleStatOptions = {
|
||||
...options,
|
||||
highlightSeriesOpts: {
|
||||
strokeWidth: 1.5,
|
||||
},
|
||||
}
|
||||
const singleStatLineColors = [
|
||||
'#7A65F2',
|
||||
'#FFD255',
|
||||
'#7CE490',
|
||||
'#F95F53',
|
||||
'#4591ED',
|
||||
'#B1B6FF',
|
||||
'#FFF6B8',
|
||||
'#C6FFD0',
|
||||
'#6BDFFF',
|
||||
]
|
||||
|
||||
let roundedValue
|
||||
if (showSingleStat) {
|
||||
const lastValue = lastValues(data)[1]
|
||||
|
||||
const precision = 100.0
|
||||
roundedValue = Math.round(+lastValue * precision) / precision
|
||||
axisLineColor: '#383846',
|
||||
gridLineColor: '#383846',
|
||||
connectSeparatedPoints: true,
|
||||
}
|
||||
|
||||
const lineColors = showSingleStat
|
||||
? singleStatLineColors
|
||||
? SINGLE_STAT_LINE_COLORS
|
||||
: overrideLineColors
|
||||
|
||||
return (
|
||||
<div className="dygraph graph--hasYLabel" style={{height: '100%'}}>
|
||||
{isRefreshing ? this.renderSpinner() : null}
|
||||
{isRefreshing ? <GraphLoadingDots /> : null}
|
||||
<Dygraph
|
||||
cell={cell}
|
||||
resizeCoords={resizeCoords}
|
||||
axes={axes}
|
||||
onZoom={onZoom}
|
||||
labels={labels}
|
||||
queries={queries}
|
||||
containerStyle={{width: '100%', height: '100%'}}
|
||||
overrideLineColors={lineColors}
|
||||
isGraphFilled={showSingleStat ? false : isGraphFilled}
|
||||
timeRange={timeRange}
|
||||
isBarGraph={isBarGraph}
|
||||
timeSeries={timeSeries}
|
||||
labels={labels}
|
||||
options={showSingleStat ? singleStatOptions : options}
|
||||
dygraphSeries={dygraphSeries}
|
||||
ruleValues={ruleValues}
|
||||
synchronizer={synchronizer}
|
||||
timeRange={timeRange}
|
||||
resizeCoords={resizeCoords}
|
||||
overrideLineColors={lineColors}
|
||||
dygraphSeries={dygraphSeries}
|
||||
setResolution={this.props.setResolution}
|
||||
onZoom={onZoom}
|
||||
containerStyle={{width: '100%', height: '100%'}}
|
||||
isGraphFilled={showSingleStat ? false : isGraphFilled}
|
||||
options={options}
|
||||
/>
|
||||
{showSingleStat
|
||||
? <div className="single-stat single-stat-line">
|
||||
<span
|
||||
className={classnames('single-stat--value', {
|
||||
'single-stat--small': cellHeight === SMALL_CELL_HEIGHT,
|
||||
})}
|
||||
>
|
||||
<span className="single-stat--shadow">
|
||||
{roundedValue}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
? <SingleStat data={data} cellHeight={cellHeight} />
|
||||
: null}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
renderSpinner() {
|
||||
return (
|
||||
<div className="graph-panel__refreshing">
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
const GraphLoadingDots = () =>
|
||||
<div className="graph-panel__refreshing">
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
|
||||
const GraphSpinner = () =>
|
||||
<div className="graph-fetching">
|
||||
<div className="graph-spinner" />
|
||||
</div>
|
||||
|
||||
const {array, arrayOf, bool, func, number, shape, string} = PropTypes
|
||||
|
||||
LineGraph.defaultProps = {
|
||||
underlayCallback: () => {},
|
||||
isGraphFilled: true,
|
||||
overrideLineColors: null,
|
||||
}
|
||||
|
||||
LineGraph.propTypes = {
|
||||
axes: shape({
|
||||
y: shape({
|
||||
bounds: array,
|
||||
label: string,
|
||||
}),
|
||||
y2: shape({
|
||||
bounds: array,
|
||||
label: string,
|
||||
}),
|
||||
}),
|
||||
title: string,
|
||||
isFetchingInitially: bool,
|
||||
isRefreshing: bool,
|
||||
underlayCallback: func,
|
||||
isGraphFilled: bool,
|
||||
isBarGraph: bool,
|
||||
overrideLineColors: array,
|
||||
showSingleStat: bool,
|
||||
displayOptions: shape({
|
||||
stepPlot: bool,
|
||||
stackedGraph: bool,
|
||||
}),
|
||||
activeQueryIndex: number,
|
||||
ruleValues: shape({}),
|
||||
timeRange: shape({
|
||||
lower: string.isRequired,
|
||||
}),
|
||||
isInDataExplorer: bool,
|
||||
synchronizer: func,
|
||||
setResolution: func,
|
||||
cellHeight: number,
|
||||
cell: shape(),
|
||||
onZoom: func,
|
||||
resizeCoords: shape(),
|
||||
queries: arrayOf(shape({}).isRequired).isRequired,
|
||||
data: arrayOf(shape({}).isRequired).isRequired,
|
||||
}
|
||||
|
||||
export default LineGraph
|
||||
|
|
|
@ -1,28 +1,20 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React, {PropTypes, Component} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import shallowCompare from 'react-addons-shallow-compare'
|
||||
import lastValues from 'shared/parsing/lastValues'
|
||||
|
||||
const SMALL_CELL_HEIGHT = 1
|
||||
|
||||
export default React.createClass({
|
||||
displayName: 'LineGraph',
|
||||
propTypes: {
|
||||
data: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
title: PropTypes.string,
|
||||
isFetchingInitially: PropTypes.bool,
|
||||
cellHeight: PropTypes.number,
|
||||
},
|
||||
import {SMALL_CELL_HEIGHT} from 'src/shared/graphs/helpers'
|
||||
|
||||
class SingleStat extends Component {
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return shallowCompare(this, nextProps, nextState)
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
const {data, cellHeight} = this.props
|
||||
const {data, cellHeight, isFetchingInitially} = this.props
|
||||
|
||||
// If data for this graph is being fetched for the first time, show a graph-wide spinner.
|
||||
if (this.props.isFetchingInitially) {
|
||||
if (isFetchingInitially) {
|
||||
return (
|
||||
<div className="graph-empty">
|
||||
<h3 className="graph-spinner" />
|
||||
|
@ -46,5 +38,15 @@ export default React.createClass({
|
|||
</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const {arrayOf, bool, number, shape} = PropTypes
|
||||
|
||||
SingleStat.propTypes = {
|
||||
data: arrayOf(shape()).isRequired,
|
||||
isFetchingInitially: bool,
|
||||
cellHeight: number,
|
||||
}
|
||||
|
||||
export default SingleStat
|
||||
|
|
|
@ -17,6 +17,20 @@ export const LINE_COLORS = [
|
|||
'#a0725b',
|
||||
]
|
||||
|
||||
export const SMALL_CELL_HEIGHT = 1
|
||||
|
||||
export const SINGLE_STAT_LINE_COLORS = [
|
||||
'#7A65F2',
|
||||
'#FFD255',
|
||||
'#7CE490',
|
||||
'#F95F53',
|
||||
'#4591ED',
|
||||
'#B1B6FF',
|
||||
'#FFF6B8',
|
||||
'#C6FFD0',
|
||||
'#6BDFFF',
|
||||
]
|
||||
|
||||
export const darkenColor = colorStr => {
|
||||
// Defined in dygraph-utils.js
|
||||
const color = Dygraphs.toRGB_(colorStr)
|
||||
|
|
Loading…
Reference in New Issue