app/js/components/menu/rightSidebar.jsx
'use strict';
var React = require('react');
var PureRenderMixin = require('react-addons-pure-render-mixin');
var Reflux = require('reflux');
var _ = require('lodash');
var $ = require('js/shims/jquery');
var classNames = require('classnames');
var EmpireRPCStore = require('js/stores/rpc/empire');
var PlanetStore = require('js/stores/menu/planet');
var RightSidebarActions = require('js/actions/menu/rightSidebar');
var MapActions = require('js/actions/menu/map');
var RightSidebarStore = require('js/stores/menu/rightSidebar');
var PlanetListItem = React.createClass({
propTypes : {
name : React.PropTypes.string.isRequired,
id : React.PropTypes.number.isRequired,
currentBody : React.PropTypes.number.isRequired,
zone : React.PropTypes.string.isRequired
},
getInitialProps : function() {
return {
name : '',
id : 0,
currentBody : 0,
zone : ''
};
},
// Returns true if this list item is the the currently selected planet.
isCurrentWorld : function() {
return this.props.currentBody === this.props.id;
},
handleClick : function() {
RightSidebarActions.rightSidebarHide();
if (this.isCurrentWorld()) {
YAHOO.lacuna.MapPlanet.Refresh();
} else {
MapActions.mapChangePlanet(this.props.id);
}
},
render : function() {
var classStr = classNames({
'ui large teal label' : this.isCurrentWorld(),
'item' : !this.isCurrentWorld()
});
return (
<a className={classStr} onClick={this.handleClick} style={{
// For some reason this doesn't get set on the items (by Semantic) when it should.
cursor : 'pointer'
}}>
{this.props.name} ({this.props.zone})
</a>
);
}
});
var AccordionItem = React.createClass({
propTypes : {
list : React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
currentBody : React.PropTypes.number.isRequired,
title : React.PropTypes.string.isRequired,
initiallyOpen : React.PropTypes.bool.isRequired
},
getInitialProps : function() {
return {
list : [],
currentBody : 0,
title : '',
initiallyOpen : false
};
},
getInitialState : function() {
return {
open : this.props.initiallyOpen
};
},
componentDidMount : function() {
RightSidebarActions.rightSidebarCollapse.listen(this.hideList);
RightSidebarActions.rightSidebarExpand.listen(this.showList);
},
showList : function() {
this.setState({
open : true
});
},
hideList : function() {
this.setState({
open : false
});
},
toggleList : function() {
this.setState({
open : !this.state.open
});
},
render : function() {
return (
<div>
<div
className="ui horizontal inverted divider"
title={
this.state.open
? 'Click to hide ' + this.props.title.toLowerCase()
: 'Click to show ' + this.props.title.toLowerCase()
}
onClick={this.toggleList}
style={{
cursor : 'pointer'
}}
>
{
this.state.open
? <i className="angle down icon"></i>
: <i className="angle right icon"></i>
} {this.props.title}
</div>
<div style={{
display : this.state.open ? '' : 'none'
}}>
{
_.map(this.props.list, _.bind(function(planet) {
return (
<PlanetListItem
key={planet.id}
name={planet.name}
id={planet.id}
x={planet.x}
y={planet.y}
zone={planet.zone}
currentBody={this.props.currentBody}
/>
);
}, this))
}
</div>
</div>
);
}
});
var BodiesAccordion = React.createClass({
propTypes : {
bodies : React.PropTypes.object.isRequired,
currentBody : React.PropTypes.number.isRequired
},
render : function() {
var items = [
{
title : 'My Colonies',
key : 'colonies',
initiallyOpen : true,
isBaby : false
},
{
title : 'My Stations',
key : 'mystations',
initiallyOpen : false,
isBaby : false
},
{
title : 'Our Stations',
key : 'ourstations',
initiallyOpen : false,
isBaby : false
}
];
// Handle all the babies.
_.chain(this.props.bodies.babies || {})
.keys()
.sortBy()
.each(function(babyName) {
items.push({
title : babyName + "'s Colonies",
key : babyName,
initiallyOpen : false,
isBaby : true
});
})
.value();
return (
<div>
{
_.map(items, _.bind(function(item) {
var list = [];
if (item.isBaby) {
list = _.values(this.props.bodies.babies[item.key].planets) || [];
} else {
list = _.values(this.props.bodies[item.key]) || [];
}
if (list.length > 0) {
return (
<AccordionItem
title={item.title}
list={list}
initiallyOpen={item.initiallyOpen}
currentBody={this.props.currentBody}
key={item.title}
/>
);
}
}, this))
}
</div>
);
}
});
var RightSidebar = React.createClass({
mixins : [
Reflux.connect(EmpireRPCStore, 'empire'),
Reflux.connect(PlanetStore, 'planet'),
Reflux.connect(RightSidebarStore, 'showSidebar'),
PureRenderMixin
],
componentDidMount : function() {
var el = this.refs.sidebar;
$(el)
.sidebar({
context : $('#sidebarContainer'),
duration : 300,
transition : 'overlay',
onHidden : RightSidebarActions.rightSidebarHide,
onVisible : RightSidebarActions.rightSidebarShow
});
},
componentDidUpdate : function(prevProps, prevState) {
if (prevState.showSidebar !== this.state.showSidebar) {
this.handleSidebarShowing();
}
var $header = $(this.refs.header);
var $content = $(this.refs.content);
$content.css({
height : window.innerHeight - $header.outerHeight()
});
},
handleSidebarShowing : function() {
var el = this.refs.sidebar;
$(el)
.sidebar(this.state.showSidebar ? 'show' : 'hide');
},
homePlanet : function() {
RightSidebarActions.rightSidebarHide();
MapActions.mapChangePlanet(this.state.empire.home_planet_id);
},
expand : function() {
RightSidebarActions.rightSidebarExpand();
},
collapse : function() {
RightSidebarActions.rightSidebarCollapse();
},
render : function() {
return (
<div className="ui right vertical inverted sidebar menu" ref="sidebar">
<div ref="header" style={{paddingTop : 7}}>
<a
title="Go to home planet"
className="item"
onClick={this.homePlanet}
style={{
display : 'inline'
}}
>
Home
</a>
<div style={{float : 'right'}}>
<a
title="Expand all"
className="item"
onClick={this.expand}
style={{
display : 'inline'
}}
>
[+]
</a>
<a
title="Collapse all"
className="item"
onClick={this.collapse}
style={{
display : 'inline'
}}
>
[-]
</a>
</div>
</div>
<div ref="content" style={{
overflow : 'auto',
overflowX : 'hidden'
}}>
<BodiesAccordion
bodies={this.state.empire.bodies}
currentBody={this.state.planet}
/>
</div>
</div>
);
}
});
module.exports = RightSidebar;