Browse Source

Merge pull request #181 from SuperNETorg/feature/tx-info-modal

Feature/tx info modal
v0.25
pbca26 7 years ago
committed by GitHub
parent
commit
ea658b2def
  1. 1
      react/src/actions/actionCreators.js
  2. 53
      react/src/actions/actions/getTxDetails.js
  3. 63
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js
  4. 200
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js
  5. 3
      react/src/translate/en.js

1
react/src/actions/actionCreators.js

@ -56,6 +56,7 @@ export * from './actions/update';
export * from './actions/jumblr';
export * from './actions/interest';
export * from './actions/nativeDashboardUpdate';
export * from './actions/getTxDetails';
export * from './actions/electrum';
export function changeActiveAddress(address) {

53
react/src/actions/actions/getTxDetails.js

@ -0,0 +1,53 @@
import {
triggerToaster
} from '../actionCreators';
import Config from '../../config';
export function getTxDetails(coin, txid, type) {
return new Promise((resolve, reject) => {
let payload = {
mode: null,
chain: coin,
cmd: 'gettransaction',
params: [
txid
],
};
if(type==='raw') {
payload = {
mode: null,
chain: coin,
cmd: 'getrawtransaction',
params: [
txid,
1
],
};
}
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ payload: payload })
},
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'getTransaction',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}

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

@ -1,7 +1,11 @@
import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../../translate/translate';
import { sortByDate } from '../../../util/sort';
import { toggleDashboardTxInfoModal } from '../../../actions/actionCreators';
import {
toggleDashboardTxInfoModal,
getTxDetails,
} from '../../../actions/actionCreators';
import Store from '../../../store';
import WalletsTxInfoRender from './walletsTxInfo.render';
@ -10,8 +14,12 @@ class WalletsTxInfo extends React.Component {
super();
this.state = {
activeTab: 0,
txDetails: null,
rawTxDetails: null,
};
this.toggleTxInfoModal = this.toggleTxInfoModal.bind(this);
this.loadTxDetails = this.loadTxDetails.bind(this);
this.loadRawTxDetails = this.loadRawTxDetails.bind(this);
}
toggleTxInfoModal() {
@ -22,6 +30,35 @@ class WalletsTxInfo extends React.Component {
}));
}
componentWillReceiveProps(nextProps) {
const texInfo = nextProps.ActiveCoin.txhistory[nextProps.ActiveCoin.showTransactionInfoTxIndex];
if (texInfo &&
this.props.ActiveCoin.showTransactionInfoTxIndex !== nextProps.ActiveCoin.showTransactionInfoTxIndex) {
this.loadTxDetails(nextProps.ActiveCoin.coin, texInfo.txid);
this.loadRawTxDetails(nextProps.ActiveCoin.coin, texInfo.txid);
}
}
loadTxDetails(coin, txid) {
getTxDetails(coin, txid)
.then((json) => {
this.setState(Object.assign({}, this.state, {
txDetails: json,
}));
});
}
loadRawTxDetails(coin, txid) {
getTxDetails(coin, txid, 'raw')
.then((json) => {
this.setState(Object.assign({}, this.state, {
rawTxDetails: json,
}));
});
}
openTab(tab) {
this.setState(Object.assign({}, this.state, {
activeTab: tab,
@ -34,6 +71,29 @@ class WalletsTxInfo extends React.Component {
}
}
openExplorerWindow(txid) {
const url = 'http://' + this.props.ActiveCoin.coin + '.explorer.supernet.org/tx/' + txid;
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,
webPreferences: {
"nodeIntegration": false
},
});
externalWindow.loadURL(url);
externalWindow.webContents.on('did-finish-load', function() {
setTimeout(function() {
externalWindow.show();
}, 40);
});
}
render() {
if (this.props &&
this.props.ActiveCoin.showTransactionInfo &&
@ -52,6 +112,7 @@ const mapStateToProps = (state) => {
return {
ActiveCoin: {
mode: state.ActiveCoin.mode,
coin: state.ActiveCoin.coin,
txhistory: state.ActiveCoin.txhistory,
showTransactionInfo: state.ActiveCoin.showTransactionInfo,
activeSection: state.ActiveCoin.activeSection,

200
react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js

@ -36,50 +36,93 @@ const WalletsTxInfoRender = function(txInfo) {
</li>
</ul>
<div className="panel-body">
<div className="tab-content">
{ this.state.activeTab === 0 &&
<div className="tab-pane active">
{ this.state.txDetails &&
<div className="tab-content">
{ this.state.activeTab === 0 &&
<div className="tab-pane active">
<table className="table table-striped">
<tbody>
<tr>
<td>{ translate('TX_INFO.ADDRESS') }</td>
<td>
{ txInfo.address }
</td>
</tr>
<tr>
<td>{ translate('TX_INFO.AMOUNT') }</td>
<td>
{ txInfo.amount }
</td>
</tr>
<tr>
<td>{ translate('TX_INFO.CATEGORY') }</td>
<td>
{ txInfo.category || txInfo.type }
</td>
</tr>
<tr>
<td>{ translate('TX_INFO.CONFIRMATIONS') }</td>
<td>
{ txInfo.confirmations }
</td>
</tr>
{ txInfo.blockhash &&
<tbody>
<tr>
<td>blockhash</td>
<td>{ translate('TX_INFO.ADDRESS') }</td>
<td>
{ txInfo.blockhash }
{ this.state.txDetails.details[0].address }
</td>
</tr>
}
{ (txInfo.blocktime || txInfo.timestamp) &&
<tr>
<td>blocktime</td>
<td>{ translate('TX_INFO.AMOUNT') }</td>
<td>
{ secondsToString(txInfo.blocktime || txInfo.timestamp) }
{ txInfo.amount }
</td>
</tr>
<tr>
<td>{ translate('TX_INFO.CATEGORY') }</td>
<td>
{ this.state.txDetails.details[0].category || txInfo.type }
</td>
</tr>
<tr>
<td>{ translate('TX_INFO.CONFIRMATIONS') }</td>
<td>
{ this.state.txDetails.confirmations }
</td>
</tr>
{ this.state.txDetails.blockindex &&
<tr>
<td>blockindex</td>
<td>
{ this.state.txDetails.blockindex }
</td>
</tr>
}
{ this.state.txDetails.blockhash &&
<tr>
<td>blockhash</td>
<td>
{ this.state.txDetails.blockhash }
</td>
</tr>
}
{ (this.state.txDetails.blocktime || this.state.txDetails.timestamp) &&
<tr>
<td>blocktime</td>
<td>
{ secondsToString(this.state.txDetails.blocktime || this.state.txDetails.timestamp) }
</td>
</tr>
}
<tr>
<td>txid</td>
<td>
{ this.state.txDetails.txid }
</td>
</tr>
<tr>
<td>walletconflicts</td>
<td>
{ this.state.txDetails.walletconflicts.length }
</td>
</tr>
<tr>
<td>time</td>
<td>
{ secondsToString(this.state.txDetails.time) }
</td>
</tr>
<tr>
<td>timereceived</td>
<td>
{ secondsToString(this.state.txDetails.timereceived) }
</td>
</tr>
</tbody>
</table>
</div>
}
{ this.state.activeTab === 1 &&
<div className="tab-pane active">
<table className="table table-striped">
<tbody>
}
<tr>
<td>txid</td>
@ -94,66 +137,55 @@ const WalletsTxInfoRender = function(txInfo) {
</td>
</tr>
<tr>
<td>time</td>
<td>vjoinsplit</td>
<td>
{ txInfo.time ? secondsToString(txInfo.time) : '' }
{ txInfo.vjoinsplit } // native
{ txInfo.time ? secondsToString(txInfo.time) : '' } // electrum
</td>
</tr>
<tr>
<td>timereceived</td>
<td>details</td>
<td>
{ txInfo.timereceived ? secondsToString(txInfo.timereceived) : '' }
{ txInfo.details } // native
{ txInfo.timereceived ? secondsToString(txInfo.timereceived) : '' } // electrum
</td>
</tr>
</tbody>
</table>
</div>
}
{ this.state.activeTab === 1 &&
<div className="tab-pane active">
<table className="table table-striped">
<tbody>
<tr>
<td>vjoinsplit</td>
<td>
{ txInfo.vjoinsplit }
</td>
</tr>
<tr>
<td>details</td>
<td>
{ txInfo.details }
</td>
</tr>
</tbody>
</table>
</div>
}
{ this.state.activeTab === 2 &&
<div className="tab-pane active">
<textarea
className="full-width height-170"
rows="10"
cols="80"
defaultValue={ txInfo.hex }
disabled></textarea>
</div>
}
{ this.state.activeTab === 3 &&
<div className="tab-pane active">
<textarea
className="full-width height-400"
rows="40"
cols="80"
defaultValue={ JSON.stringify(txInfo, null, '\t') }
disabled></textarea>
</div>
}
</div>
</tbody>
</table>
</div>
}
{ this.state.activeTab === 2 &&
<div className="tab-pane active">
<textarea
className="full-width height-170"
rows="10"
cols="80"
defaultValue={ txInfo.hex }
disabled></textarea>
</div>
}
{ this.state.activeTab === 3 &&
<div className="tab-pane active">
<textarea
className="full-width height-400"
rows="40"
cols="80"
defaultValue={ JSON.stringify(this.state.rawTxDetails, null, '\t') }
disabled></textarea>
</div>
}
</div>
}
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-sm white btn-info waves-effect waves-light pull-left"
onClick={ () => this.openExplorerWindow(txInfo.txid) }>
<i className="icon fa-external-link"></i> { translate('INDEX.OPEN_TRANSACTION_IN_EPLORER', this.props.ActiveCoin.coin) }
</button>
<button
type="button"
className="btn btn-default"

3
react/src/translate/en.js

@ -293,7 +293,8 @@ export const _lang = {
'CREATE_INVOICE_QR': 'Create Invoice QR Code',
'QR_CONTENT': 'QR Content',
'CHOOSE_RECEIVING_ADDRESS': 'Choose Address',
'SAVE_AS_IMAGE': 'Save as Image'
'SAVE_AS_IMAGE': 'Save as Image',
'OPEN_TRANSACTION_IN_EPLORER': 'Open transaction in @template@ Explorer',
},
'ATOMIC': {
'RAW_OUTPUT': 'Raw Output',

Loading…
Cancel
Save