From 345fb89699a275133af5b11a512110c8aaca3557 Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Thu, 23 Sep 2021 06:20:47 -0400 Subject: [PATCH] Dashboard: Short url generation works for variables values with spaces (#39552) (#39567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit 65d79d9a30ac577669f05b985fb2c6291d81de33) Co-authored-by: Hugo Häggmark --- .../components/ShareModal/utils.test.ts | 45 +++++++++++++++ .../dashboard/components/ShareModal/utils.ts | 56 ++++++++++++------- 2 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 public/app/features/dashboard/components/ShareModal/utils.test.ts diff --git a/public/app/features/dashboard/components/ShareModal/utils.test.ts b/public/app/features/dashboard/components/ShareModal/utils.test.ts new file mode 100644 index 00000000000..03bfae7db39 --- /dev/null +++ b/public/app/features/dashboard/components/ShareModal/utils.test.ts @@ -0,0 +1,45 @@ +import { buildParams } from './utils'; +import { TimeRange } from '@grafana/data'; + +describe('buildParams', () => { + it.each` + search | useCurrentTimeRange | selectedTheme | panel | expected + ${''} | ${true} | ${'current'} | ${undefined} | ${'from=1000&to=2000&orgId=2'} + ${''} | ${true} | ${'current'} | ${{ id: 3 }} | ${'from=1000&to=2000&orgId=2&viewPanel=3'} + ${''} | ${true} | ${'light'} | ${undefined} | ${'from=1000&to=2000&orgId=2&theme=light'} + ${''} | ${true} | ${'light'} | ${{ id: 3 }} | ${'from=1000&to=2000&orgId=2&theme=light&viewPanel=3'} + ${''} | ${false} | ${'current'} | ${undefined} | ${'orgId=2'} + ${''} | ${false} | ${'current'} | ${{ id: 3 }} | ${'orgId=2&viewPanel=3'} + ${''} | ${false} | ${'light'} | ${undefined} | ${'orgId=2&theme=light'} + ${''} | ${false} | ${'light'} | ${{ id: 3 }} | ${'orgId=2&theme=light&viewPanel=3'} + ${'editPanel=4'} | ${true} | ${'current'} | ${undefined} | ${'editPanel=4&from=1000&to=2000&orgId=2'} + ${'editPanel=4'} | ${true} | ${'current'} | ${{ id: 3 }} | ${'editPanel=4&from=1000&to=2000&orgId=2'} + ${'editPanel=4'} | ${true} | ${'light'} | ${undefined} | ${'editPanel=4&from=1000&to=2000&orgId=2&theme=light'} + ${'editPanel=4'} | ${true} | ${'light'} | ${{ id: 3 }} | ${'editPanel=4&from=1000&to=2000&orgId=2&theme=light'} + ${'editPanel=4'} | ${false} | ${'current'} | ${undefined} | ${'editPanel=4&orgId=2'} + ${'editPanel=4'} | ${false} | ${'current'} | ${{ id: 3 }} | ${'editPanel=4&orgId=2'} + ${'editPanel=4'} | ${false} | ${'light'} | ${undefined} | ${'editPanel=4&orgId=2&theme=light'} + ${'editPanel=4'} | ${false} | ${'light'} | ${{ id: 3 }} | ${'editPanel=4&orgId=2&theme=light'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${true} | ${'current'} | ${undefined} | ${'var=%2B1&var=a+value+with+spaces&var=true&from=1000&to=2000&orgId=2'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${true} | ${'current'} | ${{ id: 3 }} | ${'var=%2B1&var=a+value+with+spaces&var=true&from=1000&to=2000&orgId=2&viewPanel=3'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${true} | ${'light'} | ${undefined} | ${'var=%2B1&var=a+value+with+spaces&var=true&from=1000&to=2000&orgId=2&theme=light'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${true} | ${'light'} | ${{ id: 3 }} | ${'var=%2B1&var=a+value+with+spaces&var=true&from=1000&to=2000&orgId=2&theme=light&viewPanel=3'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${false} | ${'current'} | ${undefined} | ${'var=%2B1&var=a+value+with+spaces&var=true&orgId=2'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${false} | ${'current'} | ${{ id: 3 }} | ${'var=%2B1&var=a+value+with+spaces&var=true&orgId=2&viewPanel=3'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${false} | ${'light'} | ${undefined} | ${'var=%2B1&var=a+value+with+spaces&var=true&orgId=2&theme=light'} + ${'var=%2B1&var=a+value+with+spaces&var=true'} | ${false} | ${'light'} | ${{ id: 3 }} | ${'var=%2B1&var=a+value+with+spaces&var=true&orgId=2&theme=light&viewPanel=3'} + `( + "when called with search: '$search' and useCurrentTimeRange: '$useCurrentTimeRange' and selectedTheme: '$selectedTheme' and panel: '$panel'then result should be '$expected'", + ({ search, useCurrentTimeRange, selectedTheme, panel, expected }) => { + const range: TimeRange = ({ + from: 1000, + to: 2000, + raw: { from: 'now-6h', to: 'now' }, + } as unknown) as TimeRange; + const orgId = '2'; + const result = buildParams({ useCurrentTimeRange, selectedTheme, panel, search, range, orgId }); + + expect(result.toString()).toEqual(expected); + } + ); +}); diff --git a/public/app/features/dashboard/components/ShareModal/utils.ts b/public/app/features/dashboard/components/ShareModal/utils.ts index 51569ccaac4..8a7a26d227a 100644 --- a/public/app/features/dashboard/components/ShareModal/utils.ts +++ b/public/app/features/dashboard/components/ShareModal/utils.ts @@ -1,30 +1,45 @@ import { config } from '@grafana/runtime'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { createShortLink } from 'app/core/utils/shortLinks'; -import { PanelModel, dateTime, urlUtil } from '@grafana/data'; +import { dateTime, PanelModel, TimeRange, urlUtil } from '@grafana/data'; -export function buildParams(useCurrentTimeRange: boolean, selectedTheme?: string, panel?: PanelModel) { - let params = urlUtil.getUrlSearchParams(); +export interface BuildParamsArgs { + useCurrentTimeRange: boolean; + selectedTheme?: string; + panel?: PanelModel; + search?: string; + range?: TimeRange; + orgId?: string; +} - const range = getTimeSrv().timeRange(); - params.from = range.from.valueOf(); - params.to = range.to.valueOf(); - params.orgId = config.bootData.user.orgId; +export function buildParams({ + useCurrentTimeRange, + selectedTheme, + panel, + search = window.location.search, + range = getTimeSrv().timeRange(), + orgId = config.bootData.user.orgId, +}: BuildParamsArgs): URLSearchParams { + const searchParams = new URLSearchParams(search); + + searchParams.set('from', String(range.from.valueOf())); + searchParams.set('to', String(range.to.valueOf())); + searchParams.set('orgId', orgId); if (!useCurrentTimeRange) { - delete params.from; - delete params.to; + searchParams.delete('from'); + searchParams.delete('to'); } if (selectedTheme !== 'current') { - params.theme = selectedTheme; + searchParams.set('theme', selectedTheme!); } - if (panel && !params.editPanel) { - params.viewPanel = panel.id; + if (panel && !searchParams.has('editPanel')) { + searchParams.set('viewPanel', String(panel.id)); } - return params; + return searchParams; } export function buildBaseUrl() { @@ -45,8 +60,8 @@ export async function buildShareUrl( shortenUrl?: boolean ) { const baseUrl = buildBaseUrl(); - const params = buildParams(useCurrentTimeRange, selectedTheme, panel); - const shareUrl = urlUtil.appendQueryToUrl(baseUrl, urlUtil.toUrlParams(params)); + const params = buildParams({ useCurrentTimeRange, selectedTheme, panel }); + const shareUrl = urlUtil.appendQueryToUrl(baseUrl, params.toString()); if (shortenUrl) { return await createShortLink(shareUrl); } @@ -55,16 +70,17 @@ export async function buildShareUrl( export function buildSoloUrl(useCurrentTimeRange: boolean, selectedTheme?: string, panel?: PanelModel) { const baseUrl = buildBaseUrl(); - const params = buildParams(useCurrentTimeRange, selectedTheme, panel); + const params = buildParams({ useCurrentTimeRange, selectedTheme, panel }); let soloUrl = baseUrl.replace(config.appSubUrl + '/dashboard/', config.appSubUrl + '/dashboard-solo/'); soloUrl = soloUrl.replace(config.appSubUrl + '/d/', config.appSubUrl + '/d-solo/'); - params.panelId = params.editPanel ?? params.viewPanel; - delete params.editPanel; - delete params.viewPanel; + const panelId = params.get('editPanel') ?? params.get('viewPanel') ?? ''; + params.set('panelId', panelId); + params.delete('editPanel'); + params.delete('viewPanel'); - return urlUtil.appendQueryToUrl(soloUrl, urlUtil.toUrlParams(params)); + return urlUtil.appendQueryToUrl(soloUrl, params.toString()); } export function buildImageUrl(useCurrentTimeRange: boolean, selectedTheme?: string, panel?: PanelModel) {