From 394f34e46ffa586e093943cec86f1340c1abf548 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Sat, 22 Jul 2017 18:55:12 +0200 Subject: [PATCH 01/18] Transaction history improvements - WIP --- react/package.json | 1 + .../components/dashboard/main/dashboard.scss | 14 ++ .../walletsBalance/walletsBalance.js | 2 +- .../dashboard/walletsData/pagination.js | 45 +++++ .../walletsData/pagination.render.js | 103 ++++++++++ .../dashboard/walletsData/walletsData.js | 181 +++++++++--------- .../walletsData/walletsData.render.js | 173 ++++------------- react/src/styles/index.scss | 3 +- react/src/translate/en.js | 4 +- 9 files changed, 294 insertions(+), 232 deletions(-) create mode 100644 react/src/components/dashboard/walletsData/pagination.js create mode 100644 react/src/components/dashboard/walletsData/pagination.render.js diff --git a/react/package.json b/react/package.json index 81b81d2..3262370 100644 --- a/react/package.json +++ b/react/package.json @@ -45,6 +45,7 @@ "react-redux": "^5.0.3", "react-router": "^3.0.2", "react-router-redux": "^4.0.4", + "react-table": "~6.5.1", "react-transform-catch-errors": "^1.0.2", "react-transform-hmr": "^1.0.4", "redux": "^3.6.0", diff --git a/react/src/components/dashboard/main/dashboard.scss b/react/src/components/dashboard/main/dashboard.scss index 8dfc52c..638aa79 100755 --- a/react/src/components/dashboard/main/dashboard.scss +++ b/react/src/components/dashboard/main/dashboard.scss @@ -133,4 +133,18 @@ // walletsNativeTxInfo.js .height-170 { height: 170px; +} + +.rt-tr.-odd div, +.rt-tr.-even div { + padding-top: 2px; + padding-bottom: 2px; +} + +.rt-tr-group.-odd .-padRow { + display: none; +} + +.ReactTable .rt-tfoot .rt-td { + text-align: center; } \ No newline at end of file diff --git a/react/src/components/dashboard/walletsBalance/walletsBalance.js b/react/src/components/dashboard/walletsBalance/walletsBalance.js index b424460..c995b4d 100755 --- a/react/src/components/dashboard/walletsBalance/walletsBalance.js +++ b/react/src/components/dashboard/walletsBalance/walletsBalance.js @@ -95,7 +95,7 @@ class WalletsBalance extends React.Component { const _translationComponents = translate(_translationID).split('
'); return _translationComponents.map((_translation) => - + {_translation}
diff --git a/react/src/components/dashboard/walletsData/pagination.js b/react/src/components/dashboard/walletsData/pagination.js new file mode 100644 index 0000000..a3ff832 --- /dev/null +++ b/react/src/components/dashboard/walletsData/pagination.js @@ -0,0 +1,45 @@ +import React, { Component } from 'react'; +import PaginationRender from './pagination.render'; + +export default class TablePaginationRenderer extends Component { + constructor (props) { + super(); + + this.getSafePage = this.getSafePage.bind(this); + this.changePage = this.changePage.bind(this); + this.applyPage = this.applyPage.bind(this); + + this.state = { + page: props.page + } + } + + componentWillReceiveProps (nextProps) { + this.setState({ page: nextProps.page }); + } + + getSafePage (page) { + if (isNaN(page)) { + page = this.props.page; + } + return Math.min(Math.max(page, 0), this.props.pages - 1); + } + + changePage (page) { + page = this.getSafePage(page); + this.setState({ page }); + if (this.props.page !== page) { + this.props.onPageChange(page); + } + } + + applyPage (e) { + e && e.preventDefault(); + const page = this.state.page; + this.changePage(page === '' ? this.props.page : page); + } + + render () { + return PaginationRender.call(this); + } +} \ No newline at end of file diff --git a/react/src/components/dashboard/walletsData/pagination.render.js b/react/src/components/dashboard/walletsData/pagination.render.js new file mode 100644 index 0000000..2e930f0 --- /dev/null +++ b/react/src/components/dashboard/walletsData/pagination.render.js @@ -0,0 +1,103 @@ +import React from 'react'; +import classnames from 'classnames'; + +const defaultButton = props => + + +const PaginationRender = function() { + const { + // Computed + pages, + // Props + page, + showPageSizeOptions, + pageSizeOptions, + pageSize, + showPageJump, + canPrevious, + canNext, + onPageSizeChange, + className, + PreviousComponent = defaultButton, + NextComponent = defaultButton, + } = this.props; + + return ( +
+
+ { + if (!canPrevious) return; + this.changePage(page - 1) + }} + disabled={!canPrevious} + > + {this.props.previousText} + +
+
+ + {this.props.pageText}{' '} + {showPageJump + ? +
+ { + const val = e.target.value; + console.error('onchange', val); + this.changePage(val - 1); + }} + value={this.state.page === '' ? '' : this.state.page + 1} + onBlur={this.applyPage} + onKeyPress={e => { + if (e.which === 13 || e.keyCode === 13) { + this.applyPage(); + } + }} + /> +
+ : + + {page + 1} + }{' '} + {this.props.ofText}{' '} + {pages || 1} +
+ {showPageSizeOptions && + + + } +
+
+ { + if (!canNext) return; + this.changePage(page + 1) + }} + disabled={!canNext} + > + {this.props.nextText} + +
+
+ ) +}; + +export default PaginationRender; \ No newline at end of file diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index ce87f61..bd950af 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -20,13 +20,14 @@ import { } from '../../../actions/actionCreators'; import Store from '../../../store'; import { - PaginationItemRender, - PaginationItemsPerPageSelectorRender, - PaginationRender, + AddressTypeRender, + TransactionDetailRender, + AddressItemRender, TxHistoryListRender, AddressListRender, WalletsDataRender } from './walletsData.render'; +import { secondsToString } from '../../../util/time'; import { SocketProvider } from 'socket.io-react'; import io from 'socket.io-client'; @@ -46,8 +47,9 @@ class WalletsData extends React.Component { currentStackLength: 0, totalStackLength: 0, useCache: true, + itemsListColumns: this.generateItemsListColumns() }; - this.updateInput = this.updateInput.bind(this); + this.toggleBasiliskActionsMenu = this.toggleBasiliskActionsMenu.bind(this); this.basiliskRefreshAction = this.basiliskRefreshAction.bind(this); this.basiliskConnectionAction = this.basiliskConnectionAction.bind(this); @@ -79,6 +81,78 @@ class WalletsData extends React.Component { ); } + generateItemsListColumns() { + let columns = []; + + if (this.isNativeMode()) { + columns.push({ + Header: translate('INDEX.TYPE'), + Footer: translate('INDEX.TYPE'), + Cell: AddressTypeRender() + }); + } + + columns.push(...[ + { + id: 'direction', + Header: translate('INDEX.DIRECTION'), + Footer: translate('INDEX.DIRECTION'), + accessor: (tx) => this.renderTxType(tx.category || tx.type) + }, + { + Header: translate('INDEX.CONFIRMATIONS'), + Footer: translate('INDEX.CONFIRMATIONS'), + headerClassName: 'hidden-xs hidden-sm', + footerClassName: 'hidden-xs hidden-sm', + className: 'hidden-xs hidden-sm', + accessor: 'confirmations' + }, + { + id: 'amount', + Header: translate('INDEX.AMOUNT'), + Footer: translate('INDEX.AMOUNT'), + accessor: (tx) => tx.amount || translate('DASHBOARD.UNKNOWN') + }, + { + id: 'timestamp', + Header: translate('INDEX.TIME'), + Footer: translate('INDEX.TIME'), + accessor: (tx) => secondsToString(tx.blocktime || tx.timestamp || tx.time) + } + ]); + + if (this.isFullMode()) { + columns.push({ + Header: translate('INDEX.DEST_ADDRESS'), + Footer: translate('INDEX.DEST_ADDRESS'), + accessor: 'address' + }); + } + + if (this.isNativeMode()) { + columns.push({ + id: 'destination-address', + Header: translate('INDEX.DEST_ADDRESS'), + Footer: translate('INDEX.DEST_ADDRESS'), + accessor: (tx) => this.renderAddress(tx) + }); + } + + const txDetailColumnCssClasses = this.isBasiliskMode() ? 'hidden-xs hidden-sm text-center' : 'hidden-xs hidden-sm'; + + columns.push({ + id: 'tx-detail', + Header: translate('INDEX.TX_DETAIL'), + Footer: translate('INDEX.TX_DETAIL'), + headerClassName: txDetailColumnCssClasses, + footerClassName: txDetailColumnCssClasses, + className: txDetailColumnCssClasses, + Cell: props => TransactionDetailRender.call(this, props.index) + }); + + return columns; + } + handleClickOutside(e) { if (e.srcElement.className !== 'btn dropdown-toggle btn-info' && (e.srcElement.offsetParent && e.srcElement.offsetParent.className !== 'btn dropdown-toggle btn-info') && @@ -193,17 +267,6 @@ class WalletsData extends React.Component { Store.dispatch(displayNotariesModal(true)); } - updateInput(e) { - let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory); - historyToSplit = historyToSplit.slice(0, e.target.value); - - this.setState({ - [e.target.name]: e.target.value, - activePage: 1, - itemsList: historyToSplit, - }); - } - toggleTxInfoModal(display, txIndex) { Store.dispatch(toggleDashboardTxInfoModal(display, txIndex)); } @@ -223,14 +286,8 @@ class WalletsData extends React.Component { if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) { - let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory); - historyToSplit = historyToSplit.slice( - (this.state.activePage - 1) * this.state.itemsPerPage, - this.state.activePage * this.state.itemsPerPage - ); - this.setState(Object.assign({}, this.state, { - itemsList: historyToSplit, + itemsList: sortByDate(this.props.ActiveCoin.txhistory), })); } } @@ -245,58 +302,10 @@ class WalletsData extends React.Component { itemsList: 'loading', })); } - } - - updateCurrentPage(page) { - let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory); - historyToSplit = historyToSplit.slice( - (page - 1) * this.state.itemsPerPage, - page * this.state.itemsPerPage - ); - - this.setState(Object.assign({}, this.state, { - activePage: page, - itemsList: historyToSplit, - })); - } - - renderPaginationItems() { - let items = []; - - for (let i = 0; i < Math.ceil(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage); i++) { - items.push( - PaginationItemRender.call(this, i) - ); - } - return items; - } - - renderPaginationItemsPerPageSelector() { - if (this.props.ActiveCoin.txhistory && - this.state.itemsList !== 'loading' && - this.props.ActiveCoin.txhistory.length > 10) { - return PaginationItemsPerPageSelectorRender.call(this); - } else { - return null; - } - } - - renderPagination() { - if (this.props.ActiveCoin.txhistory && - this.state.itemsList !== 'loading' && - this.props.ActiveCoin.txhistory.length > 10) { - const _paginationFrom = ((this.state.activePage - 1) * this.state.itemsPerPage) + 1; - const _paginationTo = this.state.activePage * this.state.itemsPerPage; - - return PaginationRender.call( - this, - _paginationFrom, - _paginationTo - ); - } else { - return null; - } + this.setState({ + itemsListColumns: this.generateItemsListColumns() + }); } renderTxType(category) { @@ -362,19 +371,9 @@ class WalletsData extends React.Component { return (
{ translate('INDEX.NO_DATA') }
); - } else { - if (this.state.itemsList && - this.state.itemsList.length && - this.state.itemsList !== 'no data') { - return this.state.itemsList.map((tx, index) => - TxHistoryListRender.call( - this, - tx, - index - ) - ); - } } + + return TxHistoryListRender.call(this); } updateAddressSelection(address, type, amount) { @@ -444,13 +443,7 @@ class WalletsData extends React.Component { } items.push( -
  • - this.updateAddressSelection(address, type, _amount) }> -    - [ { _amount } { _coin } ]  { address } - - -
  • + AddressItemRender.call(this, address, type, _amount, _coin) ); } @@ -479,9 +472,7 @@ class WalletsData extends React.Component { return _addresses.public[i].amount; } else { const address = _addresses.public[i].address; - const _amount = _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A'; - - return _amount; + return _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A'; } } } diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 237a3c2..5c7345a 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -4,102 +4,41 @@ import WalletsBasiliskRefresh from '../walletsBasiliskRefresh/walletsBasiliskRef import WalletsBasiliskConnection from '../walletsBasiliskConnection/walletsBasiliskConnection'; import WalletsNotariesList from '../walletsNotariesList/walletsNotariesList'; import WalletsCacheData from '../walletsCacheData/walletsCacheData'; -import { secondsToString } from '../../../util/time'; +import ReactTable from 'react-table'; +import TablePaginationRenderer from './pagination'; // TODO: clean basilisk dropdown menu -export const PaginationItemRender = function(i) { +export const AddressTypeRender = function() { return ( -
  • - this.updateCurrentPage(i + 1) : null }>{ i + 1 } -
  • + + + { translate('IAPI.PUBLIC_SM') } + + ); }; -export const PaginationItemsPerPageSelectorRender = function() { +export const TransactionDetailRender = function(transactionIndex) { return ( -
    - -
    + ); }; -export const PaginationRender = function(paginationFrom, paginationTo) { - const disableNextBtn = this.state.activePage >= Math.floor(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage); - +export const AddressItemRender = function(address, type, amount, coin) { return ( -
    -
    -
    - { translate('INDEX.SHOWING') }  - { paginationFrom }  - { translate('INDEX.TO_ALT') }  - { paginationTo }  - { translate('INDEX.OF') }  - { this.props.ActiveCoin.txhistory.length }  - { translate('INDEX.ENTRIES_SM') } -
    -
    -
    -
    - -
    -
    -
    - ); -}; - -export const TxHistoryListRender = function(tx, index) { - return ( - - { this.isNativeMode() ? - - - { translate('IAPI.PUBLIC_SM') } - - - : - null - } - { this.renderTxType(tx.category || tx.type) } - { tx.confirmations } - { tx.amount || translate('DASHBOARD.UNKNOWN') } - { secondsToString(tx.blocktime || tx.timestamp || tx.time) } - { tx.address } - { this.renderAddress(tx) } - - - - +
  • + this.updateAddressSelection(address, type, amount) }> +    + [ { amount } { coin } ]  { address } + + +
  • ); }; @@ -128,6 +67,21 @@ export const AddressListRender = function() { ); }; +export const TxHistoryListRender = function() { + return ( + + ); +}; + export const WalletsDataRender = function() { return ( @@ -210,58 +164,9 @@ export const WalletsDataRender = function() { { this.renderAddressList() } -
    -
    - { this.renderPaginationItemsPerPageSelector() } -
    -
    -
    - -
    -
    -
    - - - - { this.isNativeMode() ? - - : - null - } - - - - - - - - - - { this.renderTxHistoryList() } - - - - { this.isNativeMode() ? - - : - null - } - - - - - - - - -
    { translate('INDEX.TYPE') }{ translate('INDEX.DIRECTION') }{ translate('INDEX.CONFIRMATIONS') }{ translate('INDEX.AMOUNT') }{ translate('INDEX.TIME') }{ translate('INDEX.DEST_ADDRESS') }{ translate('INDEX.TX_DETAIL') }
    { translate('INDEX.TYPE') }{ translate('INDEX.DIRECTION') }{ translate('INDEX.CONFIRMATIONS') }{ translate('INDEX.AMOUNT') }{ translate('INDEX.TIME') }{ translate('INDEX.DEST_ADDRESS') }{ translate('INDEX.TX_DETAIL') }
    + { this.renderTxHistoryList() }
    - { this.renderPagination() } diff --git a/react/src/styles/index.scss b/react/src/styles/index.scss index 84c0948..b8589ce 100644 --- a/react/src/styles/index.scss +++ b/react/src/styles/index.scss @@ -33,4 +33,5 @@ @import '../components/addcoin/addcoin.scss'; @import '../components/dashboard/main/dashboard.scss'; @import '../components/login/login.scss'; -@import '../components/overrides.scss'; \ No newline at end of file +@import '../components/overrides.scss'; +@import '~react-table/react-table.css'; diff --git a/react/src/translate/en.js b/react/src/translate/en.js index 8a47b93..bc8fe39 100644 --- a/react/src/translate/en.js +++ b/react/src/translate/en.js @@ -249,7 +249,9 @@ export const _lang = { 'INFO': 'Info', 'ENTER': 'Enter', 'ADDR_SM': 'address', - 'ACTIVATING': 'Activating' + 'ACTIVATING': 'Activating', + 'NEXT_PAGE': 'Next Page', + 'PREVIOUS_PAGE': 'Previous Page' }, 'ATOMIC': { 'RAW_OUTPUT': 'Raw Output', From b11c955cc9d7a93cae0707120e30464e73d9f434 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Sat, 22 Jul 2017 19:04:46 +0200 Subject: [PATCH 02/18] Initialize itemsList to an empty array --- react/src/components/dashboard/walletsData/walletsData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index bd950af..2f59532 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -41,7 +41,7 @@ class WalletsData extends React.Component { basiliskActionsMenu: false, itemsPerPage: 10, activePage: 1, - itemsList: null, + itemsList: [], currentAddress: null, addressSelectorOpen: false, currentStackLength: 0, From 294af7a09c2d68fcc375ef0ec06f3f27d977da57 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Sun, 23 Jul 2017 18:40:44 +0200 Subject: [PATCH 03/18] Transaction history improvements - visual improvements --- .../components/dashboard/main/dashboard.scss | 18 ++++++++ .../walletsData/pagination.render.js | 1 - .../dashboard/walletsData/walletsData.js | 43 +------------------ .../walletsData/walletsData.render.js | 41 ++++++++++++++++++ 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/react/src/components/dashboard/main/dashboard.scss b/react/src/components/dashboard/main/dashboard.scss index 638aa79..0df5362 100755 --- a/react/src/components/dashboard/main/dashboard.scss +++ b/react/src/components/dashboard/main/dashboard.scss @@ -147,4 +147,22 @@ .ReactTable .rt-tfoot .rt-td { text-align: center; +} + +.ReactTable .rt-thead .rt-th.-sort-asc, +.ReactTable .rt-thead .rt-td.-sort-asc, +.ReactTable .rt-thead .rt-th.-sort-desc, +.ReactTable .rt-thead .rt-td.-sort-desc{ + box-shadow: none; +} + +.ReactTable .rt-thead .rt-th.-sort-asc div:nth-child(1):after { + font-family: FontAwesome; + padding-left: 5px; + content: "\f106"; +} +.ReactTable .rt-thead .rt-th.-sort-desc div:nth-child(1):after { + font-family: FontAwesome; + padding-left: 5px; + content: "\f107"; } \ No newline at end of file diff --git a/react/src/components/dashboard/walletsData/pagination.render.js b/react/src/components/dashboard/walletsData/pagination.render.js index 2e930f0..f90af8a 100644 --- a/react/src/components/dashboard/walletsData/pagination.render.js +++ b/react/src/components/dashboard/walletsData/pagination.render.js @@ -50,7 +50,6 @@ const PaginationRender = function() { type={this.state.page === '' ? 'text' : 'number'} onChange={e => { const val = e.target.value; - console.error('onchange', val); this.changePage(val - 1); }} value={this.state.page === '' ? '' : this.state.page + 1} diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 2f59532..11384d9 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -23,6 +23,7 @@ import { AddressTypeRender, TransactionDetailRender, AddressItemRender, + TxTypeRender, TxHistoryListRender, AddressListRender, WalletsDataRender @@ -97,7 +98,7 @@ class WalletsData extends React.Component { id: 'direction', Header: translate('INDEX.DIRECTION'), Footer: translate('INDEX.DIRECTION'), - accessor: (tx) => this.renderTxType(tx.category || tx.type) + accessor: (tx) => TxTypeRender.call(this, tx.category || tx.type) }, { Header: translate('INDEX.CONFIRMATIONS'), @@ -308,46 +309,6 @@ class WalletsData extends React.Component { }); } - renderTxType(category) { - if (category === 'send' || - category === 'sent') { - return ( - - { translate('DASHBOARD.OUT') } - - ); - } - if (category === 'receive' || - category === 'received') { - return ( - - { translate('DASHBOARD.IN') } - - ); - } - if (category === 'generate') { - return ( - - { translate('DASHBOARD.MINED') } - - ); - } - if (category === 'immature') { - return ( - - { translate('DASHBOARD.IMMATURE') } - - ); - } - if (category === 'unknown') { - return ( - - { translate('DASHBOARD.UNKNOWN') } - - ); - } - } - isFullySynced() { if (this.props.Dashboard.progress && (Number(this.props.Dashboard.progress.balances) + diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 5c7345a..c9d8cb8 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -67,6 +67,46 @@ export const AddressListRender = function() { ); }; +export const TxTypeRender = function(category) { + if (category === 'send' || + category === 'sent') { + return ( + + { translate('DASHBOARD.OUT') } + + ); + } + if (category === 'receive' || + category === 'received') { + return ( + + { translate('DASHBOARD.IN') } + + ); + } + if (category === 'generate') { + return ( + + { translate('DASHBOARD.MINED') } + + ); + } + if (category === 'immature') { + return ( + + { translate('DASHBOARD.IMMATURE') } + + ); + } + if (category === 'unknown') { + return ( + + { translate('DASHBOARD.UNKNOWN') } + + ); + } +}; + export const TxHistoryListRender = function() { return ( From 8124d9ade1bfcbaaa87860becc9f16559176fe71 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Mon, 24 Jul 2017 21:35:05 +0200 Subject: [PATCH 04/18] Transaction history improvements - visual improvements --- .../dashboard/walletsData/walletsData.js | 41 ++++++++----------- .../walletsData/walletsData.render.js | 17 +++++++- 2 files changed, 32 insertions(+), 26 deletions(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 11384d9..e279bd4 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -22,6 +22,7 @@ import Store from '../../../store'; import { AddressTypeRender, TransactionDetailRender, + AddressRender, AddressItemRender, TxTypeRender, TxHistoryListRender, @@ -40,8 +41,6 @@ class WalletsData extends React.Component { super(props); this.state = { basiliskActionsMenu: false, - itemsPerPage: 10, - activePage: 1, itemsList: [], currentAddress: null, addressSelectorOpen: false, @@ -80,6 +79,7 @@ class WalletsData extends React.Component { this.handleClickOutside, false ); + socket.off('messages'); } generateItemsListColumns() { @@ -135,7 +135,7 @@ class WalletsData extends React.Component { id: 'destination-address', Header: translate('INDEX.DEST_ADDRESS'), Footer: translate('INDEX.DEST_ADDRESS'), - accessor: (tx) => this.renderAddress(tx) + accessor: (tx) => AddressRender.call(this, tx) }); } @@ -332,18 +332,19 @@ class WalletsData extends React.Component { return (
    { translate('INDEX.NO_DATA') }
    ); + } else if (this.state.itemsList) { + return TxHistoryListRender.call(this); } - return TxHistoryListRender.call(this); + return null; } - updateAddressSelection(address, type, amount) { + updateAddressSelection(address) { Store.dispatch(changeActiveAddress(address)); this.setState(Object.assign({}, this.state, { currentAddress: address, addressSelectorOpen: false, - activePage: 1, })); if (this.props.ActiveCoin.mode === 'basilisk') { @@ -373,27 +374,15 @@ class WalletsData extends React.Component { })); } - renderAddress(tx) { - if (!tx.address) { - return ( - - { translate('DASHBOARD.ZADDR_NOT_LISTED') } - - ); - } - - return tx.address; - } - renderAddressByType(type) { const _addresses = this.props.ActiveCoin.addresses; + const _coin = this.props.ActiveCoin.coin; if (_addresses && _addresses[type] && _addresses[type].length) { let items = []; const _cache = this.props.ActiveCoin.cache; - const _coin = this.props.ActiveCoin.coin; for (let i = 0; i < _addresses[type].length; i++) { const address = _addresses[type][i].address; @@ -409,19 +398,22 @@ class WalletsData extends React.Component { } return items; - } else { - return null; + } else if (this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]) { + const address = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]; + return AddressItemRender.call(this, address, type, null, _coin); } + + return null; } - hasPublicAdresses() { + hasPublicAddresses() { return this.props.ActiveCoin.addresses && this.props.ActiveCoin.addresses.public && this.props.ActiveCoin.addresses.public.length; } renderAddressAmount() { - if (this.hasPublicAdresses()) { + if (this.hasPublicAddresses()) { const _addresses = this.props.ActiveCoin.addresses; const _cache = this.props.ActiveCoin.cache; const _coin = this.props.ActiveCoin.coin; @@ -463,8 +455,7 @@ class WalletsData extends React.Component { renderAddressList() { if (this.props.Dashboard && this.props.Dashboard.activeHandle && - this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] && - this.props.ActiveCoin.mode === 'basilisk') { + this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]) { return AddressListRender.call(this); } else { return null; diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index c9d8cb8..e0e6ec4 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -30,10 +30,25 @@ export const TransactionDetailRender = function(transactionIndex) { ); }; +export const AddressRender = function(tx) { + if (!tx.address) { + return ( + + + + { translate('DASHBOARD.ZADDR_NOT_LISTED') } + + + ); + } + + return tx.address; +}; + export const AddressItemRender = function(address, type, amount, coin) { return (
  • - this.updateAddressSelection(address, type, amount) }> + this.updateAddressSelection(address) }>    [ { amount } { coin } ]  { address } From 228ef080106d4259659dcf565f47026785944fd4 Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Mon, 24 Jul 2017 21:48:09 +0200 Subject: [PATCH 05/18] Transaction history improvements - validate if itemsList has elements --- react/src/components/dashboard/walletsData/walletsData.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index e279bd4..7596576 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -332,7 +332,7 @@ class WalletsData extends React.Component { return (
    { translate('INDEX.NO_DATA') }
    ); - } else if (this.state.itemsList) { + } else if (this.state.itemsList && this.state.itemsList.length) { return TxHistoryListRender.call(this); } From caaf0ea767332914fcc20dedc3c8d8f13888f9cb Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Wed, 26 Jul 2017 22:52:35 +0200 Subject: [PATCH 06/18] Merge branch 'redux' into 'tx-history-improvements' --- .../components/dashboard/walletsData/walletsData.js | 3 ++- .../dashboard/walletsData/walletsData.render.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index ee734f8..43508bc 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -26,6 +26,7 @@ import { AddressRender, AddressItemRender, TxTypeRender, + TxAmountRender, TxHistoryListRender, AddressListRender, WalletsDataRender @@ -113,7 +114,7 @@ class WalletsData extends React.Component { id: 'amount', Header: translate('INDEX.AMOUNT'), Footer: translate('INDEX.AMOUNT'), - accessor: (tx) => tx.amount || translate('DASHBOARD.UNKNOWN') + accessor: (tx) => TxAmountRender.call(this, tx) }, { id: 'timestamp', diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 78d6bbf..63db3df 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -132,6 +132,18 @@ export const TxTypeRender = function(category) { } }; +export const TxAmountRender = function (tx) { + if (Config.roundValues) { + return ( + { formatValue('round', tx.amount, -6) || translate('DASHBOARD.UNKNOWN') } + ); + } + + return ( + { tx.amount || translate('DASHBOARD.UNKNOWN') } + ); +}; + export const TxHistoryListRender = function() { return ( Date: Thu, 3 Aug 2017 00:02:54 +0200 Subject: [PATCH 07/18] TX History improvements - remarks fixes --- .../components/dashboard/main/dashboard.scss | 10 ++++++++++ .../dashboard/walletsData/walletsData.js | 18 ++++++++++++++---- .../walletsData/walletsData.render.js | 6 ++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/react/src/components/dashboard/main/dashboard.scss b/react/src/components/dashboard/main/dashboard.scss index 0df5362..3309f01 100755 --- a/react/src/components/dashboard/main/dashboard.scss +++ b/react/src/components/dashboard/main/dashboard.scss @@ -165,4 +165,14 @@ font-family: FontAwesome; padding-left: 5px; content: "\f107"; +} + +.rt-tr.-padRow { + display: none; +} + +.ReactTable .-pagination, +.ReactTable .rt-thead.-header, +.ReactTable .rt-tfoot{ + box-shadow: none; } \ No newline at end of file diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 30755a6..d311c4f 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -51,7 +51,9 @@ class WalletsData extends React.Component { currentStackLength: 0, totalStackLength: 0, useCache: true, - itemsListColumns: this.generateItemsListColumns() + itemsListColumns: this.generateItemsListColumns(), + pageSize: 20, + showPagination: false }; this.toggleBasiliskActionsMenu = this.toggleBasiliskActionsMenu.bind(this); @@ -317,7 +319,8 @@ class WalletsData extends React.Component { (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) { this.setState(Object.assign({}, this.state, { - itemsList: sortByDate(this.props.ActiveCoin.txhistory), + itemsList: sortByDate(this.props.ActiveCoin.txhistory.slice(0, 30)), + showPagination: this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length >= this.state.pageSize })); } } @@ -360,19 +363,26 @@ class WalletsData extends React.Component { ); } - } else if (this.state.itemsList === 'no data') { + } else if (this.state.itemsList === 'no data' || this.state.itemsList.length == 0) { return ( { translate('INDEX.NO_DATA') } ); - } else if (this.state.itemsList && this.state.itemsList.length) { + } else if (this.state.itemsList) { return TxHistoryListRender.call(this); } return null; } + onPageSizeChange(pageSize, pageIndex) { + this.setState(Object.assign({}, this.state, { + pageSize: pageSize, + showPagination: this.state.itemsList && this.state.itemsList.length >= pageSize + })) + } + updateAddressSelection(address) { Store.dispatch(changeActiveAddress(address)); diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 2570602..bb8fb44 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -150,12 +150,14 @@ export const TxHistoryListRender = function() { data={this.state.itemsList} columns={this.state.itemsListColumns} sortable={true} - filterable={true} className='-striped -highlight' PaginationComponent={TablePaginationRenderer} - showPaginationTop={true} nextText={translate('INDEX.NEXT_PAGE')} previousText={translate('INDEX.PREVIOUS_PAGE')} + showPaginationBottom={this.state.showPagination} + showPaginationTop={this.state.showPagination} + pageSize={this.pageSize} + onPageSizeChange={(pageSize, pageIndex) => this.onPageSizeChange(pageSize, pageIndex)} /> ); }; From 9f90e54bc19df49701aa125d7e96ced93dba9f8d Mon Sep 17 00:00:00 2001 From: petitPapillon Date: Thu, 3 Aug 2017 22:29:52 +0200 Subject: [PATCH 08/18] Address list component - add padding --- .../src/components/dashboard/walletsData/walletsData.render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index bb8fb44..3b05f0f 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -243,7 +243,7 @@ export const WalletsDataRender = function() {
    -
    +
    { this.renderAddressList() }
    From b99e8d2a0866068e91abce13a9e77c798f12dc8b Mon Sep 17 00:00:00 2001 From: Ivana Trajanovska Date: Mon, 7 Aug 2017 19:04:31 +0200 Subject: [PATCH 09/18] Tx list - add a global filter --- .../dashboard/walletsData/walletsData.js | 47 ++++++++++++++++--- .../walletsData/walletsData.render.js | 21 ++++++--- .../walletsTxInfo/walletsTxInfo.render.js | 2 +- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index d311c4f..71c7b7e 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -46,6 +46,7 @@ class WalletsData extends React.Component { this.state = { basiliskActionsMenu: false, itemsList: [], + filteredItemsList: [], currentAddress: null, addressSelectorOpen: false, currentStackLength: 0, @@ -53,7 +54,8 @@ class WalletsData extends React.Component { useCache: true, itemsListColumns: this.generateItemsListColumns(), pageSize: 20, - showPagination: false + showPagination: false, + searchTerm: null }; this.toggleBasiliskActionsMenu = this.toggleBasiliskActionsMenu.bind(this); @@ -318,8 +320,10 @@ class WalletsData extends React.Component { if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) { - this.setState(Object.assign({}, this.state, { - itemsList: sortByDate(this.props.ActiveCoin.txhistory.slice(0, 30)), + const sortedItemsList = sortByDate(this.props.ActiveCoin.txhistory); + this.setState(Object.assign({}, this.state, { + itemsList: sortedItemsList, + filteredItemsList: this.filterTransactions(sortedItemsList, this.state.searchTerm), showPagination: this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length >= this.state.pageSize })); } @@ -502,16 +506,47 @@ class WalletsData extends React.Component { } } - renderAddressList() { - if (this.props.Dashboard && + shouldDisplayAddressList() { + return this.props.Dashboard && this.props.Dashboard.activeHandle && - this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]) { + this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]; + } + + renderAddressList() { + if (this.shouldDisplayAddressList()) { return AddressListRender.call(this); } else { return null; } } + onSearchTermChange(newSearchTerm) { + this.setState(Object.assign({}, this.state, { + searchTerm: newSearchTerm, + filteredItemsList: this.filterTransactions(this.state.itemsList, newSearchTerm) + })); + } + + filterTransactions(txList, searchTerm) { + return txList.filter(tx => this.filterTransaction(tx, searchTerm)); + } + + filterTransaction(tx, term) { + if (!term) { + return true; + } + + return this.contains(tx.address, term) + || this.contains(tx.confirmations, term) + || this.contains(tx.amount, term) + || this.contains(tx.type, term) + || this.contains(secondsToString(tx.blocktime || tx.timestamp || tx.time), term); + } + + contains(value, property) { + return (value + "").indexOf(property) !== -1; + } + isActiveCoinMode(coinMode) { return this.props.ActiveCoin.mode === coinMode; } diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 3b05f0f..cca31dd 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -147,7 +147,7 @@ export const TxAmountRender = function (tx) { export const TxHistoryListRender = function() { return ( -

    { translate('INDEX.TRANSACTION_HISTORY') }

    +

    { translate('INDEX.TRANSACTION_HISTORY') }

    -
    -
    -
    - { this.renderAddressList() } +
    +
    + {this.shouldDisplayAddressList() && +
    + {this.renderAddressList()} +
    + } +
    + this.onSearchTermChange(e.target.value)} + placeholder='Search' />
    -
    +
    { this.renderTxHistoryList() }
    diff --git a/react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js b/react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js index 7b9643b..955d324 100644 --- a/react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js +++ b/react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js @@ -95,7 +95,7 @@ const WalletsTxInfoRender = function(txInfo) { walletconflicts - { txInfo.walletconflicts.length } + { txInfo.walletconflicts ? txInfo.walletconflicts.length : null } } From c8ef1ace7adea8a7cb9253789d447adb1c834f7c Mon Sep 17 00:00:00 2001 From: Ivana Trajanovska Date: Mon, 7 Aug 2017 19:57:53 +0200 Subject: [PATCH 10/18] Fixes after merge --- react/src/components/dashboard/walletsData/walletsData.js | 4 ++-- .../components/dashboard/walletsData/walletsData.render.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 3343813..6497156 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -55,9 +55,9 @@ class WalletsData extends React.Component { itemsListColumns: this.generateItemsListColumns(), pageSize: 20, showPagination: false, - searchTerm: null + searchTerm: null, coin: null, - txhistory: null, + txhistory: null }; this.toggleBasiliskActionsMenu = this.toggleBasiliskActionsMenu.bind(this); diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 333cb8e..121c21b 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -49,7 +49,8 @@ export const AddressRender = function(tx) { export const AddressItemRender = function(address, type, amount, coin) { return ( -
  • +
  • this.updateAddressSelection(address) }>    [ { amount } { coin } ]  { address } From c1d156ab76ca96a2f86d02e7ba3d4fe3a23cdd49 Mon Sep 17 00:00:00 2001 From: Ivana Trajanovska Date: Mon, 7 Aug 2017 20:35:17 +0200 Subject: [PATCH 11/18] Fixes after merge --- .../components/dashboard/walletsData/walletsData.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 6497156..b5fcd8b 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -345,13 +345,15 @@ class WalletsData extends React.Component { this.props.ActiveCoin.txhistory !== 'loading' && this.props.ActiveCoin.txhistory !== 'no data' && this.props.ActiveCoin.txhistory.length) { - if (!this.state.itemsList || - (this.state.itemsList && !this.state.itemsList.length) || - (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) { - const sortedItemsList = sortByDate(this.props.ActiveCoin.txhistory); + if (!this.state.itemsList || + (this.state.coin && this.state.coin !== this.props.ActiveCoin.coin) || + (JSON.stringify(this.props.ActiveCoin.txhistory) !== JSON.stringify(this.state.txhistory))) { + const sortedItemsList = this.indexTxHistory(sortByDate(this.props.ActiveCoin.txhistory, this.props.ActiveCoin.mode === 'basilisk' ? 'index' : 'confirmations')); + this.setState(Object.assign({}, this.state, { itemsList: sortedItemsList, filteredItemsList: this.filterTransactions(sortedItemsList, this.state.searchTerm), + txhistory: this.props.ActiveCoin.txhistory, showPagination: this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length >= this.state.pageSize })); } From 9a07e920aee2804804b5cbdfd7245f44bc312452 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Thu, 17 Aug 2017 14:05:24 +0300 Subject: [PATCH 12/18] basilisk progress bar reposition to block header --- .../walletsData/walletsData.render.js | 22 ++++++++++--------- .../dashboard/walletsNav/walletsNav.render.js | 2 +- react/src/components/overrides.scss | 14 ++++++++++++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 9c19aa6..792db46 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -176,18 +176,20 @@ export const WalletsDataRender = function() {
    + { this.props.ActiveCoin.mode === 'basilisk' && +
    +
    + { translate('SEND.PROCESSING_REQ') }: { this.state.currentStackLength } / { this.state.totalStackLength } +
    +
    + }
    - +
    -
    -
    - { translate('SEND.PROCESSING_REQ') }: { this.state.currentStackLength } / { this.state.totalStackLength } -
    -
    { !this.isNativeMode() ?
    -
      +
        { translate('INDEX.MY') } { this.props && this.props.ActiveCoin ? this.props.ActiveCoin.coin : '-' } { translate('INDEX.ADDRESS') }: { this.props && this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : '-' } @@ -72,7 +75,9 @@ const PaginationRender = function() { value={pageSize}> { pageSizeOptions.map((option, i) => { return ( - ); @@ -85,7 +90,7 @@ const PaginationRender = function() { { if (!canNext) return; - this.changePage(page + 1) + this.changePage(page + 1); }} disabled={!canNext}> {this.props.nextText} diff --git a/react/src/components/dashboard/walletsData/walletsData.js b/react/src/components/dashboard/walletsData/walletsData.js index 2480162..43c0e1d 100644 --- a/react/src/components/dashboard/walletsData/walletsData.js +++ b/react/src/components/dashboard/walletsData/walletsData.js @@ -53,8 +53,9 @@ class WalletsData extends React.Component { totalStackLength: 0, useCache: true, itemsListColumns: this.generateItemsListColumns(), + defaultPageSize: 10, pageSize: 10, - showPagination: false, + showPagination: true, searchTerm: null, coin: null, txhistory: null @@ -108,6 +109,9 @@ class WalletsData extends React.Component { columns.push({ Header: translate('INDEX.TYPE'), Footer: translate('INDEX.TYPE'), + className: 'colum--type', + headerClassName: 'colum--type', + footerClassName: 'colum--type', Cell: AddressTypeRender() }); } @@ -329,7 +333,7 @@ class WalletsData extends React.Component { indexTxHistory(txhistoryArr) { if (txhistoryArr.length > 1) { for (let i = 0; i < txhistoryArr.length; i++) { - this.props.ActiveCoin.txhistory[i]['index'] = i + 1; + this.props.ActiveCoin.txhistory[i].index = i + 1; } } @@ -338,7 +342,8 @@ class WalletsData extends React.Component { componentWillReceiveProps(props) { if (!this.state.currentAddress && - this.props.ActiveCoin.activeAddress) { + this.props.ActiveCoin.activeAddress && + this.props.ActiveCoin.mode === 'basilisk') { this.setState(Object.assign({}, this.state, { currentAddress: this.props.ActiveCoin.activeAddress, })); @@ -357,7 +362,7 @@ class WalletsData extends React.Component { itemsList: sortedItemsList, filteredItemsList: this.filterTransactions(sortedItemsList, this.state.searchTerm), txhistory: this.props.ActiveCoin.txhistory, - showPagination: this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length >= this.state.pageSize + showPagination: this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length >= this.state.defaultPageSize })); } } @@ -392,7 +397,8 @@ class WalletsData extends React.Component { // TODO: add basilisk first run check, display no data if second run renderTxHistoryList() { - if (this.state.itemsList === 'loading' || this.state.itemsList.length == 0) { + if (this.state.itemsList === 'loading' || + this.state.itemsList.length == 0) { if (this.isFullySynced()) { return ( @@ -422,7 +428,7 @@ class WalletsData extends React.Component { onPageSizeChange(pageSize, pageIndex) { this.setState(Object.assign({}, this.state, { pageSize: pageSize, - showPagination: this.state.itemsList && this.state.itemsList.length >= pageSize, + showPagination: this.state.itemsList && this.state.itemsList.length >= defaultPageSize, })) } @@ -473,7 +479,7 @@ class WalletsData extends React.Component { for (let i = 0; i < _addresses[type].length; i++) { const address = _addresses[type][i].address; - let _amount = address.amount; + let _amount = _addresses[type][i].amount; if (this.props.ActiveCoin.mode === 'basilisk') { _amount = _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A'; @@ -489,8 +495,9 @@ class WalletsData extends React.Component { } return items; - } else if (this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]) { + } else if (this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] && this.props.ActiveCoin.mode === 'basilisk') { const address = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]; + return AddressItemRender.call(this, address, type, null, _coin); } @@ -522,7 +529,13 @@ class WalletsData extends React.Component { return _amount; } else { const address = _addresses.public[i].address; - let _amount = _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A'; + let _amount; + + if (this.props.ActiveCoin.mode === 'basilisk') { + _amount = _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A'; + } else { + _amount = _addresses.public[i].amount; + } if (_amount !== 'N/A') { _amount = formatValue('round', _amount, -6); @@ -550,16 +563,17 @@ class WalletsData extends React.Component { ); } else { return ( - - { translate('KMD_NATIVE.SELECT_ADDRESS') } - + Filter by address ); } } shouldDisplayAddressList() { - //return true; - return this.props.Dashboard && + if (this.props.ActiveCoin.mode === 'basilisk') { + return this.props.Dashboard && this.props.Dashboard.activeHandle && this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]; + } } renderAddressList() { @@ -594,7 +608,7 @@ class WalletsData extends React.Component { } contains(value, property) { - return (value + "").indexOf(property) !== -1; + return (value + '').indexOf(property) !== -1; } isActiveCoinMode(coinMode) { diff --git a/react/src/components/dashboard/walletsData/walletsData.render.js b/react/src/components/dashboard/walletsData/walletsData.render.js index 792db46..51f0f8a 100644 --- a/react/src/components/dashboard/walletsData/walletsData.render.js +++ b/react/src/components/dashboard/walletsData/walletsData.render.js @@ -9,8 +9,6 @@ import TablePaginationRenderer from './pagination'; import { formatValue } from '../../../util/formatValue'; import Config from '../../../config'; -// TODO: clean basilisk dropdown menu - export const AddressTypeRender = function() { return ( @@ -72,7 +70,7 @@ export const AddressListRender = function() { @@ -96,7 +102,7 @@ export const AddressListRender = function() { export const TxTypeRender = function(category) { if (category === 'send' || - category === 'sent') { + category === 'sent') { return ( { translate('DASHBOARD.OUT') } @@ -104,10 +110,10 @@ export const TxTypeRender = function(category) { ); } if (category === 'receive' || - category === 'received') { + category === 'received') { return ( - { translate('DASHBOARD.IN') } + { translate('DASHBOARD.IN') }     ); } @@ -134,32 +140,43 @@ export const TxTypeRender = function(category) { } }; -export const TxAmountRender = function (tx) { +export const TxAmountRender = function(tx) { + let _amountNegative; + + if ((tx.category === 'send' || + tx.category === 'sent') || + (tx.type === 'send' || + tx.type === 'sent')) { + _amountNegative = -1; + } else { + _amountNegative = 1; + } + if (Config.roundValues) { return ( - { formatValue('round', tx.amount, -6) || translate('DASHBOARD.UNKNOWN') } + { formatValue('round', tx.amount, -6) * _amountNegative || translate('DASHBOARD.UNKNOWN') } ); } return ( - { tx.amount || translate('DASHBOARD.UNKNOWN') } + { tx.amount * _amountNegative || translate('DASHBOARD.UNKNOWN') } ); }; export const TxHistoryListRender = function() { return ( this.onPageSizeChange(pageSize, pageIndex)} /> + PaginationComponent={ TablePaginationRenderer } + nextText={ translate('INDEX.NEXT_PAGE') } + previousText={ translate('INDEX.PREVIOUS_PAGE') } + showPaginationBottom={ this.state.showPagination } + pageSize={ this.pageSize } + onPageSizeChange={ (pageSize, pageIndex) => this.onPageSizeChange(pageSize, pageIndex) } /> ); }; @@ -245,16 +262,16 @@ export const WalletsDataRender = function() {

        { translate('INDEX.TRANSACTION_HISTORY') }

    -
    +
    { this.shouldDisplayAddressList() && -
    - {this.renderAddressList()} +
    + { this.renderAddressList() }
    } -
    +
    this.onSearchTermChange(e.target.value)} + onChange={ e => this.onSearchTermChange(e.target.value) } placeholder="Search" />
    diff --git a/react/src/components/dashboard/walletsNative/walletsNative.render.js b/react/src/components/dashboard/walletsNative/walletsNative.render.js index e9202c2..deacd2f 100644 --- a/react/src/components/dashboard/walletsNative/walletsNative.render.js +++ b/react/src/components/dashboard/walletsNative/walletsNative.render.js @@ -14,7 +14,7 @@ const WalletsNativeRender = function() { id="easydex-header-div" className="background-color-white" style={ this.getCoinStyle('transparent') }> -
      +
      1. { this.getCoinStyle('title') && diff --git a/react/src/components/dashboard/walletsNav/walletsNav.render.js b/react/src/components/dashboard/walletsNav/walletsNav.render.js index 76fc023..58e7cf1 100644 --- a/react/src/components/dashboard/walletsNav/walletsNav.render.js +++ b/react/src/components/dashboard/walletsNav/walletsNav.render.js @@ -27,7 +27,7 @@ export const WalletsNavWithWalletRender = function() { className={ 'page-header page-header-bordered header-easydex padding-bottom-' + (this.state.nativeOnly ? '40 page-header--native' : '20') } id="header-dashboard" style={{ marginBottom: this.props.ActiveCoin.mode === 'basilisk' ? '30px' : (this.state.nativeOnly ? '30px' : '0') }}> -
          +
            { translate('INDEX.MY') } { this.props && this.props.ActiveCoin ? this.props.ActiveCoin.coin : '-' } { translate('INDEX.ADDRESS') }: { this.props && this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : '-' }
    } -
    - this.onSearchTermChange(e.target.value) } - placeholder="Search" /> -
    + { this.props.ActiveCoin.txhistory !== 'loading' && +
    + this.onSearchTermChange(e.target.value) } + placeholder="Search" /> +
    + }
    { this.renderTxHistoryList() } From 6bfc276fa82255e3b4c17cb91cb2c7bb441e9147 Mon Sep 17 00:00:00 2001 From: pbca26 Date: Mon, 21 Aug 2017 19:05:41 +0300 Subject: [PATCH 18/18] settings support tab --- assets/mainWindow/css/loading.css | 5 ++ react/src/actions/actions/nativeSend.js | 4 +- .../src/assets/images/support/github-icon.png | Bin 0 -> 5275 bytes .../src/assets/images/support/slack-icon.png | Bin 0 -> 58329 bytes .../images/support/slack-invite-icon.png | Bin 0 -> 4428 bytes .../receiveCoin/receiveCoin.render.js | 5 +- .../components/dashboard/settings/settings.js | 32 ++++++++++ .../dashboard/settings/settings.render.js | 57 ++++++++++++++++- .../walletsProgress/walletsProgress.render.js | 1 - react/src/components/overrides.scss | 58 ++++++++++++++++++ 10 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 react/src/assets/images/support/github-icon.png create mode 100644 react/src/assets/images/support/slack-icon.png create mode 100644 react/src/assets/images/support/slack-invite-icon.png diff --git a/assets/mainWindow/css/loading.css b/assets/mainWindow/css/loading.css index c8c97c3..8782de6 100644 --- a/assets/mainWindow/css/loading.css +++ b/assets/mainWindow/css/loading.css @@ -109,4 +109,9 @@ body.agamaMode { .btn.btn-primary.btn-close-app { margin: 0; +} + +.app-closing { + position: relative; + top: 50px; } \ No newline at end of file diff --git a/react/src/actions/actions/nativeSend.js b/react/src/actions/actions/nativeSend.js index fc3e3e2..05e8dbb 100644 --- a/react/src/actions/actions/nativeSend.js +++ b/react/src/actions/actions/nativeSend.js @@ -176,8 +176,8 @@ export function getKMDOPIDState(json) { } export function getKMDOPID(opid, coin) { - let tmpopidOutput = '', - ajaxDataToHex; + let tmpopidOutput = ''; + let ajaxDataToHex; if (opid === undefined) { ajaxDataToHex = null; diff --git a/react/src/assets/images/support/github-icon.png b/react/src/assets/images/support/github-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..21ebc17f691ba7af2e68c30af8f712fdb2f0fad9 GIT binary patch literal 5275 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 literal 0 HcmV?d00001 diff --git a/react/src/assets/images/support/slack-icon.png b/react/src/assets/images/support/slack-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..edf63438a8d7f7e3b1e5d62ebdb4815f64942c60 GIT binary patch literal 58329 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 O0000# literal 0 HcmV?d00001 diff --git a/react/src/assets/images/support/slack-invite-icon.png b/react/src/assets/images/support/slack-invite-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dd38ca6a49cd8b01162705e55059de77862cc5e1 GIT binary patch literal 4428 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 type === 'public' ? address.address : `${address.address.substring(0, 34)}...` } { address.amount } - {!this.isNativeMode() && + { !this.isNativeMode() && { address.interest ? address.interest : 'N/A' } } @@ -175,5 +175,4 @@ export const ReceiveCoinRender = function() {
    ); } -}; - +}; \ No newline at end of file diff --git a/react/src/components/dashboard/settings/settings.js b/react/src/components/dashboard/settings/settings.js index 59e3078..ae1044d 100644 --- a/react/src/components/dashboard/settings/settings.js +++ b/react/src/components/dashboard/settings/settings.js @@ -79,14 +79,27 @@ class Settings extends React.Component { this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this); this._checkForUpdateUIPromise = this._checkForUpdateUIPromise.bind(this); this._updateUIPromise = this._updateUIPromise.bind(this); + this.updateTabDimensions = this.updateTabDimensions.bind(this); + } + + updateTabDimensions() { + setTimeout(() => { + const _height = document.querySelector(`#${this.state.tabElId} .panel-collapse .panel-body`).offsetHeight; + + this.setState(Object.assign({}, this.state, { + activeTabHeight: _height, + })); + }, 100); } componentWillMount() { socket.on('patch', msg => this.updateSocketsData(msg)); + window.addEventListener('resize', this.updateTabDimensions); } componentWillUnmount() { socket.removeAllListeners('patch', msg => this.updateSocketsData(msg)); + window.removeEventListener('resize', this.updateTabDimensions); if (!this.state.disableWalletSpecificUI) { document.documentElement.style.height = '100%'; @@ -115,6 +128,25 @@ class Settings extends React.Component { } } + openExternalWindow(url) { + const remote = window.require('electron').remote; + const BrowserWindow = remote.BrowserWindow; + + const externalWindow = new BrowserWindow({ + width: 1280, + height: 800, + title: 'Loading...', + icon: remote.getCurrentWindow().iguanaIcon, + }); + + externalWindow.loadURL(url); + externalWindow.webContents.on('did-finish-load', function() { + setTimeout(function() { + externalWindow.show(); + }, 40); + }); + } + _resetAppConfig() { Store.dispatch(resetAppConfig()); } diff --git a/react/src/components/dashboard/settings/settings.render.js b/react/src/components/dashboard/settings/settings.render.js index 065cfc4..96ea400 100644 --- a/react/src/components/dashboard/settings/settings.render.js +++ b/react/src/components/dashboard/settings/settings.render.js @@ -12,7 +12,7 @@ export const AppUpdateTabRender = function() { onClick={ () => this.openTab('AppUpdate', 10) }>
    this.openTab('Support', 11) }> + +
    +
    +
    +
    +
    this.openExternalWindow('http://support.supernet.org') }> + Support tickets +
    Support tickets
    +
    support.supernet.org
    +
    +
    +
    +
    this.openExternalWindow('https://sprnt.slack.com') }> + Slack +
    Slack
    +
    sprnt.slack.com
    +
    +
    +
    +
    this.openExternalWindow('http://slackinvite.supernet.org') }> + Slack invite +
    Get Slack invite
    +
    slackinvite.supernet.org
    +
    +
    +
    +
    this.openExternalWindow('https://github.com/SuperNETorg/Agama') }> + Github +
    Github
    +
    github.com/SuperNETorg/Agama
    +
    +
    +
    +
    +
    +
    diff --git a/react/src/components/dashboard/walletsProgress/walletsProgress.render.js b/react/src/components/dashboard/walletsProgress/walletsProgress.render.js index 6208677..0305aa1 100644 --- a/react/src/components/dashboard/walletsProgress/walletsProgress.render.js +++ b/react/src/components/dashboard/walletsProgress/walletsProgress.render.js @@ -76,7 +76,6 @@ export const WalletsProgressRender = function() {