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

feat(ui): allow to send multiple queries to dashboard #5737

Merged
merged 5 commits into from
Apr 27, 2021
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
1. [#5728](https://github.com/influxdata/chronograf/pull/5728): Improve InfluxDB Admin | Queries page.
1. [#5726](https://github.com/influxdata/chronograf/pull/5726): Allow to setup InfluxDB v2 connection from chronograf command-line.
1. [#5735](https://github.com/influxdata/chronograf/pull/5735): Allow to add custom auto-refresh intervals.
1. [#5737](https://github.com/influxdata/chronograf/pull/5737): Allow to send multiple queries to dashboard.

### Bug Fixes

Expand Down
133 changes: 115 additions & 18 deletions ui/src/data_explorer/components/SendToDashboardOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Libraries
import React, {PureComponent} from 'react'
import React, {ChangeEvent, PureComponent} from 'react'
import _ from 'lodash'

// Utils
Expand All @@ -9,6 +9,7 @@ import {
TimeMachineContainer,
TimeMachineContextConsumer,
} from 'src/shared/utils/TimeMachineContext'
import {buildRawText} from 'src/utils/influxql'

// Components
import {
Expand Down Expand Up @@ -37,6 +38,8 @@ import {createDashboard} from 'src/dashboards/apis'
// Types
import {
QueryConfig,
CellQuery,
TimeRange,
Dashboard,
Source,
Cell,
Expand All @@ -47,11 +50,8 @@ import {VisualizationOptions} from 'src/types/dataExplorer'
import {ColorString} from 'src/types/colors'

interface PassedProps {
queryConfig: QueryConfig
script: string
dashboards: Dashboard[]
source: Source
rawText: string
onCancel: () => void
sendDashboardCell: (
dashboard: Dashboard,
Expand All @@ -60,11 +60,15 @@ interface PassedProps {
isStaticLegend: boolean
handleGetDashboards: () => Dashboard[]
notify: (message: Notification) => void
activeQueryIndex: number
}

interface ConnectedProps {
queryType: QueryType
queryDrafts: CellQuery[]
timeRange: TimeRange
visualizationOptions: VisualizationOptions
script: string // flux script
}

type Props = PassedProps & ConnectedProps
Expand All @@ -73,6 +77,7 @@ interface State {
selectedIDs: string[]
name: string
newDashboardName: string
sendAllQueries: boolean
}

const NEW_DASHBOARD_ID = 'new'
Expand All @@ -85,8 +90,19 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
selectedIDs: [],
name: '',
newDashboardName: '',
sendAllQueries: false,
}
}
private onSendAllQueriesCheckChange = (
val: ChangeEvent<HTMLInputElement>
): void => {
this.setState({sendAllQueries: val.target.checked})
}
private onSendActiveQueriesCheckChange = (
val: ChangeEvent<HTMLInputElement>
): void => {
this.setState({sendAllQueries: !val.target.checked})
}
public async componentDidMount() {
const {handleGetDashboards} = this.props
await handleGetDashboards()
Expand All @@ -103,11 +119,13 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
}

public render() {
const {onCancel} = this.props
const {name, selectedIDs, newDashboardName} = this.state
const {onCancel, queryDrafts, queryType} = this.props
const {name, selectedIDs, newDashboardName, sendAllQueries} = this.state

const numberDashboards = selectedIDs.length > 1 ? selectedIDs.length : ''
const pluralizer = selectedIDs.length > 1 ? 's' : ''
const multipleQueries =
queryType === QueryType.InfluxQL && queryDrafts.length > 1

return (
<OverlayContainer>
Expand Down Expand Up @@ -140,6 +158,46 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
placeholder={'Name this new cell'}
/>
</Form.Element>
{multipleQueries && (
<Form.Element label="Queries">
<div className="form-group col-xs-12">
<div className="form-control-static">
<div className="radio-item">
<input
id="active_query_option"
type="radio"
name="queriesRadio"
value="active"
checked={!sendAllQueries}
onChange={this.onSendActiveQueriesCheckChange}
/>
<label
htmlFor="active_query_option"
title="Query from the selected tab"
>
Active Query
</label>
</div>
<div className="radio-item">
<input
id="all_queries_option"
type="radio"
name="queriesRadio"
value="all"
checked={sendAllQueries}
onChange={this.onSendAllQueriesCheckChange}
/>
<label
htmlFor="all_queries_option"
title="Queries from all tabs"
>
All Queries
</label>
</div>
</div>
</div>
</Form.Element>
)}
<Form.Footer>
<Button
color={ComponentColor.Success}
Expand Down Expand Up @@ -222,11 +280,33 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
return this.state.selectedIDs.includes(NEW_DASHBOARD_ID)
}

private get activeQueryConfig(): QueryConfig {
const {queryDrafts, activeQueryIndex} = this.props
if (queryDrafts === undefined || queryDrafts.length === 0) {
return undefined
}
if (activeQueryIndex < queryDrafts.length) {
return queryDrafts[activeQueryIndex].queryConfig
}
return queryDrafts[0].queryConfig
}

private rawText = (queryConfig: QueryConfig | undefined): string => {
const {timeRange} = this.props

if (queryConfig) {
return buildRawText(queryConfig, timeRange)
}

return ''
}

private hasQuery(): boolean {
const {rawText, script, queryType} = this.props
const {script, queryType} = this.props
if (queryType === QueryType.Flux) {
return script && !!script.trim()
}
const rawText = this.rawText(this.activeQueryConfig)
return rawText && !!rawText.trim()
}

Expand Down Expand Up @@ -269,17 +349,16 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
}

private sendToDashboard = async () => {
const {name, newDashboardName} = this.state
const {name, newDashboardName, sendAllQueries} = this.state
const {
queryType,
queryConfig,
script,
sendDashboardCell,
rawText,
source,
onCancel,
visualizationOptions,
isStaticLegend,
queryDrafts,
} = this.props
const {
type,
Expand All @@ -296,14 +375,7 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {

const isFluxQuery = queryType === QueryType.Flux

let newCellQueries = [
{
queryConfig,
query: rawText,
source: source.links.self,
type: QueryType.InfluxQL,
},
]
let newCellQueries: CellQuery[]

if (isFluxQuery) {
newCellQueries = [
Expand All @@ -314,6 +386,25 @@ class SendToDashboardOverlay extends PureComponent<Props, State> {
type: QueryType.Flux,
},
]
} else {
const createInfluxQLCellQuery = (queryConfig: QueryConfig): CellQuery => {
const rawText = this.rawText(queryConfig)
return {
queryConfig,
query: rawText,
source: source.links.self,
type: QueryType.InfluxQL,
}
}
// InfluxQL
if (sendAllQueries) {
newCellQueries = queryDrafts.reduce((acc, val) => {
acc.push(createInfluxQLCellQuery(val.queryConfig))
return acc
}, [])
} else {
newCellQueries = [createInfluxQLCellQuery(this.activeQueryConfig)]
}
}

const colors: ColorString[] = getCellTypeColors({
Expand Down Expand Up @@ -386,6 +477,9 @@ const ConnectedSendToDashboardOverlay = (props: PassedProps) => {
gaugeColors,
lineColors,
queryType,
queryDrafts,
timeRange,
draftScript,
} = timeMachineContainer.state

const visualizationOptions = {
Expand All @@ -407,6 +501,9 @@ const ConnectedSendToDashboardOverlay = (props: PassedProps) => {
<SendToDashboardOverlay
{...props}
queryType={queryType}
queryDrafts={queryDrafts}
timeRange={timeRange}
script={draftScript}
visualizationOptions={visualizationOptions}
/>
)
Expand Down
35 changes: 13 additions & 22 deletions ui/src/data_explorer/containers/DataExplorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import _ from 'lodash'
import {stripPrefix} from 'src/utils/basepath'
import {GlobalAutoRefresher} from 'src/utils/AutoRefresher'
import {getConfig} from 'src/dashboards/utils/cellGetters'
import {buildRawText} from 'src/utils/influxql'
import {defaultQueryDraft} from 'src/shared/utils/timeMachine'
import {
TimeMachineContainer,
Expand Down Expand Up @@ -114,6 +113,7 @@ interface State {
isSendToDashboardVisible: boolean
isStaticLegend: boolean
isComponentMounted: boolean
activeQueryIndex: number
}

@ErrorHandling
Expand All @@ -126,6 +126,7 @@ export class DataExplorer extends PureComponent<Props, State> {
isSendToDashboardVisible: false,
isStaticLegend: false,
isComponentMounted: false,
activeQueryIndex: 0,
}

props.onResetTimeMachine()
Expand Down Expand Up @@ -199,6 +200,7 @@ export class DataExplorer extends PureComponent<Props, State> {
updateSourceLink={updateSourceLink}
onResetFocus={this.handleResetFocus}
onToggleStaticLegend={this.handleToggleStaticLegend}
onActiveQueryIndexChange={this.onActiveQueryIndexChange}
refresh={autoRefresh}
>
{(activeEditorTab, onSetActiveEditorTab) => (
Expand Down Expand Up @@ -318,21 +320,22 @@ export class DataExplorer extends PureComponent<Props, State> {
sendDashboardCell,
handleGetDashboards,
notify,
draftScript,
} = this.props

const {isSendToDashboardVisible, isStaticLegend} = this.state
const {
isSendToDashboardVisible,
isStaticLegend,
activeQueryIndex,
} = this.state
return (
<Authorized requiredRole={EDITOR_ROLE}>
<OverlayTechnology visible={isSendToDashboardVisible}>
<SendToDashboardOverlay
notify={notify}
onCancel={this.toggleSendToDashboard}
queryConfig={this.activeQueryConfig}
script={draftScript}
source={source}
rawText={this.rawText}
dashboards={dashboards}
activeQueryIndex={activeQueryIndex}
handleGetDashboards={handleGetDashboards}
sendDashboardCell={sendDashboardCell}
isStaticLegend={isStaticLegend}
Expand Down Expand Up @@ -405,22 +408,6 @@ export class DataExplorer extends PureComponent<Props, State> {
return _.get(this.props.queryConfigs, ['0', 'database'], null)
}

private get activeQueryConfig(): QueryConfig {
const {queryDrafts} = this.props

return _.get(queryDrafts, '0.queryConfig')
}

private get rawText(): string {
const {timeRange} = this.props

if (this.activeQueryConfig) {
return buildRawText(this.activeQueryConfig, timeRange)
}

return ''
}

private toggleSendToDashboard = () => {
this.setState({
isSendToDashboardVisible: !this.state.isSendToDashboardVisible,
Expand All @@ -431,6 +418,10 @@ export class DataExplorer extends PureComponent<Props, State> {
this.setState({isStaticLegend})
}

private onActiveQueryIndexChange = (activeQueryIndex: number): void => {
this.setState({activeQueryIndex})
}

private handleResetFocus = () => {
return
}
Expand Down
5 changes: 5 additions & 0 deletions ui/src/shared/components/TimeMachine/TimeMachine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ interface PassedProps {
) => JSX.Element
queryStatus: QueryStatus
onUpdateScriptStatus?: (status: ScriptStatus) => void
onActiveQueryIndexChange?: (activeQueryIndex: number) => void
refresh: RefreshRate
}

Expand Down Expand Up @@ -540,6 +541,10 @@ class TimeMachine extends PureComponent<Props, State> {

private handleSetActiveQueryIndex = (activeQueryIndex): void => {
this.setState({activeQueryIndex})
const {onActiveQueryIndexChange} = this.props
if (onActiveQueryIndexChange) {
onActiveQueryIndexChange(activeQueryIndex)
}
}

private handleSetActiveEditorTab = (tabName: CEOTabs): void => {
Expand Down