poc for new metric segment
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<input type="text"
|
||||
data-provide="typeahead"
|
||||
class="gf-form-input"
|
||||
spellcheck="false"
|
||||
style="display:none"></input>
|
||||
|
||||
<a class="gf-form-label"
|
||||
ng-class="ctrl.cssClass"
|
||||
tabindex="1"
|
||||
ng-click="ctrl.open()"
|
||||
give-focus="ctrl.focus"
|
||||
ng-bind-html="ctrl.display"></a>
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
///<reference path="../../../headers/common.d.ts" />
|
||||
|
||||
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);
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
<span ng-hide="isFirst">Then by</span>
|
||||
</label>
|
||||
|
||||
<metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></metric-segment-model>
|
||||
<gf-form-dropdown value="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></gf-form-dropdown>
|
||||
<!-- <metric-segment-model property="agg.type" options="bucketAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></metric-segment-model> -->
|
||||
<metric-segment-model ng-if="agg.field" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
</div>
|
||||
|
||||
<div class="gf-form">
|
||||
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="width-10"></metric-segment-model>
|
||||
<metric-segment-model ng-if="aggDef.requiresField" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
||||
<metric-segment-model ng-if="aggDef.isPipelineAgg" property="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="width-12"></metric-segment-model>
|
||||
<gf-form-dropdown value="agg.type" options="metricAggTypes" on-change="onTypeChanged()" custom="false" css-class="width-10"></gf-form-dropdown>
|
||||
<gf-form-dropdown ng-if="aggDef.requiresField" value="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></gf-form-dropdown>
|
||||
<gf-form-dropdown ng-if="aggDef.isPipelineAgg" value="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="width-12"></gf-form-dropdown>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
|
||||
Reference in New Issue
Block a user