mirror of
https://github.com/ansible/awx.git
synced 2026-07-28 08:29:55 -02:30
decouple App and Login components
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { HashRouter as Router } from 'react-router-dom';
|
import { HashRouter as Router } from 'react-router-dom';
|
||||||
|
|
||||||
import { shallow, mount } from 'enzyme';
|
import { shallow, mount } from 'enzyme';
|
||||||
import App from '../src/App';
|
import App from '../src/App';
|
||||||
import api from '../src/api';
|
import api from '../src/api';
|
||||||
import { API_LOGOUT, API_CONFIG } from '../src/endpoints';
|
import { API_LOGOUT, API_CONFIG } from '../src/endpoints';
|
||||||
|
|
||||||
import Dashboard from '../src/pages/Dashboard';
|
import Dashboard from '../src/pages/Dashboard';
|
||||||
import Login from '../src/pages/Login';
|
|
||||||
import { asyncFlush } from '../jest.setup';
|
import { asyncFlush } from '../jest.setup';
|
||||||
|
|
||||||
const DEFAULT_ACTIVE_GROUP = 'views_group';
|
const DEFAULT_ACTIVE_GROUP = 'views_group';
|
||||||
@@ -24,30 +24,6 @@ describe('<App />', () => {
|
|||||||
expect(appWrapper.length).toBe(1);
|
expect(appWrapper.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders login page when not authenticated', () => {
|
|
||||||
api.isAuthenticated = jest.fn();
|
|
||||||
api.isAuthenticated.mockReturnValue(false);
|
|
||||||
|
|
||||||
const appWrapper = mount(<Router><App /></Router>);
|
|
||||||
|
|
||||||
const login = appWrapper.find(Login);
|
|
||||||
expect(login.length).toBe(1);
|
|
||||||
const dashboard = appWrapper.find(Dashboard);
|
|
||||||
expect(dashboard.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('renders dashboard when authenticated', () => {
|
|
||||||
api.isAuthenticated = jest.fn();
|
|
||||||
api.isAuthenticated.mockReturnValue(true);
|
|
||||||
|
|
||||||
const appWrapper = mount(<Router><App routeGroups={routeGroups} /></Router>);
|
|
||||||
|
|
||||||
const dashboard = appWrapper.find(Dashboard);
|
|
||||||
expect(dashboard.length).toBe(1);
|
|
||||||
const login = appWrapper.find(Login);
|
|
||||||
expect(login.length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('onNavToggle sets state.isNavOpen to opposite', () => {
|
test('onNavToggle sets state.isNavOpen to opposite', () => {
|
||||||
const appWrapper = shallow(<App />);
|
const appWrapper = shallow(<App />);
|
||||||
expect(appWrapper.state().isNavOpen).toBe(true);
|
expect(appWrapper.state().isNavOpen).toBe(true);
|
||||||
|
|||||||
71
src/App.jsx
71
src/App.jsx
@@ -1,6 +1,4 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { ConfigContext } from './context';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Redirect,
|
Redirect,
|
||||||
Switch,
|
Switch,
|
||||||
@@ -20,14 +18,14 @@ import { global_breakpoint_md as breakpointMd } from '@patternfly/react-tokens';
|
|||||||
|
|
||||||
import api from './api';
|
import api from './api';
|
||||||
import { API_LOGOUT, API_CONFIG } from './endpoints';
|
import { API_LOGOUT, API_CONFIG } from './endpoints';
|
||||||
|
import { ConfigContext } from './context';
|
||||||
|
|
||||||
import Login from './pages/Login';
|
|
||||||
import HelpDropdown from './components/HelpDropdown';
|
import HelpDropdown from './components/HelpDropdown';
|
||||||
import LogoutButton from './components/LogoutButton';
|
import LogoutButton from './components/LogoutButton';
|
||||||
import TowerLogo from './components/TowerLogo';
|
import TowerLogo from './components/TowerLogo';
|
||||||
import NavExpandableGroup from './components/NavExpandableGroup';
|
import NavExpandableGroup from './components/NavExpandableGroup';
|
||||||
|
|
||||||
class App extends React.Component {
|
class App extends Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -47,13 +45,21 @@ class App extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onLogoClick = () => {
|
onLogoClick = () => {
|
||||||
this.setState({ activeGroup: 'views_group' });
|
this.setState({
|
||||||
|
activeGroup: 'views_group'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onDevLogout = async () => {
|
onDevLogout = async () => {
|
||||||
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',
|
||||||
|
});
|
||||||
|
|
||||||
|
window.location.replace('/#/login');
|
||||||
|
};
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
// Grab our config data from the API and store in state
|
// Grab our config data from the API and store in state
|
||||||
@@ -67,18 +73,9 @@ class App extends React.Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { config, isNavOpen } = this.state;
|
const { config, isNavOpen } = this.state;
|
||||||
const { logo, loginInfo, navLabel, routeGroups = [] } = this.props;
|
const { navLabel = '', routeGroups = [] } = this.props;
|
||||||
|
|
||||||
return (
|
const header = (
|
||||||
api.isAuthenticated () ? (
|
|
||||||
<Switch>
|
|
||||||
<Route path="/login" render={() => <Redirect to='/home' />} />
|
|
||||||
<Route exact path="/" render={() => <Redirect to='/home' />} />
|
|
||||||
<Route render={() => (
|
|
||||||
<ConfigContext.Provider value={config}>
|
|
||||||
<Page
|
|
||||||
usecondensed="True"
|
|
||||||
header={(
|
|
||||||
<PageHeader
|
<PageHeader
|
||||||
showNavToggle
|
showNavToggle
|
||||||
onNavToggle={() => this.onNavToggle()}
|
onNavToggle={() => this.onNavToggle()}
|
||||||
@@ -102,21 +99,29 @@ class App extends React.Component {
|
|||||||
</Toolbar>
|
</Toolbar>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
);
|
||||||
sidebar={(
|
|
||||||
|
const sidebar = (
|
||||||
<PageSidebar
|
<PageSidebar
|
||||||
isNavOpen={isNavOpen}
|
isNavOpen={isNavOpen}
|
||||||
nav={(
|
nav={(
|
||||||
<Nav aria-label={navLabel}>
|
<Nav aria-label={navLabel}>
|
||||||
<NavList>
|
<NavList>
|
||||||
{
|
{routeGroups.map(params => (
|
||||||
routeGroups.map(params => <NavExpandableGroup key={params.groupId} {...params} />)
|
<NavExpandableGroup key={params.groupId} {...params} />
|
||||||
}
|
))}
|
||||||
</NavList>
|
</NavList>
|
||||||
</Nav>
|
</Nav>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfigContext.Provider value={config}>
|
||||||
|
<Page
|
||||||
|
usecondensed="True"
|
||||||
|
header={header}
|
||||||
|
sidebar={sidebar}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@@ -128,19 +133,17 @@ class App extends React.Component {
|
|||||||
routeGroups
|
routeGroups
|
||||||
.reduce((allRoutes, { routes }) => allRoutes.concat(routes), [])
|
.reduce((allRoutes, { routes }) => allRoutes.concat(routes), [])
|
||||||
.map(({ component: Component, path }) => (
|
.map(({ component: Component, path }) => (
|
||||||
<Route key={path} path={path} render={params => <Component {...params } />} />
|
<Route
|
||||||
|
key={path}
|
||||||
|
path={path}
|
||||||
|
render={params => (
|
||||||
|
<Component {...params } />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</Page>
|
</Page>
|
||||||
</ConfigContext.Provider>
|
</ConfigContext.Provider>
|
||||||
)} />
|
|
||||||
</Switch>
|
|
||||||
) : (
|
|
||||||
<Switch>
|
|
||||||
<Route path="/login" render={() => <Login logo={logo} loginInfo={loginInfo} />} />
|
|
||||||
<Redirect to="/login" />
|
|
||||||
</Switch>
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import {
|
import {
|
||||||
HashRouter as Router,
|
HashRouter,
|
||||||
|
Redirect,
|
||||||
|
Route,
|
||||||
Switch,
|
Switch,
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
@@ -59,8 +61,23 @@ export async function main () {
|
|||||||
const { data } = await api.getRoot();
|
const { data } = await api.getRoot();
|
||||||
const { custom_logo, custom_login_info } = data;
|
const { custom_logo, custom_login_info } = data;
|
||||||
|
|
||||||
|
const loginRoutes = (
|
||||||
|
<Switch>
|
||||||
|
<Route
|
||||||
|
path="/login"
|
||||||
|
render={() => (
|
||||||
|
<Login
|
||||||
|
logo={custom_logo}
|
||||||
|
loginInfo={custom_login_info}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Redirect to="/login" />
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<Router>
|
<HashRouter>
|
||||||
<I18nProvider
|
<I18nProvider
|
||||||
language={languageWithoutRegionCode}
|
language={languageWithoutRegionCode}
|
||||||
catalogs={catalogs}
|
catalogs={catalogs}
|
||||||
@@ -68,9 +85,13 @@ export async function main () {
|
|||||||
<I18n>
|
<I18n>
|
||||||
{({ i18n }) => (
|
{({ i18n }) => (
|
||||||
<Background>
|
<Background>
|
||||||
|
{!api.isAuthenticated() ? loginRoutes : (
|
||||||
|
<Switch>
|
||||||
|
<Route path="/login" render={() => <Redirect to="/home" />} />
|
||||||
|
<Route exact path="/" render={() => <Redirect to="/home" />} />
|
||||||
|
<Route
|
||||||
|
render={() => (
|
||||||
<App
|
<App
|
||||||
logo={custom_logo}
|
|
||||||
loginInfo={custom_login_info}
|
|
||||||
navLabel={i18n._(t`Primary Navigation`)}
|
navLabel={i18n._(t`Primary Navigation`)}
|
||||||
routeGroups={[
|
routeGroups={[
|
||||||
{
|
{
|
||||||
@@ -215,11 +236,15 @@ export async function main () {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
|
)}
|
||||||
</Background>
|
</Background>
|
||||||
)}
|
)}
|
||||||
</I18n>
|
</I18n>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
</Router>, el);
|
</HashRouter>, el);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default main();
|
export default main();
|
||||||
|
|||||||
Reference in New Issue
Block a user