[maps] implement save and return from dashboard (#74303)

* pass originatingApp into App

* save and return top nav option

* clean up

* navigate to originating app

* functional test

* tslint

* cutOriginatingAppConnection

* add functional test for cutting originating app flow

* one more fix for cutting originator app and another functional test to verify

* typo

* review feedback

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2020-08-12 07:09:49 -06:00 committed by GitHub
parent 178afd71fc
commit ed69f9b85a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 351 additions and 163 deletions

View file

@ -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);
}

View file

@ -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>
): void;
export const navigateToApp: (
appId: string,
options?: NavigateToAppOptions | undefined
) => Promise<void>;

View file

@ -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;
}

View file

@ -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);
};
/**

View file

@ -36,6 +36,7 @@ export interface ISavedGisMap extends SavedObject {
layerListJSON?: string;
mapStateJSON?: string;
uiStateJSON?: string;
description?: string;
getLayerList(): LayerDescriptor[];
syncWithStore(): void;
}

View file

@ -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 (
<I18nContext>
<Provider store={store}>
@ -50,13 +55,21 @@ const App = ({ history, appBasePath, onAppLeave }) => {
<LoadMapAndRender
savedMapId={props.match.params.savedMapId}
onAppLeave={onAppLeave}
stateTransfer={stateTransfer}
originatingApp={originatingApp}
/>
)}
/>
<Route
exact
path={`/map`}
render={() => <LoadMapAndRender onAppLeave={onAppLeave} />}
render={() => (
<LoadMapAndRender
onAppLeave={onAppLeave}
stateTransfer={stateTransfer}
originatingApp={originatingApp}
/>
)}
/>
// Redirect other routes to list, or if hash-containing, their non-hash equivalents
<Route

View file

@ -29,7 +29,6 @@ import {
updateFlyout,
enableFullScreen,
openMapSettings,
removePreviewLayers,
} from '../../../actions';
import { FLYOUT_STATE } from '../../../reducers/ui';
import { getMapsCapabilities } from '../../../kibana_services';
@ -74,11 +73,6 @@ function mapDispatchToProps(dispatch) {
dispatch(updateFlyout(FLYOUT_STATE.NONE));
dispatch(setReadOnly(!getMapsCapabilities().save));
},
closeFlyout: () => {
dispatch(setSelectedLayer(null));
dispatch(updateFlyout(FLYOUT_STATE.NONE));
dispatch(removePreviewLayers());
},
enableFullScreen: () => dispatch(enableFullScreen()),
openMapSettings: () => dispatch(openMapSettings()),
};

View file

@ -56,6 +56,13 @@ export const LoadMapAndRender = class extends React.Component {
return <Redirect to="/" />;
}
return savedMap ? <MapsAppView savedMap={savedMap} onAppLeave={this.props.onAppLeave} /> : null;
return savedMap ? (
<MapsAppView
savedMap={savedMap}
onAppLeave={this.props.onAppLeave}
stateTransfer={this.props.stateTransfer}
originatingApp={this.props.originatingApp}
/>
) : null;
}
};

View file

@ -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;

View file

@ -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,60 +24,181 @@ 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 [
{
id: 'full-screen',
label: i18n.translate('xpack.maps.mapController.fullScreenButtonLabel', {
defaultMessage: `full screen`,
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 },
}),
description: i18n.translate('xpack.maps.mapController.fullScreenDescription', {
defaultMessage: `full screen`,
'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',
}),
testId: 'mapsFullScreenMode',
run() {
getCoreChrome().setIsVisible(false);
enableFullScreen();
emphasize: true,
iconType: 'check',
run: () => {
onSave({
newTitle: savedMap.title ? savedMap.title : '',
newDescription: savedMap.description ? savedMap.description : '',
newCopyOnSave: false,
isTitleDuplicateConfirmed: false,
returnToOrigin: true,
onTitleDuplicate: () => {},
});
},
},
{
id: 'inspect',
label: i18n.translate('xpack.maps.mapController.openInspectorButtonLabel', {
defaultMessage: `inspect`,
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`,
}),
description: i18n.translate('xpack.maps.mapController.openInspectorDescription', {
defaultMessage: `Open Inspector`,
}),
testId: 'openInspectorButton',
run() {
getInspector().open(inspectorAdapters, {});
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 = (
<SavedObjectSaveModalOrigin
originatingApp={originatingApp}
onSave={onSave}
onClose={() => {}}
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: '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',
@ -88,107 +209,34 @@ export function getTopNavConfig({
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 = (
<SavedObjectSaveModal
onSave={onSave}
onClose={() => {}}
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 },
{
id: 'inspect',
label: i18n.translate('xpack.maps.topNav.openInspectorButtonLabel', {
defaultMessage: `inspect`,
}),
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 },
description: i18n.translate('xpack.maps.topNav.openInspectorDescription', {
defaultMessage: `Open Inspector`,
}),
'data-test-subj': 'saveMapSuccess',
});
}
return { id };
testId: 'openInspectorButton',
run() {
getInspector().open(inspectorAdapters, {});
},
},
{
id: 'full-screen',
label: i18n.translate('xpack.maps.topNav.fullScreenButtonLabel', {
defaultMessage: `full screen`,
}),
description: i18n.translate('xpack.maps.topNav.fullScreenDescription', {
defaultMessage: `full screen`,
}),
testId: 'mapsFullScreenMode',
run() {
getCoreChrome().setIsVisible(false);
enableFullScreen();
},
}
);
return topNavConfigs;
}

View file

@ -10409,18 +10409,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": "高度な設定",

View file

@ -10411,18 +10411,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": "高级设置",

View file

@ -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'));

View file

@ -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');
});
});
});
});
}

View file

@ -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');
}