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