diff --git a/test/functional/services/dashboard/panel_actions.ts b/test/functional/services/dashboard/panel_actions.ts index 0f5d6ea74a6b6..bc21a62b9df79 100644 --- a/test/functional/services/dashboard/panel_actions.ts +++ b/test/functional/services/dashboard/panel_actions.ts @@ -70,6 +70,17 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }: Ft await PageObjects.common.waitForTopNavToBeVisible(); } + async editPanelByTitle(title?: string) { + log.debug(`editPanelByTitle(${title})`); + if (title) { + const panelOptions = await this.getPanelHeading(title); + await this.openContextMenu(panelOptions); + } else { + await this.openContextMenu(); + } + await testSubjects.clickWhenNotDisabled(EDIT_PANEL_DATA_TEST_SUBJ); + } + async clickExpandPanelToggle() { await testSubjects.click(TOGGLE_EXPAND_PANEL_DATA_TEST_SUBJ); } diff --git a/x-pack/plugins/maps/public/kibana_services.d.ts b/x-pack/plugins/maps/public/kibana_services.d.ts index 2e6911e89fa0a..2b28e1a8c7dbb 100644 --- a/x-pack/plugins/maps/public/kibana_services.d.ts +++ b/x-pack/plugins/maps/public/kibana_services.d.ts @@ -6,8 +6,10 @@ import { DataPublicPluginStart } from 'src/plugins/data/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { IndexPatternsService } from 'src/plugins/data/public/index_patterns'; +import { NavigateToAppOptions } from 'kibana/public'; import { MapsConfigType } from '../config'; import { MapsLegacyConfigType } from '../../../../src/plugins/maps_legacy/public'; +import { EmbeddableStart } from '../../../../src/plugins/embeddable/public'; export function getLicenseId(): any; export function getInspector(): any; @@ -77,3 +79,12 @@ export function setKibanaCommonConfig(config: MapsLegacyConfigType): void; export function setMapAppConfig(config: MapsConfigType): void; export function setKibanaVersion(version: string): void; export function setIsGoldPlus(isGoldPlus: boolean): void; +export function setEmbeddableService(embeddableService: EmbeddableStart): void; +export function getEmbeddableService(): EmbeddableStart; +export function setNavigateToApp( + navigateToApp: (appId: string, options?: NavigateToAppOptions | undefined) => Promise +): void; +export const navigateToApp: ( + appId: string, + options?: NavigateToAppOptions | undefined +) => Promise; diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index 89d578f27b118..9b035a87a3b37 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -177,3 +177,16 @@ export const setIsGoldPlus = (igp) => { export const getIsGoldPlus = () => { return isGoldPlus; }; + +let embeddableService; +export const setEmbeddableService = (_embeddableService) => { + embeddableService = _embeddableService; +}; +export const getEmbeddableService = () => { + return embeddableService; +}; + +export let navigateToApp; +export function setNavigateToApp(_navigateToApp) { + navigateToApp = _navigateToApp; +} diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 8428a31d8b408..c374d3cb59b34 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -41,6 +41,8 @@ import { setUiActions, setUiSettings, setVisualizations, + setEmbeddableService, + setNavigateToApp, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; // @ts-ignore @@ -113,6 +115,8 @@ export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { setUiActions(plugins.uiActions); setNavigation(plugins.navigation); setCoreI18n(core.i18n); + setEmbeddableService(plugins.embeddable); + setNavigateToApp(core.application.navigateToApp); }; /** diff --git a/x-pack/plugins/maps/public/routing/bootstrap/services/saved_gis_map.ts b/x-pack/plugins/maps/public/routing/bootstrap/services/saved_gis_map.ts index 4b474424bcdab..6f8e7777f671b 100644 --- a/x-pack/plugins/maps/public/routing/bootstrap/services/saved_gis_map.ts +++ b/x-pack/plugins/maps/public/routing/bootstrap/services/saved_gis_map.ts @@ -36,6 +36,7 @@ export interface ISavedGisMap extends SavedObject { layerListJSON?: string; mapStateJSON?: string; uiStateJSON?: string; + description?: string; getLayerList(): LayerDescriptor[]; syncWithStore(): void; } diff --git a/x-pack/plugins/maps/public/routing/maps_router.js b/x-pack/plugins/maps/public/routing/maps_router.js index 9992bd7a92ab1..9b7900d032f5a 100644 --- a/x-pack/plugins/maps/public/routing/maps_router.js +++ b/x-pack/plugins/maps/public/routing/maps_router.js @@ -7,7 +7,7 @@ import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { Router, Switch, Route, Redirect } from 'react-router-dom'; -import { getCoreI18n, getToasts } from '../kibana_services'; +import { getCoreI18n, getToasts, getEmbeddableService } from '../kibana_services'; import { createKbnUrlStateStorage, withNotifyOnErrors, @@ -39,6 +39,11 @@ const App = ({ history, appBasePath, onAppLeave }) => { const store = getStore(); const I18nContext = getCoreI18n().Context; + const stateTransfer = getEmbeddableService()?.getStateTransfer(history); + + const { originatingApp } = + stateTransfer?.getIncomingEditorState({ keysToRemoveAfterFetch: ['originatingApp'] }) || {}; + return ( @@ -50,13 +55,21 @@ const App = ({ history, appBasePath, onAppLeave }) => { )} /> } + render={() => ( + + )} /> // Redirect other routes to list, or if hash-containing, their non-hash equivalents { - dispatch(setSelectedLayer(null)); - dispatch(updateFlyout(FLYOUT_STATE.NONE)); - dispatch(removePreviewLayers()); - }, enableFullScreen: () => dispatch(enableFullScreen()), openMapSettings: () => dispatch(openMapSettings()), }; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js index 3eea5b00d324e..eebbb17582821 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/load_map_and_render.js @@ -56,6 +56,13 @@ export const LoadMapAndRender = class extends React.Component { return ; } - return savedMap ? : null; + return savedMap ? ( + + ) : null; } }; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js index 91d00990772f4..23625b4591db7 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/maps_app_view.js @@ -51,6 +51,8 @@ export class MapsAppView extends React.Component { initialized: false, savedQuery: '', initialLayerListConfig: null, + // tracking originatingApp in state so the connection can be broken by users + originatingApp: props.originatingApp, }; } @@ -311,11 +313,15 @@ export class MapsAppView extends React.Component { savedMap: this.props.savedMap, isOpenSettingsDisabled: this.props.isOpenSettingsDisabled, isSaveDisabled: this.props.isSaveDisabled, - closeFlyout: this.props.closeFlyout, enableFullScreen: this.props.enableFullScreen, openMapSettings: this.props.openMapSettings, inspectorAdapters: this.props.inspectorAdapters, setBreadcrumbs: this._setBreadcrumbs, + stateTransfer: this.props.stateTransfer, + originatingApp: this.state.originatingApp, + cutOriginatingAppConnection: () => { + this.setState({ originatingApp: undefined }); + }, }); const { TopNavMenu } = getNavigation().ui; diff --git a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx index 46d662b28a82f..8a4d8ae555895 100644 --- a/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx +++ b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx @@ -7,16 +7,16 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { Adapters } from 'src/plugins/inspector/public'; -import { SavedObjectSaveOpts } from 'src/plugins/saved_objects/public'; import { getCoreChrome, getMapsCapabilities, getInspector, getToasts, getCoreI18n, + navigateToApp, } from '../../../kibana_services'; import { - SavedObjectSaveModal, + SavedObjectSaveModalOrigin, OnSaveProps, showSaveModal, } from '../../../../../../../src/plugins/saved_objects/public'; @@ -24,47 +24,197 @@ import { MAP_SAVED_OBJECT_TYPE } from '../../../../common/constants'; // @ts-expect-error import { goToSpecifiedPath } from '../../maps_router'; import { ISavedGisMap } from '../../bootstrap/services/saved_gis_map'; +import { EmbeddableStateTransfer } from '../../../../../../../src/plugins/embeddable/public'; export function getTopNavConfig({ savedMap, isOpenSettingsDisabled, isSaveDisabled, - closeFlyout, enableFullScreen, openMapSettings, inspectorAdapters, setBreadcrumbs, + stateTransfer, + originatingApp, + cutOriginatingAppConnection, }: { savedMap: ISavedGisMap; isOpenSettingsDisabled: boolean; isSaveDisabled: boolean; - closeFlyout: () => void; enableFullScreen: () => void; openMapSettings: () => void; inspectorAdapters: Adapters; setBreadcrumbs: () => void; + stateTransfer?: EmbeddableStateTransfer; + originatingApp?: string; + cutOriginatingAppConnection: () => void; }) { - return [ + const topNavConfigs = []; + const isNewMap = !savedMap.id; + const hasWritePermissions = getMapsCapabilities().save; + const hasSaveAndReturnConfig = hasWritePermissions && !isNewMap && originatingApp; + + async function onSave({ + newDescription, + newTitle, + newCopyOnSave, + isTitleDuplicateConfirmed, + onTitleDuplicate, + returnToOrigin, + }: OnSaveProps & { returnToOrigin: boolean }) { + const prevTitle = savedMap.title; + const prevDescription = savedMap.description; + savedMap.title = newTitle; + savedMap.description = newDescription; + savedMap.copyOnSave = newCopyOnSave; + + let id; + try { + savedMap.syncWithStore(); + id = await savedMap.save({ + confirmOverwrite: false, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }); + // id not returned when save fails because of duplicate title check. + // return and let user confirm duplicate title. + if (!id) { + return {}; + } + } catch (err) { + getToasts().addDanger({ + title: i18n.translate('xpack.maps.topNav.saveErrorMessage', { + defaultMessage: `Error saving '{title}'`, + values: { title: savedMap.title }, + }), + text: err.message, + 'data-test-subj': 'saveMapError', + }); + // If the save wasn't successful, put the original values back. + savedMap.title = prevTitle; + savedMap.description = prevDescription; + return { error: err }; + } + + getToasts().addSuccess({ + title: i18n.translate('xpack.maps.topNav.saveSuccessMessage', { + defaultMessage: `Saved '{title}'`, + values: { title: savedMap.title }, + }), + 'data-test-subj': 'saveMapSuccess', + }); + + getCoreChrome().docTitle.change(savedMap.title); + setBreadcrumbs(); + goToSpecifiedPath(`/map/${id}${window.location.hash}`); + + const newlyCreated = newCopyOnSave || isNewMap; + if (newlyCreated && !returnToOrigin) { + cutOriginatingAppConnection(); + } else if (!!originatingApp && returnToOrigin) { + if (newlyCreated && stateTransfer) { + stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { + state: { id, type: MAP_SAVED_OBJECT_TYPE }, + }); + } else { + navigateToApp(originatingApp); + } + } + + return { id }; + } + + if (hasSaveAndReturnConfig) { + topNavConfigs.push({ + id: 'saveAndReturn', + label: i18n.translate('xpack.maps.topNav.saveAndReturnButtonLabel', { + defaultMessage: 'Save and return', + }), + emphasize: true, + iconType: 'check', + run: () => { + onSave({ + newTitle: savedMap.title ? savedMap.title : '', + newDescription: savedMap.description ? savedMap.description : '', + newCopyOnSave: false, + isTitleDuplicateConfirmed: false, + returnToOrigin: true, + onTitleDuplicate: () => {}, + }); + }, + testId: 'mapSaveAndReturnButton', + }); + } + + if (hasWritePermissions) { + topNavConfigs.push({ + id: 'save', + label: hasSaveAndReturnConfig + ? i18n.translate('xpack.maps.topNav.saveAsButtonLabel', { + defaultMessage: 'Save as', + }) + : i18n.translate('xpack.maps.topNav.saveMapButtonLabel', { + defaultMessage: `save`, + }), + description: i18n.translate('xpack.maps.topNav.saveMapDescription', { + defaultMessage: `Save map`, + }), + emphasize: !hasSaveAndReturnConfig, + testId: 'mapSaveButton', + disableButton() { + return isSaveDisabled; + }, + tooltip() { + if (isSaveDisabled) { + return i18n.translate('xpack.maps.topNav.saveMapDisabledButtonTooltip', { + defaultMessage: 'Confirm or Cancel your layer changes before saving', + }); + } + }, + run: () => { + const saveModal = ( + {}} + documentInfo={{ + description: savedMap.description, + id: savedMap.id, + title: savedMap.title, + }} + objectType={i18n.translate('xpack.maps.topNav.saveModalType', { + defaultMessage: 'map', + })} + /> + ); + showSaveModal(saveModal, getCoreI18n().Context); + }, + }); + } + + topNavConfigs.push( { - id: 'full-screen', - label: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', { - defaultMessage: `full screen`, + id: 'mapSettings', + label: i18n.translate('xpack.maps.topNav.openSettingsButtonLabel', { + defaultMessage: `Map settings`, }), - description: i18n.translate('xpack.maps.mapController.fullScreenDescription', { - defaultMessage: `full screen`, + description: i18n.translate('xpack.maps.topNav.openSettingsDescription', { + defaultMessage: `Open map settings`, }), - testId: 'mapsFullScreenMode', + testId: 'openSettingsButton', + disableButton() { + return isOpenSettingsDisabled; + }, run() { - getCoreChrome().setIsVisible(false); - enableFullScreen(); + openMapSettings(); }, }, { id: 'inspect', - label: i18n.translate('xpack.maps.mapController.openInspectorButtonLabel', { + label: i18n.translate('xpack.maps.topNav.openInspectorButtonLabel', { defaultMessage: `inspect`, }), - description: i18n.translate('xpack.maps.mapController.openInspectorDescription', { + description: i18n.translate('xpack.maps.topNav.openInspectorDescription', { defaultMessage: `Open Inspector`, }), testId: 'openInspectorButton', @@ -73,122 +223,20 @@ export function getTopNavConfig({ }, }, { - id: 'mapSettings', - label: i18n.translate('xpack.maps.mapController.openSettingsButtonLabel', { - defaultMessage: `Map settings`, + id: 'full-screen', + label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { + defaultMessage: `full screen`, }), - description: i18n.translate('xpack.maps.mapController.openSettingsDescription', { - defaultMessage: `Open map settings`, + description: i18n.translate('xpack.maps.topNav.fullScreenDescription', { + defaultMessage: `full screen`, }), - testId: 'openSettingsButton', - disableButton() { - return isOpenSettingsDisabled; - }, + testId: 'mapsFullScreenMode', run() { - openMapSettings(); + getCoreChrome().setIsVisible(false); + enableFullScreen(); }, - }, - ...(getMapsCapabilities().save - ? [ - { - id: 'save', - label: i18n.translate('xpack.maps.mapController.saveMapButtonLabel', { - defaultMessage: `save`, - }), - description: i18n.translate('xpack.maps.mapController.saveMapDescription', { - defaultMessage: `Save map`, - }), - testId: 'mapSaveButton', - disableButton() { - return isSaveDisabled; - }, - tooltip() { - if (isSaveDisabled) { - return i18n.translate('xpack.maps.mapController.saveMapDisabledButtonTooltip', { - defaultMessage: 'Save or Cancel your layer changes before saving', - }); - } - }, - run: async () => { - const onSave = ({ - newTitle, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }: OnSaveProps) => { - const currentTitle = savedMap.title; - savedMap.title = newTitle; - savedMap.copyOnSave = newCopyOnSave; - const saveOptions: SavedObjectSaveOpts = { - confirmOverwrite: false, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }; - return doSave(savedMap, saveOptions, closeFlyout, setBreadcrumbs).then( - (response) => { - // If the save wasn't successful, put the original values back. - if (!response.id || response.error) { - savedMap.title = currentTitle; - } - return response; - } - ); - }; + } + ); - const saveModal = ( - {}} - title={savedMap.title} - showCopyOnSave={!!savedMap.id} - objectType={MAP_SAVED_OBJECT_TYPE} - showDescription={false} - /> - ); - showSaveModal(saveModal, getCoreI18n().Context); - }, - }, - ] - : []), - ]; -} - -async function doSave( - savedMap: ISavedGisMap, - saveOptions: SavedObjectSaveOpts, - closeFlyout: () => void, - setBreadcrumbs: () => void -) { - closeFlyout(); - savedMap.syncWithStore(); - let id; - - try { - id = await savedMap.save(saveOptions); - getCoreChrome().docTitle.change(savedMap.title); - } catch (err) { - getToasts().addDanger({ - title: i18n.translate('xpack.maps.mapController.saveErrorMessage', { - defaultMessage: `Error on saving '{title}'`, - values: { title: savedMap.title }, - }), - text: err.message, - 'data-test-subj': 'saveMapError', - }); - return { error: err }; - } - - if (id) { - goToSpecifiedPath(`/map/${id}${window.location.hash}`); - setBreadcrumbs(); - - getToasts().addSuccess({ - title: i18n.translate('xpack.maps.mapController.saveSuccessMessage', { - defaultMessage: `Saved '{title}'`, - values: { title: savedMap.title }, - }), - 'data-test-subj': 'saveMapSuccess', - }); - } - return { id }; + return topNavConfigs; } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 10d6e8a16fe93..dd32d7de796c1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10424,18 +10424,7 @@ "xpack.maps.layerWizardSelect.solutionsCategoryLabel": "ソリューション", "xpack.maps.loadMap.errorAttemptingToLoadSavedMap": "マップを読み込めません", "xpack.maps.map.initializeErrorTitle": "マップを初期化できません", - "xpack.maps.mapController.fullScreenButtonLabel": "全画面", - "xpack.maps.mapController.fullScreenDescription": "全画面", "xpack.maps.mapController.mapsBreadcrumbLabel": "マップ", - "xpack.maps.mapController.openInspectorButtonLabel": "検査", - "xpack.maps.mapController.openInspectorDescription": "インスペクターを開きます", - "xpack.maps.mapController.openSettingsButtonLabel": "マップ設定", - "xpack.maps.mapController.openSettingsDescription": "マップ設定を開く", - "xpack.maps.mapController.saveErrorMessage": "「{title}」の保存中にエラーが発生しました", - "xpack.maps.mapController.saveMapButtonLabel": "保存", - "xpack.maps.mapController.saveMapDescription": "マップを保存", - "xpack.maps.mapController.saveMapDisabledButtonTooltip": "保存する前に、レイヤーの変更を保存するか、キャンセルしてください", - "xpack.maps.mapController.saveSuccessMessage": "「{title}」が保存されました", "xpack.maps.mapEmbeddableFactory.invalidLayerList": "不正な形式のレイヤーリストによりマップを読み込めません", "xpack.maps.mapEmbeddableFactory.invalidSavedObject": "不正な形式の保存済みオブジェクトによりマップを読み込めません", "xpack.maps.mapListing.advancedSettingsLinkText": "高度な設定", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 378dd3817008d..28984e1da1dcb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10426,18 +10426,7 @@ "xpack.maps.layerWizardSelect.solutionsCategoryLabel": "解决方案", "xpack.maps.loadMap.errorAttemptingToLoadSavedMap": "无法加载地图", "xpack.maps.map.initializeErrorTitle": "无法初始化地图", - "xpack.maps.mapController.fullScreenButtonLabel": "全屏", - "xpack.maps.mapController.fullScreenDescription": "全屏", "xpack.maps.mapController.mapsBreadcrumbLabel": "Maps", - "xpack.maps.mapController.openInspectorButtonLabel": "检查", - "xpack.maps.mapController.openInspectorDescription": "打开检查器", - "xpack.maps.mapController.openSettingsButtonLabel": "地图设置", - "xpack.maps.mapController.openSettingsDescription": "打开地图设置", - "xpack.maps.mapController.saveErrorMessage": "保存 “{title}” 时出错", - "xpack.maps.mapController.saveMapButtonLabel": "保存", - "xpack.maps.mapController.saveMapDescription": "保存地图", - "xpack.maps.mapController.saveMapDisabledButtonTooltip": "保存或在保存之前取消您的图层更改", - "xpack.maps.mapController.saveSuccessMessage": "已保存“{title}”", "xpack.maps.mapEmbeddableFactory.invalidLayerList": "无法加载地图,图层列表格式不正确", "xpack.maps.mapEmbeddableFactory.invalidSavedObject": "无法加载地图,已保存对象格式错误", "xpack.maps.mapListing.advancedSettingsLinkText": "高级设置", diff --git a/x-pack/test/functional/apps/maps/embeddable/index.js b/x-pack/test/functional/apps/maps/embeddable/index.js index bb3dbb0ea1ef2..81d24f73838e7 100644 --- a/x-pack/test/functional/apps/maps/embeddable/index.js +++ b/x-pack/test/functional/apps/maps/embeddable/index.js @@ -6,6 +6,7 @@ export default function ({ loadTestFile }) { describe('embeddable', function () { + loadTestFile(require.resolve('./save_and_return')); loadTestFile(require.resolve('./dashboard')); loadTestFile(require.resolve('./embeddable_state')); loadTestFile(require.resolve('./tooltip_filter_actions')); diff --git a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js new file mode 100644 index 0000000000000..4aa44799db1f4 --- /dev/null +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -0,0 +1,88 @@ +/* + * 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 expect from '@kbn/expect'; + +export default function ({ getPageObjects, getService }) { + const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'maps', 'visualize']); + const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardPanelActions = getService('dashboardPanelActions'); + const dashboardVisualizations = getService('dashboardVisualizations'); + const testSubjects = getService('testSubjects'); + + describe('save and return work flow', () => { + describe('new map', () => { + beforeEach(async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.clickNewDashboard(); + await dashboardAddPanel.clickCreateNewLink(); + await await dashboardVisualizations.ensureNewVisualizationDialogIsShowing(); + await PageObjects.visualize.clickMapsApp(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.maps.waitForLayersToLoad(); + }); + + describe('save', () => { + it('should return to dashboard and add new panel', async () => { + await PageObjects.maps.saveMap('map created from dashboard save and return'); + await PageObjects.dashboard.waitForRenderComplete(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.equal(1); + }); + }); + + describe('save and uncheck return to origin switch', () => { + it('should cut the originator and stay in maps application', async () => { + await PageObjects.maps.saveMap( + 'map created from dashboard save and return with originator app cut', + true + ); + await PageObjects.maps.waitForLayersToLoad(); + await testSubjects.missingOrFail('mapSaveAndReturnButton'); + await testSubjects.existOrFail('mapSaveButton'); + }); + }); + }); + + describe('edit existing map', () => { + beforeEach(async () => { + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.loadSavedDashboard('map embeddable example'); + await PageObjects.dashboard.switchToEditMode(); + await dashboardPanelActions.editPanelByTitle('join example'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.maps.waitForLayersToLoad(); + }); + + describe('save and return', () => { + it('should return to dashboard', async () => { + await PageObjects.maps.clickSaveAndReturnButton(); + await PageObjects.dashboard.waitForRenderComplete(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.equal(2); + }); + }); + + describe('save as', () => { + it('should return to dashboard and add new panel', async () => { + await PageObjects.maps.saveMap('Clone of map embeddable example'); + await PageObjects.dashboard.waitForRenderComplete(); + const panelCount = await PageObjects.dashboard.getPanelCount(); + expect(panelCount).to.equal(3); + }); + }); + + describe('save as and uncheck return to origin switch', () => { + it('should cut the originator and stay in maps application', async () => { + await PageObjects.maps.saveMap('Clone 2 of map embeddable example', true); + await PageObjects.maps.waitForLayersToLoad(); + await testSubjects.missingOrFail('mapSaveAndReturnButton'); + await testSubjects.existOrFail('mapSaveButton'); + }); + }); + }); + }); +} diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index 99ad223b39017..613434d5375a7 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -139,12 +139,25 @@ export function GisPageProvider({ getService, getPageObjects }) { await renderable.waitForRender(); } - async saveMap(name) { + async saveMap(name, uncheckReturnToOriginModeSwitch = false) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', name); + if (uncheckReturnToOriginModeSwitch) { + const redirectToOriginCheckboxExists = await testSubjects.exists( + 'returnToOriginModeSwitch' + ); + if (!redirectToOriginCheckboxExists) { + throw new Error('Unable to uncheck "returnToOriginModeSwitch", it does not exist.'); + } + await testSubjects.setEuiSwitch('returnToOriginModeSwitch', 'uncheck'); + } await testSubjects.clickWhenNotDisabled('confirmSaveSavedObjectButton'); } + async clickSaveAndReturnButton() { + await testSubjects.click('mapSaveAndReturnButton'); + } + async expectMissingSaveButton() { await testSubjects.missingOrFail('mapSaveButton'); }