Browse Source

Merge pull request #116 from pbca26/redux

Redux
all-modes
pbca26 8 years ago
committed by GitHub
parent
commit
75a393bdd7
  1. 1236
      react/src/actions/actionCreators.js
  2. 33
      react/src/components/addcoin/addcoin.js
  3. 2
      react/src/components/dashboard/about.js
  4. 2
      react/src/components/dashboard/coinTileItem.js
  5. 1
      react/src/components/dashboard/dashboard.js
  6. 4
      react/src/components/dashboard/jumblr.js
  7. 29
      react/src/components/dashboard/navbar.js
  8. 63
      react/src/components/dashboard/notifications.js
  9. 57
      react/src/components/dashboard/sendCoin.js
  10. 5
      react/src/components/dashboard/settings.js
  11. 10
      react/src/components/dashboard/walletsBasiliskConnection.js
  12. 34
      react/src/components/dashboard/walletsData.js
  13. 22
      react/src/components/dashboard/walletsHeader.js
  14. 18
      react/src/components/dashboard/walletsNativeReceive.js
  15. 22
      react/src/components/dashboard/walletsNativeSend.js
  16. 2
      react/src/components/dashboard/walletsNativeSyncProgress.js
  17. 3
      react/src/components/dashboard/walletsNativeTxHistory.js
  18. 2
      react/src/components/dashboard/walletsNav.js
  19. 8
      react/src/components/dashboard/walletsNotariesList.js
  20. 8
      react/src/components/dashboard/walletsTxInfo.js
  21. 114
      react/src/components/login/login.js
  22. 2
      react/src/components/main/walletMain.js
  23. 20
      react/src/reducers/dashboard.js
  24. 119
      react/src/styles/index.scss
  25. 4
      react/src/translate/en.js

1236
react/src/actions/actionCreators.js

File diff suppressed because it is too large

33
react/src/components/addcoin/addcoin.js

@ -145,15 +145,15 @@ class AddCoin extends React.Component {
_coins[index] = {
selectedCoin: _coins[index].selectedCoin,
fullMode: {
...this.state.fullMode,
disabled: _coins[index].selectedCoin.indexOf('full') > -1 ? false : true,
checked: _value === '1' ? true : false,
},
basiliskMode: {
...this.state.basiliskMode,
disabled: _coins[index].selectedCoin.indexOf('basilisk') > -1 ? false : true,
checked: _value === '0' ? true : false,
},
nativeMode: {
...this.state.nativeMode,
disabled: _coins[index].selectedCoin.indexOf('native') > -1 ? false : true,
checked: _value === '-1' ? true : false,
},
mode: _value,
@ -163,8 +163,12 @@ class AddCoin extends React.Component {
this.setState(Object.assign({}, this.state, {
coins: _coins
}));
}
console.log(this.state.coins);
handleKeydown(e) {
if (e.key === 'Escape') {
this.dismiss();
}
}
activateCoin() {
@ -241,7 +245,7 @@ class AddCoin extends React.Component {
const _coin = _item.selectedCoin || '';
items.push(
<div className={this.state.coins.length > 1 ? 'multi' : 'single'} key={'add-coin-' + i}>
<div className={ this.state.coins.length > 1 ? 'multi' : 'single' } key={ 'add-coin-' + i }>
<div className="col-sm-8">
<div className="form-group">
<select
@ -249,7 +253,8 @@ class AddCoin extends React.Component {
name="selectedCoin"
id="addcoin_select_coin_mdl_options-login"
value={ _coin }
onChange={ (event) => this.updateSelectedCoin(event, i) }>
onChange={ (event) => this.updateSelectedCoin(event, i) }
autoFocus>
<option>{ translate('INDEX.SELECT') }</option>
<AddCoinOptionsCrypto />
<AddCoinOptionsAC />
@ -355,13 +360,15 @@ class AddCoin extends React.Component {
</button>
</div>
<div className={ _item.mode === '1' || _item.mode === 1 ? 'col-sm-12' : 'hide' }>
<div className="pull-left margin-right-10">
<input type="checkbox" id="addcoin_sync_only" checked={ _item.syncOnly } />
<div className="toggle-box padding-top-3 padding-bottom-10">
<span className="pointer">
<label className="switch">
<input type="checkbox" checked={ _item.syncOnly } />
<div className="slider" onClick={ () => this.toggleSyncOnlyMode(i) }></div>
</label>
<div className="toggle-label" onClick={ () => this.toggleSyncOnlyMode(i) }>{ translate('ADD_COIN.SYNC_ONLY') }</div>
</span>
</div>
<label
className="padding-top-3 padding-bottom-10"
htmlFor="addcoin_sync_only"
onClick={ () => this.toggleSyncOnlyMode(i) }>{ translate('ADD_COIN.SYNC_ONLY') }</label>
</div>
</div>
);
@ -372,7 +379,7 @@ class AddCoin extends React.Component {
render() {
return (
<div>
<div onKeyDown={ (event) => this.handleKeydown(event) }>
<div
className={ 'modal modal-3d-sign add-coin-modal ' + this.state.modalClassName }
id="AddCoinDilogModel-login"

2
react/src/components/dashboard/about.js

@ -3,7 +3,7 @@ import { translate } from '../../translate/translate';
class About extends React.Component {
render() {
return(
return (
<div className="page" style={{ marginLeft: '0' }}>
<div className="page-content" id="section-about-iguana">
<h2>About Iguana</h2>

2
react/src/components/dashboard/coinTileItem.js

@ -137,7 +137,7 @@ class CoinTileItem extends React.Component {
const { item } = this.props;
return (
<div className="list-group-item col-xlg-6 col-lg-12 wallet-widgets-info">
<div className="list-group-item col-xlg-6 col-lg-12 wallet-widgets-info pointer">
<div className={ this.props.ActiveCoin.coin === item.coin ? 'widget widget-shadow active' : 'widget widget-shadow' }>
<div
className="widget-content text-center bg-white padding-20 edexcoin-logo"

1
react/src/components/dashboard/dashboard.js

@ -3,7 +3,6 @@ import Navbar from './navbar';
import CoinTile from './coinTile';
import EDEX from './edex';
import WalletsBalance from './walletsBalance';
import WalletsHeader from './walletsHeader';
import WalletsProgress from './walletsProgress';
import WalletsNav from './walletsNav';
import SendCoin from './sendCoin';

4
react/src/components/dashboard/jumblr.js

@ -1,5 +1,6 @@
import React from 'react';
import { translate } from '../../translate/translate';
import WalletsHeader from './walletsHeader';
/*import { dashboardChangeSection, toggleAddcoinModal, logout } from '../../actions/actionCreators';
import Store from '../../store';*/
@ -31,7 +32,8 @@ class Jumblr extends React.Component {
render() {
return (
<div className="page" style={{ marginLeft: '0' }}>
<div className="page-content" id="section-jumblr">
<WalletsHeader activeSection="jumblr" />
<div className="page-content" id="section-jumblr" style={{ marginTop: '30px' }}>
<div className="row" id="jumblr_dashboard">
<div className="col-xs-12" id="jumblr_testing_alert">
<div className="alert alert-danger" role="alert">

29
react/src/components/dashboard/navbar.js

@ -4,7 +4,10 @@ import {
dashboardChangeSection,
toggleAddcoinModal,
logout,
stopInterval
stopInterval,
toggleSyncOnlyModal,
startInterval,
getSyncOnlyForks
} from '../../actions/actionCreators';
import Store from '../../store';
@ -38,6 +41,17 @@ class Navbar extends React.Component {
Store.dispatch(logout());
}
openSyncOnlyModal() {
Store.dispatch(getSyncOnlyForks());
var _iguanaActiveHandle = setInterval(function() {
Store.dispatch(getSyncOnlyForks());
}.bind(this), 3000);
Store.dispatch(startInterval('syncOnly', _iguanaActiveHandle));
Store.dispatch(toggleSyncOnlyModal(true));
}
render() {
return (
<nav className="site-navbar navbar navbar-default navbar-fixed-top navbar-mega" role="navigation">
@ -85,7 +99,8 @@ class Navbar extends React.Component {
<i className="site-menu-icon" aria-hidden="true"></i> EasyDEX
</a>
</li>
<li className={ this.props.Dashboard.activeSection === 'jumblr' ? 'active nav-top-menu' : 'nav-top-menu' } style={{ display: 'none' }}>
<li
className={ this.props.Dashboard.activeSection === 'jumblr' ? 'active nav-top-menu' : 'nav-top-menu' }>
<a id="nav-jumblr" onClick={ () => this.dashboardChangeSection('jumblr') }>
<i className="site-menu-icon" aria-hidden="true"></i> Jumblr
</a>
@ -95,6 +110,11 @@ class Navbar extends React.Component {
<i className="site-menu-icon" aria-hidden="true"></i> Atomic Explorer
</a>
</li>
<li className="nav-top-menu">
<a id="nav-iguana-atomic-explorer" onClick={ () => this.openSyncOnlyModal() }>
<i className="site-menu-icon" aria-hidden="true"></i> { translate('ADD_COIN.SYNC_ONLY') }
</a>
</li>
</ul>
<ul className="nav navbar-toolbar navbar-right navbar-toolbar-right">
<li role="presentation">
@ -102,13 +122,16 @@ class Navbar extends React.Component {
role="menuitem"
id="btn_edexcoin_addcoin"
style={{ paddingBottom: '10px', paddingTop: '16px' }}
className="pointer"
onClick={ this.toggleAddCoinModal }>
<span>
<img src="assets/images/icons/activatecoin.png" alt={ translate('INDEX.ADD_COIN') } />
</span>
</a>
</li>
<li className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') } onClick={ this.openDropMenu }>
<li
className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }>
<a className="navbar-avatar dropdown-toggle" aria-expanded="false" role="button">
<span className="avatar avatar-online">
<img src="assets/images/iguana_profile_02.jpg" alt="iguana profile pic" />

63
react/src/components/dashboard/notifications.js

@ -0,0 +1,63 @@
import React from 'react';
import { translate } from '../../translate/translate';
class Notifications extends React.Component {
constructor(props) {
super(props);
this.state = {
displayModal: false,
totalCalls: 0,
totalErrorCalls: 0,
totalSuccessCalls: 0,
totalPendingCalls: 0,
};
this.toggleNotificationsModal = this.toggleNotificationsModal.bind(this);
}
componentWillReceiveProps(props) {
// get total number of calls per type
if (this.props.Dashboard &&
this.props.Dashboard.guiLog) {
const _guiLog = this.props.Dashboard.guiLog;
let totalCalls = Object.keys(_guiLog).length;
let totalErrorCalls = 0;
let totalSuccessCalls = 0;
let totalPendingCalls = 0;
for (let timestamp in _guiLog) {
if (_guiLog[timestamp].status === 'error') {
totalErrorCalls++;
}
if (_guiLog[timestamp].status === 'success') {
totalSuccessCalls++;
}
if (_guiLog[timestamp].status === 'pending') {
totalPendingCalls++;
}
}
this.setState(Object.assign({}, this.state, {
totalCalls,
totalErrorCalls,
totalSuccessCalls,
totalPendingCalls,
}));
}
}
toggleNotificationsModal() {
}
render() {
return (
<div className="notifications-badge" onClick={ this.toggleNotificationsModal }>
<span className="badge success">{ this.state.totalSuccessCalls }</span>
<span className="badge error">{ this.state.totalErrorCalls }</span>
<span className="badge pending">{ this.state.totalPendingCalls }</span>
</div>
);
}
}
export default Notifications;

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

@ -1,4 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Config from '../../config';
import { translate } from '../../translate/translate';
import {
@ -31,6 +32,7 @@ import io from 'socket.io-client';
const socket = io.connect('http://127.0.0.1:' + Config.agamaPort);
// TODO: prevent any cache updates rather than utxo while on send coin form
// fix a bug - total amount is incorrect when switching between steps
class SendCoin extends React.Component {
constructor(props) {
@ -57,9 +59,28 @@ class SendCoin extends React.Component {
this.getOAdress = this.getOAdress.bind(this);
this.toggleSendAPIType = this.toggleSendAPIType.bind(this);
this._fetchNewUTXOData = this._fetchNewUTXOData.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
socket.on('messages', msg => this.updateSocketsData(msg));
}
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false);
}
handleClickOutside(e) {
if (e.srcElement.className !== 'btn dropdown-toggle btn-info' &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className !== 'btn dropdown-toggle btn-info') &&
(e.path && e.path[4] && e.path[4].className.indexOf('showkmdwalletaddrs') === -1)) {
this.setState({
addressSelectorOpen: false,
});
}
}
componentWillReceiveProps(props) {
if (!this.state.sendFrom && this.props.ActiveCoin.activeAddress) {
this.setState(Object.assign({}, this.state, {
@ -270,7 +291,7 @@ class SendCoin extends React.Component {
renderAddressList() {
return (
<div className={ 'btn-group bootstrap-select form-control form-material showkmdwalletaddrs show-tick ' + (this.state.addressSelectorOpen ? 'open' : '') }>
<div id="showkmdwalletaddrs" className={ 'btn-group bootstrap-select form-control form-material showkmdwalletaddrs show-tick ' + (this.state.addressSelectorOpen ? 'open' : '') }>
<button
type="button"
className="btn dropdown-toggle btn-info"
@ -733,13 +754,13 @@ class SendCoin extends React.Component {
return (
<div className="row">
<div className="col-lg-10 margin-bottom-10">
<div className="pull-left margin-right-10">
<input type="checkbox" id="edexcoin_send_api_type" />
</div>
<label
className="padding-top-3"
htmlFor="edexcoin_send_api_type"
onClick={ this.toggleSendAPIType }>{ translate('SEND.SEND_VIA') } sendtoaddress API</label>
<span className="pointer">
<label className="switch">
<input type="checkbox" checked={ this.state.sendApiType } />
<div className="slider" onClick={ this.toggleSendAPIType }></div>
</label>
<div className="toggle-label" onClick={ this.toggleSendAPIType }>{ translate('SEND.SEND_VIA') } sendtoaddress API</div>
</span>
</div>
</div>
);
@ -846,16 +867,16 @@ class SendCoin extends React.Component {
<strong>{ translate('INDEX.TOTAL') } ({ translate('INDEX.AMOUNT_SM') } - txfee):</strong> <span id="edexcoin_total_value">{ Number(this.state.amount) - Number(this.state.fee) }</span> { this.props.ActiveCoin.coin }
</span>
</div>
<div className="col-lg-10 margin-top-10">
<div className="pull-left margin-right-10">
<input type="checkbox" id="edexcoin_send_sig" />
</div>
<label
className="padding-top-3"
htmlFor="edexcoin_send_sig"
onClick={ this.toggleSendSig }>{ translate('INDEX.DONT_SEND') }</label>
<div className="col-lg-10 margin-top-30">
<span className="pointer">
<label className="switch">
<input type="checkbox" checked={ this.state.sendSig } />
<div className="slider" onClick={ this.toggleSendSig }></div>
</label>
<div className="toggle-label" onClick={ this.toggleSendSig }>{ translate('INDEX.DONT_SEND') }</div>
</span>
</div>
{ this.renderUTXOCacheInfo()}
{ this.renderUTXOCacheInfo()}
<div className="col-lg-12">
<button
type="button"
@ -919,7 +940,7 @@ class SendCoin extends React.Component {
<div className="panel-heading">
<h4 className="panel-title">{ translate('INDEX.TRANSACTION_RESULT') }</h4>
<div className={ !this.state.sendSig ? 'hide' : 'center' }>
{ translate('INDEX.YOU_PICKED_OPT') } "{ translate('INDEX.DONT_SEND') }"
{ translate('SEND.YOU_PICKED_OPT') }
</div>
<table
className="table table-hover table-striped edexcoin_sendto_result"

5
react/src/components/dashboard/settings.js

@ -129,6 +129,9 @@ class Settings extends React.Component {
<div>
{ translate('SETTINGS.VERSION') }: { this.props.Settings.appInfo.releaseInfo.version }
</div>
<div>
{ translate('SETTINGS.APP_SESSION') }: { this.props.Settings.appInfo.appSession }
</div>
</div>
</div>
<div className="col-sm-12" style={{ paddingTop: '20px' }}>
@ -305,7 +308,7 @@ class Settings extends React.Component {
render() {
return (
<div style={{marginLeft: '0'}}>
<div style={{ marginLeft: '0' }}>
<div className="page-content" id="section-iguana-wallet-settings">
<div className="row" id="iguana-wallet-settings">
<div className="col-xlg-12 col-md-12">

10
react/src/components/dashboard/walletsBasiliskConnection.js

@ -13,11 +13,17 @@ class WalletsBasiliskConnection extends React.Component {
Store.dispatch(basiliskConnection(false));
}
handleKeydown(e) {
if (e.key === 'Escape') {
this.basiliskConnectionAction();
}
}
render() {
if (this.props &&
this.props.Dashboard.basiliskConnection) {
return (
<div>
<div onKeyDown={ (event) => this.handleKeydown(event) }>
<div className="modal show" id="RefreshBasiliskConnectionsMdl" aria-hidden="false" role="dialog">
<div className="modal-dialog modal-center modal-md">
<div className="modal-content">
@ -75,7 +81,7 @@ class WalletsBasiliskConnection extends React.Component {
<div className="progress progress-sm">
<div className="progress-bar progress-bar-info progress-bar-striped active" style={{ width: Math.floor(this.props.Dashboard.connectedNotaries.current * 100 / this.props.Dashboard.connectedNotaries.total) + '%', fontSize: '80%' }} role="progressbar" id="basilisk-connections-refresh-progress-bar"></div>
</div>
<pre id="basilisk-connections-refresh-status-output">
<pre id="basilisk-connections-refresh-status-output" style={{ padding: '0' }}>
{ this.props.Dashboard.connectedNotaries.failedToConnectNodes ? 'Failed: ' + this.props.Dashboard.connectedNotaries.failedToConnectNodes : null }
</pre>
</div>

34
react/src/components/dashboard/walletsData.js

@ -57,9 +57,31 @@ class WalletsData extends React.Component {
this._fetchUtxoCache = this._fetchUtxoCache.bind(this);
this.restartBasiliskInstance = this.restartBasiliskInstance.bind(this);
this.basiliskRefreshActionOne = this.basiliskRefreshActionOne.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
socket.on('messages', msg => this.updateSocketsData(msg));
}
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false);
}
handleClickOutside(e) {
if (e.srcElement.className !== 'btn dropdown-toggle btn-info' &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className !== 'btn dropdown-toggle btn-info') &&
(e.path && e.path[4] && e.path[4].className.indexOf('showkmdwalletaddrs') === -1) &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className.indexOf('dropdown') === -1) &&
e.srcElement.className !== 'dropdown-toggle btn-xs btn-default') {
this.setState({
addressSelectorOpen: false,
basiliskActionsMenu: false,
});
}
}
componentDidMount() {
console.log('use cache = ', this.state.useCache);
}
@ -377,8 +399,8 @@ class WalletsData extends React.Component {
<td>{ tx.confirmations }</td>
<td>{ tx.amount || translate('DASHBOARD.UNKNOWN') }</td>
<td>{ secondsToString(tx.blocktime || tx.timestamp) }</td>
<td>{ tx.address }</td>
<td>
<td className={ this.props.ActiveCoin.mode === 'basilisk' ? 'hide' : '' }>{ tx.address }</td>
<td className={ this.props.ActiveCoin.mode === 'basilisk' ? 'text-center' : '' }>
<button
type="button"
className="btn btn-xs white btn-info waves-effect waves-light btn-kmdtxid"
@ -684,8 +706,8 @@ class WalletsData extends React.Component {
<th className="hidden-xs hidden-sm">{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th className="hidden-xs hidden-sm">{ translate('INDEX.TX_DETAIL') }</th>
<th className={ this.props.ActiveCoin.mode === 'basilisk' ? 'hide' : '' }>{ translate('INDEX.DEST_ADDRESS') }</th>
<th className={ this.props.ActiveCoin.mode === 'basilisk' ? 'hidden-xs hidden-sm text-center' : 'hidden-xs hidden-sm' }>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
</thead>
<tbody>
@ -697,8 +719,8 @@ class WalletsData extends React.Component {
<th>{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th className="hidden-xs hidden-sm">{ translate('INDEX.TX_DETAIL') }</th>
<th className={ this.props.ActiveCoin.mode === 'basilisk' ? 'hide' : '' }>{ translate('INDEX.DEST_ADDRESS') }</th>
<th className={ this.props.ActiveCoin.mode === 'basilisk' ? 'hidden-xs hidden-sm text-center' : 'hidden-xs hidden-sm' }>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
</tfoot>
</table>

22
react/src/components/dashboard/walletsHeader.js

@ -6,14 +6,20 @@ import { translate } from '../../translate/translate';
class WalletsHeader extends React.Component {
render() {
if (this.props &&
this.props.coin) {
this.props.activeSection) {
return (
<div className="page-header page-header-bordered header-easydex margin-bottom-0" id="easydex-header-div">
<h1 className="page-title">EasyDEX</h1>
<div
className="page-header page-header-bordered header-easydex margin-bottom-0"
id="easydex-header-div"
style={{ backgroundImage: 'url("assets/images/bg/' + this.props.activeSection + '_transparent_header_bg.png")', backgroundRepeat: 'no-repeat', backgroundPosition: '0%' }}>
<h1 className={ this.props.activeSection === 'jumblr' ? 'hide' : 'page-title' }>EasyDEX</h1>
<ol className="breadcrumb">
<li className="header-easydex-section">{ translate('INDEX.DASHBOARD') }</li>
<li className={ this.props.activeSection === 'jumblr' ? 'hide' : 'header-easydex-section' }>{ translate('INDEX.DASHBOARD') }</li>
<li className={ this.props.activeSection !== 'jumblr' ? 'hide' : 'header-easydex-section' }>
<img src="assets/images/native/jumblr_header_title_logo.png" /><br /> { translate('SIDEBAR.JUMBLR_MOTTO') }
</li>
</ol>
<div className="page-header-actions" style={{ zIndex: '1' }}>
<div className="page-header-actions" style={{ zIndex: '1', display: 'none' }}>
<div id="kmd_header_button">
<button
type="button"
@ -54,7 +60,7 @@ class WalletsHeader extends React.Component {
</ul>
</div>
<div id="zec_header_button">
<div id="zec_header_button" style={{ display: 'none' }}>
<button
type="button"
id="easydex_zec_wallet_actions_header"
@ -107,7 +113,7 @@ class WalletsHeader extends React.Component {
</button>
</div>
<div id="kmd_header_button">
<div id="kmd_header_button" style={{ display: 'none' }}>
<button
type="button"
id="easydex_acpax_wallet_actions_header"
@ -151,7 +157,7 @@ class WalletsHeader extends React.Component {
</ul>
</div>
<div className="row no-space width-350 hidden-xs" id="easydex_btc_btcd_balances_header">
<div className="row no-space width-350 hidden-xs" id="easydex_btc_btcd_balances_header" style={{ display: 'none' }}>
<div className="col-xs-6">
<div className="counter">
<span className="font-weight-medium" id="header_coinname_balance"> - BTC</span>

18
react/src/components/dashboard/walletsNativeReceive.js

@ -16,6 +16,24 @@ class WalletsNativeReceive extends React.Component {
openDropMenu: false,
};
this.openDropMenu = this.openDropMenu.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false);
}
handleClickOutside(e) {
if (e.srcElement.className.indexOf('dropdown') === -1 &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className.indexOf('dropdown') === -1)) {
this.setState({
openDropMenu: false,
});
}
}
openDropMenu() {

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

@ -27,6 +27,25 @@ class WalletsNativeSend extends React.Component {
this.handleSubmit = this.handleSubmit.bind(this);
this.openDropMenu = this.openDropMenu.bind(this);
this.getOAdress = this.getOAdress.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentWillMount() {
document.addEventListener('click', this.handleClickOutside, false);
}
componentWillUnmount() {
document.removeEventListener('click', this.handleClickOutside, false);
}
handleClickOutside(e) {
if (e.srcElement.className !== 'btn dropdown-toggle btn-info' &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className !== 'btn dropdown-toggle btn-info') &&
(e.path && e.path[4] && e.path[4].className.indexOf('showkmdwalletaddrs') === -1)) {
this.setState({
addressSelectorOpen: false,
});
}
}
renderAddressByType(type) {
@ -208,7 +227,8 @@ class WalletsNativeSend extends React.Component {
.then(function(json) {
const reply = json.Answer;
if (reply && reply.length) {
if (reply &&
reply.length) {
for (let i = 0; i < reply.length; i++) {
const _address = reply[i].data.split(' ');
const coin = _address[0].replace('"oa1:', '');

2
react/src/components/dashboard/walletsNativeSyncProgress.js

@ -29,7 +29,7 @@ class WalletsNativeSyncProgress extends React.Component {
</div>
);
} else {
var syncPercentage = (parseFloat(parseInt(this.props.Dashboard.progress.blocks, 10) * 100 / parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2) + '%').replace('NaN', 0);
const syncPercentage = (parseFloat(parseInt(this.props.Dashboard.progress.blocks, 10) * 100 / parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2) + '%').replace('NaN', 0);
return (
<div

3
react/src/components/dashboard/walletsNativeTxHistory.js

@ -26,7 +26,8 @@ class WalletsNativeTxHistory extends React.Component {
}
isFullySynced() {
if (this.props.Dashboard.progress &&
if (this.props.Dashboard &&
this.props.Dashboard.progress &&
this.props.Dashboard.progress.balances &&
(Number(this.props.Dashboard.progress.balances) +
Number(this.props.Dashboard.progress.validated) +

2
react/src/components/dashboard/walletsNav.js

@ -83,7 +83,7 @@ class WalletsNav extends React.Component {
className="btn btn-dark waves-effect waves-light"
id="btn_edexcoin_dashboard"
onClick={ this.toggleSendReceiveCoinForms }>
<i className="icon md-view-dashboard" aria-hidden="true"></i> { this.props.ActiveCoin.mode !== 'native' ? translate('INDEX.DASHBOARD') : 'Settings' }
<i className="icon md-view-dashboard" aria-hidden="true"></i> { this.props.ActiveCoin.mode !== 'native' ? translate('INDEX.DASHBOARD') : translate('INDEX.WALLET_INFO') }
</button>
<button
type="button"

8
react/src/components/dashboard/walletsNotariesList.js

@ -15,6 +15,12 @@ class WalletsNotariesList extends React.Component {
Store.dispatch(displayNotariesModal(false));
}
handleKeydown(e) {
if (e.key === 'Escape') {
this.closeNotariesModal();
}
}
renderNotariesFetching() {
if (!this.props.ActiveCoin.notaries) {
return (
@ -50,7 +56,7 @@ class WalletsNotariesList extends React.Component {
const notariesData = this.props.ActiveCoin.notaries ? this.props.ActiveCoin.notaries.notaries : null;
return (
<div>
<div onKeyDown={ (event) => this.handleKeydown(event) }>
<div className="modal show" id="kmd_txid_info_mdl" aria-hidden="false" role="dialog">
<div className="modal-dialog modal-center modal-lg">
<div className="modal-content">

8
react/src/components/dashboard/walletsTxInfo.js

@ -23,6 +23,12 @@ class WalletsTxInfo extends React.Component {
}));
}
handleKeydown(e) {
if (e.key === 'Escape') {
this.toggleTxInfoModal();
}
}
render() {
if (this.props &&
this.props.ActiveCoin.showTransactionInfo &&
@ -30,7 +36,7 @@ class WalletsTxInfo extends React.Component {
const txInfo = this.props.ActiveCoin.txhistory[this.props.ActiveCoin.showTransactionInfoTxIndex];
return (
<div>
<div onKeyDown={ (event) => this.handleKeydown(event) }>
<div className="modal show" id="kmd_txid_info_mdl" aria-hidden="false" role="dialog">
<div className="modal-dialog modal-center modal-lg">
<div className="modal-content">

114
react/src/components/login/login.js

@ -226,73 +226,125 @@ class Login extends React.Component {
className="form-control"
name="loginPassphrase"
id="password"
onChange={this.updateInput}
onKeyDown={(event) => this.handleKeydown(event)} />
<i className={this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye'} onClick={this.toggleSeedInputVisibility}></i>
<label className="floating-label" htmlFor="inputPassword">{translate('INDEX.WALLET_SEED')}</label>
onChange={ this.updateInput }
onKeyDown={ (event) => this.handleKeydown(event) } />
<i
className={ this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i>
<label className="floating-label" htmlFor="inputPassword">{ translate('INDEX.WALLET_SEED') }</label>
</div>
<button type="button" className="btn btn-primary btn-block" id="loginbtn" onClick={this.loginSeed} disabled={!this.state.loginPassphrase || !this.state.loginPassphrase.length}>{translate('INDEX.SIGN_IN')}</button>
<button
type="button"
className="btn btn-primary btn-block"
id="loginbtn"
onClick={ this.loginSeed }
disabled={ !this.state.loginPassphrase || !this.state.loginPassphrase.length }>{ translate('INDEX.SIGN_IN') }</button>
<div className="form-group form-material floating">
<button className="btn btn-lg btn-flat btn-block waves-effect" id="register-btn" onClick={() => this.updateActiveLoginSection('signup')}>{translate('INDEX.CREATE_WALLET')}</button>
<button className="btn btn-lg btn-flat btn-block waves-effect hide" id="logint-another-wallet">{translate('INDEX.LOGIN_ANOTHER_WALLET')}</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect"
id="register-btn"
onClick={ () => this.updateActiveLoginSection('signup') }>{ translate('INDEX.CREATE_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect hide"
id="logint-another-wallet">{ translate('INDEX.LOGIN_ANOTHER_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect"
id="register-btn"
role="menuitem"
onClick={this.toggleActivateCoinForm}
disabled={!this.props.Main}
style={{marginTop: '20px'}}>
<span className="ladda-label">{translate('ADD_COIN.ADD_ANOTHER_COIN')}</span>
onClick={ this.toggleActivateCoinForm }
disabled={ !this.props.Main }
style={{ marginTop: '20px' }}>
<span className="ladda-label">{ translate('ADD_COIN.ADD_ANOTHER_COIN') }</span>
</button>
</div>
</div>
</div>
<div id="section-login-addcoin-btn" className={this.state.activeLoginSection === 'activateCoin' ? 'show' : 'hide'}>
<h4 style={{ color: '#fff' }} id="login-welcome">{translate('INDEX.WELCOME_PLEASE_ADD')}</h4>
<div className="form-group form-material floating" style={{width: '540px', margin: '30px 0'}}>
<div
id="section-login-addcoin-btn"
className={ this.state.activeLoginSection === 'activateCoin' ? 'show' : 'hide' }>
<h4 style={{ color: '#fff' }} id="login-welcome">{ translate('INDEX.WELCOME_PLEASE_ADD') }</h4>
<div
className="form-group form-material floating"
style={{ width: '540px', margin: '30px 0' }}>
<button
className="btn btn-lg btn-primary btn-block ladda-button"
id="start-coin-login"
role="menuitem"
onClick={this.toggleActivateCoinForm}
disabled={!this.props.Main}>
<span className="ladda-label">{translate('INDEX.ACTIVATE_COIN')}</span>
onClick={ this.toggleActivateCoinForm }
disabled={ !this.props.Main }>
<span className="ladda-label">{ translate('INDEX.ACTIVATE_COIN') }</span>
</button>
</div>
</div>
<div id="section-register" className={this.state.activeLoginSection === 'signup' ? 'show' : 'hide'}>
<div
id="section-register"
className={ this.state.activeLoginSection === 'signup' ? 'show' : 'hide' }>
<div className="register-form">
<h4 className="hint" style={{ color: '#fff' }}>
{ translate('INDEX.SELECT_SEED_TYPE') }:
</h4>
<div className="form-group form-material floating">
<div className="radio-custom radio-default radio-inline" onClick={() => this.generateNewSeed(256)}>
<input type="radio" name="PassPhraseOptions" checked={this.state.bitsOption === 256 ? true : false} />
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(256) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 256 ? true : false } />
<label htmlFor="PassPhraseOptionsIguana">Iguana (256 bits)</label>
</div>
<div className="radio-custom radio-default radio-inline" onClick={() => this.generateNewSeed(160)}>
<input type="radio" name="PassPhraseOptions" checked={this.state.bitsOption === 160 ? true : false} />
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(160) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 160 ? true : false } />
<label htmlFor="PassPhraseOptionsWaves">Waves</label>
</div>
<div className="radio-custom radio-default radio-inline" onClick={() => this.generateNewSeed(128)}>
<input type="radio" name="PassPhraseOptions" checked={this.state.bitsOption === 128 ? true : false} />
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(128) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 128 ? true : false } />
<label htmlFor="PassPhraseOptionsNXT">NXT</label>
</div>
</div>
<div className="form-group form-material floating">
<textarea className="form-control placeholder-no-fix" type="text" id="walletseed" style={{ height: '100px' }} value={this.state.randomSeed} readOnly="true"></textarea>
<label className="floating-label" htmlFor="walletseed">{translate('INDEX.WALLET_SEED')}</label>
<textarea
className="form-control placeholder-no-fix"
type="text"
id="walletseed"
style={{ height: '100px' }}
value={ this.state.randomSeed }
readOnly="true"></textarea>
<label className="floating-label" htmlFor="walletseed">{ translate('INDEX.WALLET_SEED') }</label>
</div>
<div className="form-group form-material floating">
<textarea className="form-control placeholder-no-fix" type="text" name="randomSeedConfirm" onChange={this.updateInput} id="rwalletseed" style={{ height: '100px' }}></textarea>
<span className={ this.state.isSeedConfirmError ? 'help-block' : 'hide' }>{translate('LOGIN.ENTER_VALUE_AGAIN')}.</span>
<label className="floating-label" htmlFor="rwalletseed">{translate('INDEX.CONFIRM_SEED')}</label>
<textarea
className="form-control placeholder-no-fix"
type="text"
name="randomSeedConfirm"
onChange={ this.updateInput }
id="rwalletseed"
style={{ height: '100px' }}></textarea>
<span className={ this.state.isSeedConfirmError ? 'help-block' : 'hide' }>{ translate('LOGIN.ENTER_VALUE_AGAIN') }.</span>
<label className="floating-label" htmlFor="rwalletseed">{ translate('INDEX.CONFIRM_SEED') }</label>
</div>
<button type="button" id="register-submit-btn" className="btn btn-primary btn-block" onClick={this.handleRegisterWallet}>{translate('INDEX.REGISTER')}</button>
<button
type="button"
id="register-submit-btn"
className="btn btn-primary btn-block"
onClick={ this.handleRegisterWallet }>{ translate('INDEX.REGISTER') }</button>
<div className="form-group form-material floating">
<button className="btn btn-lg btn-flat btn-block waves-effect" id="register-back-btn" onClick={() => this.updateActiveLoginSection('login')}>{translate('INDEX.BACK_TO_LOGIN')}</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect"
id="register-back-btn"
onClick={ () => this.updateActiveLoginSection('login') }>{ translate('INDEX.BACK_TO_LOGIN') }</button>
</div>
</div>
</div>

2
react/src/components/main/walletMain.js

@ -4,6 +4,7 @@ import AddCoin from '../addcoin/addcoin';
import Login from '../login/login';
import Dashboard from '../dashboard/dashboard';
import SyncOnly from '../dashboard/syncOnly';
import Notifications from '../dashboard/notifications';
class WalletMain extends React.Component {
render() {
@ -14,6 +15,7 @@ class WalletMain extends React.Component {
<AddCoin {...this.props.AddCoin} />
<Login {...this.props} />
<Toaster {...this.props.toaster} />
<Notifications {...this.props} />
</div>
);
}

20
react/src/reducers/dashboard.js

@ -6,7 +6,9 @@ import {
SYNCING_NATIVE_MODE,
BASILISK_CONNECTION,
DASHBOARD_CONNECT_NOTARIES,
VIEW_CACHE_DATA
VIEW_CACHE_DATA,
LOG_GUI_HTTP,
TOGGLE_NOTIFICATIONS_MODAL
} from '../actions/actionCreators';
export function Dashboard(state = {
@ -20,7 +22,8 @@ export function Dashboard(state = {
current: 0,
currentNodeName: null,
failedToConnectNodes: null,
}
},
guiLog: {}
}, action) {
switch (action.type) {
case DASHBOARD_SECTION_CHANGE:
@ -64,6 +67,19 @@ export function Dashboard(state = {
return Object.assign({}, state, {
displayViewCacheModal: action.display,
});
case LOG_GUI_HTTP:
let _guiLogState = state.guiLog;
if (_guiLogState[action.timestamp]) {
_guiLogState[action.timestamp].status = action.log.status;
_guiLogState[action.timestamp].response = action.log.response;
} else {
_guiLogState[action.timestamp] = action.log;
}
return Object.assign({}, state, {
guiLog: _guiLogState,
});
default:
return state;
}

119
react/src/styles/index.scss

@ -292,6 +292,125 @@ body {
}
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 24px;
}
/* Hide default HTML checkbox */
.switch input {
display: none;
}
/* The slider */
.slider {
border-radius: 20px;
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
border-radius: 50%;
position: absolute;
content: "";
height: 20px;
width: 20px;
left: 2px;
bottom: 2px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
.toggle-label {
color: #757575;
display: inline-block;
position: relative;
top: -12px;
left: 8px;
}
input:checked + .slider {
background-color: rgb(57, 73, 171);
}
input:focus + .slider {
box-shadow: 0 0 1px rgb(57, 73, 171);
}
input:checked + .slider:before {
-webkit-transform: translateX(16px);
-ms-transform: translateX(16px);
transform: translateX(16px);
}
.dropdown-menu li {
cursor: pointer;
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.pointer {
cursor: pointer;
}
.text-center {
text-align: center;
}
.breadcrumb>li+li:before {
display: none;
}
.notifications {
}
.notifications-badge {
position: absolute;
bottom: 10px;
left: 5px;
cursor: pointer;
.badge {
margin-left: 2px;
font-weight: bold;
}
.badge.success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}
.badge.pending {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
}
.badge.error {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
}
/*.toaster .single-toast:nth-child(0) {
bottom: 12px;
}

4
react/src/translate/en.js

@ -1,6 +1,7 @@
export const _lang = {
'EN': {
'INDEX': {
'WALLET_INFO': 'Wallet Info',
'ADD_COIN': 'Add Coin',
'STOP': 'Stop',
'START': 'Start',
@ -418,7 +419,8 @@ export const _lang = {
'CONFIG': 'Config',
'BIN': 'Bin',
'DIR': 'Dir',
'ADD_PEER_IP': 'Add Peer IP'
'ADD_PEER_IP': 'Add Peer IP',
'APP_SESSION': 'App Session'
},
'TX_INFO': {
'ADDRESS': 'address',

Loading…
Cancel
Save