From 0c3657da7e41f4d895cbc7f32eda87695bbb25f9 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Wed, 30 Jan 2019 15:24:37 +0300 Subject: [PATCH] azuremonitor: suggest tables initially --- .../editor/KustoQueryField.tsx | 90 ++++++++++++++----- .../editor/editor_component.tsx | 8 +- .../partials/query.editor.html | 1 + .../query_ctrl.ts | 4 +- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx index fa79d4bdb99..c8f96fba211 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/KustoQueryField.tsx @@ -1,3 +1,4 @@ +import _ from 'lodash'; import Plain from 'slate-plain-serializer'; import QueryField from './query_field'; @@ -25,21 +26,43 @@ interface SuggestionGroup { skipFilter?: boolean; } +interface KustoSchema { + Databases: { + Default?: KustoDBSchema; + }; + Plugins?: any[]; +} + +interface KustoDBSchema { + Name?: string; + Functions?: any; + Tables?: any; +} + +const defaultSchema = () => ({ + Databases: { + Default: {} + } +}); + const cleanText = s => s.replace(/[{}[\]="(),!~+\-*/^%]/g, '').trim(); const wrapText = text => ({ text }); export default class KustoQueryField extends QueryField { fields: any; events: any; + schema: KustoSchema; constructor(props, context) { super(props, context); + this.schema = defaultSchema(); this.onTypeahead = debounce(this.onTypeahead, TYPEAHEAD_DELAY); } componentDidMount() { this.updateMenu(); + this.fetchSchema(); } onTypeahead = () => { @@ -128,7 +151,13 @@ export default class KustoQueryField extends QueryField { suggestionGroups = this._getKeywordSuggestions(); } else if (Plain.serialize(this.state.value) === '') { typeaheadContext = 'context-new'; - suggestionGroups = this._getInitialSuggestions(); + if (this.schema) { + suggestionGroups = this._getInitialSuggestions(); + } else { + this.fetchSchema(); + setTimeout(this.onTypeahead, 0); + return; + } } let results = 0; @@ -263,7 +292,7 @@ export default class KustoQueryField extends QueryField { { prefixMatch: true, label: 'Operators', - items: operatorTokens.map((s: any) => { s.type = 'function'; return s; }) + items: operatorTokens }, { prefixMatch: true, @@ -274,34 +303,46 @@ export default class KustoQueryField extends QueryField { prefixMatch: true, label: 'Macros', items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; }) + }, + { + prefixMatch: true, + label: 'Tables', + items: _.map(this.schema.Databases.Default.Tables, (t: any) => ({ text: t.Name })) } ]; } private _getInitialSuggestions(): SuggestionGroup[] { - // TODO: return datbase tables as an initial suggestion return [ { prefixMatch: true, - label: 'Keywords', - items: KEYWORDS.map(wrapText) - }, - { - prefixMatch: true, - label: 'Operators', - items: operatorTokens.map((s: any) => { s.type = 'function'; return s; }) - }, - { - prefixMatch: true, - label: 'Functions', - items: functionTokens.map((s: any) => { s.type = 'function'; return s; }) - }, - { - prefixMatch: true, - label: 'Macros', - items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; }) + label: 'Tables', + items: _.map(this.schema.Databases.Default.Tables, (t: any) => ({ text: t.Name })) } ]; + + // return [ + // { + // prefixMatch: true, + // label: 'Keywords', + // items: KEYWORDS.map(wrapText) + // }, + // { + // prefixMatch: true, + // label: 'Operators', + // items: operatorTokens.map((s: any) => { s.type = 'function'; return s; }) + // }, + // { + // prefixMatch: true, + // label: 'Functions', + // items: functionTokens.map((s: any) => { s.type = 'function'; return s; }) + // }, + // { + // prefixMatch: true, + // label: 'Macros', + // items: grafanaMacros.map((s: any) => { s.type = 'function'; return s; }) + // } + // ]; } private async _fetchEvents() { @@ -329,4 +370,13 @@ export default class KustoQueryField extends QueryField { // Stub this.fields = []; } + + private async fetchSchema() { + const schema = await this.props.getSchema(); + if (schema) { + this.schema = schema; + } else { + this.schema = defaultSchema(); + } + } } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx index 59e4ab12c81..7787f029ee7 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/editor/editor_component.tsx @@ -31,7 +31,7 @@ class Editor extends Component { }; render() { - const { request, variables } = this.props; + const { request, variables, getSchema } = this.props; const { edited, query } = this.state; return ( @@ -45,6 +45,7 @@ class Editor extends Component { placeholder="Enter a query" request={request} templateVariables={variables} + getSchema={getSchema} /> ); @@ -54,6 +55,9 @@ class Editor extends Component { coreModule.directive('kustoEditor', [ 'reactDirective', reactDirective => { - return reactDirective(Editor, ['change', 'database', 'execute', 'query', 'request', 'variables']); + return reactDirective(Editor, [ + 'change', 'database', 'execute', 'query', 'request', 'variables', + ['getSchema', { watchDepth: 'reference' }] + ]); }, ]); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/partials/query.editor.html b/public/app/plugins/datasource/grafana-azure-monitor-datasource/partials/query.editor.html index 49f02ec8355..592fccdcda9 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/partials/query.editor.html +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/partials/query.editor.html @@ -130,6 +130,7 @@ change="ctrl.onLogAnalyticsQueryChange" execute="ctrl.onLogAnalyticsQueryExecute" variables="ctrl.templateVariables" + getSchema="ctrl.getAzureLogAnalyticsSchema" /> diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts index fd42c172f11..b3aa5f9f6e9 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts @@ -304,7 +304,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl { /* Azure Log Analytics */ - getWorkspaces() { + getWorkspaces = () => { return this.datasource.azureLogAnalyticsDatasource .getWorkspaces() .then(list => { @@ -316,7 +316,7 @@ export class AzureMonitorQueryCtrl extends QueryCtrl { .catch(this.handleQueryCtrlError.bind(this)); } - getAzureLogAnalyticsSchema() { + getAzureLogAnalyticsSchema = () => { return this.getWorkspaces() .then(() => { return this.datasource.azureLogAnalyticsDatasource.getSchema(this.target.azureLogAnalytics.workspace);