mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
dashfolder: refactor breadcrumbs in PageHeader
Combines title and breadcrumbs in PageHeader instead of having to set title to empty and add it as a breadcrumb.
This commit is contained in:
parent
545d7b9477
commit
21b5ded75b
@ -49,7 +49,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
|
|||||||
const { nav, folder, view } = this.props;
|
const { nav, folder, view } = this.props;
|
||||||
|
|
||||||
folder
|
folder
|
||||||
.saveDashboard(this.dashboard, { overwrite: false })
|
.saveFolder(this.dashboard, { overwrite: false })
|
||||||
.then(newUrl => {
|
.then(newUrl => {
|
||||||
view.updatePathAndQuery(newUrl, '', '');
|
view.updatePathAndQuery(newUrl, '', '');
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ export class FolderSettings extends React.Component<IContainerProps, any> {
|
|||||||
yesText: 'Save & Overwrite',
|
yesText: 'Save & Overwrite',
|
||||||
icon: 'fa-warning',
|
icon: 'fa-warning',
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
this.props.folder.saveDashboard(this.dashboard, { overwrite: true });
|
this.props.folder.saveFolder(this.dashboard, { overwrite: true });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
53
public/app/core/components/PageHeader/PageHeader.jest.tsx
Normal file
53
public/app/core/components/PageHeader/PageHeader.jest.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PageHeader from './PageHeader';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
|
describe('PageHeader', () => {
|
||||||
|
let wrapper;
|
||||||
|
|
||||||
|
describe('when the nav tree has a node with a title', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
const nav = {
|
||||||
|
main: {
|
||||||
|
icon: 'fa fa-folder-open',
|
||||||
|
id: 'node',
|
||||||
|
subTitle: 'node subtitle',
|
||||||
|
url: '',
|
||||||
|
text: 'node',
|
||||||
|
},
|
||||||
|
node: {},
|
||||||
|
};
|
||||||
|
wrapper = shallow(<PageHeader model={nav as any} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render the title', () => {
|
||||||
|
const title = wrapper.find('.page-header__title');
|
||||||
|
expect(title.text()).toBe('node');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the nav tree has a node with breadcrumbs and a title', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
const nav = {
|
||||||
|
main: {
|
||||||
|
icon: 'fa fa-folder-open',
|
||||||
|
id: 'child',
|
||||||
|
subTitle: 'child subtitle',
|
||||||
|
url: '',
|
||||||
|
text: 'child',
|
||||||
|
breadcrumbs: [{ title: 'Parent', url: 'parentUrl' }],
|
||||||
|
},
|
||||||
|
node: {},
|
||||||
|
};
|
||||||
|
wrapper = shallow(<PageHeader model={nav as any} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render the title with breadcrumbs first and then title last', () => {
|
||||||
|
const title = wrapper.find('.page-header__title');
|
||||||
|
expect(title.text()).toBe('Parent / child');
|
||||||
|
|
||||||
|
const parentLink = wrapper.find('.page-header__title > a.text-link');
|
||||||
|
expect(parentLink.prop('href')).toBe('parentUrl');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -85,7 +85,15 @@ export default class PageHeader extends React.Component<IProps, any> {
|
|||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBreadcrumb(breadcrumbs) {
|
renderTitle(title: string, breadcrumbs: any[]) {
|
||||||
|
if (!title && (!breadcrumbs || breadcrumbs.length === 0)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!breadcrumbs || breadcrumbs.length === 0) {
|
||||||
|
return <h1 className="page-header__title">{title}</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
const breadcrumbsResult = [];
|
const breadcrumbsResult = [];
|
||||||
for (let i = 0; i < breadcrumbs.length; i++) {
|
for (let i = 0; i < breadcrumbs.length; i++) {
|
||||||
const bc = breadcrumbs[i];
|
const bc = breadcrumbs[i];
|
||||||
@ -99,7 +107,9 @@ export default class PageHeader extends React.Component<IProps, any> {
|
|||||||
breadcrumbsResult.push(<span key={i}> / {bc.title}</span>);
|
breadcrumbsResult.push(<span key={i}> / {bc.title}</span>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return breadcrumbsResult;
|
breadcrumbsResult.push(<span key={breadcrumbs.length + 1}> / {title}</span>);
|
||||||
|
|
||||||
|
return <h1 className="page-header__title">{breadcrumbsResult}</h1>;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderHeaderTitle(main) {
|
renderHeaderTitle(main) {
|
||||||
@ -111,11 +121,7 @@ export default class PageHeader extends React.Component<IProps, any> {
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div className="page-header__info-block">
|
<div className="page-header__info-block">
|
||||||
{main.text && <h1 className="page-header__title">{main.text}</h1>}
|
{this.renderTitle(main.text, main.breadcrumbs)}
|
||||||
{main.breadcrumbs &&
|
|
||||||
main.breadcrumbs.length > 0 && (
|
|
||||||
<h1 className="page-header__title">{this.renderBreadcrumb(main.breadcrumbs)}</h1>
|
|
||||||
)}
|
|
||||||
{main.subTitle && <div className="page-header__sub-title">{main.subTitle}</div>}
|
{main.subTitle && <div className="page-header__sub-title">{main.subTitle}</div>}
|
||||||
{main.subType && (
|
{main.subType && (
|
||||||
<div className="page-header__stamps">
|
<div className="page-header__stamps">
|
||||||
|
@ -10,8 +10,9 @@ export class InvitedCtrl {
|
|||||||
$scope.navModel = {
|
$scope.navModel = {
|
||||||
main: {
|
main: {
|
||||||
icon: 'gicon gicon-branding',
|
icon: 'gicon gicon-branding',
|
||||||
|
text: 'Invite',
|
||||||
subTitle: 'Register your Grafana account',
|
subTitle: 'Register your Grafana account',
|
||||||
breadcrumbs: [{ title: 'Login', url: '/login' }, { title: 'Invite' }],
|
breadcrumbs: [{ title: 'Login', url: '/login' }],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,8 +16,9 @@ export class ResetPasswordCtrl {
|
|||||||
$scope.navModel = {
|
$scope.navModel = {
|
||||||
main: {
|
main: {
|
||||||
icon: 'gicon gicon-branding',
|
icon: 'gicon gicon-branding',
|
||||||
|
text: 'Reset Password',
|
||||||
subTitle: 'Reset your Grafana password',
|
subTitle: 'Reset your Grafana password',
|
||||||
breadcrumbs: [{ title: 'Login', url: 'login' }, { title: 'Reset Password' }],
|
breadcrumbs: [{ title: 'Login', url: 'login' }],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export class FolderPageLoader {
|
|||||||
subTitle: 'Manage folder dashboards & permissions',
|
subTitle: 'Manage folder dashboards & permissions',
|
||||||
url: '',
|
url: '',
|
||||||
text: '',
|
text: '',
|
||||||
breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }, { title: ' ' }],
|
breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
active: activeChildId === 'manage-folder-dashboards',
|
active: activeChildId === 'manage-folder-dashboards',
|
||||||
@ -40,8 +40,7 @@ export class FolderPageLoader {
|
|||||||
|
|
||||||
return this.backendSrv.getDashboard('db', this.$routeParams.slug).then(result => {
|
return this.backendSrv.getDashboard('db', this.$routeParams.slug).then(result => {
|
||||||
const folderTitle = result.dashboard.title;
|
const folderTitle = result.dashboard.title;
|
||||||
ctrl.navModel.main.text = '';
|
ctrl.navModel.main.text = folderTitle;
|
||||||
ctrl.navModel.main.breadcrumbs = [{ title: 'Dashboards', url: 'dashboards' }, { title: folderTitle }];
|
|
||||||
|
|
||||||
const folderUrl = this.createFolderUrl(folderId, result.meta.slug);
|
const folderUrl = this.createFolderUrl(folderId, result.meta.slug);
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ export class PluginEditCtrl {
|
|||||||
img: model.info.logos.large,
|
img: model.info.logos.large,
|
||||||
subTitle: model.info.author.name,
|
subTitle: model.info.author.name,
|
||||||
url: '',
|
url: '',
|
||||||
text: '',
|
text: model.name,
|
||||||
breadcrumbs: [{ title: 'Plugins', url: 'plugins' }, { title: model.name }],
|
breadcrumbs: [{ title: 'Plugins', url: 'plugins' }],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
icon: 'fa fa-fw fa-file-text-o',
|
icon: 'fa fa-fw fa-file-text-o',
|
||||||
|
@ -40,8 +40,8 @@ export class AppPageCtrl {
|
|||||||
img: app.info.logos.large,
|
img: app.info.logos.large,
|
||||||
subTitle: app.name,
|
subTitle: app.name,
|
||||||
url: '',
|
url: '',
|
||||||
text: '',
|
text: this.page.name,
|
||||||
breadcrumbs: [{ title: app.name, url: pluginNav.main.url }, { title: this.page.name }],
|
breadcrumbs: [{ title: app.name, url: pluginNav.main.url }],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,13 @@ export const FolderStore = types
|
|||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setTitle: function(originalTitle: string, title: string) {
|
setTitle: function(originalTitle: string, title: string) {
|
||||||
self.folder.title = title;
|
self.folder.title = title;
|
||||||
self.folder.hasChanged = originalTitle.toLowerCase() !== title.trim().toLowerCase() && title.trim().length > 0;
|
self.folder.hasChanged = originalTitle.toLowerCase() !== title.trim().toLowerCase() && title.trim().length > 0;
|
||||||
},
|
},
|
||||||
saveDashboard: flow(function* saveDashboard(dashboard: any, options: any) {
|
|
||||||
|
saveFolder: flow(function* saveFolder(dashboard: any, options: any) {
|
||||||
const backendSrv = getEnv(self).backendSrv;
|
const backendSrv = getEnv(self).backendSrv;
|
||||||
dashboard.title = self.folder.title.trim();
|
dashboard.title = self.folder.title.trim();
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ export const FolderStore = types
|
|||||||
self.folder.slug = res.slug;
|
self.folder.slug = res.slug;
|
||||||
return `dashboards/folder/${self.folder.id}/${res.slug}/settings`;
|
return `dashboards/folder/${self.folder.id}/${res.slug}/settings`;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
deleteFolder: flow(function* deleteFolder() {
|
deleteFolder: flow(function* deleteFolder() {
|
||||||
const backendSrv = getEnv(self).backendSrv;
|
const backendSrv = getEnv(self).backendSrv;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user