From 73b74856303542d5867052f8d9c17da91b323ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Mon, 6 Dec 2021 12:44:28 +0100 Subject: [PATCH] Variables: Fix so queryparam option works for scoped variables (#42742) * Variables: Fix so queryparam option work for scoped variables * Chore: update after PR comments --- .../app/features/templating/formatRegistry.ts | 13 +++----- .../features/templating/template_srv.test.ts | 32 ++++++++++++++++++- .../app/features/templating/template_srv.ts | 12 +++---- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/public/app/features/templating/formatRegistry.ts b/public/app/features/templating/formatRegistry.ts index a6f11e7d9eb..1af3c082143 100644 --- a/public/app/features/templating/formatRegistry.ts +++ b/public/app/features/templating/formatRegistry.ts @@ -3,8 +3,6 @@ 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; @@ -244,15 +242,14 @@ export const formatRegistry = new Registry(() => { description: 'Format variables as URL parameters. 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); + const { value } = options; + const { name } = variable; - if (Array.isArray(valueForUrl)) { - return valueForUrl.map((v) => formatQueryParameter(name, v)).join('&'); + if (Array.isArray(value)) { + return value.map((v) => formatQueryParameter(name, v)).join('&'); } - return formatQueryParameter(name, valueForUrl); + return formatQueryParameter(name, value); }, }, ]; diff --git a/public/app/features/templating/template_srv.test.ts b/public/app/features/templating/template_srv.test.ts index a63572175a1..61a1253e4a9 100644 --- a/public/app/features/templating/template_srv.test.ts +++ b/public/app/features/templating/template_srv.test.ts @@ -752,29 +752,59 @@ describe('templateSrv', () => { expect(target).toBe('var-single=value1'); }); + it('query variable with single value with queryparam format and scoped vars should return correct queryparam', () => { + const target = _templateSrv.replace(`\${single:queryparam}`, { single: { value: 'value1', text: 'value1' } }); + 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 single value and queryparam format and scoped vars should return correct queryparam', () => { + const target = _templateSrv.replace('${single}', { single: { value: 'value1', text: 'value1' } }, '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 with queryparam format and scoped vars should return correct queryparam', () => { + const target = _templateSrv.replace(`\${multi:queryparam}`, { multi: { value: 'value2', text: 'value2' } }); + expect(target).toBe('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'); }); + it('query variable with multi value and queryparam format and scoped vars should return correct queryparam', () => { + const target = _templateSrv.replace('${multi}', { multi: { value: 'value2', text: 'value2' } }, 'queryparam'); + expect(target).toBe('var-multi=value2'); + }); + it('query variable with adhoc value with queryparam format should return correct queryparam', () => { const target = _templateSrv.replace(`\${adhoc:queryparam}`, {}); expect(target).toBe('var-adhoc=alertstate%7C%3D%7Cfiring&var-adhoc=alertname%7C%3D%7CExampleAlertAlwaysFiring'); }); - it('query variable with multi value and queryparam format should return correct queryparam', () => { + it('query variable with adhoc value with queryparam format should return correct queryparam', () => { + const target = _templateSrv.replace(`\${adhoc:queryparam}`, { adhoc: { value: 'value2', text: 'value2' } }); + expect(target).toBe('var-adhoc=value2'); + }); + + it('query variable with adhoc value and queryparam format should return correct queryparam', () => { const target = _templateSrv.replace('${adhoc}', {}, 'queryparam'); expect(target).toBe('var-adhoc=alertstate%7C%3D%7Cfiring&var-adhoc=alertname%7C%3D%7CExampleAlertAlwaysFiring'); }); + + it('query variable with adhoc value and queryparam format should return correct queryparam', () => { + const target = _templateSrv.replace('${adhoc}', { adhoc: { value: 'value2', text: 'value2' } }, 'queryparam'); + expect(target).toBe('var-adhoc=value2'); + }); }); }); diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index 72ece2d0f76..9b522dbbf9f 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -7,7 +7,7 @@ import { AdHocVariableFilter, AdHocVariableModel, VariableModel } from '../varia import { getDataSourceSrv, setTemplateSrv, TemplateSrv as BaseTemplateSrv } from '@grafana/runtime'; import { FormatOptions, formatRegistry, FormatRegistryID } from './formatRegistry'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/state/types'; -import { safeStringifyValue } from '../../core/utils/explore'; +import { variableAdapters } from '../variables/adapters'; interface FieldAccessorCache { [key: string]: (obj: any) => any; @@ -115,7 +115,7 @@ export class TemplateSrv implements BaseTemplateSrv { return filters; } - formatValue(value: any, format: any, variable: any, text?: string) { + formatValue(value: any, format: any, variable: any, text?: string): string { // for some scopedVars there is no variable variable = variable || {}; @@ -282,9 +282,9 @@ export class TemplateSrv implements BaseTemplateSrv { return match; } - if (isAdHoc(variable)) { - const value = safeStringifyValue(variable.filters); - const text = variable.id; + if (fmt === FormatRegistryID.queryParam || isAdHoc(variable)) { + const value = variableAdapters.get(variable.type).getValueForUrl(variable); + const text = isAdHoc(variable) ? variable.id : variable.current.text; return this.formatValue(value, fmt, variable, text); } @@ -301,7 +301,7 @@ export class TemplateSrv implements BaseTemplateSrv { value = this.getAllValue(variable); text = ALL_VARIABLE_TEXT; // skip formatting of custom all values - if (variable.allValue && fmt !== FormatRegistryID.text && fmt !== FormatRegistryID.queryParam) { + if (variable.allValue && fmt !== FormatRegistryID.text) { return this.replace(value); } }