Add decimal place options to single-stat and line plus single stat

pull/10616/head
Andrew Watkins 2018-07-10 11:24:46 -07:00
parent a13e024e93
commit 1a5b800175
7 changed files with 116 additions and 33 deletions

View File

@ -6,6 +6,7 @@ import Input from 'src/dashboards/components/DisplayOptionsInput'
import {Tabber, Tab} from 'src/dashboards/components/Tabber'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import LineGraphColorSelector from 'src/shared/components/LineGraphColorSelector'
import GraphOptionsDecimalPlaces from 'src/dashboards/components/GraphOptionsDecimalPlaces'
import {
AXES_SCALE_OPTIONS,
@ -13,9 +14,13 @@ import {
} from 'src/dashboards/constants/cellEditor'
import {GRAPH_TYPES} from 'src/dashboards/graphics/graph'
import {updateAxes} from 'src/dashboards/actions/cellEditorOverlay'
import {
updateAxes,
changeDecimalPlaces,
} from 'src/dashboards/actions/cellEditorOverlay'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {Axes} from 'src/types'
import {Axes, CellType} from 'src/types'
import {DecimalPlaces} from 'src/types/dashboards'
const {LINEAR, LOG, BASE_2, BASE_10} = AXES_SCALE_OPTIONS
const getInputMin = scale => (scale === LOG ? '0' : null)
@ -25,6 +30,8 @@ interface Props {
axes: Axes
staticLegend: boolean
defaultYLabel: string
onUpdateDecimalPlaces: () => void
decimalPlaces: DecimalPlaces
handleUpdateAxes: (axes: Axes) => void
onToggleStaticLegend: (x: boolean) => (e: MouseEvent<HTMLLIElement>) => void
}
@ -152,6 +159,7 @@ class AxesOptions extends PureComponent<Props> {
onClickTab={this.handleSetScale(LOG)}
/>
</Tabber>
{this.decimalPlaces}
<Tabber labelText="Static Legend">
<Tab
text="Show"
@ -170,6 +178,22 @@ class AxesOptions extends PureComponent<Props> {
)
}
private get decimalPlaces(): JSX.Element {
const {onUpdateDecimalPlaces, decimalPlaces, type} = this.props
if (type !== CellType.LinePlusSingleStat) {
return null
}
return (
<GraphOptionsDecimalPlaces
digits={decimalPlaces.digits}
isEnforced={decimalPlaces.isEnforced}
onDecimalPlacesChange={onUpdateDecimalPlaces}
/>
)
}
private handleSetPrefixSuffix = e => {
const {handleUpdateAxes, axes} = this.props
const {prefix, suffix} = e.target.form
@ -247,6 +271,7 @@ const mstp = ({
const mdtp = {
handleUpdateAxes: updateAxes,
onUpdateDecimalPlaces: changeDecimalPlaces,
}
export default connect(mstp, mdtp)(AxesOptions)

View File

@ -80,6 +80,7 @@ class DisplayOptions extends PureComponent<Props, State> {
<AxesOptions
staticLegend={staticLegend}
defaultYLabel={defaultYLabel}
decimalPlaces={cell.decimalPlaces}
onToggleStaticLegend={onToggleStaticLegend}
/>
)

View File

@ -9,6 +9,7 @@ interface Props extends DecimalPlaces {
}
const fixedValueString = 'fixed'
const defaultPlaceholder = 'unlimited'
@ErrorHandling
class GraphOptionsDecimalPlaces extends PureComponent<Props> {
@ -16,7 +17,7 @@ class GraphOptionsDecimalPlaces extends PureComponent<Props> {
super(props)
}
public onSetValue = (valueFromSelector: string): void => {
public handleSetValue = (valueFromSelector: string): void => {
let digits
let isEnforced
if (valueFromSelector === fixedValueString) {
@ -36,22 +37,40 @@ class GraphOptionsDecimalPlaces extends PureComponent<Props> {
}
public render() {
const {digits, isEnforced} = this.props
return (
<div className="form-group col-xs-6">
<label> Decimal Places </label>
<OptIn
customPlaceholder={isEnforced ? digits.toString() : 'unlimited'}
customValue={isEnforced ? digits.toString() : ''}
onSetValue={this.onSetValue}
fixedPlaceholder={''}
fixedValue={fixedValueString}
min="0"
type="number"
min={'0'}
fixedPlaceholder=""
customValue={this.value}
fixedValue={fixedValueString}
onSetValue={this.handleSetValue}
customPlaceholder={this.placeholder}
/>
</div>
)
}
private get placeholder(): string {
const {isEnforced, digits} = this.props
if (!isEnforced) {
return defaultPlaceholder
}
return `${digits}`
}
private get value(): string {
const {isEnforced, digits} = this.props
if (!isEnforced) {
return ''
}
return `${digits}`
}
}
export default GraphOptionsDecimalPlaces

View File

@ -4,15 +4,22 @@ import {connect} from 'react-redux'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import ThresholdsList from 'src/shared/components/ThresholdsList'
import ThresholdsListTypeToggle from 'src/shared/components/ThresholdsListTypeToggle'
import GraphOptionsDecimalPlaces from 'src/dashboards/components/GraphOptionsDecimalPlaces'
import {updateAxes} from 'src/dashboards/actions/cellEditorOverlay'
import {
updateAxes,
changeDecimalPlaces,
} from 'src/dashboards/actions/cellEditorOverlay'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {Axes} from 'src/types'
import {DecimalPlaces} from 'src/types/dashboards'
interface Props {
handleUpdateAxes: (axes: Axes) => void
axes: Axes
decimalPlaces: DecimalPlaces
onResetFocus: () => void
onUpdateAxes: (axes: Axes) => void
onUpdateDecimalPlaces: (decimalPlaces: DecimalPlaces) => void
}
@ErrorHandling
@ -23,6 +30,7 @@ class SingleStatOptions extends PureComponent<Props> {
y: {prefix, suffix},
},
onResetFocus,
decimalPlaces,
} = this.props
return (
@ -54,6 +62,11 @@ class SingleStatOptions extends PureComponent<Props> {
maxLength={5}
/>
</div>
<GraphOptionsDecimalPlaces
digits={decimalPlaces.digits}
isEnforced={decimalPlaces.isEnforced}
onDecimalPlacesChange={this.handleDecimalPlacesChange}
/>
<ThresholdsListTypeToggle containerClass="form-group col-xs-6" />
</div>
</div>
@ -61,27 +74,34 @@ class SingleStatOptions extends PureComponent<Props> {
)
}
private handleDecimalPlacesChange = (decimalPlaces: DecimalPlaces) => {
const {onUpdateDecimalPlaces} = this.props
onUpdateDecimalPlaces(decimalPlaces)
}
private handleUpdatePrefix = e => {
const {handleUpdateAxes, axes} = this.props
const {onUpdateAxes, axes} = this.props
const newAxes = {...axes, y: {...axes.y, prefix: e.target.value}}
handleUpdateAxes(newAxes)
onUpdateAxes(newAxes)
}
private handleUpdateSuffix = e => {
const {handleUpdateAxes, axes} = this.props
const {onUpdateAxes, axes} = this.props
const newAxes = {...axes, y: {...axes.y, suffix: e.target.value}}
handleUpdateAxes(newAxes)
onUpdateAxes(newAxes)
}
}
const mstp = ({cellEditorOverlay}) => ({
axes: cellEditorOverlay.cell.axes,
decimalPlaces: cellEditorOverlay.cell.decimalPlaces,
})
const mdtp = {
handleUpdateAxes: updateAxes,
onUpdateAxes: updateAxes,
onUpdateDecimalPlaces: changeDecimalPlaces,
}
export default connect(mstp, mdtp)(SingleStatOptions)

View File

@ -11,6 +11,7 @@ import {
import {ErrorHandlingWith} from 'src/shared/decorators/errors'
import InvalidData from 'src/shared/components/InvalidData'
import {Query, Axes, RuleValues, TimeRange} from 'src/types'
import {DecimalPlaces} from 'src/types/dashboards'
import {ColorString} from 'src/types/colors'
import {Data} from 'src/types/dygraphs'
@ -48,6 +49,7 @@ interface Props {
data: Data
queries: Query[]
colors: ColorString[]
decimalPlaces: DecimalPlaces
underlayCallback?: () => void
setResolution: () => void
handleSetHoverTime: () => void
@ -109,6 +111,7 @@ class LineGraph extends PureComponent<Props> {
showSingleStat,
displayOptions,
staticLegend,
decimalPlaces,
underlayCallback,
isFetchingInitially,
handleSetHoverTime,
@ -167,6 +170,7 @@ class LineGraph extends PureComponent<Props> {
prefix={this.prefix}
suffix={this.suffix}
cellHeight={cellHeight}
decimalPlaces={decimalPlaces}
isFetchingInitially={isFetchingInitially}
/>
)}

View File

@ -32,13 +32,13 @@ const RefreshingGraph = ({
cellID,
queries,
source,
tableOptions,
templates,
timeRange,
cellHeight,
autoRefresh,
fieldOptions,
timeFormat,
tableOptions,
decimalPlaces,
onSetResolution,
resizerTopHeight,
@ -62,18 +62,19 @@ const RefreshingGraph = ({
if (type === 'single-stat') {
return (
<RefreshingSingleStat
source={source}
type={type}
source={source}
colors={colors}
key={manualRefresh}
queries={[queries[0]]}
templates={templates}
autoRefresh={autoRefresh}
cellHeight={cellHeight}
editQueryStatus={editQueryStatus}
prefix={prefix}
suffix={suffix}
inView={inView}
key={manualRefresh}
templates={templates}
queries={[queries[0]]}
cellHeight={cellHeight}
autoRefresh={autoRefresh}
decimalPlaces={decimalPlaces}
editQueryStatus={editQueryStatus}
onSetResolution={onSetResolution}
/>
)
@ -149,6 +150,7 @@ const RefreshingGraph = ({
cellHeight={cellHeight}
autoRefresh={autoRefresh}
isBarGraph={type === 'bar'}
decimalPlaces={decimalPlaces}
staticLegend={staticLegend}
displayOptions={displayOptions}
editQueryStatus={editQueryStatus}

View File

@ -7,12 +7,13 @@ import {SMALL_CELL_HEIGHT} from 'src/shared/graphs/helpers'
import {DYGRAPH_CONTAINER_V_MARGIN} from 'src/shared/constants'
import {generateThresholdsListHexs} from 'src/shared/constants/colorOperations'
import {ColorString} from 'src/types/colors'
import {CellType} from 'src/types/dashboards'
import {CellType, DecimalPlaces} from 'src/types/dashboards'
import {Data} from 'src/types/dygraphs'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
isFetchingInitially: boolean
decimalPlaces: DecimalPlaces
cellHeight: number
colors: ColorString[]
prefix?: string
@ -59,21 +60,32 @@ class SingleStat extends PureComponent<Props> {
return `${prefix}${this.roundedLastValue}${suffix}`
}
private get roundedLastValue(): string {
private get lastValue(): number {
const {data} = this.props
const {lastValues, series} = getLastValues(data)
const firstAlphabeticalSeriesName = _.sortBy(series)[0]
const firstAlphabeticalindex = _.indexOf(
const firstAlphabeticalIndex = _.indexOf(
series,
firstAlphabeticalSeriesName
)
const lastValue = lastValues[firstAlphabeticalindex]
const HUNDRED = 100.0
const roundedValue = Math.round(+lastValue * HUNDRED) / HUNDRED
const localeFormatted = roundedValue.toLocaleString()
return `${localeFormatted}`
return lastValues[firstAlphabeticalIndex]
}
private get roundedLastValue(): string {
const {decimalPlaces} = this.props
let roundedValue = `${this.lastValue}`
if (decimalPlaces.isEnforced) {
roundedValue = this.lastValue.toFixed(decimalPlaces.digits)
}
return this.formatToLocale(+roundedValue)
}
private formatToLocale(n: number): string {
return n.toLocaleString()
}
private get containerStyle(): CSSProperties {