1
0
mirror of https://github.com/ascribe/onion.git synced 2025-01-03 10:25:08 +01:00
onion/js/components/header.js

209 lines
7.1 KiB
JavaScript

'use strict';
import React from 'react';
import { Link } from 'react-router';
import Nav from 'react-bootstrap/lib/Nav';
import Navbar from 'react-bootstrap/lib/Navbar';
import MenuItem from 'react-bootstrap/lib/MenuItem';
import NavDropdown from 'react-bootstrap/lib/NavDropdown';
import NavItem from 'react-bootstrap/lib/NavItem';
import LinkContainer from 'react-router-bootstrap/lib/LinkContainer';
import PieceListStore from '../stores/piece_list_store';
import AclProxy from './acl_proxy';
import withContext from './context/with_context';
import HeaderNotifications from './header_notifications';
import HeaderNotificationDebug from './header_notification_debug';
import NavRoutesLinks from './nav_routes_links';
import { currentUserShape, whitelabelShape } from './prop_types';
import { constructHead } from '../utils/dom';
import { safeMerge } from '../utils/general';
import { getLangText } from '../utils/lang';
let Header = React.createClass({
propTypes: {
routes: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
// Injected through HOCs
currentUser: currentUserShape.isRequired, // eslint-disable-line react/sort-prop-types
isLoggedIn: React.PropTypes.bool.isRequired, // eslint-disable-line react/sort-prop-types
whitelabel: whitelabelShape.isRequired // eslint-disable-line react/sort-prop-types
},
getInitialState() {
return safeMerge(
PieceListStore.getState(),
{
expandedCollapse: false
}
);
},
componentDidMount() {
// Listen to the piece list store, but don't fetch immediately to avoid
// conflicts with routes that may need to wait to load the piece list
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
collapseNav() {
if (this.state.expandedCollapse) {
this.onToggleCollapse(false);
}
},
onToggleCollapse(expandedCollapse) {
this.setState({ expandedCollapse });
},
renderLogo() {
const { whitelabel } = this.props;
if (whitelabel.head) {
constructHead(whitelabel.head);
}
if (whitelabel.subdomain && whitelabel.subdomain !== 'www' && whitelabel.logo) {
return (
<Link to="/collection">
<img alt="Whitelabel brand" className="img-brand" src={whitelabel.logo} />
</Link>
);
} else {
return (
<Link to="/collection">
<span className="icon-ascribe-logo" />
</Link>
);
}
},
renderPoweredBy() {
return (
<a className="pull-left ascribe-powered-by" href="https://www.ascribe.io/" target="_blank">
<span>{getLangText('powered by')} </span>
<span className="icon-ascribe-logo"></span>
</a>
);
},
render() {
const { currentUser, isLoggedIn, routes, whitelabel } = this.props;
const { unfilteredPieceListCount } = this.state;
let account;
let signup;
let navRoutesLinks;
if (isLoggedIn) {
account = (
<NavDropdown
id="nav-route-user-dropdown"
title={currentUser.username}>
<LinkContainer to="/settings">
<MenuItem>
{getLangText('Account Settings')}
</MenuItem>
</LinkContainer>
<AclProxy
aclName="acl_view_settings_contract"
aclObject={currentUser.acl}>
<LinkContainer to="/contract_settings">
<MenuItem>
{getLangText('Contract Settings')}
</MenuItem>
</LinkContainer>
</AclProxy>
<MenuItem divider />
<LinkContainer to="/logout">
<MenuItem>
{getLangText('Log out')}
</MenuItem>
</LinkContainer>
</NavDropdown>
);
// Let's assume that if the piece list hasn't loaded yet (ie. when
// unfilteredPieceListCount === -1) then the user has pieces.
// FIXME: this doesn't work that well as the user may not load their piece list
// until much later, so we would show the 'Collection' header as available until
// they actually click on it and get redirected to piece registration.
navRoutesLinks = (
<NavRoutesLinks
navbar
pullRight
hasPieces={!!unfilteredPieceListCount}
onSelect={this.collapseNav}
routes={routes}
userAcl={currentUser.acl} />
);
} else {
account = (
<LinkContainer to="/login">
<NavItem>
{getLangText('LOGIN')}
</NavItem>
</LinkContainer>
);
signup = (
<LinkContainer to="/signup">
<NavItem>
{getLangText('SIGNUP')}
</NavItem>
</LinkContainer>
);
}
return (
<div>
<Navbar
ref="navbar"
fixedTop
className="hidden-print"
expanded={this.state.expandedCollapse}
onToggle={this.onToggleCollapse}>
<Navbar.Header>
<Navbar.Brand>
{this.renderLogo()}
</Navbar.Brand>
<AclProxy
aclName="acl_view_powered_by"
aclObject={whitelabel}>
{this.renderPoweredBy()}
</AclProxy>
<Navbar.Toggle />
</Navbar.Header>
<Navbar.Collapse>
<Nav navbar pullRight onSelect={this.collapseNav}>
{account}
{signup}
</Nav>
<Nav navbar pullRight onSelect={this.collapseNav}>
<HeaderNotificationDebug show={false} />
<HeaderNotifications />
</Nav>
{navRoutesLinks}
</Navbar.Collapse>
</Navbar>
<p className="ascribe-print-header visible-print">
<span className="icon-ascribe-logo" />
</p>
</div>
);
}
});
export default withContext(Header, 'currentUser', 'isLoggedIn', 'whitelabel');