From a694c3160f05ce1543395cdcf395927dd138062f Mon Sep 17 00:00:00 2001 From: Jusheng Huang <117657272+viajes7@users.noreply.github.com> Date: Thu, 3 Oct 2024 08:24:46 +0800 Subject: [PATCH] [Dashboard] Fix share dashboard iframe embed code incorrectly (#194366) ## Summary Fixes [#192980](https://github.com/elastic/kibana/issues/193447) Maybe related pr: #179037 After fix it, having an URL that is like this: ``` ?embed=true&_g=(refreshInterval%3A(pause%3A!t%2Cvalue%3A60000)%2Ctime%3A(from%3Anow-15m%2Cto%3Anow))&hide-filter-bar=true ``` **Screenshot** image --------- Co-authored-by: Elastic Machine Co-authored-by: Tim Sullivan (cherry picked from commit e4ff3bb44874f77a63c24de998fde2f6d7ac9404) # Conflicts: # src/plugins/share/public/components/share_tabs.test.tsx # src/plugins/share/public/services/share_menu_manager.tsx --- .../share/public/components/context/index.tsx | 1 - .../tabs/embed/embed_content.test.tsx | 56 +++++++++++++++++++ .../components/tabs/embed/embed_content.tsx | 22 +++++--- .../public/components/tabs/embed/index.tsx | 11 +--- .../public/services/share_menu_manager.tsx | 1 - 5 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 src/plugins/share/public/components/tabs/embed/embed_content.test.tsx diff --git a/src/plugins/share/public/components/context/index.tsx b/src/plugins/share/public/components/context/index.tsx index 46cdea37f002f..121604c2a54f1 100644 --- a/src/plugins/share/public/components/context/index.tsx +++ b/src/plugins/share/public/components/context/index.tsx @@ -28,7 +28,6 @@ export interface IShareContext extends ShareContext { anonymousAccess?: AnonymousAccessServiceContract; urlService: BrowserUrlService; snapshotShareWarning?: string; - isEmbedded: boolean; theme: ThemeServiceSetup; i18n: I18nStart; publicAPIEnabled?: boolean; diff --git a/src/plugins/share/public/components/tabs/embed/embed_content.test.tsx b/src/plugins/share/public/components/tabs/embed/embed_content.test.tsx new file mode 100644 index 0000000000000..be3d8c941b8ea --- /dev/null +++ b/src/plugins/share/public/components/tabs/embed/embed_content.test.tsx @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { EmbedContent } from './embed_content'; +import React from 'react'; +import { ReactWrapper } from 'enzyme'; + +describe('Share modal embed content tab', () => { + describe('share url embedded', () => { + let component: ReactWrapper; + + beforeEach(() => { + component = mountWithIntl( + jest.fn()} + shareableUrl="/home#/" + /> + ); + }); + + it('works for simple url', async () => { + component.setProps({ shareableUrl: 'http://localhost:5601/app/home#/' }); + component.update(); + + const shareUrl = component + .find('button[data-test-subj="copyEmbedUrlButton"]') + .prop('data-share-url'); + expect(shareUrl).toBe( + '' + ); + }); + + it('works if the url has a query string', async () => { + component.setProps({ + shareableUrl: + 'http://localhost:5601/app/dashboards#/create?_g=(refreshInterval%3A(pause%3A!t%2Cvalue%3A60000)%2Ctime%3A(from%3Anow-15m%2Cto%3Anow))', + }); + component.update(); + + const shareUrl = component + .find('button[data-test-subj="copyEmbedUrlButton"]') + .prop('data-share-url'); + expect(shareUrl).toBe( + '' + ); + }); + }); +}); diff --git a/src/plugins/share/public/components/tabs/embed/embed_content.tsx b/src/plugins/share/public/components/tabs/embed/embed_content.tsx index fd98037c3a00b..6f7837ea8109d 100644 --- a/src/plugins/share/public/components/tabs/embed/embed_content.tsx +++ b/src/plugins/share/public/components/tabs/embed/embed_content.tsx @@ -29,7 +29,6 @@ type EmbedProps = Pick< | 'shareableUrlLocatorParams' | 'shareableUrlForSavedObject' | 'shareableUrl' - | 'isEmbedded' | 'embedUrlParamExtensions' | 'objectType' > & { @@ -51,7 +50,6 @@ export const EmbedContent = ({ embedUrlParamExtensions: urlParamExtensions, shareableUrlForSavedObject, shareableUrl, - isEmbedded, objectType, setIsNotSaved, }: EmbedProps) => { @@ -68,6 +66,17 @@ export const EmbedContent = ({ if (objectType !== 'dashboard') setIsNotSaved(); }, [url, setIsNotSaved, objectType]); + const makeUrlEmbeddable = useCallback((tempUrl: string): string => { + const embedParam = '?embed=true'; + const urlHasQueryString = tempUrl.indexOf('?') !== -1; + + if (urlHasQueryString) { + return tempUrl.replace('?', `${embedParam}&`); + } + + return `${tempUrl}${embedParam}`; + }, []); + const getUrlParamExtensions = useCallback( (tempUrl: string): string => { return urlParams @@ -89,10 +98,11 @@ export const EmbedContent = ({ const updateUrlParams = useCallback( (tempUrl: string) => { + tempUrl = makeUrlEmbeddable(tempUrl); tempUrl = urlParams ? getUrlParamExtensions(tempUrl) : tempUrl; return tempUrl; }, - [getUrlParamExtensions, urlParams] + [makeUrlEmbeddable, getUrlParamExtensions, urlParams] ); const getSnapshotUrl = useCallback( @@ -179,16 +189,14 @@ export const EmbedContent = ({ tempUrl = addUrlAnonymousAccessParameters(tempUrl!); } - if (isEmbedded) { - tempUrl = makeIframeTag(tempUrl!); - } + tempUrl = makeIframeTag(tempUrl!); + setUrl(tempUrl!); }, [ addUrlAnonymousAccessParameters, exportUrlAs, getSavedObjectUrl, getSnapshotUrl, - isEmbedded, shortUrlCache, useShortUrl, ]); diff --git a/src/plugins/share/public/components/tabs/embed/index.tsx b/src/plugins/share/public/components/tabs/embed/index.tsx index 1d626fad6fe7a..0a9177dac7af2 100644 --- a/src/plugins/share/public/components/tabs/embed/index.tsx +++ b/src/plugins/share/public/components/tabs/embed/index.tsx @@ -37,14 +37,8 @@ const embedTabReducer: IEmbedTab['reducer'] = (state = { url: '', isNotSaved: fa }; const EmbedTabContent: NonNullable = ({ state, dispatch }) => { - const { - embedUrlParamExtensions, - shareableUrlForSavedObject, - shareableUrl, - isEmbedded, - objectType, - isDirty, - } = useShareTabsContext()!; + const { embedUrlParamExtensions, shareableUrlForSavedObject, shareableUrl, objectType, isDirty } = + useShareTabsContext()!; const setIsNotSaved = useCallback(() => { dispatch({ @@ -59,7 +53,6 @@ const EmbedTabContent: NonNullable = ({ state, dispatch }) embedUrlParamExtensions, shareableUrlForSavedObject, shareableUrl, - isEmbedded, objectType, isNotSaved: state?.isNotSaved, setIsNotSaved, diff --git a/src/plugins/share/public/services/share_menu_manager.tsx b/src/plugins/share/public/services/share_menu_manager.tsx index 0f58e875cfcd5..d84be41f6737f 100644 --- a/src/plugins/share/public/services/share_menu_manager.tsx +++ b/src/plugins/share/public/services/share_menu_manager.tsx @@ -131,7 +131,6 @@ export class ShareMenuManager { snapshotShareWarning, disabledShareUrl, isDirty, - isEmbedded: allowEmbed, shareMenuItems: menuItems, toasts, onClose: () => {