Preferences: Use dashboardUID to set the home dashboard (#51919)

This commit is contained in:
Ivan Ortega Alba 2022-07-22 10:44:22 +02:00 committed by GitHub
parent c7f8c2a7e1
commit 2ec01c8d08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 86 additions and 50 deletions

View File

@ -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"],

View File

@ -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: '',
},

View File

@ -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({

View File

@ -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: '',

View File

@ -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 };

View File

@ -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;
}

View File

@ -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',
},

View File

@ -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';