@ -0,0 +1,86 @@ |
|||||
|
import { |
||||
|
triggerToaster |
||||
|
} from '../actionCreators'; |
||||
|
import { |
||||
|
logGuiHttp, |
||||
|
guiLogState |
||||
|
} from './log'; |
||||
|
import Config from '../../config'; |
||||
|
|
||||
|
export function getListUnspent(coin) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'listunspent', |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'getListUnspent', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function getRawTransaction(coin, txid) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'getrawtransaction', |
||||
|
params: [ |
||||
|
txid, |
||||
|
1 |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'getTransaction', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
@ -0,0 +1,164 @@ |
|||||
|
import { |
||||
|
triggerToaster, |
||||
|
getNewKMDAddresses |
||||
|
} from '../actionCreators'; |
||||
|
import { |
||||
|
logGuiHttp, |
||||
|
guiLogState |
||||
|
} from './log'; |
||||
|
import Config from '../../config'; |
||||
|
|
||||
|
function getNewAddress(coin) { // TODO: remove(?)
|
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'getnewaddress' |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'genJumblrAddress + getKMDAddressesNative', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function setJumblrAddress(coin, type, address) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: type === 'deposit' ? 'jumblr_deposit' : 'jumblr_secret', |
||||
|
params: [address], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'setJumblrAddress', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function dumpPrivkey(coin, key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'dumpprivkey', |
||||
|
params: [key], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'dumpPrivkey ', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function importPrivkey(coin, key) { |
||||
|
return new Promise((resolve, reject) => { |
||||
|
const payload = { |
||||
|
mode: null, |
||||
|
chain: coin, |
||||
|
cmd: 'importprivkey', |
||||
|
params: [ |
||||
|
key, |
||||
|
'', |
||||
|
false |
||||
|
], |
||||
|
}; |
||||
|
|
||||
|
const _fetchConfig = { |
||||
|
method: 'POST', |
||||
|
headers: { |
||||
|
'Content-Type': 'application/json', |
||||
|
}, |
||||
|
body: JSON.stringify({ 'payload': payload }), |
||||
|
}; |
||||
|
|
||||
|
fetch( |
||||
|
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, |
||||
|
_fetchConfig |
||||
|
) |
||||
|
.catch(function(error) { |
||||
|
console.log(error); |
||||
|
dispatch( |
||||
|
triggerToaster( |
||||
|
'importPrivkey ', |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
}) |
||||
|
.then(response => response.json()) |
||||
|
.then(json => { |
||||
|
resolve(json.result ? json.result : json); |
||||
|
}) |
||||
|
}); |
||||
|
} |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@ -0,0 +1,136 @@ |
|||||
|
import React from 'react'; |
||||
|
import ReactDOM from 'react-dom'; |
||||
|
import Store from '../../../store'; |
||||
|
import { |
||||
|
toggleClaimInterestModal, |
||||
|
getListUnspent, |
||||
|
getRawTransaction, |
||||
|
copyString, |
||||
|
sendToAddressPromise, |
||||
|
triggerToaster |
||||
|
} from '../../../actions/actionCreators'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
import { |
||||
|
ClaimInterestModalRender, |
||||
|
_ClaimInterestTableRender |
||||
|
} from './claimInterestModal.render'; |
||||
|
|
||||
|
class ClaimInterestModal extends React.Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
open: false, |
||||
|
isLoading: true, |
||||
|
transactionsList: [], |
||||
|
showZeroInterest: true, |
||||
|
}; |
||||
|
this.claimInterestTableRender = this.claimInterestTableRender.bind(this); |
||||
|
this.toggleZeroInterest = this.toggleZeroInterest.bind(this); |
||||
|
this.loadListUnspent = this.loadListUnspent.bind(this); |
||||
|
this.checkTransactionsListLength = this.checkTransactionsListLength.bind(this); |
||||
|
} |
||||
|
|
||||
|
componentWillMount() { |
||||
|
this.loadListUnspent(); |
||||
|
} |
||||
|
|
||||
|
loadListUnspent() { |
||||
|
let _transactionsList = []; |
||||
|
|
||||
|
getListUnspent(this.props.ActiveCoin.coin) |
||||
|
.then((json) => { |
||||
|
if (json && |
||||
|
json.length) { |
||||
|
for (let i = 0; i < json.length; i++) { |
||||
|
getRawTransaction(this.props.ActiveCoin.coin, json[i].txid) |
||||
|
.then((_json) => { |
||||
|
_transactionsList.push({ |
||||
|
address: json[i].address, |
||||
|
locktime: _json.locktime, |
||||
|
amount: json[i].amount, |
||||
|
interest: json[i].interest, |
||||
|
txid: json[i].txid, |
||||
|
}); |
||||
|
|
||||
|
if (i === json.length - 1) { |
||||
|
this.setState({ |
||||
|
transactionsList: _transactionsList, |
||||
|
isLoading: false, |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
claimInterest(address, amount) { |
||||
|
sendToAddressPromise(this.props.ActiveCoin.coin, this.state.transactionsList[0].address, this.props.ActiveCoin.balance.transparent) |
||||
|
.then((json) => { |
||||
|
if (json.error && |
||||
|
json.error.code) { |
||||
|
Store.dispatch( |
||||
|
triggerToaster( |
||||
|
json.error.message, |
||||
|
'Error', |
||||
|
'error' |
||||
|
) |
||||
|
); |
||||
|
} else if (json.result && json.result.length && json.result.length === 64) { |
||||
|
Store.dispatch( |
||||
|
triggerToaster( |
||||
|
`Your full balance is sent to address ${this.state.transactionsList[0].address}. Check back your new balance in a few minutes.`, |
||||
|
translate('TOASTR.WALLET_NOTIFICATION'), |
||||
|
'success', |
||||
|
false |
||||
|
) |
||||
|
); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
checkTransactionsListLength() { |
||||
|
if (this.state.transactionsList && this.state.transactionsList.length) { |
||||
|
return true; |
||||
|
} else if (!this.state.transactionsList || !this.state.transactionsList.length) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
toggleZeroInterest() { |
||||
|
this.setState({ |
||||
|
showZeroInterest: !this.state.showZeroInterest, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
copyTxId(txid) { |
||||
|
Store.dispatch(copyString(txid, 'Transaction ID copied')); |
||||
|
} |
||||
|
|
||||
|
claimInterestTableRender() { |
||||
|
return _ClaimInterestTableRender.call(this); |
||||
|
} |
||||
|
|
||||
|
componentWillReceiveProps(props) { |
||||
|
if (props.Dashboard.displayClaimInterestModal !== this.state.open) { |
||||
|
this.setState({ |
||||
|
open: props.Dashboard.displayClaimInterestModal, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
if (!this.state.open && |
||||
|
props.Dashboard.displayClaimInterestModal) { |
||||
|
this.loadListUnspent(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
closeModal() { |
||||
|
Store.dispatch(toggleClaimInterestModal(false)); |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
return ClaimInterestModalRender.call(this); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ClaimInterestModal; |
@ -0,0 +1,132 @@ |
|||||
|
import React from 'react'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
|
||||
|
const MIN_INTEREST_THRESHOLD = 0.001; |
||||
|
|
||||
|
export const _ClaimInterestTableRender = function() { |
||||
|
const _transactionsList = this.state.transactionsList; |
||||
|
let _items = []; |
||||
|
|
||||
|
for (let i = 0; i < _transactionsList.length; i++) { |
||||
|
if ((_transactionsList[i].interest === 0 && this.state.showZeroInterest) || (_transactionsList[i].amount > 0 && _transactionsList[i].interest > 0)) { |
||||
|
_items.push( |
||||
|
<tr key={ `${_transactionsList[i].txid}${_transactionsList[i].address}` }> |
||||
|
<td> |
||||
|
<button |
||||
|
className="btn btn-default btn-xs clipboard-edexaddr copy-string-btn" |
||||
|
title={ translate('INDEX.COPY_TO_CLIPBOARD') } |
||||
|
onClick={ () => this.copyTxId(_transactionsList[i].txid) }> |
||||
|
<i className="icon wb-copy"></i> { translate('INDEX.COPY') } |
||||
|
</button> |
||||
|
</td> |
||||
|
<td>{ _transactionsList[i].address }</td> |
||||
|
<td className={ _transactionsList[i].amount > 10 ? 'green bold' : '' }>{ _transactionsList[i].amount }</td> |
||||
|
<td>{ _transactionsList[i].interest }</td> |
||||
|
<td className="locktime center"> |
||||
|
{ _transactionsList[i].locktime && |
||||
|
<i className="fa-check-circle green"></i> |
||||
|
} |
||||
|
{ !_transactionsList[i].locktime && |
||||
|
<i className="fa-exclamation-circle red"></i> |
||||
|
} |
||||
|
</td> |
||||
|
</tr> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<span> |
||||
|
<div className="padding-bottom-20"> |
||||
|
<strong>Requirements to accrue interest:</strong> locktime field is set and amount is greater than <strong>10 KMD</strong> |
||||
|
</div> |
||||
|
<div className="text-left padding-top-10 padding-bottom-10"> |
||||
|
<label className="switch"> |
||||
|
<input |
||||
|
type="checkbox" |
||||
|
checked={ this.state.showZeroInterest } /> |
||||
|
<div |
||||
|
className="slider" |
||||
|
onClick={ this.toggleZeroInterest }></div> |
||||
|
</label> |
||||
|
<div |
||||
|
className="toggle-label margin-right-15 pointer" |
||||
|
onClick={ this.toggleZeroInterest }> |
||||
|
Show zero interest |
||||
|
</div> |
||||
|
</div> |
||||
|
<button |
||||
|
type="button" |
||||
|
className="btn btn-success waves-effect waves-light claim-btn" |
||||
|
onClick={ () => this.claimInterest() }> |
||||
|
<i className="icon fa-dollar"></i> Claim interest |
||||
|
</button> |
||||
|
<div className="table-scroll"> |
||||
|
<table className="table table-hover dataTable table-striped"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th></th> |
||||
|
<th>Address</th> |
||||
|
<th>Amount</th> |
||||
|
<th>Interest</th> |
||||
|
<th>Locktime</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
{ _items } |
||||
|
</tbody> |
||||
|
<tfoot> |
||||
|
<tr> |
||||
|
<th></th> |
||||
|
<th>Address</th> |
||||
|
<th>Amount</th> |
||||
|
<th>Interest</th> |
||||
|
<th>Locktime</th> |
||||
|
</tr> |
||||
|
</tfoot> |
||||
|
</table> |
||||
|
</div> |
||||
|
</span> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export const ClaimInterestModalRender = function() { |
||||
|
return ( |
||||
|
<span> |
||||
|
<div className={ 'modal modal-claim-interest modal-3d-sign ' + (this.state.open ? 'show in' : 'fade hide') }> |
||||
|
<div className="modal-dialog modal-center modal-sm"> |
||||
|
<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">Claim interest</h4> |
||||
|
</div> |
||||
|
<div className="modal-body"> |
||||
|
<i |
||||
|
className="icon fa-refresh pointer refresh-icon" |
||||
|
onClick={ this.loadListUnspent }></i> |
||||
|
<div className="animsition vertical-align fade-in"> |
||||
|
<div className="page-content vertical-align-middle full-width"> |
||||
|
{ this.state.isLoading && |
||||
|
<span>Loading interest data...</span> |
||||
|
} |
||||
|
{ !this.state.isLoading && this.checkTransactionsListLength() && |
||||
|
<div>{ this.claimInterestTableRender() }</div> |
||||
|
} |
||||
|
{ !this.state.isLoading && !this.checkTransactionsListLength() && |
||||
|
<div>No data</div> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className={ 'modal-backdrop ' + (this.state.open ? 'show in' : 'fade hide') }></div> |
||||
|
</span> |
||||
|
); |
||||
|
}; |
@ -0,0 +1,32 @@ |
|||||
|
import React from 'react'; |
||||
|
import { getCoinTitle } from '../../../util/coinHelper'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
import { toggleLoginSettingsModal } from '../../../actions/actionCreators'; |
||||
|
import Store from '../../../store'; |
||||
|
|
||||
|
import { LoginSettingsModalRender } from './loginSettingsModal.render'; |
||||
|
|
||||
|
class LoginSettingsModal extends React.Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
}; |
||||
|
this.closeLoginSettingsModal = this.closeLoginSettingsModal.bind(this); |
||||
|
} |
||||
|
|
||||
|
closeLoginSettingsModal() { |
||||
|
Store.dispatch(toggleLoginSettingsModal(false)); |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
if (this.props && |
||||
|
this.props.Main && |
||||
|
this.props.Main.displayLoginSettingsModal) { |
||||
|
return LoginSettingsModalRender.call(this); |
||||
|
} else { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default LoginSettingsModal; |
@ -0,0 +1,34 @@ |
|||||
|
import React from 'react'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
import About from '../about/about'; |
||||
|
import Settings from '../settings/settings'; |
||||
|
|
||||
|
export const LoginSettingsModalRender = function() { |
||||
|
return ( |
||||
|
<div> |
||||
|
<div className="modal show login-settings-modal"> |
||||
|
<div className="modal-dialog modal-center modal-lg"> |
||||
|
<div className="modal-content"> |
||||
|
<div className="modal-body modal-body-container"> |
||||
|
{ this.props.section === 'settings' && |
||||
|
<Settings |
||||
|
{...this.props} |
||||
|
disableWalletSpecificUI="true" /> |
||||
|
} |
||||
|
{ this.props.section === 'about' && |
||||
|
<About /> |
||||
|
} |
||||
|
</div> |
||||
|
<div className="modal-footer"> |
||||
|
<button |
||||
|
type="button" |
||||
|
className="btn btn-default" |
||||
|
onClick={ this.closeLoginSettingsModal }>{ translate('INDEX.CLOSE') }</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className="modal-backdrop show in"></div> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
@ -0,0 +1,80 @@ |
|||||
|
import React from 'react'; |
||||
|
import ReactDOM from 'react-dom'; |
||||
|
import Store from '../../../store'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
import QrReader from 'react-qr-reader' |
||||
|
import { |
||||
|
QRModalRender, |
||||
|
QRModalReaderRender |
||||
|
} from './qrModal.render'; |
||||
|
|
||||
|
class QRModal extends React.Component { |
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
modalIsOpen: false, |
||||
|
error: null, |
||||
|
}; |
||||
|
this.openModal = this.openModal.bind(this); |
||||
|
this.closeModal = this.closeModal.bind(this); |
||||
|
this.handleScan = this.handleScan.bind(this); |
||||
|
this.handleError = this.handleError.bind(this); |
||||
|
} |
||||
|
|
||||
|
handleScan(data) { |
||||
|
if (data !== null) { |
||||
|
if (this.props.mode === 'scan') { |
||||
|
this.props.setRecieverFromScan(data); |
||||
|
} |
||||
|
|
||||
|
this.closeModal(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
handleError(err) { |
||||
|
if (err.name === 'NoVideoInputDevicesError') { |
||||
|
this.setState({ |
||||
|
error: 'Error: No video input devices found!', |
||||
|
}); |
||||
|
} else { |
||||
|
this.setState({ |
||||
|
error: 'Error: unknown error!', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
openModal() { |
||||
|
this.setState({ |
||||
|
modalIsOpen: true |
||||
|
}); |
||||
|
|
||||
|
if (this.props.mode === 'scan') { |
||||
|
ReactDOM.render( |
||||
|
<QrReader |
||||
|
delay={50} |
||||
|
style={{ |
||||
|
height: 281, |
||||
|
width: 500, |
||||
|
transform: 'scaleX(-1)' |
||||
|
}} |
||||
|
onError={ this.handleError } |
||||
|
onScan={ this.handleScan } />, document.getElementById('webcam')); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
closeModal() { |
||||
|
this.setState({ |
||||
|
modalIsOpen: false, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
if (this.props.mode === 'scan') { |
||||
|
return QRModalReaderRender.call(this); |
||||
|
} else { |
||||
|
return QRModalRender.call(this); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default QRModal; |
@ -0,0 +1,88 @@ |
|||||
|
import React from 'react'; |
||||
|
import { translate } from '../../../translate/translate'; |
||||
|
import QRCode from 'qrcode.react'; |
||||
|
|
||||
|
export const QRModalRender = function () { |
||||
|
return ( |
||||
|
<span> |
||||
|
<span className="label label-default margin-left-10 action" |
||||
|
title={ translate('INDEX.QRCODE') } |
||||
|
onClick={ this.openModal }> |
||||
|
<i className="icon fa-qrcode"></i> |
||||
|
</span> |
||||
|
<div |
||||
|
className={ 'modal modal-3d-sign ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') } |
||||
|
id="QRModal"> |
||||
|
<div className="modal-dialog modal-center modal-sm"> |
||||
|
<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.SCAN_QR_CODE') }</h4> |
||||
|
</div> |
||||
|
<div className="modal-body"> |
||||
|
<div className="animsition vertical-align fade-in"> |
||||
|
<div className="page-content vertical-align-middle"> |
||||
|
<QRCode |
||||
|
value={ this.props.content } |
||||
|
size={ 198 } /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className={ 'modal-backdrop ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') }></div> |
||||
|
</span> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export const QRModalReaderRender = function () { |
||||
|
return ( |
||||
|
<span> |
||||
|
<button type="button" |
||||
|
className="btn btn-default" |
||||
|
onClick={ this.openModal }> |
||||
|
<i className="icon fa-qrcode"></i> |
||||
|
{ translate('INDEX.SCAN_QRCODE_WEBCAM') } |
||||
|
</button> |
||||
|
<div |
||||
|
className={ 'modal modal-3d-sign ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') } |
||||
|
id="QRReadModal"> |
||||
|
<div className="modal-dialog modal-center modal-md"> |
||||
|
<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.SCAN_QRCODE_WEBCAM') }</h4> |
||||
|
</div> |
||||
|
<div className="modal-body"> |
||||
|
<div className="animsition vertical-align fade-in"> |
||||
|
<div |
||||
|
className="page-content vertical-align-middle" |
||||
|
style={{ |
||||
|
width: '100%', |
||||
|
textAlign: 'center', |
||||
|
fontSize: '16px' |
||||
|
}}> |
||||
|
<div id="webcam"> |
||||
|
{ this.state.error } |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div className={ 'modal-backdrop ' + (this.state.modalIsOpen ? 'show in' : 'fade hide') }></div> |
||||
|
</span> |
||||
|
); |
||||
|
}; |