Split Tab from TabBar (#4318)

* Tab split (WIP)

* Split Tab component
This commit is contained in:
Jaco Greeff 2017-01-27 14:41:41 +01:00 committed by GitHub
parent da032e950f
commit b51b7849dc
5 changed files with 246 additions and 64 deletions

View File

@ -0,0 +1,17 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
export default from './tab';

View File

@ -0,0 +1,78 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { Tab as MUITab } from 'material-ui/Tabs';
import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { Badge } from '~/ui';
import styles from '../tabBar.css';
const SIGNER_ID = 'signer';
export default class Tab extends Component {
static propTypes = {
children: PropTypes.node,
pendings: PropTypes.number,
view: PropTypes.object.isRequired
};
render () {
const { view, children } = this.props;
return (
<MUITab
icon={ view.icon }
label={
view.id === SIGNER_ID
? this.renderSignerLabel()
: this.renderLabel(view.id)
}
>
{ children }
</MUITab>
);
}
renderLabel (id, bubble) {
return (
<div className={ styles.label }>
<FormattedMessage
id={ `settings.views.${id}.label` }
/>
{ bubble }
</div>
);
}
renderSignerLabel () {
const { pendings } = this.props;
let bubble;
if (pendings) {
bubble = (
<Badge
color='red'
className={ styles.labelBubble }
value={ pendings }
/>
);
}
return this.renderLabel(SIGNER_ID, bubble);
}
}

View File

@ -0,0 +1,78 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';
import Tab from './';
let component;
let instance;
function render (id = 'signer') {
component = shallow(
<Tab
children={ <div>testChildren</div> }
pending={ 5 }
view={ { id } }
/>
);
instance = component.instance();
return component;
}
describe('views/Application/TabBar/Tab', () => {
beforeEach(() => {
render();
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
describe('instance methods', () => {
describe('renderLabel', () => {
it('renders the label with correct label', () => {
expect(
shallow(instance.renderLabel('test')).find('FormattedMessage').props().id
).to.equal('settings.views.test.label');
});
it('renders the bubble when passed', () => {
expect(
shallow(instance.renderLabel('test', 'testBubble')).text()
).to.equal('<FormattedMessage />testBubble');
});
});
describe('renderSignerLabel', () => {
beforeEach(() => {
sinon.stub(instance, 'renderLabel');
});
afterEach(() => {
instance.renderLabel.restore();
});
it('calls renderLabel with the details', () => {
instance.renderSignerLabel();
expect(instance.renderLabel).to.have.been.calledWith('signer');
});
});
});
});

View File

@ -15,77 +15,18 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Link } from 'react-router'; import { Link } from 'react-router';
import { Toolbar, ToolbarGroup } from 'material-ui/Toolbar'; import { Toolbar, ToolbarGroup } from 'material-ui/Toolbar';
import { Tab as MUITab } from 'material-ui/Tabs';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { Badge, Tooltip } from '~/ui';
import imagesEthcoreBlock from '~/../assets/images/parity-logo-white-no-text.svg'; import imagesEthcoreBlock from '~/../assets/images/parity-logo-white-no-text.svg';
import { Tooltip } from '~/ui';
import Tab from './Tab';
import styles from './tabBar.css'; import styles from './tabBar.css';
class Tab extends Component {
static propTypes = {
children: PropTypes.node,
pendings: PropTypes.number,
view: PropTypes.object
};
render () {
const { view, children } = this.props;
return (
<MUITab
icon={ view.icon }
label={
view.id === 'signer'
? this.renderSignerLabel(view.id)
: this.renderLabel(view.id)
}
>
{ children }
</MUITab>
);
}
renderLabel (id, bubble) {
return (
<div className={ styles.label }>
<FormattedMessage
id={ `settings.views.${id}.label` }
/>
{ bubble }
</div>
);
}
renderSignerLabel (id) {
const { pendings } = this.props;
let bubble;
if (pendings) {
bubble = (
<Badge
color='red'
className={ styles.labelBubble }
value={ pendings }
/>
);
}
return this.renderLabel(id, bubble);
}
}
class TabBar extends Component { class TabBar extends Component {
static contextTypes = {
router: PropTypes.object.isRequired
};
static propTypes = { static propTypes = {
isTest: PropTypes.bool, isTest: PropTypes.bool,
netChain: PropTypes.string, netChain: PropTypes.string,
@ -111,7 +52,10 @@ class TabBar extends Component {
return ( return (
<ToolbarGroup> <ToolbarGroup>
<div className={ styles.logo }> <div className={ styles.logo }>
<img src={ imagesEthcoreBlock } height={ 28 } /> <img
height={ 28 }
src={ imagesEthcoreBlock }
/>
</div> </div>
</ToolbarGroup> </ToolbarGroup>
); );
@ -144,7 +88,8 @@ class TabBar extends Component {
return ( return (
<Link <Link
activeClassName={ styles.tabactive } activeClassName={ styles.tabactive }
className={ styles.tabLink }key={ view.id } className={ styles.tabLink }
key={ view.id }
to={ view.route } to={ view.route }
> >
<Tab <Tab
@ -199,5 +144,6 @@ function mapStateToProps (initState) {
} }
export default connect( export default connect(
mapStateToProps mapStateToProps,
null
)(TabBar); )(TabBar);

View File

@ -0,0 +1,63 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { shallow } from 'enzyme';
import React from 'react';
import sinon from 'sinon';
import TabBar from './';
let component;
let store;
function createStore () {
store = {
dispatch: sinon.stub(),
subscribe: sinon.stub(),
getState: () => {
return {
settings: {
views: {
settings: { fixed: true }
}
}
};
}
};
return store;
}
function render (props = {}) {
component = shallow(
<TabBar { ...props } />,
{
context: { store: createStore() }
}
).find('TabBar').shallow();
return component;
}
describe('views/Application/TabBar', () => {
beforeEach(() => {
render();
});
it('renders defaults', () => {
expect(component).to.be.ok;
});
});