diff --git a/__tests__/App.test.jsx b/__tests__/App.test.jsx index e07a1984d5..7b98adafff 100644 --- a/__tests__/App.test.jsx +++ b/__tests__/App.test.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { HashRouter as Router } from 'react-router-dom'; import { shallow, mount } from 'enzyme'; import App from '../src/App'; import api from '../src/api'; @@ -21,7 +22,7 @@ describe('', () => { api.isAuthenticated = jest.fn(); api.isAuthenticated.mockReturnValue(false); - const appWrapper = mount(); + const appWrapper = mount(); const login = appWrapper.find(Login); expect(login.length).toBe(1); @@ -33,7 +34,7 @@ describe('', () => { api.isAuthenticated = jest.fn(); api.isAuthenticated.mockReturnValue(true); - const appWrapper = mount(); + const appWrapper = mount(); const dashboard = appWrapper.find(Dashboard); expect(dashboard.length).toBe(1); @@ -41,35 +42,26 @@ describe('', () => { expect(login.length).toBe(0); }); - test('onNavSelect sets state.activeItem and state.activeGroup', () => { - const appWrapper = shallow(); - appWrapper.instance().onNavSelect({ itemId: 'foo', groupId: 'bar' }); - expect(appWrapper.state().activeItem).toBe('foo'); - expect(appWrapper.state().activeGroup).toBe('bar'); - }); - test('onNavToggle sets state.isNavOpen to opposite', () => { - const appWrapper = shallow(); + const appWrapper = shallow(); expect(appWrapper.state().isNavOpen).toBe(true); appWrapper.instance().onNavToggle(); expect(appWrapper.state().isNavOpen).toBe(false); }); test('onLogoClick sets selected nav back to defaults', () => { - const appWrapper = shallow(); + const appWrapper = shallow(); appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' }); expect(appWrapper.state().activeItem).toBe('bar'); expect(appWrapper.state().activeGroup).toBe('foo'); appWrapper.instance().onLogoClick(); - expect(appWrapper.state().activeItem).toBe(DEFAULT_ACTIVE_ITEM); expect(appWrapper.state().activeGroup).toBe(DEFAULT_ACTIVE_GROUP); }); test('api.logout called from logout button', async () => { api.get = jest.fn().mockImplementation(() => Promise.resolve({})); - const appWrapper = mount(); - const logoutButton = appWrapper.find('LogoutButton'); - logoutButton.props().onDevLogout(); + const appWrapper = shallow(); + appWrapper.instance().onDevLogout(); appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' }); expect(api.get).toHaveBeenCalledTimes(1); expect(api.get).toHaveBeenCalledWith(API_LOGOUT); diff --git a/src/App.jsx b/src/App.jsx index 62edb76d3a..f400ce3e53 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,8 +1,8 @@ import React, { Fragment } from 'react'; import { - HashRouter as Router, Redirect, Switch, + withRouter } from 'react-router-dom'; import { @@ -53,31 +53,58 @@ import Teams from './pages/Teams'; import Templates from './pages/Templates'; import Users from './pages/Users'; +const SideNavItems = ({ items, history }) => { + const currentPath = history.location.pathname.split('/')[1]; + let activeGroup; + if (currentPath !== '') { + [{ groupName: activeGroup }] = items + .map(({ groupName, routes }) => ({ + groupName, + paths: routes.map(({ path }) => path) + })) + .filter(({ paths }) => paths.indexOf(currentPath) > -1); + } else { + activeGroup = 'views'; + } + + return (items.map(({ title, groupName, routes }) => ( + + {routes.map(({ path, title: itemTitle }) => ( + + {itemTitle} + + ))} + + ))); +}; + class App extends React.Component { constructor (props) { super(props); const isNavOpen = typeof window !== 'undefined' && window.innerWidth >= parseInt(breakpointMd.value, 10); this.state = { - isNavOpen, - activeGroup: 'views_group', - activeItem: 'views_group_dashboard' + isNavOpen }; } - onNavSelect = result => { - this.setState({ - activeItem: result.itemId, - activeGroup: result.groupId - }); - }; - onNavToggle = () => { this.setState(({ isNavOpen }) => ({ isNavOpen: !isNavOpen })); }; onLogoClick = () => { - this.setState({ activeGroup: 'views_group', activeItem: 'views_group_dashboard' }); + this.setState({ activeGroup: 'views_group' }); } onDevLogout = async () => { @@ -86,8 +113,8 @@ class App extends React.Component { } render () { - const { activeItem, activeGroup, isNavOpen } = this.state; - const { logo, loginInfo } = this.props; + const { isNavOpen } = this.state; + const { logo, loginInfo, history } = this.props; const PageToolbar = ( @@ -103,279 +130,197 @@ class App extends React.Component { ); return ( - - - - - api.isAuthenticated()} redirectPath="/" path="/login" component={() => } /> - - } - toolbar={PageToolbar} - showNavToggle - onNavToggle={this.onNavToggle} - /> - )} - sidebar={( - - - - - Dashboard - - - Jobs - - - Schedules - - - My View - - - - - Templates - - - Credentials - - - Projects - - - Inventories - - - Inventory Scripts - - - - - Organizations - - - Users - - - Teams - - - - - Credential Types - - - Notification Templates - - - Management Jobs - - - Instance Groups - - - Applications - - - - - Authentication - - - Jobs - - - System - - - User Interface - - - - - )} - /> - )} - useCondensed - > - !api.isAuthenticated()} redirectPath="/login" exact path="/" component={() => ()} /> - !api.isAuthenticated()} redirectPath="/login" path="/home" component={Dashboard} /> - !api.isAuthenticated()} redirectPath="/login" path="/jobs" component={Jobs} /> - !api.isAuthenticated()} redirectPath="/login" path="/schedules" component={Schedules} /> - !api.isAuthenticated()} redirectPath="/login" path="/portal" component={Portal} /> - !api.isAuthenticated()} redirectPath="/login" path="/templates" component={Templates} /> - !api.isAuthenticated()} redirectPath="/login" path="/credentials" component={Credentials} /> - !api.isAuthenticated()} redirectPath="/login" path="/projects" component={Projects} /> - !api.isAuthenticated()} redirectPath="/login" path="/inventories" component={Inventories} /> - !api.isAuthenticated()} redirectPath="/login" path="/inventory_scripts" component={InventoryScripts} /> - !api.isAuthenticated()} redirectPath="/login" path="/organizations" component={Organizations} /> - !api.isAuthenticated()} redirectPath="/login" path="/users" component={Users} /> - !api.isAuthenticated()} redirectPath="/login" path="/teams" component={Teams} /> - !api.isAuthenticated()} redirectPath="/login" path="/credential_types" component={CredentialTypes} /> - !api.isAuthenticated()} redirectPath="/login" path="/notification_templates" component={NotificationTemplates} /> - !api.isAuthenticated()} redirectPath="/login" path="/management_jobs" component={ManagementJobs} /> - !api.isAuthenticated()} redirectPath="/login" path="/instance_groups" component={InstanceGroups} /> - !api.isAuthenticated()} redirectPath="/login" path="/applications" component={Applications} /> - !api.isAuthenticated()} redirectPath="/login" path="/auth_settings" component={AuthSettings} /> - !api.isAuthenticated()} redirectPath="/login" path="/jobs_settings" component={JobsSettings} /> - !api.isAuthenticated()} redirectPath="/login" path="/system_settings" component={SystemSettings} /> - !api.isAuthenticated()} redirectPath="/login" path="/ui_settings" component={UISettings} /> - !api.isAuthenticated()} redirectPath="/login" path="/license" component={License} /> - - - - - + + + + api.isAuthenticated()} redirectPath="/" path="/login" component={() => } /> + + } + toolbar={PageToolbar} + showNavToggle + onNavToggle={this.onNavToggle} + /> + )} + sidebar={( + + + + + + )} + /> + )} + useCondensed + > + !api.isAuthenticated()} redirectPath="/login" exact path="/" component={() => ()} /> + !api.isAuthenticated()} redirectPath="/login" path="/home" component={Dashboard} /> + !api.isAuthenticated()} redirectPath="/login" path="/jobs" component={Jobs} /> + !api.isAuthenticated()} redirectPath="/login" path="/schedules" component={Schedules} /> + !api.isAuthenticated()} redirectPath="/login" path="/portal" component={Portal} /> + !api.isAuthenticated()} redirectPath="/login" path="/templates" component={Templates} /> + !api.isAuthenticated()} redirectPath="/login" path="/credentials" component={Credentials} /> + !api.isAuthenticated()} redirectPath="/login" path="/projects" component={Projects} /> + !api.isAuthenticated()} redirectPath="/login" path="/inventories" component={Inventories} /> + !api.isAuthenticated()} redirectPath="/login" path="/inventory_scripts" component={InventoryScripts} /> + !api.isAuthenticated()} redirectPath="/login" path="/organizations" component={Organizations} /> + !api.isAuthenticated()} redirectPath="/login" path="/users" component={Users} /> + !api.isAuthenticated()} redirectPath="/login" path="/teams" component={Teams} /> + !api.isAuthenticated()} redirectPath="/login" path="/credential_types" component={CredentialTypes} /> + !api.isAuthenticated()} redirectPath="/login" path="/notification_templates" component={NotificationTemplates} /> + !api.isAuthenticated()} redirectPath="/login" path="/management_jobs" component={ManagementJobs} /> + !api.isAuthenticated()} redirectPath="/login" path="/instance_groups" component={InstanceGroups} /> + !api.isAuthenticated()} redirectPath="/login" path="/applications" component={Applications} /> + !api.isAuthenticated()} redirectPath="/login" path="/auth_settings" component={AuthSettings} /> + !api.isAuthenticated()} redirectPath="/login" path="/jobs_settings" component={JobsSettings} /> + !api.isAuthenticated()} redirectPath="/login" path="/system_settings" component={SystemSettings} /> + !api.isAuthenticated()} redirectPath="/login" path="/ui_settings" component={UISettings} /> + !api.isAuthenticated()} redirectPath="/login" path="/license" component={License} /> + + + + ); } } -export default App; +export default withRouter(App); diff --git a/src/index.jsx b/src/index.jsx index cd653d3c53..24a5eb8576 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,6 +1,9 @@ import React from 'react'; import { render } from 'react-dom'; +import { + HashRouter as Router +} from 'react-router-dom'; import App from './App'; import api from './api'; import { API_ROOT } from './endpoints'; @@ -15,8 +18,8 @@ import './components/DataListToolbar/styles.scss'; const el = document.getElementById('app'); const main = async () => { - const { custom_logo, custom_login_info } = await api.get(API_ROOT); - render(, el); + const { custom_logo, custom_login_info } = await api.get(API_ROOT); + render(, el); }; main();