Commit 63d51d0d by Alexander Zobnin

graphite-tags: refactor, use <gf-form-dropdown> instead of <metric-segment>

parent a4daba63
...@@ -10,13 +10,27 @@ ...@@ -10,13 +10,27 @@
<label class="gf-form-label query-keyword">seriesByTag</label> <label class="gf-form-label query-keyword">seriesByTag</label>
</div> </div>
<div ng-repeat="tagSegment in ctrl.tagSegments" role="menuitem" class="gf-form"> <div ng-repeat="tag in ctrl.tags" class="gf-form">
<metric-segment segment="tagSegment" <gf-form-dropdown model="tag.key" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-key"
get-options="ctrl.getAltTagSegments($index)" get-options="ctrl.getTags()"
on-change="ctrl.tagSegmentChanged(tagSegment, $index)"> on-change="ctrl.tagChanged(tag, $index)">
</metric-segment> </gf-form-dropdown>
<gf-form-dropdown model="tag.operator" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-operator"
get-options="ctrl.getTagOperators()"
on-change="ctrl.tagChanged(tag, $index)">
</gf-form-dropdown>
<gf-form-dropdown model="tag.value" lookup-text="false" allow-custom="false" label-mode="true" css-class="query-segment-value"
get-options="ctrl.getTagValues(tag)"
on-change="ctrl.tagChanged(tag, $index)">
</gf-form-dropdown>
<label class="gf-form-label query-keyword" ng-if="ctrl.showDelimiter($index)">,</label> <label class="gf-form-label query-keyword" ng-if="ctrl.showDelimiter($index)">,</label>
</div> </div>
<div ng-if="ctrl.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>
</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)"></metric-segment>
......
...@@ -7,14 +7,17 @@ import {Parser} from './parser'; ...@@ -7,14 +7,17 @@ import {Parser} from './parser';
import {QueryCtrl} from 'app/plugins/sdk'; import {QueryCtrl} from 'app/plugins/sdk';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
const GRAPHITE_TAG_OPERATORS = ['=', '!=', '=~', '!=~'];
export class GraphiteQueryCtrl extends QueryCtrl { export class GraphiteQueryCtrl extends QueryCtrl {
static templateUrl = 'partials/query.editor.html'; static templateUrl = 'partials/query.editor.html';
functions: any[]; functions: any[];
segments: any[]; segments: any[];
tagSegments: any[]; addTagSegments: any[];
tags: any[];
seriesByTagUsed: boolean; seriesByTagUsed: boolean;
removeTagSegment: any; removeTagValue: string;
/** @ngInject **/ /** @ngInject **/
constructor($scope, $injector, private uiSegmentSrv, private templateSrv) { constructor($scope, $injector, private uiSegmentSrv, private templateSrv) {
...@@ -25,7 +28,7 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -25,7 +28,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
this.parseTarget(); this.parseTarget();
} }
this.removeTagSegment = uiSegmentSrv.newSegment({fake: true, value: '-- remove tag --'}); this.removeTagValue = '-- remove tag --';
} }
toggleEditorMode() { toggleEditorMode() {
...@@ -120,40 +123,6 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -120,40 +123,6 @@ export class GraphiteQueryCtrl extends QueryCtrl {
return func.def.name !== 'seriesByTag'; return func.def.name !== 'seriesByTag';
} }
checkForSeriesByTag() {
let seriesByTagFunc = _.find(this.functions, (func) => func.def.name === 'seriesByTag');
if (seriesByTagFunc) {
this.seriesByTagUsed = true;
let tags = this.splitSeriesByTagParams(seriesByTagFunc);
this.tagSegments = [];
_.each(tags, (tag) => {
this.tagSegments.push(this.uiSegmentSrv.newKey(tag.key));
this.tagSegments.push(this.uiSegmentSrv.newOperator(tag.operator));
this.tagSegments.push(this.uiSegmentSrv.newKeyValue(tag.value));
});
this.fixTagSegments();
}
}
splitSeriesByTagParams(func) {
const tagPattern = /([^\!=~]+)([\!=~]+)([^\!=~]+)/;
return _.flatten(_.map(func.params, (param: string) => {
let matches = tagPattern.exec(param);
if (matches) {
let tag = matches.slice(1);
if (tag.length === 3) {
return {
key: tag[0],
operator: tag[1],
value: tag[2]
}
}
}
return [];
}));
}
getSegmentPathUpTo(index) { getSegmentPathUpTo(index) {
var arr = this.segments.slice(0, index); var arr = this.segments.slice(0, index);
...@@ -201,36 +170,6 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -201,36 +170,6 @@ export class GraphiteQueryCtrl extends QueryCtrl {
return func.render(target); return func.render(target);
} }
getAltTagSegments(index) {
let paramPartIndex = getParamPartIndex(index);
if (paramPartIndex === 1) {
// Operator
let operators = ['=', '!=', '=~', '!=~'];
let segments = _.map(operators, (operator) => this.uiSegmentSrv.newOperator(operator));
return Promise.resolve(segments);
} else if (paramPartIndex === 0) {
// Tag
return this.datasource.getTags().then(segments => {
let altSegments = _.map(segments, segment => {
return this.uiSegmentSrv.newSegment({value: segment.text, expandable: false});
});
altSegments.splice(0, 0, _.cloneDeep(this.removeTagSegment));
return altSegments;
});
} else {
// Tag value
let relatedTagSegmentIndex = getRelatedTagSegmentIndex(index);
let tag = this.tagSegments[relatedTagSegmentIndex].value;
return this.datasource.getTagValues(tag).then(segments => {
let altSegments = _.map(segments, segment => {
return this.uiSegmentSrv.newSegment({value: segment.text, expandable: false});
});
return altSegments;
});
}
}
getAltSegments(index) { getAltSegments(index) {
var query = index === 0 ? '*' : this.getSegmentPathUpTo(index) + '.*'; var query = index === 0 ? '*' : this.getSegmentPathUpTo(index) + '.*';
var options = {range: this.panelCtrl.range, requestId: "get-alt-segments"}; var options = {range: this.panelCtrl.range, requestId: "get-alt-segments"};
...@@ -279,52 +218,6 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -279,52 +218,6 @@ export class GraphiteQueryCtrl extends QueryCtrl {
this.targetChanged(); this.targetChanged();
} }
tagSegmentChanged(tagSegment, segmentIndex) {
this.error = null;
if (tagSegment.value === this.removeTagSegment.value) {
this.removeTag(segmentIndex);
return;
}
if (tagSegment.type === 'plus-button') {
let newTag = {key: tagSegment.value, operator: '=', value: 'select tag value'};
this.tagSegments.splice(this.tagSegments.length - 1, 1);
this.addNewTag(newTag);
}
let paramIndex = getParamIndex(segmentIndex);
let newTagParam = this.renderTagParam(segmentIndex);
this.functions[this.getSeriesByTagFuncIndex()].params[paramIndex] = newTagParam;
this.targetChanged();
this.parseTarget();
}
getSeriesByTagFuncIndex() {
return _.findIndex(this.functions, (func) => func.def.name === 'seriesByTag');
}
addNewTag(tag) {
this.tagSegments.push(this.uiSegmentSrv.newKey(tag.key));
this.tagSegments.push(this.uiSegmentSrv.newOperator(tag.operator));
this.tagSegments.push(this.uiSegmentSrv.newKeyValue(tag.value));
}
removeTag(index) {
let paramIndex = getParamIndex(index);
this.tagSegments.splice(index, 3);
this.functions[this.getSeriesByTagFuncIndex()].params.splice(paramIndex, 1);
this.targetChanged();
this.parseTarget();
}
renderTagParam(segmentIndex) {
let tagIndex = getRelatedTagSegmentIndex(segmentIndex)
return _.map(this.tagSegments.slice(tagIndex, tagIndex + 3), (segment) => segment.value).join('');
}
targetTextChanged() { targetTextChanged() {
this.updateModelTarget(); this.updateModelTarget();
this.refresh(); this.refresh();
...@@ -454,28 +347,125 @@ export class GraphiteQueryCtrl extends QueryCtrl { ...@@ -454,28 +347,125 @@ export class GraphiteQueryCtrl extends QueryCtrl {
} }
} }
fixTagSegments() { //////////////////////////////////
var count = this.tagSegments.length; // Graphite seriesByTag support //
var lastSegment = this.tagSegments[Math.max(count-1, 0)]; //////////////////////////////////
checkForSeriesByTag() {
let seriesByTagFunc = _.find(this.functions, (func) => func.def.name === 'seriesByTag');
if (seriesByTagFunc) {
this.seriesByTagUsed = true;
let tags = this.splitSeriesByTagParams(seriesByTagFunc);
this.tags = tags;
this.fixTagSegments();
}
}
splitSeriesByTagParams(func) {
const tagPattern = /([^\!=~]+)([\!=~]+)([^\!=~]+)/;
return _.flatten(_.map(func.params, (param: string) => {
let matches = tagPattern.exec(param);
if (matches) {
let tag = matches.slice(1);
if (tag.length === 3) {
return {
key: tag[0],
operator: tag[1],
value: tag[2]
}
}
}
return [];
}));
}
if (!lastSegment || lastSegment.type !== 'plus-button') { getTags() {
this.tagSegments.push(this.uiSegmentSrv.newPlusButton()); return this.datasource.getTags().then((values) => {
let altTags = _.map(values, 'text');
altTags.splice(0, 0, this.removeTagValue);
return mapToDropdownOptions(altTags);
});
}
getTagsAsSegments() {
return this.datasource.getTags().then((values) => {
return _.map(values, (val) => {
return this.uiSegmentSrv.newSegment(val.text);
});
});
}
getTagOperators() {
return mapToDropdownOptions(GRAPHITE_TAG_OPERATORS);
}
getTagValues(tag) {
let tagKey = tag.key;
return this.datasource.getTagValues(tagKey).then((values) => {
let altValues = _.map(values, 'text');
return mapToDropdownOptions(altValues);
});
}
tagChanged(tag, tagIndex) {
this.error = null;
if (tag.key === this.removeTagValue) {
this.removeTag(tagIndex);
return;
} }
let newTagParam = renderTagString(tag);
this.getSeriesByTagFunc().params[tagIndex] = newTagParam;
this.targetChanged();
this.parseTarget();
} }
showDelimiter(index) { getSeriesByTagFuncIndex() {
return getParamPartIndex(index) === 2 && index !== this.tagSegments.length - 2; return _.findIndex(this.functions, (func) => func.def.name === 'seriesByTag');
} }
}
function getParamIndex(segmentIndex) { getSeriesByTagFunc() {
return Math.floor(segmentIndex / 3); let seriesByTagFuncIndex = this.getSeriesByTagFuncIndex();
if (seriesByTagFuncIndex >= 0) {
return this.functions[seriesByTagFuncIndex];
} else {
return undefined;
}
}
addNewTag(segment) {
let newTagKey = segment.value;
let newTag = {key: newTagKey, operator: '=', value: 'select tag value'};
let newTagParam = renderTagString(newTag);
this.getSeriesByTagFunc().params.push(newTagParam);
this.targetChanged();
this.parseTarget();
}
removeTag(index) {
this.getSeriesByTagFunc().params.splice(index, 1);
this.targetChanged();
this.parseTarget();
}
fixTagSegments() {
// Adding tag with the same name as just removed works incorrectly if single segment is used (instead of array)
this.addTagSegments = [this.uiSegmentSrv.newPlusButton()];
}
showDelimiter(index) {
return index !== this.tags.length - 1;
}
} }
function getParamPartIndex(segmentIndex) { function renderTagString(tag) {
return segmentIndex % 3; return tag.key + tag.operator + tag.value;
} }
function getRelatedTagSegmentIndex(segmentIndex) { function mapToDropdownOptions(results) {
return getParamIndex(segmentIndex) * 3; return _.map(results, (value) => {
return {text: value, value: value};
});
} }
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