mirror of
https://github.com/grafana/grafana.git
synced 2024-11-24 09:50:29 -06:00
Preferences: Use dashboardUID to set the home dashboard (#51919)
This commit is contained in:
parent
c7f8c2a7e1
commit
2ec01c8d08
@ -3144,7 +3144,8 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
"public/app/core/components/SharedPreferences/SharedPreferences.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
],
|
||||
"public/app/core/components/TagFilter/TagBadge.tsx:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
|
@ -25,20 +25,32 @@ jest.mock('@grafana/runtime', () => {
|
||||
jest.mock('app/core/services/backend_srv', () => {
|
||||
return {
|
||||
backendSrv: {
|
||||
getDashboardByUid: jest.fn().mockResolvedValue({
|
||||
dashboard: {
|
||||
id: 2,
|
||||
title: 'My Dashboard',
|
||||
uid: 'myDash',
|
||||
templating: {
|
||||
list: [],
|
||||
},
|
||||
panels: [],
|
||||
},
|
||||
meta: {},
|
||||
}),
|
||||
search: jest.fn().mockResolvedValue([
|
||||
{
|
||||
id: 2,
|
||||
title: 'My Dashboard',
|
||||
tags: [],
|
||||
type: '',
|
||||
uid: '',
|
||||
uid: 'myDash',
|
||||
uri: '',
|
||||
url: '',
|
||||
folderId: 0,
|
||||
folderTitle: '',
|
||||
folderUid: '',
|
||||
folderUrl: '',
|
||||
isStarred: false,
|
||||
isStarred: true,
|
||||
slug: '',
|
||||
items: [],
|
||||
},
|
||||
@ -47,14 +59,14 @@ jest.mock('app/core/services/backend_srv', () => {
|
||||
title: 'Another Dashboard',
|
||||
tags: [],
|
||||
type: '',
|
||||
uid: '',
|
||||
uid: 'anotherDash',
|
||||
uri: '',
|
||||
url: '',
|
||||
folderId: 0,
|
||||
folderTitle: '',
|
||||
folderUid: '',
|
||||
folderUrl: '',
|
||||
isStarred: false,
|
||||
isStarred: true,
|
||||
slug: '',
|
||||
items: [],
|
||||
},
|
||||
@ -67,7 +79,7 @@ const mockPreferences: UserPreferencesDTO = {
|
||||
timezone: 'browser',
|
||||
weekStart: 'monday',
|
||||
theme: 'light',
|
||||
homeDashboardId: 2,
|
||||
homeDashboardUID: 'myDash',
|
||||
queryHistory: {
|
||||
homeTab: '',
|
||||
},
|
||||
@ -159,7 +171,7 @@ describe('SharedPreferences', () => {
|
||||
timezone: 'Australia/Sydney',
|
||||
weekStart: 'saturday',
|
||||
theme: 'dark',
|
||||
homeDashboardId: 3,
|
||||
homeDashboardUID: 'anotherDash',
|
||||
queryHistory: {
|
||||
homeTab: '',
|
||||
},
|
||||
@ -181,7 +193,7 @@ describe('SharedPreferences', () => {
|
||||
timezone: 'browser',
|
||||
weekStart: '',
|
||||
theme: '',
|
||||
homeDashboardId: 0,
|
||||
homeDashboardUID: undefined,
|
||||
queryHistory: {
|
||||
homeTab: '',
|
||||
},
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import { PreferencesService } from 'app/core/services/PreferencesService';
|
||||
import { backendSrv } from 'app/core/services/backend_srv';
|
||||
import { DashboardSearchHit, DashboardSearchItemType } from 'app/features/search/types';
|
||||
import { DashboardSearchItem, DashboardSearchItemType } from 'app/features/search/types';
|
||||
|
||||
import { UserPreferencesDTO } from '../../../types';
|
||||
|
||||
@ -32,7 +32,7 @@ export interface Props {
|
||||
}
|
||||
|
||||
export type State = UserPreferencesDTO & {
|
||||
dashboards: DashboardSearchHit[];
|
||||
dashboards: DashboardSearchItem[];
|
||||
};
|
||||
|
||||
const themes: SelectableValue[] = [
|
||||
@ -74,6 +74,22 @@ const languages: Array<SelectableValue<string>> = [
|
||||
|
||||
const i18nFlag = Boolean(config.featureToggles.internationalization);
|
||||
|
||||
const DEFAULT_DASHBOARD_HOME: DashboardSearchItem = {
|
||||
title: 'Default',
|
||||
tags: [],
|
||||
type: '' as DashboardSearchItemType,
|
||||
uid: undefined,
|
||||
uri: '',
|
||||
url: '',
|
||||
folderId: 0,
|
||||
folderTitle: '',
|
||||
folderUid: '',
|
||||
folderUrl: '',
|
||||
isStarred: false,
|
||||
slug: '',
|
||||
items: [],
|
||||
};
|
||||
|
||||
export class SharedPreferences extends PureComponent<Props, State> {
|
||||
service: PreferencesService;
|
||||
|
||||
@ -82,7 +98,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
|
||||
this.service = new PreferencesService(props.resourceUri);
|
||||
this.state = {
|
||||
homeDashboardId: 0,
|
||||
homeDashboardUID: DEFAULT_DASHBOARD_HOME.uid,
|
||||
theme: '',
|
||||
timezone: '',
|
||||
weekStart: '',
|
||||
@ -94,45 +110,44 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
|
||||
async componentDidMount() {
|
||||
const prefs = await this.service.load();
|
||||
const dashboards = await backendSrv.search({ starred: true });
|
||||
const defaultDashboardHit: DashboardSearchHit = {
|
||||
id: 0,
|
||||
title: 'Default',
|
||||
tags: [],
|
||||
type: '' as DashboardSearchItemType,
|
||||
uid: '',
|
||||
uri: '',
|
||||
url: '',
|
||||
folderId: 0,
|
||||
folderTitle: '',
|
||||
folderUid: '',
|
||||
folderUrl: '',
|
||||
isStarred: false,
|
||||
slug: '',
|
||||
items: [],
|
||||
};
|
||||
const dashboards = (await backendSrv.search({ starred: true })) as DashboardSearchItem[];
|
||||
|
||||
if (prefs.homeDashboardId > 0 && !dashboards.find((d) => d.id === prefs.homeDashboardId)) {
|
||||
const missing = await backendSrv.search({ dashboardIds: [prefs.homeDashboardId] });
|
||||
if (missing && missing.length > 0) {
|
||||
dashboards.push(missing[0]);
|
||||
if (prefs.homeDashboardUID && !dashboards.find((d) => d.uid === prefs.homeDashboardUID)) {
|
||||
const missingDash = await backendSrv.getDashboardByUid(prefs.homeDashboardUID);
|
||||
|
||||
if (missingDash?.dashboard) {
|
||||
dashboards.push({
|
||||
title: missingDash.dashboard.title,
|
||||
tags: [],
|
||||
type: DashboardSearchItemType.DashDB,
|
||||
uid: missingDash.dashboard.uid,
|
||||
uri: '', // uri is not part of dashboard metadata
|
||||
url: missingDash.meta.url || '',
|
||||
folderId: missingDash.meta.folderId,
|
||||
folderTitle: missingDash.meta.folderTitle,
|
||||
folderUid: missingDash.meta.folderUid,
|
||||
folderUrl: missingDash.meta.folderUrl,
|
||||
isStarred: missingDash.meta.isStarred || false,
|
||||
slug: missingDash.meta.slug,
|
||||
items: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
homeDashboardId: prefs.homeDashboardId,
|
||||
homeDashboardUID: prefs.homeDashboardUID,
|
||||
theme: prefs.theme,
|
||||
timezone: prefs.timezone,
|
||||
weekStart: prefs.weekStart,
|
||||
locale: prefs.locale,
|
||||
dashboards: [defaultDashboardHit, ...dashboards],
|
||||
dashboards: [DEFAULT_DASHBOARD_HOME, ...dashboards],
|
||||
queryHistory: prefs.queryHistory,
|
||||
});
|
||||
}
|
||||
|
||||
onSubmitForm = async () => {
|
||||
const { homeDashboardId, theme, timezone, weekStart, locale, queryHistory } = this.state;
|
||||
await this.service.update({ homeDashboardId, theme, timezone, weekStart, locale, queryHistory });
|
||||
const { homeDashboardUID, theme, timezone, weekStart, locale, queryHistory } = this.state;
|
||||
await this.service.update({ homeDashboardUID, theme, timezone, weekStart, locale, queryHistory });
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
@ -151,15 +166,15 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
this.setState({ weekStart: weekStart });
|
||||
};
|
||||
|
||||
onHomeDashboardChanged = (dashboardId: number) => {
|
||||
this.setState({ homeDashboardId: dashboardId });
|
||||
onHomeDashboardChanged = (dashboardUID: string) => {
|
||||
this.setState({ homeDashboardUID: dashboardUID });
|
||||
};
|
||||
|
||||
onLocaleChanged = (locale: string) => {
|
||||
this.setState({ locale });
|
||||
};
|
||||
|
||||
getFullDashName = (dashboard: SelectableValue<DashboardSearchHit>) => {
|
||||
getFullDashName = (dashboard: SelectableValue<DashboardSearchItem>) => {
|
||||
if (typeof dashboard.folderTitle === 'undefined' || dashboard.folderTitle === '') {
|
||||
return dashboard.title;
|
||||
}
|
||||
@ -167,7 +182,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { theme, timezone, weekStart, homeDashboardId, locale, dashboards } = this.state;
|
||||
const { theme, timezone, weekStart, homeDashboardUID, locale, dashboards } = this.state;
|
||||
const { disabled } = this.props;
|
||||
const styles = getStyles();
|
||||
|
||||
@ -209,11 +224,11 @@ export class SharedPreferences extends PureComponent<Props, State> {
|
||||
data-testid="User preferences home dashboard drop down"
|
||||
>
|
||||
<Select
|
||||
value={dashboards.find((dashboard) => dashboard.id === homeDashboardId)}
|
||||
getOptionValue={(i) => i.id}
|
||||
value={dashboards.find((dashboard) => dashboard.uid === homeDashboardUID)}
|
||||
getOptionValue={(i) => i.uid}
|
||||
getOptionLabel={this.getFullDashName}
|
||||
onChange={(dashboard: SelectableValue<DashboardSearchHit>) =>
|
||||
this.onHomeDashboardChanged(dashboard.id)
|
||||
onChange={(dashboard: SelectableValue<DashboardSearchItem>) =>
|
||||
this.onHomeDashboardChanged(dashboard.uid)
|
||||
}
|
||||
options={dashboards}
|
||||
placeholder={t({
|
||||
|
@ -35,7 +35,9 @@ const setup = (propOverrides?: object) => {
|
||||
jest.clearAllMocks();
|
||||
// needed because SharedPreferences is rendered in the test
|
||||
jest.spyOn(backendSrv, 'put');
|
||||
jest.spyOn(backendSrv, 'get').mockResolvedValue({ timezone: 'UTC', homeDashboardId: 0, theme: 'dark' });
|
||||
jest
|
||||
.spyOn(backendSrv, 'get')
|
||||
.mockResolvedValue({ timezone: 'UTC', homeDashboardUID: 'home-dashboard', theme: 'dark' });
|
||||
jest.spyOn(backendSrv, 'search').mockResolvedValue([]);
|
||||
|
||||
const props: Props = {
|
||||
@ -70,7 +72,7 @@ describe('Render', () => {
|
||||
id: 1,
|
||||
},
|
||||
preferences: {
|
||||
homeDashboardId: 1,
|
||||
homeDashboardUID: 'home-dashboard',
|
||||
theme: 'Default',
|
||||
timezone: 'Default',
|
||||
locale: '',
|
||||
|
@ -100,7 +100,7 @@ async function getTestContext(overrides: Partial<Props> = {}) {
|
||||
const putSpy = jest.spyOn(backendSrv, 'put');
|
||||
const getSpy = jest
|
||||
.spyOn(backendSrv, 'get')
|
||||
.mockResolvedValue({ timezone: 'UTC', homeDashboardId: 0, theme: 'dark' });
|
||||
.mockResolvedValue({ timezone: 'UTC', homeDashboardUID: 'home-dashboard', theme: 'dark' });
|
||||
const searchSpy = jest.spyOn(backendSrv, 'search').mockResolvedValue([]);
|
||||
|
||||
const props = { ...defaultProps, ...overrides };
|
||||
|
@ -51,8 +51,13 @@ export interface DashboardSectionItem {
|
||||
sortMetaName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - It uses dashboard ID which is depreacted in favor of dashboard UID. Please, use DashboardSearchItem instead.
|
||||
*/
|
||||
export interface DashboardSearchHit extends DashboardSectionItem, DashboardSection, WithAccessControlMetadata {}
|
||||
|
||||
export interface DashboardSearchItem extends Omit<DashboardSearchHit, 'id'> {}
|
||||
|
||||
export interface SearchAction extends Action {
|
||||
payload?: any;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ describe('Render', () => {
|
||||
team: getMockTeam(),
|
||||
pageName: 'settings',
|
||||
preferences: {
|
||||
homeDashboardId: 1,
|
||||
homeDashboardUID: 'home-dashboard',
|
||||
theme: 'Default',
|
||||
timezone: 'Default',
|
||||
},
|
||||
@ -131,7 +131,7 @@ describe('when feature toggle editorsCanAdmin is turned on', () => {
|
||||
team: getMockTeam(),
|
||||
pageName: 'settings',
|
||||
preferences: {
|
||||
homeDashboardId: 1,
|
||||
homeDashboardUID: 'home-dashboard',
|
||||
theme: 'Default',
|
||||
timezone: 'Default',
|
||||
},
|
||||
|
@ -4,7 +4,8 @@ export interface UserPreferencesDTO {
|
||||
timezone: TimeZone;
|
||||
weekStart: string;
|
||||
locale: string;
|
||||
homeDashboardId: number;
|
||||
// It is undefined when there is not dashboard assigned (default)
|
||||
homeDashboardUID?: string;
|
||||
theme: string;
|
||||
queryHistory: {
|
||||
homeTab: '' | 'query' | 'starred';
|
||||
|
Loading…
Reference in New Issue
Block a user