diff --git a/js/src/views/Application/TabBar/tabBar.css b/js/src/views/Application/TabBar/tabBar.css index b855d4298..8ee1254f8 100644 --- a/js/src/views/Application/TabBar/tabBar.css +++ b/js/src/views/Application/TabBar/tabBar.css @@ -23,6 +23,11 @@ .tabs { width: 100%; position: relative; + display: flex; + + & > * { + flex: 1; + } } .tabs button, @@ -38,6 +43,7 @@ button.tabactive, button.tabactive:hover { + color: white !important; background: rgba(0, 0, 0, 0.25) !important; border-radius: 4px 4px 0 0; } diff --git a/js/src/views/Application/TabBar/tabBar.js b/js/src/views/Application/TabBar/tabBar.js index 01ca4df0d..62f02b43b 100644 --- a/js/src/views/Application/TabBar/tabBar.js +++ b/js/src/views/Application/TabBar/tabBar.js @@ -18,7 +18,7 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { Toolbar, ToolbarGroup } from 'material-ui/Toolbar'; -import { Tabs, Tab } from 'material-ui/Tabs'; +import { Tab as MUITab } from 'material-ui/Tabs'; import { Badge, Tooltip } from '../../../ui'; @@ -33,20 +33,138 @@ const TABMAP = { deploy: 'contract' }; +class Tab extends Component { + static propTypes = { + active: PropTypes.bool, + view: PropTypes.object, + children: PropTypes.node, + pendings: PropTypes.number, + onChange: PropTypes.func + }; + + shouldComponentUpdate (nextProps) { + return nextProps.active !== this.props.active || + (nextProps.view.id === 'signer' && nextProps.pendings !== this.props.pendings); + } + + render () { + const { active, view, children } = this.props; + + const label = this.getLabel(view); + + return ( + + { children } + + ); + } + + getLabel (view) { + const { label } = view; + + if (view.id === 'signer') { + return this.renderSignerLabel(label); + } + + if (view.id === 'status') { + return this.renderStatusLabel(label); + } + + return this.renderLabel(label); + } + + renderLabel (name, bubble) { + return ( +
+ { name } + { bubble } +
+ ); + } + + renderSignerLabel (label) { + const { pendings } = this.props; + + if (pendings) { + const bubble = ( + + ); + + return this.renderLabel(label, bubble); + } + + return this.renderLabel(label); + } + + renderStatusLabel (label) { + // const { isTest, netChain } = this.props; + // const bubble = ( + // + // ); + + return this.renderLabel(label, null); + } + + handleClick = () => { + const { onChange, view } = this.props; + onChange(view); + } +} + class TabBar extends Component { static contextTypes = { router: PropTypes.object.isRequired - } + }; static propTypes = { + views: PropTypes.array.isRequired, + hash: PropTypes.string.isRequired, pending: PropTypes.array, isTest: PropTypes.bool, - netChain: PropTypes.string, - settings: PropTypes.object.isRequired - } + netChain: PropTypes.string + }; + + static defaultProps = { + pending: [] + }; state = { - activeRoute: '/accounts' + activeViewId: '' + }; + + setActiveView (props = this.props) { + const { hash, views } = props; + const view = views.find((view) => view.value === hash); + + this.setState({ activeViewId: view.id }); + } + + componentWillMount () { + this.setActiveView(); + } + + componentWillReceiveProps (nextProps) { + if (nextProps.hash !== this.props.hash) { + this.setActiveView(nextProps); + } + } + + shouldComponentUpdate (nextProps, nextState) { + return (nextProps.hash !== this.props.hash) || + (nextProps.pending.length !== this.props.pending.length) || + (nextState.activeViewId !== this.state.activeViewId); } render () { @@ -81,100 +199,64 @@ class TabBar extends Component { } renderTabs () { - const { settings } = this.props; - const windowHash = (window.location.hash || '').split('?')[0].split('/')[1]; - const hash = TABMAP[windowHash] || windowHash; + const { views, pending } = this.props; + const { activeViewId } = this.state; - const items = Object.keys(settings.views) - .filter((id) => settings.views[id].fixed || settings.views[id].active) - .map((id) => { - const view = settings.views[id]; - let label = this.renderLabel(view.label); - let body = null; + const items = views + .map((view, index) => { + const body = (view.id === 'accounts') + ? ( + + ) + : null; - if (id === 'accounts') { - body = ( - - ); - } else if (id === 'signer') { - label = this.renderSignerLabel(label); - } else if (id === 'status') { - label = this.renderStatusLabel(label); - } + const active = activeViewId === view.id; return ( + active={ active } + view={ view } + onChange={ this.onChange } + key={ index } + pendings={ pending.length } + > { body } ); }); return ( - + onChange={ this.onChange }> { items } - - ); - } - - renderLabel = (name, bubble) => { - return ( -
- { name } - { bubble }
); } - renderSignerLabel = (label) => { - const { pending } = this.props; - let bubble = null; - - if (pending && pending.length) { - bubble = ( - - ); - } - - return this.renderLabel(label, bubble); - } - - renderStatusLabel = (label) => { - // const { isTest, netChain } = this.props; - // const bubble = ( - // - // ); - - return this.renderLabel(label, null); - } - - onActivate = (activeRoute) => { + onChange = (view) => { const { router } = this.context; - return (event) => { - router.push(activeRoute); - this.setState({ activeRoute }); - }; + router.push(view.route); + this.setState({ activeViewId: view.id }); } } function mapStateToProps (state) { - const { settings } = state; + const { views } = state.settings; - return { settings }; + const filteredViews = Object + .keys(views) + .filter((id) => views[id].fixed || views[id].active) + .map((id) => ({ + ...views[id], + id + })); + + const windowHash = (window.location.hash || '').split('?')[0].split('/')[1]; + const hash = TABMAP[windowHash] || windowHash; + + return { views: filteredViews, hash }; } function mapDispatchToProps (dispatch) {