Change folder breadcrumb on folder change in general settings (#86342)

* Change folder breadcrumb on folder change in general settings

* tests and refactor

* refactor to fix broken tests

* fix test
This commit is contained in:
Victor Marin 2024-04-19 13:21:40 +03:00 committed by GitHub
parent f9a8e34b32
commit 60e6dd56bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 22 deletions

View File

@ -1,8 +1,6 @@
import { locationUtil } from '@grafana/data';
import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime';
import { updateNavIndex } from 'app/core/actions';
import { StateManagerBase } from 'app/core/services/StateManagerBase';
import { backendSrv } from 'app/core/services/backend_srv';
import { default as localStorageStore } from 'app/core/store';
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
@ -10,8 +8,6 @@ import {
DASHBOARD_FROM_LS_KEY,
removeDashboardToFetchFromLocalStorage,
} from 'app/features/dashboard/state/initDashboard';
import { buildNavModel } from 'app/features/folders/state/navModel';
import { store } from 'app/store/store';
import { DashboardDTO, DashboardRoutes } from 'app/types';
import { PanelEditor } from '../panel-edit/PanelEditor';
@ -19,6 +15,8 @@ import { DashboardScene } from '../scene/DashboardScene';
import { buildNewDashboardSaveModel } from '../serialization/buildNewDashboardSaveModel';
import { transformSaveModelToScene } from '../serialization/transformSaveModelToScene';
import { updateNavModel } from './utils';
export interface DashboardScenePageState {
dashboard?: DashboardScene;
panelEditor?: PanelEditor;
@ -127,7 +125,9 @@ export class DashboardScenePageStateManager extends StateManagerBase<DashboardSc
}
// Populate nav model in global store according to the folder
await this.initNavModel(rsp);
if (rsp.meta.folderUid) {
await updateNavModel(rsp.meta.folderUid);
}
// Do not cache new dashboards
this.dashboardCache = { dashboard: rsp, ts: Date.now(), cacheKey };
@ -235,20 +235,6 @@ export class DashboardScenePageStateManager extends StateManagerBase<DashboardSc
return null;
}
private async initNavModel(dashboard: DashboardDTO) {
// only the folder API has information about ancestors
// get parent folder (if it exists) and put it in the store
// this will be used to populate the full breadcrumb trail
if (dashboard.meta.folderUid) {
try {
const folder = await backendSrv.getFolderByUid(dashboard.meta.folderUid);
store.dispatch(updateNavIndex(buildNavModel(folder)));
} catch (err) {
console.warn('Error fetching parent folder', dashboard.meta.folderUid, 'for dashboard', err);
}
}
}
public clearState() {
getDashboardSrv().setCurrent(undefined);

View File

@ -0,0 +1,32 @@
import { backendSrv } from 'app/core/services/backend_srv';
import { configureStore } from 'app/store/configureStore';
import { updateNavModel } from './utils';
describe('utils', () => {
it('Should update nav model', async () => {
const reduxStore = configureStore();
jest.spyOn(backendSrv, 'getFolderByUid').mockResolvedValue({
id: 1,
uid: 'new-folder',
title: 'NewFolder',
url: '',
canAdmin: true,
canDelete: true,
canEdit: true,
canSave: true,
created: '',
createdBy: '',
hasAcl: false,
updated: '',
updatedBy: '',
});
expect(reduxStore.getState().navIndex[`folder-dashboards-new-folder`]).toBeUndefined();
await updateNavModel('new-folder');
expect(reduxStore.getState().navIndex[`folder-dashboards-new-folder`]).not.toBeUndefined();
});
});

View File

@ -0,0 +1,13 @@
import { updateNavIndex } from 'app/core/actions';
import { backendSrv } from 'app/core/services/backend_srv';
import { buildNavModel } from 'app/features/folders/state/navModel';
import { store } from 'app/store/store';
export async function updateNavModel(folderUid: string) {
try {
const folder = await backendSrv.getFolderByUid(folderUid);
store.dispatch(updateNavIndex(buildNavModel(folder)));
} catch (err) {
console.warn('Error fetching parent folder', folderUid, 'for dashboard', err);
}
}

View File

@ -1,6 +1,7 @@
import { behaviors, SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
import { DashboardCursorSync } from '@grafana/schema';
import * as utils from '../pages/utils';
import { DashboardControls } from '../scene/DashboardControls';
import { DashboardScene } from '../scene/DashboardScene';
import { activateFullSceneTree } from '../utils/test-utils';
@ -89,11 +90,14 @@ describe('GeneralSettingsEditView', () => {
expect(settings.getRefreshPicker()?.state?.intervals).toEqual(['5s']);
});
it('A change to folder updates the dashboard state', () => {
settings.onFolderChange('folder-2', 'folder 2');
it('A change to folder updates the dashboard state', async () => {
const updateNavModel = jest.spyOn(utils, 'updateNavModel').mockImplementation(jest.fn());
await settings.onFolderChange('folder-2', 'folder 2');
expect(dashboard.state.meta.folderUid).toBe('folder-2');
expect(dashboard.state.meta.folderTitle).toBe('folder 2');
expect(updateNavModel).toHaveBeenCalledWith('folder-2');
});
it('A change to tooltip settings updates the dashboard state', () => {

View File

@ -23,6 +23,7 @@ import { DeleteDashboardButton } from 'app/features/dashboard/components/DeleteD
import { GenAIDashDescriptionButton } from 'app/features/dashboard/components/GenAI/GenAIDashDescriptionButton';
import { GenAIDashTitleButton } from 'app/features/dashboard/components/GenAI/GenAIDashTitleButton';
import { updateNavModel } from '../pages/utils';
import { DashboardScene } from '../scene/DashboardScene';
import { NavToolbarActions } from '../scene/NavToolbarActions';
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
@ -96,13 +97,17 @@ export class GeneralSettingsEditView
this._dashboard.setState({ tags: value });
};
public onFolderChange = (newUID: string | undefined, newTitle: string | undefined) => {
public onFolderChange = async (newUID: string | undefined, newTitle: string | undefined) => {
const newMeta = {
...this._dashboard.state.meta,
folderUid: newUID || this._dashboard.state.meta.folderUid,
folderTitle: newTitle || this._dashboard.state.meta.folderTitle,
};
if (newMeta.folderUid) {
await updateNavModel(newMeta.folderUid);
}
this._dashboard.setState({ meta: newMeta });
};