From be92b01710fd56ba6773524c41ea559a7d89f873 Mon Sep 17 00:00:00 2001 From: yashar Date: Mon, 14 Aug 2017 12:45:07 +0430 Subject: [PATCH] Fix some bugs in votings --- src/components/voting/confirmVotes.js | 68 +++++++++++++------- src/components/voting/confirmVotes.test.js | 21 +++--- src/components/voting/votingHeader.js | 17 +++-- src/components/voting/votingHeaderWrapper.js | 2 + src/components/voting/votingRow.js | 53 ++++++++------- 5 files changed, 97 insertions(+), 64 deletions(-) diff --git a/src/components/voting/confirmVotes.js b/src/components/voting/confirmVotes.js index 19ed03023..d13cc7d11 100644 --- a/src/components/voting/confirmVotes.js +++ b/src/components/voting/confirmVotes.js @@ -1,14 +1,14 @@ import React from 'react'; import { connect } from 'react-redux'; -import grid from 'flexboxgrid/dist/flexboxgrid.css'; -import { Button } from 'react-toolbox/lib/button'; import Input from 'react-toolbox/lib/input'; import { vote } from '../../utils/api/delegate'; import { alertDialogDisplayed } from '../../actions/dialog'; import { clearVoteLists, pendingVotesAdded } from '../../actions/voting'; import InfoParagraph from '../infoParagraph'; +import ActionBar from '../actionBar'; +import { SYNC_ACTIVE_INTERVAL } from '../../constants/api'; +import Fees from '../../constants/fees'; -const delay = 10000; export class ConfirmVotes extends React.Component { constructor() { super(); @@ -16,9 +16,11 @@ export class ConfirmVotes extends React.Component { secondSecret: '', }; } + confirm() { const secondSecret = this.state.secondSecret.length === 0 ? null : this.state.secondSecret; const text = 'Your votes were successfully submitted. It can take several seconds before they are processed.'; + vote( this.props.activePeer, this.props.account.passphrase, @@ -26,11 +28,23 @@ export class ConfirmVotes extends React.Component { this.props.votedList, this.props.unvotedList, secondSecret, - ).then(() => { + ).then((data) => { this.props.pendingVotesAdded(); + + // add to pending transaction + this.props.addTransaction({ + id: data.transactionId, + senderPublicKey: this.props.account.publicKey, + senderId: this.props.account.address, + amount: 0, + fee: Fees.vote, + type: 3, + }); + + // remove pending votes setTimeout(() => { this.props.clearVoteLists(); - }, delay); + }, SYNC_ACTIVE_INTERVAL); this.props.showSuccessAlert({ title: 'Success', type: 'success', @@ -38,13 +52,17 @@ export class ConfirmVotes extends React.Component { }); }); } + setSecondPass(name, value) { this.setState({ ...this.state, [name]: value }); } + render() { - const secondPass = this.props.account.secondSignature === 0 ? null : - ; + const secondPassphrase = this.props.account.secondSignature === 1 ? + : null; + return (

Add vote to

@@ -55,23 +73,27 @@ export class ConfirmVotes extends React.Component { - {secondPass} + + {secondPassphrase} + -

You can select up to 33 delegates in one voting turn.

-

You can vote for up to 101 delegates in total.

+ You can select up to 33 delegates in one voting turn. +
+ You can vote for up to 101 delegates in total.
-
-
+ +
); } diff --git a/src/components/voting/confirmVotes.test.js b/src/components/voting/confirmVotes.test.js index d4dbc2e9e..3b0fca9fd 100644 --- a/src/components/voting/confirmVotes.test.js +++ b/src/components/voting/confirmVotes.test.js @@ -4,6 +4,7 @@ import { mount } from 'enzyme'; import chaiEnzyme from 'chai-enzyme'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; +import PropTypes from 'prop-types'; import sinonStubPromise from 'sinon-stub-promise'; import store from '../../store'; import ConfrimVotesContainer, { ConfirmVotes } from './confirmVotes'; @@ -40,10 +41,14 @@ const props = { showSuccessAlert: sinon.spy(), clearVoteLists: sinon.spy(), pendingVotesAdded: sinon.spy(), + addTransaction: sinon.spy(), }; describe('ConfrimVotesContainer', () => { it('should render ConfrimVotes', () => { - const wrapper = mount(); + const wrapper = mount(, { + context: { store }, + childContextTypes: { store: PropTypes.object.isRequired }, + }); expect(wrapper.find('ConfirmVotes').exists()).to.be.equal(true); }); }); @@ -51,26 +56,24 @@ describe('ConfrimVotes', () => { let wrapper; const delegateApiMock = sinon.stub(delegateApi, 'vote'); beforeEach(() => { - wrapper = mount(); + wrapper = mount(, { + context: { store }, + childContextTypes: { store: PropTypes.object.isRequired }, + }); }); it('should call vote api when confirm button is pressed', () => { const clock = sinon.useFakeTimers(); delegateApiMock.returnsPromise().resolves({ success: true }); - wrapper.find('#confirm').simulate('click'); + wrapper.instance().confirm(); expect(props.pendingVotesAdded).to.have.been.calledWith(); + expect(props.addTransaction).to.have.been.calledWith(); expect(props.showSuccessAlert).to.have.been.calledWith(); // it should triger 'props.clearVoteLists' after 10000 ms clock.tick(10000); expect(props.clearVoteLists).to.have.been.calledWith(); }); - it('confirm button should be disable when votedList and unvotedList is empty', () => { - wrapper.setProps({ unvotedList: [], votedList: [] }); - const disabled = wrapper.find('#confirm').props().disabled; - expect(disabled).to.be.equal(true); - }); - it('should update state when "setSecondPass" is called', () => { wrapper.setProps({ account: Object.assign(props.account, { secondSignature: 1 }), diff --git a/src/components/voting/votingHeader.js b/src/components/voting/votingHeader.js index 0b21819b5..c7a29fe6a 100644 --- a/src/components/voting/votingHeader.js +++ b/src/components/voting/votingHeader.js @@ -4,7 +4,7 @@ import { Button } from 'react-toolbox/lib/button'; import { IconMenu, MenuItem } from 'react-toolbox/lib/menu'; import Input from 'react-toolbox/lib/input'; import styles from './voting.css'; -import ConfirmVotes from './confirmVotes'; +import Confirm from './confirmVotes'; class VotingHeader extends React.Component { constructor() { @@ -14,6 +14,7 @@ class VotingHeader extends React.Component { searchIcon: 'search', }; } + search(name, value) { const icon = value.length > 0 ? 'close' : 'search'; this.setState({ @@ -22,23 +23,26 @@ class VotingHeader extends React.Component { }); this.props.search(value); } + clearSearch() { if (this.state.searchIcon === 'close') { this.search('query', ''); } } + confirmVoteText() { - let text = 'VOTE'; + let info = 'VOTE'; const voted = this.props.votedList.filter(item => !item.pending).length; const unvoted = this.props.unvotedList.filter(item => !item.pending).length; if (voted > 0 || unvoted > 0) { const seprator = (voted > 0 && unvoted > 0) ? ' / ' : ''; // eslint-disable-line const votedHtml = voted > 0 ? +{voted} : ''; const unvotedHtml = unvoted > 0 ? -{unvoted} : ''; - text = VOTE ({votedHtml}{seprator}{unvotedHtml}); + info = VOTE ({votedHtml}{seprator}{unvotedHtml}); } - return text; + return info; } + render() { const button =
visibility @@ -69,7 +73,10 @@ class VotingHeader extends React.Component {
diff --git a/src/components/voting/votingHeaderWrapper.js b/src/components/voting/votingHeaderWrapper.js index e7ff53d39..0322b6d2f 100644 --- a/src/components/voting/votingHeaderWrapper.js +++ b/src/components/voting/votingHeaderWrapper.js @@ -2,11 +2,13 @@ import { connect } from 'react-redux'; import VotingHeader from './votingHeader'; import { dialogDisplayed } from '../../actions/dialog'; import { removedFromVoteList } from '../../actions/voting'; +import { transactionAdded } from '../../actions/transactions'; const mapDispatchToProps = dispatch => ({ setActiveDialog: data => dispatch(dialogDisplayed(data)), addToUnvoted: data => dispatch(removedFromVoteList(data)), + addTransaction: data => dispatch(transactionAdded(data)), }); const mapStateToProps = state => ({ votedList: state.voting.votedList, diff --git a/src/components/voting/votingRow.js b/src/components/voting/votingRow.js index e96b654aa..e2939888d 100644 --- a/src/components/voting/votingRow.js +++ b/src/components/voting/votingRow.js @@ -1,35 +1,34 @@ import React from 'react'; import { TableRow, TableCell } from 'react-toolbox/lib/table'; import styles from './voting.css'; -import SelectableRow from './selectableRow'; +import Checkbox from './voteCheckbox'; -const setRowClass = (item) => { - let className = ''; - if (item.pending) { - className = styles.pendingRow; - } else if (item.selected && item.voted) { - className = styles.votedRow; - } else if (!item.selected && item.voted) { - className = styles.downVoteRow; - } else if (item.selected && !item.voted) { - className = styles.upVoteRow; +const setRowClass = ({ pending, selected, voted }) => { + if (pending) { + return styles.pendingRow; + } else if (selected) { + return voted ? styles.votedRow : styles.upVoteRow; } - return className; + return voted ? styles.downVoteRow : ''; +}; + +const VotingRow = (props) => { + const { data } = props; + return ( + + + + {data.rank} + {data.username} + {data.address} + {data.productivity} % + {data.approval} % + + ); }; -const VotingRow = props => ( - - - - {props.data.rank} - {props.data.username} - {props.data.address} - {props.data.productivity} % - {props.data.approval} % - -); export default VotingRow;