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

Add x and y column pickers to graph types #14052

Merged
merged 14 commits into from
Jun 5, 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
4 changes: 4 additions & 0 deletions dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ type LinePlusSingleStatProperties struct {
DecimalPlaces DecimalPlaces `json:"decimalPlaces"`
Note string `json:"note"`
ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"`
XColumn string `json:"xColumn"`
ebb-tide marked this conversation as resolved.
Show resolved Hide resolved
YColumn string `json:"yColumn"`
}

// XYViewProperties represents options for line, bar, step, or stacked view in Chronograf
Expand All @@ -603,6 +605,8 @@ type XYViewProperties struct {
ViewColors []ViewColor `json:"colors"`
Note string `json:"note"`
ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"`
XColumn string `json:"xColumn"`
YColumn string `json:"yColumn"`
}

// SingleStatViewProperties represents options for single stat view in Chronograf
Expand Down
4 changes: 3 additions & 1 deletion dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ func TestView_MarshalJSON(t *testing.T) {
"legend": {},
"geom": "",
"note": "",
"showNoteWhenEmpty": false
"showNoteWhenEmpty": false,
"xColumn": "",
"yColumn": ""
}
}
`,
Expand Down
42 changes: 42 additions & 0 deletions ui/src/shared/components/ColumnSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Libraries
import React, {FunctionComponent} from 'react'

// Components
import {Dropdown, Form, ComponentStatus} from 'src/clockface'

interface Props {
selectedColumn: string
availableColumns: string[]
axisName: string
onSelectColumn: (col: string) => void
}

const ColumnSelector: FunctionComponent<Props> = ({
selectedColumn,
onSelectColumn,
availableColumns,
axisName,
}) => {
return (
<Form.Element label={`${axisName.toUpperCase()} Column`}>
<Dropdown
selectedID={selectedColumn}
onChange={onSelectColumn}
status={
availableColumns.length == 0
? ComponentStatus.Disabled
: ComponentStatus.Default
}
titleText="None"
>
{availableColumns.map(columnName => (
<Dropdown.Item id={columnName} key={columnName} value={columnName}>
{columnName}
</Dropdown.Item>
))}
</Dropdown>
</Form.Element>
)
}

export default ColumnSelector
6 changes: 4 additions & 2 deletions ui/src/shared/components/HistogramContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ const HistogramContainer: FunctionComponent<Props> = ({
columnKeys.includes(xColumn) ? table.getColumn(xColumn, 'number') : []
)

const isValidView = xColumn && columnKeys.includes(xColumn)
fillColumns.every(col => columnKeys.includes(col))
const isValidView =
xColumn &&
columnKeys.includes(xColumn) &&
fillColumns.every(col => columnKeys.includes(col))

if (!isValidView) {
return <EmptyGraphMessage message={INVALID_DATA_COPY} />
Expand Down
62 changes: 36 additions & 26 deletions ui/src/shared/components/RefreshingViewSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,20 @@ const RefreshingViewSwitcher: FunctionComponent<Props> = ({
)
case ViewType.XY:
return (
<XYContainer
files={files}
viewProperties={properties}
loading={loading}
>
{config => <Plot config={config} />}
</XYContainer>
<VisTableTransform files={files}>
{({table, fluxGroupKeyUnion}) => (
<XYContainer
table={table}
fluxGroupKeyUnion={fluxGroupKeyUnion}
viewProperties={properties}
loading={loading}
>
{config => <Plot config={config} />}
</XYContainer>
)}
</VisTableTransform>
)

case ViewType.LinePlusSingleStat:
const xyProperties = {
...properties,
Expand All @@ -88,24 +94,29 @@ const RefreshingViewSwitcher: FunctionComponent<Props> = ({
} as SingleStatView

return (
<XYContainer
files={files}
viewProperties={xyProperties}
loading={loading}
>
{config => (
<Plot config={config}>
<LatestValueTransform table={config.table} quiet={true}>
{latestValue => (
<SingleStat
stat={latestValue}
properties={singleStatProperties}
/>
)}
</LatestValueTransform>
</Plot>
<VisTableTransform files={files}>
{({table, fluxGroupKeyUnion}) => (
<XYContainer
table={table}
fluxGroupKeyUnion={fluxGroupKeyUnion}
viewProperties={xyProperties}
loading={loading}
>
{config => (
<Plot config={config}>
<LatestValueTransform table={config.table} quiet={true}>
{latestValue => (
<SingleStat
stat={latestValue}
properties={singleStatProperties}
/>
)}
</LatestValueTransform>
</Plot>
)}
</XYContainer>
)}
</XYContainer>
</VisTableTransform>
)
case ViewType.Histogram:
return (
Expand Down Expand Up @@ -138,10 +149,9 @@ const RefreshingViewSwitcher: FunctionComponent<Props> = ({
case ViewType.Scatter:
return (
<VisTableTransform files={files}>
{({table, fluxGroupKeyUnion}) => (
{({table}) => (
<ScatterContainer
table={table}
fluxGroupKeyUnion={fluxGroupKeyUnion}
loading={loading}
viewProperties={properties}
>
Expand Down
58 changes: 8 additions & 50 deletions ui/src/shared/components/ScatterContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Libraries
import React, {FunctionComponent, useEffect} from 'react'
import {connect} from 'react-redux'
import React, {FunctionComponent} from 'react'
import {Config, Table} from '@influxdata/vis'

// Components
Expand All @@ -9,7 +8,7 @@ import GraphLoadingDots from 'src/shared/components/GraphLoadingDots'

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

// Constants
import {VIS_THEME} from 'src/shared/constants'
Expand All @@ -18,28 +17,19 @@ import {INVALID_DATA_COPY} from 'src/shared/copy/cell'

// Types
import {RemoteDataState, ScatterView} from 'src/types'
import {setFillColumns, setSymbolColumns} from 'src/timeMachine/actions'

interface OwnProps {
interface Props {
table: Table
fluxGroupKeyUnion?: string[]
loading: RemoteDataState
viewProperties: ScatterView
children: (config: Config) => JSX.Element
}

interface DispatchProps {
onSetFillColumns: typeof setFillColumns
onSetSymbolColumns: typeof setSymbolColumns
}

type Props = OwnProps & DispatchProps

const ScatterContainer: FunctionComponent<Props> = ({
table,
loading,
children,
fluxGroupKeyUnion,
viewProperties: {
xAxisLabel,
yAxisLabel,
Expand All @@ -50,39 +40,15 @@ const ScatterContainer: FunctionComponent<Props> = ({
colors,
xDomain: storedXDomain,
yDomain: storedYDomain,
xColumn: storedXColumn,
yColumn: storedYColumn,
},
onSetFillColumns,
onSetSymbolColumns,
}) => {
useEffect(() => {
if (fluxGroupKeyUnion && (!storedSymbol || !storedFill)) {
// if new view, maximize variations in symbol and color
const filteredGroupKeys = fluxGroupKeyUnion.filter(
k =>
![
'result',
'table',
'_measurement',
'_start',
'_stop',
'_field',
].includes(k)
)
if (!storedSymbol) {
onSetSymbolColumns(filteredGroupKeys)
}
if (!storedFill) {
onSetFillColumns(filteredGroupKeys)
}
}
})

const fillColumns = storedFill || []
const symbolColumns = storedSymbol || []

// TODO: allow xcolumn and ycolumn to be user selectable
const xColumn = chooseXColumn(table)
ebb-tide marked this conversation as resolved.
Show resolved Hide resolved
const yColumn = chooseYColumn(table)
const xColumn = storedXColumn || chooseXColumn(table)
const yColumn = storedYColumn || chooseYColumn(table)

const columnKeys = table.columnKeys

Expand Down Expand Up @@ -150,12 +116,4 @@ const ScatterContainer: FunctionComponent<Props> = ({
)
}

const mdtp = {
onSetFillColumns: setFillColumns,
onSetSymbolColumns: setSymbolColumns,
}

export default connect<{}, DispatchProps, {}>(
null,
mdtp
)(ScatterContainer)
export default ScatterContainer
31 changes: 18 additions & 13 deletions ui/src/shared/components/XYContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Libraries
import React, {FunctionComponent, useMemo} from 'react'
import {Config, fromFlux} from '@influxdata/vis'
import {Config, Table} from '@influxdata/vis'

// Components
import EmptyGraphMessage from 'src/shared/components/EmptyGraphMessage'
Expand All @@ -26,19 +26,23 @@ import {INVALID_DATA_COPY} from 'src/shared/copy/cell'
import {RemoteDataState, XYView} from 'src/types'

interface Props {
files: string[]
table: Table
fluxGroupKeyUnion: string[]
loading: RemoteDataState
viewProperties: XYView
children: (config: Config) => JSX.Element
}

const XYContainer: FunctionComponent<Props> = ({
files,
table,
fluxGroupKeyUnion,
loading,
children,
viewProperties: {
geom,
colors,
xColumn: storedXColumn,
yColumn: storedYColumn,
axes: {
x: {label: xAxisLabel, bounds: xBounds},
y: {
Expand All @@ -51,18 +55,12 @@ const XYContainer: FunctionComponent<Props> = ({
},
},
}) => {
const {table, fluxGroupKeyUnion} = useMemo(
() => fromFlux(files.join('\n\n')),
[files]
)

// Eventually these will be configurable in the line graph options UI
const xColumn = chooseXColumn(table)
const yColumn = chooseYColumn(table)

const storedXDomain = useMemo(() => parseBounds(xBounds), [xBounds])
const storedYDomain = useMemo(() => parseBounds(yBounds), [yBounds])

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

const columnKeys = table.columnKeys

const [xDomain, onSetXDomain, onResetXDomain] = useVisDomainSettings(
Expand All @@ -74,7 +72,14 @@ const XYContainer: FunctionComponent<Props> = ({
storedYDomain,
columnKeys.includes(yColumn) ? table.getColumn(yColumn, 'number') : []
)
if (!xColumn || !yColumn) {

const isValidView =
ebb-tide marked this conversation as resolved.
Show resolved Hide resolved
xColumn &&
columnKeys.includes(xColumn) &&
yColumn &&
columnKeys.includes(yColumn)

if (!isValidView) {
return <EmptyGraphMessage message={INVALID_DATA_COPY} />
}

Expand Down
2 changes: 2 additions & 0 deletions ui/src/shared/utils/mocks/resourceToTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export const myView: View = {
colors: [],
note: '',
showNoteWhenEmpty: false,
xColumn: null,
yColumn: null,
},
}

Expand Down
2 changes: 2 additions & 0 deletions ui/src/shared/utils/resourceToTemplate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ describe('resourceToTemplate', () => {
colors: [],
note: '',
showNoteWhenEmpty: false,
xColumn: null,
yColumn: null,
},
},
},
Expand Down
Loading