feat(@cockpit/explorer): implement pagination for accounts explorer

Display two accounts per page in the explorer overview. Display ten accounts
per page in the accounts explorer page.

Sort accounts by their api-supplied index numbers with the lowest index coming
first.

Change the `initBlockHeader` saga so that it triggers a re-fetch of accounts
and therefore the "Tx Count" numbers of displayed accounts will reflect
increased counts.
This commit is contained in:
Michael Bradley, Jr 2019-04-01 14:40:16 -05:00 committed by Iuri Matias
parent 5a502b379a
commit 745edafee4
5 changed files with 92 additions and 12 deletions

View File

@ -2,10 +2,11 @@ import React from 'react';
import {Row, Col, Card, CardHeader, CardBody} from 'reactstrap';
import {Link} from 'react-router-dom';
import PropTypes from 'prop-types';
import Pagination from './Pagination';
import CardTitleIdenticon from './CardTitleIdenticon';
const Accounts = ({accounts}) => (
const Accounts = ({accounts, changePage, currentPage, numberOfPages}) => (
<Row>
<Col>
<Card>
@ -13,6 +14,7 @@ const Accounts = ({accounts}) => (
<h2>Accounts</h2>
</CardHeader>
<CardBody>
{!accounts.length && "No accounts to display"}
{accounts.map(account => (
<div className="explorer-row border-top" key={account.address}>
<CardTitleIdenticon id={account.address}>Account&nbsp;
@ -34,6 +36,7 @@ const Accounts = ({accounts}) => (
</Row>
</div>
))}
{numberOfPages > 1 && <Pagination changePage={changePage} currentPage={currentPage} numberOfPages={numberOfPages}/>}
</CardBody>
</Card>
</Col>
@ -41,7 +44,10 @@ const Accounts = ({accounts}) => (
);
Accounts.propTypes = {
accounts: PropTypes.arrayOf(PropTypes.object)
accounts: PropTypes.arrayOf(PropTypes.object),
changePage: PropTypes.func,
currentPage: PropTypes.number,
numberOfPages: PropTypes.number
};
export default Accounts;

View File

@ -17,7 +17,7 @@ const ExplorerDashboardLayout = () => (
<div className="explorer-overview">
<Row>
<Col>
<AccountsContainer overridePageHead={false} />
<AccountsContainer numAccountsToDisplay={2} overridePageHead={false} />
</Col>
</Row>
<Row>

View File

@ -1,37 +1,105 @@
import React, {Component} from 'react';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import {accounts as accountsAction} from '../actions';
import {accounts as accountsAction,
initBlockHeader,
stopBlockHeader} from '../actions';
import Accounts from '../components/Accounts';
import DataWrapper from "../components/DataWrapper";
import {getAccounts} from "../reducers/selectors";
import PageHead from "../components/PageHead";
const MAX_ACCOUNTS = 10;
class AccountsContainer extends Component {
constructor(props) {
super(props);
this.numAccountsToDisplay = this.props.numAccountsToDisplay || MAX_ACCOUNTS;
this.state = {currentPage: 1};
}
componentDidMount() {
this.props.fetchAccounts();
this.props.initBlockHeader();
}
componentWillUnmount() {
this.props.stopBlockHeader();
}
get numberOfAccounts() {
if (this._numberOfAccounts === undefined) {
this._numberOfAccounts = this.props.accounts.length;
}
return this._numberOfAccounts;
}
get numberOfPages() {
if (this._numberOfPages === undefined) {
this._numberOfPages = Math.ceil(
this.numberOfAccounts / this.numAccountsToDisplay
);
}
return this._numberOfPages;
}
resetNums() {
this._numberOfAccounts = undefined;
this._numberOfPages = undefined;
}
changePage(newPage) {
if (newPage <= 0) {
newPage = 1;
} else if (newPage > this.numberOfPages) {
newPage = this.numberOfPages;
}
this.setState({ currentPage: newPage });
this.props.fetchAccounts();
}
get currentAccounts() {
return this.props.accounts
.filter((account) => {
const index = (
(account.index + 1) -
(this.numAccountsToDisplay * (this.state.currentPage - 1))
);
return index <= this.numAccountsToDisplay && index > 0;
});
}
render() {
this.resetNums();
return (
<React.Fragment>
<PageHead title="Accounts" enabled={this.props.overridePageHead} description="Summary view of the accounts configured for Embark" />
<DataWrapper shouldRender={this.props.accounts.length > 0} {...this.props} render={({accounts}) => (
<Accounts accounts={accounts} />
)} />
<PageHead
title="Accounts"
enabled={this.props.overridePageHead}
description="Summary view of the accounts configured for Embark" />
<Accounts accounts={this.currentAccounts}
numberOfPages={this.numberOfPages}
changePage={(newPage) => this.changePage(newPage)}
currentPage={this.state.currentPage} />
</React.Fragment>
);
}
}
function mapStateToProps(state) {
return {accounts: getAccounts(state), error: state.errorMessage, loading: state.loading};
return {
accounts: getAccounts(state),
error: state.errorMessage,
loading: state.loading
};
}
AccountsContainer.propTypes = {
accounts: PropTypes.arrayOf(PropTypes.object),
fetchAccounts: PropTypes.func,
numAccountsToDisplay: PropTypes.number,
initBlockHeader: PropTypes.func,
stopBlockHeader: PropTypes.func,
error: PropTypes.string,
loading: PropTypes.bool,
overridePageHead: PropTypes.bool
@ -40,6 +108,8 @@ AccountsContainer.propTypes = {
export default connect(
mapStateToProps,
{
fetchAccounts: accountsAction.request
fetchAccounts: accountsAction.request,
initBlockHeader,
stopBlockHeader
},
)(AccountsContainer);

View File

@ -41,6 +41,9 @@ const entitiesDefaultState = {
};
const sorter = {
accounts: function(a, b) {
return a.index - b.index;
},
blocks: function(a, b) {
return b.number - a.number;
},

View File

@ -420,6 +420,7 @@ export function *initBlockHeader() {
channel.close();
return;
}
yield put({type: actions.ACCOUNTS[actions.REQUEST]});
yield put({type: actions.BLOCKS[actions.REQUEST]});
yield put({type: actions.BLOCKS_FULL[actions.REQUEST], txObjects: true, txReceipts: true});
yield put({type: actions.TRANSACTIONS[actions.REQUEST]});