// Libraries import React, { PureComponent } from 'react'; // Services import { getAngularLoader, AngularComponent } from '@grafana/runtime'; // Types import { DataQuery, TimeRange, EventBusExtended } from '@grafana/data'; import 'app/features/plugins/plugin_loader'; interface QueryEditorProps { error?: any; datasource: any; onExecuteQuery?: () => void; onQueryChange?: (value: DataQuery) => void; initialQuery: DataQuery; exploreEvents: EventBusExtended; range: TimeRange; textEditModeEnabled?: boolean; } export default class QueryEditor extends PureComponent { element: any; component?: AngularComponent; angularScope: any; async componentDidMount() { if (!this.element) { return; } const { datasource, initialQuery, exploreEvents, range } = this.props; const loader = getAngularLoader(); const template = ' '; const target = { datasource: datasource.name, ...initialQuery }; const scopeProps = { ctrl: { datasource, target, range, refresh: () => { setTimeout(() => { // the "hide" attribute of the quries can be changed from the "outside", // it will be applied to "this.props.initialQuery.hide", but not to "target.hide". // so we have to apply it. if (target.hide !== this.props.initialQuery.hide) { target.hide = this.props.initialQuery.hide; } this.props.onQueryChange?.(target); this.props.onExecuteQuery?.(); }, 1); }, onQueryChange: () => { setTimeout(() => { this.props.onQueryChange?.(target); }, 1); }, events: exploreEvents, panel: { datasource, targets: [target] }, dashboard: {}, }, }; this.component = loader.load(this.element, scopeProps, template); this.angularScope = scopeProps.ctrl; setTimeout(() => { this.props.onQueryChange?.(target); this.props.onExecuteQuery?.(); }, 1); } componentDidUpdate(prevProps: QueryEditorProps) { const hasToggledEditorMode = prevProps.textEditModeEnabled !== this.props.textEditModeEnabled; const hasNewError = prevProps.error !== this.props.error; if (this.component) { if (hasToggledEditorMode && this.angularScope && this.angularScope.toggleEditorMode) { this.angularScope.toggleEditorMode(); } if (this.angularScope) { this.angularScope.range = this.props.range; } if (hasNewError || hasToggledEditorMode) { // Some query controllers listen to data error events and need a digest // for some reason this needs to be done in next tick setTimeout(this.component.digest); } } } componentWillUnmount() { if (this.component) { this.component.destroy(); } } render() { return
(this.element = element)} style={{ width: '100%' }} />; } }