Skip to content

Commit fc11f17

Browse files
opensearch-trigger-bot[bot]github-actions[bot]neodescisopensearch-changeset-bot[bot]
authored
Fix add to dashboard after saving (with unit tests) (#9072) (#9311) (#9324)
* Preserve Dashboards scoped history state across URL updates * update/add unit tests * Changeset file for PR #9072 created/updated * update unit tests * update unit tests * use scopedHistoryMock in unit tests --------- (cherry picked from commit 95cfb51) (cherry picked from commit bb54599) Signed-off-by: Nick Steinbaugh <[email protected]> Signed-off-by: Tony Lee <[email protected]> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Nick Steinbaugh <[email protected]> Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
1 parent b07a7c9 commit fc11f17

File tree

6 files changed

+182
-6
lines changed

6 files changed

+182
-6
lines changed

changelogs/fragments/9072.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fix:
2+
- Preserve location state at dashboard app startup to fix adding a new visualization ([#9072](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9072))

src/plugins/dashboard/public/application/components/dashboard_top_nav/__snapshots__/dashboard_top_nav.test.tsx.snap

Lines changed: 120 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/dashboard/public/application/utils/create_dashboard_app_state.test.tsx

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { createDashboardServicesMock } from './mocks';
1717
import { SavedObjectDashboard } from '../..';
1818
import { syncQueryStateWithUrl } from 'src/plugins/data/public';
1919
import { ViewMode } from 'src/plugins/embeddable/public';
20+
import { scopedHistoryMock } from '../../../../../core/public/mocks';
2021

2122
const mockStartStateSync = jest.fn();
2223
const mockStopStateSync = jest.fn();
@@ -48,7 +49,7 @@ const { createStateContainer, syncState } = jest.requireMock(
4849
const osdUrlStateStorage = ({
4950
set: jest.fn(),
5051
get: jest.fn(() => ({ linked: false })),
51-
flush: jest.fn(),
52+
flush: jest.fn().mockReturnValue(true),
5253
} as unknown) as IOsdUrlStateStorage;
5354

5455
describe('createDashboardGlobalAndAppState', () => {
@@ -148,13 +149,47 @@ describe('updateStateUrl', () => {
148149
...dashboardAppStateStub,
149150
viewMode: ViewMode.VIEW,
150151
};
151-
updateStateUrl({ osdUrlStateStorage, state: dashboardAppState, replace: true });
152152

153153
test('update URL to not contain panels', () => {
154154
const { panels, ...statesWithoutPanels } = dashboardAppState;
155+
156+
const basePath = '/base';
157+
const history = scopedHistoryMock.create({
158+
pathname: basePath,
159+
});
160+
161+
updateStateUrl({
162+
osdUrlStateStorage,
163+
state: dashboardAppState,
164+
scopedHistory: history,
165+
replace: true,
166+
});
167+
155168
expect(osdUrlStateStorage.set).toHaveBeenCalledWith('_a', statesWithoutPanels, {
156169
replace: true,
157170
});
158171
expect(osdUrlStateStorage.flush).toHaveBeenCalledWith({ replace: true });
159172
});
173+
174+
test('preserve Dashboards scoped history state', () => {
175+
const basePath = '/base';
176+
const someState = { some: 'state' };
177+
const history = scopedHistoryMock.create({
178+
pathname: basePath,
179+
state: someState,
180+
});
181+
const { location } = history;
182+
const replaceSpy = jest.spyOn(history, 'replace');
183+
184+
const changed = updateStateUrl({
185+
osdUrlStateStorage,
186+
state: dashboardAppState,
187+
scopedHistory: history,
188+
replace: true,
189+
});
190+
191+
expect(history.location.state).toEqual(someState);
192+
expect(changed).toBe(true);
193+
expect(replaceSpy).toHaveBeenCalledWith({ ...location, state: someState });
194+
});
160195
});

src/plugins/dashboard/public/application/utils/create_dashboard_app_state.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6+
import { ScopedHistory } from 'src/core/public';
67
import { migrateAppState } from '../utils/migrate_app_state';
78
import {
89
IOsdUrlStateStorage,
@@ -40,13 +41,14 @@ export const createDashboardGlobalAndAppState = ({
4041
opensearchDashboardsVersion,
4142
usageCollection,
4243
history,
44+
scopedHistory,
4345
data: { query },
4446
} = services;
4547

46-
/*
48+
/*
4749
Function migrateAppState() does two things
4850
1. Migrate panel before version 7.3.0 to the 7.3.0 panel structure.
49-
There are no changes to the panel structure after version 7.3.0 to the current
51+
There are no changes to the panel structure after version 7.3.0 to the current
5052
OpenSearch version so no need to migrate panels that are version 7.3.0 or higher
5153
2. Update the version number on each panel to the current version.
5254
*/
@@ -131,7 +133,7 @@ export const createDashboardGlobalAndAppState = ({
131133
osdUrlStateStorage
132134
);
133135

134-
updateStateUrl({ osdUrlStateStorage, state: initialState, replace: true });
136+
updateStateUrl({ osdUrlStateStorage, state: initialState, scopedHistory, replace: true });
135137
// start syncing the appState with the ('_a') url
136138
startStateSync();
137139
return { stateContainer, stopStateSync, stopSyncingQueryServiceStateWithUrl };
@@ -147,15 +149,26 @@ export const createDashboardGlobalAndAppState = ({
147149
export const updateStateUrl = ({
148150
osdUrlStateStorage,
149151
state,
152+
scopedHistory,
150153
replace,
151154
}: {
152155
osdUrlStateStorage: IOsdUrlStateStorage;
153156
state: DashboardAppState;
157+
scopedHistory: ScopedHistory;
154158
replace: boolean;
155159
}) => {
156160
osdUrlStateStorage.set(APP_STATE_STORAGE_KEY, toUrlState(state), { replace });
157161
// immediately forces scheduled updates and changes location
158-
return osdUrlStateStorage.flush({ replace });
162+
// scoped history state is preserved to allow embeddable state transfer
163+
const previousState = scopedHistory.location.state;
164+
const changed = osdUrlStateStorage.flush({ replace });
165+
if (changed) {
166+
scopedHistory.replace({
167+
...scopedHistory.location,
168+
state: previousState,
169+
});
170+
}
171+
return changed;
159172
};
160173

161174
const toUrlState = (state: DashboardAppState): DashboardAppStateInUrl => {

src/plugins/dashboard/public/application/utils/mocks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { dashboardPluginMock } from '../../../../dashboard/public/mocks';
99
import { usageCollectionPluginMock } from '../../../../usage_collection/public/mocks';
1010
import { embeddablePluginMock } from '../../../../embeddable/public/mocks';
1111
import { DashboardServices } from '../../types';
12+
import { scopedHistoryMock } from '../../../../../core/public/mocks';
13+
import { ScopedHistory } from '../../../../../core/public';
1214

1315
export const createDashboardServicesMock = () => {
1416
const coreStartMock = coreMock.createStart();
@@ -18,6 +20,7 @@ export const createDashboardServicesMock = () => {
1820
const usageCollection = usageCollectionPluginMock.createSetupContract();
1921
const embeddable = embeddablePluginMock.createStartContract();
2022
const opensearchDashboardsVersion = '3.0.0';
23+
const scopedHistory = (scopedHistoryMock.create() as unknown) as ScopedHistory;
2124

2225
return ({
2326
...coreStartMock,
@@ -27,6 +30,7 @@ export const createDashboardServicesMock = () => {
2730
replace: jest.fn(),
2831
location: { pathname: '' },
2932
},
33+
scopedHistory,
3034
dashboardConfig: {
3135
getHideWriteControls: jest.fn(),
3236
},

src/plugins/dashboard/public/application/utils/use/use_dashboard_app_state.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const useDashboardAppAndGlobalState = ({
5454
usageCollection,
5555
opensearchDashboardsVersion,
5656
osdUrlStateStorage,
57+
scopedHistory,
5758
} = services;
5859
const hideWriteControls = dashboardConfig.getHideWriteControls();
5960
const stateDefaults = migrateAppState(
@@ -136,6 +137,7 @@ export const useDashboardAppAndGlobalState = ({
136137
const updated = updateStateUrl({
137138
osdUrlStateStorage,
138139
state: stateContainer.getState(),
140+
scopedHistory,
139141
replace,
140142
});
141143

0 commit comments

Comments
 (0)