You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

572 lines
29 KiB

import React from 'react';
import { translate } from '../../translate/translate';
import {
iguanaActiveHandle,
encryptWallet,
settingsWifkeyState,
importPrivKey,
getDebugLog,
getPeersList,
addPeerNode,
getAppConfig,
saveAppConfig,
getAppInfo
} from '../../actions/actionCreators';
import Store from '../../store';
import AddCoinOptionsCrypto from '../addcoin/addcoinOptionsCrypto';
import AddCoinOptionsAC from '../addcoin/addcoinOptionsAC';
import AddCoinOptionsACFiat from '../addcoin/addcoinOptionsACFiat';
/*
TODO:
1) pre-select active coin in add node tab
2) add agama config section
3) add fiat section
4) kickstart section
*/
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: 0,
debugLinesCount: 10,
debugTarget: 'iguana',
activeTabHeight: '10px',
appSettings: [],
};
this.exportWifKeys = this.exportWifKeys.bind(this);
this.updateInput = this.updateInput.bind(this);
this.importWifKey = this.importWifKey.bind(this);
this.readDebugLog = this.readDebugLog.bind(this);
this.checkNodes = this.checkNodes.bind(this);
this.addNode = this.addNode.bind(this);
this.renderPeersList = this.renderPeersList.bind(this);
this.renderSNPeersList = this.renderSNPeersList.bind(this);
}
componentDidMount() {
Store.dispatch(iguanaActiveHandle());
Store.dispatch(getAppConfig());
Store.dispatch(getAppInfo());
}
_saveAppConfig() {
Store.dispatch(saveAppConfig);
}
openTab(elemId, tab) {
const _height = document.querySelector('#' + elemId + ' .panel-collapse .panel-body').clientHeight;
this.setState(Object.assign({}, this.state, {
activeTab: tab,
activeTabHeight: _height,
}));
}
exportWifKeys() {
Store.dispatch(encryptWallet(this.state.wifkeysPassphrase, settingsWifkeyState, this.props.ActiveCoin.coin));
}
importWifKey() {
Store.dispatch(importPrivKey(this.state.importWifKey));
}
readDebugLog() {
Store.dispatch(getDebugLog(this.state.debugTarget, this.state.debugLinesCount));
}
checkNodes() {
if (this.state.getPeersCoin) {
Store.dispatch(getPeersList(this.state.getPeersCoin.split('|')[0]));
}
}
addNode() {
if (this.state.addNodeCoin) {
Store.dispatch(addPeerNode(this.state.addNodeCoin.split('|')[0], this.state.addPeerIP));
}
}
renderPeersList() {
if (this.state.getPeersCoin) {
const coin = this.state.getPeersCoin.split('|')[0];
if (this.props.Settings.rawPeers &&
this.state.getPeersCoin &&
this.props.Settings.rawPeers[coin]) {
return this.props.Settings.rawPeers[coin].map((ip) => <div key={ip}>{ip}</div>);
} else {
return null;
}
} else {
return null;
}
}
renderAppInfoTab() {
const releaseInfo = this.props.Settings.appInfo && this.props.Settings.appInfo.releaseInfo;
if (releaseInfo) {
return (
<div className="panel" id="AppInfo">
<div className="panel-heading" role="tab" onClick={() => this.openTab('AppInfo', 8)}>
<a className={this.state.activeTab === 8 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#AppInfoAccordion">
<i className="icon md-info" aria-hidden="true"></i>App Info
</a>
</div>
<div className={this.state.activeTab === 8 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 8 ? this.state.activeTabHeight + 'px' : '10px'}} aria-labelledby="DebugLog" role="tabpanel">
<div className="panel-body">
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<div className="row">
<h5>App Release</h5>
<div>
Name: {this.props.Settings.appInfo.releaseInfo.name}
</div>
<div>
Version: {this.props.Settings.appInfo.releaseInfo.version}
</div>
</div>
</div>
<div className="col-sm-12" style={{paddingTop: '20px'}}>
<div className="row">
<h5>System Info</h5>
<div>
Architecture: {this.props.Settings.appInfo.sysInfo.arch}
</div>
<div>
OS Type: {this.props.Settings.appInfo.sysInfo.os_type}
</div>
<div>
OS Platfrom: {this.props.Settings.appInfo.sysInfo.platform}
</div>
<div>
OS Release: {this.props.Settings.appInfo.sysInfo.os_release}
</div>
<div>
CPU: {this.props.Settings.appInfo.sysInfo.cpu}
</div>
<div>
CPU Cores: {this.props.Settings.appInfo.sysInfo.cpu_cores}
</div>
<div>
Memory: {this.props.Settings.appInfo.sysInfo.totalmem_readable}
</div>
</div>
</div>
<div className="col-sm-12" style={{paddingTop: '20px'}}>
<div className="row">
<h5>Locations</h5>
<div>
Cache: {this.props.Settings.appInfo.dirs.cacheLocation}
</div>
<div>
Config: {this.props.Settings.appInfo.dirs.configLocation}
</div>
<div>
Iguana Bin: {this.props.Settings.appInfo.dirs.iguanaBin}
</div>
<div>
Iguana Dir: {this.props.Settings.appInfo.dirs.iguanaDir}
</div>
<div>
Komodo Bin: {this.props.Settings.appInfo.dirs.komododBin}
</div>
<div>
Komodo Dir: {this.props.Settings.appInfo.dirs.komodoDir}
</div>
</div>
</div>
</div>
</div>
</div>
);
} else {
return null;
}
}
renderSNPeersList() {
if (this.state.getPeersCoin) {
const coin = this.state.getPeersCoin.split('|')[0];
if (this.props.Settings.supernetPeers &&
this.state.getPeersCoin &&
this.props.Settings.supernetPeers[coin]) {
return this.props.Settings.supernetPeers[coin].map((ip) => <div key={ip}>{ip}</div>);
} else {
return null;
}
} else {
return null;
}
}
renderConfigEditForm() {
console.log(this.props.Settings.appSettings);
let items = [];
const _appConfig = this.props.Settings.appSettings;
for (let key in this.props.Settings.appSettings) {
if (Object.keys(this.props.Settings.appSettings[key]).length && key !== 'host') {
items.push(
<tr key={`app-settings-${key}`}>
<td style={{padding: '15px'}}>
{key}
</td>
<td style={{padding: '15px'}}></td>
</tr>
);
for (let _key in this.props.Settings.appSettings[key]) {
items.push(
<tr key={`app-settings-${key}-${_key}`}>
<td style={{padding: '15px', paddingLeft: '30px'}}>
{_key}
</td>
<td style={{padding: '15px'}}>
<input type="text" name={`app-settings-${_key}-edit`} defaultValue={_appConfig[key][_key]} />
</td>
</tr>
);
}
} else {
items.push(
<tr key={`app-settings-${key}`}>
<td style={{padding: '15px'}}>
{key}
</td>
<td style={{padding: '15px'}}>
<input type="text" name={`app-settings-${key}-edit`} defaultValue={_appConfig[key]} />
</td>
</tr>
);
}
}
return items;
}
updateInput(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
render() {
return (
<div data-animsition-in="fade-in" data-animsition-out="fade-out" style={{marginLeft: '0'}}>
<div className="page-content" id="section-iguana-wallet-settings">
<div className="row" id="iguana-wallet-settings" data-plugin="masonry">
<div className="col-xlg-12 col-md-12">
<div className="row" id="iguana-wallet-settings" data-plugin="masonry">
<div className="col-xlg-12 col-md-12">
<h4 className="font-size-14 text-uppercase">{translate('INDEX.WALLET_SETTINGS')}</h4>
<div className="panel-group" id="SettingsAccordion" aria-multiselectable="true" role="tablist">
<div className="panel" id="WalletInfo">
<div className="panel-heading" role="tab" onClick={() => this.openTab('WalletInfo', 0)}>
<a className={this.state.activeTab === 0 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon md-balance-wallet" aria-hidden="true"></i>{translate('INDEX.WALLET_INFO')}
</a>
</div>
<div className={this.state.activeTab === 0 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 0 ? this.state.activeTabHeight + 'px' : '10px'}} id="WalletInfoTab" aria-labelledby="WalletInfo" role="tabpanel">
<div className="panel-body">
<table className="table" id="wallet-info-table">
<thead>
<tr>
<th width="10%">{translate('INDEX.KEY')}</th>
<th>{translate('INDEX.VALUE')}</th>
</tr>
</thead>
<tbody>
<tr>
<td style={{fontWeight: 'bold'}}>pubkey</td>
<td>
<div id="winfo_pubkey_value">{this.props.Main.activeHandle.pubkey}</div>
</td>
</tr>
<tr>
<td style={{fontWeight: 'bold'}}>btcpubkey</td>
<td>
<div id="winfo_btcpubkey_value">{this.props.Main.activeHandle.btcpubkey}</div>
</td>
</tr>
<tr>
<td style={{fontWeight: 'bold'}}>rmd160</td>
<td>
<div id="winfo_rmd160_value">{this.props.Main.activeHandle.rmd160}</div>
</td>
</tr>
<tr>
<td style={{fontWeight: 'bold'}}>NXT</td>
<td>
<div id="winfo_NXT_value">{this.props.Main.activeHandle.NXT}</div>
</td>
</tr>
<tr>
<td style={{fontWeight: 'bold'}}>notary</td>
<td>
<div id="winfo_notary_value">{this.props.Main.activeHandle.notary}</div>
</td>
</tr>
<tr>
<td style={{fontWeight: 'bold'}}>status</td>
<td>
<div id="winfo_status_value">{this.props.Main.activeHandle.status}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="panel" id="AddNodeforCoin">
<div className="panel-heading" role="tab" onClick={() => this.openTab('AddNodeforCoin', 1)}>
<a className={this.state.activeTab === 1 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon md-plus-square" aria-hidden="true"></i>{translate('INDEX.ADD_NODE')}
</a>
</div>
<div className={this.state.activeTab === 1 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 1 ? this.state.activeTabHeight + 'px' : '10px'}} id="AddNodeforCoinTab" aria-labelledby="AddNodeforCoin" role="tabpanel">
<div className="panel-body">
<div className="row">
<div className="col-sm-6">
<div className="col-sm-12">
<p>{translate('INDEX.USE_THIS_SECTION')}</p>
</div>
<div className="col-sm-8 col-xs-12">
<div className="form-group">
<select className="form-control form-material" id="settings_select_coin_options" name="getPeersCoin" onChange={this.updateInput}>
<option>{translate('INDEX.SELECT_COIN')}</option>
<AddCoinOptionsCrypto />
<AddCoinOptionsAC />
<AddCoinOptionsACFiat />
</select>
</div>
</div>
<div className="col-sm-4 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="settings_getcoinpeers_btn" onClick={this.checkNodes}>{translate('INDEX.CHECK_NODES')}</button>
</div>
<div className="col-sm-12">
<h5>
SuperNET Peers: <span id="coin_supernetpeers_h"></span>
</h5>
<p id="coin_supernetpeers">{this.renderSNPeersList()}</p>
<h5>
Raw Peers: <span id="coin_rawpeers_h"></span>
</h5>
<p id="coin_rawpeers">{this.renderPeersList()}</p>
</div>
</div>
<div className="col-sm-6">
<div className="col-sm-12">
<p>{translate('INDEX.USE_THIS_SECTION_PEER')}</p>
</div>
<div className="col-sm-8 col-xs-12">
<div className="form-group">
<select className="form-control form-material" id="settings_select_coin_addpeer_options" name="addNodeCoin" onChange={this.updateInput}>
<option>{translate('INDEX.SELECT_COIN')}</option>
<AddCoinOptionsCrypto />
<AddCoinOptionsAC />
<AddCoinOptionsACFiat />
</select>
</div>
<div className="form-group">
<input type="text" className="form-control" id="settings_add_peer_ip" name="addPeerIP" placeholder="Add Peer IP" onChange={this.updateInput} />
</div>
</div>
<div className="col-sm-4 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="settings_addcoinpeers_btn" onClick={this.addNode}>{translate('INDEX.ADD_NODE')}</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="panel" id="DumpWallet">
<div className="panel-heading" role="tab" onClick={() => this.openTab('DumpWallet', 2)}>
<a className={this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon wb-briefcase" aria-hidden="true"></i>{translate('INDEX.WALLET_BACKUP')}
</a>
</div>
<div className={this.state.activeTab === 2 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 2 ? this.state.activeTabHeight + 'px' : '10px'}} id="DumpWalletTab" aria-labelledby="DumpWallet" role="tabpanel">
<div className="panel-body">Wallet Backup section to be updated soon.</div>
</div>
</div>
<div className="panel" id="FiatCurrencySettings">
<div className="panel-heading" role="tab" onClick={() => this.openTab('FiatCurrencySettings', 3)}>
<a className={this.state.activeTab === 3 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon fa-money" aria-hidden="true"></i>{translate('INDEX.FIAT_CURRENCY')}
</a>
</div>
<div className={this.state.activeTab === 3 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 3 ? this.state.activeTabHeight + 'px' : '10px'}} id="FiatCurrencySettingsTab" aria-labelledby="FiatCurrencySettings" role="tabpanel">
<div className="panel-body">Fiat currency settings section to be updated soon.</div>
</div>
</div>
<div className="panel" id="ExportKeys">
<div className="panel-heading" role="tab" onClick={() => this.openTab('ExportKeys', 4)}>
<a className={this.state.activeTab === 4 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon md-key" aria-hidden="true"></i>{translate('INDEX.EXPORT_KEYS')}
</a>
</div>
<div className={this.state.activeTab === 4 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 4 ? this.state.activeTabHeight + 'px' : '10px'}} id="ExportKeysTab" aria-labelledby="ExportKeys" role="tabpanel">
<div className="panel-body">
<p>
<div>{translate('INDEX.ONLY_ACTIVE_WIF_KEYS')}</div><br/>
<b>
<i>{translate('INDEX.PLEASE_KEEP_KEYS_SAFE')}</i>
</b>
</p>
<div className="col-sm-12"></div>
<form className="wifkeys-form" method="post" action="javascript:" autoComplete="off">
<div className="form-group form-material floating">
<input type="password" className="form-control" name="wifkeysPassphrase" id="wifkeys_passphrase" onChange={this.updateInput} />
<label className="floating-label" htmlFor="wifkeys_passphrase">{translate('INDEX.PASSPHRASE')}</label>
</div>
<div className="col-sm-12 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="wifkeys_passphrase_btn" onClick={this.exportWifKeys}>{translate('INDEX.GET_WIF_KEYS')}</button>
</div>
</form>
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<div className="row" id="wif-priv-keys" data-plugin="masonry">
<table className={this.props.Settings && this.props.Settings.address ? 'table show' : 'table hide'}>
<tr>
<td style={{width: '5%'}}>
<b>{this.props.ActiveCoin.coin}</b>
</td>
<td>{this.props.Settings.address}</td>
</tr>
<tr>
<td>
<b>{this.props.ActiveCoin.coin}Wif</b>
</td>
<td>{this.props.Settings.wifkey}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div className="panel" id="ImportKeys">
<div className="panel-heading" role="tab" onClick={() => this.openTab('ImportKeys', 5)}>
<a className={this.state.activeTab === 5 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse">
<i className="icon md-key" aria-hidden="true"></i>{translate('INDEX.IMPORT_KEYS')}
</a>
</div>
<div className={this.state.activeTab === 5 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 5 ? this.state.activeTabHeight + 'px' : '10px'}} id="ImportKeysTab" aria-labelledby="ImportKeys" role="tabpanel">
<div className="panel-body">
<p>
<div>{translate('INDEX.IMPORT_KEYS_DESC_P1')}</div><br/>
<div>{translate('INDEX.IMPORT_KEYS_DESC_P2')}</div><br/>
<div>{translate('INDEX.IMPORT_KEYS_DESC_P3')}</div><br/>
<b>
<i>{translate('INDEX.PLEASE_KEEP_KEYS_SAFE')}</i>
</b>
</p>
<div className="col-sm-12"></div>
<form className="wifkeys-import-form" method="post" action="javascript:" autoComplete="off">
<div className="form-group form-material floating">
<input type="text" className="form-control" name="importWifKey" id="import_wifkey" onChange={this.updateInput} />
<label className="floating-label" htmlFor="import_wifkey">{translate('INDEX.INPUT_PRIV_KEY')}</label>
</div>
<div className="col-sm-12 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="import_wifkey_btn" onClick={this.importWifKey}>{translate('INDEX.IMPORT_PRIV_KEY')}</button>
</div>
</form>
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<div className="row" id="wif-priv-keys" data-plugin="masonry">
</div>
</div>
</div>
</div>
</div>
<div className="panel" id="DebugLog">
<div className="panel-heading" role="tab" onClick={() => this.openTab('DebugLog', 6)}>
<a className={this.state.activeTab === 6 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#SettingsAccordion">
<i className="icon md-info" aria-hidden="true"></i>{translate('INDEX.DEBUG_LOG')}
</a>
</div>
<div className={this.state.activeTab === 6 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 6 ? this.state.activeTabHeight + 'px' : '10px'}} id="DebugLogTab" aria-labelledby="DebugLog" role="tabpanel">
<div className="panel-body">
<p>{translate('INDEX.DEBUG_LOG_DESC')}</p>
<div className="col-sm-12"></div>
<form className="read-debug-log-import-form" method="post" action="javascript:" autoComplete="off">
<div className="form-group form-material floating">
<input type="text" className="form-control" name="debugLinesCount" id="read_debug_log_lines" value={this.state.debugLinesCount} onChange={this.updateInput} />
<label className="floating-label" htmlFor="read_debug_log_lines">{translate('INDEX.DEBUG_LOG_LINES')}</label>
</div>
<div className="form-group form-material floating">
<select className="form-control form-material" name="debugTarget" id="settings_select_debuglog_options" onChange={this.updateInput}>
<option value="iguana">Iguana</option>
<option value="komodo">Komodo</option>
</select>
<label className="floating-label" htmlFor="settings_select_debuglog_options">{translate('INDEX.TARGET')}</label>
</div>
<div className="col-sm-12 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="read_debug_log_btn" onClick={this.readDebugLog}>{translate('INDEX.LOAD_DEBUG_LOG')}</button>
</div>
<div className="col-sm-12 col-xs-12" style={{textAlign: 'left'}}>
<br />
<div style={{padding: '20px 0'}}>{this.props.Settings.debugLog}</div>
</div>
</form>
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<div className="row" data-plugin="masonry"></div>
</div>
</div>
</div>
</div>
<div className="panel" id="AppSettings">
<div className="panel-heading" role="tab" onClick={() => this.openTab('AppSettings', 7)}>
<a className={this.state.activeTab === 7 ? 'panel-title' : 'panel-title collapsed'} data-toggle="collapse" data-parent="#AppSettings">
<i className="icon md-info" aria-hidden="true"></i>App Config (config.json)
</a>
</div>
<div className={this.state.activeTab === 7 ? 'panel-collapse collapse in' : 'panel-collapse collapse'} style={{height: this.state.activeTab === 7 ? this.state.activeTabHeight + 'px' : '10px'}} id="DebugLogTab" aria-labelledby="DebugLog" role="tabpanel">
<div className="panel-body">
<p>Manage app config</p>
<p>
<strong>Most changes to app config require wallet restart!</strong>
</p>
<div className="col-sm-12"></div>
<form className="read-debug-log-import-form" method="post" action="javascript:" autoComplete="off">
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<div className="row" data-plugin="masonry"></div>
</div>
<div className="col-sm-12" style={{paddingTop: '15px'}}>
<table>
<tbody>
{this.renderConfigEditForm()}
</tbody>
</table>
</div>
<div className="col-sm-12 col-xs-12" style={{textAlign: 'center'}}>
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" data-dismiss="modal" id="read_debug_log_btn" onClick={this._saveAppConfig}>Save app config</button>
</div>
</form>
</div>
</div>
</div>
{this.renderAppInfoTab()}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default Settings;