From 437f3ff93667b0b0e7dfb41b2875541de5c77e97 Mon Sep 17 00:00:00 2001 From: jackyin <648588267@qq.com> Date: Wed, 21 May 2025 12:57:33 +0800 Subject: [PATCH] URLParams: Stringify true values as key=true always (#97346) --- packages/grafana-data/src/utils/url.test.ts | 10 ++++++---- packages/grafana-data/src/utils/url.ts | 7 +------ .../dashboard-scene/sharing/ShareLinkTab.test.tsx | 2 +- public/app/features/dashboard/services/TimeSrv.test.ts | 2 +- public/app/features/templating/template_srv.ts | 4 ++-- public/app/features/variables/utils.ts | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/grafana-data/src/utils/url.test.ts b/packages/grafana-data/src/utils/url.test.ts index 58e20733593..d0be86cb209 100644 --- a/packages/grafana-data/src/utils/url.test.ts +++ b/packages/grafana-data/src/utils/url.test.ts @@ -11,7 +11,9 @@ describe('toUrlParams', () => { isNull: null, isUndefined: undefined, }); - expect(url).toBe('server=backend-01&hasSpace=has%20space&many=1&many=2&many=3&true&number=20&isNull=&isUndefined='); + expect(url).toBe( + 'server=backend-01&hasSpace=has%20space&many=1&many=2&many=3&true=true&number=20&isNull=&isUndefined=' + ); }); it('should encode the same way as angularjs', () => { const url = urlUtil.toUrlParams({ @@ -25,7 +27,7 @@ describe('toUrlParams', () => { bool1: true, bool2: false, }); - expect(url).toBe('bool1&bool2=false'); + expect(url).toBe('bool1=true&bool2=false'); }); it("should encode the following special characters [!'()*]", () => { const url = urlUtil.toUrlParams({ @@ -45,7 +47,7 @@ describe('toUrlParams', () => { oneMore: false, }); expect(params).toBe( - 'server=backend-01&hasSpace=has%20space&many=1&many=2&many=3&true&number=20&isNull=&isUndefined=&oneMore=false' + 'server=backend-01&hasSpace=has%20space&many=1&many=2&many=3&true=true&number=20&isNull=&isUndefined=&oneMore=false' ); }); @@ -61,7 +63,7 @@ describe('toUrlParams', () => { bool1: true, bool2: false, }); - expect(url).toBe('bool1&bool2=false'); + expect(url).toBe('bool1=true&bool2=false'); }); }); diff --git a/packages/grafana-data/src/utils/url.ts b/packages/grafana-data/src/utils/url.ts index b98ee5f5b64..d1557ff905b 100644 --- a/packages/grafana-data/src/utils/url.ts +++ b/packages/grafana-data/src/utils/url.ts @@ -60,12 +60,7 @@ function toUrlParams(a: any, encodeAsAngularJS = true) { const add = (k: string, v: any) => { v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v; - if (typeof v !== 'boolean') { - s[s.length] = encodingFunction(k, true) + '=' + encodingFunction(v, true); - } else { - const valueQueryPart = v ? '' : '=' + encodingFunction('false', true); - s[s.length] = encodingFunction(k, true) + valueQueryPart; - } + s[s.length] = encodingFunction(k, true) + '=' + encodingFunction(v, true); }; const buildParams = (prefix: string, obj: any) => { diff --git a/public/app/features/dashboard-scene/sharing/ShareLinkTab.test.tsx b/public/app/features/dashboard-scene/sharing/ShareLinkTab.test.tsx index d149d075e02..c7bb7284d0f 100644 --- a/public/app/features/dashboard-scene/sharing/ShareLinkTab.test.tsx +++ b/public/app/features/dashboard-scene/sharing/ShareLinkTab.test.tsx @@ -88,7 +88,7 @@ describe('ShareLinkTab', () => { await screen.findByRole('link', { name: selectors.pages.SharePanelModal.linkToRenderedImage }) ).toHaveAttribute( 'href', - 'http://dashboards.grafana.com/grafana/render/d-solo/dash-1?from=2019-02-11T13:00:00.000Z&to=2019-02-11T19:00:00.000Z&panelId=panel-12&__feature.dashboardSceneSolo&width=1000&height=500&tz=Pacific%2FEaster' + 'http://dashboards.grafana.com/grafana/render/d-solo/dash-1?from=2019-02-11T13:00:00.000Z&to=2019-02-11T19:00:00.000Z&panelId=panel-12&__feature.dashboardSceneSolo=true&width=1000&height=500&tz=Pacific%2FEaster' ); }); }); diff --git a/public/app/features/dashboard/services/TimeSrv.test.ts b/public/app/features/dashboard/services/TimeSrv.test.ts index 5418d88994f..981911116ea 100644 --- a/public/app/features/dashboard/services/TimeSrv.test.ts +++ b/public/app/features/dashboard/services/TimeSrv.test.ts @@ -297,7 +297,7 @@ describe('timeSrv', () => { timeSrv.setTime({ from: 'now-1h', to: 'now-10s' }); timeSrv.setTime({ from: 'now-1h', to: 'now-10s' }); - expect(locationUpdates[1].search).toEqual('?kiosk&from=now-1h&to=now-10s'); + expect(locationUpdates[1].search).toEqual('?kiosk=true&from=now-1h&to=now-10s'); }); it('should not change the URL if the updateUrl param is false', () => { diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index 9e0a22adb53..99ff71260d4 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -376,8 +376,8 @@ export class TemplateSrv implements BaseTemplateSrv { private _replaceWithVariableRegex(text: string, format: string | Function | undefined, replace: ReplaceFunction) { this.regex.lastIndex = 0; - return text.replace(this.regex, (match, var1, var2, fmt2, var3, fieldPath, fmt3) => { - const variableName = var1 || var2 || var3; + return text.replace(this.regex, (match, var1, var2, var3, fmt2, var4, fieldPath, fmt3) => { + const variableName = var1 || var2 || var3 || var4; const fmt = fmt2 || fmt3 || format; return replace(match, variableName, fieldPath, fmt); }); diff --git a/public/app/features/variables/utils.ts b/public/app/features/variables/utils.ts index 4ab42c8ec5c..8a0804d7e1f 100644 --- a/public/app/features/variables/utils.ts +++ b/public/app/features/variables/utils.ts @@ -30,7 +30,7 @@ import { TransactionStatus, VariableModel } from './types'; * \[\[(\w+?)(?::(\w+))?\]\] [[var2]] or [[var2:fmt2]] * \${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?} ${var3} or ${var3.fieldPath} or ${var3:fmt3} (or ${var3.fieldPath:fmt3} but that is not a separate capture group) */ -export const variableRegex = /\$(\w+)|\[\[(\w+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?}/g; +export const variableRegex = /\$(\w+)=true|\$(\w+)|\[\[(\w+?)(?::(\w+))?\]\]|\${(\w+)(?:\.([^:^\}]+))?(?::([^\}]+))?}/g; // Helper function since lastIndex is not reset export const variableRegexExec = (variableString: string) => {