Browse Source

Merge pull request #172 from SuperNETorg/feature/qr-invoice

Feature/qr invoice
all-modes^2
pbca26 8 years ago
committed by GitHub
parent
commit
9c1c979c7d
  1. 32
      react/src/components/dashboard/bodyBottom/bodyBottom.js
  2. 140
      react/src/components/dashboard/invoiceModal/invoiceModal.js
  3. 107
      react/src/components/dashboard/invoiceModal/invoiceModal.render.js
  4. 14
      react/src/components/dashboard/qrModal/qrModal.js
  5. 3
      react/src/components/dashboard/receiveCoin/receiveCoin.render.js
  6. 26
      react/src/components/dashboard/sendCoin/sendCoin.js
  7. 35
      react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js
  8. 4
      react/src/translate/en.js

32
react/src/components/dashboard/bodyBottom/bodyBottom.js

@ -0,0 +1,32 @@
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
export default class BodyEnd extends React.PureComponent {
static propTypes = {
children: PropTypes.node,
};
componentDidMount() {
this._popup = document.createElement('div');
document.body.appendChild(this._popup);
this._render();
}
componentDidUpdate() {
this._render();
}
componentWillUnmount() {
ReactDOM.unmountComponentAtNode(this._popup);
document.body.removeChild(this._popup);
}
_render() {
ReactDOM.render(this.props.children, this._popup);
}
render() {
return null;
}
}

140
react/src/components/dashboard/invoiceModal/invoiceModal.js

@ -0,0 +1,140 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { connect } from 'react-redux';
import Store from '../../../store';
import { translate } from '../../../translate/translate';
import BodyEnd from '../bodyBottom/bodyBottom';
import {
InvoiceModalRender,
InvoiceModalButtonRender,
AddressItemRender,
} from './invoiceModal.render';
class InvoiceModal extends React.Component {
constructor() {
super();
this.state = {
modalIsOpen: false,
content: '',
qrAddress: '',
qrAmount: 0,
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.updateInput = this.updateInput.bind(this);
this.renderAddressList = this.renderAddressList.bind(this);
this.updateQRContent = this.updateQRContent.bind(this);
}
openModal() {
this.setState({
modalIsOpen: true
});
}
updateInput(e) {
this.setState({
[e.target.name]: e.target.value
}, this.updateQRContent);
}
updateQRContent() {
this.setState({
content: JSON.stringify({
address: this.state.qrAddress,
amount: this.state.qrAmount,
coin: this.props.ActiveCoin.coin,
}),
});
}
closeModal() {
this.setState({
modalIsOpen: false,
});
}
hasNoAmount(address) {
return address.amount === 'N/A' || address.amount === 0;
}
hasNoInterest(address) {
return address.interest === 'N/A' || address.interest === 0 || !address.interest;
}
isBasiliskMode() {
return this.props.ActiveCoin.mode === 'basilisk';
}
isNativeMode() {
return this.props.ActiveCoin.mode == 'native';
}
renderAddressList(type) {
const _addresses = this.props.ActiveCoin.addresses;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
let items = [];
for (let i = 0; i < _addresses[type].length; i++) {
let address = _addresses[type][i];
if (this.isBasiliskMode() &&
this.hasNoAmount(address)) {
address.amount = _cache && _cache[_coin][address.address] &&
_cache[_coin][address.address].getbalance &&
_cache[_coin][address.address].getbalance.data &&
_cache[_coin][address.address].getbalance.data.balance ? _cache[_coin][address.address].getbalance.data.balance : 'N/A';
}
if (this.isBasiliskMode() &&
this.hasNoInterest(address)) {
address.interest = _cache && _cache[_coin][address.address] &&
_cache[_coin][address.address].getbalance &&
_cache[_coin][address.address].getbalance.data &&
_cache[_coin][address.address].getbalance.data.interest ? _cache[_coin][address.address].getbalance.data.interest : 'N/A';
}
items.push(
AddressItemRender.call(this, address, type)
);
}
return items;
} else {
return null;
}
}
render() {
if (this.state.modalIsOpen) {
return <BodyEnd>{ InvoiceModalRender.call(this) }</BodyEnd>
} else {
return InvoiceModalButtonRender.call(this);
}
}
}
const mapStateToProps = (state) => {
return {
ActiveCoin: {
coin: state.ActiveCoin.coin,
mode: state.ActiveCoin.mode,
send: state.ActiveCoin.send,
receive: state.ActiveCoin.receive,
balance: state.ActiveCoin.balance,
cache: state.ActiveCoin.cache,
activeAddress: state.ActiveCoin.activeAddress,
lastSendToResponse: state.ActiveCoin.lastSendToResponse,
addresses: state.ActiveCoin.addresses,
},
Dashboard: {
activeHandle: state.Dashboard.activeHandle,
},
};
};
export default connect(mapStateToProps)(InvoiceModal);

107
react/src/components/dashboard/invoiceModal/invoiceModal.render.js

@ -0,0 +1,107 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import QRCode from 'qrcode.react';
export const InvoiceModalRender = function () {
return (
<span>
<div
className={ 'modal modal-3d-sign ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') }
id="QRModal">
<div className="modal-dialog modal-center modal-lg">
<div className="modal-content">
<div className="modal-header bg-orange-a400 wallet-send-header">
<button
type="button"
className="close white"
onClick={ this.closeModal }>
<span>×</span>
</button>
<h4 className="modal-title white text-left">{ translate('INDEX.CREATE_INVOICE_QR') }</h4>
</div>
<div className="modal-body">
<div className="animsition fade-in">
<div className="page-content">
<div className="row">
<div className="col-lg-8 form-group form-material vertical-align-middle">
<form>
<label
className="control-label"
htmlFor="qrAddress">
{ translate('INDEX.RECEIVING_ADDRESS') }
</label>
<select
className="form-control"
name="qrAddress"
id="qrAddress"
value={ this.state.qrAddress }
onChange={ this.updateInput }>
<option value="-1">
{ translate('INDEX.CHOOSE_RECEIVING_ADDRESS') }
</option>
{ this.renderAddressList('public') }
{ this.isNativeMode() && this.renderAddressList('private') }
</select>
<label
className="control-label margin-top-20"
htmlFor="qrCoinAmount">
{ this.props.ActiveCoin.coin }
</label>
<input
type="number"
min="0"
className="form-control"
id="qrCoinAmount"
name="qrAmount"
placeholder="0"
autoComplete="off"
value={ this.state.qrAmount }
onChange={ this.updateInput } />
</form>
</div>
<div className="col-lg-4">
<QRCode
value={ this.state.content }
size={ 198 } />
</div>
</div>
<div className="row hide">
<div className="col-lg-12">
<p className="help-block">
{ translate('INDEX.QR_CONTENT') }:<br />
{ this.state.content }
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className={ 'modal-backdrop ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') }></div>
</span>
);
};
export const InvoiceModalButtonRender = function () {
return (
<span>
<button type="button"
className="btn btn-success waves-effect waves-light margin-right-10"
onClick={ this.openModal }>
<i className="icon fa-file-text-o"></i>&nbsp;
{ translate('INDEX.CREATE_INVOICE') }
</button>
</span>
);
};
export const AddressItemRender = function(address, type) {
return (
<option key={ address.address } value={ address.address }>
{ type === 'public' ? address.address : `${address.address.substring(0, 34)}...` }
&nbsp; (Balance: { address.amount })
</option>
);
};

14
react/src/components/dashboard/qrModal/qrModal.js

@ -33,15 +33,9 @@ class QRModal extends React.Component {
} }
handleError(err) { handleError(err) {
if (err.name === 'NoVideoInputDevicesError') { this.setState({
this.setState({ error: err.name === 'NoVideoInputDevicesError' ? translate('DASHBOARD.QR_ERR_NO_VIDEO_DEVICE') : translate('DASHBOARD.QR_ERR_UNKNOWN'),
error: translate('DASHBOARD.QR_ERR_NO_VIDEO_DEVICE'), });
});
} else {
this.setState({
error: translate('DASHBOARD.QR_ERR_UNKNOWN'),
});
}
} }
openModal() { openModal() {
@ -68,6 +62,8 @@ class QRModal extends React.Component {
modalIsOpen: false, modalIsOpen: false,
errorShown: this.state.error ? true : false, errorShown: this.state.error ? true : false,
}); });
ReactDOM.unmountComponentAtNode(document.getElementById('webcam'));
} }
render() { render() {

3
react/src/components/dashboard/receiveCoin/receiveCoin.render.js

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { translate } from '../../../translate/translate'; import { translate } from '../../../translate/translate';
import QRModal from '../qrModal/qrModal'; import QRModal from '../qrModal/qrModal';
import InvoiceModal from '../invoiceModal/invoiceModal';
export const AddressActionsBasiliskModeRender = function(address) { export const AddressActionsBasiliskModeRender = function(address) {
return ( return (
@ -69,6 +70,7 @@ export const _ReceiveCoinTableRender = function() {
<label className="switch"> <label className="switch">
<input <input
type="checkbox" type="checkbox"
value="on"
checked={ this.state.hideZeroAddresses } /> checked={ this.state.hideZeroAddresses } />
<div <div
className="slider" className="slider"
@ -139,6 +141,7 @@ export const ReceiveCoinRender = function() {
<header className="panel-heading"> <header className="panel-heading">
{ this.isNativeMode() && { this.isNativeMode() &&
<div className="panel-actions"> <div className="panel-actions">
<InvoiceModal />
<div <div
className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') } className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }> onClick={ this.openDropMenu }>

26
react/src/components/dashboard/sendCoin/sendCoin.js

@ -67,9 +67,29 @@ class SendCoin extends React.Component {
} }
setRecieverFromScan(receiver) { setRecieverFromScan(receiver) {
this.setState({ try {
sendTo: receiver const recObj = JSON.parse(receiver);
});
if (recObj &&
typeof recObj === 'object') {
if (recObj.coin === this.props.ActiveCoin.coin) {
if (recObj.amount) {
this.setState({
amount: recObj.amount,
});
}
if (recObj.address) {
this.setState({
sendTo: recObj.address,
});
}
}
}
} catch (e) {
this.setState({
sendTo: receiver,
});
}
document.getElementById('edexcoinSendTo').focus(); document.getElementById('edexcoinSendTo').focus();
} }

35
react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js

@ -81,10 +81,29 @@ class WalletsNativeSend extends React.Component {
} }
setRecieverFromScan(receiver) { setRecieverFromScan(receiver) {
this.setState({ try {
sendTo: receiver, const recObj = JSON.parse(receiver);
});
if (recObj &&
typeof recObj === 'object') {
if (recObj.coin === this.props.ActiveCoin.coin) {
if (recObj.amount) {
this.setState({
amount: recObj.amount,
});
}
if (recObj.address) {
this.setState({
sendTo: recObj.address,
});
}
}
}
} catch (e) {
this.setState({
sendTo: receiver,
});
}
document.getElementById('kmdWalletSendTo').focus(); document.getElementById('kmdWalletSendTo').focus();
} }
@ -99,9 +118,11 @@ class WalletsNativeSend extends React.Component {
} }
checkZAddressCount() { checkZAddressCount() {
if (this.props.ActiveCoin.addresses && const _addresses = this.props.ActiveCoin.addresses;
(!this.props.ActiveCoin.addresses.private ||
this.props.ActiveCoin.addresses.private.length === 0)) { if (_addresses &&
(!_addresses.private ||
_addresses.private.length === 0)) {
this.setState({ this.setState({
renderAddressDropdown: false, renderAddressDropdown: false,
}); });

4
react/src/translate/en.js

@ -307,6 +307,10 @@ export const _lang = {
'TOGGLE_ZERO_ADDRESSES': 'Toggle empty addresses', 'TOGGLE_ZERO_ADDRESSES': 'Toggle empty addresses',
'NEXT_PAGE': 'Next Page', 'NEXT_PAGE': 'Next Page',
'PREVIOUS_PAGE': 'Previous Page', 'PREVIOUS_PAGE': 'Previous Page',
'CREATE_INVOICE': 'Create Invoice',
'CREATE_INVOICE_QR': 'Create Invoice QR Code',
'QR_CONTENT': 'QR Content',
'CHOOSE_RECEIVING_ADDRESS': 'Choose Address',
}, },
'ATOMIC': { 'ATOMIC': {
'RAW_OUTPUT': 'Raw Output', 'RAW_OUTPUT': 'Raw Output',

Loading…
Cancel
Save