Add QrCode & Copy to ShapeShift (#4322)

* Extract CopyIcon to ~/ui/Icons

* Add copy & QrCode address

* Default size 4

* Add bitcoin: link

* use protocol links applicable to coin exchanged

* Remove .only
This commit is contained in:
Jaco Greeff 2017-01-27 15:33:02 +01:00 committed by GitHub
parent e81787da34
commit cb8fea3b5a
6 changed files with 130 additions and 10 deletions

View File

@ -18,6 +18,8 @@ import { observer } from 'mobx-react';
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { CopyToClipboard, QrCode } from '~/ui';
import Value from '../Value'; import Value from '../Value';
import styles from '../shapeshift.css'; import styles from '../shapeshift.css';
@ -61,9 +63,7 @@ export default class AwaitingDepositStep extends Component {
} } } }
/> />
</div> </div>
<div className={ styles.hero }> { this.renderAddress(depositAddress, coinSymbol) }
{ depositAddress }
</div>
<div className={ styles.price }> <div className={ styles.price }>
<div> <div>
<FormattedMessage <FormattedMessage
@ -79,4 +79,42 @@ export default class AwaitingDepositStep extends Component {
</div> </div>
); );
} }
renderAddress (depositAddress, coinSymbol) {
const qrcode = (
<QrCode
className={ styles.qrcode }
value={ depositAddress }
/>
);
let protocolLink = null;
// TODO: Expand for other coins where protocols are available
switch (coinSymbol) {
case 'BTC':
protocolLink = `bitcoin:${depositAddress}`;
break;
}
return (
<div className={ styles.addressInfo }>
{
protocolLink
? (
<a
href={ protocolLink }
target='_blank'
>
{ qrcode }
</a>
)
: qrcode
}
<div className={ styles.address }>
<CopyToClipboard data={ depositAddress } />
<span>{ depositAddress }</span>
</div>
</div>
);
}
} }

View File

@ -19,7 +19,10 @@ import React from 'react';
import AwaitingDepositStep from './'; import AwaitingDepositStep from './';
const TEST_ADDRESS = '0x123456789123456789123456789123456789';
let component; let component;
let instance;
function render () { function render () {
component = shallow( component = shallow(
@ -30,6 +33,7 @@ function render () {
} } } }
/> />
); );
instance = component.instance();
return component; return component;
} }
@ -48,4 +52,61 @@ describe('modals/Shapeshift/AwaitingDepositStep', () => {
render({ depositAddress: 'xyz' }); render({ depositAddress: 'xyz' });
expect(component.find('FormattedMessage').first().props().id).to.match(/awaitingDeposit/); expect(component.find('FormattedMessage').first().props().id).to.match(/awaitingDeposit/);
}); });
describe('instance methods', () => {
describe('renderAddress', () => {
let address;
beforeEach(() => {
address = shallow(instance.renderAddress(TEST_ADDRESS));
});
it('renders the address', () => {
expect(address.text()).to.contain(TEST_ADDRESS);
});
describe('CopyToClipboard', () => {
let copy;
beforeEach(() => {
copy = address.find('Connect(CopyToClipboard)');
});
it('renders the copy', () => {
expect(copy.length).to.equal(1);
});
it('passes the address', () => {
expect(copy.props().data).to.equal(TEST_ADDRESS);
});
});
describe('QrCode', () => {
let qr;
beforeEach(() => {
qr = address.find('QrCode');
});
it('renders the QrCode', () => {
expect(qr.length).to.equal(1);
});
it('passed the address', () => {
expect(qr.props().value).to.equal(TEST_ADDRESS);
});
describe('protocol link', () => {
it('does not render a protocol link (unlinked type)', () => {
expect(address.find('a')).to.have.length(0);
});
it('renders protocol link for BTC', () => {
address = shallow(instance.renderAddress(TEST_ADDRESS, 'BTC'));
expect(address.find('a').props().href).to.equal(`bitcoin:${TEST_ADDRESS}`);
});
});
});
});
});
}); });

View File

@ -14,9 +14,28 @@
/* 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/>.
*/ */
.body { .body {
} }
.addressInfo {
text-align: center;
.address {
background: rgba(255, 255, 255, 0.1);
margin: 0.75em 0;
padding: 1em;
span {
margin-left: 0.75em;
}
}
.qrcode {
margin: 0.75em 0;
}
}
.shapeshift { .shapeshift {
position: absolute; position: absolute;
bottom: 0.5em; bottom: 0.5em;

View File

@ -14,21 +14,21 @@
// 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 { IconButton } from 'material-ui';
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import Clipboard from 'react-copy-to-clipboard';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { IconButton } from 'material-ui';
import Clipboard from 'react-copy-to-clipboard';
import CopyIcon from 'material-ui/svg-icons/content/content-copy';
import Theme from '../Theme';
import { showSnackbar } from '~/redux/providers/snackbarActions'; import { showSnackbar } from '~/redux/providers/snackbarActions';
const { textColor, disabledTextColor } = Theme.flatButton; import { CopyIcon } from '../Icons';
import Theme from '../Theme';
import styles from './copyToClipboard.css'; import styles from './copyToClipboard.css';
const { textColor, disabledTextColor } = Theme.flatButton;
class CopyToClipboard extends Component { class CopyToClipboard extends Component {
static propTypes = { static propTypes = {
showSnackbar: PropTypes.func.isRequired, showSnackbar: PropTypes.func.isRequired,

View File

@ -22,6 +22,7 @@ import CloseIcon from 'material-ui/svg-icons/navigation/close';
import CompareIcon from 'material-ui/svg-icons/action/compare-arrows'; import CompareIcon from 'material-ui/svg-icons/action/compare-arrows';
import ComputerIcon from 'material-ui/svg-icons/hardware/desktop-mac'; import ComputerIcon from 'material-ui/svg-icons/hardware/desktop-mac';
import ContractIcon from 'material-ui/svg-icons/action/code'; import ContractIcon from 'material-ui/svg-icons/action/code';
import CopyIcon from 'material-ui/svg-icons/content/content-copy';
import DashboardIcon from 'material-ui/svg-icons/action/dashboard'; import DashboardIcon from 'material-ui/svg-icons/action/dashboard';
import DeleteIcon from 'material-ui/svg-icons/action/delete'; import DeleteIcon from 'material-ui/svg-icons/action/delete';
import DoneIcon from 'material-ui/svg-icons/action/done-all'; import DoneIcon from 'material-ui/svg-icons/action/done-all';
@ -50,6 +51,7 @@ export {
CompareIcon, CompareIcon,
ComputerIcon, ComputerIcon,
ContractIcon, ContractIcon,
CopyIcon,
DashboardIcon, DashboardIcon,
DeleteIcon, DeleteIcon,
DoneIcon, DoneIcon,

View File

@ -34,7 +34,7 @@ export default class QrCode extends Component {
static defaultProps = { static defaultProps = {
margin: 2, margin: 2,
size: 5 size: 4
}; };
state = { state = {