Tooltips with react-intl (#4549)
* Tooltips support intl strings * FormattedMessage for strings to Tooltip * Fix TabBar tooltip display * r after o (PR comment)
This commit is contained in:
parent
812017f9b3
commit
efe76d7004
@ -15,12 +15,13 @@
|
|||||||
// 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 { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { FlatButton } from 'material-ui';
|
import { FlatButton } from 'material-ui';
|
||||||
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
|
|
||||||
import ContentClear from 'material-ui/svg-icons/content/clear';
|
import { CancelIcon, DoneIcon, NextIcon } from '~/ui/Icons';
|
||||||
import NavigationArrowForward from 'material-ui/svg-icons/navigation/arrow-forward';
|
import { nodeOrStringProptype } from '~/util/proptypes';
|
||||||
|
|
||||||
import { newTooltip, nextTooltip, closeTooltips } from '../actions';
|
import { newTooltip, nextTooltip, closeTooltips } from '../actions';
|
||||||
|
|
||||||
@ -30,15 +31,15 @@ let tooltipId = 0;
|
|||||||
|
|
||||||
class Tooltip extends Component {
|
class Tooltip extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
title: PropTypes.string,
|
className: PropTypes.string,
|
||||||
text: PropTypes.string,
|
|
||||||
right: PropTypes.bool,
|
|
||||||
currentId: PropTypes.number,
|
currentId: PropTypes.number,
|
||||||
maxId: PropTypes.number,
|
maxId: PropTypes.number,
|
||||||
className: PropTypes.string,
|
|
||||||
onNewTooltip: PropTypes.func,
|
onNewTooltip: PropTypes.func,
|
||||||
onNextTooltip: PropTypes.func,
|
onNextTooltip: PropTypes.func,
|
||||||
onCloseTooltips: PropTypes.func
|
onCloseTooltips: PropTypes.func,
|
||||||
|
right: PropTypes.bool,
|
||||||
|
text: nodeOrStringProptype(),
|
||||||
|
title: nodeOrStringProptype()
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -54,8 +55,7 @@ class Tooltip extends Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { id } = this.state;
|
const { id } = this.state;
|
||||||
const { className, currentId, maxId, right, onCloseTooltips, onNextTooltip } = this.props;
|
const { className, currentId, maxId, right, onCloseTooltips, onNextTooltip, text, title } = this.props;
|
||||||
const classes = `${styles.box} ${right ? styles.arrowRight : styles.arrowLeft} ${className}`;
|
|
||||||
|
|
||||||
if (id !== currentId) {
|
if (id !== currentId) {
|
||||||
return null;
|
return null;
|
||||||
@ -64,32 +64,57 @@ class Tooltip extends Component {
|
|||||||
const buttons = id !== maxId
|
const buttons = id !== maxId
|
||||||
? [
|
? [
|
||||||
<FlatButton
|
<FlatButton
|
||||||
|
icon={ <CancelIcon /> }
|
||||||
key='skipButton'
|
key='skipButton'
|
||||||
icon={ <ContentClear /> }
|
label={
|
||||||
label='Skip'
|
<FormattedMessage
|
||||||
|
id='ui.tooltips.button.skip'
|
||||||
|
defaultMessage='Skip'
|
||||||
|
/>
|
||||||
|
}
|
||||||
onTouchTap={ onCloseTooltips }
|
onTouchTap={ onCloseTooltips }
|
||||||
/>,
|
/>,
|
||||||
<FlatButton
|
<FlatButton
|
||||||
|
icon={ <NextIcon /> }
|
||||||
key='nextButton'
|
key='nextButton'
|
||||||
icon={ <NavigationArrowForward /> }
|
label={
|
||||||
label='Next'
|
<FormattedMessage
|
||||||
|
id='ui.tooltips.button.next'
|
||||||
|
defaultMessage='Next'
|
||||||
|
/>
|
||||||
|
}
|
||||||
onTouchTap={ onNextTooltip }
|
onTouchTap={ onNextTooltip }
|
||||||
/>
|
/>
|
||||||
] : (
|
] : (
|
||||||
<FlatButton
|
<FlatButton
|
||||||
icon={ <ActionDoneAll /> }
|
icon={ <DoneIcon /> }
|
||||||
label='Done'
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='ui.tooltips.button.done'
|
||||||
|
defaultMessage='Done'
|
||||||
|
/>
|
||||||
|
}
|
||||||
onTouchTap={ onCloseTooltips }
|
onTouchTap={ onCloseTooltips }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={ classes }>
|
<div
|
||||||
|
className={
|
||||||
|
[
|
||||||
|
styles.box,
|
||||||
|
right
|
||||||
|
? styles.arrowRight
|
||||||
|
: styles.arrowLeft,
|
||||||
|
className
|
||||||
|
].join(' ')
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className={ styles.title }>
|
<div className={ styles.title }>
|
||||||
{ this.props.title }
|
{ title }
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.text }>
|
<div className={ styles.text }>
|
||||||
{ this.props.text }
|
{ text }
|
||||||
</div>
|
</div>
|
||||||
<div className={ styles.buttons }>
|
<div className={ styles.buttons }>
|
||||||
{ buttons }
|
{ buttons }
|
||||||
@ -102,7 +127,10 @@ class Tooltip extends Component {
|
|||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { currentId, maxId } = state.tooltip;
|
const { currentId, maxId } = state.tooltip;
|
||||||
|
|
||||||
return { currentId, maxId };
|
return {
|
||||||
|
currentId,
|
||||||
|
maxId
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
|
68
js/src/ui/Tooltips/Tooltip/tooltip.spec.js
Normal file
68
js/src/ui/Tooltips/Tooltip/tooltip.spec.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 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 React from 'react';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
|
||||||
|
import Tooltip from './';
|
||||||
|
|
||||||
|
let component;
|
||||||
|
let store;
|
||||||
|
|
||||||
|
function createRedux (currentId = 0) {
|
||||||
|
store = {
|
||||||
|
dispatch: sinon.stub(),
|
||||||
|
subscribe: sinon.stub(),
|
||||||
|
getState: () => {
|
||||||
|
return {
|
||||||
|
tooltip: {
|
||||||
|
currentId,
|
||||||
|
maxId: 2
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render () {
|
||||||
|
component = shallow(
|
||||||
|
<Tooltip />,
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
store: createRedux()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).find('Tooltip').shallow();
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ui/Tooltips/Tooltip', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders defaults', () => {
|
||||||
|
expect(component.get(0)).to.be.ok;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders null when id !== currentId', () => {
|
||||||
|
expect(render(1).get(0)).to.be.null;
|
||||||
|
});
|
||||||
|
});
|
@ -14,8 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import Tooltip from './Tooltip';
|
|
||||||
import tooltipReducer from './reducers';
|
|
||||||
|
|
||||||
export default from './tooltips';
|
export default from './tooltips';
|
||||||
export { Tooltip, tooltipReducer };
|
|
||||||
|
export Tooltip from './Tooltip';
|
||||||
|
export tooltipReducer from './reducers';
|
||||||
|
@ -29,7 +29,6 @@ class Tooltips extends Component {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
currentId: PropTypes.number,
|
currentId: PropTypes.number,
|
||||||
closed: PropTypes.bool,
|
|
||||||
onNextTooltip: PropTypes.func
|
onNextTooltip: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +71,9 @@ class Tooltips extends Component {
|
|||||||
function mapStateToProps (state) {
|
function mapStateToProps (state) {
|
||||||
const { currentId } = state.tooltip;
|
const { currentId } = state.tooltip;
|
||||||
|
|
||||||
return { currentId };
|
return {
|
||||||
|
currentId
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapDispatchToProps (dispatch) {
|
function mapDispatchToProps (dispatch) {
|
||||||
|
76
js/src/ui/Tooltips/tooltips.spec.js
Normal file
76
js/src/ui/Tooltips/tooltips.spec.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// 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 Tooltips from './';
|
||||||
|
|
||||||
|
let component;
|
||||||
|
let router;
|
||||||
|
let store;
|
||||||
|
|
||||||
|
function createRedux () {
|
||||||
|
store = {
|
||||||
|
dispatch: sinon.stub(),
|
||||||
|
subscribe: sinon.stub(),
|
||||||
|
getState: () => {
|
||||||
|
return {
|
||||||
|
tooltip: {
|
||||||
|
currentId: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createRouter () {
|
||||||
|
router = {
|
||||||
|
push: sinon.stub()
|
||||||
|
};
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render () {
|
||||||
|
component = shallow(
|
||||||
|
<Tooltips />,
|
||||||
|
{
|
||||||
|
context: {
|
||||||
|
store: createRedux()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).find('Tooltips').shallow({
|
||||||
|
context: {
|
||||||
|
router: createRouter()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('ui/Tooltips', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders defaults', () => {
|
||||||
|
expect(component.get(0)).to.be.ok;
|
||||||
|
});
|
||||||
|
});
|
@ -15,6 +15,7 @@
|
|||||||
// 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 { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import ContentAdd from 'material-ui/svg-icons/content/add';
|
import ContentAdd from 'material-ui/svg-icons/content/add';
|
||||||
@ -88,7 +89,12 @@ class Accounts extends Component {
|
|||||||
<Page>
|
<Page>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
className={ styles.accountTooltip }
|
className={ styles.accountTooltip }
|
||||||
text='your accounts are visible for easy access, allowing you to edit the meta information, make transfers, view transactions and fund the account'
|
text={
|
||||||
|
<FormattedMessage
|
||||||
|
id='accounts.tooltip.overview'
|
||||||
|
defaultMessage='your accounts are visible for easy access, allowing you to edit the meta information, make transfers, view transactions and fund the account'
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{ this.renderWallets() }
|
{ this.renderWallets() }
|
||||||
@ -228,7 +234,12 @@ class Accounts extends Component {
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
className={ styles.toolbarTooltip }
|
className={ styles.toolbarTooltip }
|
||||||
right
|
right
|
||||||
text='actions relating to the current view are available on the toolbar for quick access, be it for performing actions or creating a new item'
|
text={
|
||||||
|
<FormattedMessage
|
||||||
|
id='accounts.tooltip.actions'
|
||||||
|
defaultMessage='actions relating to the current view are available on the toolbar for quick access, be it for performing actions or creating a new item'
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Actionbar>
|
</Actionbar>
|
||||||
);
|
);
|
||||||
|
@ -26,13 +26,12 @@ const SIGNER_ID = 'signer';
|
|||||||
|
|
||||||
export default class Tab extends Component {
|
export default class Tab extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
children: PropTypes.node,
|
|
||||||
pendings: PropTypes.number,
|
pendings: PropTypes.number,
|
||||||
view: PropTypes.object.isRequired
|
view: PropTypes.object.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { view, children } = this.props;
|
const { view } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MUITab
|
<MUITab
|
||||||
@ -42,9 +41,7 @@ export default class Tab extends Component {
|
|||||||
? this.renderSignerLabel()
|
? this.renderSignerLabel()
|
||||||
: this.renderLabel(view.id)
|
: this.renderLabel(view.id)
|
||||||
}
|
}
|
||||||
>
|
/>
|
||||||
{ children }
|
|
||||||
</MUITab>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ let instance;
|
|||||||
function render (id = 'signer') {
|
function render (id = 'signer') {
|
||||||
component = shallow(
|
component = shallow(
|
||||||
<Tab
|
<Tab
|
||||||
children={ <div>testChildren</div> }
|
|
||||||
pending={ 5 }
|
pending={ 5 }
|
||||||
view={ { id } }
|
view={ { id } }
|
||||||
/>
|
/>
|
||||||
|
@ -60,8 +60,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabbarTooltip {
|
.tabbarTooltip {
|
||||||
left: 3.3em;
|
left: 3em;
|
||||||
top: 0.5em;
|
top: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
// 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';
|
||||||
@ -49,6 +50,15 @@ class TabBar extends Component {
|
|||||||
</ToolbarGroup>
|
</ToolbarGroup>
|
||||||
<div className={ styles.tabs }>
|
<div className={ styles.tabs }>
|
||||||
{ this.renderTabItems() }
|
{ this.renderTabItems() }
|
||||||
|
<Tooltip
|
||||||
|
className={ styles.tabbarTooltip }
|
||||||
|
text={
|
||||||
|
<FormattedMessage
|
||||||
|
id='tabBar.tooltip.overview'
|
||||||
|
defaultMessage='navigate between the different parts and views of the application, switching between an account view, token view and distributed application view'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ToolbarGroup className={ styles.last }>
|
<ToolbarGroup className={ styles.last }>
|
||||||
<div />
|
<div />
|
||||||
@ -61,15 +71,6 @@ class TabBar extends Component {
|
|||||||
const { views, pending } = this.props;
|
const { views, pending } = this.props;
|
||||||
|
|
||||||
return views.map((view, index) => {
|
return views.map((view, index) => {
|
||||||
const body = (view.id === 'accounts')
|
|
||||||
? (
|
|
||||||
<Tooltip
|
|
||||||
className={ styles.tabbarTooltip }
|
|
||||||
text='navigate between the different parts and views of the application, switching between an account view, token view and distributed application view'
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
activeClassName={ styles.tabactive }
|
activeClassName={ styles.tabactive }
|
||||||
@ -80,9 +81,7 @@ class TabBar extends Component {
|
|||||||
<Tab
|
<Tab
|
||||||
pendings={ pending.length }
|
pendings={ pending.length }
|
||||||
view={ view }
|
view={ view }
|
||||||
>
|
/>
|
||||||
{ body }
|
|
||||||
</Tab>
|
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user