Refactor single stat colors into redux state instead of CEO state
parent
da600f613c
commit
85d13d27ed
|
@ -22,3 +22,17 @@ export const renameCell = cellName => ({
|
|||
cellName,
|
||||
},
|
||||
})
|
||||
|
||||
export const updateSingleStatColors = singleStatColors => ({
|
||||
type: 'UPDATE_SINGLE_STAT_COLORS',
|
||||
payload: {
|
||||
singleStatColors,
|
||||
},
|
||||
})
|
||||
|
||||
export const updateSingleStatType = singleStatType => ({
|
||||
type: 'UPDATE_SINGLE_STAT_TYPE',
|
||||
payload: {
|
||||
singleStatType,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -25,12 +25,8 @@ import {AUTO_GROUP_BY} from 'shared/constants'
|
|||
import {
|
||||
COLOR_TYPE_THRESHOLD,
|
||||
MAX_THRESHOLDS,
|
||||
DEFAULT_VALUE_MIN,
|
||||
DEFAULT_VALUE_MAX,
|
||||
GAUGE_COLORS,
|
||||
validateGaugeColors,
|
||||
validateSingleStatColors,
|
||||
getSingleStatType,
|
||||
stringifyColorValues,
|
||||
} from 'src/dashboards/constants/gaugeColors'
|
||||
|
||||
|
@ -51,16 +47,12 @@ class CellEditorOverlay extends Component {
|
|||
}))
|
||||
)
|
||||
|
||||
const singleStatType = getSingleStatType(colors)
|
||||
|
||||
this.state = {
|
||||
queriesWorkingDraft,
|
||||
activeQueryIndex: 0,
|
||||
isDisplayOptionsTabActive: false,
|
||||
axes,
|
||||
singleStatType,
|
||||
gaugeColors: validateGaugeColors(colors),
|
||||
singleStatColors: validateSingleStatColors(colors, singleStatType),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,113 +102,39 @@ class CellEditorOverlay extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
handleAddSingleStatThreshold = () => {
|
||||
const {singleStatColors, singleStatType} = this.state
|
||||
|
||||
const randomColor = _.random(0, GAUGE_COLORS.length - 1)
|
||||
|
||||
const maxValue = DEFAULT_VALUE_MIN
|
||||
const minValue = DEFAULT_VALUE_MAX
|
||||
|
||||
let randomValue = _.round(_.random(minValue, maxValue, true), 2)
|
||||
|
||||
if (singleStatColors.length > 0) {
|
||||
const colorsValues = _.mapValues(singleStatColors, 'value')
|
||||
do {
|
||||
randomValue = _.round(_.random(minValue, maxValue, true), 2)
|
||||
} while (_.includes(colorsValues, randomValue))
|
||||
}
|
||||
|
||||
const newThreshold = {
|
||||
type: singleStatType,
|
||||
id: uuid.v4(),
|
||||
value: randomValue,
|
||||
hex: GAUGE_COLORS[randomColor].hex,
|
||||
name: GAUGE_COLORS[randomColor].name,
|
||||
}
|
||||
|
||||
this.setState({singleStatColors: [...singleStatColors, newThreshold]})
|
||||
}
|
||||
|
||||
handleDeleteThreshold = threshold => () => {
|
||||
const {type} = this.props.cell
|
||||
const gaugeColors = this.state.gaugeColors.filter(
|
||||
color => color.id !== threshold.id
|
||||
)
|
||||
|
||||
if (type === 'gauge') {
|
||||
const gaugeColors = this.state.gaugeColors.filter(
|
||||
color => color.id !== threshold.id
|
||||
)
|
||||
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
if (type === 'single-stat') {
|
||||
const singleStatColors = this.state.singleStatColors.filter(
|
||||
color => color.id !== threshold.id
|
||||
)
|
||||
|
||||
this.setState({singleStatColors})
|
||||
}
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
handleChooseColor = threshold => chosenColor => {
|
||||
const {type} = this.props.cell
|
||||
const gaugeColors = this.state.gaugeColors.map(
|
||||
color =>
|
||||
color.id === threshold.id
|
||||
? {...color, hex: chosenColor.hex, name: chosenColor.name}
|
||||
: color
|
||||
)
|
||||
|
||||
if (type === 'gauge') {
|
||||
const gaugeColors = this.state.gaugeColors.map(
|
||||
color =>
|
||||
color.id === threshold.id
|
||||
? {...color, hex: chosenColor.hex, name: chosenColor.name}
|
||||
: color
|
||||
)
|
||||
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
if (type === 'single-stat') {
|
||||
const singleStatColors = this.state.singleStatColors.map(
|
||||
color =>
|
||||
color.id === threshold.id
|
||||
? {...color, hex: chosenColor.hex, name: chosenColor.name}
|
||||
: color
|
||||
)
|
||||
|
||||
this.setState({singleStatColors})
|
||||
}
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
handleUpdateColorValue = (threshold, value) => {
|
||||
const {type} = this.props.cell
|
||||
const gaugeColors = this.state.gaugeColors.map(
|
||||
color => (color.id === threshold.id ? {...color, value} : color)
|
||||
)
|
||||
|
||||
if (type === 'gauge') {
|
||||
const gaugeColors = this.state.gaugeColors.map(
|
||||
color => (color.id === threshold.id ? {...color, value} : color)
|
||||
)
|
||||
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
if (type === 'single-stat') {
|
||||
const singleStatColors = this.state.singleStatColors.map(
|
||||
color => (color.id === threshold.id ? {...color, value} : color)
|
||||
)
|
||||
|
||||
this.setState({singleStatColors})
|
||||
}
|
||||
this.setState({gaugeColors})
|
||||
}
|
||||
|
||||
handleValidateColorValue = (threshold, targetValue) => {
|
||||
const {gaugeColors, singleStatColors} = this.state
|
||||
const {type} = this.props.cell
|
||||
const {gaugeColors} = this.state
|
||||
|
||||
const thresholdValue = threshold.value
|
||||
let allowedToUpdate = false
|
||||
|
||||
if (type === 'single-stat') {
|
||||
// If type is single-stat then value only has to be unique
|
||||
const sortedColors = _.sortBy(singleStatColors, color => color.value)
|
||||
return !sortedColors.some(color => color.value === targetValue)
|
||||
}
|
||||
|
||||
const sortedColors = _.sortBy(gaugeColors, color => color.value)
|
||||
|
||||
const minValue = sortedColors[0].value
|
||||
|
@ -252,18 +170,6 @@ class CellEditorOverlay extends Component {
|
|||
return allowedToUpdate
|
||||
}
|
||||
|
||||
handleToggleSingleStatType = type => () => {
|
||||
const singleStatColors = this.state.singleStatColors.map(color => ({
|
||||
...color,
|
||||
type,
|
||||
}))
|
||||
|
||||
this.setState({
|
||||
singleStatType: type,
|
||||
singleStatColors,
|
||||
})
|
||||
}
|
||||
|
||||
handleSetSuffix = e => {
|
||||
const {axes} = this.state
|
||||
|
||||
|
@ -355,14 +261,9 @@ class CellEditorOverlay extends Component {
|
|||
}
|
||||
|
||||
handleSaveCell = () => {
|
||||
const {
|
||||
queriesWorkingDraft,
|
||||
axes,
|
||||
gaugeColors,
|
||||
singleStatColors,
|
||||
} = this.state
|
||||
const {queriesWorkingDraft, axes, gaugeColors} = this.state
|
||||
|
||||
const {cell} = this.props
|
||||
const {cell, singleStatColors} = this.props
|
||||
|
||||
const queries = queriesWorkingDraft.map(q => {
|
||||
const timeRange = q.range || {upper: null, lower: ':dashboardTime:'}
|
||||
|
@ -520,7 +421,6 @@ class CellEditorOverlay extends Component {
|
|||
|
||||
render() {
|
||||
const {
|
||||
cell,
|
||||
onCancel,
|
||||
templates,
|
||||
timeRange,
|
||||
|
@ -531,11 +431,9 @@ class CellEditorOverlay extends Component {
|
|||
const {
|
||||
axes,
|
||||
gaugeColors,
|
||||
singleStatColors,
|
||||
activeQueryIndex,
|
||||
isDisplayOptionsTabActive,
|
||||
queriesWorkingDraft,
|
||||
singleStatType,
|
||||
} = this.state
|
||||
|
||||
const queryActions = {
|
||||
|
@ -547,9 +445,6 @@ class CellEditorOverlay extends Component {
|
|||
(!!query.measurement && !!query.database && !!query.fields.length) ||
|
||||
!!query.rawText
|
||||
|
||||
const visualizationColors =
|
||||
cell.type === 'gauge' ? gaugeColors : singleStatColors
|
||||
|
||||
return (
|
||||
<div
|
||||
className={OVERLAY_TECHNOLOGY}
|
||||
|
@ -566,8 +461,6 @@ class CellEditorOverlay extends Component {
|
|||
>
|
||||
<Visualization
|
||||
axes={axes}
|
||||
colors={visualizationColors}
|
||||
type={cell.type}
|
||||
timeRange={timeRange}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
|
@ -590,15 +483,11 @@ class CellEditorOverlay extends Component {
|
|||
? <DisplayOptions
|
||||
axes={axes}
|
||||
gaugeColors={gaugeColors}
|
||||
singleStatColors={singleStatColors}
|
||||
onChooseColor={this.handleChooseColor}
|
||||
onValidateColorValue={this.handleValidateColorValue}
|
||||
onUpdateColorValue={this.handleUpdateColorValue}
|
||||
onAddGaugeThreshold={this.handleAddGaugeThreshold}
|
||||
onAddSingleStatThreshold={this.handleAddSingleStatThreshold}
|
||||
onDeleteThreshold={this.handleDeleteThreshold}
|
||||
onToggleSingleStatType={this.handleToggleSingleStatType}
|
||||
singleStatType={singleStatType}
|
||||
onSetBase={this.handleSetBase}
|
||||
onSetLabel={this.handleSetLabel}
|
||||
onSetScale={this.handleSetScale}
|
||||
|
@ -663,6 +552,8 @@ CellEditorOverlay.propTypes = {
|
|||
}).isRequired,
|
||||
dashboardID: string.isRequired,
|
||||
sources: arrayOf(shape()),
|
||||
singleStatType: string.isRequired,
|
||||
singleStatColors: arrayOf(shape({}).isRequired).isRequired,
|
||||
}
|
||||
|
||||
CEOBottom.propTypes = {
|
||||
|
|
|
@ -38,7 +38,6 @@ class DisplayOptions extends Component {
|
|||
const {
|
||||
cell,
|
||||
gaugeColors,
|
||||
singleStatColors,
|
||||
onSetBase,
|
||||
onSetScale,
|
||||
onSetLabel,
|
||||
|
@ -46,13 +45,10 @@ class DisplayOptions extends Component {
|
|||
onSetYAxisBoundMin,
|
||||
onSetYAxisBoundMax,
|
||||
onAddGaugeThreshold,
|
||||
onAddSingleStatThreshold,
|
||||
onDeleteThreshold,
|
||||
onChooseColor,
|
||||
onValidateColorValue,
|
||||
onUpdateColorValue,
|
||||
singleStatType,
|
||||
onToggleSingleStatType,
|
||||
onSetSuffix,
|
||||
} = this.props
|
||||
const {axes, axes: {y: {suffix}}} = this.state
|
||||
|
@ -70,20 +66,7 @@ class DisplayOptions extends Component {
|
|||
/>
|
||||
)
|
||||
case 'single-stat':
|
||||
return (
|
||||
<SingleStatOptions
|
||||
colors={singleStatColors}
|
||||
suffix={suffix}
|
||||
onSetSuffix={onSetSuffix}
|
||||
onChooseColor={onChooseColor}
|
||||
onValidateColorValue={onValidateColorValue}
|
||||
onUpdateColorValue={onUpdateColorValue}
|
||||
onAddThreshold={onAddSingleStatThreshold}
|
||||
onDeleteThreshold={onDeleteThreshold}
|
||||
singleStatType={singleStatType}
|
||||
onToggleSingleStatType={onToggleSingleStatType}
|
||||
/>
|
||||
)
|
||||
return <SingleStatOptions suffix={suffix} onSetSuffix={onSetSuffix} />
|
||||
default:
|
||||
return (
|
||||
<AxesOptions
|
||||
|
@ -113,7 +96,6 @@ const {arrayOf, func, number, shape, string} = PropTypes
|
|||
|
||||
DisplayOptions.propTypes = {
|
||||
onAddGaugeThreshold: func.isRequired,
|
||||
onAddSingleStatThreshold: func.isRequired,
|
||||
onDeleteThreshold: func.isRequired,
|
||||
onChooseColor: func.isRequired,
|
||||
onValidateColorValue: func.isRequired,
|
||||
|
@ -138,18 +120,7 @@ DisplayOptions.propTypes = {
|
|||
value: number.isRequired,
|
||||
}).isRequired
|
||||
),
|
||||
singleStatColors: arrayOf(
|
||||
shape({
|
||||
type: string.isRequired,
|
||||
hex: string.isRequired,
|
||||
id: string.isRequired,
|
||||
name: string.isRequired,
|
||||
value: number.isRequired,
|
||||
}).isRequired
|
||||
),
|
||||
queryConfigs: arrayOf(shape()).isRequired,
|
||||
singleStatType: string.isRequired,
|
||||
onToggleSingleStatType: func.isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({cellEditorOverlay: {cell}}) => ({
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import React, {Component, PropTypes} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import _ from 'lodash'
|
||||
import uuid from 'node-uuid'
|
||||
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
import Threshold from 'src/dashboards/components/Threshold'
|
||||
|
@ -7,106 +11,185 @@ import ColorDropdown from 'shared/components/ColorDropdown'
|
|||
|
||||
import {
|
||||
GAUGE_COLORS,
|
||||
DEFAULT_VALUE_MIN,
|
||||
DEFAULT_VALUE_MAX,
|
||||
MAX_THRESHOLDS,
|
||||
SINGLE_STAT_BASE,
|
||||
SINGLE_STAT_TEXT,
|
||||
SINGLE_STAT_BG,
|
||||
} from 'src/dashboards/constants/gaugeColors'
|
||||
|
||||
import {
|
||||
updateSingleStatType,
|
||||
updateSingleStatColors,
|
||||
} from 'src/dashboards/actions/cellEditorOverlay'
|
||||
|
||||
const formatColor = color => {
|
||||
const {hex, name} = color
|
||||
return {hex, name}
|
||||
}
|
||||
const SingleStatOptions = ({
|
||||
suffix,
|
||||
onSetSuffix,
|
||||
colors,
|
||||
onAddThreshold,
|
||||
onDeleteThreshold,
|
||||
onChooseColor,
|
||||
onValidateColorValue,
|
||||
onUpdateColorValue,
|
||||
singleStatType,
|
||||
onToggleSingleStatType,
|
||||
}) => {
|
||||
const disableAddThreshold = colors.length > MAX_THRESHOLDS
|
||||
|
||||
const sortedColors = _.sortBy(colors, color => color.value)
|
||||
class SingleStatOptions extends Component {
|
||||
handleToggleSingleStatType = newType => () => {
|
||||
const {handleUpdateSingleStatType} = this.props
|
||||
|
||||
return (
|
||||
<FancyScrollbar
|
||||
className="display-options--cell y-axis-controls"
|
||||
autoHide={false}
|
||||
>
|
||||
<div className="display-options--cell-wrapper">
|
||||
<h5 className="display-options--header">Single Stat Controls</h5>
|
||||
<div className="gauge-controls">
|
||||
<button
|
||||
className="btn btn-sm btn-primary gauge-controls--add-threshold"
|
||||
onClick={onAddThreshold}
|
||||
disabled={disableAddThreshold}
|
||||
>
|
||||
<span className="icon plus" /> Add Threshold
|
||||
</button>
|
||||
{sortedColors.map(
|
||||
color =>
|
||||
color.id === SINGLE_STAT_BASE
|
||||
? <div className="gauge-controls--section" key={color.id}>
|
||||
<div className="gauge-controls--label">Base Color</div>
|
||||
<ColorDropdown
|
||||
colors={GAUGE_COLORS}
|
||||
selected={formatColor(color)}
|
||||
onChoose={onChooseColor(color)}
|
||||
stretchToFit={true}
|
||||
handleUpdateSingleStatType(newType)
|
||||
}
|
||||
|
||||
handleAddThreshold = () => {
|
||||
const {
|
||||
singleStatColors,
|
||||
singleStatType,
|
||||
handleUpdateSingleStatColors,
|
||||
} = this.props
|
||||
|
||||
const randomColor = _.random(0, GAUGE_COLORS.length - 1)
|
||||
|
||||
const maxValue = DEFAULT_VALUE_MIN
|
||||
const minValue = DEFAULT_VALUE_MAX
|
||||
|
||||
let randomValue = _.round(_.random(minValue, maxValue, true), 2)
|
||||
|
||||
if (singleStatColors.length > 0) {
|
||||
const colorsValues = _.mapValues(singleStatColors, 'value')
|
||||
do {
|
||||
randomValue = _.round(_.random(minValue, maxValue, true), 2)
|
||||
} while (_.includes(colorsValues, randomValue))
|
||||
}
|
||||
|
||||
const newThreshold = {
|
||||
type: singleStatType,
|
||||
id: uuid.v4(),
|
||||
value: randomValue,
|
||||
hex: GAUGE_COLORS[randomColor].hex,
|
||||
name: GAUGE_COLORS[randomColor].name,
|
||||
}
|
||||
|
||||
handleUpdateSingleStatColors([...singleStatColors, newThreshold])
|
||||
}
|
||||
|
||||
handleDeleteThreshold = threshold => () => {
|
||||
const {handleUpdateSingleStatColors} = this.props
|
||||
|
||||
const singleStatColors = this.props.singleStatColors.filter(
|
||||
color => color.id !== threshold.id
|
||||
)
|
||||
|
||||
handleUpdateSingleStatColors(singleStatColors)
|
||||
}
|
||||
|
||||
handleChooseColor = threshold => chosenColor => {
|
||||
const {handleUpdateSingleStatColors} = this.props
|
||||
|
||||
const singleStatColors = this.props.singleStatColors.map(
|
||||
color =>
|
||||
color.id === threshold.id
|
||||
? {...color, hex: chosenColor.hex, name: chosenColor.name}
|
||||
: color
|
||||
)
|
||||
|
||||
handleUpdateSingleStatColors(singleStatColors)
|
||||
}
|
||||
|
||||
handleUpdateColorValue = (threshold, value) => {
|
||||
const {handleUpdateSingleStatColors} = this.props
|
||||
|
||||
const singleStatColors = this.props.singleStatColors.map(
|
||||
color => (color.id === threshold.id ? {...color, value} : color)
|
||||
)
|
||||
|
||||
handleUpdateSingleStatColors(singleStatColors)
|
||||
}
|
||||
|
||||
handleValidateColorValue = (threshold, targetValue) => {
|
||||
const {singleStatColors} = this.props
|
||||
const sortedColors = _.sortBy(singleStatColors, color => color.value)
|
||||
|
||||
return !sortedColors.some(color => color.value === targetValue)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {suffix, onSetSuffix, singleStatColors, singleStatType} = this.props
|
||||
|
||||
const disableAddThreshold = singleStatColors.length > MAX_THRESHOLDS
|
||||
|
||||
const sortedColors = _.sortBy(singleStatColors, color => color.value)
|
||||
|
||||
return (
|
||||
<FancyScrollbar
|
||||
className="display-options--cell y-axis-controls"
|
||||
autoHide={false}
|
||||
>
|
||||
<div className="display-options--cell-wrapper">
|
||||
<h5 className="display-options--header">Single Stat Controls</h5>
|
||||
<div className="gauge-controls">
|
||||
<button
|
||||
className="btn btn-sm btn-primary gauge-controls--add-threshold"
|
||||
onClick={this.handleAddThreshold}
|
||||
disabled={disableAddThreshold}
|
||||
>
|
||||
<span className="icon plus" /> Add Threshold
|
||||
</button>
|
||||
{sortedColors.map(
|
||||
color =>
|
||||
color.id === SINGLE_STAT_BASE
|
||||
? <div className="gauge-controls--section" key={color.id}>
|
||||
<div className="gauge-controls--label">Base Color</div>
|
||||
<ColorDropdown
|
||||
colors={GAUGE_COLORS}
|
||||
selected={formatColor(color)}
|
||||
onChoose={this.handleChooseColor(color)}
|
||||
stretchToFit={true}
|
||||
/>
|
||||
</div>
|
||||
: <Threshold
|
||||
visualizationType="single-stat"
|
||||
threshold={color}
|
||||
key={color.id}
|
||||
onChooseColor={this.handleChooseColor}
|
||||
onValidateColorValue={this.handleValidateColorValue}
|
||||
onUpdateColorValue={this.handleUpdateColorValue}
|
||||
onDeleteThreshold={this.handleDeleteThreshold}
|
||||
/>
|
||||
</div>
|
||||
: <Threshold
|
||||
visualizationType="single-stat"
|
||||
threshold={color}
|
||||
key={color.id}
|
||||
onChooseColor={onChooseColor}
|
||||
onValidateColorValue={onValidateColorValue}
|
||||
onUpdateColorValue={onUpdateColorValue}
|
||||
onDeleteThreshold={onDeleteThreshold}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="single-stat-controls">
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Coloring</label>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
<li
|
||||
className={`${singleStatType === SINGLE_STAT_BG
|
||||
? 'active'
|
||||
: ''}`}
|
||||
onClick={onToggleSingleStatType(SINGLE_STAT_BG)}
|
||||
>
|
||||
Background
|
||||
</li>
|
||||
<li
|
||||
className={`${singleStatType === SINGLE_STAT_TEXT
|
||||
? 'active'
|
||||
: ''}`}
|
||||
onClick={onToggleSingleStatType(SINGLE_STAT_TEXT)}
|
||||
>
|
||||
Text
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Suffix</label>
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
placeholder="%, MPH, etc."
|
||||
defaultValue={suffix}
|
||||
onChange={onSetSuffix}
|
||||
maxLength="5"
|
||||
/>
|
||||
<div className="single-stat-controls">
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Coloring</label>
|
||||
<ul className="nav nav-tablist nav-tablist-sm">
|
||||
<li
|
||||
className={`${singleStatType === SINGLE_STAT_BG
|
||||
? 'active'
|
||||
: ''}`}
|
||||
onClick={this.handleToggleSingleStatType(SINGLE_STAT_BG)}
|
||||
>
|
||||
Background
|
||||
</li>
|
||||
<li
|
||||
className={`${singleStatType === SINGLE_STAT_TEXT
|
||||
? 'active'
|
||||
: ''}`}
|
||||
onClick={this.handleToggleSingleStatType(SINGLE_STAT_TEXT)}
|
||||
>
|
||||
Text
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="form-group col-xs-6">
|
||||
<label>Suffix</label>
|
||||
<input
|
||||
className="form-control input-sm"
|
||||
placeholder="%, MPH, etc."
|
||||
defaultValue={suffix}
|
||||
onChange={onSetSuffix}
|
||||
maxLength="5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
)
|
||||
</FancyScrollbar>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {arrayOf, func, number, shape, string} = PropTypes
|
||||
|
@ -116,7 +199,8 @@ SingleStatOptions.defaultProps = {
|
|||
}
|
||||
|
||||
SingleStatOptions.propTypes = {
|
||||
colors: arrayOf(
|
||||
singleStatType: string.isRequired,
|
||||
singleStatColors: arrayOf(
|
||||
shape({
|
||||
type: string.isRequired,
|
||||
hex: string.isRequired,
|
||||
|
@ -125,15 +209,28 @@ SingleStatOptions.propTypes = {
|
|||
value: number.isRequired,
|
||||
}).isRequired
|
||||
),
|
||||
onAddThreshold: func.isRequired,
|
||||
onDeleteThreshold: func.isRequired,
|
||||
onChooseColor: func.isRequired,
|
||||
onValidateColorValue: func.isRequired,
|
||||
onUpdateColorValue: func.isRequired,
|
||||
singleStatType: string.isRequired,
|
||||
onToggleSingleStatType: func.isRequired,
|
||||
onSetSuffix: func.isRequired,
|
||||
suffix: string.isRequired,
|
||||
handleUpdateSingleStatType: func.isRequired,
|
||||
handleUpdateSingleStatColors: func.isRequired,
|
||||
}
|
||||
|
||||
export default SingleStatOptions
|
||||
const mapStateToProps = ({
|
||||
cellEditorOverlay: {singleStatType, singleStatColors},
|
||||
}) => ({
|
||||
singleStatType,
|
||||
singleStatColors,
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
handleUpdateSingleStatType: bindActionCreators(
|
||||
updateSingleStatType,
|
||||
dispatch
|
||||
),
|
||||
handleUpdateSingleStatColors: bindActionCreators(
|
||||
updateSingleStatColors,
|
||||
dispatch
|
||||
),
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SingleStatOptions)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import RefreshingGraph from 'shared/components/RefreshingGraph'
|
||||
import buildQueries from 'utils/buildQueriesForGraphs'
|
||||
import VisualizationName from 'src/dashboards/components/VisualizationName'
|
||||
|
@ -9,40 +11,41 @@ const DashVisualization = (
|
|||
{
|
||||
axes,
|
||||
type,
|
||||
colors,
|
||||
templates,
|
||||
timeRange,
|
||||
autoRefresh,
|
||||
queryConfigs,
|
||||
editQueryStatus,
|
||||
resizerTopHeight,
|
||||
singleStatColors,
|
||||
},
|
||||
{source: {links: {proxy}}}
|
||||
) =>
|
||||
<div className="graph">
|
||||
<VisualizationName />
|
||||
<div className="graph-container">
|
||||
<RefreshingGraph
|
||||
colors={stringifyColorValues(colors)}
|
||||
axes={axes}
|
||||
type={type}
|
||||
queries={buildQueries(proxy, queryConfigs, timeRange)}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
editQueryStatus={editQueryStatus}
|
||||
resizerTopHeight={resizerTopHeight}
|
||||
/>
|
||||
) => {
|
||||
// const colors = type === 'gauge' ? gaugeColors : singleStatColors
|
||||
|
||||
return (
|
||||
<div className="graph">
|
||||
<VisualizationName />
|
||||
<div className="graph-container">
|
||||
<RefreshingGraph
|
||||
colors={stringifyColorValues(singleStatColors)}
|
||||
axes={axes}
|
||||
type={type}
|
||||
queries={buildQueries(proxy, queryConfigs, timeRange)}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
editQueryStatus={editQueryStatus}
|
||||
resizerTopHeight={resizerTopHeight}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {arrayOf, func, number, shape, string} = PropTypes
|
||||
|
||||
DashVisualization.defaultProps = {
|
||||
type: '',
|
||||
}
|
||||
|
||||
DashVisualization.propTypes = {
|
||||
type: string,
|
||||
type: string.isRequired,
|
||||
autoRefresh: number.isRequired,
|
||||
templates: arrayOf(shape()),
|
||||
timeRange: shape({
|
||||
|
@ -57,15 +60,11 @@ DashVisualization.propTypes = {
|
|||
}),
|
||||
}),
|
||||
resizerTopHeight: number,
|
||||
colors: arrayOf(
|
||||
singleStatColors: arrayOf(
|
||||
shape({
|
||||
type: string.isRequired,
|
||||
hex: string.isRequired,
|
||||
id: string.isRequired,
|
||||
name: string.isRequired,
|
||||
value: number.isRequired,
|
||||
})
|
||||
),
|
||||
}).isRequired
|
||||
).isRequired,
|
||||
}
|
||||
|
||||
DashVisualization.contextTypes = {
|
||||
|
@ -76,4 +75,11 @@ DashVisualization.contextTypes = {
|
|||
}).isRequired,
|
||||
}
|
||||
|
||||
export default DashVisualization
|
||||
const mapStateToProps = ({
|
||||
cellEditorOverlay: {singleStatColors, cell: {type}},
|
||||
}) => ({
|
||||
singleStatColors,
|
||||
type,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(DashVisualization)
|
||||
|
|
|
@ -244,6 +244,8 @@ class DashboardPage extends Component {
|
|||
manualRefresh,
|
||||
onManualRefresh,
|
||||
cellQueryStatus,
|
||||
singleStatType,
|
||||
singleStatColors,
|
||||
dashboardActions,
|
||||
inPresentationMode,
|
||||
handleChooseAutoRefresh,
|
||||
|
@ -348,6 +350,8 @@ class DashboardPage extends Component {
|
|||
onCancel={handleHideCellEditorOverlay}
|
||||
templates={templatesIncludingDashTime}
|
||||
editQueryStatus={dashboardActions.editCellQueryStatus}
|
||||
singleStatType={singleStatType}
|
||||
singleStatColors={singleStatColors}
|
||||
/>
|
||||
: null}
|
||||
<DashboardHeader
|
||||
|
@ -473,6 +477,8 @@ DashboardPage.propTypes = {
|
|||
handleShowCellEditorOverlay: func.isRequired,
|
||||
handleHideCellEditorOverlay: func.isRequired,
|
||||
selectedCell: shape({}),
|
||||
singleStatType: string.isRequired,
|
||||
singleStatColors: arrayOf(shape({}).isRequired).isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = (state, {params: {dashboardID}}) => {
|
||||
|
@ -485,7 +491,7 @@ const mapStateToProps = (state, {params: {dashboardID}}) => {
|
|||
sources,
|
||||
dashTimeV1,
|
||||
auth: {me, isUsingAuth},
|
||||
cellEditorOverlay: {cell},
|
||||
cellEditorOverlay: {cell, singleStatType, singleStatColors},
|
||||
} = state
|
||||
const meRole = _.get(me, 'role', null)
|
||||
|
||||
|
@ -511,6 +517,8 @@ const mapStateToProps = (state, {params: {dashboardID}}) => {
|
|||
meRole,
|
||||
isUsingAuth,
|
||||
selectedCell,
|
||||
singleStatType,
|
||||
singleStatColors,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
import {
|
||||
SINGLE_STAT_TEXT,
|
||||
DEFAULT_SINGLESTAT_COLORS,
|
||||
validateSingleStatColors,
|
||||
getSingleStatType,
|
||||
} from 'src/dashboards/constants/gaugeColors'
|
||||
|
||||
const initialState = {
|
||||
cell: null,
|
||||
singleStatType: SINGLE_STAT_TEXT,
|
||||
singleStatColors: DEFAULT_SINGLESTAT_COLORS,
|
||||
}
|
||||
|
||||
export default function cellEditorOverlay(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case 'SHOW_CELL_EDITOR_OVERLAY': {
|
||||
const {cell} = action.payload
|
||||
const {cell, cell: {colors}} = action.payload
|
||||
|
||||
return {...state, cell}
|
||||
const singleStatType = getSingleStatType(colors)
|
||||
const singleStatColors = validateSingleStatColors(colors, singleStatType)
|
||||
|
||||
return {...state, cell, singleStatType, singleStatColors}
|
||||
}
|
||||
|
||||
case 'HIDE_CELL_EDITOR_OVERLAY': {
|
||||
|
@ -29,6 +41,23 @@ export default function cellEditorOverlay(state = initialState, action) {
|
|||
|
||||
return {...state, cell}
|
||||
}
|
||||
|
||||
case 'UPDATE_SINGLE_STAT_COLORS': {
|
||||
const {singleStatColors} = action.payload
|
||||
|
||||
return {...state, singleStatColors}
|
||||
}
|
||||
|
||||
case 'UPDATE_SINGLE_STAT_TYPE': {
|
||||
const {singleStatType} = action.payload
|
||||
|
||||
const singleStatColors = state.singleStatColors.map(color => ({
|
||||
...color,
|
||||
type: singleStatType,
|
||||
}))
|
||||
|
||||
return {...state, singleStatType, singleStatColors}
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
|
|
Loading…
Reference in New Issue