|
|
|
@ -1,10 +1,9 @@ |
|
|
|
|
// Libraries
|
|
|
|
|
import React, { PureComponent } from 'react'; |
|
|
|
|
// Components
|
|
|
|
|
import { EditorTabBody, EditorToolbarView } from './EditorTabBody'; |
|
|
|
|
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker'; |
|
|
|
|
import { QueryOptions } from './QueryOptions'; |
|
|
|
|
import { PanelOptionsGroup } from '@grafana/ui'; |
|
|
|
|
import { CustomScrollbar, stylesFactory, Button, HorizontalGroup, Modal } from '@grafana/ui'; |
|
|
|
|
import { getLocationSrv } from '@grafana/runtime'; |
|
|
|
|
import { QueryEditorRows } from './QueryEditorRows'; |
|
|
|
|
// Services
|
|
|
|
@ -20,6 +19,7 @@ import { addQuery } from 'app/core/utils/query'; |
|
|
|
|
import { Unsubscribable } from 'rxjs'; |
|
|
|
|
import { DashboardQueryEditor, isSharedDashboardQuery } from 'app/plugins/datasource/dashboard'; |
|
|
|
|
import { expressionDatasource, ExpressionDatasourceID } from 'app/features/expressions/ExpressionDatasource'; |
|
|
|
|
import { css } from 'emotion'; |
|
|
|
|
import { e2e } from '@grafana/e2e'; |
|
|
|
|
|
|
|
|
|
interface Props { |
|
|
|
@ -35,6 +35,7 @@ interface State { |
|
|
|
|
isAddingMixed: boolean; |
|
|
|
|
scrollTop: number; |
|
|
|
|
data: PanelData; |
|
|
|
|
isHelpOpen: boolean; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
@ -48,6 +49,7 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
helpContent: null, |
|
|
|
|
isPickerOpen: false, |
|
|
|
|
isAddingMixed: false, |
|
|
|
|
isHelpOpen: false, |
|
|
|
|
scrollTop: 0, |
|
|
|
|
data: { |
|
|
|
|
state: LoadingState.NotStarted, |
|
|
|
@ -121,6 +123,7 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
|
|
|
|
|
openQueryInspector = () => { |
|
|
|
|
const { panel } = this.props; |
|
|
|
|
|
|
|
|
|
getLocationSrv().update({ |
|
|
|
|
query: { inspect: panel.id, inspectTab: 'query' }, |
|
|
|
|
partial: true, |
|
|
|
@ -128,7 +131,7 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderHelp = () => { |
|
|
|
|
return <PluginHelp plugin={this.state.currentDS.meta} type="query_help" />; |
|
|
|
|
return; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -155,30 +158,45 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onScrollBottom = () => { |
|
|
|
|
this.setState({ scrollTop: this.state.scrollTop + 10000 }); |
|
|
|
|
this.setState({ scrollTop: 1000 }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderToolbar = () => { |
|
|
|
|
const { currentDS, isAddingMixed } = this.state; |
|
|
|
|
const showAddButton = !(isAddingMixed || isSharedDashboardQuery(currentDS.name)); |
|
|
|
|
renderTopSection(styles: QueriesTabStyls) { |
|
|
|
|
const { panel } = this.props; |
|
|
|
|
const { currentDS, data } = this.state; |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<> |
|
|
|
|
<div> |
|
|
|
|
<div className={styles.dataSourceRow}> |
|
|
|
|
<div className={styles.dataSourceRowItem}> |
|
|
|
|
<DataSourcePicker datasources={this.datasources} onChange={this.onChangeDataSource} current={currentDS} /> |
|
|
|
|
<div className="flex-grow-1" /> |
|
|
|
|
{showAddButton && ( |
|
|
|
|
<button className="btn navbar-button" onClick={this.onAddQueryClick}> |
|
|
|
|
Add query |
|
|
|
|
</button> |
|
|
|
|
)} |
|
|
|
|
{isAddingMixed && this.renderMixedPicker()} |
|
|
|
|
{config.featureToggles.expressions && ( |
|
|
|
|
<button className="btn navbar-button" onClick={this.onAddExpressionClick}> |
|
|
|
|
Add Expression |
|
|
|
|
</button> |
|
|
|
|
)} |
|
|
|
|
</> |
|
|
|
|
</div> |
|
|
|
|
<div className={styles.dataSourceRowItem}> |
|
|
|
|
<Button variant="secondary" icon="info-circle" title="Open data source help" onClick={this.onOpenHelp} /> |
|
|
|
|
</div> |
|
|
|
|
<div className={styles.dataSourceRowItem}> |
|
|
|
|
<Button |
|
|
|
|
variant="secondary" |
|
|
|
|
onClick={this.openQueryInspector} |
|
|
|
|
aria-label={e2e.components.QueryTab.selectors.queryInspectorButton} |
|
|
|
|
> |
|
|
|
|
Query inspector |
|
|
|
|
</Button> |
|
|
|
|
</div> |
|
|
|
|
<div className={styles.dataSourceRowItemOptions}> |
|
|
|
|
<QueryOptions panel={panel} datasource={currentDS} data={data} /> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onOpenHelp = () => { |
|
|
|
|
this.setState({ isHelpOpen: true }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
onCloseHelp = () => { |
|
|
|
|
this.setState({ isHelpOpen: false }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderMixedPicker = () => { |
|
|
|
@ -218,7 +236,7 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
this.setState({ scrollTop: target.scrollTop }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
renderQueryBody = () => { |
|
|
|
|
renderQueries() { |
|
|
|
|
const { panel, dashboard } = this.props; |
|
|
|
|
const { currentDS, data } = this.state; |
|
|
|
|
|
|
|
|
@ -237,36 +255,83 @@ export class QueriesTab extends PureComponent<Props, State> { |
|
|
|
|
dashboard={dashboard} |
|
|
|
|
data={data} |
|
|
|
|
/> |
|
|
|
|
<PanelOptionsGroup> |
|
|
|
|
<QueryOptions panel={panel} datasource={currentDS} /> |
|
|
|
|
</PanelOptionsGroup> |
|
|
|
|
</div> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render() { |
|
|
|
|
const { scrollTop } = this.state; |
|
|
|
|
const queryInspector: EditorToolbarView = { |
|
|
|
|
title: 'Query inspector', |
|
|
|
|
onClick: this.openQueryInspector, |
|
|
|
|
}; |
|
|
|
|
renderAddQueryRow(styles: QueriesTabStyls) { |
|
|
|
|
const { currentDS, isAddingMixed } = this.state; |
|
|
|
|
const showAddButton = !(isAddingMixed || isSharedDashboardQuery(currentDS.name)); |
|
|
|
|
|
|
|
|
|
const dsHelp: EditorToolbarView = { |
|
|
|
|
heading: 'Help', |
|
|
|
|
icon: 'question-circle', |
|
|
|
|
render: this.renderHelp, |
|
|
|
|
}; |
|
|
|
|
return ( |
|
|
|
|
<HorizontalGroup spacing="md" align="flex-start"> |
|
|
|
|
{showAddButton && ( |
|
|
|
|
<Button icon="plus" onClick={this.onAddQueryClick} variant="secondary"> |
|
|
|
|
Query |
|
|
|
|
</Button> |
|
|
|
|
)} |
|
|
|
|
{isAddingMixed && this.renderMixedPicker()} |
|
|
|
|
{config.featureToggles.expressions && ( |
|
|
|
|
<Button icon="plus" onClick={this.onAddExpressionClick} variant="secondary"> |
|
|
|
|
Expression |
|
|
|
|
</Button> |
|
|
|
|
)} |
|
|
|
|
</HorizontalGroup> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
render() { |
|
|
|
|
const { scrollTop, isHelpOpen } = this.state; |
|
|
|
|
const styles = getStyles(); |
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
<EditorTabBody |
|
|
|
|
heading="Data source" |
|
|
|
|
renderToolbar={this.renderToolbar} |
|
|
|
|
toolbarItems={[queryInspector, dsHelp]} |
|
|
|
|
setScrollTop={this.setScrollTop} |
|
|
|
|
<CustomScrollbar |
|
|
|
|
autoHeightMin="100%" |
|
|
|
|
autoHide={true} |
|
|
|
|
updateAfterMountMs={300} |
|
|
|
|
scrollTop={scrollTop} |
|
|
|
|
setScrollTop={this.setScrollTop} |
|
|
|
|
> |
|
|
|
|
<>{this.renderQueryBody()}</> |
|
|
|
|
</EditorTabBody> |
|
|
|
|
<div className={styles.innerWrapper}> |
|
|
|
|
{this.renderTopSection(styles)} |
|
|
|
|
<div className={styles.queriesWrapper}>{this.renderQueries()}</div> |
|
|
|
|
{this.renderAddQueryRow(styles)} |
|
|
|
|
|
|
|
|
|
{isHelpOpen && ( |
|
|
|
|
<Modal title="Data source help" isOpen={true} onDismiss={this.onCloseHelp}> |
|
|
|
|
<PluginHelp plugin={this.state.currentDS.meta} type="query_help" /> |
|
|
|
|
</Modal> |
|
|
|
|
)} |
|
|
|
|
</div> |
|
|
|
|
</CustomScrollbar> |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const getStyles = stylesFactory(() => { |
|
|
|
|
const { theme } = config; |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
innerWrapper: css` |
|
|
|
|
display: flex; |
|
|
|
|
flex-direction: column; |
|
|
|
|
height: 100%; |
|
|
|
|
padding: ${theme.spacing.md}; |
|
|
|
|
`,
|
|
|
|
|
dataSourceRow: css` |
|
|
|
|
display: flex; |
|
|
|
|
margin-bottom: ${theme.spacing.md}; |
|
|
|
|
`,
|
|
|
|
|
dataSourceRowItem: css` |
|
|
|
|
margin-right: ${theme.spacing.inlineFormMargin}; |
|
|
|
|
`,
|
|
|
|
|
dataSourceRowItemOptions: css` |
|
|
|
|
flex-grow: 1; |
|
|
|
|
`,
|
|
|
|
|
queriesWrapper: css` |
|
|
|
|
padding-bottom: 16px; |
|
|
|
|
`,
|
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
type QueriesTabStyls = ReturnType<typeof getStyles>; |
|
|
|
|