grafana/public/app/features/templating/variable.ts

185 lines
4.5 KiB
TypeScript
Raw Normal View History

import _ from 'lodash';
2017-12-20 05:33:33 -06:00
import { assignModelProperties } from 'app/core/utils/model_utils';
import { ScopedVars } from '@grafana/data';
/*
* This regex matches 3 types of variable reference with an optional format specifier
* \$(\w+) $var1
* \[\[([\s\S]+?)(?::(\w+))?\]\] [[var2]] or [[var2:fmt2]]
* \${(\w+)(?::(\w+))?} ${var3} or ${var3:fmt3}
*/
DataLinks: enable access to labels & field names (#18918) * POC: trying to see if there is a way to support objects in template interpolations * Added support for nested objects, and arrays * Added accessor cache * fixed unit tests * First take * Use links supplier in graph * Add field's index to cache items * Get field index from field cache * CHange FiledCacheItem to FieldWithIndex * Add refId to TimeSeries class * Make field link supplier work with _series, _field and _value vars * use field link supplier in graph * Fix yaxis settings * Update dashboard schema version and add migration for data links variables * Update snapshots * Update build in data link variables * FieldCache - idx -> index * Add current query results to panel editor * WIP Updated data links dropdown to display new variables * Fix build * Update variables syntac in field display, update migration * Field links supplier: review updates * Add data frame view and field name to TimeSeries for later inspection * Retrieve data frame from TimeSeries when clicking on plot graph * Use data frame's index instead of view * Retrieve data frame by index instead of view on TimeSeries * Update data links prism regex * Fix typecheck * Add value variables to suggestions list * UI update * Rename field to config in DisplayProcessorOptions * Proces single value of a field instead of entire data frame * Updated font size from 10px to 12px for auto complete * Replace fieldName with fieldIndex in TimeSeries * Don't use .entries() for iterating in field cache * Don't use FieldCache when retrieving field for datalinks in graph * Add value calculation variable to data links (#19031) * Add support for labels with dots in the name (#19033) * Docs update * Use field name instead of removed series.fieldName * Add test dashboard * Typos fix * Make visualization tab subscribe to query results * Added tags to dashboard so it shows up in lists * minor docs fix * Update singlestat-ish variables suggestions to contain series variables * Decrease suggestions update debounce * Enable whitespace characters(new line, space) in links and strip them when processing the data link * minor data links UI update * DataLinks: Add __from and __to variables suggestions to data links (#19093) * Add from and to variables suggestions to data links * Update docs * UI update and added info text * Change ESC global bind to bind (doesn't capture ESC on input) * Close datalinks suggestions on ESC * Remove unnecessary fragment
2019-09-13 09:38:21 -05:00
export const variableRegex = /\$(\w+)|\[\[([\s\S]+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::(\w+))?}/g;
// Helper function since lastIndex is not reset
export const variableRegexExec = (variableString: string) => {
variableRegex.lastIndex = 0;
return variableRegex.exec(variableString);
};
export const SEARCH_FILTER_VARIABLE = '__searchFilter';
export const containsSearchFilter = (query: string | unknown): boolean =>
query && typeof query === 'string' ? query.indexOf(SEARCH_FILTER_VARIABLE) !== -1 : false;
export const getSearchFilterScopedVar = (args: {
query: string;
wildcardChar: string;
options: { searchFilter?: string };
}): ScopedVars => {
const { query, wildcardChar } = args;
if (!containsSearchFilter(query)) {
return {};
}
let { options } = args;
options = options || { searchFilter: '' };
const value = options.searchFilter ? `${options.searchFilter}${wildcardChar}` : `${wildcardChar}`;
return {
__searchFilter: {
value,
text: '',
},
};
};
export enum VariableRefresh {
never,
onDashboardLoad,
onTimeRangeChanged,
}
export enum VariableHide {
dontHide,
hideVariable,
hideLabel,
}
export enum VariableSort {
disabled,
alphabeticalAsc,
alphabeticalDesc,
numericalAsc,
numericalDesc,
alphabeticalCaseInsensitiveAsc,
alphabeticalCaseInsensitiveDesc,
}
export interface VariableTag {
text: string | string[];
}
export interface VariableOption {
selected: boolean;
text: string | string[];
value: string | string[];
isNone?: boolean;
}
export type VariableType = 'query' | 'adhoc' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom';
export interface AdHocVariableFilter {
key: string;
operator: string;
value: string;
condition: string;
}
export interface AdHocVariableModel extends VariableModel {
datasource: string;
filters: AdHocVariableFilter[];
}
export interface CustomVariableModel extends VariableWithOptions {
allValue: string;
includeAll: boolean;
multi: boolean;
}
export interface DataSourceVariableModel extends VariableWithOptions {
includeAll: boolean;
multi: boolean;
refresh: VariableRefresh;
regex: string;
}
export interface IntervalVariableModel extends VariableWithOptions {
auto: boolean;
auto_min: string;
auto_count: number;
refresh: VariableRefresh;
}
export interface QueryVariableModel extends VariableWithOptions {
allValue: string;
datasource: string;
definition: string;
includeAll: boolean;
multi: boolean;
refresh: VariableRefresh;
regex: string;
sort: VariableSort;
tags: VariableTag[];
tagsQuery: string;
tagValuesQuery: string;
useTags: boolean;
}
export interface TextBoxVariableModel extends VariableWithOptions {}
export interface ConstantVariableModel extends VariableWithOptions {}
export interface VariableWithOptions extends VariableModel {
current: VariableOption;
options: VariableOption[];
query: string;
}
export interface VariableModel {
type: VariableType;
name: string;
label: string;
hide: VariableHide;
skipUrlSync: boolean;
}
export interface VariableActions {
setValue(option: any): any;
updateOptions(searchFilter?: string): any;
dependsOn(variable: any): any;
setValueFromUrl(urlValue: any): any;
getValueForUrl(): any;
getSaveModel(): any;
}
export type CtorType = new (...args: any[]) => {};
export interface VariableTypes {
[key: string]: {
name: string;
ctor: CtorType;
description: string;
supportsMulti?: boolean;
};
}
export let variableTypes: VariableTypes = {};
export { assignModelProperties };
export function containsVariable(...args: any[]) {
const variableName = args[args.length - 1];
args[0] = _.isString(args[0]) ? args[0] : Object['values'](args[0]).join(' ');
const variableString = args.slice(0, -1).join(' ');
const matches = variableString.match(variableRegex);
const isMatchingVariable =
matches !== null
? matches.find(match => {
const varMatch = variableRegexExec(match);
return varMatch !== null && varMatch.indexOf(variableName) > -1;
})
: false;
return !!isMatchingVariable;
}