From e6995d7ea70dfc5e6bb7a4c7a58e761f843afaff Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Fri, 10 Jan 2020 22:08:48 +0000 Subject: [PATCH] Parse URL through legacy platform URLs --- .../dashboard/__tests__/url_helper.test.ts | 108 +++++++++++++++++ .../kibana/public/dashboard/legacy_imports.ts | 1 + .../public/dashboard/np_ready/url_helper.ts | 102 ++++++++++++++++ .../plugins/lens/public/app_plugin/plugin.tsx | 44 +++---- .../lens/public/app_plugin/url_helper.test.ts | 102 ---------------- .../lens/public/app_plugin/url_helper.ts | 110 ------------------ 6 files changed, 235 insertions(+), 232 deletions(-) create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts create mode 100644 src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts delete mode 100644 x-pack/legacy/plugins/lens/public/app_plugin/url_helper.test.ts delete mode 100644 x-pack/legacy/plugins/lens/public/app_plugin/url_helper.ts diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts new file mode 100644 index 000000000000000..eab8d221ff8bb85 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts @@ -0,0 +1,108 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +jest.mock('../', () => ({ + DashboardConstants: { + ADD_EMBEDDABLE_ID: 'addEmbeddableId', + ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', + }, +})); + +jest.mock('../legacy_imports', () => { + return { + absoluteToParsedUrl: jest.fn(() => { + return { + basePath: '/pep', + appId: 'kibana', + appPath: '/dashboard?addEmbeddableType=lens&addEmbeddableId=123eb456cd&x=1&y=2&z=3', + hostname: 'localhost', + port: 5601, + protocol: 'http:', + addQueryParameter: () => {}, + }; + }), + }; +}); + +import { + addEmbeddableToDashboardUrl, + getLensUrlFromDashboardAbsoluteUrl, + getUrlVars, +} from '../np_ready/url_helper'; + +describe('Dashboard URL Helper', () => { + beforeEach(() => { + jest.resetModules(); + }); + + it('addEmbeddableToDashboardUrl', () => { + const id = '123eb456cd'; + const type = 'lens'; + const urlVars = { + x: '1', + y: '2', + z: '3', + }; + const basePath = '/pep'; + const url = + "http://localhost:5601/pep/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; + expect(addEmbeddableToDashboardUrl(url, basePath, id, urlVars, type)).toEqual( + `http://localhost:5601/pep/app/kibana#/dashboard?addEmbeddableType=${type}&addEmbeddableId=${id}&x=1&y=2&z=3` + ); + }); + + it('getUrlVars', () => { + let url = + "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; + expect(getUrlVars(url)).toEqual({ + _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))', + _a: "(description:'',filters:!()", + }); + url = 'http://mybusiness.mydomain.com/app/kibana#/dashboard?x=y&y=z'; + expect(getUrlVars(url)).toEqual({ + x: 'y', + y: 'z', + }); + url = 'http://notDashboardUrl'; + expect(getUrlVars(url)).toEqual({}); + url = 'http://localhost:5601/app/kibana#/dashboard/777182'; + expect(getUrlVars(url)).toEqual({}); + }); + + it('getLensUrlFromDashboardAbsoluteUrl', () => { + const id = '1244'; + const basePath = '/wev'; + let url = + "http://localhost:5601/wev/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; + expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( + 'http://localhost:5601/wev/app/kibana#/lens/edit/1244' + ); + + url = + "http://localhost:5601/wev/app/kibana#/dashboard/625357282?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"; + expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( + 'http://localhost:5601/wev/app/kibana#/lens/edit/1244' + ); + + url = 'http://myserver.mydomain.com:5601/wev/app/kibana#/dashboard/777182'; + expect(getLensUrlFromDashboardAbsoluteUrl(url, basePath, id)).toEqual( + 'http://myserver.mydomain.com:5601/wev/app/kibana#/lens/edit/1244' + ); + }); +}); diff --git a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts index ec0913e5fb3e772..ba019194310807f 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts +++ b/src/legacy/core_plugins/kibana/public/dashboard/legacy_imports.ts @@ -67,3 +67,4 @@ export { IInjector } from 'ui/chrome'; export { SavedObjectLoader } from 'ui/saved_objects'; export { VISUALIZE_EMBEDDABLE_TYPE } from '../visualize_embeddable'; export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router'; +export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url'; diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts new file mode 100644 index 000000000000000..517f91ed4cd32e1 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts @@ -0,0 +1,102 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { parse } from 'url'; +import { absoluteToParsedUrl } from '../legacy_imports'; +import { DashboardConstants } from './dashboard_constants'; +/** + * Return query params from URL + * @param url given url + */ +export function getUrlVars(url: string): Record { + const vars: Record = {}; + // @ts-ignore + url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(_, key, value) { + // @ts-ignore + vars[key] = value; + }); + return vars; +} + +/** * + * Returns dashboard URL with added embeddableType and embeddableId query params + * eg. + * input: url: http://localhost:5601/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)), embeddableId: 12345, embeddableType: 'lens' + * output: http://localhost:5601/lib/app/kibana#dashboard?addEmbeddableType=lens&addEmbeddableId=12345&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)) + * @param url dasbhoard absolute url + * @param embeddableId id of the saved visualization + * @param basePath current base path + * @param urlVars url query params (optional) + * @param embeddableType 'lens' or 'visualization' (optional, default is 'lens') + */ +export function addEmbeddableToDashboardUrl( + url: string | undefined, + basePath: string, + embeddableId: string, + urlVars?: Record, + embeddableType?: string +): string | null { + if (!url) { + return null; + } + const dashboardUrl = getUrlWithoutQueryParams(url); + const dashboardParsedUrl = absoluteToParsedUrl(dashboardUrl, basePath); + if (urlVars) { + const keys = Object.keys(urlVars).sort(); + keys.forEach(key => { + dashboardParsedUrl.addQueryParameter(key, urlVars[key]); + }); + } + dashboardParsedUrl.addQueryParameter( + DashboardConstants.ADD_EMBEDDABLE_TYPE, + embeddableType || 'lens' + ); + dashboardParsedUrl.addQueryParameter(DashboardConstants.ADD_EMBEDDABLE_ID, embeddableId); + return dashboardParsedUrl.getAbsoluteUrl(); +} + +/** + * Return Lens URL from dashboard absolute URL + * @param dashboardAbsoluteUrl + * @param basePath current base path + * @param id Lens id + */ +export function getLensUrlFromDashboardAbsoluteUrl( + dashboardAbsoluteUrl: string | undefined | null, + basePath: string | null, + id: string +): string | null { + if (!dashboardAbsoluteUrl || !basePath) { + return null; + } + const { host, protocol } = parse(dashboardAbsoluteUrl); + return `${protocol}//${host}${basePath}/app/kibana#/lens/edit/${id}`; +} + +/** + * Returns the portion of the URL without query params + * eg. + * input: http://localhost:5601/lib/app/kibana#/dashboard?param1=x¶m2=y¶m3=z + * output:http://localhost:5601/lib/app/kibana#/dashboard + * input: http://localhost:5601/lib/app/kibana#/dashboard/39292992?param1=x¶m2=y¶m3=z + * output: http://localhost:5601/lib/app/kibana#/dashboard/39292992 + * @param url url to parse + */ +function getUrlWithoutQueryParams(url: string): string { + return url.split('?')[0]; +} diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx index a787af6de8c3cbb..7465de2dba7f1f0 100644 --- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx +++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx @@ -44,11 +44,10 @@ import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../../common'; import { KibanaLegacySetup } from '../../../../../../src/plugins/kibana_legacy/public'; import { EditorFrameStart } from '../types'; import { - getKibanaBasePathFromDashboardUrl, addEmbeddableToDashboardUrl, - getDashboardUrlWithQueryParams, getUrlVars, -} from './url_helper'; + getLensUrlFromDashboardAbsoluteUrl, +} from '../../../../../../src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper'; export interface LensPluginSetupDependencies { kibana_legacy: KibanaLegacySetup; @@ -95,7 +94,6 @@ export class AppPlugin { } const { data, savedObjectsClient, editorFrame } = this.startDependencies; addHelpMenuToAppChrome(context.core.chrome); - const instance = editorFrame.createInstance({}); setReportManager( @@ -126,25 +124,31 @@ export class AppPlugin { routeProps.history.push(`/lens/edit/${id}`); const url = context.core.chrome.navLinks.get('kibana:dashboard'); if (!url) { - return; + throw new Error('Cannot get last dashboard url'); } const lastDashboardAbsoluteUrl = url.url; - const lensUrl = `${getKibanaBasePathFromDashboardUrl( - lastDashboardAbsoluteUrl - )}/lens/edit/${id}`; - if (lastDashboardAbsoluteUrl && lensUrl) { - const urlVars = getUrlVars(lastDashboardAbsoluteUrl); - updateUrlTime(urlVars); - window.history.pushState({}, '', lensUrl); - const dashboardUrl = getDashboardUrlWithQueryParams( - lastDashboardAbsoluteUrl, - urlVars - ); - const dashboardParsedUrl = addEmbeddableToDashboardUrl(dashboardUrl, id, 'lens'); - if (dashboardParsedUrl) { - window.history.pushState({}, '', dashboardParsedUrl); - } + const basePath = context.core.http.basePath.get(); + const lensUrl = getLensUrlFromDashboardAbsoluteUrl( + lastDashboardAbsoluteUrl, + basePath, + id + ); + if (!lastDashboardAbsoluteUrl || !lensUrl) { + throw new Error('Cannot get last dashboard url'); + } + window.history.pushState({}, '', lensUrl); + const urlVars = getUrlVars(lastDashboardAbsoluteUrl); + updateUrlTime(urlVars); // we need to pass in timerange in query params directly + const dashboardParsedUrl = addEmbeddableToDashboardUrl( + lastDashboardAbsoluteUrl, + basePath, + id, + urlVars + ); + if (!dashboardParsedUrl) { + throw new Error('Problem parsing dashboard url'); } + window.history.pushState({}, '', dashboardParsedUrl); } }; diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.test.ts b/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.test.ts deleted file mode 100644 index 1da035707e29fb4..000000000000000 --- a/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -jest.mock('../../../../../../src/legacy/core_plugins/kibana/public/dashboard', () => ({ - DashboardConstants: { - ADD_EMBEDDABLE_ID: 'addEmbeddableId', - ADD_EMBEDDABLE_TYPE: 'addEmbeddableType', - }, -})); - -import { - addEmbeddableToDashboardUrl, - getKibanaBasePathFromDashboardUrl, - getUrlVars, - getDashboardUrlWithQueryParams, -} from './url_helper'; - -describe('Lens URL Helper', () => { - it('getKibanaBasePathFromDashboardUrl', () => { - let url = - "http://localhost:5601/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getKibanaBasePathFromDashboardUrl(url)).toEqual('http://localhost:5601/lib/app/kibana#'); - - url = - 'http://mybusiness.mydomain.com/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))'; - expect(getKibanaBasePathFromDashboardUrl(url)).toEqual( - 'http://mybusiness.mydomain.com/lib/app/kibana#' - ); - - url = 'http://invalidUrl'; - expect(getKibanaBasePathFromDashboardUrl(url)).toBe(null); - }); - - it('addEmbeddableToDashboardUrl', () => { - const id = '123eb456cd'; - const type = 'lens'; - let url = - "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(addEmbeddableToDashboardUrl(url, id, type)).toEqual( - `http://localhost:5601/app/kibana#/dashboard?addEmbeddableType=${type}&addEmbeddableId=${id}&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:\'\',filters:!()` - ); - - url = - "http://mybusiness.mydomain.com/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(addEmbeddableToDashboardUrl(url, id, type)).toEqual( - `http://mybusiness.mydomain.com/app/kibana#/dashboard?addEmbeddableType=${type}&addEmbeddableId=${id}&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:\'\',filters:!()` - ); - - url = 'http://invalidUrl'; - expect(addEmbeddableToDashboardUrl(url, id, type)).toBe(null); - - url = - "http://localhost:5601/app/kibana#/dashboard/777182?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-4h,to:now))&_a=(description:'',filters:!()"; - expect(addEmbeddableToDashboardUrl(url, id, type)).toBe( - `http://localhost:5601/app/kibana#/dashboard/777182?addEmbeddableType=${type}&addEmbeddableId=${id}&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-4h,to:now))&_a=(description:'',filters:!()` - ); - }); - - it('getUrlVars', () => { - let url = - "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getUrlVars(url)).toEqual({ - _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))', - _a: "(description:'',filters:!()", - }); - url = 'http://mybusiness.mydomain.com/app/kibana#/dashboard?x=y&y=z'; - expect(getUrlVars(url)).toEqual({ - x: 'y', - y: 'z', - }); - url = 'http://notDashboardUrl'; - expect(getUrlVars(url)).toEqual({}); - url = 'http://localhost:5601/app/kibana#/dashboard/777182'; - expect(getUrlVars(url)).toEqual({}); - }); - - it('getDashboardUrlWithQueryParams', () => { - const queryParams = { - _g: '(refreshInterval:(pause:!t,value:0),time:(from:now-45m,to:now))', - _a: "(description:'',filters:!()", - }; - let url = - "http://localhost:5601/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!()"; - expect(getDashboardUrlWithQueryParams(url, queryParams)).toEqual( - "http://localhost:5601/app/kibana#/dashboard?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-45m,to:now))" - ); - - url = - "http://localhost:5601/app/kibana#/dashboard/625357282?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))"; - expect(getDashboardUrlWithQueryParams(url, queryParams)).toEqual( - "http://localhost:5601/app/kibana#/dashboard/625357282?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-45m,to:now))" - ); - - url = 'http://localhost:5601/app/kibana#/dashboard/777182'; - expect(getDashboardUrlWithQueryParams(url, queryParams)).toEqual( - "http://localhost:5601/app/kibana#/dashboard/777182?_a=(description:'',filters:!()&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-45m,to:now))" - ); - }); -}); diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.ts b/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.ts deleted file mode 100644 index 9a9cd8b54919054..000000000000000 --- a/x-pack/legacy/plugins/lens/public/app_plugin/url_helper.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import { DashboardConstants } from '../../../../../../src/legacy/core_plugins/kibana/public/dashboard'; - -const EMPTY_DASHBOARD_PATTERN = /(.*#\/dashboard\?)(.*)/; -const DASHBOARD_WITH_ID_PATTERN = /(.*#\/dashboard\/.*\?)(.*)/; - -/** * - * Returns base path from dashboard url - * eg. - * input: http://localhost:5601/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),panels:!(),query:(language:kuery,query:''),timeRestore:!f,title:'',viewMode:edit) - * output: http://localhost:5601/lib/app/kibana# - * @param url - */ -export function getKibanaBasePathFromDashboardUrl(url: string | undefined): string | null { - if (!url) { - return null; - } - let regex = RegExp(/(.*)(\/dashboard\?)/).exec(url); - if (regex) { - return regex[1]; - } - regex = RegExp(/(.*)(\/dashboard)/).exec(url); - if (regex) { - return regex[1]; - } - return null; -} - -/** - * Returns dashboard url with given query params. If query params already exist in the url, they will be replaced - * eg. - * input: http://localhost:5601/lib/app/kibana#/dashboard, {_a: {...}, _g: {...}} - * output: http://localhost:5601/lib/app/kibana#/dashboard??_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now))&_a=(description:'',filters:!(),fullScreenMode:!f,options:(hidePanelTitles:!f,useMargins:!t),panels:!(),query:(language:kuery,query:''),timeRestore:!f,title:'',viewMode:edit) - * @param absoluteUrl dashboard absolute url - * @param urlParams query params to append to the url - */ -export function getDashboardUrlWithQueryParams( - absoluteUrl: string, - urlParams: Record -): string { - let dashboardUrl = getUrlWithoutQueryParams(absoluteUrl); - if (!dashboardUrl) { - return absoluteUrl; - } - dashboardUrl += '?'; - const keys = Object.keys(urlParams).sort(); - keys.forEach((key, index) => { - dashboardUrl += `${key}=${urlParams[key]}`; - if (index !== keys.length - 1) { - dashboardUrl += '&'; - } - }); - return dashboardUrl; -} - -export function getUrlVars(url: string): Record { - const vars: Record = {}; - // @ts-ignore - url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(_, key, value) { - vars[key] = value; - }); - return vars; -} - -/** * - * Returns dashboard URL with added embeddableType and embeddableId query params - * eg. - * input: url: http://localhost:5601/lib/app/kibana#/dashboard?_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)), embeddableId: 12345, embeddableType: 'lens' - * output: http://localhost:5601/lib/app/kibana#dashboard?addEmbeddableType=lens&addEmbeddableId=12345&_g=(refreshInterval:(pause:!t,value:0),time:(from:now-15m,to:now)) - * @param url dasbhoard absolute url - * @param embeddableId id of the saved visualization - * @param embeddableType 'lens' or 'visualization' - */ -export function addEmbeddableToDashboardUrl( - url: string | undefined, - embeddableId: string, - embeddableType: 'lens' -): string | null { - if (!url) { - return null; - } - let regex = RegExp(EMPTY_DASHBOARD_PATTERN).exec(url); // check for empty dashboard first - regex = regex || RegExp(DASHBOARD_WITH_ID_PATTERN).exec(url); // check for dashboard with id if not empty - if (!regex) { - return null; - } - const base = regex[1]; - const dashboardState = regex[2]; - return `${base}${DashboardConstants.ADD_EMBEDDABLE_TYPE}=${embeddableType}&${DashboardConstants.ADD_EMBEDDABLE_ID}=${embeddableId}&${dashboardState}`; -} - -/** - * Returns the portion of the URL without query params - * eg. - * input: http://localhost:5601/lib/app/kibana#/dashboard?param1=x¶m2=y¶m3=z - * output:http://localhost:5601/lib/app/kibana#/dashboard - * input: http://localhost:5601/lib/app/kibana#/dashboard/39292992?param1=x¶m2=y¶m3=z - * output: http://localhost:5601/lib/app/kibana#/dashboard/39292992 - * @param url dashboard absolute url - */ -function getUrlWithoutQueryParams(url: string | undefined): string | null { - if (!url) { - return null; - } - return url.split('?')[0]; -}