From 83284916499e11dcec30268158148de2b50595a7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 3 Aug 2020 08:18:55 -0600 Subject: [PATCH 01/11] pass originatingApp into App --- x-pack/plugins/maps/public/kibana_services.js | 8 ++++++++ x-pack/plugins/maps/public/plugin.ts | 2 ++ x-pack/plugins/maps/public/routing/maps_router.js | 6 +++++- .../public/routing/routes/maps_app/load_map_and_render.js | 8 +++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index 89d578f27b118..89d20ae9878e9 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -177,3 +177,11 @@ export const setIsGoldPlus = (igp) => { export const getIsGoldPlus = () => { return isGoldPlus; }; + +let _embeddableService; +export const setEmbeddableService = (embeddableService) => { + _embeddableService = embeddableService; +}; +export const getEmbeddableService = () => { + return _embeddableService; +}; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 8428a31d8b408..f9310224980e1 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -41,6 +41,7 @@ import { setUiActions, setUiSettings, setVisualizations, + setEmbeddableService, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; // @ts-ignore @@ -113,6 +114,7 @@ export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { setUiActions(plugins.uiActions); setNavigation(plugins.navigation); setCoreI18n(core.i18n); + setEmbeddableService(plugins.embeddable); }; /** diff --git a/x-pack/plugins/maps/public/routing/maps_router.js b/x-pack/plugins/maps/public/routing/maps_router.js index 30b2137399c1e..7060f56e84293 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 } from '../kibana_services'; +import { getCoreI18n, getEmbeddableService } from '../kibana_services'; import { createKbnUrlStateStorage } from '../../../../../src/plugins/kibana_utils/public'; import { getStore } from './store_operations'; import { Provider } from 'react-redux'; @@ -32,6 +32,9 @@ const App = ({ history, appBasePath, onAppLeave }) => { const store = getStore(); const I18nContext = getCoreI18n().Context; + const { originatingApp } = + getEmbeddableService()?.getStateTransfer(history)?.getIncomingEditorState() || {}; + return ( @@ -43,6 +46,7 @@ const App = ({ history, appBasePath, onAppLeave }) => { )} /> 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..c13a294fdd3c9 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,12 @@ export const LoadMapAndRender = class extends React.Component { return ; } - return savedMap ? : null; + return savedMap ? ( + + ) : null; } }; From 00a4f2ba050b3f1de666e6e4e0e985627a58a20f Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 3 Aug 2020 14:07:42 -0600 Subject: [PATCH 02/11] save and return top nav option --- .../routing/routes/maps_app/maps_app_view.js | 1 + .../routes/maps_app/top_nav_config.tsx | 179 +++++++++++------- 2 files changed, 107 insertions(+), 73 deletions(-) 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 97a08f11a6757..c33c9c7f217e2 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 @@ -308,6 +308,7 @@ export class MapsAppView extends React.Component { openMapSettings: this.props.openMapSettings, inspectorAdapters: this.props.inspectorAdapters, setBreadcrumbs: this._setBreadcrumbs, + originatingApp: this.props.originatingApp, }); 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..0a5157e037740 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 @@ -16,7 +16,7 @@ import { getCoreI18n, } from '../../../kibana_services'; import { - SavedObjectSaveModal, + SavedObjectSaveModalOrigin, OnSaveProps, showSaveModal, } from '../../../../../../../src/plugins/saved_objects/public'; @@ -34,6 +34,7 @@ export function getTopNavConfig({ openMapSettings, inspectorAdapters, setBreadcrumbs, + originatingApp, }: { savedMap: ISavedGisMap; isOpenSettingsDisabled: boolean; @@ -43,14 +44,104 @@ export function getTopNavConfig({ openMapSettings: () => void; inspectorAdapters: Adapters; setBreadcrumbs: () => void; + originatingApp?: string; }) { - return [ + const topNavConfigs = []; + + const hasWritePermissions = getMapsCapabilities().save; + + if (hasWritePermissions && savedMap.id && originatingApp) { + topNavConfigs.push({ + id: 'saveAndReturn', + label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { + defaultMessage: 'Save and return', + }), + emphasize: true, + iconType: 'check', + run: () => { + /* if (isSaveable && lastKnownDoc) { + runSave({ + newTitle: lastKnownDoc.title, + newCopyOnSave: false, + isTitleDuplicateConfirmed: false, + returnToOrigin: true, + }); + }*/ + }, + testId: 'mapSaveAndReturnButton', + }); + } + + if (hasWritePermissions) { + topNavConfigs.push({ + id: 'save', + label: i18n.translate('xpack.maps.topNav.saveMapButtonLabel', { + defaultMessage: `save`, + }), + description: i18n.translate('xpack.maps.topNav.saveMapDescription', { + defaultMessage: `Save map`, + }), + 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: 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 = ( + {}} + documentInfo={{ + 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', { + label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { defaultMessage: `full screen`, }), - description: i18n.translate('xpack.maps.mapController.fullScreenDescription', { + description: i18n.translate('xpack.maps.topNav.fullScreenDescription', { defaultMessage: `full screen`, }), testId: 'mapsFullScreenMode', @@ -61,10 +152,10 @@ export function getTopNavConfig({ }, { 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', @@ -74,10 +165,10 @@ export function getTopNavConfig({ }, { id: 'mapSettings', - label: i18n.translate('xpack.maps.mapController.openSettingsButtonLabel', { + label: i18n.translate('xpack.maps.topNav.openSettingsButtonLabel', { defaultMessage: `Map settings`, }), - description: i18n.translate('xpack.maps.mapController.openSettingsDescription', { + description: i18n.translate('xpack.maps.topNav.openSettingsDescription', { defaultMessage: `Open map settings`, }), testId: 'openSettingsButton', @@ -87,70 +178,10 @@ export function getTopNavConfig({ run() { openMapSettings(); }, - }, - ...(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); - }, - }, - ] - : []), - ]; + return topNavConfigs; } async function doSave( @@ -168,7 +199,7 @@ async function doSave( getCoreChrome().docTitle.change(savedMap.title); } catch (err) { getToasts().addDanger({ - title: i18n.translate('xpack.maps.mapController.saveErrorMessage', { + title: i18n.translate('xpack.maps.topNav.saveErrorMessage', { defaultMessage: `Error on saving '{title}'`, values: { title: savedMap.title }, }), @@ -182,8 +213,10 @@ async function doSave( goToSpecifiedPath(`/map/${id}${window.location.hash}`); setBreadcrumbs(); + // coreStart.application.navigateToApp(originatingApp); + getToasts().addSuccess({ - title: i18n.translate('xpack.maps.mapController.saveSuccessMessage', { + title: i18n.translate('xpack.maps.topNav.saveSuccessMessage', { defaultMessage: `Saved '{title}'`, values: { title: savedMap.title }, }), From efc3169cdc9482be00c60e8324f3b9914c8bd693 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 4 Aug 2020 08:46:29 -0600 Subject: [PATCH 03/11] clean up --- .../routes/maps_app/top_nav_config.tsx | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) 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 0a5157e037740..786ac7413ca29 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 @@ -50,7 +50,9 @@ export function getTopNavConfig({ const hasWritePermissions = getMapsCapabilities().save; + let hasSaveAndReturnConfig = false; if (hasWritePermissions && savedMap.id && originatingApp) { + hasSaveAndReturnConfig = true; topNavConfigs.push({ id: 'saveAndReturn', label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { @@ -81,6 +83,7 @@ export function getTopNavConfig({ description: i18n.translate('xpack.maps.topNav.saveMapDescription', { defaultMessage: `Save map`, }), + emphasize: !hasSaveAndReturnConfig, testId: 'mapSaveButton', disableButton() { return isSaveDisabled; @@ -92,15 +95,18 @@ export function getTopNavConfig({ }); } }, - run: async () => { + run: () => { const onSave = ({ + newDescription, newTitle, newCopyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate, }: OnSaveProps) => { const currentTitle = savedMap.title; + const currentDescription = savedMap.description; savedMap.title = newTitle; + savedMap.description = newDescription; savedMap.copyOnSave = newCopyOnSave; const saveOptions: SavedObjectSaveOpts = { confirmOverwrite: false, @@ -111,6 +117,7 @@ export function getTopNavConfig({ // If the save wasn't successful, put the original values back. if (!response.id || response.error) { savedMap.title = currentTitle; + savedMap.description = currentDescription; } return response; }); @@ -122,6 +129,7 @@ export function getTopNavConfig({ onSave={onSave} onClose={() => {}} documentInfo={{ + description: savedMap.description, id: savedMap.id, title: savedMap.title, }} @@ -137,17 +145,19 @@ export function getTopNavConfig({ topNavConfigs.push( { - id: 'full-screen', - label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { - defaultMessage: `full screen`, + id: 'mapSettings', + label: i18n.translate('xpack.maps.topNav.openSettingsButtonLabel', { + defaultMessage: `Map settings`, }), - description: i18n.translate('xpack.maps.topNav.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(); }, }, { @@ -164,19 +174,17 @@ export function getTopNavConfig({ }, }, { - id: 'mapSettings', - label: i18n.translate('xpack.maps.topNav.openSettingsButtonLabel', { - defaultMessage: `Map settings`, + id: 'full-screen', + label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { + defaultMessage: `full screen`, }), - description: i18n.translate('xpack.maps.topNav.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(); }, } ); From f626cce07d038912666a73761a2bff248da753d7 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 4 Aug 2020 12:47:35 -0600 Subject: [PATCH 04/11] navigate to originating app --- x-pack/plugins/maps/public/kibana_services.js | 5 + x-pack/plugins/maps/public/plugin.ts | 2 + .../maps/public/routing/maps_router.js | 13 +- .../public/routing/routes/maps_app/index.js | 6 - .../routes/maps_app/load_map_and_render.js | 1 + .../routing/routes/maps_app/maps_app_view.js | 2 +- .../routes/maps_app/top_nav_config.tsx | 173 +++++++++--------- 7 files changed, 107 insertions(+), 95 deletions(-) diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index 89d20ae9878e9..e713089790064 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -185,3 +185,8 @@ export const setEmbeddableService = (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 f9310224980e1..c374d3cb59b34 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -42,6 +42,7 @@ import { setUiSettings, setVisualizations, setEmbeddableService, + setNavigateToApp, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; // @ts-ignore @@ -115,6 +116,7 @@ export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { setNavigation(plugins.navigation); setCoreI18n(core.i18n); setEmbeddableService(plugins.embeddable); + setNavigateToApp(core.application.navigateToApp); }; /** diff --git a/x-pack/plugins/maps/public/routing/maps_router.js b/x-pack/plugins/maps/public/routing/maps_router.js index 7060f56e84293..11f7d01549108 100644 --- a/x-pack/plugins/maps/public/routing/maps_router.js +++ b/x-pack/plugins/maps/public/routing/maps_router.js @@ -32,8 +32,10 @@ const App = ({ history, appBasePath, onAppLeave }) => { const store = getStore(); const I18nContext = getCoreI18n().Context; + const stateTransfer = getEmbeddableService()?.getStateTransfer(history); + const { originatingApp } = - getEmbeddableService()?.getStateTransfer(history)?.getIncomingEditorState() || {}; + stateTransfer?.getIncomingEditorState({ keysToRemoveAfterFetch: ['originatingApp'] }) || {}; return ( @@ -46,6 +48,7 @@ const App = ({ history, appBasePath, onAppLeave }) => { )} @@ -53,7 +56,13 @@ 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 c13a294fdd3c9..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 @@ -60,6 +60,7 @@ export const LoadMapAndRender = class extends React.Component { ) : 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 c33c9c7f217e2..0f4f52573b770 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 @@ -303,11 +303,11 @@ 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.props.originatingApp, }); 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 786ac7413ca29..905b179fbfb7e 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 @@ -14,6 +14,7 @@ import { getInspector, getToasts, getCoreI18n, + navigateToApp, } from '../../../kibana_services'; import { SavedObjectSaveModalOrigin, @@ -29,30 +30,96 @@ export function getTopNavConfig({ savedMap, isOpenSettingsDisabled, isSaveDisabled, - closeFlyout, enableFullScreen, openMapSettings, inspectorAdapters, setBreadcrumbs, + stateTransfer, originatingApp, }: { savedMap: ISavedGisMap; isOpenSettingsDisabled: boolean; isSaveDisabled: boolean; - closeFlyout: () => void; enableFullScreen: () => void; openMapSettings: () => void; inspectorAdapters: Adapters; setBreadcrumbs: () => void; + stateTransfer?: unknown; originatingApp?: string; }) { 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, + }); + } 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 }; + } + + if (!id) { + return {}; + } + + 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}`); - let hasSaveAndReturnConfig = false; - if (hasWritePermissions && savedMap.id && originatingApp) { - hasSaveAndReturnConfig = true; + if (!!originatingApp && returnToOrigin) { + const newlyCreated = newCopyOnSave || isNewMap; + 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.fullScreenButtonLabel', { @@ -61,14 +128,13 @@ export function getTopNavConfig({ emphasize: true, iconType: 'check', run: () => { - /* if (isSaveable && lastKnownDoc) { - runSave({ - newTitle: lastKnownDoc.title, - newCopyOnSave: false, - isTitleDuplicateConfirmed: false, - returnToOrigin: true, - }); - }*/ + onSave({ + newTitle: savedMap.title, + newDescription: savedMap.description, + newCopyOnSave: false, + isTitleDuplicateConfirmed: false, + returnToOrigin: true, + }); }, testId: 'mapSaveAndReturnButton', }); @@ -77,9 +143,13 @@ export function getTopNavConfig({ if (hasWritePermissions) { topNavConfigs.push({ id: 'save', - label: i18n.translate('xpack.maps.topNav.saveMapButtonLabel', { - defaultMessage: `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`, }), @@ -96,33 +166,6 @@ export function getTopNavConfig({ } }, run: () => { - const onSave = ({ - newDescription, - newTitle, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }: OnSaveProps) => { - const currentTitle = savedMap.title; - const currentDescription = savedMap.description; - savedMap.title = newTitle; - savedMap.description = newDescription; - 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; - savedMap.description = currentDescription; - } - return response; - }); - }; - const saveModal = ( 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.topNav.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(); - - // coreStart.application.navigateToApp(originatingApp); - - getToasts().addSuccess({ - title: i18n.translate('xpack.maps.topNav.saveSuccessMessage', { - defaultMessage: `Saved '{title}'`, - values: { title: savedMap.title }, - }), - 'data-test-subj': 'saveMapSuccess', - }); - } - return { id }; -} From d7bc9fbb1e6eb40807a0aa3808744378d71d395d Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 4 Aug 2020 14:29:26 -0600 Subject: [PATCH 05/11] functional test --- .../services/dashboard/panel_actions.ts | 11 +++ .../routes/maps_app/top_nav_config.tsx | 9 +-- .../functional/apps/maps/embeddable/index.js | 1 + .../apps/maps/embeddable/save_and_return.js | 71 +++++++++++++++++++ .../test/functional/page_objects/gis_page.js | 4 ++ 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 x-pack/test/functional/apps/maps/embeddable/save_and_return.js 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/routing/routes/maps_app/top_nav_config.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx index 905b179fbfb7e..137ce453655ae 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 @@ -74,6 +74,11 @@ export function getTopNavConfig({ 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', { @@ -89,10 +94,6 @@ export function getTopNavConfig({ return { error: err }; } - if (!id) { - return {}; - } - getToasts().addSuccess({ title: i18n.translate('xpack.maps.topNav.saveSuccessMessage', { defaultMessage: `Saved '{title}'`, 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..1cf71d282991f --- /dev/null +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -0,0 +1,71 @@ +/* + * 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'); + + describe('save and return work flow', () => { + describe('new map', () => { + it('creating a new map from dashboard should open maps application', 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(); + const doesLayerExist = await PageObjects.maps.doesLayerExist('Road map'); + expect(doesLayerExist).to.equal(true); + }); + + it('clicking save 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('exit 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('editing map from dashboard should open maps application', async () => { + const doesLayerExist = await PageObjects.maps.doesLayerExist('geo_shapes*'); + expect(doesLayerExist).to.equal(true); + }); + + it('clicking "save and return" 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('clicking "save as" 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); + }); + }); + }); + }); +} diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index b8f4faf3ebfd8..457564fd543b2 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -145,6 +145,10 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.clickWhenNotDisabled('confirmSaveSavedObjectButton'); } + async clickSaveAndReturnButton() { + await testSubjects.click('mapSaveAndReturnButton'); + } + async expectMissingSaveButton() { await testSubjects.missingOrFail('mapSaveButton'); } From 2b2c9f9c8c7527c4fee5b8fd472472917efe3bea Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 4 Aug 2020 17:12:48 -0600 Subject: [PATCH 06/11] tslint --- x-pack/plugins/maps/public/kibana_services.d.ts | 7 +++++++ .../routing/bootstrap/services/saved_gis_map.ts | 1 + .../public/routing/routes/maps_app/top_nav_config.tsx | 8 ++++---- x-pack/plugins/translations/translations/ja-JP.json | 11 ----------- x-pack/plugins/translations/translations/zh-CN.json | 11 ----------- 5 files changed, 12 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/maps/public/kibana_services.d.ts b/x-pack/plugins/maps/public/kibana_services.d.ts index 2e6911e89fa0a..cff03e590aec1 100644 --- a/x-pack/plugins/maps/public/kibana_services.d.ts +++ b/x-pack/plugins/maps/public/kibana_services.d.ts @@ -8,6 +8,7 @@ import { DataPublicPluginStart } from 'src/plugins/data/public'; import { IndexPatternsService } from 'src/plugins/data/public/index_patterns'; 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 +78,9 @@ 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?: unknown | undefined) => Promise +): void; +// export navigateToApp: (appId: string, options?: unknown | undefined) => Promise; 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/routes/maps_app/top_nav_config.tsx b/x-pack/plugins/maps/public/routing/routes/maps_app/top_nav_config.tsx index 137ce453655ae..1360ea245c6b1 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,7 +7,6 @@ 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, @@ -25,6 +24,7 @@ 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, @@ -44,7 +44,7 @@ export function getTopNavConfig({ openMapSettings: () => void; inspectorAdapters: Adapters; setBreadcrumbs: () => void; - stateTransfer?: unknown; + stateTransfer?: EmbeddableStateTransfer; originatingApp?: string; }) { const topNavConfigs = []; @@ -123,7 +123,7 @@ export function getTopNavConfig({ if (hasSaveAndReturnConfig) { topNavConfigs.push({ id: 'saveAndReturn', - label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', { + label: i18n.translate('xpack.maps.topNav.saveAndReturnButtonLabel', { defaultMessage: 'Save and return', }), emphasize: true, @@ -131,7 +131,7 @@ export function getTopNavConfig({ run: () => { onSave({ newTitle: savedMap.title, - newDescription: savedMap.description, + newDescription: savedMap.description ? savedMap.description : '', newCopyOnSave: false, isTitleDuplicateConfirmed: false, returnToOrigin: true, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 544f6cc6ec342..49e06ada9b7a8 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10418,18 +10418,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 2ee85fc87cc72..1765be33c4f50 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10420,18 +10420,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": "高级设置", From f34ae2f4f01c38a97496f12dd8b22f68dfebe804 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 5 Aug 2020 10:29:34 -0600 Subject: [PATCH 07/11] cutOriginatingAppConnection --- x-pack/plugins/maps/public/kibana_services.d.ts | 8 ++++++-- .../maps/public/routing/routes/maps_app/maps_app_view.js | 7 ++++++- .../public/routing/routes/maps_app/top_nav_config.tsx | 9 ++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/maps/public/kibana_services.d.ts b/x-pack/plugins/maps/public/kibana_services.d.ts index cff03e590aec1..2b28e1a8c7dbb 100644 --- a/x-pack/plugins/maps/public/kibana_services.d.ts +++ b/x-pack/plugins/maps/public/kibana_services.d.ts @@ -6,6 +6,7 @@ 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'; @@ -81,6 +82,9 @@ export function setIsGoldPlus(isGoldPlus: boolean): void; export function setEmbeddableService(embeddableService: EmbeddableStart): void; export function getEmbeddableService(): EmbeddableStart; export function setNavigateToApp( - navigateToApp: (appId: string, options?: unknown | undefined) => Promise + navigateToApp: (appId: string, options?: NavigateToAppOptions | undefined) => Promise ): void; -// export navigateToApp: (appId: string, options?: unknown | undefined) => Promise; +export const navigateToApp: ( + appId: string, + options?: NavigateToAppOptions | undefined +) => Promise; 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 0f4f52573b770..ae8394e819185 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, }; } @@ -308,7 +310,10 @@ export class MapsAppView extends React.Component { inspectorAdapters: this.props.inspectorAdapters, setBreadcrumbs: this._setBreadcrumbs, stateTransfer: this.props.stateTransfer, - originatingApp: this.props.originatingApp, + 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 1360ea245c6b1..739dc93b8beab 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 @@ -36,6 +36,7 @@ export function getTopNavConfig({ setBreadcrumbs, stateTransfer, originatingApp, + cutOriginatingAppConnection, }: { savedMap: ISavedGisMap; isOpenSettingsDisabled: boolean; @@ -46,6 +47,7 @@ export function getTopNavConfig({ setBreadcrumbs: () => void; stateTransfer?: EmbeddableStateTransfer; originatingApp?: string; + cutOriginatingAppConnection: () => void; }) { const topNavConfigs = []; const isNewMap = !savedMap.id; @@ -106,6 +108,10 @@ export function getTopNavConfig({ setBreadcrumbs(); goToSpecifiedPath(`/map/${id}${window.location.hash}`); + if (newCopyOnSave && !returnToOrigin) { + cutOriginatingAppConnection(); + } + if (!!originatingApp && returnToOrigin) { const newlyCreated = newCopyOnSave || isNewMap; if (newlyCreated && stateTransfer) { @@ -130,11 +136,12 @@ export function getTopNavConfig({ iconType: 'check', run: () => { onSave({ - newTitle: savedMap.title, + newTitle: savedMap.title ? savedMap.title : '', newDescription: savedMap.description ? savedMap.description : '', newCopyOnSave: false, isTitleDuplicateConfirmed: false, returnToOrigin: true, + onTitleDuplicate: () => {}, }); }, testId: 'mapSaveAndReturnButton', From 68c623db22276b607f6cfe50cc9bec5f6c562c62 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 5 Aug 2020 11:32:05 -0600 Subject: [PATCH 08/11] add functional test for cutting originating app flow --- .../apps/maps/embeddable/save_and_return.js | 19 ++++++++++++------- .../test/functional/page_objects/gis_page.js | 9 ++++++++- 2 files changed, 20 insertions(+), 8 deletions(-) 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 index 1cf71d282991f..ddf0e40c2743d 100644 --- a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -11,6 +11,7 @@ export default function ({ getPageObjects, getService }) { 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', () => { @@ -45,12 +46,7 @@ export default function ({ getPageObjects, getService }) { }); describe('save and return', () => { - it('editing map from dashboard should open maps application', async () => { - const doesLayerExist = await PageObjects.maps.doesLayerExist('geo_shapes*'); - expect(doesLayerExist).to.equal(true); - }); - - it('clicking "save and return" should return to dashboard', async () => { + it('should return to dashboard', async () => { await PageObjects.maps.clickSaveAndReturnButton(); await PageObjects.dashboard.waitForRenderComplete(); const panelCount = await PageObjects.dashboard.getPanelCount(); @@ -59,13 +55,22 @@ export default function ({ getPageObjects, getService }) { }); describe('save as', () => { - it('clicking "save as" should return to dashboard and add new panel', async () => { + 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 457564fd543b2..27e86d913e7b5 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -139,9 +139,16 @@ 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'); } From 25e71c07071550b0fcf5c20ce8fa159d98b8d464 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 5 Aug 2020 14:47:04 -0600 Subject: [PATCH 09/11] one more fix for cutting originator app and another functional test to verify --- .../routes/maps_app/top_nav_config.tsx | 8 ++---- .../apps/maps/embeddable/save_and_return.js | 28 +++++++++++++------ .../test/functional/page_objects/gis_page.js | 4 ++- 3 files changed, 26 insertions(+), 14 deletions(-) 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 739dc93b8beab..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 @@ -108,12 +108,10 @@ export function getTopNavConfig({ setBreadcrumbs(); goToSpecifiedPath(`/map/${id}${window.location.hash}`); - if (newCopyOnSave && !returnToOrigin) { + const newlyCreated = newCopyOnSave || isNewMap; + if (newlyCreated && !returnToOrigin) { cutOriginatingAppConnection(); - } - - if (!!originatingApp && returnToOrigin) { - const newlyCreated = newCopyOnSave || isNewMap; + } else if (!!originatingApp && returnToOrigin) { if (newlyCreated && stateTransfer) { stateTransfer.navigateToWithEmbeddablePackage(originatingApp, { state: { id, type: MAP_SAVED_OBJECT_TYPE }, 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 index ddf0e40c2743d..75289e5399438 100644 --- a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -15,7 +15,7 @@ export default function ({ getPageObjects, getService }) { describe('save and return work flow', () => { describe('new map', () => { - it('creating a new map from dashboard should open maps application', async () => { + beforeEach(async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.clickNewDashboard(); await dashboardAddPanel.clickCreateNewLink(); @@ -23,15 +23,27 @@ export default function ({ getPageObjects, getService }) { await PageObjects.visualize.clickMapsApp(); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.maps.waitForLayersToLoad(); - const doesLayerExist = await PageObjects.maps.doesLayerExist('Road map'); - expect(doesLayerExist).to.equal(true); }); - it('clicking save 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', () => { + 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'); + }); }); }); diff --git a/x-pack/test/functional/page_objects/gis_page.js b/x-pack/test/functional/page_objects/gis_page.js index 27e86d913e7b5..4998635096c39 100644 --- a/x-pack/test/functional/page_objects/gis_page.js +++ b/x-pack/test/functional/page_objects/gis_page.js @@ -143,7 +143,9 @@ export function GisPageProvider({ getService, getPageObjects }) { await testSubjects.click('mapSaveButton'); await testSubjects.setValue('savedObjectTitle', name); if (uncheckReturnToOriginModeSwitch) { - const redirectToOriginCheckboxExists = await testSubjects.exists('returnToOriginModeSwitch'); + const redirectToOriginCheckboxExists = await testSubjects.exists( + 'returnToOriginModeSwitch' + ); if (!redirectToOriginCheckboxExists) { throw new Error('Unable to uncheck "returnToOriginModeSwitch", it does not exist.'); } From 8fd1d813f07ff81be0ceade36790a6abe96708e3 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 5 Aug 2020 14:50:14 -0600 Subject: [PATCH 10/11] typo --- x-pack/test/functional/apps/maps/embeddable/save_and_return.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 75289e5399438..4aa44799db1f4 100644 --- a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js +++ b/x-pack/test/functional/apps/maps/embeddable/save_and_return.js @@ -47,7 +47,7 @@ export default function ({ getPageObjects, getService }) { }); }); - describe('exit existing map', () => { + describe('edit existing map', () => { beforeEach(async () => { await PageObjects.common.navigateToApp('dashboard'); await PageObjects.dashboard.loadSavedDashboard('map embeddable example'); From aa2a57ea7055edc6bd89a9bb8d13738defef899b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 11 Aug 2020 15:56:34 -0600 Subject: [PATCH 11/11] review feedback --- x-pack/plugins/maps/public/kibana_services.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/maps/public/kibana_services.js b/x-pack/plugins/maps/public/kibana_services.js index e713089790064..9b035a87a3b37 100644 --- a/x-pack/plugins/maps/public/kibana_services.js +++ b/x-pack/plugins/maps/public/kibana_services.js @@ -178,12 +178,12 @@ export const getIsGoldPlus = () => { return isGoldPlus; }; -let _embeddableService; -export const setEmbeddableService = (embeddableService) => { - _embeddableService = embeddableService; +let embeddableService; +export const setEmbeddableService = (_embeddableService) => { + embeddableService = _embeddableService; }; export const getEmbeddableService = () => { - return _embeddableService; + return embeddableService; }; export let navigateToApp;