diff --git a/react/src/components/dashboard/bodyBottom/bodyBottom.js b/react/src/components/dashboard/bodyBottom/bodyBottom.js new file mode 100644 index 0000000..f8b741e --- /dev/null +++ b/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; + } +} \ No newline at end of file diff --git a/react/src/components/dashboard/invoiceModal/invoiceModal.js b/react/src/components/dashboard/invoiceModal/invoiceModal.js new file mode 100755 index 0000000..73602ab --- /dev/null +++ b/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 { InvoiceModalRender.call(this) } + } 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); diff --git a/react/src/components/dashboard/invoiceModal/invoiceModal.render.js b/react/src/components/dashboard/invoiceModal/invoiceModal.render.js new file mode 100644 index 0000000..25b59b9 --- /dev/null +++ b/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 ( + +
+
+
+
+ +

{ translate('INDEX.CREATE_INVOICE_QR') }

+
+
+
+
+
+
+
+ + + + +
+
+
+ +
+
+
+
+

+ { translate('INDEX.QR_CONTENT') }:
+ { this.state.content } +

+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export const InvoiceModalButtonRender = function () { + return ( + + + + ); +}; + +export const AddressItemRender = function(address, type) { + return ( + + ); +}; diff --git a/react/src/components/dashboard/qrModal/qrModal.js b/react/src/components/dashboard/qrModal/qrModal.js index c1a5757..e152ba9 100755 --- a/react/src/components/dashboard/qrModal/qrModal.js +++ b/react/src/components/dashboard/qrModal/qrModal.js @@ -33,15 +33,9 @@ class QRModal extends React.Component { } handleError(err) { - if (err.name === 'NoVideoInputDevicesError') { - this.setState({ - error: translate('DASHBOARD.QR_ERR_NO_VIDEO_DEVICE'), - }); - } else { - this.setState({ - error: translate('DASHBOARD.QR_ERR_UNKNOWN'), - }); - } + this.setState({ + error: err.name === 'NoVideoInputDevicesError' ? translate('DASHBOARD.QR_ERR_NO_VIDEO_DEVICE') : translate('DASHBOARD.QR_ERR_UNKNOWN'), + }); } openModal() { @@ -68,6 +62,8 @@ class QRModal extends React.Component { modalIsOpen: false, errorShown: this.state.error ? true : false, }); + + ReactDOM.unmountComponentAtNode(document.getElementById('webcam')); } render() { diff --git a/react/src/components/dashboard/receiveCoin/receiveCoin.render.js b/react/src/components/dashboard/receiveCoin/receiveCoin.render.js index 13dc485..8ad55fe 100644 --- a/react/src/components/dashboard/receiveCoin/receiveCoin.render.js +++ b/react/src/components/dashboard/receiveCoin/receiveCoin.render.js @@ -1,6 +1,7 @@ import React from 'react'; import { translate } from '../../../translate/translate'; import QRModal from '../qrModal/qrModal'; +import InvoiceModal from '../invoiceModal/invoiceModal'; export const AddressActionsBasiliskModeRender = function(address) { return ( @@ -69,6 +70,7 @@ export const _ReceiveCoinTableRender = function() {