diff --git a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx index e5b467a4181770..8ab2a458d78e02 100644 --- a/src/plugins/dashboard/public/application/dashboard_app_controller.tsx +++ b/src/plugins/dashboard/public/application/dashboard_app_controller.tsx @@ -359,10 +359,6 @@ export class DashboardAppController { incomingEmbeddable = undefined; } - let expandedPanelId; - if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) { - expandedPanelId = dashboardContainer.getInput().expandedPanelId; - } const shouldShowEditHelp = getShouldShowEditHelp(); const shouldShowViewHelp = getShouldShowViewHelp(); const isEmptyInReadonlyMode = shouldShowUnauthorizedEmptyState(); @@ -384,7 +380,7 @@ export class DashboardAppController { lastReloadRequestTime, title: dashboardStateManager.getTitle(), description: dashboardStateManager.getDescription(), - expandedPanelId, + expandedPanelId: dashboardStateManager.getExpandedPanelId(), }; }; diff --git a/src/plugins/dashboard/public/application/dashboard_state.test.ts b/src/plugins/dashboard/public/application/dashboard_state.test.ts index e32bb9b9ecabee..42425ebf2cacf2 100644 --- a/src/plugins/dashboard/public/application/dashboard_state.test.ts +++ b/src/plugins/dashboard/public/application/dashboard_state.test.ts @@ -23,6 +23,9 @@ import { getSavedDashboardMock } from './test_helpers'; import { InputTimeRange, TimefilterContract, TimeRange } from 'src/plugins/data/public'; import { ViewMode } from 'src/plugins/embeddable/public'; import { createKbnUrlStateStorage } from 'src/plugins/kibana_utils/public'; +import { DashboardContainer, DashboardContainerInput } from '.'; +import { DashboardContainerOptions } from './embeddable/dashboard_container'; +import { embeddablePluginMock } from '../../../embeddable/public/mocks'; describe('DashboardState', function () { let dashboardState: DashboardStateManager; @@ -48,6 +51,23 @@ describe('DashboardState', function () { }); } + function initDashboardContainer(initialInput?: Partial) { + const { doStart } = embeddablePluginMock.createInstance(); + const defaultInput: DashboardContainerInput = { + id: '123', + viewMode: ViewMode.EDIT, + filters: [] as DashboardContainerInput['filters'], + query: {} as DashboardContainerInput['query'], + timeRange: {} as DashboardContainerInput['timeRange'], + useMargins: true, + title: 'ultra awesome test dashboard', + isFullScreenMode: false, + panels: {} as DashboardContainerInput['panels'], + }; + const input = { ...defaultInput, ...(initialInput ?? {}) }; + return new DashboardContainer(input, { embeddable: doStart() } as DashboardContainerOptions); + } + describe('syncTimefilterWithDashboard', function () { test('syncs quick time', function () { savedDashboard.timeRestore = true; @@ -95,6 +115,43 @@ describe('DashboardState', function () { }); }); + describe('Dashboard Container Changes', () => { + beforeEach(() => { + initDashboardState(); + }); + + test('expanedPanelId in container input casues state update', () => { + dashboardState.setExpandedPanelId = jest.fn(); + + const dashboardContainer = initDashboardContainer({ + expandedPanelId: 'theCoolestPanelOnThisDashboard', + }); + + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledWith( + 'theCoolestPanelOnThisDashboard' + ); + }); + + test('expanedPanelId is not updated when it is the same', () => { + dashboardState.setExpandedPanelId = jest + .fn() + .mockImplementation(dashboardState.setExpandedPanelId); + + const dashboardContainer = initDashboardContainer({ + expandedPanelId: 'theCoolestPanelOnThisDashboard', + }); + + dashboardState.handleDashboardContainerChanges(dashboardContainer); + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(1); + + dashboardContainer.updateInput({ expandedPanelId: 'woah it changed' }); + dashboardState.handleDashboardContainerChanges(dashboardContainer); + expect(dashboardState.setExpandedPanelId).toHaveBeenCalledTimes(2); + }); + }); + describe('isDirty', function () { beforeAll(() => { initDashboardState(); diff --git a/src/plugins/dashboard/public/application/dashboard_state_manager.ts b/src/plugins/dashboard/public/application/dashboard_state_manager.ts index 910a2b470b2eb0..93a63b0535259f 100644 --- a/src/plugins/dashboard/public/application/dashboard_state_manager.ts +++ b/src/plugins/dashboard/public/application/dashboard_state_manager.ts @@ -267,6 +267,10 @@ export class DashboardStateManager { this.setFullScreenMode(input.isFullScreenMode); } + if (input.expandedPanelId !== this.getExpandedPanelId()) { + this.setExpandedPanelId(input.expandedPanelId); + } + if (!_.isEqual(input.query, this.getQuery())) { this.setQuery(input.query); } @@ -282,6 +286,14 @@ export class DashboardStateManager { this.stateContainer.transitions.set('fullScreenMode', fullScreenMode); } + public getExpandedPanelId() { + return this.appState.expandedPanelId; + } + + public setExpandedPanelId(expandedPanelId?: string) { + this.stateContainer.transitions.set('expandedPanelId', expandedPanelId); + } + public setFilters(filters: Filter[]) { this.stateContainer.transitions.set('filters', filters); } diff --git a/src/plugins/dashboard/public/types.ts b/src/plugins/dashboard/public/types.ts index 21c6bbc1bfc515..2764f4b075579d 100644 --- a/src/plugins/dashboard/public/types.ts +++ b/src/plugins/dashboard/public/types.ts @@ -89,6 +89,7 @@ export interface DashboardAppState { query: Query | string; filters: Filter[]; viewMode: ViewMode; + expandedPanelId?: string; savedQuery?: string; } diff --git a/test/functional/apps/dashboard/panel_expand_toggle.js b/test/functional/apps/dashboard/panel_expand_toggle.js index e3343f29922e25..7fe3f87918e573 100644 --- a/test/functional/apps/dashboard/panel_expand_toggle.js +++ b/test/functional/apps/dashboard/panel_expand_toggle.js @@ -21,6 +21,7 @@ import expect from '@kbn/expect'; export default function ({ getService, getPageObjects }) { const retry = getService('retry'); + const browser = getService('browser'); const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const dashboardPanelActions = getService('dashboardPanelActions'); @@ -61,5 +62,18 @@ export default function ({ getService, getPageObjects }) { expect(panelCountAfterMaxThenMinimize).to.be(panelCount); }); }); + + it('minimizes using the browser back button', async () => { + const panelCount = await PageObjects.dashboard.getPanelCount(); + + await dashboardPanelActions.openContextMenu(); + await dashboardPanelActions.clickExpandPanelToggle(); + + await browser.goBack(); + await retry.try(async () => { + const panelCountAfterMaxThenMinimize = await PageObjects.dashboard.getPanelCount(); + expect(panelCountAfterMaxThenMinimize).to.be(panelCount); + }); + }); }); }