Commit ebad19b2 by Dan Cech

work on tag dropdown behavior

parent 3a4e0513
import _ from 'lodash'; import _ from 'lodash';
import $ from 'jquery';
import coreModule from '../../core_module'; import coreModule from '../../core_module';
function typeaheadMatcher(item) { function typeaheadMatcher(item) {
var str = this.query; var str = this.query;
if (str === '') {
return true;
}
if (str[0] === '/') { if (str[0] === '/') {
str = str.substring(1); str = str.substring(1);
} }
...@@ -30,6 +32,8 @@ export class FormDropdownCtrl { ...@@ -30,6 +32,8 @@ export class FormDropdownCtrl {
getOptions: any; getOptions: any;
optionCache: any; optionCache: any;
lookupText: boolean; lookupText: boolean;
placeholder: any;
startOpen: any;
/** @ngInject **/ /** @ngInject **/
constructor(private $scope, $element, private $sce, private templateSrv, private $q) { constructor(private $scope, $element, private $sce, private templateSrv, private $q) {
...@@ -47,6 +51,10 @@ export class FormDropdownCtrl { ...@@ -47,6 +51,10 @@ export class FormDropdownCtrl {
this.cssClasses = 'gf-form-input gf-form-input--dropdown ' + this.cssClass; this.cssClasses = 'gf-form-input gf-form-input--dropdown ' + this.cssClass;
} }
if (this.placeholder) {
this.inputElement.attr('placeholder', this.placeholder);
}
this.inputElement.attr('data-provide', 'typeahead'); this.inputElement.attr('data-provide', 'typeahead');
this.inputElement.typeahead({ this.inputElement.typeahead({
source: this.typeaheadSource.bind(this), source: this.typeaheadSource.bind(this),
...@@ -61,8 +69,7 @@ export class FormDropdownCtrl { ...@@ -61,8 +69,7 @@ export class FormDropdownCtrl {
var typeahead = this.inputElement.data('typeahead'); var typeahead = this.inputElement.data('typeahead');
typeahead.lookup = function() { typeahead.lookup = function() {
this.query = this.$element.val() || ''; this.query = this.$element.val() || '';
var items = this.source(this.query, $.proxy(this.process, this)); this.source(this.query, this.process.bind(this));
return items ? this.process(items) : items;
}; };
this.linkElement.keydown(evt => { this.linkElement.keydown(evt => {
...@@ -81,6 +88,10 @@ export class FormDropdownCtrl { ...@@ -81,6 +88,10 @@ export class FormDropdownCtrl {
}); });
this.inputElement.blur(this.inputBlur.bind(this)); this.inputElement.blur(this.inputBlur.bind(this));
if (this.startOpen) {
setTimeout(this.open.bind(this), 0);
}
} }
getOptionsInternal(query) { getOptionsInternal(query) {
...@@ -121,9 +132,9 @@ export class FormDropdownCtrl { ...@@ -121,9 +132,9 @@ export class FormDropdownCtrl {
}); });
// add custom values // add custom values
if (this.allowCustom) { if (this.allowCustom && this.text !== '') {
if (_.indexOf(optionTexts, this.text) === -1) { if (_.indexOf(optionTexts, this.text) === -1) {
options.unshift(this.text); optionTexts.unshift(this.text);
} }
} }
...@@ -165,7 +176,7 @@ export class FormDropdownCtrl { ...@@ -165,7 +176,7 @@ export class FormDropdownCtrl {
updateValue(text) { updateValue(text) {
text = _.unescape(text); text = _.unescape(text);
if (text === '' || this.text === text) { if ((!this.allowCustom && text === '') || this.text === text) {
return; return;
} }
...@@ -214,7 +225,9 @@ export class FormDropdownCtrl { ...@@ -214,7 +225,9 @@ export class FormDropdownCtrl {
var typeahead = this.inputElement.data('typeahead'); var typeahead = this.inputElement.data('typeahead');
if (typeahead) { if (typeahead) {
if (!this.allowCustom) {
this.inputElement.val(''); this.inputElement.val('');
}
typeahead.lookup(); typeahead.lookup();
} }
} }
...@@ -231,7 +244,7 @@ const template = ` ...@@ -231,7 +244,7 @@ const template = `
tabindex="1" tabindex="1"
ng-click="ctrl.open()" ng-click="ctrl.open()"
give-focus="ctrl.focus" give-focus="ctrl.focus"
ng-bind-html="ctrl.display"> ng-bind-html="ctrl.display || ' '">
</a> </a>
`; `;
...@@ -250,6 +263,8 @@ export function formDropdownDirective() { ...@@ -250,6 +263,8 @@ export function formDropdownDirective() {
allowCustom: '@', allowCustom: '@',
labelMode: '@', labelMode: '@',
lookupText: '@', lookupText: '@',
placeholder: '@',
startOpen: '@',
}, },
}; };
} }
......
...@@ -106,10 +106,6 @@ function (angular, _, coreModule) { ...@@ -106,10 +106,6 @@ function (angular, _, coreModule) {
return new MetricSegment({fake: true, html: '<i class="fa fa-plus "></i>', type: 'plus-button', cssClass: 'query-part' }); return new MetricSegment({fake: true, html: '<i class="fa fa-plus "></i>', type: 'plus-button', cssClass: 'query-part' });
}; };
this.newSelectTagValue = function() {
return new MetricSegment({value: 'select tag value', fake: true});
};
}); });
}); });
...@@ -209,7 +209,7 @@ export default class GraphiteQuery { ...@@ -209,7 +209,7 @@ export default class GraphiteQuery {
} }
splitSeriesByTagParams(func) { splitSeriesByTagParams(func) {
const tagPattern = /([^\!=~]+)([\!=~]+)([^\!=~]+)/; const tagPattern = /([^\!=~]+)(\!?=~?)(.*)/;
return _.flatten( return _.flatten(
_.map(func.params, (param: string) => { _.map(func.params, (param: string) => {
let matches = tagPattern.exec(param); let matches = tagPattern.exec(param);
......
...@@ -11,29 +11,45 @@ ...@@ -11,29 +11,45 @@
</div> </div>
<div ng-repeat="tag in ctrl.queryModel.tags" class="gf-form"> <div ng-repeat="tag in ctrl.queryModel.tags" class="gf-form">
<gf-form-dropdown model="tag.key" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-key" <gf-form-dropdown
model="tag.key"
lookup-text="false"
allow-custom="true"
label-mode="true"
css-class="query-segment-key"
get-options="ctrl.getTags($index, $query)" get-options="ctrl.getTags($index, $query)"
on-change="ctrl.tagChanged(tag, $index)"> on-change="ctrl.tagChanged(tag, $index)"
</gf-form-dropdown> />
<gf-form-dropdown model="tag.operator" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-operator" <gf-form-dropdown
model="tag.operator"
lookup-text="false"
allow-custom="false"
label-mode="true"
css-class="query-segment-operator"
get-options="ctrl.getTagOperators()" get-options="ctrl.getTagOperators()"
on-change="ctrl.tagChanged(tag, $index)" on-change="ctrl.tagChanged(tag, $index)"
min-input-width="30"> min-input-width="30"
</gf-form-dropdown> />
<gf-form-dropdown model="tag.value" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-value" <gf-form-dropdown
model="tag.value"
lookup-text="false"
allow-custom="true"
label-mode="true"
css-class="query-segment-value"
placeholder="select tag value"
get-options="ctrl.getTagValues(tag, $index, $query)" get-options="ctrl.getTagValues(tag, $index, $query)"
on-change="ctrl.tagChanged(tag, $index)"> on-change="ctrl.tagChanged(tag, $index)"
</gf-form-dropdown> start-open="!ctrl.showDelimiter($index)"
/>
<label class="gf-form-label query-keyword" ng-if="ctrl.showDelimiter($index)">AND</label> <label class="gf-form-label query-keyword" ng-if="ctrl.showDelimiter($index)">AND</label>
</div> </div>
<div ng-repeat="segment in ctrl.segments" role="menuitem" class="gf-form"> <div ng-repeat="segment in ctrl.segments" role="menuitem" class="gf-form">
<metric-segment segment="segment" get-options="ctrl.getAltSegments($index)" on-change="ctrl.segmentValueChanged(segment, $index)"></metric-segment> <metric-segment segment="segment" get-options="ctrl.getAltSegments($index)" on-change="ctrl.segmentValueChanged(segment, $index)" />
</div> </div>
<div ng-if="ctrl.queryModel.seriesByTagUsed" ng-repeat="segment in ctrl.addTagSegments" role="menuitem" class="gf-form"> <div ng-if="ctrl.queryModel.seriesByTagUsed" ng-repeat="segment in ctrl.addTagSegments" role="menuitem" class="gf-form">
<metric-segment segment="segment" get-options="ctrl.getTagsAsSegments()" on-change="ctrl.addNewTag(segment)"> <metric-segment segment="segment" get-options="ctrl.getTagsAsSegments()" on-change="ctrl.addNewTag(segment)" />
</metric-segment>
</div> </div>
<div class="gf-form gf-form--grow"> <div class="gf-form gf-form--grow">
......
...@@ -270,7 +270,7 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -270,7 +270,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
let newFunc = this.datasource.createFuncInstance('seriesByTag', { let newFunc = this.datasource.createFuncInstance('seriesByTag', {
withDefaultParams: false, withDefaultParams: false,
}); });
let tagParam = `${tag}=select tag value`; let tagParam = `${tag}=`;
newFunc.params = [tagParam]; newFunc.params = [tagParam];
this.queryModel.addFunction(newFunc); this.queryModel.addFunction(newFunc);
newFunc.added = true; newFunc.added = true;
...@@ -353,7 +353,7 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -353,7 +353,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
addNewTag(segment) { addNewTag(segment) {
let newTagKey = segment.value; let newTagKey = segment.value;
let newTag = { key: newTagKey, operator: '=', value: 'select tag value' }; let newTag = { key: newTagKey, operator: '=', value: '' };
this.queryModel.addTag(newTag); this.queryModel.addTag(newTag);
this.targetChanged(); this.targetChanged();
this.fixTagSegments(); this.fixTagSegments();
......
...@@ -284,12 +284,12 @@ describe('GraphiteQueryCtrl', function() { ...@@ -284,12 +284,12 @@ describe('GraphiteQueryCtrl', function() {
}); });
it('should update tags with default value', function() { it('should update tags with default value', function() {
const expected = [{ key: 'tag1', operator: '=', value: 'select tag value' }]; const expected = [{ key: 'tag1', operator: '=', value: '' }];
expect(ctx.ctrl.queryModel.tags).to.eql(expected); expect(ctx.ctrl.queryModel.tags).to.eql(expected);
}); });
it('should update target', function() { it('should update target', function() {
const expected = "seriesByTag('tag1=select tag value')"; const expected = "seriesByTag('tag1=')";
expect(ctx.ctrl.target.target).to.eql(expected); expect(ctx.ctrl.target.target).to.eql(expected);
}); });
}); });
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment