From cab6861d27b9ea9b579af8e3dc962f020951c69c Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Tue, 4 Sep 2018 17:24:08 +0200 Subject: [PATCH] Reactify sidebar (#13091) * created react component and moved markdown * extracting components * Broke out parts into components * tests * Flattened file structure * Tests * made instances typed in test * typing * function instead of variable * updated user model with missing properties * added full set of properties to user mock * redone from variable to function * refactor: minor refactorings of #13091 * removed logging --- public/app/core/angular_wrappers.ts | 2 + .../sidemenu/BottomNavLinks.test.tsx | 96 +++++++++++ .../components/sidemenu/BottomNavLinks.tsx | 78 +++++++++ .../sidemenu/BottomSection.test.tsx | 44 +++++ .../components/sidemenu/BottomSection.tsx | 29 ++++ .../sidemenu/DropDownChild.test.tsx | 35 ++++ .../components/sidemenu/DropDownChild.tsx | 21 +++ .../components/sidemenu/SideMenu.test.tsx | 70 ++++++++ .../app/core/components/sidemenu/SideMenu.tsx | 32 ++++ .../sidemenu/SideMenuDropDown.test.tsx | 35 ++++ .../components/sidemenu/SideMenuDropDown.tsx | 23 +++ .../core/components/sidemenu/SignIn.test.tsx | 11 ++ .../app/core/components/sidemenu/SignIn.tsx | 23 +++ .../components/sidemenu/TopSection.test.tsx | 41 +++++ .../core/components/sidemenu/TopSection.tsx | 19 ++ .../sidemenu/TopSectionItem.test.tsx | 22 +++ .../components/sidemenu/TopSectionItem.tsx | 23 +++ .../BottomNavLinks.test.tsx.snap | 163 ++++++++++++++++++ .../__snapshots__/BottomSection.test.tsx.snap | 34 ++++ .../__snapshots__/DropDownChild.test.tsx.snap | 21 +++ .../__snapshots__/SideMenu.test.tsx.snap | 22 +++ .../SideMenuDropDown.test.tsx.snap | 59 +++++++ .../__snapshots__/SignIn.test.tsx.snap | 40 +++++ .../__snapshots__/TopSection.test.tsx.snap | 33 ++++ .../TopSectionItem.test.tsx.snap | 17 ++ .../core/components/sidemenu/sidemenu.html | 81 --------- .../app/core/components/sidemenu/sidemenu.ts | 89 ---------- public/app/core/core.ts | 2 - public/app/core/services/context_srv.ts | 2 + 29 files changed, 995 insertions(+), 172 deletions(-) create mode 100644 public/app/core/components/sidemenu/BottomNavLinks.test.tsx create mode 100644 public/app/core/components/sidemenu/BottomNavLinks.tsx create mode 100644 public/app/core/components/sidemenu/BottomSection.test.tsx create mode 100644 public/app/core/components/sidemenu/BottomSection.tsx create mode 100644 public/app/core/components/sidemenu/DropDownChild.test.tsx create mode 100644 public/app/core/components/sidemenu/DropDownChild.tsx create mode 100644 public/app/core/components/sidemenu/SideMenu.test.tsx create mode 100644 public/app/core/components/sidemenu/SideMenu.tsx create mode 100644 public/app/core/components/sidemenu/SideMenuDropDown.test.tsx create mode 100644 public/app/core/components/sidemenu/SideMenuDropDown.tsx create mode 100644 public/app/core/components/sidemenu/SignIn.test.tsx create mode 100644 public/app/core/components/sidemenu/SignIn.tsx create mode 100644 public/app/core/components/sidemenu/TopSection.test.tsx create mode 100644 public/app/core/components/sidemenu/TopSection.tsx create mode 100644 public/app/core/components/sidemenu/TopSectionItem.test.tsx create mode 100644 public/app/core/components/sidemenu/TopSectionItem.tsx create mode 100644 public/app/core/components/sidemenu/__snapshots__/BottomNavLinks.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/BottomSection.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/DropDownChild.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/SideMenu.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/SideMenuDropDown.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/SignIn.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/TopSection.test.tsx.snap create mode 100644 public/app/core/components/sidemenu/__snapshots__/TopSectionItem.test.tsx.snap delete mode 100644 public/app/core/components/sidemenu/sidemenu.html delete mode 100644 public/app/core/components/sidemenu/sidemenu.ts diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index e7295646172..18e9d8dbd84 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -4,10 +4,12 @@ import PageHeader from './components/PageHeader/PageHeader'; import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; import { SearchResult } from './components/search/SearchResult'; import { TagFilter } from './components/TagFilter/TagFilter'; +import { SideMenu } from './components/sidemenu/SideMenu'; import DashboardPermissions from './components/Permissions/DashboardPermissions'; export function registerAngularDirectives() { react2AngularDirective('passwordStrength', PasswordStrength, ['password']); + react2AngularDirective('sidemenu', SideMenu, []); react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); react2AngularDirective('searchResult', SearchResult, []); diff --git a/public/app/core/components/sidemenu/BottomNavLinks.test.tsx b/public/app/core/components/sidemenu/BottomNavLinks.test.tsx new file mode 100644 index 00000000000..8eaed4ca264 --- /dev/null +++ b/public/app/core/components/sidemenu/BottomNavLinks.test.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import BottomNavLinks from './BottomNavLinks'; +import appEvents from '../../app_events'; + +jest.mock('../../app_events', () => ({ + emit: jest.fn(), +})); + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + link: {}, + user: { + isGrafanaAdmin: false, + isSignedIn: false, + orgCount: 2, + orgRole: '', + orgId: 1, + orgName: 'Grafana', + timezone: 'UTC', + helpFlags1: 1, + lightTheme: false, + hasEditPermissionInFolders: false, + }, + }, + propOverrides + ); + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render organisation switcher', () => { + const wrapper = setup({ + link: { + showOrgSwitcher: true, + }, + }); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render subtitle', () => { + const wrapper = setup({ + link: { + subTitle: 'subtitle', + }, + }); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render children', () => { + const wrapper = setup({ + link: { + children: [ + { + id: '1', + }, + { + id: '2', + }, + { + id: '3', + }, + { + id: '4', + hideFromMenu: true, + }, + ], + }, + }); + + expect(wrapper).toMatchSnapshot(); + }); +}); + +describe('Functions', () => { + describe('item clicked', () => { + const wrapper = setup(); + const mockEvent = { preventDefault: jest.fn() }; + it('should emit show modal event if url matches shortcut', () => { + const child = { url: '/shortcuts' }; + const instance = wrapper.instance() as BottomNavLinks; + instance.itemClicked(mockEvent, child); + + expect(appEvents.emit).toHaveBeenCalledWith('show-modal', { templateHtml: '' }); + }); + }); +}); diff --git a/public/app/core/components/sidemenu/BottomNavLinks.tsx b/public/app/core/components/sidemenu/BottomNavLinks.tsx new file mode 100644 index 00000000000..21c83864c62 --- /dev/null +++ b/public/app/core/components/sidemenu/BottomNavLinks.tsx @@ -0,0 +1,78 @@ +import React, { PureComponent } from 'react'; +import appEvents from '../../app_events'; +import { User } from '../../services/context_srv'; + +export interface Props { + link: any; + user: User; +} + +class BottomNavLinks extends PureComponent { + itemClicked = (event, child) => { + if (child.url === '/shortcuts') { + event.preventDefault(); + appEvents.emit('show-modal', { + templateHtml: '', + }); + } + }; + + switchOrg = () => { + appEvents.emit('show-modal', { + templateHtml: '', + }); + }; + + render() { + const { link, user } = this.props; + return ( +
+ + + {link.icon && } + {link.img && } + + + +
+ ); + } +} + +export default BottomNavLinks; diff --git a/public/app/core/components/sidemenu/BottomSection.test.tsx b/public/app/core/components/sidemenu/BottomSection.test.tsx new file mode 100644 index 00000000000..40307895c57 --- /dev/null +++ b/public/app/core/components/sidemenu/BottomSection.test.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import BottomSection from './BottomSection'; + +jest.mock('../../config', () => ({ + bootData: { + navTree: [ + { + id: 'profile', + hideFromMenu: true, + }, + { + hideFromMenu: true, + }, + { + hideFromMenu: false, + }, + { + hideFromMenu: true, + }, + ], + }, + user: { + orgCount: 5, + orgName: 'Grafana', + }, +})); + +jest.mock('app/core/services/context_srv', () => ({ + contextSrv: { + sidemenu: true, + isSignedIn: false, + isGrafanaAdmin: false, + hasEditPermissionFolders: false, + }, +})); + +describe('Render', () => { + it('should render component', () => { + const wrapper = shallow(); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/BottomSection.tsx b/public/app/core/components/sidemenu/BottomSection.tsx new file mode 100644 index 00000000000..ee5175ca763 --- /dev/null +++ b/public/app/core/components/sidemenu/BottomSection.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import _ from 'lodash'; +import SignIn from './SignIn'; +import BottomNavLinks from './BottomNavLinks'; +import { contextSrv } from 'app/core/services/context_srv'; +import config from '../../config'; + +export default function BottomSection() { + const navTree = _.cloneDeep(config.bootData.navTree); + const bottomNav = _.filter(navTree, item => item.hideFromMenu); + const isSignedIn = contextSrv.isSignedIn; + const user = contextSrv.user; + + if (user && user.orgCount > 1) { + const profileNode = _.find(bottomNav, { id: 'profile' }); + if (profileNode) { + profileNode.showOrgSwitcher = true; + } + } + + return ( +
+ {!isSignedIn && } + {bottomNav.map((link, index) => { + return ; + })} +
+ ); +} diff --git a/public/app/core/components/sidemenu/DropDownChild.test.tsx b/public/app/core/components/sidemenu/DropDownChild.test.tsx new file mode 100644 index 00000000000..6a15ca5b23f --- /dev/null +++ b/public/app/core/components/sidemenu/DropDownChild.test.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import DropDownChild from './DropDownChild'; + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + child: { + divider: true, + }, + }, + propOverrides + ); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render icon if exists', () => { + const wrapper = setup({ + child: { + divider: false, + icon: 'icon-test', + }, + }); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/DropDownChild.tsx b/public/app/core/components/sidemenu/DropDownChild.tsx new file mode 100644 index 00000000000..1a577d185e5 --- /dev/null +++ b/public/app/core/components/sidemenu/DropDownChild.tsx @@ -0,0 +1,21 @@ +import React, { SFC } from 'react'; + +export interface Props { + child: any; +} + +const DropDownChild: SFC = props => { + const { child } = props; + const listItemClassName = child.divider ? 'divider' : ''; + + return ( +
  • + + {child.icon && } + {child.text} + +
  • + ); +}; + +export default DropDownChild; diff --git a/public/app/core/components/sidemenu/SideMenu.test.tsx b/public/app/core/components/sidemenu/SideMenu.test.tsx new file mode 100644 index 00000000000..2a262adca5a --- /dev/null +++ b/public/app/core/components/sidemenu/SideMenu.test.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { SideMenu } from './SideMenu'; +import appEvents from '../../app_events'; +import { contextSrv } from 'app/core/services/context_srv'; + +jest.mock('../../app_events', () => ({ + emit: jest.fn(), +})); + +jest.mock('app/core/services/context_srv', () => ({ + contextSrv: { + sidemenu: true, + user: {}, + isSignedIn: false, + isGrafanaAdmin: false, + isEditor: false, + hasEditPermissionFolders: false, + toggleSideMenu: jest.fn(), + }, +})); + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + loginUrl: '', + user: {}, + mainLinks: [], + bottomeLinks: [], + isSignedIn: false, + }, + propOverrides + ); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); +}); + +describe('Functions', () => { + describe('toggle side menu', () => { + const wrapper = setup(); + const instance = wrapper.instance() as SideMenu; + instance.toggleSideMenu(); + + it('should call contextSrv.toggleSideMenu', () => { + expect(contextSrv.toggleSideMenu).toHaveBeenCalled(); + }); + + it('should emit toggle sidemenu event', () => { + expect(appEvents.emit).toHaveBeenCalledWith('toggle-sidemenu'); + }); + }); + + describe('toggle side menu on mobile', () => { + const wrapper = setup(); + const instance = wrapper.instance() as SideMenu; + instance.toggleSideMenuSmallBreakpoint(); + + it('should emit toggle sidemenu event', () => { + expect(appEvents.emit).toHaveBeenCalledWith('toggle-sidemenu-mobile'); + }); + }); +}); diff --git a/public/app/core/components/sidemenu/SideMenu.tsx b/public/app/core/components/sidemenu/SideMenu.tsx new file mode 100644 index 00000000000..0092c1e3842 --- /dev/null +++ b/public/app/core/components/sidemenu/SideMenu.tsx @@ -0,0 +1,32 @@ +import React, { PureComponent } from 'react'; +import appEvents from '../../app_events'; +import { contextSrv } from 'app/core/services/context_srv'; +import TopSection from './TopSection'; +import BottomSection from './BottomSection'; + +export class SideMenu extends PureComponent { + toggleSideMenu = () => { + contextSrv.toggleSideMenu(); + appEvents.emit('toggle-sidemenu'); + }; + + toggleSideMenuSmallBreakpoint = () => { + appEvents.emit('toggle-sidemenu-mobile'); + }; + + render() { + return [ +
    + graphana_logo +
    , +
    + + +  Close + +
    , + , + , + ]; + } +} diff --git a/public/app/core/components/sidemenu/SideMenuDropDown.test.tsx b/public/app/core/components/sidemenu/SideMenuDropDown.test.tsx new file mode 100644 index 00000000000..c98d78ca021 --- /dev/null +++ b/public/app/core/components/sidemenu/SideMenuDropDown.test.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import SideMenuDropDown from './SideMenuDropDown'; + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + link: { + text: 'link', + }, + }, + propOverrides + ); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render children', () => { + const wrapper = setup({ + link: { + text: 'link', + children: [{ id: 1 }, { id: 2 }, { id: 3 }], + }, + }); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/SideMenuDropDown.tsx b/public/app/core/components/sidemenu/SideMenuDropDown.tsx new file mode 100644 index 00000000000..7cd7554f82c --- /dev/null +++ b/public/app/core/components/sidemenu/SideMenuDropDown.tsx @@ -0,0 +1,23 @@ +import React, { SFC } from 'react'; +import DropDownChild from './DropDownChild'; + +interface Props { + link: any; +} + +const SideMenuDropDown: SFC = props => { + const { link } = props; + return ( +
      +
    • + {link.text} +
    • + {link.children && + link.children.map((child, index) => { + return ; + })} +
    + ); +}; + +export default SideMenuDropDown; diff --git a/public/app/core/components/sidemenu/SignIn.test.tsx b/public/app/core/components/sidemenu/SignIn.test.tsx new file mode 100644 index 00000000000..c202926086f --- /dev/null +++ b/public/app/core/components/sidemenu/SignIn.test.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import SignIn from './SignIn'; + +describe('Render', () => { + it('should render component', () => { + const wrapper = shallow(); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/SignIn.tsx b/public/app/core/components/sidemenu/SignIn.tsx new file mode 100644 index 00000000000..17dd913823a --- /dev/null +++ b/public/app/core/components/sidemenu/SignIn.tsx @@ -0,0 +1,23 @@ +import React, { SFC } from 'react'; + +const SignIn: SFC = () => { + const loginUrl = `login?redirect=${encodeURIComponent(window.location.pathname)}`; + return ( + + ); +}; + +export default SignIn; diff --git a/public/app/core/components/sidemenu/TopSection.test.tsx b/public/app/core/components/sidemenu/TopSection.test.tsx new file mode 100644 index 00000000000..6ed01479833 --- /dev/null +++ b/public/app/core/components/sidemenu/TopSection.test.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import TopSection from './TopSection'; + +jest.mock('../../config', () => ({ + bootData: { + navTree: [ + { id: '1', hideFromMenu: true }, + { id: '2', hideFromMenu: true }, + { id: '3', hideFromMenu: false }, + { id: '4', hideFromMenu: true }, + ], + }, +})); + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + mainLinks: [], + }, + propOverrides + ); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); + + it('should render items', () => { + const wrapper = setup({ + mainLinks: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }], + }); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/TopSection.tsx b/public/app/core/components/sidemenu/TopSection.tsx new file mode 100644 index 00000000000..c6bf5df8242 --- /dev/null +++ b/public/app/core/components/sidemenu/TopSection.tsx @@ -0,0 +1,19 @@ +import React, { SFC } from 'react'; +import _ from 'lodash'; +import TopSectionItem from './TopSectionItem'; +import config from '../../config'; + +const TopSection: SFC = () => { + const navTree = _.cloneDeep(config.bootData.navTree); + const mainLinks = _.filter(navTree, item => !item.hideFromMenu); + + return ( +
    + {mainLinks.map((link, index) => { + return ; + })} +
    + ); +}; + +export default TopSection; diff --git a/public/app/core/components/sidemenu/TopSectionItem.test.tsx b/public/app/core/components/sidemenu/TopSectionItem.test.tsx new file mode 100644 index 00000000000..e7d3c4b7c75 --- /dev/null +++ b/public/app/core/components/sidemenu/TopSectionItem.test.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import TopSectionItem from './TopSectionItem'; + +const setup = (propOverrides?: object) => { + const props = Object.assign( + { + link: {}, + }, + propOverrides + ); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/sidemenu/TopSectionItem.tsx b/public/app/core/components/sidemenu/TopSectionItem.tsx new file mode 100644 index 00000000000..4a207cc0df9 --- /dev/null +++ b/public/app/core/components/sidemenu/TopSectionItem.tsx @@ -0,0 +1,23 @@ +import React, { SFC } from 'react'; +import SideMenuDropDown from './SideMenuDropDown'; + +export interface Props { + link: any; +} + +const TopSectionItem: SFC = props => { + const { link } = props; + return ( +
    + + + + {link.img && } + + + {link.children && } +
    + ); +}; + +export default TopSectionItem; diff --git a/public/app/core/components/sidemenu/__snapshots__/BottomNavLinks.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/BottomNavLinks.test.tsx.snap new file mode 100644 index 00000000000..f3181b617ad --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/BottomNavLinks.test.tsx.snap @@ -0,0 +1,163 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render children 1`] = ` + +`; + +exports[`Render should render component 1`] = ` +
    + + + +
      +
    • + +
    • +
    +
    +`; + +exports[`Render should render organisation switcher 1`] = ` + +`; + +exports[`Render should render subtitle 1`] = ` +
    + + + +
      +
    • + + subtitle + +
    • +
    • + +
    • +
    +
    +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/BottomSection.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/BottomSection.test.tsx.snap new file mode 100644 index 00000000000..ea92e8b7343 --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/BottomSection.test.tsx.snap @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` +
    + + + + +
    +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/DropDownChild.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/DropDownChild.test.tsx.snap new file mode 100644 index 00000000000..fcfd8ea936a --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/DropDownChild.test.tsx.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` +
  • + +
  • +`; + +exports[`Render should render icon if exists 1`] = ` +
  • + + + +
  • +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/SideMenu.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/SideMenu.test.tsx.snap new file mode 100644 index 00000000000..78e64209749 --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/SideMenu.test.tsx.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` +Array [ +
    , +
    , + , + , +] +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/SideMenuDropDown.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/SideMenuDropDown.test.tsx.snap new file mode 100644 index 00000000000..861168c1cc3 --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/SideMenuDropDown.test.tsx.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render children 1`] = ` +
      +
    • + + link + +
    • + + + +
    +`; + +exports[`Render should render component 1`] = ` +
      +
    • + + link + +
    • +
    +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/SignIn.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/SignIn.test.tsx.snap new file mode 100644 index 00000000000..ba21be63b51 --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/SignIn.test.tsx.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` + +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/TopSection.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/TopSection.test.tsx.snap new file mode 100644 index 00000000000..c78ec726302 --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/TopSection.test.tsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` +
    + +
    +`; + +exports[`Render should render items 1`] = ` +
    + +
    +`; diff --git a/public/app/core/components/sidemenu/__snapshots__/TopSectionItem.test.tsx.snap b/public/app/core/components/sidemenu/__snapshots__/TopSectionItem.test.tsx.snap new file mode 100644 index 00000000000..f7ff56bff6b --- /dev/null +++ b/public/app/core/components/sidemenu/__snapshots__/TopSectionItem.test.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` + +`; diff --git a/public/app/core/components/sidemenu/sidemenu.html b/public/app/core/components/sidemenu/sidemenu.html deleted file mode 100644 index 3a4ce11333e..00000000000 --- a/public/app/core/components/sidemenu/sidemenu.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - -  Close - - -
    - -
    - - \ No newline at end of file diff --git a/public/app/core/components/sidemenu/sidemenu.ts b/public/app/core/components/sidemenu/sidemenu.ts deleted file mode 100644 index f2798f874bd..00000000000 --- a/public/app/core/components/sidemenu/sidemenu.ts +++ /dev/null @@ -1,89 +0,0 @@ -import _ from 'lodash'; -import config from 'app/core/config'; -import $ from 'jquery'; -import coreModule from '../../core_module'; -import appEvents from 'app/core/app_events'; - -export class SideMenuCtrl { - user: any; - mainLinks: any; - bottomNav: any; - loginUrl: string; - isSignedIn: boolean; - isOpenMobile: boolean; - - /** @ngInject */ - constructor(private $scope, private $rootScope, private $location, private contextSrv, private $timeout) { - this.isSignedIn = contextSrv.isSignedIn; - this.user = contextSrv.user; - - const navTree = _.cloneDeep(config.bootData.navTree); - this.mainLinks = _.filter(navTree, item => !item.hideFromMenu); - this.bottomNav = _.filter(navTree, item => item.hideFromMenu); - this.loginUrl = 'login?redirect=' + encodeURIComponent(this.$location.path()); - - if (contextSrv.user.orgCount > 1) { - const profileNode = _.find(this.bottomNav, { id: 'profile' }); - if (profileNode) { - profileNode.showOrgSwitcher = true; - } - } - - this.$scope.$on('$routeChangeSuccess', () => { - this.loginUrl = 'login?redirect=' + encodeURIComponent(this.$location.path()); - }); - } - - toggleSideMenu() { - this.contextSrv.toggleSideMenu(); - appEvents.emit('toggle-sidemenu'); - - this.$timeout(() => { - this.$rootScope.$broadcast('render'); - }); - } - - toggleSideMenuSmallBreakpoint() { - appEvents.emit('toggle-sidemenu-mobile'); - } - - switchOrg() { - this.$rootScope.appEvent('show-modal', { - templateHtml: '', - }); - } - - itemClicked(item, evt) { - if (item.url === '/shortcuts') { - appEvents.emit('show-modal', { - templateHtml: '', - }); - evt.preventDefault(); - } - } -} - -export function sideMenuDirective() { - return { - restrict: 'E', - templateUrl: 'public/app/core/components/sidemenu/sidemenu.html', - controller: SideMenuCtrl, - bindToController: true, - controllerAs: 'ctrl', - scope: {}, - link: function(scope, elem) { - // hack to hide dropdown menu - elem.on('click.dropdown', '.dropdown-menu a', function(evt) { - const menu = $(evt.target).parents('.dropdown-menu'); - const parent = menu.parent(); - menu.detach(); - - setTimeout(function() { - parent.append(menu); - }, 100); - }); - }, - }; -} - -coreModule.directive('sidemenu', sideMenuDirective); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index bff98e1fbb3..173d6b80b15 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -20,7 +20,6 @@ import './services/search_srv'; import './services/ng_react'; import { grafanaAppDirective } from './components/grafana_app'; -import { sideMenuDirective } from './components/sidemenu/sidemenu'; import { searchDirective } from './components/search/search'; import { infoPopover } from './components/info_popover'; import { navbarDirective } from './components/navbar/navbar'; @@ -62,7 +61,6 @@ export { arrayJoin, coreModule, grafanaAppDirective, - sideMenuDirective, navbarDirective, searchDirective, liveSrv, diff --git a/public/app/core/services/context_srv.ts b/public/app/core/services/context_srv.ts index c2742c82958..c40fbff2ab2 100644 --- a/public/app/core/services/context_srv.ts +++ b/public/app/core/services/context_srv.ts @@ -8,6 +8,8 @@ export class User { isSignedIn: any; orgRole: any; orgId: number; + orgName: string; + orgCount: number; timezone: string; helpFlags1: number; lightTheme: boolean;