mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Variables: Adds queryparam formatting option (#30858)
* Variables: Adds queryparam formatting option * Chore: fixes strict errors * Chore: changes after PR comments
This commit is contained in:
@@ -3,6 +3,8 @@ import { dateTime, Registry, RegistryItem, textUtil, VariableModel } from '@graf
|
||||
import { isArray, map, replace } from 'lodash';
|
||||
import { formatVariableLabel } from '../variables/shared/formatVariable';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/state/types';
|
||||
import { variableAdapters } from '../variables/adapters';
|
||||
import { VariableModel as ExtendedVariableModel } from '../variables/types';
|
||||
|
||||
export interface FormatOptions {
|
||||
value: any;
|
||||
@@ -217,6 +219,23 @@ export const formatRegistry = new Registry<FormatRegistryItem>(() => {
|
||||
return formatVariableLabel(variable);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'queryparam',
|
||||
name: 'Query Parameter',
|
||||
description:
|
||||
'Format variables as url parameter. Example in multi variable scenario A + B + C => var-foo=A&var-foo=B&var-foo=C.',
|
||||
formatter: (options, variable) => {
|
||||
const { name, type } = variable;
|
||||
const adapter = variableAdapters.get(type);
|
||||
const valueForUrl = adapter.getValueForUrl(variable as ExtendedVariableModel);
|
||||
|
||||
if (Array.isArray(valueForUrl)) {
|
||||
return valueForUrl.map((v) => formatQueryParameter(name, v)).join('&');
|
||||
}
|
||||
|
||||
return formatQueryParameter(name, valueForUrl);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return formats;
|
||||
@@ -236,3 +255,11 @@ function encodeURIComponentStrict(str: string) {
|
||||
return '%' + c.charCodeAt(0).toString(16).toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
function formatQueryParameter(name: string, value: string): string {
|
||||
return `var-${name}=${encodeURIComponentStrict(value)}`;
|
||||
}
|
||||
|
||||
export function isAllValue(value: any) {
|
||||
return value === ALL_VARIABLE_VALUE || (Array.isArray(value) && value[0] === ALL_VARIABLE_VALUE);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import { dateTime, TimeRange } from '@grafana/data';
|
||||
import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv';
|
||||
import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput';
|
||||
import { VariableAdapter, variableAdapters } from '../variables/adapters';
|
||||
import { createQueryVariableAdapter } from '../variables/query/adapter';
|
||||
import { createAdHocVariableAdapter } from '../variables/adhoc/adapter';
|
||||
import { VariableModel } from '../variables/types';
|
||||
|
||||
variableAdapters.setInit(() => [
|
||||
(createQueryVariableAdapter() as unknown) as VariableAdapter<VariableModel>,
|
||||
(createAdHocVariableAdapter() as unknown) as VariableAdapter<VariableModel>,
|
||||
]);
|
||||
|
||||
describe('templateSrv', () => {
|
||||
silenceConsoleOutput();
|
||||
@@ -225,6 +234,11 @@ describe('templateSrv', () => {
|
||||
const target = _templateSrv.replace('${test:pipe},$test', {}, 'glob');
|
||||
expect(target).toBe('value1|value2,{value1,value2}');
|
||||
});
|
||||
|
||||
it('should replace ${test:queryparam} with correct query parameter', () => {
|
||||
const target = _templateSrv.replace('${test:queryparam}', {});
|
||||
expect(target).toBe('var-test=All');
|
||||
});
|
||||
});
|
||||
|
||||
describe('variable with all option and custom value', () => {
|
||||
@@ -264,6 +278,11 @@ describe('templateSrv', () => {
|
||||
const target = _templateSrv.replace('this.$test', {}, 'regex');
|
||||
expect(target).toBe('this.*');
|
||||
});
|
||||
|
||||
it('should replace ${test:queryparam} with correct query parameter', () => {
|
||||
const target = _templateSrv.replace('${test:queryparam}', {});
|
||||
expect(target).toBe('var-test=All');
|
||||
});
|
||||
});
|
||||
|
||||
describe('lucene format', () => {
|
||||
@@ -640,4 +659,43 @@ describe('templateSrv', () => {
|
||||
expect(passedValue).toBe('hello');
|
||||
});
|
||||
});
|
||||
|
||||
describe('queryparam', () => {
|
||||
beforeEach(() => {
|
||||
_templateSrv = initTemplateSrv([
|
||||
{
|
||||
type: 'query',
|
||||
name: 'single',
|
||||
current: { value: 'value1' },
|
||||
options: [{ value: 'value1' }, { value: 'value2' }],
|
||||
},
|
||||
{
|
||||
type: 'query',
|
||||
name: 'multi',
|
||||
current: { value: ['value1', 'value2'] },
|
||||
options: [{ value: 'value1' }, { value: 'value2' }],
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('query variable with single value with queryparam format should return correct queryparam', () => {
|
||||
const target = _templateSrv.replace('${single:queryparam}', {});
|
||||
expect(target).toBe('var-single=value1');
|
||||
});
|
||||
|
||||
it('query variable with single value and queryparam format should return correct queryparam', () => {
|
||||
const target = _templateSrv.replace('${single}', {}, 'queryparam');
|
||||
expect(target).toBe('var-single=value1');
|
||||
});
|
||||
|
||||
it('query variable with multi value with queryparam format should return correct queryparam', () => {
|
||||
const target = _templateSrv.replace('${multi:queryparam}', {});
|
||||
expect(target).toBe('var-multi=value1&var-multi=value2');
|
||||
});
|
||||
|
||||
it('query variable with multi value and queryparam format should return correct queryparam', () => {
|
||||
const target = _templateSrv.replace('${multi}', {}, 'queryparam');
|
||||
expect(target).toBe('var-multi=value1&var-multi=value2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -282,7 +282,7 @@ export class TemplateSrv implements BaseTemplateSrv {
|
||||
value = this.getAllValue(variable);
|
||||
text = ALL_VARIABLE_TEXT;
|
||||
// skip formatting of custom all values
|
||||
if (variable.allValue && fmt !== 'text') {
|
||||
if (variable.allValue && fmt !== 'text' && fmt !== 'queryparam') {
|
||||
return this.replace(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
QueryEditorProps,
|
||||
StandardVariableQuery,
|
||||
StandardVariableSupport,
|
||||
VariableModel,
|
||||
VariableSupportType,
|
||||
} from '@grafana/data';
|
||||
|
||||
@@ -18,7 +19,6 @@ import {
|
||||
AdHocVariableModel,
|
||||
ConstantVariableModel,
|
||||
QueryVariableModel,
|
||||
VariableModel,
|
||||
VariableQueryEditorType,
|
||||
VariableWithMultiSupport,
|
||||
VariableWithOptions,
|
||||
|
||||
@@ -3,23 +3,42 @@ import { VariableRefresh } from './types';
|
||||
|
||||
describe('isAllVariable', () => {
|
||||
it.each`
|
||||
variable | expected
|
||||
${null} | ${false}
|
||||
${undefined} | ${false}
|
||||
${{}} | ${false}
|
||||
${{ current: {} }} | ${false}
|
||||
${{ current: { text: '' } }} | ${false}
|
||||
${{ current: { text: null } }} | ${false}
|
||||
${{ current: { text: undefined } }} | ${false}
|
||||
${{ current: { text: 'Alll' } }} | ${false}
|
||||
${{ current: { text: 'All' } }} | ${true}
|
||||
${{ current: { text: [] } }} | ${false}
|
||||
${{ current: { text: [null] } }} | ${false}
|
||||
${{ current: { text: [undefined] } }} | ${false}
|
||||
${{ current: { text: ['Alll'] } }} | ${false}
|
||||
${{ current: { text: ['Alll', 'All'] } }} | ${false}
|
||||
${{ current: { text: ['All'] } }} | ${true}
|
||||
${{ current: { text: { prop1: 'test' } } }} | ${false}
|
||||
variable | expected
|
||||
${null} | ${false}
|
||||
${undefined} | ${false}
|
||||
${{}} | ${false}
|
||||
${{ current: {} }} | ${false}
|
||||
${{ current: { text: '' } }} | ${false}
|
||||
${{ current: { text: null } }} | ${false}
|
||||
${{ current: { text: undefined } }} | ${false}
|
||||
${{ current: { text: 'Alll' } }} | ${false}
|
||||
${{ current: { text: 'All' } }} | ${true}
|
||||
${{ current: { text: [] } }} | ${false}
|
||||
${{ current: { text: [null] } }} | ${false}
|
||||
${{ current: { text: [undefined] } }} | ${false}
|
||||
${{ current: { text: ['Alll'] } }} | ${false}
|
||||
${{ current: { text: ['Alll', 'All'] } }} | ${false}
|
||||
${{ current: { text: ['All'] } }} | ${true}
|
||||
${{ current: { text: ['All', 'Alll'] } }} | ${true}
|
||||
${{ current: { text: { prop1: 'test' } } }} | ${false}
|
||||
${{ current: { value: '' } }} | ${false}
|
||||
${{ current: { value: null } }} | ${false}
|
||||
${{ current: { value: undefined } }} | ${false}
|
||||
${{ current: { value: '$__alll' } }} | ${false}
|
||||
${{ current: { value: '$__all' } }} | ${true}
|
||||
${{ current: { value: [] } }} | ${false}
|
||||
${{ current: { value: [null] } }} | ${false}
|
||||
${{ current: { value: [undefined] } }} | ${false}
|
||||
${{ current: { value: ['$__alll'] } }} | ${false}
|
||||
${{ current: { value: ['$__alll', '$__all'] } }} | ${false}
|
||||
${{ current: { value: ['$__all'] } }} | ${true}
|
||||
${{ current: { value: ['$__all', '$__alll'] } }} | ${true}
|
||||
${{ current: { value: { prop1: 'test' } } }} | ${false}
|
||||
${{ current: { value: '', text: '' } }} | ${false}
|
||||
${{ current: { value: '', text: 'All' } }} | ${true}
|
||||
${{ current: { value: '$__all', text: '' } }} | ${true}
|
||||
${{ current: { value: '', text: ['All'] } }} | ${true}
|
||||
${{ current: { value: ['$__all'], text: '' } }} | ${true}
|
||||
`("when called with params: 'variable': '$variable' then result should be '$expected'", ({ variable, expected }) => {
|
||||
expect(isAllVariable(variable)).toEqual(expected);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import isString from 'lodash/isString';
|
||||
import { ScopedVars, VariableType } from '@grafana/data';
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
|
||||
import { ALL_VARIABLE_TEXT } from './state/types';
|
||||
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from './state/types';
|
||||
import { QueryVariableModel, VariableModel, VariableRefresh } from './types';
|
||||
import { getTimeSrv } from '../dashboard/services/TimeSrv';
|
||||
import { variableAdapters } from './adapters';
|
||||
@@ -74,15 +74,29 @@ export const isAllVariable = (variable: any): boolean => {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!variable.current.text) {
|
||||
return false;
|
||||
if (variable.current.value) {
|
||||
const isArray = Array.isArray(variable.current.value);
|
||||
if (isArray && variable.current.value.length && variable.current.value[0] === ALL_VARIABLE_VALUE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isArray && variable.current.value === ALL_VARIABLE_VALUE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(variable.current.text)) {
|
||||
return variable.current.text.length ? variable.current.text[0] === ALL_VARIABLE_TEXT : false;
|
||||
if (variable.current.text) {
|
||||
const isArray = Array.isArray(variable.current.text);
|
||||
if (isArray && variable.current.text.length && variable.current.text[0] === ALL_VARIABLE_TEXT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isArray && variable.current.text === ALL_VARIABLE_TEXT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return variable.current.text === ALL_VARIABLE_TEXT;
|
||||
return false;
|
||||
};
|
||||
|
||||
export const getCurrentText = (variable: any): string => {
|
||||
|
||||
Reference in New Issue
Block a user