-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(app, auth, pageLayout, router): issues/18 migrate prep pf4 (#47)
* build, gitignore * router, routerConstants restructure, rename, unit tests * app, breakout aspects of auth & page layout, prep pf4 * authentication, layer for confirming login auth * pageLayout, vertical nav and basic page layout * styling, naming alignment
- Loading branch information
Showing
24 changed files
with
975 additions
and
425 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,171 +1,33 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { withRouter } from 'react-router'; | ||
import { Alert, EmptyState, Modal, VerticalNav } from 'patternfly-react'; | ||
import _startsWith from 'lodash/startsWith'; | ||
import { routes } from '../routes'; | ||
import { connect, reduxActions, reduxTypes, store } from '../redux'; | ||
import helpers from '../common/helpers'; | ||
import { connectRouter } from '../redux'; | ||
import Authentication from './authentication/authentication'; | ||
import { ConnectedPageLayout } from './pageLayout/pageLayout'; | ||
import { Router } from './router/router'; | ||
import ToastNotificationsList from './toastNotificationsList/toastNotificationsList'; | ||
import ConfirmationModal from './confirmationModal/confirmationModal'; | ||
import AboutModal from './aboutModal/aboutModal'; | ||
import AddSourceWizard from './addSourceWizard/addSourceWizard'; | ||
import CreateCredentialDialog from './createCredentialDialog/createCredentialDialog'; | ||
import CreateScanDialog from './createScanDialog/createScanDialog'; | ||
import Content from './content/content'; | ||
import ToastNotificationsList from './toastNotificationsList/toastNotificationsList'; | ||
import ConfirmationModal from './confirmationModal/confirmationModal'; | ||
import MastheadOptions from './mastheadOptions/mastheadOptions'; | ||
import titleImg from '../styles/images/title.svg'; | ||
import titleImgBrand from '../styles/images/title-brand.svg'; | ||
|
||
class App extends React.Component { | ||
componentDidMount() { | ||
const { authorizeUser } = this.props; | ||
|
||
authorizeUser(); | ||
} | ||
|
||
onLogout = () => { | ||
const { logoutUser } = this.props; | ||
|
||
logoutUser().finally(() => { | ||
window.location = '/logout'; | ||
}); | ||
}; | ||
|
||
onNavigateTo = path => { | ||
const { history } = this.props; | ||
history.push(path); | ||
}; | ||
|
||
onShowAbout = () => { | ||
store.dispatch({ | ||
type: reduxTypes.aboutModal.ABOUT_MODAL_SHOW | ||
}); | ||
}; | ||
|
||
renderMenuItems() { | ||
const { location, menu } = this.props; | ||
const activeItem = menu.find(item => _startsWith(location.pathname, item.to)); | ||
|
||
return menu.map(item => ( | ||
<VerticalNav.Item | ||
key={item.to} | ||
title={item.title} | ||
iconClass={item.iconClass} | ||
active={item === activeItem || (!activeItem && item.redirect)} | ||
onClick={() => this.onNavigateTo(item.to)} | ||
/> | ||
)); | ||
} | ||
|
||
renderMenuActions() { | ||
const { logoutUser } = this.props; | ||
|
||
return [ | ||
<VerticalNav.Item key="about" className="collapsed-nav-item" title="About" onClick={() => this.onShowAbout()} />, | ||
<VerticalNav.Item key="logout" className="collapsed-nav-item" title="Logout" onClick={logoutUser} /> | ||
]; | ||
} | ||
|
||
render() { | ||
const { session } = this.props; | ||
const productTitleImg = helpers.RH_BRAND ? titleImgBrand : titleImg; | ||
|
||
if (session.pending) { | ||
return ( | ||
<Modal bsSize="lg" backdrop={false} show animation={false}> | ||
<Modal.Body> | ||
<div className="spinner spinner-xl" /> | ||
<div className="text-center">Logging in...</div> | ||
</Modal.Body> | ||
</Modal> | ||
); | ||
} | ||
|
||
if (!session.authorized || session.error) { | ||
return ( | ||
<div className="layout-pf layout-pf-fixed fadein"> | ||
<nav className="navbar navbar-pf-vertical"> | ||
<div className="navbar-header"> | ||
<span className="navbar-brand"> | ||
<img className="navbar-brand-name" src={productTitleImg} alt="" /> | ||
</span> | ||
</div> | ||
</nav> | ||
<div> | ||
<EmptyState className="full-page-blank-slate"> | ||
<Alert type="error"> | ||
<span> | ||
Login error: {session.errorMessage.replace(/\.$/, '')} | ||
{session.errorMessage && '.'} | ||
{!session.authorized && ( | ||
<React.Fragment> | ||
Please <a href="/login">login</a> to continue. | ||
</React.Fragment> | ||
)} | ||
</span> | ||
</Alert> | ||
</EmptyState> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="layout-pf layout-pf-fixed fadein"> | ||
<VerticalNav persistentSecondary={false}> | ||
<VerticalNav.Masthead> | ||
<VerticalNav.Brand titleImg={productTitleImg} /> | ||
<MastheadOptions username={session.username} showAboutModal={this.onShowAbout} logoutUser={this.onLogout} /> | ||
</VerticalNav.Masthead> | ||
{this.renderMenuItems()} | ||
{this.renderMenuActions()} | ||
</VerticalNav> | ||
<div className="container-pf-nav-pf-vertical"> | ||
<Content /> | ||
<ToastNotificationsList key="toastList" /> | ||
<ConfirmationModal key="confirmationModal" /> | ||
<AboutModal /> | ||
<AddSourceWizard /> | ||
<CreateCredentialDialog /> | ||
<CreateScanDialog /> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
App.propTypes = { | ||
authorizeUser: PropTypes.func, | ||
logoutUser: PropTypes.func, | ||
session: PropTypes.object, | ||
location: PropTypes.object, | ||
menu: PropTypes.array, | ||
history: PropTypes.shape({ | ||
push: PropTypes.func.isRequired | ||
}).isRequired | ||
}; | ||
const App = () => ( | ||
<Authentication> | ||
<ConnectedPageLayout> | ||
<Router /> | ||
<ToastNotificationsList /> | ||
<ConfirmationModal /> | ||
<AboutModal /> | ||
<AddSourceWizard /> | ||
<CreateCredentialDialog /> | ||
<CreateScanDialog /> | ||
</ConnectedPageLayout> | ||
</Authentication> | ||
); | ||
|
||
App.defaultProps = { | ||
authorizeUser: helpers.noop, | ||
logoutUser: helpers.noop, | ||
menu: routes(), | ||
session: {}, | ||
location: {} | ||
}; | ||
App.propTypes = {}; | ||
|
||
const mapDispatchToProps = dispatch => ({ | ||
authorizeUser: () => dispatch(reduxActions.user.authorizeUser()), | ||
logoutUser: () => dispatch(reduxActions.user.logoutUser()) | ||
}); | ||
App.defaultProps = {}; | ||
|
||
const mapStateToProps = state => ({ | ||
session: state.user.session | ||
}); | ||
const ConnectedApp = connectRouter()(App); | ||
|
||
export default withRouter( | ||
connect( | ||
mapStateToProps, | ||
mapDispatchToProps | ||
)(App) | ||
); | ||
export { ConnectedApp as default, ConnectedApp, App }; |
Oops, something went wrong.