pbca26
7 years ago
committed by
GitHub
17 changed files with 1774 additions and 1433 deletions
@ -0,0 +1,180 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
import { |
|||
addPeerNode, |
|||
getPeersList, |
|||
getPeersListState, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
import AddCoinOptionsCrypto from '../../addcoin/addcoinOptionsCrypto'; |
|||
import AddCoinOptionsAC from '../../addcoin/addcoinOptionsAC'; |
|||
import AddCoinOptionsACFiat from '../../addcoin/addcoinOptionsACFiat'; |
|||
|
|||
class AddNodePanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
addNodeCoin: null, |
|||
addPeerIP: null, |
|||
getPeersCoin: null, |
|||
trimPassphraseTimer: null, |
|||
wifkeysPassphrase:'', |
|||
}; |
|||
this.renderSNPeersList = this.renderSNPeersList.bind(this); |
|||
this.renderPeersList = this.renderPeersList.bind(this); |
|||
this.checkNodes = this.checkNodes.bind(this); |
|||
this.addNode = this.addNode.bind(this); |
|||
this.updateInput = this.updateInput.bind(this); |
|||
} |
|||
|
|||
renderSNPeersList() { |
|||
if (this.state.getPeersCoin) { |
|||
const _getPeersCoin = this.state.getPeersCoin; |
|||
const _supernetPeers = this.props.Settings.supernetPeers; |
|||
const coin = _getPeersCoin.split('|')[0]; |
|||
|
|||
if (_supernetPeers && |
|||
_getPeersCoin && |
|||
_supernetPeers[coin]) { |
|||
return _supernetPeers[coin].map((ip) => |
|||
<div key={ ip }>{ ip }</div> |
|||
); |
|||
} else { |
|||
return null; |
|||
} |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
renderPeersList() { |
|||
if (this.state.getPeersCoin) { |
|||
const _getPeersCoin = this.state.getPeersCoin; |
|||
const _rawPeers = this.props.Settings.rawPeers; |
|||
const coin = _getPeersCoin.split('|')[0]; |
|||
|
|||
if (_rawPeers && |
|||
_getPeersCoin && |
|||
_rawPeers[coin]) { |
|||
return _rawPeers[coin].map((ip) => |
|||
<div key={ ip }>{ ip }</div> |
|||
); |
|||
} else { |
|||
return null; |
|||
} |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
checkNodes() { |
|||
if (this.state.getPeersCoin) { |
|||
console.warn(this.state.getPeersCoin.split('|')[0]); |
|||
Store.dispatch(getPeersList(this.state.getPeersCoin.split('|')[0])); |
|||
} |
|||
} |
|||
|
|||
addNode() { |
|||
if (this.state.addNodeCoin && this.state.addPeerIP) { |
|||
Store.dispatch( |
|||
addPeerNode( |
|||
this.state.addNodeCoin.split('|')[0], |
|||
this.state.addPeerIP |
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
updateInput(e) { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<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" |
|||
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 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.checkNodes }>{ translate('INDEX.CHECK_NODES') }</button> |
|||
</div> |
|||
<div className="col-sm-12"> |
|||
<h5> |
|||
SuperNET Peers: |
|||
</h5> |
|||
<div>{ this.renderSNPeersList() }</div> |
|||
<h5> |
|||
Raw Peers: |
|||
</h5> |
|||
<div>{ this.renderPeersList() }</div> |
|||
</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" |
|||
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" |
|||
name="addPeerIP" |
|||
placeholder={ translate('SETTINGS.ADD_PEER_IP') } |
|||
onChange={ this.updateInput } /> |
|||
</div> |
|||
</div> |
|||
<div className="col-sm-4 col-xs-12 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.addNode }>{ translate('INDEX.ADD_NODE') }</button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(AddNodePanel); |
@ -0,0 +1,90 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
class AppInfoPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<div className="col-sm-12 padding-top-15"> |
|||
<div className="row"> |
|||
<h5>{ translate('SETTINGS.APP_RELEASE') }</h5> |
|||
<div> |
|||
{ translate('SETTINGS.NAME') }: { this.props.Settings.appInfo.releaseInfo.name } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.VERSION') }: { `${this.props.Settings.appInfo.releaseInfo.version.replace('version=', '')}-beta` } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.APP_SESSION') }: { this.props.Settings.appInfo.appSession } |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div className="col-sm-12 padding-top-20"> |
|||
<div className="row"> |
|||
<h5>{ translate('SETTINGS.SYS_INFO') }</h5> |
|||
<div> |
|||
{ translate('SETTINGS.ARCH') }: { this.props.Settings.appInfo.sysInfo.arch } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.OS_TYPE') }: { this.props.Settings.appInfo.sysInfo.os_type } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.OS_PLATFORM') }: { this.props.Settings.appInfo.sysInfo.platform } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.OS_RELEASE') }: { this.props.Settings.appInfo.sysInfo.os_release } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.CPU') }: { this.props.Settings.appInfo.sysInfo.cpu } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.CPU_CORES') }: { this.props.Settings.appInfo.sysInfo.cpu_cores } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.MEM') }: { this.props.Settings.appInfo.sysInfo.totalmem_readable } |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div className="col-sm-12 padding-top-20"> |
|||
<div className="row"> |
|||
<h5>{ translate('SETTINGS.LOCATIONS') }</h5> |
|||
<div> |
|||
{ translate('SETTINGS.CACHE') }: { this.props.Settings.appInfo.dirs.cacheLocation } |
|||
</div> |
|||
<div> |
|||
{ translate('SETTINGS.CONFIG') }: { this.props.Settings.appInfo.dirs.configLocation } |
|||
</div> |
|||
<div> |
|||
Iguana { translate('SETTINGS.BIN') }: { this.props.Settings.appInfo.dirs.iguanaBin } |
|||
</div> |
|||
<div> |
|||
Iguana { translate('SETTINGS.DIR') }: { this.props.Settings.appInfo.dirs.iguanaDir } |
|||
</div> |
|||
<div> |
|||
Komodo { translate('SETTINGS.BIN') }: { this.props.Settings.appInfo.dirs.komododBin } |
|||
</div> |
|||
<div> |
|||
Komodo { translate('SETTINGS.DIR') }: { this.props.Settings.appInfo.dirs.komodoDir } |
|||
</div> |
|||
<div> |
|||
Komodo wallet.dat: { this.props.Settings.appInfo.dirs.komodoDir } |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(AppInfoPanel); |
@ -0,0 +1,321 @@ |
|||
import React from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import Config from '../../../config'; |
|||
import { |
|||
iguanaActiveHandle, |
|||
getAppConfig, |
|||
getAppInfo, |
|||
resetAppConfig, |
|||
saveAppConfig, |
|||
skipFullDashboardUpdate, |
|||
triggerToaster, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
class AppSettingsPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
appSettings: {}, |
|||
appConfigSchema: {}, |
|||
}; |
|||
this._saveAppConfig = this._saveAppConfig.bind(this); |
|||
this._resetAppConfig = this._resetAppConfig.bind(this); |
|||
this._skipFullDashboardUpdate = this._skipFullDashboardUpdate.bind(this); |
|||
this.updateInput = this.updateInput.bind(this); |
|||
} |
|||
|
|||
componentWillMount() { |
|||
try { |
|||
const _appConfigSchema = window.require('electron').remote.getCurrentWindow().appConfigSchema; |
|||
const _appSettings = this.props.Settings.appSettings ? this.props.Settings.appSettings : Object.assign({}, window.require('electron').remote.getCurrentWindow().appConfig); |
|||
|
|||
this.setState(Object.assign({}, this.state, { |
|||
appConfigSchema: _appConfigSchema, |
|||
appSettings: _appSettings, |
|||
})); |
|||
} catch(e) {} |
|||
} |
|||
|
|||
componentDidMount(props) { |
|||
if (!this.props.disableWalletSpecificUI) { |
|||
Store.dispatch(iguanaActiveHandle()); |
|||
} |
|||
|
|||
Store.dispatch(getAppConfig()); |
|||
Store.dispatch(getAppInfo()); |
|||
} |
|||
|
|||
_skipFullDashboardUpdate() { |
|||
Store.dispatch(skipFullDashboardUpdate(!this.props.Dashboard.skipFullDashboardUpdate)); |
|||
} |
|||
|
|||
_resetAppConfig() { |
|||
Store.dispatch(resetAppConfig()); |
|||
} |
|||
|
|||
_saveAppConfig() { |
|||
const _appSettings = this.state.appSettings; |
|||
let _appSettingsPristine = Object.assign({}, this.props.Settings.appSettings); |
|||
let isError = false; |
|||
let saveAfterPathCheck = false; |
|||
|
|||
for (let key in _appSettings) { |
|||
if (key.indexOf('__') === -1) { |
|||
_appSettingsPristine[key] = this.state.appConfigSchema[key] && this.state.appConfigSchema[key].type === 'number' ? Number(_appSettings[key]) : _appSettings[key]; |
|||
|
|||
if (this.state.appConfigSchema[key] && this.state.appConfigSchema[key].type === 'folder' && |
|||
_appSettings[key] && |
|||
_appSettings[key].length) { |
|||
const _testLocation = window.require('electron').remote.getCurrentWindow().testLocation; |
|||
saveAfterPathCheck = true; |
|||
|
|||
_testLocation(_appSettings[key]) |
|||
.then((res) => { |
|||
if (res === -1) { |
|||
isError = true; |
|||
Store.dispatch( |
|||
triggerToaster( |
|||
translate('TOASTR.KOMODO_DATADIR_INVALID'), |
|||
translate('INDEX.SETTINGS'), |
|||
'error' |
|||
) |
|||
); |
|||
} else if (res === false) { |
|||
isError = true; |
|||
Store.dispatch( |
|||
triggerToaster( |
|||
translate('TOASTR.KOMODO_DATADIR_NOT_DIR'), |
|||
translate('INDEX.SETTINGS'), |
|||
'error' |
|||
) |
|||
); |
|||
} else { |
|||
Store.dispatch(saveAppConfig(_appSettingsPristine)); |
|||
} |
|||
}); |
|||
} |
|||
} else { |
|||
const _nestedKey = key.split('__'); |
|||
_appSettingsPristine[_nestedKey[0]][_nestedKey[1]] = this.state.appConfigSchema[_nestedKey[0]][_nestedKey[1]].type === 'number' ? Number(_appSettings[key]) : _appSettings[key]; |
|||
} |
|||
} |
|||
|
|||
if (!saveAfterPathCheck) { |
|||
Store.dispatch(saveAppConfig(_appSettingsPristine)); |
|||
} |
|||
} |
|||
|
|||
renderConfigEditForm() { |
|||
let items = []; |
|||
const _appConfig = this.state.appSettings; |
|||
for (let key in _appConfig) { |
|||
if (this.state.appConfigSchema[key] && typeof _appConfig[key] === 'object') { |
|||
if (this.state.appConfigSchema[key].display) { |
|||
items.push( |
|||
<tr key={ `app-settings-${key}` }> |
|||
<td className="padding-15"> |
|||
{ this.state.appConfigSchema[key].displayName ? this.state.appConfigSchema[key].displayName : key } |
|||
{ this.state.appConfigSchema[key].info && |
|||
<i |
|||
className="icon fa-question-circle settings-help" |
|||
title={ this.state.appConfigSchema[key].info }></i> |
|||
} |
|||
</td> |
|||
<td className="padding-15"></td> |
|||
</tr> |
|||
); |
|||
|
|||
for (let _key in _appConfig[key]) { |
|||
items.push( |
|||
<tr key={ `app-settings-${key}-${_key}` }> |
|||
<td className="padding-15 padding-left-30"> |
|||
{ this.state.appConfigSchema[key][_key].displayName ? this.state.appConfigSchema[key][_key].displayName : _key } |
|||
{ this.state.appConfigSchema[key][_key].info && |
|||
<i |
|||
className="icon fa-question-circle settings-help" |
|||
title={ this.state.appConfigSchema[key][_key].info }></i> |
|||
} |
|||
</td> |
|||
<td className="padding-15"> |
|||
{ this.state.appConfigSchema[key][_key].type === 'number' && |
|||
<input |
|||
type="number" |
|||
pattern="[0-9]*" |
|||
name={ `${key}__${_key}` } |
|||
value={ _appConfig[key][_key] } |
|||
onChange={ (event) => this.updateInputSettings(event, key, _key) } /> |
|||
} |
|||
{ (this.state.appConfigSchema[key][_key].type === 'string' || this.state.appConfigSchema[key][_key].type === 'folder') && |
|||
<input |
|||
type="text" |
|||
name={ `${key}__${_key}` } |
|||
value={ _appConfig[key][_key] } |
|||
className={ this.state.appConfigSchema[key][_key].type === 'folder' ? 'full-width': '' } |
|||
onChange={ (event) => this.updateInputSettings(event, key, _key) } /> |
|||
} |
|||
{ this.state.appConfigSchema[key][_key].type === 'boolean' && |
|||
<span className="pointer toggle"> |
|||
<label className="switch"> |
|||
<input |
|||
type="checkbox" |
|||
name={ `${key}__${_key}` } |
|||
value={ _appConfig[key] } |
|||
checked={ _appConfig[key][_key] } /> |
|||
<div |
|||
className="slider" |
|||
onClick={ (event) => this.updateInputSettings(event, key, _key) }></div> |
|||
</label> |
|||
</span> |
|||
} |
|||
</td> |
|||
</tr> |
|||
); |
|||
} |
|||
} |
|||
} else { |
|||
if (this.state.appConfigSchema[key] && this.state.appConfigSchema[key].display) { |
|||
items.push( |
|||
<tr key={ `app-settings-${key}` }> |
|||
<td className="padding-15"> |
|||
{ this.state.appConfigSchema[key].displayName ? this.state.appConfigSchema[key].displayName : key } |
|||
{ this.state.appConfigSchema[key].info && |
|||
<i |
|||
className="icon fa-question-circle settings-help" |
|||
title={ this.state.appConfigSchema[key].info }></i> |
|||
} |
|||
</td> |
|||
<td className="padding-15"> |
|||
{ this.state.appConfigSchema[key].type === 'number' && |
|||
<input |
|||
type="number" |
|||
pattern="[0-9]*" |
|||
name={ `${key}` } |
|||
value={ _appConfig[key] } |
|||
onChange={ (event) => this.updateInputSettings(event, key) } /> |
|||
} |
|||
{ (this.state.appConfigSchema[key].type === 'string' || this.state.appConfigSchema[key].type === 'folder') && |
|||
<input |
|||
type="text" |
|||
name={ `${key}` } |
|||
value={ _appConfig[key] } |
|||
className={ this.state.appConfigSchema[key].type === 'folder' ? 'full-width': '' } |
|||
onChange={ (event) => this.updateInputSettings(event, key) } /> |
|||
} |
|||
{ this.state.appConfigSchema[key].type === 'boolean' && |
|||
<span className="pointer toggle"> |
|||
<label className="switch"> |
|||
<input |
|||
type="checkbox" |
|||
name={ `${key}` } |
|||
value={ _appConfig[key] } |
|||
checked={ _appConfig[key] } /> |
|||
<div |
|||
className="slider" |
|||
onClick={ (event) => this.updateInputSettings(event, key) }></div> |
|||
</label> |
|||
</span> |
|||
} |
|||
</td> |
|||
</tr> |
|||
); |
|||
} |
|||
} |
|||
} |
|||
|
|||
items.push( |
|||
<tr key={ `kmd-main-sync-only` }> |
|||
<td className="padding-15"> |
|||
KMD main sync only |
|||
<i |
|||
className="icon fa-question-circle settings-help" |
|||
title="Fetch block synchronization data only. Skip any other requests that can deteriorate sync speed."></i> |
|||
</td> |
|||
<td className="padding-15"> |
|||
<span className="pointer toggle"> |
|||
<label className="switch"> |
|||
<input |
|||
type="checkbox" |
|||
name={ `kmd-main-sync-only` } |
|||
value={ this.props.Dashboard.skipFullDashboardUpdate } |
|||
checked={ this.props.Dashboard.skipFullDashboardUpdate } /> |
|||
<div |
|||
className="slider" |
|||
onClick={ this._skipFullDashboardUpdate }></div> |
|||
</label> |
|||
</span> |
|||
</td> |
|||
</tr> |
|||
); |
|||
|
|||
return items; |
|||
} |
|||
|
|||
updateInput(e) { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
|
|||
updateInputSettings(e, parentKey, childKey) { |
|||
let _appSettings = this.state.appSettings; |
|||
let _appSettingsPrev = Object.assign({}, _appSettings); |
|||
|
|||
if (!childKey && this.state.appConfigSchema[parentKey].type === 'boolean') { |
|||
_appSettings[parentKey] = typeof _appSettings[parentKey] !== undefined ? !_appSettings[parentKey] : !this.state.appSettings[parentKey]; |
|||
} else if (childKey && this.state.appConfigSchema[parentKey][childKey].type === 'boolean') { |
|||
_appSettings[parentKey][childKey] = typeof _appSettings[parentKey][childKey] !== undefined ? !_appSettings[parentKey][childKey] : !this.state.appSettings[parentKey][childKey]; |
|||
} else if ((!childKey && this.state.appConfigSchema[parentKey].type === 'number') || (childKey && this.state.appConfigSchema[parentKey][childKey].type === 'number')) { |
|||
if (e.target.value === '') { |
|||
_appSettings[e.target.name] = _appSettingsPrev[e.target.name]; |
|||
} else { |
|||
_appSettings[e.target.name] = e.target.value.replace(/[^0-9]+/g, ''); |
|||
} |
|||
} else { |
|||
_appSettings[e.target.name] = e.target.value; |
|||
} |
|||
|
|||
this.setState({ |
|||
appSettings: _appSettings, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<p> |
|||
<strong>{ translate('SETTINGS.CONFIG_RESTART_REQUIRED') }</strong> |
|||
</p> |
|||
<div className="col-sm-12 padding-top-15"> |
|||
<table> |
|||
<tbody> |
|||
{ this.renderConfigEditForm() } |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-center padding-top-35 padding-bottom-30"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this._saveAppConfig }>{ translate('SETTINGS.SAVE_APP_CONFIG') }</button> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light margin-left-30" |
|||
onClick={ this._resetAppConfig }>Reset to default</button> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
Dashboard: { |
|||
skipFullDashboardUpdate: state.Dashboard.skipFullDashboardUpdate, |
|||
}, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(AppSettingsPanel); |
@ -0,0 +1,151 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
import Config from '../../../config'; |
|||
import { |
|||
getPeersList, |
|||
checkForUpdateUIPromise, |
|||
updateUIPromise, |
|||
} from '../../../actions/actionCreators'; |
|||
|
|||
import { SocketProvider } from 'socket.io-react'; |
|||
import io from 'socket.io-client'; |
|||
|
|||
const socket = io.connect(`http://127.0.0.1:${Config.agamaPort}`); |
|||
|
|||
let updateProgressBar = { |
|||
patch: -1, |
|||
}; |
|||
|
|||
class AppUpdatePanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
updatePatch: null, |
|||
updateLog: [], |
|||
updateProgressPatch: null, |
|||
updatePatch: null, |
|||
updateBins: null, |
|||
}; |
|||
this._checkForUpdateUIPromise = this._checkForUpdateUIPromise.bind(this); |
|||
this._updateUIPromise = this._updateUIPromise.bind(this); |
|||
this.checkNodes = this.checkNodes.bind(this); |
|||
} |
|||
|
|||
componentWillMount() { |
|||
socket.on('patch', msg => this.updateSocketsData = (msg) => {}); |
|||
} |
|||
|
|||
componentWillUnmount() { |
|||
socket.removeAllListeners('patch', msg => this.updateSocketsData(msg)); |
|||
} |
|||
|
|||
checkNodes() { |
|||
if (this.state.getPeersCoin) { |
|||
Store.dispatch(getPeersList(this.state.getPeersCoin.split('|')[0])); |
|||
} |
|||
} |
|||
|
|||
_updateUIPromise() { |
|||
updateProgressBar.patch = 0; |
|||
let _updateLog = []; |
|||
_updateLog.push(`${translate('INDEX.DOWNLOADING_UI_UPDATE')}...`); |
|||
this.setState(Object.assign({}, this.state, { |
|||
updateLog: _updateLog, |
|||
})); |
|||
|
|||
updateUIPromise(); |
|||
} |
|||
|
|||
_checkForUpdateUIPromise() { |
|||
let _updateLog = []; |
|||
_updateLog.push(translate('INDEX.CHECKING_UI_UPDATE')); |
|||
this.setState(Object.assign({}, this.state, { |
|||
updateLog: _updateLog, |
|||
})); |
|||
|
|||
checkForUpdateUIPromise() |
|||
.then((res) => { |
|||
let _updateLog = this.state.updateLog; |
|||
_updateLog.push(res.result === 'update' ? (`${translate('INDEX.NEW_UI_UPDATE')} ${res.version.remote}`) : translate('INDEX.YOU_HAVE_LATEST_UI')); |
|||
this.setState(Object.assign({}, this.state, { |
|||
updatePatch: res.result === 'update' ? true : false, |
|||
updateLog: _updateLog, |
|||
})); |
|||
}); |
|||
} |
|||
|
|||
renderUpdateStatus() { |
|||
let items = []; |
|||
let patchProgressBar = null; |
|||
const _updateLogLength = this.state.updateLog.length; |
|||
|
|||
for (let i = 0; i < _updateLogLength; i++) { |
|||
items.push( |
|||
<div key={ `settings-update-log-${i}` }>{ this.state.updateLog[i] }</div> |
|||
); |
|||
} |
|||
|
|||
if (_updateLogLength) { |
|||
return ( |
|||
<div style={{ minHeight: '200px' }}> |
|||
<hr /> |
|||
<h5>{ translate('SETTINGS.PROGRESS') }:</h5> |
|||
<div className="padding-bottom-15">{ items }</div> |
|||
<div className={ updateProgressBar.patch > -1 ? 'progress progress-sm' : 'hide' }> |
|||
<div |
|||
className="progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success font-size-80-percent" |
|||
style={{ width: `${updateProgressBar.patch}%` }}> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<div className="col-sm-4 padding-top-15"> |
|||
<h5>{ translate('INDEX.UI_UPDATE') }</h5> |
|||
<div className="padding-top-15"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-info waves-effect waves-light" |
|||
onClick={ this._checkForUpdateUIPromise }>{ translate('INDEX.CHECK_FOR_UPDATE') }</button> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light margin-left-20" |
|||
onClick={ this._updateUIPromise } |
|||
disabled={ !this.state.updatePatch }>{ translate('INDEX.UPDATE_UI_NOW') }</button> |
|||
</div> |
|||
</div> |
|||
<div className="col-sm-4 padding-top-15 hide"> |
|||
<h5>{ translate('INDEX.BINS_UPDATE') }</h5> |
|||
<div className="padding-top-15"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-info waves-effect waves-light" |
|||
onClick={ this._checkForUpdateUIPromise }>{ translate('INDEX.CHECK_FOR_UPDATE') }</button> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light margin-left-20" |
|||
onClick={ this.checkNodes }>{ translate('INDEX.UPDATE_BINS_NOW') }</button> |
|||
</div> |
|||
</div> |
|||
<div className="col-sm-12 padding-top-15"> |
|||
{ this.renderUpdateStatus() } |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(AppUpdatePanel); |
@ -0,0 +1,206 @@ |
|||
import React from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { |
|||
shepherdCli, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
class CliPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
cliCmdString: '', |
|||
cliCoin: null, |
|||
cliResponse: null, |
|||
}; |
|||
} |
|||
|
|||
renderActiveCoinsList(mode) { |
|||
const modes = [ |
|||
'native', |
|||
'basilisk', |
|||
'full' |
|||
]; |
|||
|
|||
const allCoins = this.props.Main.coins; |
|||
let items = []; |
|||
|
|||
if (allCoins) { |
|||
if (mode === 'all') { |
|||
modes.map(function(mode) { |
|||
allCoins[mode].map(function(coin) { |
|||
items.push( |
|||
<option |
|||
value={ coin } |
|||
key={ coin }> |
|||
{ coin } ({ mode }) |
|||
</option> |
|||
); |
|||
}); |
|||
}); |
|||
} else { |
|||
allCoins[mode].map(function(coin) { |
|||
items.push( |
|||
<option |
|||
value={ coin } |
|||
key={ coin }> |
|||
{ coin } ({ mode }) |
|||
</option> |
|||
); |
|||
}); |
|||
} |
|||
|
|||
return items; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
// TODO: rerender only if prop is changed
|
|||
renderCliResponse() { |
|||
const _cliResponse = this.props.Settings.cli; |
|||
let _items = []; |
|||
|
|||
if (_cliResponse) { |
|||
let _cliResponseParsed; |
|||
let responseType; |
|||
|
|||
try { |
|||
_cliResponseParsed = JSON.parse(_cliResponse.result); |
|||
} catch(e) { |
|||
_cliResponseParsed = _cliResponse.result; |
|||
} |
|||
|
|||
if (Object.prototype.toString.call(_cliResponseParsed) === '[object Array]') { |
|||
responseType = 'array'; |
|||
|
|||
for (let i = 0; i < _cliResponseParsed.length; i++) { |
|||
_items.push( |
|||
<div key={ `cli-response-${Math.random(0, 9) * 10}` }>{ JSON.stringify(_cliResponseParsed[i], null, '\t') }</div> |
|||
); |
|||
} |
|||
} |
|||
if (Object.prototype.toString.call(_cliResponseParsed) === '[object]' || |
|||
typeof _cliResponseParsed === 'object') { |
|||
responseType = 'object'; |
|||
|
|||
_items.push( |
|||
<div key={ `cli-response-${Math.random(0, 9) * 10}` }>{ JSON.stringify(_cliResponseParsed, null, '\t') }</div> |
|||
); |
|||
} |
|||
if (Object.prototype.toString.call(_cliResponseParsed) === 'number' || |
|||
typeof _cliResponseParsed === 'boolean' || |
|||
_cliResponseParsed === 'wrong cli string format') { |
|||
responseType = 'number'; |
|||
|
|||
_items.push( |
|||
<div key={ `cli-response-${Math.random(0, 9) * 10}` }>{ _cliResponseParsed.toString() }</div> |
|||
); |
|||
} |
|||
|
|||
if (responseType !== 'number' && |
|||
responseType !== 'array' && |
|||
responseType !== 'object' && |
|||
_cliResponseParsed.indexOf('\n') > -1) { |
|||
_cliResponseParsed = _cliResponseParsed.split('\n'); |
|||
|
|||
for (let i = 0; i < _cliResponseParsed.length; i++) { |
|||
_items.push( |
|||
<div key={ `cli-response-${Math.random(0, 9) * 10}` }>{ _cliResponseParsed[i] }</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<div> |
|||
<strong>{ translate('SETTINGS.CLI_RESPONSE') }:</strong> |
|||
</div> |
|||
{ _items } |
|||
</div> |
|||
); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
execCliCmd() { |
|||
Store.dispatch( |
|||
shepherdCli( |
|||
'passthru', |
|||
this.state.cliCoin, |
|||
this.state.cliCmdString |
|||
) |
|||
); |
|||
} |
|||
|
|||
updateInput = (e) => { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<p>{ translate('INDEX.CLI_SELECT_A_COIN') }</p> |
|||
<div className="col-sm-12"></div> |
|||
<form |
|||
className="execute-cli-cmd-form" |
|||
method="post" |
|||
action="javascript:" |
|||
autoComplete="off"> |
|||
<div className="form-group form-material floating"> |
|||
<select |
|||
className="form-control form-material" |
|||
name="cliCoin" |
|||
id="settingsCliOptions" |
|||
onChange={ this.updateInput }> |
|||
<option>{ translate('INDEX.CLI_NATIVE_COIN') }</option> |
|||
{ this.renderActiveCoinsList('native') } |
|||
</select> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="settingsDelectDebugLogOptions">{ translate('INDEX.COIN') }</label> |
|||
</div> |
|||
<div className="form-group form-material floating"> |
|||
<textarea |
|||
type="text" |
|||
className="form-control" |
|||
name="cliCmdString" |
|||
id="cliCmd" |
|||
value={ this.state.cliCmdString } |
|||
onChange={ this.updateInput }></textarea> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="readDebugLogLines">{ translate('INDEX.TYPE_CLI_CMD') }</label> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
disabled={ !this.state.cliCoin || !this.state.cliCmdString } |
|||
onClick={ () => this.execCliCmd() }>{ translate('INDEX.EXECUTE') }</button> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-left"> |
|||
<div className="padding-top-40 padding-bottom-20 horizontal-padding-0"> |
|||
{ this.renderCliResponse() } |
|||
</div> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Main: { |
|||
coins: state.Main.coins, |
|||
}, |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(CliPanel); |
@ -0,0 +1,180 @@ |
|||
import React from 'react'; |
|||
import { connect } from 'react-redux'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import Config from '../../../config'; |
|||
import { secondsToString } from '../../../util/time'; |
|||
import { |
|||
getDebugLog, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
class DebugLogPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
appRuntimeLog: [], |
|||
debugLinesCount: 10, |
|||
debugTarget: 'iguana', |
|||
nativeOnly: Config.iguanaLessMode, |
|||
toggleAppRuntimeLog: false, |
|||
}; |
|||
this.readDebugLog = this.readDebugLog.bind(this); |
|||
this.updateInput = this.updateInput.bind(this); |
|||
this.getAppRuntimeLog = this.getAppRuntimeLog.bind(this); |
|||
this.toggleAppRuntimeLog = this.toggleAppRuntimeLog.bind(this); |
|||
this.renderAppRuntimeLog = this.renderAppRuntimeLog.bind(this); |
|||
} |
|||
|
|||
readDebugLog() { |
|||
Store.dispatch( |
|||
getDebugLog( |
|||
this.state.debugTarget, |
|||
this.state.debugLinesCount |
|||
) |
|||
); |
|||
} |
|||
|
|||
renderAppRuntimeLog() { |
|||
let _items = []; |
|||
const _appRuntimeLog = this.state.appRuntimeLog; |
|||
|
|||
for (let i = 0; i < _appRuntimeLog.length; i++) { |
|||
_items.push( |
|||
<p key={ `app-runtime-log-entry-${i}` }> |
|||
<span>{ secondsToString(_appRuntimeLog[i].time, true) }</span> |
|||
<span className="padding-left-30">{ JSON.stringify(_appRuntimeLog[i].msg, null, '').replace('\\n', ' ') }</span> |
|||
</p> |
|||
); |
|||
} |
|||
|
|||
return _items; |
|||
} |
|||
|
|||
toggleAppRuntimeLog() { |
|||
this.setState(Object.assign({}, this.state, { |
|||
toggleAppRuntimeLog: !this.state.toggleAppRuntimeLog, |
|||
})); |
|||
|
|||
this.getAppRuntimeLog(); |
|||
} |
|||
|
|||
getAppRuntimeLog() { |
|||
let _appRuntimeLog; |
|||
|
|||
try { |
|||
_appRuntimeLog = window.require('electron').remote.getCurrentWindow().getAppRuntimeLog; |
|||
} catch (e) {} |
|||
|
|||
_appRuntimeLog() |
|||
.then((json) => { |
|||
this.setState(Object.assign({}, this.state, { |
|||
appRuntimeLog: json, |
|||
})); |
|||
}); |
|||
} |
|||
|
|||
renderDebugLogData() { |
|||
if (this.props.Settings.debugLog) { |
|||
const _debugLogDataRows = this.props.Settings.debugLog.split('\n'); |
|||
|
|||
if (_debugLogDataRows && |
|||
_debugLogDataRows.length) { |
|||
return _debugLogDataRows.map((_row) => |
|||
<div |
|||
key={ `settings-debuglog-${Math.random(0, 9) * 10}` } |
|||
className="padding-bottom-5">{ _row }</div> |
|||
); |
|||
} else { |
|||
return ( |
|||
<span>{ translate('INDEX.EMPTY_DEBUG_LOG') }</span> |
|||
); |
|||
} |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
updateInput(e) { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<p>{ translate('INDEX.DEBUG_LOG_DESC') }</p> |
|||
<div className="margin-top-30"> |
|||
<span className="pointer toggle"> |
|||
<label className="switch"> |
|||
<input |
|||
type="checkbox" |
|||
name="settings-app-debug-toggle" |
|||
value={ this.state.toggleAppRuntimeLog } |
|||
checked={ this.state.toggleAppRuntimeLog } /> |
|||
<div |
|||
className="slider" |
|||
onClick={ this.toggleAppRuntimeLog }></div> |
|||
</label> |
|||
<span |
|||
className="title" |
|||
onClick={ this.toggleAppRuntimeLog }>Show app runtime log</span> |
|||
</span> |
|||
</div> |
|||
{ !this.state.toggleAppRuntimeLog && |
|||
<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="readDebugLogLines" |
|||
value={ this.state.debugLinesCount } |
|||
onChange={ this.updateInput } /> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="readDebugLogLines">{ translate('INDEX.DEBUG_LOG_LINES') }</label> |
|||
</div> |
|||
<div className="form-group form-material floating"> |
|||
<select |
|||
className="form-control form-material" |
|||
name="debugTarget" |
|||
id="settingsDelectDebugLogOptions" |
|||
onChange={ this.updateInput }> |
|||
<option value="iguana" className={ this.state.nativeOnly ? 'hide' : '' }>Iguana</option> |
|||
<option value="komodo">Komodo</option> |
|||
</select> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="settingsDelectDebugLogOptions">{ translate('INDEX.TARGET') }</label> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.readDebugLog }>{ translate('INDEX.LOAD_DEBUG_LOG') }</button> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-left"> |
|||
<div className="padding-top-40 padding-bottom-20 horizontal-padding-0">{ this.renderDebugLogData() }</div> |
|||
</div> |
|||
</form> |
|||
} |
|||
{ this.state.toggleAppRuntimeLog && |
|||
<div className="margin-top-20">{ this.renderAppRuntimeLog() }</div> |
|||
} |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(DebugLogPanel); |
@ -0,0 +1,221 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
import { |
|||
encryptWallet, |
|||
settingsWifkeyState, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
class ExportKeysPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
exportWifKeysRaw: false, |
|||
seedInputVisibility: false, |
|||
trimPassphraseTimer: null, |
|||
wifkeysPassphrase: '', |
|||
}; |
|||
this.exportWifKeys = this.exportWifKeys.bind(this); |
|||
this.exportWifKeysRaw = this.exportWifKeysRaw.bind(this); |
|||
this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this); |
|||
this.updateInput = this.updateInput.bind(this); |
|||
} |
|||
|
|||
exportWifKeys() { |
|||
Store.dispatch( |
|||
encryptWallet( |
|||
this.state.wifkeysPassphrase, |
|||
settingsWifkeyState, |
|||
this.props.ActiveCoin.coin |
|||
) |
|||
); |
|||
} |
|||
|
|||
exportWifKeysRaw() { |
|||
this.setState(Object.assign({}, this.state, { |
|||
exportWifKeysRaw: !this.state.exportWifKeysRaw, |
|||
})); |
|||
} |
|||
|
|||
toggleSeedInputVisibility() { |
|||
this.setState({ |
|||
seedInputVisibility: !this.state.seedInputVisibility, |
|||
}); |
|||
} |
|||
|
|||
renderExportWifKeysRaw() { |
|||
const _wifKeysResponse = this.props.Settings.wifkey; |
|||
|
|||
if (_wifKeysResponse && |
|||
this.state.exportWifKeysRaw) { |
|||
return ( |
|||
<div className="padding-bottom-30 padding-top-30"> |
|||
{ JSON.stringify(_wifKeysResponse, null, '\t') } |
|||
</div> |
|||
); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
renderWifKeys() { |
|||
let items = []; |
|||
|
|||
if (this.props.Settings.wifkey) { |
|||
const _wifKeys = this.props.Settings.wifkey; |
|||
|
|||
for (let i = 0; i < 2; i++) { |
|||
items.push( |
|||
<tr key={ `wif-export-table-header-${i}` }> |
|||
<td className="padding-bottom-10 padding-top-10"> |
|||
<strong>{ i === 0 ? translate('SETTINGS.ADDRESS_LIST') : translate('SETTINGS.WIF_KEY_LIST') }</strong> |
|||
</td> |
|||
<td className="padding-bottom-10 padding-top-10"></td> |
|||
</tr> |
|||
); |
|||
|
|||
for (let _key in _wifKeys) { |
|||
if ((i === 0 && _key.length === 3 && _key !== 'tag') || |
|||
(i === 1 && _key.indexOf('wif') > -1)) { |
|||
items.push( |
|||
<tr key={ _key }> |
|||
<td>{ _key }</td> |
|||
<td className="padding-left-15">{ _wifKeys[_key] }</td> |
|||
</tr> |
|||
); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return items; |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
updateInput(e) { |
|||
if (e.target.name === 'wifkeysPassphrase') { |
|||
// remove any empty chars from the start/end of the string
|
|||
const newValue = e.target.value; |
|||
|
|||
clearTimeout(this.state.trimPassphraseTimer); |
|||
|
|||
const _trimPassphraseTimer = setTimeout(() => { |
|||
this.setState({ |
|||
wifkeysPassphrase: newValue ? newValue.trim() : '', // hardcoded field name
|
|||
}); |
|||
}, 2000); |
|||
|
|||
this.resizeLoginTextarea(); |
|||
|
|||
this.setState({ |
|||
trimPassphraseTimer: _trimPassphraseTimer, |
|||
[e.target.name]: newValue, |
|||
}); |
|||
} else { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
} |
|||
|
|||
resizeLoginTextarea() { |
|||
// auto-size textarea
|
|||
setTimeout(() => { |
|||
if (this.state.seedInputVisibility) { |
|||
document.querySelector('#wifkeysPassphraseTextarea').style.height = '1px'; |
|||
document.querySelector('#wifkeysPassphraseTextarea').style.height = `${(15 + document.querySelector('#wifkeysPassphraseTextarea').scrollHeight)}px`; |
|||
} |
|||
}, 100); |
|||
} |
|||
|
|||
renderLB(_translationID) { |
|||
const _translationComponents = translate(_translationID).split('<br>'); |
|||
|
|||
return _translationComponents.map((_translation) => |
|||
<span key={ `settings-label-${Math.random(0, 9) * 10}` }> |
|||
{ _translation } |
|||
<br /> |
|||
</span> |
|||
); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<div> |
|||
<div className="padding-bottom-20">{ this.renderLB('INDEX.ONLY_ACTIVE_WIF_KEYS') }</div> |
|||
<div className="padding-bottom-20"> |
|||
<i>{ this.renderLB('SETTINGS.EXPORT_KEYS_NOTE') }</i> |
|||
</div> |
|||
<strong> |
|||
<i>{ translate('INDEX.PLEASE_KEEP_KEYS_SAFE') }</i> |
|||
</strong> |
|||
</div> |
|||
<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={ !this.state.seedInputVisibility ? 'form-control' : 'hide' } |
|||
name="wifkeysPassphrase" |
|||
id="wifkeysPassphrase" |
|||
onChange={ this.updateInput } |
|||
value={ this.state.wifkeysPassphrase } /> |
|||
<textarea |
|||
className={ this.state.seedInputVisibility ? 'form-control' : 'hide' } |
|||
id="wifkeysPassphraseTextarea" |
|||
name="wifkeysPassphrase" |
|||
onChange={ this.updateInput } |
|||
value={ this.state.wifkeysPassphrase }></textarea> |
|||
<i |
|||
className={ 'seed-toggle fa fa-eye' + (!this.state.seedInputVisibility ? '-slash' : '') } |
|||
onClick={ this.toggleSeedInputVisibility }></i> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="wifkeysPassphrase">{ translate('INDEX.PASSPHRASE') }</label> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.exportWifKeys }>{ translate('INDEX.GET_WIF_KEYS') }</button> |
|||
</div> |
|||
</form> |
|||
|
|||
<div className="col-sm-12 padding-top-15"> |
|||
<div className="row"> |
|||
<table className="table"> |
|||
{ this.renderWifKeys() } |
|||
</table> |
|||
<div className={ this.props.wifkey ? 'col-sm-12 col-xs-12 text-align-center' : 'hide' }> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.exportWifKeysRaw }>{ this.state.exportWifKeysRaw ? 'Hide' : 'Show' } raw data</button> |
|||
</div> |
|||
<div className={ this.state.exportWifKeysRaw ? 'col-sm-12 col-xs-12 text-align-center' : 'hide' }> |
|||
{ this.renderExportWifKeysRaw() } |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
ActiveCoin: { |
|||
coin: state.ActiveCoin.coin, |
|||
}, |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(ExportKeysPanel); |
@ -0,0 +1,23 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
class FiatCurrencyPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body">Fiat currency settings section to be updated soon.</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(FiatCurrencyPanel); |
@ -0,0 +1,67 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { |
|||
importPrivKey, |
|||
} from '../../../actions/actionCreators'; |
|||
import Store from '../../../store'; |
|||
|
|||
class ImportKeysPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
this.state = { |
|||
importWifKey: '', |
|||
}; |
|||
this.importWifKey = this.importWifKey.bind(this); |
|||
} |
|||
|
|||
importWifKey() { |
|||
Store.dispatch(importPrivKey(this.state.importWifKey)); |
|||
} |
|||
|
|||
updateInput = (e) => { |
|||
this.setState({ |
|||
[e.target.name]: e.target.value, |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<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/> |
|||
<div> |
|||
<strong> |
|||
<i>{ translate('INDEX.PLEASE_KEEP_KEYS_SAFE') }</i> |
|||
</strong> |
|||
</div> |
|||
<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="importWifkey" |
|||
onChange={ this.updateInput } /> |
|||
<label |
|||
className="floating-label" |
|||
htmlFor="importWifkey">{ translate('INDEX.INPUT_PRIV_KEY') }</label> |
|||
</div> |
|||
<div className="col-sm-12 col-xs-12 text-align-center"> |
|||
<button |
|||
type="button" |
|||
className="btn btn-primary waves-effect waves-light" |
|||
onClick={ this.importWifKey }>{ translate('INDEX.IMPORT_PRIV_KEY') }</button> |
|||
</div> |
|||
</form> |
|||
</div> |
|||
); |
|||
} |
|||
} |
|||
|
|||
export default ImportKeysPanel; |
@ -0,0 +1,82 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
|
|||
class SupportPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
} |
|||
|
|||
openExternalWindow(url) { |
|||
const remote = window.require('electron').remote; |
|||
const BrowserWindow = remote.BrowserWindow; |
|||
|
|||
const externalWindow = new BrowserWindow({ |
|||
width: 1280, |
|||
height: 800, |
|||
title: `${translate('INDEX.LOADING')}...`, |
|||
icon: remote.getCurrentWindow().iguanaIcon, |
|||
}); |
|||
|
|||
externalWindow.loadURL(url); |
|||
externalWindow.webContents.on('did-finish-load', function() { |
|||
setTimeout(function() { |
|||
externalWindow.show(); |
|||
}, 40); |
|||
}); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<div className="col-sm-12 no-padding-left"> |
|||
<div className="support-box-wrapper"> |
|||
<div |
|||
className="support-box" |
|||
onClick={ () => this.openExternalWindow('http://support.supernet.org') }> |
|||
<img |
|||
src="assets/images/cryptologo/supernet.png" |
|||
alt="Support tickets" /> |
|||
<div className="support-box-title">{ translate('SETTINGS.SUPPORT_TICKETS') }</div> |
|||
<div className="support-box-link">support.supernet.org</div> |
|||
</div> |
|||
</div> |
|||
<div className="support-box-wrapper"> |
|||
<div |
|||
className="support-box" |
|||
onClick={ () => this.openExternalWindow('https://sprnt.slack.com') }> |
|||
<img |
|||
src="assets/images/support/slack-icon.png" |
|||
alt="Slack" /> |
|||
<div className="support-box-title">Slack</div> |
|||
<div className="support-box-link">sprnt.slack.com</div> |
|||
</div> |
|||
</div> |
|||
<div className="support-box-wrapper"> |
|||
<div |
|||
className="support-box" |
|||
onClick={ () => this.openExternalWindow('http://slackinvite.supernet.org') }> |
|||
<img |
|||
src="assets/images/support/slack-invite-icon.png" |
|||
alt="Slack invite" /> |
|||
<div className="support-box-title">{ translate('SETTINGS.GET_SLACK_INVITE') }</div> |
|||
<div className="support-box-link">slackinvite.supernet.org</div> |
|||
</div> |
|||
</div> |
|||
<div className="support-box-wrapper"> |
|||
<div |
|||
className="support-box" |
|||
onClick={ () => this.openExternalWindow('https://github.com/SuperNETorg/Agama') }> |
|||
<img |
|||
src="assets/images/support/github-icon.png" |
|||
alt="Github" /> |
|||
<div className="support-box-title">Github</div> |
|||
<div className="support-box-link">github.com/SuperNETorg/Agama</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
export default SupportPanel; |
@ -0,0 +1,23 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
class WalletBackupPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body">Wallet Backup section to be updated soon.</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Settings: state.Settings, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(WalletBackupPanel); |
@ -0,0 +1,60 @@ |
|||
import React from 'react'; |
|||
import { translate } from '../../../translate/translate'; |
|||
import { connect } from 'react-redux'; |
|||
|
|||
class WalletInfoPanel extends React.Component { |
|||
constructor() { |
|||
super(); |
|||
} |
|||
|
|||
render() { |
|||
return ( |
|||
<div className="panel-body"> |
|||
<table className="table"> |
|||
<thead> |
|||
<tr> |
|||
<th width="10%">{ translate('INDEX.KEY') }</th> |
|||
<th>{ translate('INDEX.VALUE') }</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
<tr> |
|||
<td className="wallet-info-key">pubkey</td> |
|||
<td>{ this.props.Main.activeHandle.pubkey }</td> |
|||
</tr> |
|||
<tr> |
|||
<td className="wallet-info-key">btcpubkey</td> |
|||
<td>{ this.props.Main.activeHandle.btcpubkey }</td> |
|||
</tr> |
|||
<tr> |
|||
<td className="wallet-info-key">rmd160</td> |
|||
<td>{ this.props.Main.activeHandle.rmd160 }</td> |
|||
</tr> |
|||
<tr> |
|||
<td className="wallet-info-key">NXT</td> |
|||
<td>{ this.props.Main.activeHandle.NXT }</td> |
|||
</tr> |
|||
<tr> |
|||
<td className="wallet-info-key">notary</td> |
|||
<td>{ this.props.Main.activeHandle.notary }</td> |
|||
</tr> |
|||
<tr> |
|||
<td className="wallet-info-key">status</td> |
|||
<td>{ this.props.Main.activeHandle.status }</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
); |
|||
}; |
|||
} |
|||
|
|||
const mapStateToProps = (state) => { |
|||
return { |
|||
Main: { |
|||
activeHandle: state.Main.activeHandle, |
|||
}, |
|||
}; |
|||
}; |
|||
|
|||
export default connect(mapStateToProps)(WalletInfoPanel); |
Loading…
Reference in new issue