Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui): enable selecting more columns in line visualizations #14188

Merged
merged 1 commit into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions ui/src/shared/components/ScatterContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import GraphLoadingDots from 'src/shared/components/GraphLoadingDots'

// Utils
import {useVisDomainSettings} from 'src/shared/utils/useVisDomainSettings'
import {getFormatter, chooseXColumn, chooseYColumn} from 'src/shared/utils/vis'
import {
getFormatter,
defaultXColumn,
defaultYColumn,
} from 'src/shared/utils/vis'

// Constants
import {VIS_THEME} from 'src/shared/constants'
Expand Down Expand Up @@ -47,8 +51,8 @@ const ScatterContainer: FunctionComponent<Props> = ({
const fillColumns = storedFill || []
const symbolColumns = storedSymbol || []

const xColumn = storedXColumn || chooseXColumn(table)
const yColumn = storedYColumn || chooseYColumn(table)
const xColumn = storedXColumn || defaultXColumn(table)
const yColumn = storedYColumn || defaultYColumn(table)

const columnKeys = table.columnKeys

Expand Down
8 changes: 4 additions & 4 deletions ui/src/shared/components/XYContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
geomToInterpolation,
filterNoisyColumns,
parseBounds,
chooseXColumn,
chooseYColumn,
defaultXColumn,
defaultYColumn,
} from 'src/shared/utils/vis'

// Constants
Expand Down Expand Up @@ -59,8 +59,8 @@ const XYContainer: FunctionComponent<Props> = ({
const storedXDomain = useMemo(() => parseBounds(xBounds), [xBounds])
const storedYDomain = useMemo(() => parseBounds(yBounds), [yBounds])

const xColumn = storedXColumn || chooseXColumn(table)
const yColumn = storedYColumn || chooseYColumn(table)
const xColumn = storedXColumn || defaultXColumn(table)
const yColumn = storedYColumn || defaultYColumn(table)

const columnKeys = table.columnKeys

Expand Down
96 changes: 79 additions & 17 deletions ui/src/shared/utils/vis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,32 +105,94 @@ export const extent = (xs: number[]): [number, number] | null => {
return [low, high]
}

export const chooseXColumn = (table: Table): string | null => {
const columnKeys = new Set(table.columnKeys)
export const checkResultsLength = (giraffeResult: FromFluxResult): boolean => {
return get(giraffeResult, 'table.length', 0) > 0
}

export const getNumericColumns = (table: Table): string[] => {
const numericColumnKeys = table.columnKeys.filter(k => {
if (k === 'result' || k === 'table') {
return false
}

const columnType = table.getColumnType(k)

return columnType === 'time' || columnType === 'number'
})

if (columnKeys.has('_time')) {
return '_time'
return numericColumnKeys
}

export const getGroupableColumns = (table: Table): string[] => {
const invalidGroupColumns = new Set(['_value', '_time', 'table'])
const groupableColumns = table.columnKeys.filter(
name => !invalidGroupColumns.has(name)
)

return groupableColumns
}

/*
Previously we would automatically select an x and y column setting for an
`XYView` based on the current Flux response. We then added support for an
explicit x and y column setting by adding `xColumn` and `yColumn` fields to
the `XYView`.

We did not migrate existing views when adding the fields, so the fields are
considered optional. Thus to resolve the correct x and y column selections
for an `XYView`, we need to:

1. Use the `xColumn` and `yColumn` fields if they exist
2. Fall back to automatically selecting and x and y column if not

A `null` result from this function indicates that no valid selection could be
made.
*/
export const defaultXColumn = (
table: Table,
preferredColumnKey?: string
): string | null => {
const validColumnKeys = getNumericColumns(table)

if (validColumnKeys.includes(preferredColumnKey)) {
return preferredColumnKey
}

if (columnKeys.has('_stop')) {
return '_stop'
for (const key of ['_time', '_stop', '_start']) {
if (validColumnKeys.includes(key)) {
return key
}
}

if (columnKeys.has('_start')) {
return '_start'
if (validColumnKeys.length) {
return validColumnKeys[0]
}

return null
}

export const chooseYColumn = (table: Table): string | null => {
return table.columnKeys.find(
k =>
k.startsWith('_value') &&
(table.getColumnType(k) === 'number' || table.getColumnType(k) === 'time')
)
}
/*
See `defaultXColumn`.
*/
export const defaultYColumn = (
table: Table,
preferredColumnKey?: string
): string | null => {
const validColumnKeys = getNumericColumns(table)

if (validColumnKeys.includes(preferredColumnKey)) {
return preferredColumnKey
}

export const checkResultsLength = (giraffeResult: FromFluxResult): boolean => {
return get(giraffeResult, 'table.length', 0) > 0
for (const key of validColumnKeys) {
if (key.startsWith('_value')) {
return key
}
}

if (validColumnKeys.length) {
return validColumnKeys[0]
}

return null
}
83 changes: 18 additions & 65 deletions ui/src/timeMachine/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import {fromFlux, Table} from '@influxdata/giraffe'

// Utils
import {parseResponse} from 'src/shared/parsing/flux/response'
import {chooseYColumn, chooseXColumn} from 'src/shared/utils/vis'
import {
defaultXColumn,
defaultYColumn,
getNumericColumns as getNumericColumnsUtil,
getGroupableColumns as getGroupableColumnsUtil,
} from 'src/shared/utils/vis'

// Types
import {
Expand Down Expand Up @@ -47,92 +52,40 @@ export const getVisTable = (
return {table, fluxGroupKeyUnion}
}

const getNumericColumnsMemoized = memoizeOne(
(table: Table): string[] => {
const columnKeys = table.columnKeys
return columnKeys.reduce((numericColumns, key) => {
const columnType = table.getColumnType(key)
const columnName = table.getColumnName(key)
if (
(columnType === 'number' || columnType === 'time') &&
columnName !== 'result' &&
columnName !== 'table'
) {
numericColumns.push(columnName)
}
return numericColumns
}, [])
}
)
const getNumericColumnsMemoized = memoizeOne(getNumericColumnsUtil)

export const getNumericColumns = (state: AppState): string[] => {
const {table} = getVisTable(state)

return getNumericColumnsMemoized(table)
}

const getGroupableColumnsMemoized = memoizeOne(
(table: Table): string[] => {
const invalidGroupColumns = new Set(['_value', '_time', 'table'])
const groupableColumns = table.columnKeys.filter(
name => !invalidGroupColumns.has(name)
)

return groupableColumns
}
)
const getGroupableColumnsMemoized = memoizeOne(getGroupableColumnsUtil)

export const getGroupableColumns = (state: AppState): string[] => {
const {table} = getVisTable(state)

return getGroupableColumnsMemoized(table)
}

const selectXYColumn = (
validColumns: string[],
preference: string,
defaultSelection: string
): string => {
if (preference && validColumns.includes(preference)) {
return preference
}

return defaultSelection
}

const getXColumnSelectionMemoized = memoizeOne(selectXYColumn)

const getYColumnSelectionMemoized = memoizeOne(selectXYColumn)

export const getXColumnSelection = (state: AppState): string => {
const validXColumns = getNumericColumns(state)

const preference = get(getActiveTimeMachine(state), 'view.properties.xColumn')

const {table} = getVisTable(state)
const defaultSelection = chooseXColumn(table)

return getXColumnSelectionMemoized(
validXColumns,
preference,
defaultSelection
const preferredXColumnKey = get(
getActiveTimeMachine(state),
'view.properties.xColumn'
)

return defaultXColumn(table, preferredXColumnKey)
}

export const getYColumnSelection = (state: AppState): string => {
const validYColumns = getNumericColumns(state)

const preference = get(getActiveTimeMachine(state), 'view.properties.yColumn')

const {table} = getVisTable(state)

const defaultSelection = chooseYColumn(table)

return getYColumnSelectionMemoized(
validYColumns,
preference,
defaultSelection
const preferredYColumnKey = get(
getActiveTimeMachine(state),
'view.properties.yColumn'
)

return defaultYColumn(table, preferredYColumnKey)
}

const getGroupableColumnSelection = (
Expand Down