fix(ui): fix decimalPlaces with wrapper (#5073)

pull/5076/head
Delmer 2019-02-12 11:29:30 -05:00 committed by GitHub
parent 0913f97b67
commit ca9f8ace80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 140 additions and 15 deletions

View File

@ -1,8 +1,9 @@
## v1.7.8 [2019-02-08]
### Bug Fixes
1. [#5068](https://github.com/influxdata/chronograf/pull/5068): Escape injected meta query values
1. [#5073](https://github.com/influxdata/chronograf/pull/5073): Fix out of range decimal places
## v1.7.7 [2019-01-16]
## v1.7.7 [2018-01-16]
### Bug Fixes
1. [#5045](https://github.com/influxdata/chronograf/pull/5045): Use JWT in enterprise for authentication in flux

View File

@ -15,6 +15,7 @@ import {
} from 'src/types/dashboards'
import {TimeSeriesValue, InfluxQLQueryType} from 'src/types/series'
import {DataType} from 'src/shared/constants'
import {isTruncatedNumber, toFixed} from 'src/shared/utils/decimalPlaces'
const calculateSize = (message: string): number => {
return message.length * 7
@ -89,8 +90,8 @@ const updateMaxWidths = (
let colValue = `${col}`
if (foundField && foundField.displayName) {
colValue = foundField.displayName
} else if (_.isNumber(col) && decimalPlaces.isEnforced) {
colValue = col.toFixed(decimalPlaces.digits)
} else if (isTruncatedNumber(col, decimalPlaces)) {
colValue = toFixed(col, decimalPlaces)
}
const columnLabel = topRow[c]
@ -301,5 +302,18 @@ export const transformTableData = (
- `parseFloat('02abc')` is 2
*/
export const isNumerical = (x: any): boolean =>
!isNaN(Number(x)) && !isNaN(parseFloat(x))
export const isNumerical = <T>(x: T | string): x is string =>
!isNaN(Number(x)) && !isNaN(parseFloat(x as string))
export const formatNumericCell = (
cellData: string,
decimalPlaces: DecimalPlaces
) => {
const cellValue = parseFloat(cellData)
if (isTruncatedNumber(cellValue, decimalPlaces)) {
return toFixed(cellValue, decimalPlaces)
}
return `${cellValue}`
}

View File

@ -6,6 +6,8 @@ import uuid from 'uuid'
import ClickOutsideInput from 'src/shared/components/ClickOutsideInput'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {toValueInRange} from 'src/shared/utils/decimalPlaces'
interface Props {
min?: string
max?: string
@ -123,10 +125,18 @@ export default class OptIn extends Component<Props, State> {
this.useCustomValue()
}
// Typing into number inputs does not enforce min/max
private handleChangeCustomValue = (
e: ChangeEvent<HTMLInputElement>
): void => {
this.setCustomValue(e.target.value)
const {min, max} = this.props
const {value} = e.target
if (value === '') {
this.setCustomValue('')
} else {
this.setCustomValue(toValueInRange(value, min, max))
}
}
private handleKeyDownCustomValueInput = (

View File

@ -18,6 +18,7 @@ import {
} from 'src/shared/graphs/helpers'
import getLastValues from 'src/shared/parsing/lastValues'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {isTruncatedNumber, toFixed} from 'src/shared/utils/decimalPlaces'
// Constants
import {DYGRAPH_CONTAINER_V_MARGIN} from 'src/shared/constants'
@ -155,8 +156,8 @@ class SingleStat extends PureComponent<Props, State> {
let roundedValue = `${this.lastValue}`
if (decimalPlaces.isEnforced && _.isNumber(this.lastValue)) {
roundedValue = this.lastValue.toFixed(decimalPlaces.digits)
if (isTruncatedNumber(this.lastValue, decimalPlaces)) {
roundedValue = toFixed(this.lastValue, decimalPlaces)
}
return this.formatToLocale(+roundedValue)

View File

@ -12,7 +12,11 @@ import {MultiGrid, PropsMultiGrid} from 'src/shared/components/MultiGrid'
// Utils
import {fastReduce} from 'src/utils/fast'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {getDefaultTimeField, isNumerical} from 'src/dashboards/utils/tableGraph'
import {
getDefaultTimeField,
isNumerical,
formatNumericCell,
} from 'src/dashboards/utils/tableGraph'
// Constants
import {
@ -443,12 +447,8 @@ class TableGraph extends PureComponent<Props, State> {
return _.defaultTo(fieldName, '').toString()
}
if (
isNumerical(cellData) &&
decimalPlaces.isEnforced &&
decimalPlaces.digits < 100
) {
return parseFloat(cellData as any).toFixed(decimalPlaces.digits)
if (isNumerical(cellData)) {
return formatNumericCell(cellData, decimalPlaces)
}
return _.defaultTo(cellData, '').toString()

View File

@ -0,0 +1,45 @@
import {DecimalPlaces} from 'src/types/dashboards'
import {isNumerical} from 'src/dashboards/utils/tableGraph'
import {isFinite} from 'lodash'
export const isTruncatedNumber = <T>(
value: T | number,
decimalPlaces: DecimalPlaces
): value is number => isFinite(value) && decimalPlaces.isEnforced
export const toFixed = (
value: number,
decimalPlaces: DecimalPlaces
): string => {
const {digits} = decimalPlaces
if (!isFinite(digits)) {
return `${value}`
} else if (digits < 0) {
return value.toFixed(0)
} else if (digits > 20) {
return value.toFixed(20)
}
return value.toFixed(digits)
}
export const toValueInRange = (
stringValue: string,
min: string,
max: string
): string => {
if (!isNumerical(stringValue)) {
return min
}
const value = +parseFloat(stringValue).toFixed(0)
if (value < +min) {
return min
} else if (value > +max) {
return max
} else {
return `${value}`
}
}

View File

@ -0,0 +1,54 @@
import {
isTruncatedNumber,
toFixed,
toValueInRange,
} from 'src/shared/utils/decimalPlaces'
describe('decimalPlaces', () => {
const digits = (d: number) => ({isEnforced: true, digits: d})
describe('.toFixed', () => {
it('can skip fixing nonFinite digits', () => {
expect(toFixed(20.123456789, digits(Infinity))).toBe('20.123456789')
expect(toFixed(20.123456789, digits(-Infinity))).toBe('20.123456789')
expect(toFixed(20.123456789, digits(NaN))).toBe('20.123456789')
})
it('caps fixed digits to 20 decimal places', () => {
const value = 0.000000000931322574615478515625
expect(toFixed(value, digits(25))).toBe('0.00000000093132257462')
})
it('treats negative decimal places as 0', () => {
expect(toFixed(1234.56, digits(-1))).toBe('1235')
expect(toFixed(1234.12, digits(-1))).toBe('1234')
})
})
describe('.isTruncatedNumber', () => {
it('can return false for non finite numbers', () => {
expect(isTruncatedNumber(Infinity, digits(0))).toBe(false)
expect(isTruncatedNumber(-Infinity, digits(0))).toBe(false)
expect(isTruncatedNumber(-NaN, digits(0))).toBe(false)
})
})
describe('.toValueInRange', () => {
it('can return an integer value when provided a float', () => {
expect(toValueInRange('1.2', '0', '10')).toBe('1')
})
it('can enforce the min', () => {
expect(toValueInRange('1', '5', '10')).toBe('5')
})
it('can enforce the max', () => {
expect(toValueInRange('11', '-5', '0')).toBe('0')
})
it('can default to min', () => {
expect(toValueInRange('', '9999', '10000')).toBe('9999')
expect(toValueInRange('----', '9999', '10000')).toBe('9999')
expect(toValueInRange('-++++', '9999', '10000')).toBe('9999')
})
})
})