mirror of
https://github.com/ansible/awx.git
synced 2026-07-28 00:19:54 -02:30
Update active nav item based on url
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { HashRouter as Router } from 'react-router-dom';
|
||||||
import { shallow, mount } from 'enzyme';
|
import { shallow, mount } from 'enzyme';
|
||||||
|
import { createMemoryHistory } from 'history'
|
||||||
|
|
||||||
import App from '../src/App';
|
import App from '../src/App';
|
||||||
import api from '../src/api';
|
import api from '../src/api';
|
||||||
import { API_LOGOUT } from '../src/endpoints';
|
import { API_LOGOUT } from '../src/endpoints';
|
||||||
@@ -21,7 +24,7 @@ describe('<App />', () => {
|
|||||||
api.isAuthenticated = jest.fn();
|
api.isAuthenticated = jest.fn();
|
||||||
api.isAuthenticated.mockReturnValue(false);
|
api.isAuthenticated.mockReturnValue(false);
|
||||||
|
|
||||||
const appWrapper = mount(<App />);
|
const appWrapper = mount(<Router><App /></Router>);
|
||||||
|
|
||||||
const login = appWrapper.find(Login);
|
const login = appWrapper.find(Login);
|
||||||
expect(login.length).toBe(1);
|
expect(login.length).toBe(1);
|
||||||
@@ -33,7 +36,7 @@ describe('<App />', () => {
|
|||||||
api.isAuthenticated = jest.fn();
|
api.isAuthenticated = jest.fn();
|
||||||
api.isAuthenticated.mockReturnValue(true);
|
api.isAuthenticated.mockReturnValue(true);
|
||||||
|
|
||||||
const appWrapper = mount(<App />);
|
const appWrapper = mount(<Router><App /></Router>);
|
||||||
|
|
||||||
const dashboard = appWrapper.find(Dashboard);
|
const dashboard = appWrapper.find(Dashboard);
|
||||||
expect(dashboard.length).toBe(1);
|
expect(dashboard.length).toBe(1);
|
||||||
@@ -42,39 +45,47 @@ describe('<App />', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('onNavSelect sets state.activeItem and state.activeGroup', () => {
|
test('onNavSelect sets state.activeItem and state.activeGroup', () => {
|
||||||
const appWrapper = shallow(<App />);
|
const history = createMemoryHistory('/jobs');
|
||||||
appWrapper.instance().onNavSelect({ itemId: 'foo', groupId: 'bar' });
|
const appWrapper = shallow(<App.WrappedComponent history={history} />);
|
||||||
expect(appWrapper.state().activeItem).toBe('foo');
|
|
||||||
|
appWrapper.instance().onNavSelect({ groupId: 'bar' });
|
||||||
expect(appWrapper.state().activeGroup).toBe('bar');
|
expect(appWrapper.state().activeGroup).toBe('bar');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('onNavToggle sets state.isNavOpen to opposite', () => {
|
test('onNavToggle sets state.isNavOpen to opposite', () => {
|
||||||
const appWrapper = shallow(<App />);
|
const history = createMemoryHistory('/jobs');
|
||||||
|
|
||||||
|
const appWrapper = shallow(<App.WrappedComponent history={history} />);
|
||||||
expect(appWrapper.state().isNavOpen).toBe(true);
|
expect(appWrapper.state().isNavOpen).toBe(true);
|
||||||
appWrapper.instance().onNavToggle();
|
appWrapper.instance().onNavToggle();
|
||||||
expect(appWrapper.state().isNavOpen).toBe(false);
|
expect(appWrapper.state().isNavOpen).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('onLogoClick sets selected nav back to defaults', () => {
|
test('onLogoClick sets selected nav back to defaults', () => {
|
||||||
const appWrapper = shallow(<App />);
|
const history = createMemoryHistory('/jobs');
|
||||||
|
|
||||||
|
const appWrapper = shallow(<App.WrappedComponent history={history} />);
|
||||||
appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' });
|
appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' });
|
||||||
expect(appWrapper.state().activeItem).toBe('bar');
|
expect(appWrapper.state().activeItem).toBe('bar');
|
||||||
expect(appWrapper.state().activeGroup).toBe('foo');
|
expect(appWrapper.state().activeGroup).toBe('foo');
|
||||||
appWrapper.instance().onLogoClick();
|
appWrapper.instance().onLogoClick();
|
||||||
expect(appWrapper.state().activeItem).toBe(DEFAULT_ACTIVE_ITEM);
|
|
||||||
expect(appWrapper.state().activeGroup).toBe(DEFAULT_ACTIVE_GROUP);
|
expect(appWrapper.state().activeGroup).toBe(DEFAULT_ACTIVE_GROUP);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('api.logout called from logout button', async () => {
|
test('api.logout called from logout button', async () => {
|
||||||
api.get = jest.fn().mockImplementation(() => Promise.resolve({}));
|
api.get = jest.fn().mockImplementation(() => Promise.resolve({}));
|
||||||
const appWrapper = mount(<App />);
|
let appWrapper = mount(<Router><App /></Router>);
|
||||||
const logoutButton = appWrapper.find('LogoutButton');
|
let logoutButton = appWrapper.find('LogoutButton');
|
||||||
logoutButton.props().onDevLogout();
|
logoutButton.props().onDevLogout();
|
||||||
appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' });
|
appWrapper.setState({ activeGroup: 'foo', activeItem: 'bar' });
|
||||||
|
|
||||||
|
await asyncFlush();
|
||||||
|
|
||||||
expect(api.get).toHaveBeenCalledTimes(1);
|
expect(api.get).toHaveBeenCalledTimes(1);
|
||||||
expect(api.get).toHaveBeenCalledWith(API_LOGOUT);
|
expect(api.get).toHaveBeenCalledWith(API_LOGOUT);
|
||||||
await asyncFlush();
|
|
||||||
expect(appWrapper.state().activeItem).toBe(DEFAULT_ACTIVE_ITEM);
|
console.log(appWrapper.state());
|
||||||
expect(appWrapper.state().activeGroup).toBe(DEFAULT_ACTIVE_GROUP);
|
expect(appWrapper.state().activeGroup).toBe(DEFAULT_ACTIVE_GROUP);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
69
src/App.jsx
69
src/App.jsx
@@ -1,8 +1,8 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import {
|
import {
|
||||||
HashRouter as Router,
|
|
||||||
Redirect,
|
Redirect,
|
||||||
Switch,
|
Switch,
|
||||||
|
withRouter
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -61,13 +61,11 @@ class App extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
isNavOpen,
|
isNavOpen,
|
||||||
activeGroup: 'views_group',
|
activeGroup: 'views_group',
|
||||||
activeItem: 'views_group_dashboard'
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onNavSelect = result => {
|
onNavSelect = result => {
|
||||||
this.setState({
|
this.setState({
|
||||||
activeItem: result.itemId,
|
|
||||||
activeGroup: result.groupId
|
activeGroup: result.groupId
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -77,16 +75,31 @@ class App extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onLogoClick = () => {
|
onLogoClick = () => {
|
||||||
this.setState({ activeGroup: 'views_group', activeItem: 'views_group_dashboard' });
|
this.setState({ activeGroup: 'views_group' });
|
||||||
}
|
}
|
||||||
|
|
||||||
onDevLogout = async () => {
|
onDevLogout = async () => {
|
||||||
|
console.log('called')
|
||||||
await api.get(API_LOGOUT);
|
await api.get(API_LOGOUT);
|
||||||
this.setState({ activeGroup: 'views_group', activeItem: 'views_group_dashboard' });
|
this.setState({ activeGroup: 'views_group', activeItem: 'views_group_dashboard' });
|
||||||
|
|
||||||
|
console.log(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expand = (path, group) => {
|
||||||
|
const { history } = this.props;
|
||||||
|
const { activeGroup } = this.state;
|
||||||
|
|
||||||
|
const currentPath = history.location.pathname.split('/')[1];
|
||||||
|
if ((path === currentPath) && (group !== activeGroup)) {
|
||||||
|
this.setState({ activeGroup: group });
|
||||||
|
}
|
||||||
|
return (path === currentPath);
|
||||||
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { activeItem, activeGroup, isNavOpen } = this.state;
|
console.log('render');
|
||||||
|
const { activeGroup, isNavOpen } = this.state;
|
||||||
const { logo, loginInfo } = this.props;
|
const { logo, loginInfo } = this.props;
|
||||||
|
|
||||||
const PageToolbar = (
|
const PageToolbar = (
|
||||||
@@ -103,7 +116,6 @@ class App extends React.Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<BackgroundImage
|
<BackgroundImage
|
||||||
src={{
|
src={{
|
||||||
@@ -146,7 +158,7 @@ class App extends React.Component {
|
|||||||
to="#/home"
|
to="#/home"
|
||||||
groupId="views_group"
|
groupId="views_group"
|
||||||
itemId="views_group_dashboard"
|
itemId="views_group_dashboard"
|
||||||
isActive={activeItem === 'views_group_dashboard'}
|
isActive={this.expand('home', 'views_group')}
|
||||||
>
|
>
|
||||||
Dashboard
|
Dashboard
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -154,7 +166,7 @@ class App extends React.Component {
|
|||||||
to="#/jobs"
|
to="#/jobs"
|
||||||
groupId="views_group"
|
groupId="views_group"
|
||||||
itemId="views_group_jobs"
|
itemId="views_group_jobs"
|
||||||
isActive={activeItem === 'views_group_jobs'}
|
isActive={this.expand('jobs', 'views_group')}
|
||||||
>
|
>
|
||||||
Jobs
|
Jobs
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -162,7 +174,7 @@ class App extends React.Component {
|
|||||||
to="#/schedules"
|
to="#/schedules"
|
||||||
groupId="views_group"
|
groupId="views_group"
|
||||||
itemId="views_group_schedules"
|
itemId="views_group_schedules"
|
||||||
isActive={activeItem === 'views_group_schedules'}
|
isActive={this.expand('schedules', 'views_group')}
|
||||||
>
|
>
|
||||||
Schedules
|
Schedules
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -170,7 +182,7 @@ class App extends React.Component {
|
|||||||
to="#/portal"
|
to="#/portal"
|
||||||
groupId="views_group"
|
groupId="views_group"
|
||||||
itemId="views_group_portal"
|
itemId="views_group_portal"
|
||||||
isActive={activeItem === 'views_group_portal'}
|
isActive={this.expand('portal', 'views_group')}
|
||||||
>
|
>
|
||||||
My View
|
My View
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -185,7 +197,7 @@ class App extends React.Component {
|
|||||||
to="#/templates"
|
to="#/templates"
|
||||||
groupId="resources_group"
|
groupId="resources_group"
|
||||||
itemId="resources_group_templates"
|
itemId="resources_group_templates"
|
||||||
isActive={activeItem === 'resources_group_templates'}
|
isActive={this.expand('templates', 'resources_group')}
|
||||||
>
|
>
|
||||||
Templates
|
Templates
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -193,7 +205,7 @@ class App extends React.Component {
|
|||||||
to="#/credentials"
|
to="#/credentials"
|
||||||
groupId="resources_group"
|
groupId="resources_group"
|
||||||
itemId="resources_group_credentials"
|
itemId="resources_group_credentials"
|
||||||
isActive={activeItem === 'resources_group_credentials'}
|
isActive={this.expand('credentials', 'resources_group')}
|
||||||
>
|
>
|
||||||
Credentials
|
Credentials
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -201,7 +213,7 @@ class App extends React.Component {
|
|||||||
to="#/projects"
|
to="#/projects"
|
||||||
groupId="resources_group"
|
groupId="resources_group"
|
||||||
itemId="resources_group_projects"
|
itemId="resources_group_projects"
|
||||||
isActive={activeItem === 'resources_group_projects'}
|
isActive={this.expand('projects', 'resources_group')}
|
||||||
>
|
>
|
||||||
Projects
|
Projects
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -209,7 +221,7 @@ class App extends React.Component {
|
|||||||
to="#/inventories"
|
to="#/inventories"
|
||||||
groupId="resources_group"
|
groupId="resources_group"
|
||||||
itemId="resources_group_inventories"
|
itemId="resources_group_inventories"
|
||||||
isActive={activeItem === 'resources_group_inventories'}
|
isActive={this.expand('inventories', 'resources_group')}
|
||||||
>
|
>
|
||||||
Inventories
|
Inventories
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -217,7 +229,7 @@ class App extends React.Component {
|
|||||||
to="#/inventory_scripts"
|
to="#/inventory_scripts"
|
||||||
groupId="resources_group"
|
groupId="resources_group"
|
||||||
itemId="resources_group_inventory_scripts"
|
itemId="resources_group_inventory_scripts"
|
||||||
isActive={activeItem === 'resources_group_inventory_scripts'}
|
isActive={this.expand('inventory_scripts', 'resources_group')}
|
||||||
>
|
>
|
||||||
Inventory Scripts
|
Inventory Scripts
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -232,7 +244,7 @@ class App extends React.Component {
|
|||||||
to="#/organizations"
|
to="#/organizations"
|
||||||
groupId="access_group"
|
groupId="access_group"
|
||||||
itemId="access_group_organizations"
|
itemId="access_group_organizations"
|
||||||
isActive={activeItem === 'access_group_organizations'}
|
isActive={this.expand('organizations', 'access_group')}
|
||||||
>
|
>
|
||||||
Organizations
|
Organizations
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -240,7 +252,7 @@ class App extends React.Component {
|
|||||||
to="#/users"
|
to="#/users"
|
||||||
groupId="access_group"
|
groupId="access_group"
|
||||||
itemId="access_group_users"
|
itemId="access_group_users"
|
||||||
isActive={activeItem === 'access_group_users'}
|
isActive={this.expand('users', 'access_group')}
|
||||||
>
|
>
|
||||||
Users
|
Users
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -248,7 +260,7 @@ class App extends React.Component {
|
|||||||
to="#/teams"
|
to="#/teams"
|
||||||
groupId="access_group"
|
groupId="access_group"
|
||||||
itemId="access_group_teams"
|
itemId="access_group_teams"
|
||||||
isActive={activeItem === 'access_group_teams'}
|
isActive={this.expand('teams', 'access_group')}
|
||||||
>
|
>
|
||||||
Teams
|
Teams
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -263,7 +275,7 @@ class App extends React.Component {
|
|||||||
to="#/credential_types"
|
to="#/credential_types"
|
||||||
groupId="administration_group"
|
groupId="administration_group"
|
||||||
itemId="administration_group_credential_types"
|
itemId="administration_group_credential_types"
|
||||||
isActive={activeItem === 'administration_group_credential_types'}
|
isActive={this.expand('credential_types', 'administration_group')}
|
||||||
>
|
>
|
||||||
Credential Types
|
Credential Types
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -271,7 +283,7 @@ class App extends React.Component {
|
|||||||
to="#/notification_templates"
|
to="#/notification_templates"
|
||||||
groupId="administration_group"
|
groupId="administration_group"
|
||||||
itemId="administration_group_notification_templates"
|
itemId="administration_group_notification_templates"
|
||||||
isActive={activeItem === 'administration_group_notification_templates'}
|
isActive={this.expand('notification_templates', 'administration_group')}
|
||||||
>
|
>
|
||||||
Notification Templates
|
Notification Templates
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -279,7 +291,7 @@ class App extends React.Component {
|
|||||||
to="#/management_jobs"
|
to="#/management_jobs"
|
||||||
groupId="administration_group"
|
groupId="administration_group"
|
||||||
itemId="administration_group_management_jobs"
|
itemId="administration_group_management_jobs"
|
||||||
isActive={activeItem === 'administration_group_management_jobs'}
|
isActive={this.expand('management_jobs', 'administration_group')}
|
||||||
>
|
>
|
||||||
Management Jobs
|
Management Jobs
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -287,7 +299,7 @@ class App extends React.Component {
|
|||||||
to="#/instance_groups"
|
to="#/instance_groups"
|
||||||
groupId="administration_group"
|
groupId="administration_group"
|
||||||
itemId="administration_group_instance_groups"
|
itemId="administration_group_instance_groups"
|
||||||
isActive={activeItem === 'administration_group_instance_groups'}
|
isActive={this.expand('instance_groups', 'administration_group')}
|
||||||
>
|
>
|
||||||
Instance Groups
|
Instance Groups
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -295,7 +307,7 @@ class App extends React.Component {
|
|||||||
to="#/applications"
|
to="#/applications"
|
||||||
groupId="administration_group"
|
groupId="administration_group"
|
||||||
itemId="administration_group_applications"
|
itemId="administration_group_applications"
|
||||||
isActive={activeItem === 'administration_group_applications'}
|
isActive={this.expand('applications', 'administration_group')}
|
||||||
>
|
>
|
||||||
Applications
|
Applications
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -310,7 +322,7 @@ class App extends React.Component {
|
|||||||
to="#/auth_settings"
|
to="#/auth_settings"
|
||||||
groupId="settings_group"
|
groupId="settings_group"
|
||||||
itemId="settings_group_auth"
|
itemId="settings_group_auth"
|
||||||
isActive={activeItem === 'settings_group_auth'}
|
isActive={this.expand('auth_settings', 'settings_group')}
|
||||||
>
|
>
|
||||||
Authentication
|
Authentication
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -318,7 +330,7 @@ class App extends React.Component {
|
|||||||
to="#/jobs_settings"
|
to="#/jobs_settings"
|
||||||
groupId="settings_group"
|
groupId="settings_group"
|
||||||
itemId="settings_group_jobs"
|
itemId="settings_group_jobs"
|
||||||
isActive={activeItem === 'settings_group_jobs'}
|
isActive={this.expand('jobs_settings', 'settings_group')}
|
||||||
>
|
>
|
||||||
Jobs
|
Jobs
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -326,7 +338,7 @@ class App extends React.Component {
|
|||||||
to="#/system_settings"
|
to="#/system_settings"
|
||||||
groupId="settings_group"
|
groupId="settings_group"
|
||||||
itemId="settings_group_system"
|
itemId="settings_group_system"
|
||||||
isActive={activeItem === 'settings_group_system'}
|
isActive={this.expand('system_settings', 'settings_group')}
|
||||||
>
|
>
|
||||||
System
|
System
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -334,7 +346,7 @@ class App extends React.Component {
|
|||||||
to="#/ui_settings"
|
to="#/ui_settings"
|
||||||
groupId="settings_group"
|
groupId="settings_group"
|
||||||
itemId="settings_group_ui"
|
itemId="settings_group_ui"
|
||||||
isActive={activeItem === 'settings_group_ui'}
|
isActive={this.expand('ui_settings', 'settings_group')}
|
||||||
>
|
>
|
||||||
User Interface
|
User Interface
|
||||||
</NavItem>
|
</NavItem>
|
||||||
@@ -373,9 +385,8 @@ class App extends React.Component {
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
</Router>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default withRouter(App);
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
|
|
||||||
|
import {
|
||||||
|
HashRouter as Router
|
||||||
|
} from 'react-router-dom';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import api from './api';
|
import api from './api';
|
||||||
import { API_ROOT } from './endpoints';
|
import { API_ROOT } from './endpoints';
|
||||||
@@ -16,7 +19,7 @@ const el = document.getElementById('app');
|
|||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const { custom_logo, custom_login_info } = await api.get(API_ROOT);
|
const { custom_logo, custom_login_info } = await api.get(API_ROOT);
|
||||||
render(<App logo={custom_logo} loginInfo={custom_login_info} />, el);
|
render(<Router><App logo={custom_logo} loginInfo={custom_login_info} /></Router>, el);
|
||||||
};
|
};
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|||||||
Reference in New Issue
Block a user