import { css } from '@emotion/css'; import React, { FormEvent, PureComponent } from 'react'; import { connect, ConnectedProps } from 'react-redux'; import { DataSourceInstanceSettings, getDataSourceRef, LoadingState, SelectableValue } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { DataSourcePicker, getTemplateSrv } from '@grafana/runtime'; import { InlineField, InlineFieldRow, VerticalGroup } from '@grafana/ui'; import { StoreState } from '../../../types'; import { getTimeSrv } from '../../dashboard/services/TimeSrv'; import { SelectionOptionsEditor } from '../editor/SelectionOptionsEditor'; import { VariableSectionHeader } from '../editor/VariableSectionHeader'; import { VariableTextField } from '../editor/VariableTextField'; import { initialVariableEditorState } from '../editor/reducer'; import { getQueryVariableEditorState } from '../editor/selectors'; import { OnPropChangeArguments, VariableEditorProps } from '../editor/types'; import { isLegacyQueryEditor, isQueryEditor } from '../guard'; import { changeVariableMultiValue } from '../state/actions'; import { getVariablesState } from '../state/selectors'; import { QueryVariableModel, VariableRefresh, VariableSort, VariableWithMultiSupport } from '../types'; import { toKeyedVariableIdentifier } from '../utils'; import { QueryVariableRefreshSelect } from './QueryVariableRefreshSelect'; import { QueryVariableSortSelect } from './QueryVariableSortSelect'; import { changeQueryVariableDataSource, changeQueryVariableQuery, initQueryVariableEditor } from './actions'; const mapStateToProps = (state: StoreState, ownProps: OwnProps) => { const { rootStateKey } = ownProps.variable; if (!rootStateKey) { console.error('QueryVariableEditor: variable has no rootStateKey'); return { extended: getQueryVariableEditorState(initialVariableEditorState), }; } const { editor } = getVariablesState(rootStateKey, state); return { extended: getQueryVariableEditorState(editor), }; }; const mapDispatchToProps = { initQueryVariableEditor, changeQueryVariableDataSource, changeQueryVariableQuery, changeVariableMultiValue, }; const connector = connect(mapStateToProps, mapDispatchToProps); export interface OwnProps extends VariableEditorProps {} export type Props = OwnProps & ConnectedProps; export interface State { regex: string | null; tagsQuery: string | null; tagValuesQuery: string | null; } export class QueryVariableEditorUnConnected extends PureComponent { state: State = { regex: null, tagsQuery: null, tagValuesQuery: null, }; async componentDidMount() { await this.props.initQueryVariableEditor(toKeyedVariableIdentifier(this.props.variable)); } componentDidUpdate(prevProps: Readonly): void { if (prevProps.variable.datasource !== this.props.variable.datasource) { this.props.changeQueryVariableDataSource( toKeyedVariableIdentifier(this.props.variable), this.props.variable.datasource ); } } onDataSourceChange = (dsSettings: DataSourceInstanceSettings) => { this.props.onPropChange({ propName: 'datasource', propValue: dsSettings.isDefault ? null : getDataSourceRef(dsSettings), }); }; onLegacyQueryChange = async (query: any, definition: string) => { if (this.props.variable.query !== query) { this.props.changeQueryVariableQuery(toKeyedVariableIdentifier(this.props.variable), query, definition); } }; onQueryChange = async (query: any) => { if (this.props.variable.query !== query) { let definition = ''; if (query && query.hasOwnProperty('query') && typeof query.query === 'string') { definition = query.query; } this.props.changeQueryVariableQuery(toKeyedVariableIdentifier(this.props.variable), query, definition); } }; onRegExChange = (event: FormEvent) => { this.setState({ regex: event.currentTarget.value }); }; onRegExBlur = async (event: FormEvent) => { const regex = event.currentTarget.value; if (this.props.variable.regex !== regex) { this.props.onPropChange({ propName: 'regex', propValue: regex, updateOptions: true }); } }; onRefreshChange = (option: SelectableValue) => { this.props.onPropChange({ propName: 'refresh', propValue: option.value }); }; onSortChange = async (option: SelectableValue) => { this.props.onPropChange({ propName: 'sort', propValue: option.value, updateOptions: true }); }; onSelectionOptionsChange = async ({ propValue, propName }: OnPropChangeArguments) => { this.props.onPropChange({ propName, propValue, updateOptions: true }); }; renderQueryEditor = () => { const { extended, variable } = this.props; if (!extended || !extended.dataSource || !extended.VariableQueryEditor) { return null; } const query = variable.query; const datasource = extended.dataSource; const VariableQueryEditor = extended.VariableQueryEditor; if (isLegacyQueryEditor(VariableQueryEditor, datasource)) { return ( ); } const range = getTimeSrv().timeRange(); if (isQueryEditor(VariableQueryEditor, datasource)) { return ( {}} data={{ series: [], state: LoadingState.Done, timeRange: range }} range={range} onBlur={() => {}} history={[]} /> ); } return null; }; render() { return (
{this.renderQueryEditor()}
Optional, if you want to extract part of a series name or metric node segment. Named capture groups can be used to separate the display text and value ( see examples ). } testId={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2} grow />
); } } export const QueryVariableEditor = connector(QueryVariableEditorUnConnected);