{
- private lastValue = memoizeOne(lastValue)
-
public render() {
- const {tables} = this.props
+ const {value} = this.props
const {colors, prefix, suffix, decimalPlaces} = this.props.properties
- const lastValue = this.lastValue(tables) || 0
-
return (
{
colors={colors}
prefix={prefix}
suffix={suffix}
- gaugePosition={lastValue}
+ gaugePosition={value}
decimalPlaces={decimalPlaces}
/>
diff --git a/ui/src/shared/components/LatestValueTransform.tsx b/ui/src/shared/components/LatestValueTransform.tsx
new file mode 100644
index 0000000000..ed30426d81
--- /dev/null
+++ b/ui/src/shared/components/LatestValueTransform.tsx
@@ -0,0 +1,40 @@
+// Libraries
+import React, {useMemo, FunctionComponent} from 'react'
+import {Table} from '@influxdata/vis'
+
+// Components
+import EmptyGraphMessage from 'src/shared/components/EmptyGraphMessage'
+
+// Utils
+import {latestValues as getLatestValues} from 'src/shared/utils/latestValues'
+
+interface Props {
+ table: Table
+ children: (latestValue: number) => JSX.Element
+
+ // If `quiet` is set and a latest value can't be found, this component will
+ // display nothing instead of an empty graph error message
+ quiet?: boolean
+}
+
+const LatestValueTransform: FunctionComponent = ({
+ table,
+ quiet = false,
+ children,
+}) => {
+ const latestValues = useMemo(() => getLatestValues(table), [table])
+
+ if (latestValues.length === 0 && quiet) {
+ return null
+ }
+
+ if (latestValues.length === 0) {
+ return
+ }
+
+ const latestValue = latestValues[0]
+
+ return children(latestValue)
+}
+
+export default LatestValueTransform
diff --git a/ui/src/shared/components/RefreshingViewSwitcher.tsx b/ui/src/shared/components/RefreshingViewSwitcher.tsx
index 821f2f2e1e..4fefe79b48 100644
--- a/ui/src/shared/components/RefreshingViewSwitcher.tsx
+++ b/ui/src/shared/components/RefreshingViewSwitcher.tsx
@@ -5,11 +5,11 @@ import {Plot} from '@influxdata/vis'
// Components
import GaugeChart from 'src/shared/components/GaugeChart'
import SingleStat from 'src/shared/components/SingleStat'
-import SingleStatTransform from 'src/shared/components/SingleStatTransform'
import TableGraphs from 'src/shared/components/tables/TableGraphs'
import HistogramContainer from 'src/shared/components/HistogramContainer'
import VisTableTransform from 'src/shared/components/VisTableTransform'
import XYContainer from 'src/shared/components/XYContainer'
+import LatestValueTransform from 'src/shared/components/LatestValueTransform'
// Types
import {
@@ -37,14 +37,30 @@ const RefreshingViewSwitcher: FunctionComponent = ({
switch (properties.type) {
case ViewType.SingleStat:
return (
-
- {stat => }
-
+
+ {table => (
+
+ {latestValue => (
+
+ )}
+
+ )}
+
)
case ViewType.Table:
return
case ViewType.Gauge:
- return
+ return (
+
+ {table => (
+
+ {latestValue => (
+
+ )}
+
+ )}
+
+ )
case ViewType.XY:
return (
= ({
>
{config => (
-
- {stat => (
-
+
+ {latestValue => (
+
)}
-
+
)}
diff --git a/ui/src/shared/components/SingleStatTransform.tsx b/ui/src/shared/components/SingleStatTransform.tsx
deleted file mode 100644
index 162efb8f63..0000000000
--- a/ui/src/shared/components/SingleStatTransform.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-// Libraries
-import React, {PureComponent} from 'react'
-import memoizeOne from 'memoize-one'
-import _ from 'lodash'
-
-// Components
-import EmptyGraphMessage from 'src/shared/components/EmptyGraphMessage'
-
-// Parsing
-import {lastValue} from 'src/shared/parsing/flux/lastValue'
-
-// Types
-import {FluxTable} from 'src/types'
-
-const NON_NUMERIC_ERROR =
- 'Could not display single stat because your values are non-numeric'
-
-interface Props {
- tables: FluxTable[]
- children: (stat: number) => JSX.Element
-}
-
-export default class SingleStatTransform extends PureComponent {
- private lastValue = memoizeOne(lastValue)
-
- public render() {
- const {tables} = this.props
- const lastValue = this.lastValue(tables)
-
- if (!_.isFinite(lastValue)) {
- return
- }
-
- return this.props.children(lastValue)
- }
-}
diff --git a/ui/src/shared/parsing/flux/__snapshots__/spreadTables.test.ts.snap b/ui/src/shared/parsing/flux/__snapshots__/spreadTables.test.ts.snap
deleted file mode 100644
index cd3a5f51b0..0000000000
--- a/ui/src/shared/parsing/flux/__snapshots__/spreadTables.test.ts.snap
+++ /dev/null
@@ -1,48 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`spreadTables it spreads multiple series into a single table 1`] = `
-Object {
- "seriesDescriptions": Array [
- Object {
- "key": "_value[result=max][_field=active][_measurement=mem][host=oox4k.local]",
- "metaColumns": Object {
- "_field": "active",
- "_measurement": "mem",
- "host": "oox4k.local",
- "result": "max",
- },
- "valueColumnIndex": 6,
- "valueColumnName": "_value",
- },
- Object {
- "key": "_value[result=min][_field=active][_measurement=mem][host=oox4k.local]",
- "metaColumns": Object {
- "_field": "active",
- "_measurement": "mem",
- "host": "oox4k.local",
- "result": "min",
- },
- "valueColumnIndex": 6,
- "valueColumnName": "_value",
- },
- ],
- "table": Object {
- "2018-12-10T18:29:48Z": Object {
- "_value[result=min][_field=active][_measurement=mem][host=oox4k.local]": 4589981696,
- },
- "2018-12-10T18:29:58Z": Object {
- "_value[result=max][_field=active][_measurement=mem][host=oox4k.local]": 4906213376,
- },
- "2018-12-10T18:40:18Z": Object {
- "_value[result=min][_field=active][_measurement=mem][host=oox4k.local]": 4318040064,
- },
- "2018-12-10T18:54:08Z": Object {
- "_value[result=max][_field=active][_measurement=mem][host=oox4k.local]": 5860683776,
- },
- "2018-12-10T19:11:58Z": Object {
- "_value[result=max][_field=active][_measurement=mem][host=oox4k.local]": 5115428864,
- "_value[result=min][_field=active][_measurement=mem][host=oox4k.local]": 4131692544,
- },
- },
-}
-`;
diff --git a/ui/src/shared/parsing/flux/lastValue.test.ts b/ui/src/shared/parsing/flux/lastValue.test.ts
deleted file mode 100644
index 17a4db69b3..0000000000
--- a/ui/src/shared/parsing/flux/lastValue.test.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import {lastValue} from 'src/shared/parsing/flux/lastValue'
-import {parseResponse} from 'src/shared/parsing/flux/response'
-
-describe('lastValue', () => {
- test('the last value returned does not depend on the ordering of series', () => {
- const respA = `#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,0,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:58Z,1,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:54:08Z,2,active,mem,oox4k.local
-
-#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,1,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:48Z,3,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:40:18Z,4,active,mem,oox4k.local
-
-`
-
- const respB = `#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,1,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:48Z,3,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:40:18Z,4,active,mem,oox4k.local
-
-#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,0,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:58Z,1,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:54:08Z,2,active,mem,oox4k.local
-
-`
-
- const lastValueA = lastValue(parseResponse(respA))
- const lastValueB = lastValue(parseResponse(respB))
-
- expect(lastValueA).toEqual(2)
- expect(lastValueB).toEqual(2)
- })
-})
diff --git a/ui/src/shared/parsing/flux/lastValue.ts b/ui/src/shared/parsing/flux/lastValue.ts
deleted file mode 100644
index 6727e4e83d..0000000000
--- a/ui/src/shared/parsing/flux/lastValue.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import {spreadTables} from 'src/shared/parsing/flux/spreadTables'
-
-import {FluxTable} from 'src/types'
-
-export const lastValue = (tables: FluxTable[]): number => {
- if (tables.every(table => !table.data.length)) {
- return null
- }
-
- const {table, seriesDescriptions} = spreadTables(tables)
- const seriesKeys = seriesDescriptions.map(d => d.key)
- const times = Object.keys(table)
-
- times.sort()
- seriesKeys.sort()
-
- const lastTime = times[times.length - 1]
- const firstSeriesKey = seriesKeys[0]
-
- return table[lastTime][firstSeriesKey]
-}
diff --git a/ui/src/shared/parsing/flux/spreadTables.test.ts b/ui/src/shared/parsing/flux/spreadTables.test.ts
deleted file mode 100644
index c9ee042fe1..0000000000
--- a/ui/src/shared/parsing/flux/spreadTables.test.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import {parseResponse} from 'src/shared/parsing/flux/response'
-import {spreadTables} from 'src/shared/parsing/flux/spreadTables'
-
-describe('spreadTables', () => {
- test('it spreads multiple series into a single table', () => {
- const resp = `#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,max,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:58Z,4906213376,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:54:08Z,5860683776,active,mem,oox4k.local
-,,0,2018-12-10T19:00:00Z,2018-12-10T19:21:52.748859Z,2018-12-10T19:11:58Z,5115428864,active,mem,oox4k.local
-
-#group,false,false,false,false,false,false,true,true,true
-#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,long,string,string,string
-#default,min,,,,,,,,
-,result,table,_start,_stop,_time,_value,_field,_measurement,host
-,,0,2018-12-10T18:21:52.748859Z,2018-12-10T18:30:00Z,2018-12-10T18:29:48Z,4589981696,active,mem,oox4k.local
-,,0,2018-12-10T18:30:00Z,2018-12-10T19:00:00Z,2018-12-10T18:40:18Z,4318040064,active,mem,oox4k.local
-,,0,2018-12-10T19:00:00Z,2018-12-10T19:21:52.748859Z,2018-12-10T19:11:58Z,4131692544,active,mem,oox4k.local
-
-`
-
- const result = spreadTables(parseResponse(resp))
-
- expect(result).toMatchSnapshot()
- })
-})
diff --git a/ui/src/shared/parsing/flux/spreadTables.ts b/ui/src/shared/parsing/flux/spreadTables.ts
deleted file mode 100644
index f955a51ad1..0000000000
--- a/ui/src/shared/parsing/flux/spreadTables.ts
+++ /dev/null
@@ -1,133 +0,0 @@
-import {FluxTable} from 'src/types'
-
-export interface SeriesDescription {
- // A key identifying a unique (column, table, result) triple for a particular
- // Flux response—i.e. a single time series
- key: string
- // The name of the column that this series is extracted from (typically this
- // is `_value`, but could be any column)
- valueColumnName: string
- // The index of the column that this series was extracted from
- valueColumnIndex: number
- // The names and values of columns in the group key, plus the result name.
- // This provides the data for a user-recognizable label of the time series
- metaColumns: {
- [columnName: string]: string
- }
-}
-
-interface SpreadTablesResult {
- seriesDescriptions: SeriesDescription[]
- table: {
- [time: string]: {[seriesKey: string]: number}
- }
-}
-
-// Given a collection of `FluxTable`s parsed from a single Flux response,
-// `spreadTables` will place each unique series found within the response into
-// a single table, indexed by time. This data munging operation is often
-// referred to as as a “spread”, “cast”, “pivot”, or “unfold”.
-export const spreadTables = (tables: FluxTable[]): SpreadTablesResult => {
- const result: SpreadTablesResult = {
- table: {},
- seriesDescriptions: [],
- }
-
- for (const table of tables) {
- const header = table.data[0]
-
- if (!header) {
- continue
- }
-
- const seriesDescriptions = getSeriesDescriptions(table)
- const timeIndex = getTimeIndex(header)
-
- for (let i = 1; i < table.data.length; i++) {
- const row = table.data[i]
- const time = row[timeIndex]
-
- for (const {key, valueColumnIndex} of seriesDescriptions) {
- if (!result.table[time]) {
- result.table[time] = {}
- }
-
- result.table[time][key] = Number(row[valueColumnIndex])
- }
- }
-
- result.seriesDescriptions.push(...seriesDescriptions)
- }
-
- return result
-}
-
-const EXCLUDED_SERIES_COLUMNS = new Set([
- '_time',
- 'result',
- 'table',
- '_start',
- '_stop',
- '',
-])
-
-const NUMERIC_DATATYPES = new Set(['double', 'long', 'int', 'float'])
-
-const getSeriesDescriptions = (table: FluxTable): SeriesDescription[] => {
- const seriesDescriptions = []
- const header = table.data[0]
-
- for (let i = 0; i < header.length; i++) {
- const columnName = header[i]
- const dataType = table.dataTypes[columnName]
-
- if (EXCLUDED_SERIES_COLUMNS.has(columnName)) {
- continue
- }
-
- if (table.groupKey[columnName]) {
- continue
- }
-
- if (!NUMERIC_DATATYPES.has(dataType)) {
- continue
- }
-
- const key = Object.entries(table.groupKey).reduce(
- (acc, [k, v]) => acc + `[${k}=${v}]`,
- `${columnName}[result=${table.result}]`
- )
-
- seriesDescriptions.push({
- key,
- valueColumnName: columnName,
- valueColumnIndex: i,
- metaColumns: {
- ...table.groupKey,
- result: table.result,
- },
- })
- }
-
- return seriesDescriptions
-}
-
-const getTimeIndex = header => {
- let timeIndex = header.indexOf('_time')
-
- if (timeIndex >= 0) {
- return timeIndex
- }
-
- timeIndex = header.indexOf('_start')
- if (timeIndex >= 0) {
- return timeIndex
- }
-
- timeIndex = header.indexOf('_end')
- if (timeIndex >= 0) {
- return timeIndex
- }
-
- return -1
-}
diff --git a/ui/src/shared/utils/latestValues.test.ts b/ui/src/shared/utils/latestValues.test.ts
new file mode 100644
index 0000000000..cfef840681
--- /dev/null
+++ b/ui/src/shared/utils/latestValues.test.ts
@@ -0,0 +1,132 @@
+import {fluxToTable} from '@influxdata/vis'
+
+import {latestValues} from 'src/shared/utils/latestValues'
+
+describe('latestValues', () => {
+ test('the last value returned does not depend on the ordering of tables in response', () => {
+ const respA = `#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long
+#default,1,,,
+,result,table,_time,_value
+,,0,2018-12-10T18:29:48Z,1
+,,0,2018-12-10T18:54:18Z,2
+
+#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long
+#default,1,,,
+,result,table,_time,_value
+,,1,2018-12-10T18:29:48Z,3
+,,1,2018-12-10T18:40:18Z,4`
+
+ const respB = `#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long
+#default,1,,,
+,result,table,_time,_value
+,,0,2018-12-10T18:29:48Z,3
+,,0,2018-12-10T18:40:18Z,4
+
+#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long
+#default,1,,,
+,result,table,_time,_value
+,,1,2018-12-10T18:29:48Z,1
+,,1,2018-12-10T18:54:18Z,2`
+
+ const latestValuesA = latestValues(fluxToTable(respA).table)
+ const latestValuesB = latestValues(fluxToTable(respB).table)
+
+ expect(latestValuesA).toEqual([2])
+ expect(latestValuesB).toEqual([2])
+ })
+
+ test('uses the latest time for which a value is defined', () => {
+ const resp = `#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long
+#default,1,,,
+,result,table,_time,_value
+,,0,2018-12-10T18:29:48Z,3
+,,0,2018-12-10T18:40:18Z,4
+
+#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,string
+#default,1,,,
+,result,table,_time,_value
+,,1,2018-12-10T19:00:00Z,howdy
+,,1,2018-12-10T20:00:00Z,howdy`
+
+ const result = latestValues(fluxToTable(resp).table)
+
+ expect(result).toEqual([4])
+ })
+
+ test('falls back to _stop column if _time column does not exist', () => {
+ const resp = `#group,false,false,true,true,false
+#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,long
+#default,1,,,,
+,result,table,_start,_stop,_value
+,,0,2018-12-10T18:29:48Z,2018-12-10T18:29:48Z,3
+,,0,2018-12-10T18:40:18Z,2018-12-10T18:40:18Z,4`
+
+ const result = latestValues(fluxToTable(resp).table)
+
+ expect(result).toEqual([4])
+ })
+
+ test('returns no latest values if no time column exists and multiple rows', () => {
+ const resp = `#group,false,false,false
+#datatype,string,long,long
+#default,1,,
+,result,table,_value
+,,0,3
+,,0,4`
+
+ const result = latestValues(fluxToTable(resp).table)
+
+ expect(result).toEqual([])
+ })
+
+ test('returns latest values if no time column exists but table has single row', () => {
+ const resp = `#group,false,false,false,false
+#datatype,string,long,long,long
+#default,1,,,
+,result,table,_value,foo
+,,0,3,4`
+
+ const result = latestValues(fluxToTable(resp).table)
+
+ expect(result).toEqual([3, 4])
+ })
+
+ test('returns no latest values if no numeric column exists', () => {
+ const resp = `#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,string
+#default,1,,,
+,result,table,_time,_value
+,,1,2018-12-10T19:00:00Z,howdy
+,,1,2018-12-10T20:00:00Z,howdy`
+
+ const result = latestValues(fluxToTable(resp).table)
+
+ expect(result).toEqual([])
+ })
+
+ test('returns latest values from multiple numeric value columns', () => {
+ const resp = `#group,false,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long,double
+#default,1,,,,
+,result,table,_time,_value,foo
+,,0,2018-12-10T18:29:48Z,3,5.0
+,,0,2018-12-10T18:40:18Z,4,6.0
+
+#group,false,false,false,false
+#datatype,string,long,dateTime:RFC3339,long,double
+#default,1,,,,
+,result,table,_time,_value,foo
+,,0,2018-12-10T18:29:48Z,1,7.0
+,,0,2018-12-10T18:40:18Z,2,8.0`
+ const table = fluxToTable(resp).table
+ const result = latestValues(table)
+
+ expect(result).toEqual([4, 6.0, 2.0, 8.0])
+ })
+})
diff --git a/ui/src/shared/utils/latestValues.ts b/ui/src/shared/utils/latestValues.ts
new file mode 100644
index 0000000000..b11703e17e
--- /dev/null
+++ b/ui/src/shared/utils/latestValues.ts
@@ -0,0 +1,108 @@
+import {get, range, flatMap} from 'lodash'
+import {isNumeric, Table} from '@influxdata/vis'
+
+/*
+ Return a list of the maximum elements in `xs`, where the magnitude of each
+ element is computed using the passed function `d`.
+*/
+const maxesBy = (xs: X[], d: (x: X) => number): X[] => {
+ let maxes = []
+ let maxDist = -Infinity
+
+ for (const x of xs) {
+ const dist = d(x)
+
+ if (dist > maxDist) {
+ maxes = [x]
+ maxDist = dist
+ } else if (dist === maxDist && dist !== -Infinity) {
+ maxes.push(x)
+ }
+ }
+
+ return maxes
+}
+
+const EXCLUDED_COLUMNS = new Set([
+ '_start',
+ '_stop',
+ '_time',
+ 'table',
+ 'result',
+ '',
+])
+
+/*
+ Determine if the values in a column should be considered in `latestValues`.
+*/
+const isValueCol = (table: Table, colKey: string): boolean => {
+ const {name, type} = table.columns[colKey]
+
+ return isNumeric(type) && !EXCLUDED_COLUMNS.has(name)
+}
+
+/*
+ We sort the column keys that we pluck latest values from, so that:
+
+ - Columns named `_value` have precedence
+ - The returned latest values are in a somewhat stable order
+*/
+const sortTableKeys = (keyA: string, keyB: string): number => {
+ if (keyA.includes('_value')) {
+ return -1
+ } else if (keyB.includes('_value')) {
+ return 1
+ } else {
+ return keyA.localeCompare(keyB)
+ }
+}
+
+/*
+ Return a list of the most recent numeric values present in a `Table`.
+
+ This utility searches any numeric column to find values, and uses the `_time`
+ column as their associated timestamp.
+
+ If the table only has one row, then a time column is not needed.
+*/
+export const latestValues = (table: Table): number[] => {
+ const valueColsData = Object.keys(table.columns)
+ .sort((a, b) => sortTableKeys(a, b))
+ .filter(k => isValueCol(table, k))
+ .map(k => table.columns[k].data) as number[][]
+
+ if (!valueColsData.length) {
+ return []
+ }
+
+ const timeColData = get(
+ table,
+ 'columns._time.data',
+ get(table, 'columns._stop.data') // Fallback to `_stop` column if `_time` column missing
+ )
+
+ if (!timeColData && table.length !== 1) {
+ return []
+ }
+
+ const d = i => {
+ const time = timeColData[i]
+
+ if (time && valueColsData.some(colData => !isNaN(colData[i]))) {
+ return time
+ }
+
+ return -Infinity
+ }
+
+ const latestRowIndices =
+ table.length === 1 ? [0] : maxesBy(range(table.length), d)
+
+ const latestValues = flatMap(latestRowIndices, i =>
+ valueColsData.map(colData => colData[i])
+ )
+
+ const definedLatestValues = latestValues.filter(x => !isNaN(x))
+
+ return definedLatestValues
+}
diff --git a/ui/src/timeMachine/components/VisSwitcher.tsx b/ui/src/timeMachine/components/VisSwitcher.tsx
index e729a87829..cab7f252e3 100644
--- a/ui/src/timeMachine/components/VisSwitcher.tsx
+++ b/ui/src/timeMachine/components/VisSwitcher.tsx
@@ -6,13 +6,9 @@ import {Plot} from '@influxdata/vis'
// Components
import RawFluxDataTable from 'src/timeMachine/components/RawFluxDataTable'
-import GaugeChart from 'src/shared/components/GaugeChart'
-import SingleStat from 'src/shared/components/SingleStat'
-import SingleStatTransform from 'src/shared/components/SingleStatTransform'
-import TableGraphs from 'src/shared/components/tables/TableGraphs'
import HistogramContainer from 'src/shared/components/HistogramContainer'
import HistogramTransform from 'src/timeMachine/components/HistogramTransform'
-import XYContainer from 'src/shared/components/XYContainer'
+import RefreshingViewSwitcher from 'src/shared/components/RefreshingViewSwitcher'
// Utils
import {getActiveTimeMachine, getTables} from 'src/timeMachine/selectors'
@@ -23,9 +19,6 @@ import {
QueryViewProperties,
FluxTable,
RemoteDataState,
- XYView,
- XYViewGeom,
- SingleStatView,
AppState,
} from 'src/types'
@@ -57,76 +50,36 @@ const VisSwitcher: FunctionComponent = ({
)
}
- switch (properties.type) {
- case ViewType.SingleStat:
- return (
-
- {stat => }
-
- )
- case ViewType.Table:
- return
- case ViewType.Gauge:
- return
- case ViewType.XY:
- return (
-
- {config => }
-
- )
- case ViewType.LinePlusSingleStat:
- const xyProperties: XYView = {
- ...properties,
- colors: properties.colors.filter(c => c.type === 'scale'),
- type: ViewType.XY,
- geom: XYViewGeom.Line,
- }
-
- const singleStatProperties: SingleStatView = {
- ...properties,
- colors: properties.colors.filter(c => c.type !== 'scale'),
- type: ViewType.SingleStat,
- }
-
- return (
-
- {config => (
-
-
- {stat => (
-
- )}
-
-
- )}
-
- )
-
- case ViewType.Histogram:
- return (
-
- {({table, xColumn, fillColumns}) => (
-
- {config => }
-
- )}
-
- )
- default:
- return null
+ if (properties.type === ViewType.Histogram) {
+ // Histograms have special treatment when rendered within a time machine:
+ // if the backing view for the histogram has `xColumn` and `fillColumn`
+ // selections that are invalid given the current query response, then we
+ // fall back to using valid selections for those fields (if available).
+ // When a histogram is rendered on a dashboard, we use the selections
+ // stored in the view verbatim and display an error if they are invalid.
+ return (
+
+ {({table, xColumn, fillColumns}) => (
+
+ {config => }
+
+ )}
+
+ )
}
+
+ return (
+
+ )
}
const mstp = (state: AppState) => {