From 21b5ded75bae01f0dcaf36bbdf967f41da378eff Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 11 Jan 2018 17:53:06 +0100 Subject: [PATCH] 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. --- .../ManageDashboards/FolderSettings.tsx | 4 +- .../components/PageHeader/PageHeader.jest.tsx | 53 +++++++++++++++++++ .../core/components/PageHeader/PageHeader.tsx | 20 ++++--- public/app/core/controllers/invited_ctrl.ts | 3 +- .../core/controllers/reset_password_ctrl.ts | 3 +- .../features/dashboard/folder_page_loader.ts | 5 +- .../app/features/plugins/plugin_edit_ctrl.ts | 4 +- .../app/features/plugins/plugin_page_ctrl.ts | 4 +- public/app/stores/FolderStore/FolderStore.ts | 5 +- 9 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 public/app/core/components/PageHeader/PageHeader.jest.tsx diff --git a/public/app/containers/ManageDashboards/FolderSettings.tsx b/public/app/containers/ManageDashboards/FolderSettings.tsx index acf34b925ab..ef3377622df 100644 --- a/public/app/containers/ManageDashboards/FolderSettings.tsx +++ b/public/app/containers/ManageDashboards/FolderSettings.tsx @@ -49,7 +49,7 @@ export class FolderSettings extends React.Component { const { nav, folder, view } = this.props; folder - .saveDashboard(this.dashboard, { overwrite: false }) + .saveFolder(this.dashboard, { overwrite: false }) .then(newUrl => { view.updatePathAndQuery(newUrl, '', ''); @@ -96,7 +96,7 @@ export class FolderSettings extends React.Component { yesText: 'Save & Overwrite', icon: 'fa-warning', onConfirm: () => { - this.props.folder.saveDashboard(this.dashboard, { overwrite: true }); + this.props.folder.saveFolder(this.dashboard, { overwrite: true }); }, }); } diff --git a/public/app/core/components/PageHeader/PageHeader.jest.tsx b/public/app/core/components/PageHeader/PageHeader.jest.tsx new file mode 100644 index 00000000000..a9ba8d008a3 --- /dev/null +++ b/public/app/core/components/PageHeader/PageHeader.jest.tsx @@ -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(); + }); + + 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(); + }); + + 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'); + }); + }); +}); diff --git a/public/app/core/components/PageHeader/PageHeader.tsx b/public/app/core/components/PageHeader/PageHeader.tsx index b6b6511c04e..f2c6d3f1bad 100644 --- a/public/app/core/components/PageHeader/PageHeader.tsx +++ b/public/app/core/components/PageHeader/PageHeader.tsx @@ -85,7 +85,15 @@ export default class PageHeader extends React.Component { super(props); } - renderBreadcrumb(breadcrumbs) { + renderTitle(title: string, breadcrumbs: any[]) { + if (!title && (!breadcrumbs || breadcrumbs.length === 0)) { + return null; + } + + if (!breadcrumbs || breadcrumbs.length === 0) { + return

{title}

; + } + const breadcrumbsResult = []; for (let i = 0; i < breadcrumbs.length; i++) { const bc = breadcrumbs[i]; @@ -99,7 +107,9 @@ export default class PageHeader extends React.Component { breadcrumbsResult.push( / {bc.title}); } } - return breadcrumbsResult; + breadcrumbsResult.push( / {title}); + + return

{breadcrumbsResult}

; } renderHeaderTitle(main) { @@ -111,11 +121,7 @@ export default class PageHeader extends React.Component {
- {main.text &&

{main.text}

} - {main.breadcrumbs && - main.breadcrumbs.length > 0 && ( -

{this.renderBreadcrumb(main.breadcrumbs)}

- )} + {this.renderTitle(main.text, main.breadcrumbs)} {main.subTitle &&
{main.subTitle}
} {main.subType && (
diff --git a/public/app/core/controllers/invited_ctrl.ts b/public/app/core/controllers/invited_ctrl.ts index e88c810b557..4bfb7106a69 100644 --- a/public/app/core/controllers/invited_ctrl.ts +++ b/public/app/core/controllers/invited_ctrl.ts @@ -10,8 +10,9 @@ export class InvitedCtrl { $scope.navModel = { main: { icon: 'gicon gicon-branding', + text: 'Invite', subTitle: 'Register your Grafana account', - breadcrumbs: [{ title: 'Login', url: '/login' }, { title: 'Invite' }], + breadcrumbs: [{ title: 'Login', url: '/login' }], }, }; diff --git a/public/app/core/controllers/reset_password_ctrl.ts b/public/app/core/controllers/reset_password_ctrl.ts index bc184838803..360c5bf8071 100644 --- a/public/app/core/controllers/reset_password_ctrl.ts +++ b/public/app/core/controllers/reset_password_ctrl.ts @@ -16,8 +16,9 @@ export class ResetPasswordCtrl { $scope.navModel = { main: { icon: 'gicon gicon-branding', + text: 'Reset Password', subTitle: 'Reset your Grafana password', - breadcrumbs: [{ title: 'Login', url: 'login' }, { title: 'Reset Password' }], + breadcrumbs: [{ title: 'Login', url: 'login' }], }, }; diff --git a/public/app/features/dashboard/folder_page_loader.ts b/public/app/features/dashboard/folder_page_loader.ts index ae610cb8014..d54fa1d51e4 100755 --- a/public/app/features/dashboard/folder_page_loader.ts +++ b/public/app/features/dashboard/folder_page_loader.ts @@ -11,7 +11,7 @@ export class FolderPageLoader { subTitle: 'Manage folder dashboards & permissions', url: '', text: '', - breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }, { title: ' ' }], + breadcrumbs: [{ title: 'Dashboards', url: 'dashboards' }], children: [ { active: activeChildId === 'manage-folder-dashboards', @@ -40,8 +40,7 @@ export class FolderPageLoader { return this.backendSrv.getDashboard('db', this.$routeParams.slug).then(result => { const folderTitle = result.dashboard.title; - ctrl.navModel.main.text = ''; - ctrl.navModel.main.breadcrumbs = [{ title: 'Dashboards', url: 'dashboards' }, { title: folderTitle }]; + ctrl.navModel.main.text = folderTitle; const folderUrl = this.createFolderUrl(folderId, result.meta.slug); diff --git a/public/app/features/plugins/plugin_edit_ctrl.ts b/public/app/features/plugins/plugin_edit_ctrl.ts index 07d7911df1a..1244e6e38f7 100644 --- a/public/app/features/plugins/plugin_edit_ctrl.ts +++ b/public/app/features/plugins/plugin_edit_ctrl.ts @@ -32,8 +32,8 @@ export class PluginEditCtrl { img: model.info.logos.large, subTitle: model.info.author.name, url: '', - text: '', - breadcrumbs: [{ title: 'Plugins', url: 'plugins' }, { title: model.name }], + text: model.name, + breadcrumbs: [{ title: 'Plugins', url: 'plugins' }], children: [ { icon: 'fa fa-fw fa-file-text-o', diff --git a/public/app/features/plugins/plugin_page_ctrl.ts b/public/app/features/plugins/plugin_page_ctrl.ts index 876997c1c5e..397916aacc8 100644 --- a/public/app/features/plugins/plugin_page_ctrl.ts +++ b/public/app/features/plugins/plugin_page_ctrl.ts @@ -40,8 +40,8 @@ export class AppPageCtrl { img: app.info.logos.large, subTitle: app.name, url: '', - text: '', - breadcrumbs: [{ title: app.name, url: pluginNav.main.url }, { title: this.page.name }], + text: this.page.name, + breadcrumbs: [{ title: app.name, url: pluginNav.main.url }], }, }; } diff --git a/public/app/stores/FolderStore/FolderStore.ts b/public/app/stores/FolderStore/FolderStore.ts index 1928fbcad61..d0216e32ad7 100644 --- a/public/app/stores/FolderStore/FolderStore.ts +++ b/public/app/stores/FolderStore/FolderStore.ts @@ -25,11 +25,13 @@ export const FolderStore = types }); return res; }), + setTitle: function(originalTitle: string, title: string) { self.folder.title = title; 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; dashboard.title = self.folder.title.trim(); @@ -37,6 +39,7 @@ export const FolderStore = types self.folder.slug = res.slug; return `dashboards/folder/${self.folder.id}/${res.slug}/settings`; }), + deleteFolder: flow(function* deleteFolder() { const backendSrv = getEnv(self).backendSrv;