diff --git a/docs/user/dashboard/dashboard.asciidoc b/docs/user/dashboard/dashboard.asciidoc index cd6a024da8172..f4f3aa74a8c8f 100644 --- a/docs/user/dashboard/dashboard.asciidoc +++ b/docs/user/dashboard/dashboard.asciidoc @@ -363,7 +363,7 @@ Apply a set of design options to the entire dashboard. . If you're in view mode, click *Edit* in the toolbar. -. In the toolbar, *Options*, then use the following options: +. In the toolbar, click *Settings*, to open the *Dashboard settings* flyout, then use the following options: * *Use margins between panels* — Adds a margin of space between each panel. diff --git a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts index 26faaa87acad7..c10646430494d 100644 --- a/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts +++ b/src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts @@ -323,12 +323,12 @@ export const topNavStrings = { defaultMessage: 'Share Dashboard', }), }, - options: { - label: i18n.translate('dashboard.topNave.optionsButtonAriaLabel', { - defaultMessage: 'options', + settings: { + label: i18n.translate('dashboard.topNave.settingsButtonAriaLabel', { + defaultMessage: 'settings', }), - description: i18n.translate('dashboard.topNave.optionsConfigDescription', { - defaultMessage: 'Options', + description: i18n.translate('dashboard.topNave.settingsConfigDescription', { + defaultMessage: 'Open dashboard settings', }), }, clone: { diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx index d436402763343..645aa42ec918d 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/use_dashboard_menu_items.tsx @@ -55,6 +55,7 @@ export const useDashboardMenuItems = ({ const dispatch = useEmbeddableDispatch(); const hasUnsavedChanges = select((state) => state.componentState.hasUnsavedChanges); + const hasOverlays = select((state) => state.componentState.hasOverlays); const lastSavedId = select((state) => state.componentState.lastSavedId); const dashboardTitle = select((state) => state.explicitInput.title); @@ -169,13 +170,13 @@ export const useDashboardMenuItems = ({ emphasize: true, isLoading: isSaveInProgress, testId: 'dashboardQuickSaveMenuItem', - disableButton: !hasUnsavedChanges || isSaveInProgress, + disableButton: !hasUnsavedChanges || isSaveInProgress || hasOverlays, run: () => quickSaveDashboard(), } as TopNavMenuData, saveAs: { description: topNavStrings.saveAs.description, - disableButton: isSaveInProgress, + disableButton: isSaveInProgress || hasOverlays, id: 'save', emphasize: !Boolean(lastSavedId), testId: 'dashboardSaveMenuItem', @@ -187,7 +188,7 @@ export const useDashboardMenuItems = ({ switchToViewMode: { ...topNavStrings.switchToViewMode, id: 'cancel', - disableButton: isSaveInProgress || !lastSavedId, + disableButton: isSaveInProgress || !lastSavedId || hasOverlays, testId: 'dashboardViewOnlyMode', run: () => returnToViewMode(), } as TopNavMenuData, @@ -196,16 +197,16 @@ export const useDashboardMenuItems = ({ ...topNavStrings.share, id: 'share', testId: 'shareTopNavButton', - disableButton: isSaveInProgress, + disableButton: isSaveInProgress || hasOverlays, run: showShare, } as TopNavMenuData, - options: { - ...topNavStrings.options, - id: 'options', - testId: 'dashboardOptionsButton', - disableButton: isSaveInProgress, - run: (anchor) => dashboardContainer.showOptions(anchor), + settings: { + ...topNavStrings.settings, + id: 'settings', + testId: 'dashboardSettingsButton', + disableButton: isSaveInProgress || hasOverlays, + run: () => dashboardContainer.showSettings(), } as TopNavMenuData, clone: { @@ -220,6 +221,7 @@ export const useDashboardMenuItems = ({ quickSaveDashboard, dashboardContainer, hasUnsavedChanges, + hasOverlays, setFullScreenMode, isSaveInProgress, returnToViewMode, @@ -252,7 +254,7 @@ export const useDashboardMenuItems = ({ } else { editModeItems.push(menuItems.switchToViewMode, menuItems.saveAs); } - return [...labsMenuItem, menuItems.options, ...shareMenuItem, ...editModeItems]; + return [...labsMenuItem, menuItems.settings, ...shareMenuItem, ...editModeItems]; }, [lastSavedId, menuItems, share, isLabsEnabled]); return { viewModeTopNavConfig, editModeTopNavConfig }; diff --git a/src/plugins/dashboard/public/dashboard_container/component/settings/index.ts b/src/plugins/dashboard/public/dashboard_container/component/settings/index.ts new file mode 100644 index 0000000000000..00d5be0ca3a0d --- /dev/null +++ b/src/plugins/dashboard/public/dashboard_container/component/settings/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { DashboardSettings } from './settings_flyout'; diff --git a/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx new file mode 100644 index 0000000000000..d7cd61cdd7f7c --- /dev/null +++ b/src/plugins/dashboard/public/dashboard_container/component/settings/settings_flyout.tsx @@ -0,0 +1,361 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback, useState } from 'react'; +import useMountedState from 'react-use/lib/useMountedState'; +import { i18n } from '@kbn/i18n'; +import { + EuiFormRow, + EuiFieldText, + EuiTextArea, + EuiForm, + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, + EuiTitle, + EuiCallOut, + EuiSwitch, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { DashboardContainerByValueInput } from '../../../../common'; +import { pluginServices } from '../../../services/plugin_services'; +import { useDashboardContainerContext } from '../../dashboard_container_context'; + +interface DashboardSettingsProps { + onClose: () => void; +} + +const DUPLICATE_TITLE_CALLOUT_ID = 'duplicateTitleCallout'; + +export const DashboardSettings = ({ onClose }: DashboardSettingsProps) => { + const { + savedObjectsTagging: { components }, + dashboardSavedObject: { checkForDuplicateDashboardTitle }, + } = pluginServices.getServices(); + + const { + useEmbeddableDispatch, + useEmbeddableSelector: select, + actions: { setStateFromSettingsFlyout }, + embeddableInstance: dashboardContainer, + } = useDashboardContainerContext(); + + const [dashboardSettingsState, setDashboardSettingsState] = useState({ + ...dashboardContainer.getInputAsValueType(), + }); + + const [isTitleDuplicate, setIsTitleDuplicate] = useState(false); + const [isTitleDuplicateConfirmed, setIsTitleDuplicateConfirmed] = useState(false); + const [isApplying, setIsApplying] = useState(false); + + const lastSavedId = select((state) => state.componentState.lastSavedId); + const lastSavedTitle = select((state) => state.explicitInput.title); + + const isMounted = useMountedState(); + + const onTitleDuplicate = () => { + if (!isMounted()) return; + setIsTitleDuplicate(true); + setIsTitleDuplicateConfirmed(true); + }; + + const onApply = async () => { + setIsApplying(true); + const validTitle = await checkForDuplicateDashboardTitle({ + title: dashboardSettingsState.title, + copyOnSave: false, + lastSavedTitle, + onTitleDuplicate, + isTitleDuplicateConfirmed, + }); + + if (!isMounted()) return; + + setIsApplying(false); + + if (validTitle) { + dispatch(setStateFromSettingsFlyout({ lastSavedId, ...dashboardSettingsState })); + onClose(); + } + }; + + const updateDashboardSetting = useCallback( + (newSettings: Partial) => { + setDashboardSettingsState((prevDashboardSettingsState) => { + return { + ...prevDashboardSettingsState, + ...newSettings, + }; + }); + }, + [] + ); + + const dispatch = useEmbeddableDispatch(); + + const renderDuplicateTitleCallout = () => { + if (!isTitleDuplicate) { + return; + } + + return ( + + } + color="warning" + data-test-subj="duplicateTitleWarningMessage" + id={DUPLICATE_TITLE_CALLOUT_ID} + > +

+ +

+
+ ); + }; + + const renderTagSelector = () => { + if (!components) return; + return ( + + } + > + updateDashboardSetting({ tags: selectedTags })} + /> + + ); + }; + + return ( + <> + + +

+ +

+
+
+ + {renderDuplicateTitleCallout()} + + + } + > + { + setIsTitleDuplicate(false); + setIsTitleDuplicateConfirmed(false); + updateDashboardSetting({ title: event.target.value }); + }} + aria-label={i18n.translate( + 'dashboard.embeddableApi.showSettings.flyout.form.panelTitleInputAriaLabel', + { + defaultMessage: 'Change the dashboard title', + } + )} + aria-describedby={isTitleDuplicate ? DUPLICATE_TITLE_CALLOUT_ID : undefined} + /> + + + } + > + updateDashboardSetting({ description: event.target.value })} + aria-label={i18n.translate( + 'dashboard.embeddableApi.showSettings.flyout.form.panelDescriptionAriaLabel', + { + defaultMessage: 'Change the dashboard description', + } + )} + /> + + {renderTagSelector()} + + } + > + updateDashboardSetting({ timeRestore: event.target.checked })} + label={ + + } + /> + + + updateDashboardSetting({ useMargins: event.target.checked })} + data-test-subj="dashboardMarginsCheckbox" + /> + + + + + updateDashboardSetting({ hidePanelTitles: !event.target.checked }) + } + data-test-subj="dashboardPanelTitlesCheckbox" + /> + + + <> + + updateDashboardSetting({ syncColors: event.target.checked })} + data-test-subj="dashboardSyncColorsCheckbox" + /> + + + { + const syncCursor = event.target.checked; + if (!syncCursor && dashboardSettingsState.syncTooltips) { + updateDashboardSetting({ syncCursor, syncTooltips: false }); + } else { + updateDashboardSetting({ syncCursor }); + } + }} + data-test-subj="dashboardSyncCursorCheckbox" + /> + + + + updateDashboardSetting({ syncTooltips: event.target.checked }) + } + data-test-subj="dashboardSyncTooltipsCheckbox" + /> + + + + + + + + + + + + + + + {isTitleDuplicate ? ( + + ) : ( + + )} + + + + + + ); +}; diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/index.ts b/src/plugins/dashboard/public/dashboard_container/embeddable/api/index.ts index fc58e3ad0aca5..2a2d20cc5da14 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/api/index.ts +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/api/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -export { showOptions } from './show_options_popover'; +export { showSettings } from './show_settings'; export { addFromLibrary } from './add_panel_from_library'; export { runSaveAs, runQuickSave, runClone } from './run_save_functions'; export { addOrUpdateEmbeddable, replacePanel, showPlaceholderUntil } from './panel_management'; diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/overlays/options.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/api/overlays/options.tsx deleted file mode 100644 index ba0acfdf0eb51..0000000000000 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/api/overlays/options.tsx +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; - -import { EuiForm, EuiFormRow, EuiSwitch } from '@elastic/eui'; -import { useDashboardContainerContext } from '../../../dashboard_container_context'; - -export const DashboardOptions = () => { - const { - useEmbeddableDispatch, - useEmbeddableSelector: select, - actions: { setUseMargins, setSyncCursor, setSyncColors, setSyncTooltips, setHidePanelTitles }, - } = useDashboardContainerContext(); - const dispatch = useEmbeddableDispatch(); - - const useMargins = select((state) => state.explicitInput.useMargins); - const syncColors = select((state) => state.explicitInput.syncColors); - const syncCursor = select((state) => state.explicitInput.syncCursor); - const syncTooltips = select((state) => state.explicitInput.syncTooltips); - const hidePanelTitles = select((state) => state.explicitInput.hidePanelTitles); - - return ( - - - dispatch(setUseMargins(event.target.checked))} - data-test-subj="dashboardMarginsCheckbox" - /> - - - - dispatch(setHidePanelTitles(!event.target.checked))} - data-test-subj="dashboardPanelTitlesCheckbox" - /> - - - <> - - dispatch(setSyncColors(event.target.checked))} - data-test-subj="dashboardSyncColorsCheckbox" - /> - - - dispatch(setSyncCursor(event.target.checked))} - data-test-subj="dashboardSyncCursorCheckbox" - /> - - - dispatch(setSyncTooltips(event.target.checked))} - data-test-subj="dashboardSyncTooltipsCheckbox" - /> - - - - - ); -}; diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_options_popover.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_options_popover.tsx deleted file mode 100644 index ebbd63bd6a93f..0000000000000 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_options_popover.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import ReactDOM from 'react-dom'; - -import { I18nProvider } from '@kbn/i18n-react'; -import { EuiWrappingPopover } from '@elastic/eui'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; - -import { DashboardOptions } from './overlays/options'; -import { DashboardContainer } from '../dashboard_container'; -import { pluginServices } from '../../../services/plugin_services'; - -let isOpen = false; - -const container = document.createElement('div'); -const onClose = () => { - ReactDOM.unmountComponentAtNode(container); - isOpen = false; -}; - -export function showOptions(this: DashboardContainer, anchorElement: HTMLElement) { - const { - settings: { - theme: { theme$ }, - }, - } = pluginServices.getServices(); - - if (isOpen) { - onClose(); - return; - } - - isOpen = true; - const { Wrapper: DashboardReduxWrapper } = this.getReduxEmbeddableTools(); - - document.body.appendChild(container); - const element = ( - - - - - - - - - - ); - ReactDOM.render(element, container); -} diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_settings.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_settings.tsx new file mode 100644 index 0000000000000..266c0a414b5b9 --- /dev/null +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/api/show_settings.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; + +import { toMountPoint } from '@kbn/kibana-react-plugin/public'; + +import { DashboardSettings } from '../../component/settings/settings_flyout'; +import { DashboardContainer } from '../dashboard_container'; +import { pluginServices } from '../../../services/plugin_services'; + +export function showSettings(this: DashboardContainer) { + const { + settings: { + theme: { theme$ }, + }, + overlays, + } = pluginServices.getServices(); + + const { + dispatch, + Wrapper: DashboardReduxWrapper, + actions: { setHasOverlays }, + } = this.getReduxEmbeddableTools(); + + // TODO Move this action into DashboardContainer.openOverlay + dispatch(setHasOverlays(true)); + + this.openOverlay( + overlays.openFlyout( + toMountPoint( + + { + dispatch(setHasOverlays(false)); + this.clearOverlays(); + }} + /> + , + { theme$ } + ), + { + size: 's', + 'data-test-subj': 'dashboardSettingsFlyout', + onClose: (flyout) => { + this.clearOverlays(); + dispatch(setHasOverlays(false)); + flyout.close(); + }, + } + ) + ); +} diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx index e370945d58f4f..4c351177113d9 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx @@ -37,7 +37,7 @@ import { ExitFullScreenButtonKibanaProvider } from '@kbn/shared-ux-button-exit-f import { runClone, runSaveAs, - showOptions, + showSettings, runQuickSave, replacePanel, addFromLibrary, @@ -521,7 +521,7 @@ export class DashboardContainer extends Container + ) => { + state.componentState.lastSavedId = action.payload.lastSavedId; + + state.explicitInput.tags = action.payload.tags; + state.explicitInput.title = action.payload.title; + state.explicitInput.description = action.payload.description; + state.explicitInput.timeRestore = action.payload.timeRestore; + + state.explicitInput.useMargins = action.payload.useMargins; + state.explicitInput.syncColors = action.payload.syncColors; + state.explicitInput.syncCursor = action.payload.syncCursor; + state.explicitInput.syncTooltips = action.payload.syncTooltips; + state.explicitInput.hidePanelTitles = action.payload.hidePanelTitles; + }, + setDescription: ( state: DashboardReduxState, action: PayloadAction @@ -106,29 +129,6 @@ export const dashboardContainerReducers = { state.explicitInput = state.componentState.lastSavedInput; }, - // ------------------------------------------------------------------------------ - // Options Reducers - // ------------------------------------------------------------------------------ - setUseMargins: (state: DashboardReduxState, action: PayloadAction) => { - state.explicitInput.useMargins = action.payload; - }, - - setSyncCursor: (state: DashboardReduxState, action: PayloadAction) => { - state.explicitInput.syncCursor = action.payload; - }, - - setSyncColors: (state: DashboardReduxState, action: PayloadAction) => { - state.explicitInput.syncColors = action.payload; - }, - - setSyncTooltips: (state: DashboardReduxState, action: PayloadAction) => { - state.explicitInput.syncTooltips = action.payload; - }, - - setHidePanelTitles: (state: DashboardReduxState, action: PayloadAction) => { - state.explicitInput.hidePanelTitles = action.payload; - }, - // ------------------------------------------------------------------------------ // Filtering Reducers // ------------------------------------------------------------------------------ @@ -200,4 +200,12 @@ export const dashboardContainerReducers = { setFullScreenMode: (state: DashboardReduxState, action: PayloadAction) => { state.componentState.fullScreenMode = action.payload; }, + + // ------------------------------------------------------------------------------ + // Component state reducers + // ------------------------------------------------------------------------------ + + setHasOverlays: (state: DashboardReduxState, action: PayloadAction) => { + state.componentState.hasOverlays = action.payload; + }, }; diff --git a/src/plugins/dashboard/public/dashboard_container/types.ts b/src/plugins/dashboard/public/dashboard_container/types.ts index 6d09e75671db3..436a6ab0029d8 100644 --- a/src/plugins/dashboard/public/dashboard_container/types.ts +++ b/src/plugins/dashboard/public/dashboard_container/types.ts @@ -8,7 +8,7 @@ import type { ContainerOutput } from '@kbn/embeddable-plugin/public'; import type { ReduxEmbeddableState } from '@kbn/presentation-util-plugin/public'; -import type { DashboardContainerByValueInput } from '../../common/dashboard_container/types'; +import type { DashboardContainerByValueInput, DashboardOptions } from '../../common'; export type DashboardReduxState = ReduxEmbeddableState< DashboardContainerByValueInput, @@ -22,10 +22,13 @@ export type DashboardStateFromSaveModal = Pick< > & Pick; +export type DashboardStateFromSettingsFlyout = DashboardStateFromSaveModal & DashboardOptions; + export interface DashboardPublicState { lastSavedInput: DashboardContainerByValueInput; isEmbeddedExternally?: boolean; hasUnsavedChanges?: boolean; + hasOverlays?: boolean; expandedPanelId?: string; fullScreenMode?: boolean; savedQueryId?: string; diff --git a/test/accessibility/apps/dashboard.ts b/test/accessibility/apps/dashboard.ts index b334563167fcd..37c2bb2ba4586 100644 --- a/test/accessibility/apps/dashboard.ts +++ b/test/accessibility/apps/dashboard.ts @@ -12,6 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home', 'settings']); const a11y = getService('a11y'); const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardSettings = getService('dashboardSettings'); const testSubjects = getService('testSubjects'); const listingTable = getService('listingTable'); @@ -65,18 +66,23 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await a11y.testAppSnapshot(); }); - it('open options menu', async () => { - await PageObjects.dashboard.openOptions(); + it('open settings flyout', async () => { + await PageObjects.dashboard.openSettingsFlyout(); await a11y.testAppSnapshot(); }); it('Should be able to hide panel titles', async () => { - await testSubjects.click('dashboardPanelTitlesCheckbox'); + await dashboardSettings.toggleShowPanelTitles(false); await a11y.testAppSnapshot(); }); it('Should be able display panels without margins', async () => { - await testSubjects.click('dashboardMarginsCheckbox'); + await dashboardSettings.toggleUseMarginsBetweenPanels(true); + await a11y.testAppSnapshot(); + }); + + it('close settings flyout', async () => { + await dashboardSettings.clickCancelButton(); await a11y.testAppSnapshot(); }); diff --git a/test/functional/apps/dashboard/group5/dashboard_options.ts b/test/functional/apps/dashboard/group5/dashboard_options.ts deleted file mode 100644 index 096f8595072bf..0000000000000 --- a/test/functional/apps/dashboard/group5/dashboard_options.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const retry = getService('retry'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'dashboard']); - - describe('dashboard options', () => { - let originalTitles: string[] = []; - - before(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.load( - 'test/functional/fixtures/kbn_archiver/dashboard/current/kibana' - ); - await kibanaServer.uiSettings.replace({ - defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', - }); - await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.preserveCrossAppState(); - await PageObjects.dashboard.loadSavedDashboard('few panels'); - await PageObjects.dashboard.switchToEditMode(); - originalTitles = await PageObjects.dashboard.getPanelTitles(); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - }); - - it('should be able to hide all panel titles', async () => { - await PageObjects.dashboard.checkHideTitle(); - await retry.try(async () => { - const titles = await PageObjects.dashboard.getPanelTitles(); - expect(titles[0]).to.eql(''); - }); - }); - - it('should be able to unhide all panel titles', async () => { - await PageObjects.dashboard.checkHideTitle(); - await retry.try(async () => { - const titles = await PageObjects.dashboard.getPanelTitles(); - expect(titles[0]).to.eql(originalTitles[0]); - }); - }); - }); -} diff --git a/test/functional/apps/dashboard/group5/dashboard_settings.ts b/test/functional/apps/dashboard/group5/dashboard_settings.ts new file mode 100644 index 0000000000000..bbfb867cdf176 --- /dev/null +++ b/test/functional/apps/dashboard/group5/dashboard_settings.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const globalNav = getService('globalNav'); + const kibanaServer = getService('kibanaServer'); + const dashboardSettings = getService('dashboardSettings'); + const PageObjects = getPageObjects(['common', 'dashboard']); + + describe('dashboard settings', () => { + let originalTitles: string[] = []; + + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/dashboard/current/kibana' + ); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.preserveCrossAppState(); + await PageObjects.dashboard.loadSavedDashboard('few panels'); + await PageObjects.dashboard.switchToEditMode(); + originalTitles = await PageObjects.dashboard.getPanelTitles(); + }); + + after(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + it('should be able to hide all panel titles', async () => { + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.toggleShowPanelTitles(false); + await dashboardSettings.clickApplyButton(); + await retry.try(async () => { + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles[0]).to.eql(''); + }); + }); + + it('should be able to unhide all panel titles', async () => { + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.toggleShowPanelTitles(true); + await dashboardSettings.clickApplyButton(); + await retry.try(async () => { + const titles = await PageObjects.dashboard.getPanelTitles(); + expect(titles[0]).to.eql(originalTitles[0]); + }); + }); + + it('should update the title of the dashboard', async () => { + const newTitle = 'My awesome dashboard!!1'; + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.setCustomPanelTitle(newTitle); + await dashboardSettings.clickApplyButton(); + await retry.try(async () => { + expect((await globalNav.getLastBreadcrumb()) === newTitle); + }); + }); + + it('should disable quick save when the settings are open', async () => { + await PageObjects.dashboard.expectQuickSaveButtonEnabled(); + await PageObjects.dashboard.openSettingsFlyout(); + await retry.try(async () => { + await PageObjects.dashboard.expectQuickSaveButtonDisabled(); + }); + await dashboardSettings.clickCancelButton(); + }); + + it('should enable quick save when the settings flyout is closed', async () => { + await PageObjects.dashboard.expectQuickSaveButtonEnabled(); + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.clickCloseFlyoutButton(); + await retry.try(async () => { + await PageObjects.dashboard.expectQuickSaveButtonEnabled(); + }); + }); + + it('should warn when creating a duplicate title', async () => { + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.setCustomPanelTitle('couple panels'); + await dashboardSettings.clickApplyButton(false); + await retry.try(async () => { + await dashboardSettings.expectDuplicateTitleWarningDisplayed(); + }); + await dashboardSettings.clickCancelButton(); + }); + + it('should allow duplicate title if warned once', async () => { + const newTitle = 'couple panels'; + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.setCustomPanelTitle(newTitle); + await dashboardSettings.clickApplyButton(false); + await retry.try(async () => { + await dashboardSettings.expectDuplicateTitleWarningDisplayed(); + }); + await dashboardSettings.clickApplyButton(); + await retry.try(async () => { + expect((await globalNav.getLastBreadcrumb()) === newTitle); + }); + }); + }); +} diff --git a/test/functional/apps/dashboard/group5/index.ts b/test/functional/apps/dashboard/group5/index.ts index f78f7e2d549b8..f8f2f4c2d0df7 100644 --- a/test/functional/apps/dashboard/group5/index.ts +++ b/test/functional/apps/dashboard/group5/index.ts @@ -29,7 +29,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { // This has to be first since the other tests create some embeddables as side affects and our counting assumes // a fresh index. loadTestFile(require.resolve('./empty_dashboard')); - loadTestFile(require.resolve('./dashboard_options')); + loadTestFile(require.resolve('./dashboard_settings')); loadTestFile(require.resolve('./data_shared_attributes')); loadTestFile(require.resolve('./share')); loadTestFile(require.resolve('./embed_mode')); diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index 41a99e046aa42..2fa2290a70a6c 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -393,16 +393,16 @@ export class DashboardPageObject extends FtrService { return this.testSubjects.exists('emptyListPrompt'); } - public async isOptionsOpen() { - this.log.debug('isOptionsOpen'); - return await this.testSubjects.exists('dashboardOptionsMenu'); + public async isSettingsOpen() { + this.log.debug('isSettingsOpen'); + return await this.testSubjects.exists('dashboardSettingsMenu'); } - public async openOptions() { - this.log.debug('openOptions'); - const isOpen = await this.isOptionsOpen(); + public async openSettingsFlyout() { + this.log.debug('openSettingsFlyout'); + const isOpen = await this.isSettingsOpen(); if (!isOpen) { - return await this.testSubjects.click('dashboardOptionsButton'); + return await this.testSubjects.click('dashboardSettingsButton'); } } @@ -414,34 +414,6 @@ export class DashboardPageObject extends FtrService { await this.gotoDashboardLandingPage(); } - public async isMarginsOn() { - this.log.debug('isMarginsOn'); - await this.openOptions(); - return await this.testSubjects.getAttribute('dashboardMarginsCheckbox', 'checked'); - } - - public async useMargins(on = true) { - await this.openOptions(); - const isMarginsOn = await this.isMarginsOn(); - if (isMarginsOn !== 'on') { - return await this.testSubjects.click('dashboardMarginsCheckbox'); - } - } - - public async isColorSyncOn() { - this.log.debug('isColorSyncOn'); - await this.openOptions(); - return await this.testSubjects.getAttribute('dashboardSyncColorsCheckbox', 'checked'); - } - - public async useColorSync(on = true) { - await this.openOptions(); - const isColorSyncOn = await this.isColorSyncOn(); - if (isColorSyncOn !== 'on') { - return await this.testSubjects.click('dashboardSyncColorsCheckbox'); - } - } - public async gotoDashboardEditMode(dashboardName: string) { await this.loadSavedDashboard(dashboardName); await this.switchToEditMode(); @@ -751,12 +723,6 @@ export class DashboardPageObject extends FtrService { }); } - public async checkHideTitle() { - this.log.debug('ensure that you can click on hide title checkbox'); - await this.openOptions(); - return await this.testSubjects.click('dashboardPanelTitlesCheckbox'); - } - public async expectMissingSaveOption() { await this.testSubjects.missingOrFail('dashboardSaveMenuItem'); } @@ -777,6 +743,15 @@ export class DashboardPageObject extends FtrService { } } + public async expectQuickSaveButtonDisabled() { + this.log.debug('expectQuickSaveButtonDisabled'); + const quickSaveButton = await this.testSubjects.find('dashboardQuickSaveMenuItem'); + const isDisabled = await quickSaveButton.getAttribute('disabled'); + if (!isDisabled) { + throw new Error('Quick save button not disabled'); + } + } + public async getNotLoadedVisualizations(vizList: string[]) { const checkList = []; for (const name of vizList) { diff --git a/test/functional/services/dashboard/dashboard_settings.ts b/test/functional/services/dashboard/dashboard_settings.ts new file mode 100644 index 0000000000000..0796444ea7189 --- /dev/null +++ b/test/functional/services/dashboard/dashboard_settings.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function DashboardSettingsProvider({ getService }: FtrProviderContext) { + const log = getService('log'); + const retry = getService('retry'); + const toasts = getService('toasts'); + const testSubjects = getService('testSubjects'); + + return new (class DashboardSettingsPanel { + public readonly FLYOUT_TEST_SUBJ = 'dashboardSettingsFlyout'; + public readonly SYNC_TOOLTIPS_DATA_SUBJ = 'dashboardSyncTooltipsCheckbox'; + + async expectDashboardSettingsFlyoutOpen() { + log.debug('expectDashboardSettingsFlyoutOpen'); + await testSubjects.existOrFail(this.FLYOUT_TEST_SUBJ); + } + + async expectDashboardSettingsFlyoutClosed() { + log.debug('expectDashboardSettingsFlyoutClosed'); + await testSubjects.missingOrFail(this.FLYOUT_TEST_SUBJ); + } + + async expectDuplicateTitleWarningDisplayed() { + log.debug('expectDuplicateTitleWarningDisplayed'); + await testSubjects.existOrFail('duplicateTitleWarningMessage'); + } + + async findFlyout() { + log.debug('findFlyout'); + return await testSubjects.find(this.FLYOUT_TEST_SUBJ); + } + + public async findFlyoutTestSubject(testSubject: string) { + log.debug(`findFlyoutTestSubject::${testSubject}`); + const flyout = await this.findFlyout(); + return await flyout.findByCssSelector(`[data-test-subj="${testSubject}"]`); + } + + public async setCustomPanelTitle(customTitle: string) { + log.debug(`setCustomPanelTitle::${customTitle}`); + await testSubjects.setValue('dashboardTitleInput', customTitle, { + clearWithKeyboard: customTitle === '', // if clearing the title using the empty string as the new value, 'clearWithKeyboard' must be true; otherwise, false + }); + } + + public async setCustomPanelDescription(customDescription: string) { + log.debug(`setCustomPanelDescription::${customDescription}`); + await testSubjects.setValue('dashboardDescriptionInput', customDescription, { + clearWithKeyboard: customDescription === '', // if clearing the description using the empty string as the new value, 'clearWithKeyboard' must be true; otherwise, false + }); + } + + public async toggleStoreTimeWithDashboard(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleStoreTimeWithDashboard::${status}`); + await testSubjects.setEuiSwitch('storeTimeWithDashboard', status); + } + + public async toggleUseMarginsBetweenPanels(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleUseMarginsBetweenPanels::${status}`); + await testSubjects.setEuiSwitch('dashboardMarginsCheckbox', status); + } + + public async toggleShowPanelTitles(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleShowPanelTitles::${status}`); + await testSubjects.setEuiSwitch('dashboardPanelTitlesCheckbox', status); + } + + public async toggleSyncColors(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleSyncColors::${status}`); + await testSubjects.setEuiSwitch('dashboardSyncColorsCheckbox', status); + } + + public async toggleSyncCursor(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleSyncCursor::${status}`); + await testSubjects.setEuiSwitch('dashboardSyncCursorCheckbox', status); + } + + public async isSyncTooltipsEnabled() { + log.debug('isSyncTooltipsEnabled'); + return await testSubjects.isEuiSwitchChecked(this.SYNC_TOOLTIPS_DATA_SUBJ); + } + + public async toggleSyncTooltips(value: boolean) { + const status = value ? 'check' : 'uncheck'; + log.debug(`toggleSyncTooltips::${status}`); + if (await this.isSyncTooltipsEnabled) { + await testSubjects.setEuiSwitch(this.SYNC_TOOLTIPS_DATA_SUBJ, status); + } + } + + public async isShowingDuplicateTitleWarning() { + log.debug('isShowingDuplicateTitleWarning'); + await testSubjects.exists('duplicateTitleWarningMessage'); + } + + public async clickApplyButton(shouldClose: boolean = true) { + log.debug('clickApplyButton'); + await retry.try(async () => { + await toasts.dismissAllToasts(); + await testSubjects.click('applyCustomizeDashboardButton'); + if (shouldClose) await this.expectDashboardSettingsFlyoutClosed(); + }); + } + + public async clickCancelButton() { + log.debug('clickCancelButton'); + await retry.try(async () => { + await toasts.dismissAllToasts(); + await testSubjects.click('cancelCustomizeDashboardButton'); + await this.expectDashboardSettingsFlyoutClosed(); + }); + } + + public async clickCloseFlyoutButton() { + log.debug(); + await retry.try(async () => { + await toasts.dismissAllToasts(); + await (await this.findFlyoutTestSubject('euiFlyoutCloseButton')).click(); + await this.expectDashboardSettingsFlyoutClosed(); + }); + } + })(); +} diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index e13cac581ce52..11975f560e2d7 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -56,6 +56,7 @@ import { MenuToggleService } from './menu_toggle'; import { MonacoEditorService } from './monaco_editor'; import { UsageCollectionService } from './usage_collection'; import { SavedObjectsFinderService } from './saved_objects_finder'; +import { DashboardSettingsProvider } from './dashboard/dashboard_settings'; export const services = { ...commonServiceProviders, @@ -80,6 +81,7 @@ export const services = { dashboardBadgeActions: DashboardBadgeActionsProvider, dashboardDrilldownPanelActions: DashboardDrilldownPanelActionsProvider, dashboardDrilldownsManage: DashboardDrilldownsManageProvider, + dashboardSettings: DashboardSettingsProvider, flyout: FlyoutService, comboBox: ComboBoxService, dataGrid: DataGridService, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 3865eb1d62428..49ae7a52135f0 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -1203,11 +1203,11 @@ "dashboard.topNav.cloneModal.enterNewNameForDashboardDescription": "Veuillez saisir un autre nom pour votre tableau de bord.", "dashboard.topNav.labsButtonAriaLabel": "ateliers", "dashboard.topNav.labsConfigDescription": "Ateliers", - "dashboard.topNav.options.hideAllPanelTitlesSwitchLabel": "Afficher les titres de panneau", - "dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel": "Synchroniser les palettes de couleur de tous les panneaux", - "dashboard.topNav.options.syncCursorBetweenPanelsSwitchLabel": "Synchroniser le curseur de tous les panneaux", - "dashboard.topNav.options.syncTooltipsBetweenPanelsSwitchLabel": "Synchroniser les infobulles de tous les panneaux", - "dashboard.topNav.options.useMarginsBetweenPanelsSwitchLabel": "Utiliser des marges entre les panneaux", + "dashboard.embeddableApi.showSettings.flyout.form.hideAllPanelTitlesSwitchLabel": "Afficher les titres de panneau", + "dashboard.embeddableApi.showSettings.flyout.form.syncColorsBetweenPanelsSwitchLabel": "Synchroniser les palettes de couleur de tous les panneaux", + "dashboard.embeddableApi.showSettings.flyout.form.syncCursorBetweenPanelsSwitchLabel": "Synchroniser le curseur de tous les panneaux", + "dashboard.embeddableApi.showSettings.flyout.form.syncTooltipsBetweenPanelsSwitchLabel": "Synchroniser les infobulles de tous les panneaux", + "dashboard.embeddableApi.showSettings.flyout.form.useMarginsBetweenPanelsSwitchLabel": "Utiliser des marges entre les panneaux", "dashboard.topNav.saveModal.descriptionFormRowLabel": "Description", "dashboard.topNav.saveModal.objectType": "tableau de bord", "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowHelpText": "Le filtre temporel est défini sur l’option sélectionnée chaque fois que ce tableau de bord est chargé.", @@ -1219,8 +1219,6 @@ "dashboard.topNave.editConfigDescription": "Basculer en mode Édition", "dashboard.topNave.fullScreenButtonAriaLabel": "plein écran", "dashboard.topNave.fullScreenConfigDescription": "Mode Plein écran", - "dashboard.topNave.optionsButtonAriaLabel": "options", - "dashboard.topNave.optionsConfigDescription": "Options", "dashboard.topNave.saveAsButtonAriaLabel": "enregistrer sous", "dashboard.topNave.saveAsConfigDescription": "Enregistrer en tant que nouveau tableau de bord", "dashboard.topNave.saveButtonAriaLabel": "enregistrer", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ab041537da4a3..7486c4a79ef67 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1203,11 +1203,11 @@ "dashboard.topNav.cloneModal.enterNewNameForDashboardDescription": "ダッシュボードの新しい名前を入力してください。", "dashboard.topNav.labsButtonAriaLabel": "ラボ", "dashboard.topNav.labsConfigDescription": "ラボ", - "dashboard.topNav.options.hideAllPanelTitlesSwitchLabel": "パネルタイトルを表示", - "dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel": "パネル全体でカラーパレットを同期", - "dashboard.topNav.options.syncCursorBetweenPanelsSwitchLabel": "パネル全体でカーソルを同期", - "dashboard.topNav.options.syncTooltipsBetweenPanelsSwitchLabel": "パネル間でツールチップを同期", - "dashboard.topNav.options.useMarginsBetweenPanelsSwitchLabel": "パネルの間に余白を使用", + "dashboard.embeddableApi.showSettings.flyout.form.hideAllPanelTitlesSwitchLabel": "パネルタイトルを表示", + "dashboard.embeddableApi.showSettings.flyout.form.syncColorsBetweenPanelsSwitchLabel": "パネル全体でカラーパレットを同期", + "dashboard.embeddableApi.showSettings.flyout.form.syncCursorBetweenPanelsSwitchLabel": "パネル全体でカーソルを同期", + "dashboard.embeddableApi.showSettings.flyout.form.syncTooltipsBetweenPanelsSwitchLabel": "パネル間でツールチップを同期", + "dashboard.embeddableApi.showSettings.flyout.form.useMarginsBetweenPanelsSwitchLabel": "パネルの間に余白を使用", "dashboard.topNav.saveModal.descriptionFormRowLabel": "説明", "dashboard.topNav.saveModal.objectType": "ダッシュボード", "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowHelpText": "有効化すると、ダッシュボードが読み込まれるごとに現在選択された時刻の時間フィルターが変更されます。", @@ -1219,8 +1219,6 @@ "dashboard.topNave.editConfigDescription": "編集モードに切り替えます", "dashboard.topNave.fullScreenButtonAriaLabel": "全画面", "dashboard.topNave.fullScreenConfigDescription": "全画面モード", - "dashboard.topNave.optionsButtonAriaLabel": "オプション", - "dashboard.topNave.optionsConfigDescription": "オプション", "dashboard.topNave.saveAsButtonAriaLabel": "名前を付けて保存", "dashboard.topNave.saveAsConfigDescription": "新しいダッシュボードとして保存", "dashboard.topNave.saveButtonAriaLabel": "保存", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 70d733bdcf65f..a9227c99a172d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1203,11 +1203,11 @@ "dashboard.topNav.cloneModal.enterNewNameForDashboardDescription": "请为您的仪表板输入新的名称。", "dashboard.topNav.labsButtonAriaLabel": "实验", "dashboard.topNav.labsConfigDescription": "实验", - "dashboard.topNav.options.hideAllPanelTitlesSwitchLabel": "显示面板标题", - "dashboard.topNav.options.syncColorsBetweenPanelsSwitchLabel": "在面板之间同步调色板", - "dashboard.topNav.options.syncCursorBetweenPanelsSwitchLabel": "在面板之间同步光标", - "dashboard.topNav.options.syncTooltipsBetweenPanelsSwitchLabel": "在面板之间同步工具提示", - "dashboard.topNav.options.useMarginsBetweenPanelsSwitchLabel": "在面板间使用边距", + "dashboard.embeddableApi.showSettings.flyout.form.hideAllPanelTitlesSwitchLabel": "显示面板标题", + "dashboard.embeddableApi.showSettings.flyout.form.syncColorsBetweenPanelsSwitchLabel": "在面板之间同步调色板", + "dashboard.embeddableApi.showSettings.flyout.form.syncCursorBetweenPanelsSwitchLabel": "在面板之间同步光标", + "dashboard.embeddableApi.showSettings.flyout.form.syncTooltipsBetweenPanelsSwitchLabel": "在面板之间同步工具提示", + "dashboard.embeddableApi.showSettings.flyout.form.useMarginsBetweenPanelsSwitchLabel": "在面板间使用边距", "dashboard.topNav.saveModal.descriptionFormRowLabel": "描述", "dashboard.topNav.saveModal.objectType": "仪表板", "dashboard.topNav.saveModal.storeTimeWithDashboardFormRowHelpText": "每次加载此仪表板时,都会将时间筛选更改为当前选定的时间。", @@ -1219,8 +1219,6 @@ "dashboard.topNave.editConfigDescription": "切换到编辑模式", "dashboard.topNave.fullScreenButtonAriaLabel": "全屏", "dashboard.topNave.fullScreenConfigDescription": "全屏模式", - "dashboard.topNave.optionsButtonAriaLabel": "选项", - "dashboard.topNave.optionsConfigDescription": "选项", "dashboard.topNave.saveAsButtonAriaLabel": "另存为", "dashboard.topNave.saveAsConfigDescription": "另存为新仪表板", "dashboard.topNave.saveButtonAriaLabel": "保存", diff --git a/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts index 612f6c44c2c27..fc68346ac5745 100644 --- a/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts +++ b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts @@ -20,6 +20,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'timePicker', ]); const dashboardAddPanel = getService('dashboardAddPanel'); + const dashboardSettings = getService('dashboardSettings'); const filterBar = getService('filterBar'); const elasticChart = getService('elasticChart'); const kibanaServer = getService('kibanaServer'); @@ -87,7 +88,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await filterBar.addFilter({ field: 'geo.src', operation: 'is not', value: 'CN' }); await PageObjects.lens.save('vis2', false, true); - await PageObjects.dashboard.useColorSync(true); + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.toggleSyncColors(true); + await dashboardSettings.clickApplyButton(); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.dashboard.waitForRenderComplete(); @@ -116,7 +119,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should be possible to disable color sync', async () => { - await PageObjects.dashboard.useColorSync(false); + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.toggleSyncColors(false); + await dashboardSettings.clickApplyButton(); await PageObjects.header.waitUntilLoadingHasFinished(); const colorMapping1 = getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(0)); const colorMapping2 = getColorMapping(await PageObjects.dashboard.getPanelChartDebugState(1)); diff --git a/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts b/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts index 37da0d3205c9c..14d59767b35ee 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/dashboard_integration.ts @@ -14,6 +14,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const listingTable = getService('listingTable'); const testSubjects = getService('testSubjects'); + const dashboardSettings = getService('dashboardSettings'); const PageObjects = getPageObjects(['dashboard', 'tagManagement', 'common']); describe('dashboard integration', () => { @@ -161,7 +162,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('retains dashboard saved object tags after quicksave', async () => { // edit and save dashboard await PageObjects.dashboard.gotoDashboardEditMode('dashboard 4 with real data (tag-1)'); - await PageObjects.dashboard.useMargins(false); // turn margins off to cause quicksave to be enabled + await PageObjects.dashboard.openSettingsFlyout(); + await dashboardSettings.toggleUseMarginsBetweenPanels(false); // turn margins off to cause quicksave to be enabled + await dashboardSettings.clickApplyButton(); await PageObjects.dashboard.clickQuickSave(); // verify dashboard still has original tags