From 61294adee864a5b4876556fcc5f5c5f26f4af23a Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 15:34:00 +0200 Subject: [PATCH 01/27] :seedling: Create empty 'Voting summary' page --- i18n/locales/en/common.json | 1 + src/components/votingSummary/index.js | 16 ++++++++++++++++ src/components/votingSummary/votingSummary.js | 9 +++++++++ src/constants/routes.js | 6 ++++++ 4 files changed, 32 insertions(+) create mode 100644 src/components/votingSummary/index.js create mode 100644 src/components/votingSummary/votingSummary.js diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 3f25529517..3b1e18e428 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -522,6 +522,7 @@ "Votes": "Votes", "Votes submitted": "Votes submitted", "Voting": "Voting", + "Voting summary": "Voting summary", "Wallet": "Wallet", "We recommend including date & time or a specific keyword.": "We recommend including date & time or a specific keyword.", "Welcome back": "Welcome back", diff --git a/src/components/votingSummary/index.js b/src/components/votingSummary/index.js new file mode 100644 index 0000000000..764afa9f8b --- /dev/null +++ b/src/components/votingSummary/index.js @@ -0,0 +1,16 @@ +/* istanbul ignore file */ +import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; +import VotingSummary from './votingSummary'; +import { clearVotes } from '../../actions/voting'; + +const mapStateToProps = state => ({ + votes: state.voting.votes, +}); + +const mapDispatchToProps = { + clearVotes, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(translate()(VotingSummary)); + diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js new file mode 100644 index 0000000000..4015647c55 --- /dev/null +++ b/src/components/votingSummary/votingSummary.js @@ -0,0 +1,9 @@ +import React from 'react'; + +const VotingSummary = ({ t }) => ( +
+

{t('Voting summary')}

+
+); + +export default VotingSummary; diff --git a/src/constants/routes.js b/src/constants/routes.js index 8e9d8f0b51..f12ca411ac 100644 --- a/src/constants/routes.js +++ b/src/constants/routes.js @@ -10,6 +10,7 @@ import TransactionDashboard from '../components/transactionDashboard'; import AccountTransactions from '../components/accountTransactions'; import Voting from '../components/voting'; import VotingV2 from '../components/votingV2'; +import VotingSummary from '../components/votingSummary'; import SingleTransaction from '../components/singleTransactionV2'; import HwWalletLogin from '../components/hwWalletLogin'; // import NotFound from '../components/notFound'; @@ -48,6 +49,11 @@ export default { component: Voting, isPrivate: true, }, + voting: { + path: '/delegatesV2/vote', + component: VotingSummary, + isPrivate: true, + }, delegatesV2: { path: '/delegatesV2', component: VotingV2, From f1ff2864558c2cd024943416f119e4064acf04fa Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 16:25:17 +0200 Subject: [PATCH 02/27] :seedling: Create generic transactionSummary component --- src/components/transactionSummary/index.js | 31 ++++++++ .../transactionSummary/transactionSummary.css | 77 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/components/transactionSummary/index.js create mode 100644 src/components/transactionSummary/transactionSummary.css diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js new file mode 100644 index 0000000000..6e9a4f021f --- /dev/null +++ b/src/components/transactionSummary/index.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { PrimaryButtonV2, TertiaryButtonV2 } from '../toolbox/buttons/button'; +import styles from './transactionSummary.css'; + +const TransactionSummary = ({ + title, children, confirmButton, cancelButton, +}) => ( +
+
+

{title}

+
+
+ {children} +
+
+ + {confirmButton.label} + + + {cancelButton.label} + +
+
+); + +export default TransactionSummary; + diff --git a/src/components/transactionSummary/transactionSummary.css b/src/components/transactionSummary/transactionSummary.css new file mode 100644 index 0000000000..ff032056b5 --- /dev/null +++ b/src/components/transactionSummary/transactionSummary.css @@ -0,0 +1,77 @@ +@import '../app/variablesV2.css'; +@import '../app/mixins.css'; + +.wrapper { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + box-sizing: border-box; + + & > footer { + width: 100%; + min-width: 572px; + margin: 36px 0 0; + padding: 0; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + box-sizing: border-box; + + & > .confirmBtn { + width: 431px; + } + + & > .editBtn { + width: auto !important; + } + } + + & > header { + width: 100%; + height: 63px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + box-sizing: border-box; + + & > h1 { + @mixin headingNormal bold; + + width: 100%; + margin: 0; + padding: 0; + } + } +} + +.content { + width: 100%; + box-sizing: border-box; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + + & section { + width: 100%; + height: 88px; + padding: 16px 0; + display: flex; + flex-direction: column; + justify-content: center; + align-items: flex-start; + border-top: 1px solid rgba(111, 114, 118, 0.1); + box-sizing: border-box; + + & > label:first-child { + @mixin contentNormal bold; + + color: var(--color-maastricht-blue); + margin-bottom: 10px; + } + } +} From 4c14ce6436fbbba7327681e0fcd42488b20a231e Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 16:25:50 +0200 Subject: [PATCH 03/27] :seedling: Implement basic structure of votingSummary --- i18n/locales/en/common.json | 3 ++ src/components/votingSummary/index.js | 3 +- src/components/votingSummary/votingSummary.js | 50 +++++++++++++++++-- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 3b1e18e428..9bcfaeeba1 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -90,6 +90,7 @@ "Confirm to register your second passphrase on the blockchain.": "Confirm to register your second passphrase on the blockchain.", "Confirm transaction on {{deviceModel}}": "Confirm transaction on {{deviceModel}}", "Confirm vote on {{deviceModel}}": "Confirm vote on {{deviceModel}}", + "Confirm voting": "Confirm voting", "Confirm your name": "Confirm your name", "Confirm your passphrase": "Confirm your passphrase", "Confirmation in the next step": "Confirmation in the next step", @@ -153,6 +154,7 @@ "Each time you add or remove a vote it is counted as an action. There's {{fee}} LSK fee per every 33 actions.": "Each time you add or remove a vote it is counted as an action. There's {{fee}} LSK fee per every 33 actions.", "Edit": "Edit", "Edit transaction": "Edit transaction", + "Edit voting": "Edit voting", "Enter URL of the *.js file with the extension": "Enter URL of the *.js file with the extension", "Enter your 1st passphrase to confirm": "Enter your 1st passphrase to confirm", "Enter your passphrase": "Enter your passphrase", @@ -520,6 +522,7 @@ "Voted delegates": "Voted delegates", "Voter": "Voter", "Votes": "Votes", + "Votes after confirmation": "Votes after confirmation", "Votes submitted": "Votes submitted", "Voting": "Voting", "Voting summary": "Voting summary", diff --git a/src/components/votingSummary/index.js b/src/components/votingSummary/index.js index 764afa9f8b..7045f2b038 100644 --- a/src/components/votingSummary/index.js +++ b/src/components/votingSummary/index.js @@ -1,6 +1,7 @@ /* istanbul ignore file */ import { connect } from 'react-redux'; import { translate } from 'react-i18next'; +import { withRouter } from 'react-router'; import VotingSummary from './votingSummary'; import { clearVotes } from '../../actions/voting'; @@ -12,5 +13,5 @@ const mapDispatchToProps = { clearVotes, }; -export default connect(mapStateToProps, mapDispatchToProps)(translate()(VotingSummary)); +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(translate()(VotingSummary))); diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index 4015647c55..7c6401eac2 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -1,9 +1,49 @@ import React from 'react'; +import TransactionSummary from '../transactionSummary'; +import { + getVoteList, + getUnvoteList, +} from '../../utils/voting'; +import routes from '../../constants/routes'; -const VotingSummary = ({ t }) => ( -
-

{t('Voting summary')}

-
-); +const VotingSummary = ({ t, votes, history }) => { + const voteList = getVoteList(votes); + const unvoteList = getUnvoteList(votes); + return ( + {}, + }} + cancelButton={{ + label: t('Edit voting'), + onClick: () => { + history.push(routes.delegatesV2.path); + }, + }} + title={t('Voting summary')} > +
+ + +
+
+ + +
+ {voteList.length > 0 ? +
+ + +
: + null } + {unvoteList.length > 0 ? +
+ + +
: + null } +
+ ); +}; export default VotingSummary; From 214181a257c228ef29a9d28c0dc42730250e44b8 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 16:26:36 +0200 Subject: [PATCH 04/27] :seedling: Implement "Go to Confirmation" in voting --- src/components/votingV2/votingHeader.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/votingV2/votingHeader.js b/src/components/votingV2/votingHeader.js index d12970e16b..17fcd463e1 100644 --- a/src/components/votingV2/votingHeader.js +++ b/src/components/votingV2/votingHeader.js @@ -67,9 +67,11 @@ class VotingHeader extends React.Component { {t('Cancel voting')} - - {t('Go to Confirmation')} - + + + {t('Go to Confirmation')} + + : From 8c279ddbae215f7f62212f6f7a4278d9827d07e7 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 16:34:03 +0200 Subject: [PATCH 05/27] :seedling: Implement layout of transactionSummary --- src/components/transactionSummary/index.js | 38 ++++++++++--------- .../transactionSummary/transactionSummary.css | 12 ++++++ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js index 6e9a4f021f..031107a906 100644 --- a/src/components/transactionSummary/index.js +++ b/src/components/transactionSummary/index.js @@ -5,25 +5,27 @@ import styles from './transactionSummary.css'; const TransactionSummary = ({ title, children, confirmButton, cancelButton, }) => ( -
-
-

{title}

-
-
- {children} +
+
+
+

{title}

+
+
+ {children} +
+
+ + {confirmButton.label} + + + {cancelButton.label} + +
-
- - {confirmButton.label} - - - {cancelButton.label} - -
); diff --git a/src/components/transactionSummary/transactionSummary.css b/src/components/transactionSummary/transactionSummary.css index ff032056b5..196bb3831c 100644 --- a/src/components/transactionSummary/transactionSummary.css +++ b/src/components/transactionSummary/transactionSummary.css @@ -1,6 +1,15 @@ @import '../app/variablesV2.css'; @import '../app/mixins.css'; +.container { + display: flex; + flex-direction: column; + justify-content: center; + height: 100%; + align-items: center; + width: 100%; +} + .wrapper { width: 100%; display: flex; @@ -8,6 +17,9 @@ justify-content: center; align-items: flex-start; box-sizing: border-box; + background: transparent; + max-width: 670px; + height: auto; & > footer { width: 100%; From 2c900a3a73a263992a2cb1ba46441effbfcfee04 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 16:52:11 +0200 Subject: [PATCH 06/27] :seedling: Implement vote lists in votingSummary --- .../votingSummary/votingSummary.css | 42 +++++++++++++++++++ src/components/votingSummary/votingSummary.js | 35 ++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 src/components/votingSummary/votingSummary.css diff --git a/src/components/votingSummary/votingSummary.css b/src/components/votingSummary/votingSummary.css new file mode 100644 index 0000000000..07805449c5 --- /dev/null +++ b/src/components/votingSummary/votingSummary.css @@ -0,0 +1,42 @@ +@import '../app/variablesV2.css'; +@import '../app/mixins.css'; + +.votesContainer { + display: flex; + flex-wrap: wrap; + margin-bottom: 16px; + + &:last-child { + margin-bottom: 0; + } + + & .voteTag { + @mixin contentSmall bold; + + align-items: center; + border: 1px solid var(--dark-border-color); + border-radius: var(--border-radius-standard); + box-sizing: border-box; + color: var(--color-maastricht-blue); + display: flex; + height: 32px; + margin-bottom: 8px; + margin-right: 8px; + padding: 7px 10px; + text-decoration: none; + } + + & .rank { + @mixin contentSmall semi-bold; + + align-items: center; + background-color: var(--color-slate-gray); + border-radius: var(--border-radius-standard); + color: var(--color-white); + display: flex; + height: 18px; + margin-right: 10px; + padding: 0 5px; + text-align: center; + } +} diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index 7c6401eac2..5a5bbd376f 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -1,13 +1,22 @@ import React from 'react'; import TransactionSummary from '../transactionSummary'; +import votingConst from '../../constants/voting'; import { + getTotalVotesCount, getVoteList, getUnvoteList, } from '../../utils/voting'; import routes from '../../constants/routes'; +import styles from './votingSummary.css'; + const VotingSummary = ({ t, votes, history }) => { + const { + maxCountOfVotes, + fee, + } = votingConst; const voteList = getVoteList(votes); + console.log(voteList); const unvoteList = getUnvoteList(votes); return ( { title={t('Voting summary')} >
- +
- +
{voteList.length > 0 ?
- +
: null } {unvoteList.length > 0 ?
- +
: null }
From 90fffe0245061300876b6e6798cba533400d67b8 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 21 May 2019 17:00:42 +0200 Subject: [PATCH 07/27] :seedling: Implement transaction fee tooltip in voting --- .../transactionSummary/transactionSummary.css | 1 + src/components/votingSummary/votingSummary.js | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/components/transactionSummary/transactionSummary.css b/src/components/transactionSummary/transactionSummary.css index 196bb3831c..24b43e2c61 100644 --- a/src/components/transactionSummary/transactionSummary.css +++ b/src/components/transactionSummary/transactionSummary.css @@ -84,6 +84,7 @@ color: var(--color-maastricht-blue); margin-bottom: 10px; + display: flex; } } } diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index 5a5bbd376f..eff93c3cc3 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -7,6 +7,8 @@ import { getUnvoteList, } from '../../utils/voting'; import routes from '../../constants/routes'; +import Tooltip from '../toolbox/tooltip/tooltip'; +import links from '../../constants/externalLinks'; import styles from './votingSummary.css'; @@ -36,7 +38,26 @@ const VotingSummary = ({ t, votes, history }) => {
- +
{voteList.length > 0 ? From 831abf93934e037e2e1d655715b4b6e006e3c0f9 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 09:20:37 +0200 Subject: [PATCH 08/27] :seedling: Implement voteUrlProcessorV2 to get votes from url, e.g. http://localhost:8080/#/delegatesV2/vote?votes=joel,hirish,cc001,mrv,12e0asdlhiu&unvotes=bioly,aaa,bbb --- i18n/locales/en/common.json | 2 + src/components/voteUrlProcessorV2/index.js | 33 ++++++++ .../voteUrlProcessorV2/voteUrlProcessor.js | 79 +++++++++++++++++++ src/components/votingSummary/votingSummary.js | 4 +- 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/components/voteUrlProcessorV2/index.js create mode 100644 src/components/voteUrlProcessorV2/voteUrlProcessor.js diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 9bcfaeeba1..7f3bf9dfaf 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -72,6 +72,7 @@ "Cancel": "Cancel", "Cancel voting": "Cancel voting", "Check for updates...": "Check for updates...", + "Check spelling – delegate name does not exist": "Check spelling – delegate name does not exist", "Check spelling – name does not exist on mainnet": "Check spelling – name does not exist on mainnet", "Choose": "Choose", "Choose a name": "Choose a name", @@ -350,6 +351,7 @@ "Print more than one copy and store them in two separate secure places.": "Print more than one copy and store them in two separate secure places.", "Privacy Policy": "Privacy Policy", "Processing Speed": "Processing Speed", + "Processing...": "Processing...", "Productivity": "Productivity", "Provide a correct amount of {{token}}": "Provide a correct amount of {{token}}", "Provide a correct wallet address or a name of a bookmarked account": "Provide a correct wallet address or a name of a bookmarked account", diff --git a/src/components/voteUrlProcessorV2/index.js b/src/components/voteUrlProcessorV2/index.js new file mode 100644 index 0000000000..9549c80d84 --- /dev/null +++ b/src/components/voteUrlProcessorV2/index.js @@ -0,0 +1,33 @@ +/* istanbul ignore file */ +import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; +import { withRouter } from 'react-router'; + +import { + urlVotesFound, + voteLookupStatusCleared, +} from '../../actions/voting'; +import VoteUrlProcessor from './voteUrlProcessor'; + +const filterObjectPropsWithValue = (object = {}, value) => ( + Object.keys(object).filter(key => object[key] === value) +); + +const mapStateToProps = state => ({ + votes: state.voting.votes, + urlVoteCount: Object.keys(state.voting.voteLookupStatus || {}).length, + pending: filterObjectPropsWithValue(state.voting.voteLookupStatus, 'pending'), + alreadyVoted: filterObjectPropsWithValue(state.voting.voteLookupStatus, 'alreadyVoted').concat(filterObjectPropsWithValue(state.voting.voteLookupStatus, 'notVotedYet')), + notFound: filterObjectPropsWithValue(state.voting.voteLookupStatus, 'notFound'), + account: state.account, +}); + +const mapDispatchToProps = { + urlVotesFound, + clearVoteLookupStatus: voteLookupStatusCleared, +}; + +export default withRouter(connect( + mapStateToProps, + mapDispatchToProps, +)(translate()(VoteUrlProcessor))); diff --git a/src/components/voteUrlProcessorV2/voteUrlProcessor.js b/src/components/voteUrlProcessorV2/voteUrlProcessor.js new file mode 100644 index 0000000000..a94d19fbce --- /dev/null +++ b/src/components/voteUrlProcessorV2/voteUrlProcessor.js @@ -0,0 +1,79 @@ +import React from 'react'; +import { parseSearchParams } from '../../utils/searchParams'; +import routes from '../../constants/routes'; + +import styles from '../votingSummary/votingSummary.css'; + +export default class VoteUrlProcessor extends React.Component { + constructor(props) { + super(props); + + this.state = { + votes: [], + unvotes: [], + params: '', + }; + } + componentDidMount() { + this.props.clearVoteLookupStatus(); + let params = parseSearchParams(this.props.history.location.search); + if (params.votes || params.unvotes) { + this.setVotesFromParams(params); + } + + this.props.history.listen((location) => { + if (location.pathname === routes.delegates.path) { + params = parseSearchParams(location.search); + + if (location.search && location.search !== this.state.params) { + this.props.clearVoteLookupStatus(); + this.setVotesFromParams(params); + this.setState({ + params: location.search, + }); + } + } + }); + } + + setVotesFromParams(params) { + const upvotes = params.votes ? params.votes.split(',') : []; + const unvotes = params.unvotes ? params.unvotes.split(',') : []; + this.props.urlVotesFound({ + upvotes, + unvotes, + address: this.props.account.address, + }); + + this.setState({ + votes: params.votes, + unvotes: params.unvotes, + }); + } + + render() { + const { t } = this.props; + const sections = { + pending: t('Processing...'), + notFound: t('Check spelling – delegate name does not exist'), + alreadyVoted: t('Nothing to change – already voted/unvoted'), + }; + + return + {Object.keys(sections).map((list, key) => ( + this.props[list].length ? ( +
+ + +
+ ) : null + ))} +
; + } +} diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index eff93c3cc3..65aeb2fa1c 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -9,6 +9,8 @@ import { import routes from '../../constants/routes'; import Tooltip from '../toolbox/tooltip/tooltip'; import links from '../../constants/externalLinks'; +import VoteUrlProcessor from '../voteUrlProcessorV2'; + import styles from './votingSummary.css'; @@ -18,7 +20,6 @@ const VotingSummary = ({ t, votes, history }) => { fee, } = votingConst; const voteList = getVoteList(votes); - console.log(voteList); const unvoteList = getUnvoteList(votes); return ( { + {voteList.length > 0 ?
From 21d56bc5bdfdd69bd01bd6facab8f0324be7965d Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 09:26:30 +0200 Subject: [PATCH 09/27] :seedling: Implement total fee in votingSummary --- src/components/votingSummary/votingSummary.js | 4 +++- src/components/votingV2/votingHeader.js | 6 ++---- src/utils/voting.js | 9 ++++++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index 65aeb2fa1c..b7c4f5b7c8 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -5,6 +5,7 @@ import { getTotalVotesCount, getVoteList, getUnvoteList, + getTotalActions, } from '../../utils/voting'; import routes from '../../constants/routes'; import Tooltip from '../toolbox/tooltip/tooltip'; @@ -21,6 +22,7 @@ const VotingSummary = ({ t, votes, history }) => { } = votingConst; const voteList = getVoteList(votes); const unvoteList = getUnvoteList(votes); + const totalActions = getTotalActions(votes); return ( {

- +
{voteList.length > 0 ? diff --git a/src/components/votingV2/votingHeader.js b/src/components/votingV2/votingHeader.js index 17fcd463e1..ebf3942ba1 100644 --- a/src/components/votingV2/votingHeader.js +++ b/src/components/votingV2/votingHeader.js @@ -8,6 +8,7 @@ import { getTotalVotesCount, getVoteList, getUnvoteList, + getTotalActions, } from './../../utils/voting'; import styles from './votingHeader.css'; @@ -22,14 +23,11 @@ class VotingHeader extends React.Component { } = this.props; const voteList = getVoteList(votes); const unvoteList = getUnvoteList(votes); + const totalActions = getTotalActions(votes); const { - maxCountOfVotesInOneTurn, maxCountOfVotes, fee, } = votingConst; - const totalActions = Math.ceil(( - voteList.length + unvoteList.length - ) / maxCountOfVotesInOneTurn); return (
diff --git a/src/utils/voting.js b/src/utils/voting.js index 89dbe4bede..9d100c9c1d 100644 --- a/src/utils/voting.js +++ b/src/utils/voting.js @@ -1,3 +1,4 @@ +import votingConst from '../constants/voting'; const getVotedList = votes => (Object.keys(votes).filter(key => votes[key].confirmed)); @@ -10,4 +11,10 @@ const getVoteList = votes => (Object.keys(votes).filter(key => const getTotalVotesCount = votes => ((getVotedList(votes).length - getUnvoteList(votes).length) + getVoteList(votes).length); -export { getTotalVotesCount, getVotedList, getVoteList, getUnvoteList }; +const getTotalActions = votes => ( + Math.ceil(( + getVoteList(votes).length + getUnvoteList(votes).length + ) / votingConst.maxCountOfVotesInOneTurn) +); + +export { getTotalVotesCount, getVotedList, getVoteList, getUnvoteList, getTotalActions }; From fbd3b0342fe3cb75d391b662da56782b3b3c1e0a Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 10:14:21 +0200 Subject: [PATCH 10/27] :seedling: Add second passphrase to transactionSummary --- src/components/transactionSummary/index.js | 19 +++++++++++++++++-- .../transactionSummary/transactionSummary.css | 1 - src/components/votingSummary/index.js | 1 + src/components/votingSummary/votingSummary.js | 6 +++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js index 031107a906..c9b77bbcff 100644 --- a/src/components/transactionSummary/index.js +++ b/src/components/transactionSummary/index.js @@ -1,9 +1,12 @@ import React from 'react'; import { PrimaryButtonV2, TertiaryButtonV2 } from '../toolbox/buttons/button'; +import PassphraseInputV2 from '../passphraseInputV2/passphraseInputV2'; import styles from './transactionSummary.css'; +const checkSecondPassphrase = () => {}; + const TransactionSummary = ({ - title, children, confirmButton, cancelButton, + title, children, confirmButton, cancelButton, account, t, }) => (
@@ -11,7 +14,19 @@ const TransactionSummary = ({

{title}

- {children} + {children} + {account.secondPublicKey ? +
+ + +
+ : null + }
({ votes: state.voting.votes, + account: state.account, }); const mapDispatchToProps = { diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingSummary/votingSummary.js index b7c4f5b7c8..34bf0a91be 100644 --- a/src/components/votingSummary/votingSummary.js +++ b/src/components/votingSummary/votingSummary.js @@ -15,7 +15,9 @@ import VoteUrlProcessor from '../voteUrlProcessorV2'; import styles from './votingSummary.css'; -const VotingSummary = ({ t, votes, history }) => { +const VotingSummary = ({ + t, votes, history, account, +}) => { const { maxCountOfVotes, fee, @@ -25,6 +27,8 @@ const VotingSummary = ({ t, votes, history }) => { const totalActions = getTotalActions(votes); return ( {}, From 0968e655c2ff2cfb6e6abf4474c6b9906770fdf2 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 10:22:41 +0200 Subject: [PATCH 11/27] :bug: Fix "Edit voting" to preserve the votes --- .../votingListViewV2/votingListViewV2.js | 2 +- src/components/votingV2/votingV2.js | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/votingListViewV2/votingListViewV2.js b/src/components/votingListViewV2/votingListViewV2.js index e499af42c2..944aaab21e 100644 --- a/src/components/votingListViewV2/votingListViewV2.js +++ b/src/components/votingListViewV2/votingListViewV2.js @@ -23,7 +23,7 @@ class VotingListViewV2 extends React.Component { } componentDidMount() { - if (this.props.account.serverPublicKey) { + if (this.props.account.serverPublicKey && !this.props.votingModeEnabled) { this.loadVotedDelegates(); } this.loadDelegates('', true); diff --git a/src/components/votingV2/votingV2.js b/src/components/votingV2/votingV2.js index ae426448c7..ebd5fde605 100644 --- a/src/components/votingV2/votingV2.js +++ b/src/components/votingV2/votingV2.js @@ -3,25 +3,19 @@ import grid from 'flexboxgrid/dist/flexboxgrid.css'; import styles from './votingV2.css'; import VotingListViewV2 from '../votingListViewV2'; import VotingHeader from './votingHeader'; +import { getTotalActions } from './../../utils/voting'; class VotingV2 extends React.Component { - constructor() { + constructor({ votes }) { super(); + this.state = { - votingModeEnabled: false, + votingModeEnabled: getTotalActions(votes) > 0, }; this.toggleVotingMode = this.toggleVotingMode.bind(this); } - setLayover(isLayover) { - if (isLayover && this.root) { - this.root.classList.add(styles.hasLayover); - } else if (!isLayover && this.root) { - this.root.classList.remove(styles.hasLayover); - } - } - toggleVotingMode() { if (this.state.votingModeEnabled) { this.props.clearVotes(); From 41c3a4fa82251110303dcf03617b8141e3a975fd Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 11:18:20 +0200 Subject: [PATCH 12/27] :seedling: Implement guest mode for delegatesV2 --- i18n/locales/en/common.json | 2 ++ src/components/signInTooltipWrapper/index.js | 11 +++++++ .../signInTooltipWrapper.js | 33 +++++++++++++++++++ src/components/toolbox/tooltip/tooltip.js | 14 +++++--- src/components/votingV2/votingHeader.css | 4 +++ src/components/votingV2/votingHeader.js | 21 +++++++----- src/components/votingV2/votingV2.js | 1 - src/constants/routes.js | 2 +- 8 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 src/components/signInTooltipWrapper/index.js create mode 100644 src/components/signInTooltipWrapper/signInTooltipWrapper.js diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 7f3bf9dfaf..38880ed2d1 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -216,6 +216,7 @@ "ID already added to bookmarks": "ID already added to bookmarks", "If you’re not sure how to do this please follow the": "If you’re not sure how to do this please follow the", "In": "In", + "In order to use this Lisk Hub feature you need to sign in to your Lisk account.": "In order to use this Lisk Hub feature you need to sign in to your Lisk account.", "Include your operating system and screen resolution in your report": "Include your operating system and screen resolution in your report", "Incoming": "Incoming", "Incoming transactions": "Incoming transactions", @@ -342,6 +343,7 @@ "Please go back and check your passphrase again.": "Please go back and check your passphrase again.", "Please keep it safe!": "Please keep it safe!", "Please select the account you’d like to sign in to or": "Please select the account you’d like to sign in to or", + "Please sign in": "Please sign in", "Please sign in with your passphrase": "Please sign in with your passphrase", "Please sign in with your second passphrase": "Please sign in with your second passphrase", "Please use only digits and dots": "Please use only digits and dots", diff --git a/src/components/signInTooltipWrapper/index.js b/src/components/signInTooltipWrapper/index.js new file mode 100644 index 0000000000..835cc5827b --- /dev/null +++ b/src/components/signInTooltipWrapper/index.js @@ -0,0 +1,11 @@ +/* istanbul ignore file */ +import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; +import { withRouter } from 'react-router'; +import SignInTooltipWrapper from './signInTooltipWrapper'; + +const mapStateToProps = state => ({ + account: state.account, +}); + +export default withRouter(connect(mapStateToProps)(translate()(SignInTooltipWrapper))); diff --git a/src/components/signInTooltipWrapper/signInTooltipWrapper.js b/src/components/signInTooltipWrapper/signInTooltipWrapper.js new file mode 100644 index 0000000000..07235f8f6f --- /dev/null +++ b/src/components/signInTooltipWrapper/signInTooltipWrapper.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import routes from './../../constants/routes'; +import Tooltip from '../toolbox/tooltip/tooltip'; + +const SignInTooltipWrapper = ({ + children, account, t, history, +}) => { + const { pathname, search } = history.location; + return + { account && account.address ? + children : + + + {children} + } + title={t('Please sign in')} + footer={ + + {t('Sign in')} + + } + > +

{t('In order to use this Lisk Hub feature you need to sign in to your Lisk account.')}

+ + } +
; +}; + +export default SignInTooltipWrapper; diff --git a/src/components/toolbox/tooltip/tooltip.js b/src/components/toolbox/tooltip/tooltip.js index 372df5b50d..524ccf0f04 100644 --- a/src/components/toolbox/tooltip/tooltip.js +++ b/src/components/toolbox/tooltip/tooltip.js @@ -64,7 +64,7 @@ class Tooltip extends React.Component { render() { const { - title, children, footer, className, alwaysShow, + title, children, footer, className, alwaysShow, content, } = this.props; const { showTooltip, @@ -78,10 +78,13 @@ class Tooltip extends React.Component { onMouseLeave={this.handleMouseLeave} onMouseMove={this.handleMouseMove} ref={this.setWrapperRef}> - + {React.isValidElement(content) ? + content : + + + }
@@ -107,6 +110,7 @@ Tooltip.propTypes = { children: PropTypes.node.isRequired, footer: PropTypes.node, className: PropTypes.string, + content: PropTypes.node, }; Tooltip.defaultProps = { diff --git a/src/components/votingV2/votingHeader.css b/src/components/votingV2/votingHeader.css index 3299f8b83b..944de19d46 100644 --- a/src/components/votingV2/votingHeader.css +++ b/src/components/votingV2/votingHeader.css @@ -6,6 +6,10 @@ justify-content: space-between; width: 100%; margin-bottom: 25px; + + & > * { + display: flex; + } } .box, diff --git a/src/components/votingV2/votingHeader.js b/src/components/votingV2/votingHeader.js index ebf3942ba1..efbee2e517 100644 --- a/src/components/votingV2/votingHeader.js +++ b/src/components/votingV2/votingHeader.js @@ -2,6 +2,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { SecondaryButtonV2, PrimaryButtonV2 } from '../toolbox/buttons/button'; import Tooltip from '../toolbox/tooltip/tooltip'; +import SignInTooltipWrapper from '../signInTooltipWrapper'; import routes from './../../constants/routes'; import votingConst from '../../constants/voting'; import { @@ -72,14 +73,18 @@ class VotingHeader extends React.Component { : - - - {t('Register as a Delegate')} - - - - {t('Start voting')} - + + + + {t('Register as a Delegate')} + + + + + + {t('Start voting')} + + }
diff --git a/src/components/votingV2/votingV2.js b/src/components/votingV2/votingV2.js index ebd5fde605..59044a30b5 100644 --- a/src/components/votingV2/votingV2.js +++ b/src/components/votingV2/votingV2.js @@ -36,7 +36,6 @@ class VotingV2 extends React.Component {
diff --git a/src/constants/routes.js b/src/constants/routes.js index f12ca411ac..1518897535 100644 --- a/src/constants/routes.js +++ b/src/constants/routes.js @@ -57,7 +57,7 @@ export default { delegatesV2: { path: '/delegatesV2', component: VotingV2, - isPrivate: true, + isPrivate: false, }, help: { path: '/help', From f6cb0c7e331579d2a8145ef665b705da8154404b Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 11:28:35 +0200 Subject: [PATCH 13/27] :white_check_mark: Create unit tests for signInTooltipWrapper --- .../signInTooltipWrapper.test.js | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/components/signInTooltipWrapper/signInTooltipWrapper.test.js diff --git a/src/components/signInTooltipWrapper/signInTooltipWrapper.test.js b/src/components/signInTooltipWrapper/signInTooltipWrapper.test.js new file mode 100644 index 0000000000..b2039bebb6 --- /dev/null +++ b/src/components/signInTooltipWrapper/signInTooltipWrapper.test.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import PropTypes from 'prop-types'; +import { MemoryRouter as Router } from 'react-router-dom'; +import i18n from '../../i18n'; +import SignInTooltipWrapper from './signInTooltipWrapper'; + +describe('SignInTooltipWrapper', () => { + const history = { + location: { + pathname: '/delegates/', + search: '', + }, + }; + const props = { + children: , + t: key => key, + history, + router: { route: history, history }, + }; + + const options = { + context: { + history, i18n, router: { route: history, history }, + }, + childContextTypes: { + history: PropTypes.object.isRequired, + i18n: PropTypes.object.isRequired, + router: PropTypes.object.isRequired, + }, + }; + + it('should render Tooltip if no props.account', () => { + const wrapper = mount(, options); + expect(wrapper.find('Tooltip')).toHaveLength(1); + }); + + it('should not render Tooltip if props.account.address exists', () => { + const account = { + address: '16313739661670634666L', + }; + const wrapper = mount( + + , options); + expect(wrapper.find('Tooltip')).toHaveLength(0); + expect(wrapper.find('span')).toHaveLength(1); + }); +}); From 9434fcbbc7e826506b15e0510554f3d559f35187 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 11:48:11 +0200 Subject: [PATCH 14/27] :recycle: Rename votingV2 to delegatesV2 --- i18n/locales/en/common.json | 1 + jest.config.js | 4 ++-- .../{votingV2/votingV2.js => delegatesV2/delegatesV2.js} | 4 ++-- .../votingV2.test.js => delegatesV2/delegatesV2.test.js} | 6 +++--- src/components/{votingV2 => delegatesV2}/index.js | 4 ++-- src/components/{votingV2 => delegatesV2}/votingHeader.css | 0 src/components/{votingV2 => delegatesV2}/votingHeader.js | 0 src/components/{votingV2 => delegatesV2}/votingV2.css | 0 src/constants/routes.js | 4 ++-- 9 files changed, 12 insertions(+), 11 deletions(-) rename src/components/{votingV2/votingV2.js => delegatesV2/delegatesV2.js} (94%) rename src/components/{votingV2/votingV2.test.js => delegatesV2/delegatesV2.test.js} (92%) rename src/components/{votingV2 => delegatesV2}/index.js (84%) rename src/components/{votingV2 => delegatesV2}/votingHeader.css (100%) rename src/components/{votingV2 => delegatesV2}/votingHeader.js (100%) rename src/components/{votingV2 => delegatesV2}/votingV2.css (100%) diff --git a/i18n/locales/en/common.json b/i18n/locales/en/common.json index 38880ed2d1..d0d4a93687 100644 --- a/i18n/locales/en/common.json +++ b/i18n/locales/en/common.json @@ -168,6 +168,7 @@ "Error retrieving convertion rates.": "Error retrieving convertion rates.", "Error retrieving dynamic fees.": "Error retrieving dynamic fees.", "Every transaction needs to be confirmed and forged into Lisks blockchain network. \n Such operations require hardware resources and because of that there is a small fee for processing those.": "Every transaction needs to be confirmed and forged into Lisks blockchain network. \n Such operations require hardware resources and because of that there is a small fee for processing those.", + "Every transaction needs to be confirmed and forged into Lisks blockchain network. \n Such operations require hardware resources and because of that there is a small fee for processing those.": "Every transaction needs to be confirmed and forged into Lisks blockchain network. \n Such operations require hardware resources and because of that there is a small fee for processing those.", "Explain Blockchain Like I'm 5": "Explain Blockchain Like I'm 5", "Explore as a Guest": "Explore as a Guest", "Failed to connect to node": "Failed to connect to node", diff --git a/jest.config.js b/jest.config.js index 4f671beae7..215978d33e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,7 +20,7 @@ module.exports = { 'src/store/middlewares/socket.test.js', 'src/store/middlewares/peers.test.js', 'src/components/votingListViewV2/*', - 'src/components/votingV2/*', + 'src/components/delegatesV2/*', 'src/components/registerV2/registerV2.test.js', 'src/components/headerV2/headerV2.test.js', ], @@ -132,7 +132,7 @@ module.exports = { 'src/components/loginV2/loginV2.js', 'src/utils/hwWallet.js', 'src/components/votingListViewV2/*', - 'src/components/votingV2/*', + 'src/components/delegatesV2/*', 'src/components/headerV2/headerV2.js', 'src/components/registerV2/registerV2.js', ], diff --git a/src/components/votingV2/votingV2.js b/src/components/delegatesV2/delegatesV2.js similarity index 94% rename from src/components/votingV2/votingV2.js rename to src/components/delegatesV2/delegatesV2.js index 59044a30b5..843a066e73 100644 --- a/src/components/votingV2/votingV2.js +++ b/src/components/delegatesV2/delegatesV2.js @@ -5,7 +5,7 @@ import VotingListViewV2 from '../votingListViewV2'; import VotingHeader from './votingHeader'; import { getTotalActions } from './../../utils/voting'; -class VotingV2 extends React.Component { +class DelegatesV2 extends React.Component { constructor({ votes }) { super(); @@ -43,4 +43,4 @@ class VotingV2 extends React.Component { } } -export default VotingV2; +export default DelegatesV2; diff --git a/src/components/votingV2/votingV2.test.js b/src/components/delegatesV2/delegatesV2.test.js similarity index 92% rename from src/components/votingV2/votingV2.test.js rename to src/components/delegatesV2/delegatesV2.test.js index fe5dcc468f..9ef3d79f88 100644 --- a/src/components/votingV2/votingV2.test.js +++ b/src/components/delegatesV2/delegatesV2.test.js @@ -7,11 +7,11 @@ import { prepareStore } from '../../../test/unit-test-utils/applicationInit'; import peersReducer from '../../store/reducers/peers'; import accountReducer from '../../store/reducers/account'; import votingReducer from '../../store/reducers/voting'; -import VotingV2 from './votingV2'; +import DelegatesV2 from './delegatesV2'; import history from '../../history'; import i18n from '../../i18n'; -describe('VotingV2', () => { +describe('DelegatesV2', () => { let wrapper; const votes = { username1: { confirmed: true, unconfirmed: true, publicKey: 'sample_key' }, @@ -48,7 +48,7 @@ describe('VotingV2', () => { }; beforeEach(() => { wrapper = mount( -, +, { context: { store, history, i18n }, childContextTypes: { diff --git a/src/components/votingV2/index.js b/src/components/delegatesV2/index.js similarity index 84% rename from src/components/votingV2/index.js rename to src/components/delegatesV2/index.js index a26f3ce9c5..f1313bf126 100644 --- a/src/components/votingV2/index.js +++ b/src/components/delegatesV2/index.js @@ -1,7 +1,7 @@ /* istanbul ignore file */ import { connect } from 'react-redux'; import { translate } from 'react-i18next'; -import VotingV2 from './votingV2'; +import DelegatesV2 from './delegatesV2'; import { clearVotes } from '../../actions/voting'; const mapStateToProps = state => ({ @@ -12,4 +12,4 @@ const mapDispatchToProps = { clearVotes, }; -export default connect(mapStateToProps, mapDispatchToProps)(translate()(VotingV2)); +export default connect(mapStateToProps, mapDispatchToProps)(translate()(DelegatesV2)); diff --git a/src/components/votingV2/votingHeader.css b/src/components/delegatesV2/votingHeader.css similarity index 100% rename from src/components/votingV2/votingHeader.css rename to src/components/delegatesV2/votingHeader.css diff --git a/src/components/votingV2/votingHeader.js b/src/components/delegatesV2/votingHeader.js similarity index 100% rename from src/components/votingV2/votingHeader.js rename to src/components/delegatesV2/votingHeader.js diff --git a/src/components/votingV2/votingV2.css b/src/components/delegatesV2/votingV2.css similarity index 100% rename from src/components/votingV2/votingV2.css rename to src/components/delegatesV2/votingV2.css diff --git a/src/constants/routes.js b/src/constants/routes.js index 1518897535..e06c80b67a 100644 --- a/src/constants/routes.js +++ b/src/constants/routes.js @@ -9,7 +9,7 @@ import SearchResult from '../components/searchResult'; import TransactionDashboard from '../components/transactionDashboard'; import AccountTransactions from '../components/accountTransactions'; import Voting from '../components/voting'; -import VotingV2 from '../components/votingV2'; +import DelegatesV2 from '../components/delegatesV2'; import VotingSummary from '../components/votingSummary'; import SingleTransaction from '../components/singleTransactionV2'; import HwWalletLogin from '../components/hwWalletLogin'; @@ -56,7 +56,7 @@ export default { }, delegatesV2: { path: '/delegatesV2', - component: VotingV2, + component: DelegatesV2, isPrivate: false, }, help: { From f55d8d2bb82f53230bc0476136d707c05700f368 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 11:50:57 +0200 Subject: [PATCH 15/27] :recycle: Rename votingSummary to votingV2 --- src/components/{votingSummary => votingV2}/index.js | 0 src/components/{votingSummary => votingV2}/votingSummary.css | 0 src/components/{votingSummary => votingV2}/votingSummary.js | 0 src/constants/routes.js | 4 ++-- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/components/{votingSummary => votingV2}/index.js (100%) rename src/components/{votingSummary => votingV2}/votingSummary.css (100%) rename src/components/{votingSummary => votingV2}/votingSummary.js (100%) diff --git a/src/components/votingSummary/index.js b/src/components/votingV2/index.js similarity index 100% rename from src/components/votingSummary/index.js rename to src/components/votingV2/index.js diff --git a/src/components/votingSummary/votingSummary.css b/src/components/votingV2/votingSummary.css similarity index 100% rename from src/components/votingSummary/votingSummary.css rename to src/components/votingV2/votingSummary.css diff --git a/src/components/votingSummary/votingSummary.js b/src/components/votingV2/votingSummary.js similarity index 100% rename from src/components/votingSummary/votingSummary.js rename to src/components/votingV2/votingSummary.js diff --git a/src/constants/routes.js b/src/constants/routes.js index e06c80b67a..79f6e97a19 100644 --- a/src/constants/routes.js +++ b/src/constants/routes.js @@ -10,7 +10,7 @@ import TransactionDashboard from '../components/transactionDashboard'; import AccountTransactions from '../components/accountTransactions'; import Voting from '../components/voting'; import DelegatesV2 from '../components/delegatesV2'; -import VotingSummary from '../components/votingSummary'; +import VotingV2 from '../components/votingV2'; import SingleTransaction from '../components/singleTransactionV2'; import HwWalletLogin from '../components/hwWalletLogin'; // import NotFound from '../components/notFound'; @@ -51,7 +51,7 @@ export default { }, voting: { path: '/delegatesV2/vote', - component: VotingSummary, + component: VotingV2, isPrivate: true, }, delegatesV2: { From d660de945e82807292754e412cb13d89bde8ae4f Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 12:12:26 +0200 Subject: [PATCH 16/27] :seedling: Create voting result step --- src/components/transactionSummary/index.js | 62 +++++++++---------- .../transactionSummary/transactionSummary.css | 9 --- .../voteUrlProcessorV2/voteUrlProcessor.js | 2 +- src/components/votingV2/index.js | 5 +- src/components/votingV2/votingResult.js | 10 +++ src/components/votingV2/votingSummary.js | 9 +-- .../{votingSummary.css => votingV2.css} | 9 +++ src/components/votingV2/votingV2.js | 27 ++++++++ 8 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 src/components/votingV2/votingResult.js rename src/components/votingV2/{votingSummary.css => votingV2.css} (86%) create mode 100644 src/components/votingV2/votingV2.js diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js index c9b77bbcff..1e4c35f247 100644 --- a/src/components/transactionSummary/index.js +++ b/src/components/transactionSummary/index.js @@ -8,39 +8,37 @@ const checkSecondPassphrase = () => {}; const TransactionSummary = ({ title, children, confirmButton, cancelButton, account, t, }) => ( -
-
-
-

{title}

-
-
- {children} - {account.secondPublicKey ? -
- - -
- : null - } -
-
- - {confirmButton.label} - - - {cancelButton.label} - -
+
+
+

{title}

+
+
+ {children} + {account.secondPublicKey ? +
+ + +
+ : null + }
+
+ + {confirmButton.label} + + + {cancelButton.label} + +
); diff --git a/src/components/transactionSummary/transactionSummary.css b/src/components/transactionSummary/transactionSummary.css index dad54f40fe..4ee3919b3d 100644 --- a/src/components/transactionSummary/transactionSummary.css +++ b/src/components/transactionSummary/transactionSummary.css @@ -1,15 +1,6 @@ @import '../app/variablesV2.css'; @import '../app/mixins.css'; -.container { - display: flex; - flex-direction: column; - justify-content: center; - height: 100%; - align-items: center; - width: 100%; -} - .wrapper { width: 100%; display: flex; diff --git a/src/components/voteUrlProcessorV2/voteUrlProcessor.js b/src/components/voteUrlProcessorV2/voteUrlProcessor.js index a94d19fbce..2f29c01bb6 100644 --- a/src/components/voteUrlProcessorV2/voteUrlProcessor.js +++ b/src/components/voteUrlProcessorV2/voteUrlProcessor.js @@ -2,7 +2,7 @@ import React from 'react'; import { parseSearchParams } from '../../utils/searchParams'; import routes from '../../constants/routes'; -import styles from '../votingSummary/votingSummary.css'; +import styles from '../votingV2/votingV2.css'; export default class VoteUrlProcessor extends React.Component { constructor(props) { diff --git a/src/components/votingV2/index.js b/src/components/votingV2/index.js index bd8fb89baf..26e031e226 100644 --- a/src/components/votingV2/index.js +++ b/src/components/votingV2/index.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { translate } from 'react-i18next'; import { withRouter } from 'react-router'; -import VotingSummary from './votingSummary'; +import VotingV2 from './votingV2'; import { clearVotes } from '../../actions/voting'; const mapStateToProps = state => ({ @@ -14,5 +14,4 @@ const mapDispatchToProps = { clearVotes, }; -export default withRouter(connect(mapStateToProps, mapDispatchToProps)(translate()(VotingSummary))); - +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(translate()(VotingV2))); diff --git a/src/components/votingV2/votingResult.js b/src/components/votingV2/votingResult.js new file mode 100644 index 0000000000..f63f26a427 --- /dev/null +++ b/src/components/votingV2/votingResult.js @@ -0,0 +1,10 @@ +import React from 'react'; + +const VotingResult = () => ( +
+

Voting Result - TODO

+
+); + +export default VotingResult; + diff --git a/src/components/votingV2/votingSummary.js b/src/components/votingV2/votingSummary.js index 34bf0a91be..c45657fd5f 100644 --- a/src/components/votingV2/votingSummary.js +++ b/src/components/votingV2/votingSummary.js @@ -12,11 +12,10 @@ import Tooltip from '../toolbox/tooltip/tooltip'; import links from '../../constants/externalLinks'; import VoteUrlProcessor from '../voteUrlProcessorV2'; - -import styles from './votingSummary.css'; +import styles from './votingV2.css'; const VotingSummary = ({ - t, votes, history, account, + t, votes, history, account, nextStep, }) => { const { maxCountOfVotes, @@ -31,7 +30,9 @@ const VotingSummary = ({ account={account} confirmButton={{ label: t('Confirm voting'), - onClick: () => {}, + onClick: () => { + nextStep(); + }, }} cancelButton={{ label: t('Edit voting'), diff --git a/src/components/votingV2/votingSummary.css b/src/components/votingV2/votingV2.css similarity index 86% rename from src/components/votingV2/votingSummary.css rename to src/components/votingV2/votingV2.css index 07805449c5..d98bd557a0 100644 --- a/src/components/votingV2/votingSummary.css +++ b/src/components/votingV2/votingV2.css @@ -1,6 +1,15 @@ @import '../app/variablesV2.css'; @import '../app/mixins.css'; +.wrapper { + display: flex; + flex-direction: column; + justify-content: center; + height: 100%; + align-items: center; + width: 100%; +} + .votesContainer { display: flex; flex-wrap: wrap; diff --git a/src/components/votingV2/votingV2.js b/src/components/votingV2/votingV2.js new file mode 100644 index 0000000000..41d6bd03f4 --- /dev/null +++ b/src/components/votingV2/votingV2.js @@ -0,0 +1,27 @@ +import React from 'react'; +import VotingSummary from './votingSummary'; +import VotingResult from './votingResult'; +import MultiStep from '../multiStep'; + +import styles from './votingV2.css'; + +const VotingV2 = ({ + t, votes, history, account, +}) => ( +
+ + + + +
+); + +export default VotingV2; From 3a09702e117984a4eb3108ee1bb9734d6df602a5 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 12:19:41 +0200 Subject: [PATCH 17/27] :seedling: Implement vote submission in votingSummaryV2 --- src/components/votingV2/index.js | 3 ++- src/components/votingV2/votingSummary.js | 9 +++++++-- src/components/votingV2/votingV2.js | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/votingV2/index.js b/src/components/votingV2/index.js index 26e031e226..1307ffb4e9 100644 --- a/src/components/votingV2/index.js +++ b/src/components/votingV2/index.js @@ -3,7 +3,7 @@ import { connect } from 'react-redux'; import { translate } from 'react-i18next'; import { withRouter } from 'react-router'; import VotingV2 from './votingV2'; -import { clearVotes } from '../../actions/voting'; +import { clearVotes, votePlaced } from '../../actions/voting'; const mapStateToProps = state => ({ votes: state.voting.votes, @@ -12,6 +12,7 @@ const mapStateToProps = state => ({ const mapDispatchToProps = { clearVotes, + votePlaced, }; export default withRouter(connect(mapStateToProps, mapDispatchToProps)(translate()(VotingV2))); diff --git a/src/components/votingV2/votingSummary.js b/src/components/votingV2/votingSummary.js index c45657fd5f..70d499f354 100644 --- a/src/components/votingV2/votingSummary.js +++ b/src/components/votingV2/votingSummary.js @@ -15,7 +15,7 @@ import VoteUrlProcessor from '../voteUrlProcessorV2'; import styles from './votingV2.css'; const VotingSummary = ({ - t, votes, history, account, nextStep, + t, votes, history, account, nextStep, votePlaced, }) => { const { maxCountOfVotes, @@ -31,7 +31,12 @@ const VotingSummary = ({ confirmButton={{ label: t('Confirm voting'), onClick: () => { - nextStep(); + votePlaced({ + account, + votes, + passphrase: account.passphrase, + goToNextStep: nextStep, + }); }, }} cancelButton={{ diff --git a/src/components/votingV2/votingV2.js b/src/components/votingV2/votingV2.js index 41d6bd03f4..098d668b34 100644 --- a/src/components/votingV2/votingV2.js +++ b/src/components/votingV2/votingV2.js @@ -6,7 +6,7 @@ import MultiStep from '../multiStep'; import styles from './votingV2.css'; const VotingV2 = ({ - t, votes, history, account, + t, votes, history, account, votePlaced, }) => (
@@ -15,6 +15,7 @@ const VotingV2 = ({ votes={votes} history={history} account={account} + votePlaced={votePlaced} /> Date: Wed, 22 May 2019 12:52:50 +0200 Subject: [PATCH 18/27] :seedling: Implement submitting votes with 2nd passphrase --- src/components/transactionSummary/index.js | 76 +++++++++++++++++----- src/components/votingV2/votingSummary.js | 3 +- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js index 1e4c35f247..83210c9ee2 100644 --- a/src/components/transactionSummary/index.js +++ b/src/components/transactionSummary/index.js @@ -1,14 +1,57 @@ import React from 'react'; import { PrimaryButtonV2, TertiaryButtonV2 } from '../toolbox/buttons/button'; import PassphraseInputV2 from '../passphraseInputV2/passphraseInputV2'; +import { extractPublicKey } from '../../utils/account'; + import styles from './transactionSummary.css'; -const checkSecondPassphrase = () => {}; +class TransactionSummary extends React.Component { + constructor(props) { + super(props); + + this.state = { + secondPassphrase: { + isValid: false, + feedback: '', + value: null, + }, + }; + this.checkSecondPassphrase = this.checkSecondPassphrase.bind(this); + this.confirmOnClick = this.confirmOnClick.bind(this); + } + + checkSecondPassphrase(passphrase, error) { + let feedback = error || ''; + const expectedPublicKey = !error && extractPublicKey(passphrase); + const isPassphraseValid = this.props.account.secondPublicKey === expectedPublicKey; -const TransactionSummary = ({ - title, children, confirmButton, cancelButton, account, t, -}) => ( -
+ if (feedback === '' && !isPassphraseValid) { + feedback = this.props.t('Oops! Wrong passphrase'); + } + this.setState({ + secondPassphrase: { + ...this.state.secondPassphrase, + isValid: feedback === '' && passphrase !== '', + feedback, + value: passphrase, + }, + }); + } + + confirmOnClick() { + this.props.confirmButton.onClick({ + secondPassphrase: this.state.secondPassphrase.value, + }); + } + + render() { + const { + title, children, confirmButton, cancelButton, account, t, + } = this.props; + const { + secondPassphrase, + } = this.state; + return

{title}

@@ -16,13 +59,13 @@ const TransactionSummary = ({ {children} {account.secondPublicKey ?
- - + +
: null } @@ -30,7 +73,8 @@ const TransactionSummary = ({
+ disabled={!!account.secondPublicKey && !secondPassphrase.isValid} + onClick={this.confirmOnClick}> {confirmButton.label}
-
-); +
; + } +} export default TransactionSummary; - diff --git a/src/components/votingV2/votingSummary.js b/src/components/votingV2/votingSummary.js index 70d499f354..f36193f65b 100644 --- a/src/components/votingV2/votingSummary.js +++ b/src/components/votingV2/votingSummary.js @@ -30,11 +30,12 @@ const VotingSummary = ({ account={account} confirmButton={{ label: t('Confirm voting'), - onClick: () => { + onClick: ({ secondPassphrase }) => { votePlaced({ account, votes, passphrase: account.passphrase, + secondPassphrase, goToNextStep: nextStep, }); }, From bad2afc964bf4040ca5f8a1c7e0f3814cf43c8f8 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 14:49:49 +0200 Subject: [PATCH 19/27] :seedling: Implement illustration toolbox component --- .../illustration-trezor-confirm-light.svg | 38 +++++++++++++++++++ src/components/toolbox/illustration/index.js | 13 +++++++ 2 files changed, 51 insertions(+) create mode 100644 src/assets/images/illustrations/illustration-trezor-confirm-light.svg create mode 100644 src/components/toolbox/illustration/index.js diff --git a/src/assets/images/illustrations/illustration-trezor-confirm-light.svg b/src/assets/images/illustrations/illustration-trezor-confirm-light.svg new file mode 100644 index 0000000000..a1b719cea4 --- /dev/null +++ b/src/assets/images/illustrations/illustration-trezor-confirm-light.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/toolbox/illustration/index.js b/src/components/toolbox/illustration/index.js new file mode 100644 index 0000000000..5df094cedc --- /dev/null +++ b/src/components/toolbox/illustration/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import ledgerNanoLight from '../../../assets/images/illustrations/illustration-ledger-nano-light.svg'; +import trezorLight from '../../../assets/images/illustrations/illustration-trezor-confirm-light.svg'; + +const illustrations = { + ledgerNanoLight, + trezorLight, +}; + +const Illustration = ({ name, className }) => ( + +); +export default Illustration; From 0100a5bce272873069084ea8049cf9324b4a7663 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 22 May 2019 14:50:47 +0200 Subject: [PATCH 20/27] :seedling: Implement voting with hw wallet in new design --- src/components/transactionSummary/index.js | 43 +++++++++++++++---- .../transactionSummary/transactionSummary.css | 16 +++++-- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/components/transactionSummary/index.js b/src/components/transactionSummary/index.js index 83210c9ee2..700ace7936 100644 --- a/src/components/transactionSummary/index.js +++ b/src/components/transactionSummary/index.js @@ -1,5 +1,6 @@ import React from 'react'; import { PrimaryButtonV2, TertiaryButtonV2 } from '../toolbox/buttons/button'; +import Illustration from '../toolbox/illustration'; import PassphraseInputV2 from '../passphraseInputV2/passphraseInputV2'; import { extractPublicKey } from '../../utils/account'; @@ -8,8 +9,10 @@ import styles from './transactionSummary.css'; class TransactionSummary extends React.Component { constructor(props) { super(props); + const { account } = props; this.state = { + isHardwareWalletConnected: !!(account.hwInfo && account.hwInfo.deviceId), secondPassphrase: { isValid: false, feedback: '', @@ -18,6 +21,14 @@ class TransactionSummary extends React.Component { }; this.checkSecondPassphrase = this.checkSecondPassphrase.bind(this); this.confirmOnClick = this.confirmOnClick.bind(this); + this.getHwWalletIllustration = this.getHwWalletIllustration.bind(this); + } + componentDidMount() { + const { isHardwareWalletConnected } = this.state; + + if (isHardwareWalletConnected) { + this.confirmOnClick(); + } } checkSecondPassphrase(passphrase, error) { @@ -44,16 +55,29 @@ class TransactionSummary extends React.Component { }); } + getHwWalletIllustration() { + return { + 'Trezor Model T': 'trezorLight', + 'Ledger Nano S': 'ledgerNanoLight', + }[this.props.account.hwInfo.deviceModel]; + } + render() { const { title, children, confirmButton, cancelButton, account, t, } = this.props; const { - secondPassphrase, + secondPassphrase, isHardwareWalletConnected, } = this.state; return
-

{title}

+ { isHardwareWalletConnected ? + +

{t('Confirm transaction on your {{deviceModel}}', { deviceModel: account.hwInfo.deviceModel })}

+

{t('Please check if all the transaction details are correct.')}

+ +
: null } +

{title}

{children} @@ -71,12 +95,15 @@ class TransactionSummary extends React.Component { }