Skip to content

Commit

Permalink
Revert "Merge pull request #2735 from zooniverse/revert-2730-project-…
Browse files Browse the repository at this point in the history
…demotes-site-nav"

This reverts commit 5896b97, reversing
changes made to 67880c4.
  • Loading branch information
brian-c committed Jun 27, 2016
1 parent 5896b97 commit ea433f8
Show file tree
Hide file tree
Showing 30 changed files with 1,359 additions and 839 deletions.
59 changes: 59 additions & 0 deletions app/components/admin-only.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import counterpart from 'counterpart';
import React from 'react';
import apiClient from 'panoptes-client/lib/api-client';
import isAdmin from '../lib/is-admin';

const AdminOnly = React.createClass({
refreshing: false,

contextTypes: {
user: React.PropTypes.object,
},

getDefaultProps() {
return {
whenActive: false,
};
},

componentDidMount() {
apiClient.listen('change', this.handleClientChange);
},

componentWillUnmount() {
apiClient.stopListening('change', this.handleClientChange);
},

componentDidUpdate(prevProps, prevState) {
if (this.refreshing) {
this.refreshing = false;
this.forceUpdate();
}
},

handleClientChange() {
if (!this.refreshing) {
this.refreshing = true;
// Debounce just a bit.
setTimeout(() => {
this.forceUpdate();
}, 100);
}
},

render() {
React.Children.only(this.props.children);
if (!!this.context.user && this.context.user.admin && (!this.props.whenActive || isAdmin())) {
if (this.refreshing) {
// Return null during refresh force re-render the child.
return null
} else {
return this.props.children;
}
} else {
return null;
}
},
});

export default AdminOnly;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ React = require 'react'
module.exports = React.createClass
contextTypes:
router: routerShape
geordi: React.PropTypes.object

childContextTypes:
router: routerShape
Expand Down
213 changes: 213 additions & 0 deletions app/layout/account-bar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import React from 'react';
import { routerShape } from 'react-router/lib/PropTypes';
import { Link } from 'react-router';
import auth from 'panoptes-client/lib/auth';
import talkClient from 'panoptes-client/lib/talk-client';
import counterpart from 'counterpart';
import Translate from 'react-translate-component';
import Avatar from '../partials/avatar';
import TriggeredModalForm from 'modal-form/triggered';
import PassContext from '../components/pass-context';

const FOCUSABLES = 'a[href], button';

const UP = 38;
const DOWN = 40;

counterpart.registerTranslations('en', {
accountMenu: {
profile: 'Profile',
settings: 'Settings',
signOut: 'Sign Out',
collections: 'Collections',
favorites: 'Favorites',
},
});

const AccountBar = React.createClass({
contextTypes: {
router: routerShape,
geordi: React.PropTypes.object,
},

propTypes: {
user: React.PropTypes.shape({
id: React.PropTypes.string,
display_name: React.PropTypes.string,
login: React.PropTypes.string,
}),
},

getInitialState() {
return {
unread: false,
};
},

componentDidMount() {
addEventListener('locationchange', this.lookUpUnread);
this.lookUpUnread();
},

componentWillReceiveProps(nextProps, nextContext) {
this.logClick = !!nextContext &&
!!nextContext.geordi &&
!!nextContext.geordi.makeHandler &&
nextContext.geordi.makeHandler('about-menu');
},

componentWillUnmount() {
removeEventListener('locationchange', this.lookUpUnread);
},

lookUpUnread() {
talkClient.type('conversations').get({
user_id: this.props.user.id,
unread: true,
page_size: 1,
}).then((conversations) => {
this.setState({
unread: conversations.length > 0,
});
});
},

handleAccountMenuOpen() {
setTimeout(() => { // Wait for the modal's internal state change to happen.
if (this.refs.accountMenuButton.state.open) {
// React's `autoFocus` apparently doesn't work on <a> tags.
const firstFocusable = this.refs.accountMenu.querySelector(FOCUSABLES);
if (!!firstFocusable) {
firstFocusable.focus();
}
}
});
},

navigateMenu(event) {
const focusables = this.refs.accountMenu.querySelectorAll(FOCUSABLES);
const focusIndex = Array.prototype.indexOf.call(focusables, document.activeElement);

const newIndex = {
[UP]: Math.max(0, focusIndex - 1),
[DOWN]: Math.min(focusables.length - 1, focusIndex + 1),
}[event.which];

if (focusables[newIndex] !== undefined) {
focusables[newIndex].focus();
event.preventDefault();
}
},

handleSignOutClick() {
!!this.logClick && this.logClick('accountMenu.signOut');
!!this.context.geordi && this.context.geordi.logEvent({
type: 'logout',
});

auth.signOut();
},

render() {
return (
<span>
<TriggeredModalForm
ref="accountMenuButton"
className="site-nav__modal"
trigger={
<span className="site-nav__link">
<strong>{this.props.user.display_name}</strong>{' '}
<Avatar className="site-nav__user-avatar" user={this.props.user} size="2em" />
</span>
}
triggerProps={{
className: 'secret-button',
onClick: this.handleAccountMenuOpen,
}}
>
<PassContext context={this.context}>
<div ref="accountMenu" role="menu" onKeyDown={this.navigateMenu}>
<Link
role="menuitem"
to={`/users/${this.props.user.login}`}
className="site-nav__link"
onClick={!!this.logClick ? this.logClick.bind(this, 'accountMenu.profile') : null}
>
<i className="fa fa-user fa-fw"></i>{' '}
<Translate content="accountMenu.profile" />
</Link>
<br />
<Link
role="menuitem"
to="/settings"
className="site-nav__link"
onClick={!!this.logClick ? this.logClick.bind(this, 'accountMenu.settings') : null}
>
<i className="fa fa-cogs fa-fw"></i>{' '}
<Translate content="accountMenu.settings" />
</Link>
<br />
<Link
role="menuitem"
to={`/collections/${this.props.user.login}`}
className="site-nav__link"
onClick={!!this.logClick ? this.logClick.bind(this, 'accountMenu.collections') : null}
>
<i className="fa fa-image fa-fw"></i>{' '}
<Translate content="accountMenu.collections" />
</Link>
<br />
<Link
role="menuitem"
to={`/favorites/${this.props.user.login}`}
className="site-nav__link"
onClick={!!this.logClick ? this.logClick.bind(this, 'accountMenu.favorites') : null}
>
<i className="fa fa-star fa-fw"></i>{' '}
<Translate content="accountMenu.favorites" />
</Link>
<hr />
<button
role="menuitem"
type="button"
className="secret-button"
onClick={this.handleSignOutClick}
>
<span className="site-nav__link">
<i className="fa fa-sign-out fa-fw"></i>{' '}
<Translate content="accountMenu.signOut" />
</span>
</button>
</div>
</PassContext>
</TriggeredModalForm>

<span className="site-nav__link-buncher"></span>

<Link
to="/inbox"
className="site-nav__link"
activeClassName="site-nav__link--active"
aria-label={`
Inbox ${this.state.unread ? 'with unread messages' : ''}
`.trim()}
onClick={!!this.logClick ? this.logClick.bind(this, 'accountMenu.inbox', 'top-menu') : null}
>
<span
className={`
site-nav__inbox-link
${this.state.unread ? 'site-nav__inbox-link--unread' : ''}
`.trim()}
>
{this.state.unread ?
<i className="fa fa-envelope fa-fw" />
:
<i className="fa fa-envelope-o fa-fw" />}
</span>
</Link>
</span>
);
},
});

export default AccountBar;
49 changes: 49 additions & 0 deletions app/layout/admin-toggle.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import counterpart from 'counterpart';
import React from 'react';
import apiClient from 'panoptes-client/lib/api-client';
import classnames from 'classnames';
import Translate from 'react-translate-component';

counterpart.registerTranslations('en', {
footerAdminMode: 'Admin mode',
});

const AdminToggle = React.createClass({
componentDidMount() {
apiClient.update({
'params.admin': !!localStorage.getItem('adminFlag') || undefined,
});
},

toggleAdminMode(e) {
apiClient.update({
'params.admin': e.target.checked || undefined,
});

if (e.target.checked) {
localStorage.setItem('adminFlag', true);
} else {
localStorage.removeItem('adminFlag');
}
},

render() {
console.log('RENDER with', apiClient.params.admin);
return (
<label
className={classnames('footer-admin-toggle', {
'footer-admin-toggle--active': !!apiClient.params.admin,
})}
>
<input
type="checkbox"
checked={!!apiClient.params.admin}
onChange={this.toggleAdminMode}
/>{' '}
<Translate content="footerAdminMode" />
</label>
);
},
});

export default AdminToggle;
Loading

0 comments on commit ea433f8

Please sign in to comment.