From b65642564a311f07b572ce2e1d63e4b83cb20903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sat, 8 Oct 2016 10:06:47 +0200 Subject: [PATCH 1/5] poc for new metric segment --- .../form_dropdown/form_dropdown.html | 13 ++ .../components/form_dropdown/form_dropdown.ts | 182 ++++++++++++++++++ public/app/core/core.ts | 2 + public/app/core/directives/metric_segment.js | 2 - .../elasticsearch/partials/bucket_agg.html | 3 +- .../elasticsearch/partials/metric_agg.html | 6 +- 6 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 public/app/core/components/form_dropdown/form_dropdown.html create mode 100644 public/app/core/components/form_dropdown/form_dropdown.ts diff --git a/public/app/core/components/form_dropdown/form_dropdown.html b/public/app/core/components/form_dropdown/form_dropdown.html new file mode 100644 index 00000000000..34737eab27e --- /dev/null +++ b/public/app/core/components/form_dropdown/form_dropdown.html @@ -0,0 +1,13 @@ + + + + diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts new file mode 100644 index 00000000000..fd363d3b75e --- /dev/null +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -0,0 +1,182 @@ +/// + +import config from 'app/core/config'; +import _ from 'lodash'; +import $ from 'jquery'; +import coreModule from '../../core_module'; + +function typeaheadMatcher(item) { + var str = this.query; + if (str[0] === '/') { str = str.substring(1); } + if (str[str.length - 1] === '/') { str = str.substring(0, str.length-1); } + return item.toLowerCase().match(str.toLowerCase()); +} + +export class FormDropdownCtrl { + inputElement: any; + linkElement: any; + value: any; + text: any; + display: any; + options: any; + cssClass: any; + allowCustom: any; + linkMode: boolean; + cancelBlur: any; + onChange: any; + + constructor(private $scope, $element, private $sce, private templateSrv) { + this.inputElement = $element.find('input').first(); + this.linkElement = $element.find('a').first(); + this.linkMode = true; + this.cancelBlur = null; + + if (this.options) { + var item = _.find(this.options, {value: this.value}); + this.updateDisplay(item ? item.text : this.value); + } + + this.inputElement.attr('data-provide', 'typeahead'); + this.inputElement.typeahead({ + source: this.typeaheadSource.bind(this), + minLength: 0, + items: 10000, + updater: this.typeaheadUpdater.bind(this), + matcher: typeaheadMatcher, + }); + + // modify typeahead lookup + // this = typeahead + var typeahead = this.inputElement.data('typeahead'); + typeahead.lookup = function () { + this.query = this.$element.val() || ''; + var items = this.source(this.query, $.proxy(this.process, this)); + return items ? this.process(items) : items; + }; + + this.linkElement.keydown(evt => { + // trigger typeahead on down arrow or enter key + if (evt.keyCode === 40 || evt.keyCode === 13) { + this.linkElement.click(); + } + }); + + this.inputElement.blur(this.inputBlur.bind(this)); + } + + typeaheadSource(query, callback) { + if (this.options) { + var typeaheadOptions = _.map(this.options, 'text'); + + // add current custom value + if (this.allowCustom) { + if (_.indexOf(typeaheadOptions, this.text) === -1) { + typeaheadOptions.unshift(this.text); + } + } + + callback(typeaheadOptions); + } + } + + typeaheadUpdater(text) { + if (text === this.text) { + clearTimeout(this.cancelBlur); + this.inputElement.focus(); + return text; + } + + this.inputElement.val(text); + this.switchToLink(true); + return text; + } + + switchToLink(fromClick) { + if (this.linkMode && !fromClick) { return; } + + clearTimeout(this.cancelBlur); + this.cancelBlur = null; + this.linkMode = true; + this.inputElement.hide(); + this.linkElement.show(); + this.updateValue(this.inputElement.val()); + } + + inputBlur() { + // happens long before the click event on the typeahead options + // need to have long delay because the blur + this.cancelBlur = setTimeout(this.switchToLink.bind(this), 200); + } + + updateValue(text) { + if (text === '' || this.text === text) { + return; + } + + this.$scope.$apply(() => { + var option = _.find(this.options, {text: text}); + + if (option) { + this.value = option.value; + this.updateDisplay(option.text); + } else if (this.allowCustom) { + this.value = text; + this.updateDisplay(text); + } + + // needs to call this after digest so + // property is synced with outerscope + this.$scope.$$postDigest(() => { + this.$scope.$apply(() => { + this.onChange(); + }); + }); + + }); + } + + updateDisplay(text) { + this.text = text; + this.display = this.$sce.trustAsHtml(this.templateSrv.highlightVariablesAsHtml(text)); + } + + open() { + this.inputElement.show(); + + this.inputElement.css('width', (Math.max(this.linkElement.width(), 80) + 16) + 'px'); + this.inputElement.focus(); + + this.linkElement.hide(); + this.linkMode = false; + + var typeahead = this.inputElement.data('typeahead'); + if (typeahead) { + this.inputElement.val(''); + typeahead.lookup(); + } + } +} + + + +export function formDropdownDirective() { + return { + restrict: 'E', + templateUrl: 'public/app/core/components/form_dropdown/form_dropdown.html', + controller: FormDropdownCtrl, + bindToController: true, + controllerAs: 'ctrl', + scope: { + value: "=", + options: "=", + getOptions: "&", + onChange: "&", + cssClass: "@", + allowCustom: "@", + }, + link: function() { + } + }; +} + +coreModule.directive('gfFormDropdown', formDropdownDirective); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index d44cbf4dbfb..ea55c22be8f 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -35,6 +35,7 @@ import {switchDirective} from './components/switch'; import {dashboardSelector} from './components/dashboard_selector'; import {queryPartEditorDirective} from './components/query_part/query_part_editor'; import {WizardFlow} from './components/wizard/wizard'; +import {formDropdownDirective} from './components/form_dropdown/form_dropdown'; import 'app/core/controllers/all'; import 'app/core/services/all'; import 'app/core/routes/routes'; @@ -62,4 +63,5 @@ export { queryPartEditorDirective, WizardFlow, colors, + formDropdownDirective, }; diff --git a/public/app/core/directives/metric_segment.js b/public/app/core/directives/metric_segment.js index 2001073ed80..62805161155 100644 --- a/public/app/core/directives/metric_segment.js +++ b/public/app/core/directives/metric_segment.js @@ -143,7 +143,6 @@ function (_, $, coreModule) { $input.focus(); linkMode = false; - var typeahead = $input.data('typeahead'); if (typeahead) { $input.val(''); @@ -152,7 +151,6 @@ function (_, $, coreModule) { }); $input.blur($scope.inputBlur); - $compile(elem.contents())($scope); } }; diff --git a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html index 36e914d06e0..2b674a9fdf9 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html +++ b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html @@ -5,7 +5,8 @@ Then by - + + diff --git a/public/app/plugins/datasource/elasticsearch/partials/metric_agg.html b/public/app/plugins/datasource/elasticsearch/partials/metric_agg.html index faa12b5693d..472cfca37fa 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/metric_agg.html +++ b/public/app/plugins/datasource/elasticsearch/partials/metric_agg.html @@ -11,9 +11,9 @@
- - - + + +
From 6a95df403ac967f1b24133209e36ebe313ce2d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 14 Jun 2017 19:42:45 -0400 Subject: [PATCH 2/5] refacoring: more work on metric segment replacement --- .../form_dropdown/form_dropdown.html | 13 --- .../components/form_dropdown/form_dropdown.ts | 90 ++++++++++++++----- public/app/core/directives/dash_edit_link.js | 2 +- public/app/core/directives/metric_segment.js | 2 + public/app/features/panel/metrics_tab.ts | 51 +++++------ .../features/panel/partials/metrics_tab.html | 15 ++-- 6 files changed, 102 insertions(+), 71 deletions(-) delete mode 100644 public/app/core/components/form_dropdown/form_dropdown.html diff --git a/public/app/core/components/form_dropdown/form_dropdown.html b/public/app/core/components/form_dropdown/form_dropdown.html deleted file mode 100644 index 34737eab27e..00000000000 --- a/public/app/core/components/form_dropdown/form_dropdown.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index fd363d3b75e..eb8be1e0945 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -15,15 +15,17 @@ function typeaheadMatcher(item) { export class FormDropdownCtrl { inputElement: any; linkElement: any; - value: any; - text: any; + model: any; display: any; + text: any; options: any; cssClass: any; allowCustom: any; linkMode: boolean; cancelBlur: any; onChange: any; + getOptions: any; + optionCache: any; constructor(private $scope, $element, private $sce, private templateSrv) { this.inputElement = $element.find('input').first(); @@ -31,11 +33,15 @@ export class FormDropdownCtrl { this.linkMode = true; this.cancelBlur = null; - if (this.options) { - var item = _.find(this.options, {value: this.value}); - this.updateDisplay(item ? item.text : this.value); + if (!this.getOptions) { + this.getOptions = () => { + return Promise.resolve(this.options); + }; } + // listen to model changes + $scope.$watch("ctrl.model", this.modelChanged.bind(this)); + this.inputElement.attr('data-provide', 'typeahead'); this.inputElement.typeahead({ source: this.typeaheadSource.bind(this), @@ -64,19 +70,40 @@ export class FormDropdownCtrl { this.inputElement.blur(this.inputBlur.bind(this)); } - typeaheadSource(query, callback) { - if (this.options) { - var typeaheadOptions = _.map(this.options, 'text'); + modelChanged(newVal) { + if (_.isObject(this.model)) { + this.updateDisplay(this.model.text); + } else { - // add current custom value + // if we have text use it + if (this.text) { + this.updateDisplay(this.text); + } else { + // otherwise we need to do initial lookup, usually happens first time + this.getOptions().then(options => { + var item = _.find(options, {value: this.model}); + this.updateDisplay(item ? item.text : this.model); + }); + } + } + } + + typeaheadSource(query, callback) { + this.getOptions({$query: query}).then(options => { + this.optionCache = options; + + // extract texts + let optionTexts = _.map(options, 'text'); + + // add custom values if (this.allowCustom) { - if (_.indexOf(typeaheadOptions, this.text) === -1) { - typeaheadOptions.unshift(this.text); + if (_.indexOf(optionTexts, this.text) === -1) { + options.unshift(this.text); } } - callback(typeaheadOptions); - } + callback(optionTexts); + }); } typeaheadUpdater(text) { @@ -114,21 +141,29 @@ export class FormDropdownCtrl { } this.$scope.$apply(() => { - var option = _.find(this.options, {text: text}); + var option = _.find(this.optionCache, {text: text}); if (option) { - this.value = option.value; - this.updateDisplay(option.text); + if (_.isObject(this.model)) { + this.model = option; + } else { + this.model = option.value; + } + this.text = option.text; } else if (this.allowCustom) { - this.value = text; - this.updateDisplay(text); + if (_.isObject(this.model)) { + this.model.text = this.model.value = text; + } else { + this.model = text; + } + this.text = text; } // needs to call this after digest so // property is synced with outerscope this.$scope.$$postDigest(() => { this.$scope.$apply(() => { - this.onChange(); + this.onChange({$option: option}); }); }); @@ -157,17 +192,30 @@ export class FormDropdownCtrl { } } +const template = ` + + +`; export function formDropdownDirective() { return { restrict: 'E', - templateUrl: 'public/app/core/components/form_dropdown/form_dropdown.html', + template: template, controller: FormDropdownCtrl, bindToController: true, controllerAs: 'ctrl', scope: { - value: "=", + model: "=", options: "=", getOptions: "&", onChange: "&", diff --git a/public/app/core/directives/dash_edit_link.js b/public/app/core/directives/dash_edit_link.js index 3e4bdd4c5c7..a4c1ad53b3c 100644 --- a/public/app/core/directives/dash_edit_link.js +++ b/public/app/core/directives/dash_edit_link.js @@ -35,7 +35,7 @@ function ($, angular, coreModule) { options.html = editViewMap[options.editview].html; } - if (lastEditView === options.editview) { + if (lastEditView && lastEditView === options.editview) { hideEditorPane(false); return; } diff --git a/public/app/core/directives/metric_segment.js b/public/app/core/directives/metric_segment.js index 0605d54a815..2e9442c15a0 100644 --- a/public/app/core/directives/metric_segment.js +++ b/public/app/core/directives/metric_segment.js @@ -143,6 +143,7 @@ function (_, $, coreModule) { $input.focus(); linkMode = false; + var typeahead = $input.data('typeahead'); if (typeahead) { $input.val(''); @@ -151,6 +152,7 @@ function (_, $, coreModule) { }); $input.blur($scope.inputBlur); + $compile(elem.contents())($scope); } }; diff --git a/public/app/features/panel/metrics_tab.ts b/public/app/features/panel/metrics_tab.ts index f2d99738040..c03c4d83bc2 100644 --- a/public/app/features/panel/metrics_tab.ts +++ b/public/app/features/panel/metrics_tab.ts @@ -5,8 +5,6 @@ import _ from 'lodash'; import {DashboardModel} from '../dashboard/model'; export class MetricsTabCtrl { - dsSegment: any; - mixedDsSegment: any; dsName: string; panel: any; panelCtrl: any; @@ -14,30 +12,26 @@ export class MetricsTabCtrl { current: any; nextRefId: string; dashboard: DashboardModel; + panelDsValue: any; + addQueryDropdown: any; /** @ngInject */ - constructor($scope, private uiSegmentSrv, datasourceSrv) { + constructor($scope, private uiSegmentSrv, private datasourceSrv) { this.panelCtrl = $scope.ctrl; $scope.ctrl = this; this.panel = this.panelCtrl.panel; this.dashboard = this.panelCtrl.dashboard; this.datasources = datasourceSrv.getMetricSources(); - - var dsValue = this.panelCtrl.panel.datasource || null; + this.panelDsValue = this.panelCtrl.panel.datasource || null; for (let ds of this.datasources) { - if (ds.value === dsValue) { + if (ds.value === this.panelDsValue) { this.current = ds; } } - if (!this.current) { - this.current = {name: dsValue + ' not found', value: null}; - } - - this.dsSegment = uiSegmentSrv.newSegment({value: this.current.name, selectMode: true}); - this.mixedDsSegment = uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true}); + this.addQueryDropdown = {text: 'Add Query', value: null, fake: true}; // update next ref id this.panelCtrl.nextRefId = this.dashboard.getNextQueryLetter(this.panel); @@ -46,33 +40,28 @@ export class MetricsTabCtrl { getOptions(includeBuiltin) { return Promise.resolve(this.datasources.filter(value => { return includeBuiltin || !value.meta.builtIn; - }).map(value => { - return this.uiSegmentSrv.newSegment(value.name); + }).map(ds => { + return {value: ds.value, text: ds.name, datasource: ds}; })); } - datasourceChanged() { - var ds = _.find(this.datasources, {name: this.dsSegment.value}); - if (ds) { - this.current = ds; - this.panelCtrl.setDatasource(ds); + datasourceChanged(option) { + if (!option) { + return; } + + this.current = option.datasource; + this.panelCtrl.setDatasource(option.datasource); } - mixedDatasourceChanged() { - var target: any = {isNew: true}; - var ds = _.find(this.datasources, {name: this.mixedDsSegment.value}); - - if (ds) { - target.datasource = ds.name; - this.panelCtrl.addQuery(target); + addMixedQuery(option) { + if (!option) { + return; } - // metric segments are really bad, requires hacks to update - const segment = this.uiSegmentSrv.newSegment({value: 'Add Query', selectMode: true, fake: true}); - this.mixedDsSegment.value = segment.value; - this.mixedDsSegment.html = segment.html; - this.mixedDsSegment.text = segment.text; + var target: any = {isNew: true}; + this.panelCtrl.addQuery({isNew: true, datasource: option.datasource.name}); + this.addQueryDropdown = {text: 'Add Query', value: null, fake: true}; } addQuery() { diff --git a/public/app/features/panel/partials/metrics_tab.html b/public/app/features/panel/partials/metrics_tab.html index a020a2edbd1..32f43f1d639 100644 --- a/public/app/features/panel/partials/metrics_tab.html +++ b/public/app/features/panel/partials/metrics_tab.html @@ -19,7 +19,10 @@
@@ -30,10 +33,12 @@
- - + + +
From 5f3b5fdcb25c8d3c35b098d990520b1f1dc93d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 15 Jun 2017 12:21:12 -0400 Subject: [PATCH 3/5] updated --- .../core/components/form_dropdown/form_dropdown.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index eb8be1e0945..cb7390ead9a 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -194,17 +194,19 @@ export class FormDropdownCtrl { const template = ` + data-provide="typeahead" + class="gf-form-input" + spellcheck="false" + style="display:none"> + + ng-bind-html="ctrl.display"> + `; export function formDropdownDirective() { @@ -221,6 +223,7 @@ export function formDropdownDirective() { onChange: "&", cssClass: "@", allowCustom: "@", + selectMode: "@", }, link: function() { } From 76c4bfe2682a926ee479783abfe3ba4571e973ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 15 Jun 2017 14:03:26 -0400 Subject: [PATCH 4/5] ux: new metric segment is starting to work --- .../components/form_dropdown/form_dropdown.ts | 21 +++++++++---------- .../features/panel/partials/metrics_tab.html | 3 +-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index cb7390ead9a..50017225720 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -20,7 +20,9 @@ export class FormDropdownCtrl { text: any; options: any; cssClass: any; + cssClasses: any; allowCustom: any; + labelMode: boolean; linkMode: boolean; cancelBlur: any; onChange: any; @@ -33,15 +35,15 @@ export class FormDropdownCtrl { this.linkMode = true; this.cancelBlur = null; - if (!this.getOptions) { - this.getOptions = () => { - return Promise.resolve(this.options); - }; - } - // listen to model changes $scope.$watch("ctrl.model", this.modelChanged.bind(this)); + if (this.labelMode) { + this.cssClasses = 'gf-form-label ' + this.cssClass; + } else { + this.cssClasses = 'gf-form-input gf-form-input--dropdown ' + this.cssClass; + } + this.inputElement.attr('data-provide', 'typeahead'); this.inputElement.typeahead({ source: this.typeaheadSource.bind(this), @@ -199,9 +201,7 @@ const template = ` spellcheck="false" style="display:none"> - -Panel Data Source + on-change="ctrl.datasourceChanged($option)"> From 840099bec0b58f464f3605c30c2f072a96f4d994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 15 Jun 2017 15:56:24 -0400 Subject: [PATCH 5/5] refactor: metric segment remake --- .../components/form_dropdown/form_dropdown.ts | 38 ++++++++++---- .../features/panel/partials/metrics_tab.html | 1 + .../datasource/elasticsearch/bucket_agg.js | 21 +++++--- .../elasticsearch/partials/bucket_agg.html | 51 ++++++++++++++++--- .../elasticsearch/partials/metric_agg.html | 6 +-- .../datasource/elasticsearch/query_ctrl.ts | 4 +- 6 files changed, 91 insertions(+), 30 deletions(-) diff --git a/public/app/core/components/form_dropdown/form_dropdown.ts b/public/app/core/components/form_dropdown/form_dropdown.ts index 50017225720..72a101388b7 100644 --- a/public/app/core/components/form_dropdown/form_dropdown.ts +++ b/public/app/core/components/form_dropdown/form_dropdown.ts @@ -28,8 +28,9 @@ export class FormDropdownCtrl { onChange: any; getOptions: any; optionCache: any; + lookupText: boolean; - constructor(private $scope, $element, private $sce, private templateSrv) { + constructor(private $scope, $element, private $sce, private templateSrv, private $q) { this.inputElement = $element.find('input').first(); this.linkElement = $element.find('a').first(); this.linkMode = true; @@ -69,29 +70,45 @@ export class FormDropdownCtrl { } }); + this.inputElement.keydown(evt => { + if (evt.keyCode === 13) { + this.inputElement.blur(); + } + }); + this.inputElement.blur(this.inputBlur.bind(this)); } - modelChanged(newVal) { + getOptionsInternal(query) { + var result = this.getOptions({$query: query}); + if (this.isPromiseLike(result)) { + return result; + } + return this.$q.when(result); + } + + isPromiseLike(obj) { + return obj && (typeof obj.then === 'function'); + } + + modelChanged() { if (_.isObject(this.model)) { this.updateDisplay(this.model.text); } else { - // if we have text use it - if (this.text) { - this.updateDisplay(this.text); - } else { - // otherwise we need to do initial lookup, usually happens first time - this.getOptions().then(options => { + if (this.lookupText) { + this.getOptionsInternal("").then(options => { var item = _.find(options, {value: this.model}); this.updateDisplay(item ? item.text : this.model); }); + } else { + this.updateDisplay(this.model); } } } typeaheadSource(query, callback) { - this.getOptions({$query: query}).then(options => { + this.getOptionsInternal(query).then(options => { this.optionCache = options; // extract texts @@ -223,9 +240,8 @@ export function formDropdownDirective() { cssClass: "@", allowCustom: "@", labelMode: "@", + lookupText: "@", }, - link: function() { - } }; } diff --git a/public/app/features/panel/partials/metrics_tab.html b/public/app/features/panel/partials/metrics_tab.html index d8d8816d63b..bc0bcf7c6b2 100644 --- a/public/app/features/panel/partials/metrics_tab.html +++ b/public/app/features/panel/partials/metrics_tab.html @@ -35,6 +35,7 @@
diff --git a/public/app/plugins/datasource/elasticsearch/bucket_agg.js b/public/app/plugins/datasource/elasticsearch/bucket_agg.js index b2cfc819579..5adaed173af 100644 --- a/public/app/plugins/datasource/elasticsearch/bucket_agg.js +++ b/public/app/plugins/datasource/elasticsearch/bucket_agg.js @@ -26,13 +26,21 @@ function (angular, _, queryDef) { var bucketAggs = $scope.target.bucketAggs; $scope.orderByOptions = []; - $scope.bucketAggTypes = queryDef.bucketAggTypes; - $scope.orderOptions = queryDef.orderOptions; - $scope.sizeOptions = queryDef.sizeOptions; + + $scope.getBucketAggTypes = function() { + return queryDef.bucketAggTypes; + }; + + $scope.getOrderOptions = function() { + return queryDef.orderOptions; + }; + + $scope.getSizeOptions = function() { + return queryDef.sizeOptions; + }; $rootScope.onAppEvent('elastic-query-updated', function() { $scope.validateModel(); - $scope.updateOrderByOptions(); }, $scope); $scope.init = function() { @@ -166,11 +174,10 @@ function (angular, _, queryDef) { $scope.toggleOptions = function() { $scope.showOptions = !$scope.showOptions; - $scope.updateOrderByOptions(); }; - $scope.updateOrderByOptions = function() { - $scope.orderByOptions = queryDef.getOrderByOptions($scope.target); + $scope.getOrderByOptions = function() { + return queryDef.getOrderByOptions($scope.target); }; $scope.getFieldsInternal = function() { diff --git a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html index f6c86db0d1e..a180f97c994 100644 --- a/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html +++ b/public/app/plugins/datasource/elasticsearch/partials/bucket_agg.html @@ -5,9 +5,22 @@ Then by - - - + + + +
@@ -34,7 +47,13 @@
- + +
@@ -67,11 +86,23 @@
- + +
- + +
@@ -79,7 +110,13 @@
- + +
- - - + + +
diff --git a/public/app/plugins/datasource/elasticsearch/query_ctrl.ts b/public/app/plugins/datasource/elasticsearch/query_ctrl.ts index 009befb37a4..ef6f1c5cdc7 100644 --- a/public/app/plugins/datasource/elasticsearch/query_ctrl.ts +++ b/public/app/plugins/datasource/elasticsearch/query_ctrl.ts @@ -31,11 +31,11 @@ export class ElasticQueryCtrl extends QueryCtrl { queryUpdated() { var newJson = angular.toJson(this.datasource.queryBuilder.build(this.target), true); - if (newJson !== this.rawQueryOld) { - this.rawQueryOld = newJson; + if (this.rawQueryOld && newJson !== this.rawQueryOld) { this.refresh(); } + this.rawQueryOld = newJson; this.$rootScope.appEvent('elastic-query-updated'); }