EVOLUTION-MANAGER
Edit File: query_variable.ts
import _ from 'lodash'; import { assignModelProperties, containsVariable, QueryVariableModel, VariableActions, VariableHide, VariableOption, VariableRefresh, VariableSort, VariableTag, VariableType, variableTypes, } from './variable'; import { stringToJsRegex } from '@grafana/data'; import DatasourceSrv from '../plugins/datasource_srv'; import { TemplateSrv } from './template_srv'; import { VariableSrv } from './variable_srv'; import { TimeSrv } from '../dashboard/services/TimeSrv'; function getNoneOption(): VariableOption { return { text: 'None', value: '', isNone: true, selected: false }; } export class QueryVariable implements QueryVariableModel, VariableActions { type: VariableType; name: string; label: string; hide: VariableHide; skipUrlSync: boolean; datasource: string; query: string; regex: string; sort: VariableSort; options: VariableOption[]; current: VariableOption; refresh: VariableRefresh; multi: boolean; includeAll: boolean; useTags: boolean; tagsQuery: string; tagValuesQuery: string; tags: VariableTag[]; definition: string; allValue: string; defaults: QueryVariableModel = { type: 'query', name: '', label: null, hide: VariableHide.dontHide, skipUrlSync: false, datasource: null, query: '', regex: '', sort: VariableSort.disabled, refresh: VariableRefresh.never, multi: false, includeAll: false, allValue: null, options: [], current: {} as VariableOption, tags: [], useTags: false, tagsQuery: '', tagValuesQuery: '', definition: '', }; /** @ngInject */ constructor( private model: any, private datasourceSrv: DatasourceSrv, private templateSrv: TemplateSrv, private variableSrv: VariableSrv, private timeSrv: TimeSrv ) { // copy model properties to this instance assignModelProperties(this, model, this.defaults); this.updateOptionsFromMetricFindQuery.bind(this); } getSaveModel() { // copy back model properties to model assignModelProperties(this.model, this, this.defaults); // remove options if (this.refresh !== 0) { this.model.options = []; } return this.model; } setValue(option: any) { return this.variableSrv.setOptionAsCurrent(this, option); } setValueFromUrl(urlValue: any) { return this.variableSrv.setOptionFromUrl(this, urlValue); } getValueForUrl() { if (this.current.text === 'All') { return 'All'; } return this.current.value; } updateOptions(searchFilter?: string) { return this.datasourceSrv .get(this.datasource) .then(ds => this.updateOptionsFromMetricFindQuery(ds, searchFilter)) .then(this.updateTags.bind(this)) .then(this.variableSrv.validateVariableSelectionState.bind(this.variableSrv, this)); } updateTags(datasource: any) { if (this.useTags) { return this.metricFindQuery(datasource, this.tagsQuery).then((results: any[]) => { this.tags = []; for (let i = 0; i < results.length; i++) { this.tags.push(results[i].text); } return datasource; }); } else { delete this.tags; } return datasource; } getValuesForTag(tagKey: string) { return this.datasourceSrv.get(this.datasource).then(datasource => { const query = this.tagValuesQuery.replace('$tag', tagKey); return this.metricFindQuery(datasource, query).then((results: any) => { return _.map(results, value => { return value.text; }); }); }); } updateOptionsFromMetricFindQuery(datasource: any, searchFilter?: string) { return this.metricFindQuery(datasource, this.query, searchFilter).then((results: any) => { this.options = this.metricNamesToVariableValues(results); if (this.includeAll) { this.addAllOption(); } if (!this.options.length) { this.options.push(getNoneOption()); } return datasource; }); } metricFindQuery(datasource: any, query: string, searchFilter?: string) { const options: any = { range: undefined, variable: this, searchFilter }; if (this.refresh === 2) { options.range = this.timeSrv.timeRange(); } return datasource.metricFindQuery(query, options); } addAllOption() { this.options.unshift({ text: 'All', value: '$__all', selected: false }); } metricNamesToVariableValues(metricNames: any[]) { let regex, options, i, matches; options = []; if (this.regex) { regex = stringToJsRegex(this.templateSrv.replace(this.regex, {}, 'regex')); } for (i = 0; i < metricNames.length; i++) { const item = metricNames[i]; let text = item.text === undefined || item.text === null ? item.value : item.text; let value = item.value === undefined || item.value === null ? item.text : item.value; if (_.isNumber(value)) { value = value.toString(); } if (_.isNumber(text)) { text = text.toString(); } if (regex) { matches = regex.exec(value); if (!matches) { continue; } if (matches.length > 1) { value = matches[1]; text = matches[1]; } } options.push({ text: text, value: value }); } options = _.uniqBy(options, 'value'); return this.sortVariableValues(options, this.sort); } sortVariableValues(options: any[], sortOrder: number) { if (sortOrder === 0) { return options; } const sortType = Math.ceil(sortOrder / 2); const reverseSort = sortOrder % 2 === 0; if (sortType === 1) { options = _.sortBy(options, 'text'); } else if (sortType === 2) { options = _.sortBy(options, opt => { const matches = opt.text.match(/.*?(\d+).*/); if (!matches || matches.length < 2) { return -1; } else { return parseInt(matches[1], 10); } }); } else if (sortType === 3) { options = _.sortBy(options, opt => { return _.toLower(opt.text); }); } if (reverseSort) { options = options.reverse(); } return options; } dependsOn(variable: any) { return containsVariable(this.query, this.datasource, this.regex, variable.name); } } // @ts-ignore variableTypes['query'] = { name: 'Query', ctor: QueryVariable, description: 'Variable values are fetched from a datasource query', supportsMulti: true, };