Update vis types to not assume there is a time field

pull/4486/head
Iris Scholten 2018-09-21 11:40:36 -07:00
parent 2e4e978c3d
commit c107beaf49
5 changed files with 86 additions and 79 deletions

View File

@ -80,15 +80,17 @@ const updateMaxWidths = (
}
const columnLabel = topRow[c]
const isTimeColumn =
columnLabel === DEFAULT_INFLUXQL_TIME_FIELD.internalName ||
columnLabel === DEFAULT_FLUX_TIME_FIELD.internalName
const isTimeRow =
topRow[0] === DEFAULT_INFLUXQL_TIME_FIELD.internalName ||
topRow[0] === DEFAULT_FLUX_TIME_FIELD.internalName
const useTimeWidth =
(columnLabel === DEFAULT_INFLUXQL_TIME_FIELD.internalName &&
verticalTimeAxis &&
!isTopRow) ||
(!verticalTimeAxis &&
isTopRow &&
topRow[0] === DEFAULT_INFLUXQL_TIME_FIELD.internalName &&
c !== 0)
(isTimeColumn && verticalTimeAxis && !isTopRow) ||
(!verticalTimeAxis && isTopRow && isTimeRow && c !== 0)
const currentWidth = useTimeWidth
? timeFormatWidth
@ -110,23 +112,12 @@ const updateMaxWidths = (
return maxWidths
}
export const getTimeField = (
fieldOptions: FieldOption[],
dataType: DataType
): FieldOption => {
export const getDefaultTimeField = (dataType: DataType): FieldOption => {
if (dataType === DataType.flux) {
return (
fieldOptions.find(
f => f.internalName === DEFAULT_FLUX_TIME_FIELD.internalName
) || DEFAULT_FLUX_TIME_FIELD
)
return DEFAULT_FLUX_TIME_FIELD
}
return (
fieldOptions.find(
f => f.internalName === DEFAULT_INFLUXQL_TIME_FIELD.internalName
) || DEFAULT_INFLUXQL_TIME_FIELD
)
return DEFAULT_INFLUXQL_TIME_FIELD
}
export const computeFieldOptions = (
@ -134,18 +125,16 @@ export const computeFieldOptions = (
sortedLabels: SortedLabel[],
dataType: DataType
): FieldOption[] => {
const timeField = getTimeField(existingFieldOptions, dataType)
const defaultTimeField = getDefaultTimeField(dataType)
let astNames = [timeField]
let astNames = dataType === DataType.influxQL ? [defaultTimeField] : []
sortedLabels.forEach(({label}) => {
if (label !== timeField.internalName) {
const field: FieldOption = {
internalName: label,
displayName: '',
visible: true,
}
astNames = [...astNames, field]
const field: FieldOption = {
internalName: label,
displayName: '',
visible: true,
}
astNames = [...astNames, field]
})
const intersection = existingFieldOptions.filter(f => {

View File

@ -5,6 +5,7 @@ import {manager} from 'src/worker/JobManager'
import getLastValues from 'src/shared/parsing/lastValues'
import Gauge from 'src/shared/components/Gauge'
import InvalidData from 'src/shared/components/InvalidData'
import {DEFAULT_GAUGE_COLORS} from 'src/shared/constants/thresholds'
import {stringifyColorValues} from 'src/shared/constants/colorOperations'
@ -33,6 +34,7 @@ interface State {
values: number[]
series: string[]
}
isValidData: boolean
}
@ErrorHandling
@ -46,7 +48,7 @@ class GaugeChart extends PureComponent<Props, State> {
constructor(props: Props) {
super(props)
this.state = {}
this.state = {isValidData: true}
}
public async componentDidMount() {
@ -70,6 +72,14 @@ class GaugeChart extends PureComponent<Props, State> {
public render() {
const {colors, prefix, suffix, decimalPlaces} = this.props
if (!this.state.isValidData) {
return <InvalidData />
}
if (!this.state.lastValues) {
return <h3 className="graph-spinner" />
}
return (
<div className="single-stat">
<Gauge
@ -115,8 +125,9 @@ class GaugeChart extends PureComponent<Props, State> {
private async dataToLastValues() {
const {data, dataType} = this.props
let lastValues
let isValidData = true
try {
let lastValues
if (dataType === DataType.flux) {
lastValues = await manager.fluxTablesToSingleStat(data as FluxTable[])
} else if (dataType === DataType.influxQL) {
@ -126,11 +137,10 @@ class GaugeChart extends PureComponent<Props, State> {
if (!this.isComponentMounted) {
return
}
this.setState({lastValues})
} catch (err) {
console.error(err)
isValidData = false
}
this.setState({lastValues, isValidData})
}
}

View File

@ -1,5 +1,6 @@
// Libraries
import React, {PureComponent, CSSProperties} from 'react'
import _ from 'lodash'
import Dygraph from 'src/shared/components/Dygraph'
import {withRouter, RouteComponentProps} from 'react-router'
@ -83,25 +84,30 @@ class LineGraph extends PureComponent<LineGraphProps, State> {
data: TimeSeriesServerResponse[] | FluxTable[],
dataType: DataType
) {
let timeSeries
try {
const timeSeries = await this.convertToDygraphData(data, dataType)
timeSeries = await this.convertToDygraphData(data, dataType)
this.isValidData = await manager.validateDygraphData(
timeSeries.timeSeries
)
if (!this.isComponentMounted) {
return
}
this.setState({timeSeries})
this.isValidData = await manager.validateDygraphData(
timeSeries.timeSeries
)
} catch (err) {
this.isValidData = false
}
this.setState({timeSeries})
}
public componentWillReceiveProps(nextProps: LineGraphProps) {
if (nextProps.loading === RemoteDataState.Done) {
this.parseTimeSeries(nextProps.data, nextProps.dataType)
public componentDidUpdate(prevProps: LineGraphProps) {
const isDataChanged =
prevProps.data.length !== this.props.data.length ||
!_.isEqual(_.get(prevProps, 'data.0.id'), _.get(this.props, 'data.0.id'))
if (this.props.loading === RemoteDataState.Done && isDataChanged) {
this.parseTimeSeries(this.props.data, this.props.dataType)
}
}
@ -109,7 +115,6 @@ class LineGraph extends PureComponent<LineGraphProps, State> {
if (!this.isValidData) {
return <InvalidData />
}
const {
data,
axes,

View File

@ -4,6 +4,8 @@ import getLastValues from 'src/shared/parsing/lastValues'
import _ from 'lodash'
import {manager} from 'src/worker/JobManager'
import InvalidData from 'src/shared/components/InvalidData'
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'
@ -32,6 +34,7 @@ interface State {
values: number[]
series: string[]
}
isValidData: boolean
}
const NOOP = () => {}
@ -49,7 +52,7 @@ class SingleStat extends PureComponent<Props, State> {
constructor(props: Props) {
super(props)
this.state = {}
this.state = {isValidData: true}
}
public async componentDidMount() {
@ -72,6 +75,9 @@ class SingleStat extends PureComponent<Props, State> {
}
public render() {
if (!this.state.isValidData) {
return <InvalidData />
}
if (!this.state.lastValues) {
return <h3 className="graph-spinner" />
}
@ -223,8 +229,9 @@ class SingleStat extends PureComponent<Props, State> {
private async dataToLastValues() {
const {data, dataType} = this.props
let lastValues
let isValidData = true
try {
let lastValues
if (dataType === DataType.flux) {
lastValues = await manager.fluxTablesToSingleStat(data as FluxTable[])
} else if (dataType === DataType.influxQL) {
@ -234,11 +241,10 @@ class SingleStat extends PureComponent<Props, State> {
if (!this.isComponentMounted) {
return
}
this.setState({lastValues})
} catch (err) {
console.error(err)
isValidData = false
}
this.setState({lastValues, isValidData})
}
}

View File

@ -9,13 +9,12 @@ import {MultiGrid, PropsMultiGrid} from 'src/shared/components/MultiGrid'
import {bindActionCreators} from 'redux'
import {fastReduce} from 'src/utils/fast'
import {timeSeriesToTableGraph} from 'src/utils/timeSeriesTransformers'
import {computeFieldOptions} from 'src/dashboards/utils/tableGraph'
import {
computeFieldOptions,
getDefaultTimeField,
} from 'src/dashboards/utils/tableGraph'
import {updateFieldOptions} from 'src/shared/actions/visualizations'
import {QueryUpdateState} from 'src/shared/actions/queries'
import {
DEFAULT_INFLUXQL_TIME_FIELD,
DEFAULT_FLUX_TIME_FIELD,
} from 'src/dashboards/constants'
import {
ASCENDING,
DESCENDING,
@ -95,16 +94,12 @@ class TableGraph extends PureComponent<Props, State> {
constructor(props: Props) {
super(props)
const defaultTimeField =
props.dataType === DataType.flux
? DEFAULT_FLUX_TIME_FIELD
: DEFAULT_INFLUXQL_TIME_FIELD
const sortField: string = _.get(
this.props,
'tableOptions.sortBy.internalName',
defaultTimeField.internalName
''
)
this.state = {
shouldResize: false,
data: [[]],
@ -208,14 +203,18 @@ class TableGraph extends PureComponent<Props, State> {
let sortField: string = _.get(
this.props,
['tableOptions', 'sortBy', 'internalName'],
this.defaultTimeField.internalName
''
)
const isValidSortField = !!fieldOptions.find(
f => f.internalName === sortField
)
if (!isValidSortField) {
sortField = this.defaultTimeField.internalName
sortField = _.get(
this.defaultTimeField,
'internalName',
_.get(fieldOptions, '0.internalName', '')
)
}
const sort: Sort = {field: sortField, direction: DEFAULT_SORT_DIRECTION}
@ -246,7 +245,7 @@ class TableGraph extends PureComponent<Props, State> {
decimalPlaces
)
const isTimeVisible = _.get(this.timeField, 'visible', true)
const isTimeVisible = _.get(this.timeField, 'visible', false)
this.setState(
{
@ -312,12 +311,17 @@ class TableGraph extends PureComponent<Props, State> {
f => f.internalName === sortField
)
const defaultTimeField = getDefaultTimeField(dataType)
if (!isValidSortField) {
const defaultTimeField =
dataType === DataType.flux
? DEFAULT_FLUX_TIME_FIELD
: DEFAULT_INFLUXQL_TIME_FIELD
sortField = defaultTimeField.internalName
const timeField = fieldOptions.find(
f => f.internalName === defaultTimeField.internalName
)
sortField = _.get(
timeField,
'internalName',
_.get(fieldOptions, '0.internalName', '')
)
}
if (
@ -349,12 +353,9 @@ class TableGraph extends PureComponent<Props, State> {
let isTimeVisible = this.state.isTimeVisible
if (_.includes(updatedProps, 'fieldOptions')) {
const timeField = _.find(nextProps.fieldOptions, f => {
if (dataType === DataType.flux) {
return f.internalName === DEFAULT_FLUX_TIME_FIELD.internalName
}
return f.internalName === DEFAULT_INFLUXQL_TIME_FIELD.internalName
return f.internalName === defaultTimeField.internalName
})
isTimeVisible = _.get(timeField, 'visible', this.state.isTimeVisible)
isTimeVisible = _.get(timeField, 'visible', false)
}
if (!this.isComponentMounted) {
@ -601,11 +602,7 @@ class TableGraph extends PureComponent<Props, State> {
private get defaultTimeField(): FieldOption {
const {dataType} = this.props
if (dataType === DataType.flux) {
return DEFAULT_FLUX_TIME_FIELD
}
return DEFAULT_INFLUXQL_TIME_FIELD
return getDefaultTimeField(dataType)
}
private get timeFieldIndex(): number {