mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboard: Select the last used data source by default when adding a panel to a dashboard (#71777)
Co-authored-by: Juan Cabanas <juan.cabanas@grafana.com>
This commit is contained in:
parent
6f0d3830b0
commit
3fda30194c
@ -4,9 +4,16 @@ import { DataQuery, getDataSourceRef } from '@grafana/data';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||
import { QueryGroup } from 'app/features/query/components/QueryGroup';
|
||||
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
||||
import { QueryGroupDataSource, QueryGroupOptions } from 'app/types';
|
||||
|
||||
import { getDashboardSrv } from '../../services/DashboardSrv';
|
||||
import { PanelModel } from '../../state';
|
||||
import {
|
||||
getLastUsedDatasourceFromStorage,
|
||||
initLastUsedDatasourceKeyForDashboard,
|
||||
setLastUsedDatasourceKeyForDashboard,
|
||||
} from '../../utils/dashboard';
|
||||
|
||||
interface Props {
|
||||
/** Current panel */
|
||||
@ -20,12 +27,28 @@ export class PanelEditorQueries extends PureComponent<Props> {
|
||||
super(props);
|
||||
}
|
||||
|
||||
// store last used datasource in local storage
|
||||
updateLastUsedDatasource = (datasource: QueryGroupDataSource) => {
|
||||
if (!datasource.uid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dashboardUid = getDashboardSrv().getCurrent()?.uid ?? '';
|
||||
// if datasource is MIXED reset datasource uid in storage, because Mixed datasource can contain multiple ds
|
||||
if (datasource.uid === MIXED_DATASOURCE_NAME) {
|
||||
return initLastUsedDatasourceKeyForDashboard(dashboardUid!);
|
||||
}
|
||||
setLastUsedDatasourceKeyForDashboard(dashboardUid, datasource.uid);
|
||||
};
|
||||
|
||||
buildQueryOptions(panel: PanelModel): QueryGroupOptions {
|
||||
const dataSource: QueryGroupDataSource = panel.datasource ?? {
|
||||
default: true,
|
||||
};
|
||||
const datasourceSettings = getDatasourceSrv().getInstanceSettings(dataSource);
|
||||
|
||||
// store last datasource used in local storage
|
||||
this.updateLastUsedDatasource(dataSource);
|
||||
return {
|
||||
cacheTimeout: datasourceSettings?.meta.queryOptions?.cacheTimeout ? panel.cacheTimeout : undefined,
|
||||
dataSource: {
|
||||
@ -51,7 +74,20 @@ export class PanelEditorQueries extends PureComponent<Props> {
|
||||
// If the panel model has no datasource property load the default data source property and update the persisted model
|
||||
// Because this part of the panel model is not in redux yet we do a forceUpdate.
|
||||
if (!panel.datasource) {
|
||||
const ds = getDatasourceSrv().getInstanceSettings(null);
|
||||
let ds;
|
||||
// check if we have last used datasource from local storage
|
||||
// get dashboard uid
|
||||
const dashboardUid = getDashboardSrv().getCurrent()?.uid ?? '';
|
||||
const lastUsedDatasource = getLastUsedDatasourceFromStorage(dashboardUid!);
|
||||
// do we have a last used datasource for this dashboard
|
||||
if (lastUsedDatasource?.datasourceUid !== null) {
|
||||
// get datasource from uid
|
||||
ds = getDatasourceSrv().getInstanceSettings(lastUsedDatasource?.datasourceUid);
|
||||
}
|
||||
// else load default datasource
|
||||
if (!ds) {
|
||||
ds = getDatasourceSrv().getInstanceSettings(null);
|
||||
}
|
||||
panel.datasource = getDataSourceRef(ds!);
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import { saveDashboard as saveDashboardApiCall } from 'app/features/manage-dashb
|
||||
import { useDispatch } from 'app/types';
|
||||
import { DashboardSavedEvent } from 'app/types/events';
|
||||
|
||||
import { updateDashboardUidLastUsedDatasource } from '../../utils/dashboard';
|
||||
|
||||
import { SaveDashboardOptions } from './types';
|
||||
|
||||
const saveDashboard = async (
|
||||
@ -60,6 +62,10 @@ export const useDashboardSave = (dashboard: DashboardModel, isCopy = false) => {
|
||||
// important that these happen before location redirect below
|
||||
appEvents.publish(new DashboardSavedEvent());
|
||||
notifyApp.success('Dashboard saved');
|
||||
|
||||
//Update local storage dashboard to handle things like last used datasource
|
||||
updateDashboardUidLastUsedDatasource(result.uid);
|
||||
|
||||
if (isCopy) {
|
||||
reportInteraction('grafana_dashboard_copied', {
|
||||
name: dashboard.title,
|
||||
|
78
public/app/features/dashboard/utils/dashboard.test.ts
Normal file
78
public/app/features/dashboard/utils/dashboard.test.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import {
|
||||
updateDashboardUidLastUsedDatasource,
|
||||
getLastUsedDatasourceFromStorage,
|
||||
initLastUsedDatasourceKeyForDashboard,
|
||||
setLastUsedDatasourceKeyForDashboard,
|
||||
} from './dashboard'; // Replace with the path to your actual module
|
||||
|
||||
// Mock the store module
|
||||
jest.mock('app/core/store', () => ({
|
||||
exists: jest.fn(),
|
||||
getObject: jest.fn(),
|
||||
setObject: jest.fn(),
|
||||
}));
|
||||
|
||||
const store = jest.requireMock('app/core/store');
|
||||
|
||||
describe('Last Used Datasource Local Storage', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should retrieve the last used datasource', () => {
|
||||
store.exists.mockReturnValue(true);
|
||||
store.getObject.mockReturnValue({
|
||||
dashboardUid: '123',
|
||||
datasourceUid: 'datasource1',
|
||||
});
|
||||
|
||||
const result = getLastUsedDatasourceFromStorage('123');
|
||||
expect(result).toEqual({ dashboardUid: '123', datasourceUid: 'datasource1' });
|
||||
});
|
||||
|
||||
it('should update only the dashboard UID', () => {
|
||||
store.exists.mockReturnValue(true);
|
||||
store.getObject.mockReturnValue({
|
||||
dashboardUid: '456',
|
||||
datasourceUid: 'datasource2',
|
||||
});
|
||||
|
||||
updateDashboardUidLastUsedDatasource('789');
|
||||
expect(store.setObject).toHaveBeenCalledWith('grafana.dashboards.panelEdit.lastUsedDatasource', {
|
||||
dashboardUid: '789',
|
||||
datasourceUid: 'datasource2',
|
||||
});
|
||||
});
|
||||
|
||||
it('should initialize local storage for a dashboard with empty datasource UID', () => {
|
||||
initLastUsedDatasourceKeyForDashboard('999');
|
||||
expect(store.setObject).toHaveBeenCalledWith('grafana.dashboards.panelEdit.lastUsedDatasource', {
|
||||
dashboardUid: '999',
|
||||
datasourceUid: '',
|
||||
});
|
||||
});
|
||||
|
||||
it('should set a new datasource UID and dashboard UID for a dashboard', () => {
|
||||
store.exists.mockReturnValue(false);
|
||||
|
||||
setLastUsedDatasourceKeyForDashboard('111', 'datasource3');
|
||||
expect(store.setObject).toHaveBeenCalledWith('grafana.dashboards.panelEdit.lastUsedDatasource', {
|
||||
dashboardUid: '111',
|
||||
datasourceUid: 'datasource3',
|
||||
});
|
||||
});
|
||||
|
||||
it('should update the datasource UID while keeping the existing dashboard UID', () => {
|
||||
store.exists.mockReturnValue(true);
|
||||
store.getObject.mockReturnValue({
|
||||
dashboardUid: '222',
|
||||
datasourceUid: 'datasource4',
|
||||
});
|
||||
|
||||
setLastUsedDatasourceKeyForDashboard('222', 'datasource5');
|
||||
expect(store.setObject).toHaveBeenCalledWith('grafana.dashboards.panelEdit.lastUsedDatasource', {
|
||||
dashboardUid: '222',
|
||||
datasourceUid: 'datasource5',
|
||||
});
|
||||
});
|
||||
});
|
@ -104,3 +104,60 @@ export function getCopiedPanelPlugin(): (PanelPluginMeta & PanelPluginInfo) | un
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
type LastUsedDatasource =
|
||||
| {
|
||||
dashboardUid: string;
|
||||
datasourceUid: string;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
const PANEL_EDIT_LAST_USED_DATASOURCE = 'grafana.dashboards.panelEdit.lastUsedDatasource';
|
||||
|
||||
// Function that returns last used datasource from local storage
|
||||
export function getLastUsedDatasourceFromStorage(dashboardUid: string): LastUsedDatasource {
|
||||
// Check if user has any local storage associated with this dashboard
|
||||
if (store.exists(PANEL_EDIT_LAST_USED_DATASOURCE)) {
|
||||
const lastUsedDatasource: LastUsedDatasource = store.getObject(PANEL_EDIT_LAST_USED_DATASOURCE);
|
||||
if (lastUsedDatasource?.dashboardUid === dashboardUid) {
|
||||
return lastUsedDatasource;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Function that updates local storage with new dashboard uid and keeps existing datasource
|
||||
export function updateDashboardUidLastUsedDatasource(dashUid: string) {
|
||||
// Check if user has any datasource uid in local storage
|
||||
if (!store.exists(PANEL_EDIT_LAST_USED_DATASOURCE)) {
|
||||
return;
|
||||
}
|
||||
const oldRegistryLastUsedDatasource: LastUsedDatasource = store.getObject(PANEL_EDIT_LAST_USED_DATASOURCE);
|
||||
//keep existing datasource uid
|
||||
const datasourceUid = oldRegistryLastUsedDatasource?.datasourceUid ?? '';
|
||||
updatePropsLastUsedDatasourceKey(dashUid, datasourceUid);
|
||||
}
|
||||
|
||||
// Function that updates local storage with new dashboard uid and resets datasource to empty
|
||||
export function initLastUsedDatasourceKeyForDashboard(dashboardUid: string | undefined) {
|
||||
store.setObject(PANEL_EDIT_LAST_USED_DATASOURCE, { dashboardUid: dashboardUid, datasourceUid: '' });
|
||||
}
|
||||
|
||||
// Function that updates local storage with new datasource uid and keeps existing dashboard when there is dash uid key in local storage
|
||||
// or sets new local storage with new dashboard uid and existing datasource
|
||||
export function setLastUsedDatasourceKeyForDashboard(dashUid: string, dsUid: string) {
|
||||
// Check if user has any datasource uid in local storage
|
||||
const lastUsedDatasource = getLastUsedDatasourceFromStorage(dashUid);
|
||||
if (!lastUsedDatasource) {
|
||||
updatePropsLastUsedDatasourceKey(dashUid, dsUid);
|
||||
} else {
|
||||
// set new local storage with new dashboard uid and existing datasource
|
||||
const dashboardUid = lastUsedDatasource?.dashboardUid ?? '';
|
||||
updatePropsLastUsedDatasourceKey(dashboardUid, dsUid);
|
||||
}
|
||||
}
|
||||
|
||||
// Function that updates local storage with new dashboard uid and datasource uid
|
||||
function updatePropsLastUsedDatasourceKey(dashboardUid: string | undefined, datasourceUid: string) {
|
||||
store.setObject(PANEL_EDIT_LAST_USED_DATASOURCE, { dashboardUid: dashboardUid, datasourceUid: datasourceUid });
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user