| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- import kbn from 'app/core/utils/kbn';
- import _ from 'lodash';
- import { variableRegex } from 'app/features/templating/variable';
- function luceneEscape(value) {
- return value.replace(/([\!\*\+\-\=<>\s\&\|\(\)\[\]\{\}\^\~\?\:\\/"])/g, '\\$1');
- }
- export class TemplateSrv {
- variables: any[];
- private regex = variableRegex;
- private index = {};
- private grafanaVariables = {};
- private builtIns = {};
- constructor() {
- this.builtIns['__interval'] = { text: '1s', value: '1s' };
- this.builtIns['__interval_ms'] = { text: '100', value: '100' };
- this.variables = [];
- }
- init(variables) {
- this.variables = variables;
- this.updateTemplateData();
- }
- updateTemplateData() {
- const existsOrEmpty = value => value || value === '';
- this.index = this.variables.reduce((acc, currentValue) => {
- if (currentValue.current && (currentValue.current.isNone || existsOrEmpty(currentValue.current.value))) {
- acc[currentValue.name] = currentValue;
- }
- return acc;
- }, {});
- }
- variableInitialized(variable) {
- this.index[variable.name] = variable;
- }
- getAdhocFilters(datasourceName) {
- let filters = [];
- if (this.variables) {
- for (let i = 0; i < this.variables.length; i++) {
- const variable = this.variables[i];
- if (variable.type !== 'adhoc') {
- continue;
- }
- // null is the "default" datasource
- if (variable.datasource === null || variable.datasource === datasourceName) {
- filters = filters.concat(variable.filters);
- } else if (variable.datasource.indexOf('$') === 0) {
- if (this.replace(variable.datasource) === datasourceName) {
- filters = filters.concat(variable.filters);
- }
- }
- }
- }
- return filters;
- }
- luceneFormat(value) {
- if (typeof value === 'string') {
- return luceneEscape(value);
- }
- if (value instanceof Array && value.length === 0) {
- return '__empty__';
- }
- const quotedValues = _.map(value, val => {
- return '"' + luceneEscape(val) + '"';
- });
- return '(' + quotedValues.join(' OR ') + ')';
- }
- // encode string according to RFC 3986; in contrast to encodeURIComponent()
- // also the sub-delims "!", "'", "(", ")" and "*" are encoded;
- // unicode handling uses UTF-8 as in ECMA-262.
- encodeURIComponentStrict(str) {
- return encodeURIComponent(str).replace(/[!'()*]/g, (c) => {
- return '%' + c.charCodeAt(0).toString(16).toUpperCase();
- });
- }
- formatValue(value, format, variable) {
- // for some scopedVars there is no variable
- variable = variable || {};
- if (typeof format === 'function') {
- return format(value, variable, this.formatValue);
- }
- switch (format) {
- case 'regex': {
- if (typeof value === 'string') {
- return kbn.regexEscape(value);
- }
- const escapedValues = _.map(value, kbn.regexEscape);
- if (escapedValues.length === 1) {
- return escapedValues[0];
- }
- return '(' + escapedValues.join('|') + ')';
- }
- case 'lucene': {
- return this.luceneFormat(value);
- }
- case 'pipe': {
- if (typeof value === 'string') {
- return value;
- }
- return value.join('|');
- }
- case 'distributed': {
- if (typeof value === 'string') {
- return value;
- }
- return this.distributeVariable(value, variable.name);
- }
- case 'csv': {
- if (_.isArray(value)) {
- return value.join(',');
- }
- return value;
- }
- case 'percentencode': {
- // like glob, but url escaped
- if (_.isArray(value)) {
- return this.encodeURIComponentStrict('{' + value.join(',') + '}');
- }
- return this.encodeURIComponentStrict(value);
- }
- default: {
- if (_.isArray(value)) {
- return '{' + value.join(',') + '}';
- }
- return value;
- }
- }
- }
- setGrafanaVariable(name, value) {
- this.grafanaVariables[name] = value;
- }
- getVariableName(expression) {
- this.regex.lastIndex = 0;
- const match = this.regex.exec(expression);
- if (!match) {
- return null;
- }
- const variableName = match.slice(1).find(match => match !== undefined);
- return variableName;
- }
- variableExists(expression) {
- const name = this.getVariableName(expression);
- return name && this.index[name] !== void 0;
- }
- highlightVariablesAsHtml(str) {
- if (!str || !_.isString(str)) {
- return str;
- }
- str = _.escape(str);
- this.regex.lastIndex = 0;
- return str.replace(this.regex, (match, var1, var2, fmt2, var3) => {
- if (this.index[var1 || var2 || var3] || this.builtIns[var1 || var2 || var3]) {
- return '<span class="template-variable">' + match + '</span>';
- }
- return match;
- });
- }
- getAllValue(variable) {
- if (variable.allValue) {
- return variable.allValue;
- }
- const values = [];
- for (let i = 1; i < variable.options.length; i++) {
- values.push(variable.options[i].value);
- }
- return values;
- }
- replace(target, scopedVars?, format?) {
- if (!target) {
- return target;
- }
- let variable, systemValue, value, fmt;
- this.regex.lastIndex = 0;
- return target.replace(this.regex, (match, var1, var2, fmt2, var3, fmt3) => {
- variable = this.index[var1 || var2 || var3];
- fmt = fmt2 || fmt3 || format;
- if (scopedVars) {
- value = scopedVars[var1 || var2 || var3];
- if (value) {
- return this.formatValue(value.value, fmt, variable);
- }
- }
- if (!variable) {
- return match;
- }
- systemValue = this.grafanaVariables[variable.current.value];
- if (systemValue) {
- return this.formatValue(systemValue, fmt, variable);
- }
- value = variable.current.value;
- if (this.isAllValue(value)) {
- value = this.getAllValue(variable);
- // skip formatting of custom all values
- if (variable.allValue) {
- return this.replace(value);
- }
- }
- const res = this.formatValue(value, fmt, variable);
- return res;
- });
- }
- isAllValue(value) {
- return value === '$__all' || (Array.isArray(value) && value[0] === '$__all');
- }
- replaceWithText(target, scopedVars) {
- if (!target) {
- return target;
- }
- let variable;
- this.regex.lastIndex = 0;
- return target.replace(this.regex, (match, var1, var2, fmt2, var3) => {
- if (scopedVars) {
- const option = scopedVars[var1 || var2 || var3];
- if (option) {
- return option.text;
- }
- }
- variable = this.index[var1 || var2 || var3];
- if (!variable) {
- return match;
- }
- return this.grafanaVariables[variable.current.value] || variable.current.text;
- });
- }
- fillVariableValuesForUrl(params, scopedVars) {
- _.each(this.variables, variable => {
- if (scopedVars && scopedVars[variable.name] !== void 0) {
- if (scopedVars[variable.name].skipUrlSync) {
- return;
- }
- params['var-' + variable.name] = scopedVars[variable.name].value;
- } else {
- if (variable.skipUrlSync) {
- return;
- }
- params['var-' + variable.name] = variable.getValueForUrl();
- }
- });
- }
- distributeVariable(value, variable) {
- value = _.map(value, (val, index) => {
- if (index !== 0) {
- return variable + '=' + val;
- } else {
- return val;
- }
- });
- return value.join(',');
- }
- }
- export default new TemplateSrv();
|