From 7d3d9aefb9d5bbc857ad4a8b2176807c985babcf Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 18 Sep 2017 15:55:42 +0200 Subject: [PATCH 01/36] Add voting bar e2e test specification --- features/voting.feature | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/features/voting.feature b/features/voting.feature index 5d455df0a..ef6aa3146 100644 --- a/features/voting.feature +++ b/features/voting.feature @@ -36,6 +36,19 @@ Feature: Voting tab Then I should see "Insufficient funds for 1 LSK fee" error message And "submit button" should be disabled + @ignore + Scenario: should display voting bar with numbers of selected votes if any selected + Given I'm logged in as "delegate candidate" + When I click tab number 2 + And I should see no "voting bar" + And I click checkbox on table row no. 3 + Then I should see text "Upvotes: 1 Downvotes: 0 Total new votes: 1 / 33 Total votes: 1 / 101" in "voting bar" elment + And I click checkbox on table row no. 5 + And I should see text "Upvotes: 2 Downvotes: 0 Total new votes: 2 / 33 Total votes: 2 / 101" in "voting bar" elment + And I click checkbox on table row no. 3 + And I click checkbox on table row no. 5 + And I should see no "voting bar" + Scenario: should allow to select delegates in the "Voting" tab and vote for them Given I'm logged in as "delegate candidate" When I click tab number 2 From 79dc67c2812b1ba0af5adec66bafc0d41b93c6a4 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 19 Sep 2017 12:03:08 +0200 Subject: [PATCH 02/36] Add voting bar with summary numbers of votes --- src/components/voting/voting.js | 11 ++++--- src/components/voting/votingBar.css | 9 ++++++ src/components/voting/votingBar.js | 48 +++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 src/components/voting/votingBar.css create mode 100644 src/components/voting/votingBar.js diff --git a/src/components/voting/voting.js b/src/components/voting/voting.js index d5151c638..bfd7b365e 100644 --- a/src/components/voting/voting.js +++ b/src/components/voting/voting.js @@ -1,11 +1,13 @@ -import React from 'react'; -import { themr } from 'react-css-themr'; import { TABLE } from 'react-toolbox/lib/identifiers'; -import { tableFactory } from 'react-toolbox/lib/table/Table'; import { TableHead, TableCell } from 'react-toolbox/lib/table'; +import { tableFactory } from 'react-toolbox/lib/table/Table'; +import { themr } from 'react-css-themr'; +import React from 'react'; import TableTheme from 'react-toolbox/lib/table/theme.css'; import Waypoint from 'react-waypoint'; + import Header from './votingHeader'; +import VotingBar from './votingBar'; import VotingRow from './votingRow'; // Create a new Table component injecting Head and Row @@ -40,7 +42,7 @@ class Voting extends React.Component { } loadVotedDelegates(refresh) { - /* istanbul-ignore-else */ + /* istanbul-ignore-else */ if (!this.freezeLoading) { this.props.votesFetched({ activePeer: this.props.activePeer, @@ -126,6 +128,7 @@ class Voting extends React.Component { scrollableAncestor={window} key={this.props.delegates.length} onEnter={this.loadMore.bind(this)}> + ); } diff --git a/src/components/voting/votingBar.css b/src/components/voting/votingBar.css new file mode 100644 index 000000000..f255da0ff --- /dev/null +++ b/src/components/voting/votingBar.css @@ -0,0 +1,9 @@ +.red { + color: #c62828; +} + +.fixedAtBottom { + position: fixed; + bottom: 0; + left: 0; +} diff --git a/src/components/voting/votingBar.js b/src/components/voting/votingBar.js new file mode 100644 index 000000000..46708e41c --- /dev/null +++ b/src/components/voting/votingBar.js @@ -0,0 +1,48 @@ +import React from 'react'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; + +import style from './votingBar.css'; + +const VotingBar = ({ votes }) => { + const voteMaxCount = 33; + const votedMaxCount = 101; + const votedList = Object.keys(votes).filter(key => votes[key].confirmed); + const voteList = Object.keys(votes).filter( + key => votes[key].unconfirmed && !votes[key].confirmed); + const unvoteList = Object.keys(votes).filter( + key => !votes[key].unconfirmed && votes[key].confirmed); + const totalVotesCount = (votedList.length - unvoteList.length) + voteList.length; + const totalNewVotesCount = voteList.length + unvoteList.length; + + return (voteList.length + unvoteList.length ? +
+
+ + Upvotes: + {voteList.length} + + + Downvotes: + {unvoteList.length} + + + Total new votes + voteMaxCount && style.red}> + {voteList.length + unvoteList.length} + + / {voteMaxCount} + + + Total votes: + 101 && style.red}> + {(votedList.length - unvoteList.length) + voteList.length} + + / {votedMaxCount} + +
+
: + null + ); +}; + +export default VotingBar; From 476042307182c2cf0e3bc7a254c35caeee554d3d Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 19 Sep 2017 12:38:31 +0200 Subject: [PATCH 03/36] Add unit tests for votingBar --- src/components/voting/votingBar.js | 14 +++--- src/components/voting/votingBar.test.js | 57 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/components/voting/votingBar.test.js diff --git a/src/components/voting/votingBar.js b/src/components/voting/votingBar.js index 46708e41c..d291f106c 100644 --- a/src/components/voting/votingBar.js +++ b/src/components/voting/votingBar.js @@ -17,25 +17,25 @@ const VotingBar = ({ votes }) => { return (voteList.length + unvoteList.length ?
- + Upvotes: {voteList.length} - + Downvotes: {unvoteList.length} - - Total new votes + + Total new votes: voteMaxCount && style.red}> - {voteList.length + unvoteList.length} + {totalNewVotesCount} / {voteMaxCount} - + Total votes: 101 && style.red}> - {(votedList.length - unvoteList.length) + voteList.length} + {totalVotesCount} / {votedMaxCount} diff --git a/src/components/voting/votingBar.test.js b/src/components/voting/votingBar.test.js new file mode 100644 index 000000000..927e11e06 --- /dev/null +++ b/src/components/voting/votingBar.test.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { expect } from 'chai'; +import { mount } from 'enzyme'; +import VotingBar from './votingBar'; + +describe.only('VotingBar', () => { + let wrapper; + const props = { + votes: { + voted: { + confirmed: true, + unconfirmed: false, + }, + downvote: { + confirmed: true, + unconfirmed: true, + }, + upvote: { + confirmed: false, + unconfirmed: true, + }, + upvote2: { + confirmed: false, + unconfirmed: true, + }, + notVoted: { + confirmed: false, + unconfirmed: false, + }, + }, + }; + beforeEach(() => { + wrapper = mount(); + }); + + it('should render number of upvotes', () => { + expect(wrapper.find('.upvotes').text()).to.equal('Upvotes: 2'); + }); + + it('should render number of downvotes', () => { + expect(wrapper.find('.downvotes').text()).to.equal('Downvotes: 1'); + }); + + it('should render number of downvotes', () => { + expect(wrapper.find('.total-new-votes').text()).to.equal('Total new votes: 3 / 33'); + }); + + it('should render number of total votes', () => { + expect(wrapper.find('.total-votes').text()).to.equal('Total votes: 3 / 101'); + }); + + it('should not render if no upvotes or downvotes', () => { + wrapper.setProps({ votes: {} }); + expect(wrapper.html()).to.equal(null); + }); +}); + From 5b6dc016a60851d93f51f3b9367aef0cb697bcba Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 19 Sep 2017 13:16:05 +0200 Subject: [PATCH 04/36] Enable voting bar e2e test --- features/step_definitions/generic.step.js | 9 +++++++-- features/voting.feature | 17 ++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/features/step_definitions/generic.step.js b/features/step_definitions/generic.step.js index ce6dc887f..e083f8c9d 100644 --- a/features/step_definitions/generic.step.js +++ b/features/step_definitions/generic.step.js @@ -114,8 +114,13 @@ defineSupportCode(({ Given, When, Then, setDefaultTimeout }) => { .and.notify(callback); }); - Then('I should see text "{text}" in "{fieldName}" element', (text, fieldName, callback) => { - const selectorClass = `.${fieldName.replace(/ /g, '-')}`; + Then('I should see text "{text}" in "{elementName}" element', (text, elementName, callback) => { + const selectorClass = `.${elementName.replace(/ /g, '-')}`; + waitForElemAndCheckItsText(selectorClass, text, callback); + }); + + Then('I should see element "{elementName}" that contains text:', (elementName, text, callback) => { + const selectorClass = `.${elementName.replace(/ /g, '-')}`; waitForElemAndCheckItsText(selectorClass, text, callback); }); diff --git a/features/voting.feature b/features/voting.feature index ef6aa3146..f66bbae40 100644 --- a/features/voting.feature +++ b/features/voting.feature @@ -36,15 +36,26 @@ Feature: Voting tab Then I should see "Insufficient funds for 1 LSK fee" error message And "submit button" should be disabled - @ignore Scenario: should display voting bar with numbers of selected votes if any selected Given I'm logged in as "delegate candidate" When I click tab number 2 And I should see no "voting bar" And I click checkbox on table row no. 3 - Then I should see text "Upvotes: 1 Downvotes: 0 Total new votes: 1 / 33 Total votes: 1 / 101" in "voting bar" elment + Then I should see element "voting bar" that contains text: + """ + Upvotes: 1 + Downvotes: 0 + Total new votes: 1 / 33 + Total votes: 1 / 101 + """ And I click checkbox on table row no. 5 - And I should see text "Upvotes: 2 Downvotes: 0 Total new votes: 2 / 33 Total votes: 2 / 101" in "voting bar" elment + And I should see element "voting bar" that contains text: + """ + Upvotes: 2 + Downvotes: 0 + Total new votes: 2 / 33 + Total votes: 2 / 101 + """ And I click checkbox on table row no. 3 And I click checkbox on table row no. 5 And I should see no "voting bar" From dfada0d81912d646a4c013c3f3b118e253498eb2 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 19 Sep 2017 15:14:00 +0200 Subject: [PATCH 05/36] Add more votingBar unit tests --- src/components/voting/votingBar.test.js | 39 +++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/components/voting/votingBar.test.js b/src/components/voting/votingBar.test.js index 927e11e06..1dbac3cb8 100644 --- a/src/components/voting/votingBar.test.js +++ b/src/components/voting/votingBar.test.js @@ -1,9 +1,12 @@ import React from 'react'; import { expect } from 'chai'; import { mount } from 'enzyme'; + import VotingBar from './votingBar'; -describe.only('VotingBar', () => { +import styles from './votingBar.css'; + +describe('VotingBar', () => { let wrapper; const props = { votes: { @@ -29,29 +32,55 @@ describe.only('VotingBar', () => { }, }, }; + + const generateNVotes = n => ( + [...Array(n)].map((item, i) => i).reduce( + (dict, value) => { + dict[`genesis_${value}`] = { unconfirmed: true }; + return dict; + }, {}) + ); + beforeEach(() => { wrapper = mount(); }); it('should render number of upvotes', () => { - expect(wrapper.find('.upvotes').text()).to.equal('Upvotes: 2'); + expect(wrapper.find('.upvotes')).to.have.text('Upvotes: 2'); }); it('should render number of downvotes', () => { - expect(wrapper.find('.downvotes').text()).to.equal('Downvotes: 1'); + expect(wrapper.find('.downvotes')).to.have.text('Downvotes: 1'); }); it('should render number of downvotes', () => { - expect(wrapper.find('.total-new-votes').text()).to.equal('Total new votes: 3 / 33'); + expect(wrapper.find('.total-new-votes')).to.have.text('Total new votes: 3 / 33'); }); it('should render number of total votes', () => { - expect(wrapper.find('.total-votes').text()).to.equal('Total votes: 3 / 101'); + expect(wrapper.find('.total-votes')).to.have.text('Total votes: 3 / 101'); }); it('should not render if no upvotes or downvotes', () => { wrapper.setProps({ votes: {} }); expect(wrapper.html()).to.equal(null); }); + + it('should render number of total votes in red if 101 exceeded', () => { + const votes = generateNVotes(102); + + expect(wrapper.find(`.total-votes .${styles.red}`)).to.be.not.present(); + wrapper.setProps({ votes }); + expect(wrapper.find('.total-votes')).to.have.text('Total votes: 102 / 101'); + expect(wrapper.find(`.total-votes .${styles.red}`)).to.have.text('102'); + }); + + it('should render number of total new votes in red if 33 exceeded', () => { + const votes = generateNVotes(34); + expect(wrapper.find(`.total-new-votes .${styles.red}`)).to.be.not.present(); + wrapper.setProps({ votes }); + expect(wrapper.find('.total-new-votes')).to.have.text('Total new votes: 34 / 33'); + expect(wrapper.find(`.total-new-votes .${styles.red}`)).to.have.text('34'); + }); }); From 50a91cfcd5a79ac4ffd253bcfa5a588292a10248 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 20 Sep 2017 13:11:30 +0200 Subject: [PATCH 06/36] Add voting middleware ... that shows an error toast if more than 33 delegates selected --- src/constants/voting.js | 6 +++ src/store/middlewares/index.js | 2 + src/store/middlewares/voting.js | 23 ++++++++++ src/store/middlewares/voting.test.js | 68 ++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 src/constants/voting.js create mode 100644 src/store/middlewares/voting.js create mode 100644 src/store/middlewares/voting.test.js diff --git a/src/constants/voting.js b/src/constants/voting.js new file mode 100644 index 000000000..bc8bcaa0f --- /dev/null +++ b/src/constants/voting.js @@ -0,0 +1,6 @@ +const votingConst = { + maxCountOfVotesInOneTurn: 33, + maxCountOfVotes: 101, +}; + +export default votingConst; diff --git a/src/store/middlewares/index.js b/src/store/middlewares/index.js index 6899dc017..b6c9eea9e 100644 --- a/src/store/middlewares/index.js +++ b/src/store/middlewares/index.js @@ -6,6 +6,7 @@ import addedTransactionMiddleware from './addedTransaction'; import loadingBarMiddleware from './loadingBar'; import offlineMiddleware from './offline'; import notificationMiddleware from './notification'; +import votingMiddleware from './voting'; export default [ thunk, @@ -16,4 +17,5 @@ export default [ loadingBarMiddleware, offlineMiddleware, notificationMiddleware, + votingMiddleware, ]; diff --git a/src/store/middlewares/voting.js b/src/store/middlewares/voting.js new file mode 100644 index 000000000..9e0f4bc55 --- /dev/null +++ b/src/store/middlewares/voting.js @@ -0,0 +1,23 @@ +import actionTypes from '../../constants/actions'; +import votingConst from '../../constants/voting'; +import { errorToastDisplayed } from '../../actions/toaster'; + +const votingMiddleware = store => next => (action) => { + next(action); + if (action.type === actionTypes.voteToggled) { + const { votes } = store.getState().voting; + const voteCount = Object.keys(votes).filter( + key => votes[key].confirmed !== votes[key].unconfirmed).length; + const currentVote = votes[action.data.username] || { unconfirmed: true, confirmed: false }; + console.log(voteCount, votingConst.maxCountOfVotesInOneTurn, currentVote); + if (voteCount === votingConst.maxCountOfVotesInOneTurn + 1 && + currentVote.unconfirmed !== currentVote.confirmed) { + const label = `Maximum of ${votingConst.maxCountOfVotesInOneTurn} votes in one transaction exceeded.`; + const newAction = errorToastDisplayed({ label }); + store.dispatch(newAction); + } + } +}; + +export default votingMiddleware; + diff --git a/src/store/middlewares/voting.test.js b/src/store/middlewares/voting.test.js new file mode 100644 index 000000000..1237fbecc --- /dev/null +++ b/src/store/middlewares/voting.test.js @@ -0,0 +1,68 @@ +import { expect } from 'chai'; +import { spy, stub } from 'sinon'; +import { errorToastDisplayed } from '../../actions/toaster'; +import middleware from './voting'; +import actionTypes from '../../constants/actions'; +import votingConst from '../../constants/voting'; + +describe('voting middleware', () => { + let store; + let next; + const label = `Maximum of ${votingConst.maxCountOfVotesInOneTurn} votes in one transaction exceeded.`; + + const generateNVotes = n => ( + [...Array(n)].map((item, i) => i).reduce( + (dict, value) => { + dict[`genesis_${value}`] = { confirmed: false, unconfirmed: true }; + return dict; + }, {}) + ); + + beforeEach(() => { + store = stub(); + store.getState = () => ({ + voting: { + votes: { + ...generateNVotes(votingConst.maxCountOfVotesInOneTurn + 1), + test2: { + unconfirmed: false, + confirmed: false, + }, + }, + }, + }); + store.dispatch = spy(); + next = spy(); + }); + + it('should passes the action to next middleware', () => { + const givenAction = { + type: 'TEST_ACTION', + }; + + middleware(store)(next)(givenAction); + expect(next).to.have.been.calledWith(givenAction); + }); + + it('should dispatch errorToastDisplayed if 34 new votes and new vote unconfirmed !== confirmed ', () => { + const givenAction = { + type: actionTypes.voteToggled, + data: { + username: 'test', + }, + }; + middleware(store)(next)(givenAction); + expect(store.dispatch).to.have.been.calledWith(errorToastDisplayed({ label })); + }); + + it('should not dispatch errorToastDisplayed if 34 new votes and new vote unconfirmed === confirmed ', () => { + const givenAction = { + type: actionTypes.voteToggled, + data: { + username: 'test2', + }, + }; + middleware(store)(next)(givenAction); + expect(store.dispatch).to.not.have.been.calledWith(errorToastDisplayed({ label })); + }); +}); From 9348eb973219f1f9e371329e51778338ca1f55e6 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 20 Sep 2017 13:13:11 +0200 Subject: [PATCH 07/36] Use votingConst in votingBar and voteDialog --- src/components/voteDialog/voteDialog.js | 11 +++++++---- src/components/voting/votingBar.js | 10 +++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/voteDialog/voteDialog.js b/src/components/voteDialog/voteDialog.js index 0ebc477d7..d485056c6 100644 --- a/src/components/voteDialog/voteDialog.js +++ b/src/components/voteDialog/voteDialog.js @@ -2,11 +2,14 @@ import React from 'react'; import InfoParagraph from '../infoParagraph'; import ActionBar from '../actionBar'; import Fees from '../../constants/fees'; +import votingConst from '../../constants/voting'; import Autocomplete from './voteAutocomplete'; import styles from './voteDialog.css'; import AuthInputs from '../authInputs'; import { authStatePrefill, authStateIsValid } from '../../utils/form'; +const { maxCountOfVotes, maxCountOfVotesInOneTurn } = votingConst; + export default class VoteDialog extends React.Component { constructor() { super(); @@ -58,9 +61,9 @@ export default class VoteDialog extends React.Component {

- You can select up to 33 delegates in one voting turn. + You can select up to {maxCountOfVotesInOneTurn} delegates in one voting turn.

- You can vote for up to 101 delegates in total. + You can vote for up to {maxCountOfVotes} delegates in total.
@@ -72,9 +75,9 @@ export default class VoteDialog extends React.Component { label: 'Confirm', fee: Fees.vote, disabled: ( - totalVotes > 101 || + totalVotes > maxCountOfVotes || votesList.length === 0 || - votesList.length > 33 || + votesList.length > maxCountOfVotesInOneTurn || !authStateIsValid(this.state) ), onClick: this.confirm.bind(this), diff --git a/src/components/voting/votingBar.js b/src/components/voting/votingBar.js index d291f106c..c20934e6d 100644 --- a/src/components/voting/votingBar.js +++ b/src/components/voting/votingBar.js @@ -1,11 +1,11 @@ import React from 'react'; import grid from 'flexboxgrid/dist/flexboxgrid.css'; +import votingConst from '../../constants/voting'; import style from './votingBar.css'; const VotingBar = ({ votes }) => { - const voteMaxCount = 33; - const votedMaxCount = 101; + const { maxCountOfVotes, maxCountOfVotesInOneTurn } = votingConst; const votedList = Object.keys(votes).filter(key => votes[key].confirmed); const voteList = Object.keys(votes).filter( key => votes[key].unconfirmed && !votes[key].confirmed); @@ -27,17 +27,17 @@ const VotingBar = ({ votes }) => {
Total new votes: - voteMaxCount && style.red}> + maxCountOfVotesInOneTurn && style.red}> {totalNewVotesCount} - / {voteMaxCount} + / {maxCountOfVotesInOneTurn} Total votes: 101 && style.red}> {totalVotesCount} - / {votedMaxCount} + / {maxCountOfVotes}
: From 0cd6351fe37ecf46ee88f016b48b90609507e7f4 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Fri, 22 Sep 2017 08:46:30 +0200 Subject: [PATCH 08/36] Give an offset to votingBar on md screen size --- src/components/voting/votingBar.css | 2 +- src/components/voting/votingBar.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/voting/votingBar.css b/src/components/voting/votingBar.css index f255da0ff..ec882de27 100644 --- a/src/components/voting/votingBar.css +++ b/src/components/voting/votingBar.css @@ -5,5 +5,5 @@ .fixedAtBottom { position: fixed; bottom: 0; - left: 0; + left: 8px; } diff --git a/src/components/voting/votingBar.js b/src/components/voting/votingBar.js index c20934e6d..c066a05c9 100644 --- a/src/components/voting/votingBar.js +++ b/src/components/voting/votingBar.js @@ -15,8 +15,10 @@ const VotingBar = ({ votes }) => { const totalNewVotesCount = voteList.length + unvoteList.length; return (voteList.length + unvoteList.length ? -
-
+
+
Upvotes: {voteList.length} From d2679bab1a5c902ba87ea3a313818c9f189cd0d6 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 14:39:23 +0200 Subject: [PATCH 09/36] Setup a i18n scanner command - Closes #769 --- .eslintrc | 1 + package.json | 3 +++ src/i18n-scanner.js | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/i18n-scanner.js diff --git a/.eslintrc b/.eslintrc index ba83c3e3a..89a002a38 100644 --- a/.eslintrc +++ b/.eslintrc @@ -42,6 +42,7 @@ "./features/*/*.js", "./src/**/stories.js", "./src/tests.js" + "./src/i18n-scanner.js" ] } ], diff --git a/package.json b/package.json index 64736203a..d8504ea16 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "clean": "del app/dist -f", "eslint": "eslint ./src/ ./app/main.js ./features/", "storybook": "start-storybook -p 6006 -s ./src/", + "i18n-scanner": "node ./src/i18n-scanner.js", "build-storybook": "build-storybook" }, "author": "Lisk Foundation , lightcurve GmbH ", @@ -87,6 +88,8 @@ "exports-loader": "=0.6.3", "extract-text-webpack-plugin": "=2.1.2", "file-loader": "=0.9.0", + "glob": "=7.1.2", + "i18next-scanner": "=2.0.0", "imports-loader": "=0.6.5", "js-nacl": "=1.2.2", "json-loader": "=0.5.4", diff --git a/src/i18n-scanner.js b/src/i18n-scanner.js new file mode 100644 index 000000000..44bd341d2 --- /dev/null +++ b/src/i18n-scanner.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const glob = require('glob'); +const Parser = require('i18next-scanner').Parser; + +const translationFunctionNames = ['i18next.t', 'props.t', 'this.props.t', 't']; +const outputFilePath = './src/locales/en/common.json'; + +const parser = new Parser(); + +const customHandler = function (key) { + parser.set(key, key); +}; + +const files = glob.sync('./src/**/*.js', {}); +files.forEach((file) => { + const content = fs.readFileSync(file, 'utf-8'); + parser.parseFuncFromString(content, { list: translationFunctionNames }, customHandler) +}); + +const translations = parser.get({ sort: true }).en.translation; +const count = Object.keys(translations).length; +const outputJSON = JSON.stringify(translations, null, 2); +fs.writeFileSync(outputFilePath, outputJSON); +console.log(`${count} translation keys parsed and written to '${outputFilePath}'`); From e80a3aee13c94613a806b552fbd6baa2113e151c Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 14:41:10 +0200 Subject: [PATCH 10/36] Update translations source file ...generated by npm run i18n-scanner --- src/locales/en/common.json | 91 +++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/src/locales/en/common.json b/src/locales/en/common.json index d46707f63..d76d4968f 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -1,58 +1,57 @@ { - "Send": "Send", - "Logout": "Logout", - "Register as delegate": "Register as delegate", - "Sign message": "Sign message", - "Verify message": "Verify message", - "Register second passphrase": "Register second passphrase", - "Peer": "Peer", - "Balance": "Balance", "Address": "Address", + "Amount": "Amount", + "Approval": "Approval", + "Balance": "Balance", + "Block Id": "Block Id", + "Block height": "Block height", + "Blockchain Application Registration": "Blockchain Application Registration", "Delegate": "Delegate", - "Transactions": "Transactions", - "Voting": "Voting", + "Delegate Registration": "Delegate Registration", + "Enter your passphrase": "Enter your passphrase", + "Fee": "Fee", "Forging": "Forging", - "Time": "Time", - "Transaction ID": "Transaction ID", "From / To": "From / To", - "Amount": "Amount", - "Fee": "Fee", - "Second Signature Creation": "Second Signature Creation", - "Delegate Registration": "Delegate Registration", - "Vote": "Vote", - "Multisignature Creation": "Multisignature Creation", - "Blockchain Application Registration": "Blockchain Application Registration", - "Send Lisk to Blockchain Application": "Send Lisk to Blockchain Application", - "Send Lisk from Blockchain Application": "Send Lisk from Blockchain Application", - "Send to this address": "Send to this address", - "Repeat the transaction": "Repeat the transaction", - "confirmations": "confirmations", - "confirmation": "confirmation", "LSK Earned": "LSK Earned", - "Last x days": "Last {{count}} days", "Last 24 hours": "Last 24 hours", + "Lisk Address": "Lisk Address", + "Login": "Login", + "Logout": "Logout", + "Losing access to this passphrase will mean no funds can be sent from this account": { + "": "Losing access to this passphrase will mean no funds can be sent from this account." + }, + "Multisignature Creation": "Multisignature Creation", + "Name": "Name", + "New Account": "New Account", + "No delegates found": "No delegates found", + "Node address": "Node address", + "Peer": "Peer", "Rank": "Rank", - "Productivity": "Productivity", - "Approval": "Approval", - "Forged Blocks": "Forged Blocks", - "Block height": "Block height", - "Block Id": "Block Id", + "Register": "Register", + "Register as delegate": "Register as delegate", + "Register second passphrase": "Register second passphrase", + "Repeat the transaction": "Repeat the transaction", + "Reward": "Reward", + "Search": "Search", + "Second Signature Creation": "Second Signature Creation", + "Select a network": "Select a network", + "Send": "Send", + "Send Lisk from Blockchain Application": "Send Lisk from Blockchain Application", + "Send Lisk to Blockchain Application": "Send Lisk to Blockchain Application", + "Send to this address": "Send to this address", + "Sign message": "Sign message", + "Time": "Time", "Timestamp": "Timestamp", "Total fee": "Total fee", - "Reward": "Reward", + "Transaction ID": "Transaction ID", + "Transactions": "Transactions", + "Uptime": "Uptime", + "Verify message": "Verify message", + "Vote": "Vote", + "Voting": "Voting", "You have not forged any blocks yet": "You have not forged any blocks yet", - "Select a network": "Select a network", - "Node address": "Node address", - "passphrase": "Enter your passphrase", - "Empty passphrase": "Empty passphrase", - "Passphrase should have 12 words, entered passphrase has length": "Passphrase should have 12 words, entered passphrase has {{length}}", - "Show passphrase": "Show passphrase", - "Login": "Login", - "New Account": "New Account", + "confirmation": "confirmation", + "confirmations": "confirmations", "my votes": "my votes", - "Search": "Search", - "Name": "Name", - "Lisk Address": "Lisk Address", - "Uptime": "Uptime", - "No delegates found": "No delegates found" -} + "your second passphrase will be required for all transactions sent from this account": "your second passphrase will be required for all transactions sent from this account" +} \ No newline at end of file From 94929f02668b5919ea185bd3942dbe64c34f186a Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 14:46:42 +0200 Subject: [PATCH 11/36] Fix missing coma in .eslintrc --- .eslintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc b/.eslintrc index 89a002a38..ae5f55396 100644 --- a/.eslintrc +++ b/.eslintrc @@ -41,7 +41,7 @@ "./src/**/*.test.js", "./features/*/*.js", "./src/**/stories.js", - "./src/tests.js" + "./src/tests.js", "./src/i18n-scanner.js" ] } From 248e66c82c7be2c23befed633f544e6a2cdc17b9 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 14:54:23 +0200 Subject: [PATCH 12/36] Fix eslint violations in i18n-scanner --- src/i18n-scanner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n-scanner.js b/src/i18n-scanner.js index 44bd341d2..455b72568 100644 --- a/src/i18n-scanner.js +++ b/src/i18n-scanner.js @@ -14,11 +14,11 @@ const customHandler = function (key) { const files = glob.sync('./src/**/*.js', {}); files.forEach((file) => { const content = fs.readFileSync(file, 'utf-8'); - parser.parseFuncFromString(content, { list: translationFunctionNames }, customHandler) + parser.parseFuncFromString(content, { list: translationFunctionNames }, customHandler); }); const translations = parser.get({ sort: true }).en.translation; const count = Object.keys(translations).length; const outputJSON = JSON.stringify(translations, null, 2); fs.writeFileSync(outputFilePath, outputJSON); -console.log(`${count} translation keys parsed and written to '${outputFilePath}'`); +process.stdout.write(`${count} translation keys parsed and written to '${outputFilePath}'`); From c16aae5a6a99ed79d35fe633c0bee94fc385634d Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 16:06:47 +0200 Subject: [PATCH 13/36] Fix switching language in Electron - Closes #767 --- src/components/header/header.js | 2 +- src/constants/languages.js | 10 ++++++++-- src/i18n.js | 11 +++++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/header/header.js b/src/components/header/header.js index 24ec95ee8..0824726a5 100644 --- a/src/components/header/header.js +++ b/src/components/header/header.js @@ -74,7 +74,7 @@ const Header = props => ( className={`${styles.iconButton} ${offlineStyle.disableWhenOffline}`} icon='language' position='topRight'> {Object.keys(languages).map(key => ( - i18n.changeLanguage(key)} /> ))} diff --git a/src/constants/languages.js b/src/constants/languages.js index c3682a3bb..3ffae793e 100644 --- a/src/constants/languages.js +++ b/src/constants/languages.js @@ -1,6 +1,12 @@ const languages = { - en: 'English', - de: 'Deutsch', + en: { + name: 'English', + common: require('../locales/en/common.json'), + }, + de: { + name: 'Deutsch', + common: require('../locales/de/common.json'), + }, }; export default languages; diff --git a/src/i18n.js b/src/i18n.js index d45f2f59b..1c64c7c54 100755 --- a/src/i18n.js +++ b/src/i18n.js @@ -1,13 +1,20 @@ import i18n from 'i18next'; -import XHR from 'i18next-xhr-backend'; +import languages from './constants/languages'; // import Cache from 'i18next-localstorage-cache'; +const resources = Object.keys(languages).reduce((accumulator, key) => { + accumulator[key] = { + common: languages[key].common, + }; + return accumulator; +}, {}); + i18n - .use(XHR) // .use(Cache) .init({ fallbackLng: 'en', lng: 'en', + resources, react: { // wait: true, // globally set to wait for loaded translations in translate hoc // exposeNamespace: true // exposes namespace on data-i18next-options to be used in eg. From 2cd40e688c40fee1f238df2a9cb41ff0a3b99058 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 16:27:34 +0200 Subject: [PATCH 14/36] Fix forgingStats unit tests --- src/components/forging/forgingStats.js | 2 +- src/components/forging/forgingStats.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/forging/forgingStats.js b/src/components/forging/forgingStats.js index 94c6ea9f1..ead417167 100644 --- a/src/components/forging/forgingStats.js +++ b/src/components/forging/forgingStats.js @@ -31,7 +31,7 @@ class ForgingStats extends React.Component { statCardObjects[0].label = this.props.t('Last 24 hours'); [1, 2, 3].forEach((i) => { statCardObjects[i].label = this.props.t( - 'Last x days', { day: statCardObjects[i].days }); + 'Last x days', { count: statCardObjects[i].days }); }); return ( diff --git a/src/components/forging/forgingStats.test.js b/src/components/forging/forgingStats.test.js index f96390f93..528cf5e61 100644 --- a/src/components/forging/forgingStats.test.js +++ b/src/components/forging/forgingStats.test.js @@ -42,14 +42,14 @@ describe('ForgingStats', () => { }); it('should render Card component for Last 7 days', () => { - expect(wrapper.find('Card').at(1).text().trim()).to.equal('Last x days 32.13 LSK'); + expect(wrapper.find('Card').at(1).text().trim()).to.equal('Last 7 days 32.13 LSK'); }); it('should render Card component for Last 30 days', () => { - expect(wrapper.find('Card').at(2).text().trim()).to.equal('Last x days 3,213.18 LSK'); + expect(wrapper.find('Card').at(2).text().trim()).to.equal('Last 30 days 3,213.18 LSK'); }); it('should render Card component for Last 365 days', () => { - expect(wrapper.find('Card').at(3).text().trim()).to.equal('Last x days 321,317.91 LSK'); + expect(wrapper.find('Card').at(3).text().trim()).to.equal('Last 365 days 321,317.91 LSK'); }); }); From 17b192ed9334d831aa4937a77aa4ca40f28fedf7 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Mon, 25 Sep 2017 18:23:09 +0200 Subject: [PATCH 15/36] Add newline to end of locales/en/common.json --- src/i18n-scanner.js | 2 +- src/locales/en/common.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n-scanner.js b/src/i18n-scanner.js index 455b72568..cb60cf114 100644 --- a/src/i18n-scanner.js +++ b/src/i18n-scanner.js @@ -20,5 +20,5 @@ files.forEach((file) => { const translations = parser.get({ sort: true }).en.translation; const count = Object.keys(translations).length; const outputJSON = JSON.stringify(translations, null, 2); -fs.writeFileSync(outputFilePath, outputJSON); +fs.writeFileSync(outputFilePath, `${outputJSON}\n`); process.stdout.write(`${count} translation keys parsed and written to '${outputFilePath}'`); diff --git a/src/locales/en/common.json b/src/locales/en/common.json index d76d4968f..3e7854a75 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -54,4 +54,4 @@ "confirmations": "confirmations", "my votes": "my votes", "your second passphrase will be required for all transactions sent from this account": "your second passphrase will be required for all transactions sent from this account" -} \ No newline at end of file +} From 53bc44d61402793b4861c62bfd031d1794e82ca3 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 08:44:54 +0200 Subject: [PATCH 16/36] Add favicon --- package.json | 2 +- src/index.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 64736203a..b633e90ee 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dist:win": "build --win --ia32 --x64", "dist:mac": "build --mac", "dist:linux": "build --linux --ia32 --x64 --armv7l", - "copy-files": "mkdir app/dist && cp -r ./src/index.html ./app/dist", + "copy-files": "mkdir app/dist && cp -r ./src/index.html ./src/assets ./app/dist", "clean": "del app/dist -f", "eslint": "eslint ./src/ ./app/main.js ./features/", "storybook": "start-storybook -p 6006 -s ./src/", diff --git a/src/index.html b/src/index.html index 205c9bd7f..406cb8b0c 100644 --- a/src/index.html +++ b/src/index.html @@ -4,6 +4,7 @@ Lisk Nano +
From 26099bcd128da583411e4385344285db1c4a349d Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 09:03:32 +0200 Subject: [PATCH 17/36] Cleanup Jenkins stages Merge short ones and update labels when necessary --- Jenkinsfile | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 570497a6e..99adac927 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,7 +7,7 @@ def fail(reason) { node('lisk-nano-01'){ lock(resource: "lisk-nano-01", inversePrecedence: true) { - stage ('Cleanup Orphaned Processes') { + stage ('Cleanup, Checkout, and Start Lisk Core') { try { sh ''' # Clean up old processes @@ -21,18 +21,14 @@ node('lisk-nano-01'){ } catch (err) { fail('Stopping build, installation failed') } - } - stage ('Prepare Workspace') { try { deleteDir() checkout scm } catch (err) { fail('Stopping build, Checkout failed') } - } - stage ('Start Lisk Core') { try { sh '''#!/bin/bash cd ~/lisk-test-nano @@ -84,7 +80,7 @@ node('lisk-nano-01'){ } } - stage ('Run Tests') { + stage ('Run Unit Tests') { try { ansiColor('xterm') { sh ''' @@ -103,7 +99,7 @@ node('lisk-nano-01'){ } } - stage ('Start Dev Server and Run Tests') { + stage ('Start Dev Server and Run E2E Tests') { try { ansiColor('xterm') { sh ''' @@ -134,7 +130,7 @@ node('lisk-nano-01'){ } } - stage ('Deploy') { + stage ('Deploy and Set milestone') { try { sh ''' rsync -axl --delete "$WORKSPACE/app/dist/" "jenkins@master-01:/var/www/test/lisk-nano/$BRANCH_NAME/" @@ -143,11 +139,8 @@ node('lisk-nano-01'){ rm -rf "$WORKSPACE/*" ''' } catch (err) { - fail('Stopping build, End to End Test suite failed') + fail('Stopping build, Deploy failed') } - } - - stage ('Set milestone') { milestone 1 } } From da46109044156adb47ade0ca6113cb1f09de0dec Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 09:19:03 +0200 Subject: [PATCH 18/36] Upgrade eslint 3 to 4 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 096fc30f7..418407ae0 100644 --- a/package.json +++ b/package.json @@ -78,8 +78,8 @@ "electron": "=1.6.2", "electron-builder": "=16.8.3", "enzyme": "=2.8.2", - "eslint": "=3.19.0", - "eslint-config-airbnb": "=14.1.0", + "eslint": "=4.7.2", + "eslint-config-airbnb": "=15.1.0", "eslint-config-google": "=0.7.1", "eslint-loader": "=1.7.1", "eslint-plugin-html": "=2.0.3", From 13bbb1b0863a806c49e22fa07631b6b2d9c4747f Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 09:19:43 +0200 Subject: [PATCH 19/36] Fix eslint violations --- features/step_definitions/hooks.js | 10 +- src/actions/forging.js | 12 +- src/actions/transactions.js | 12 +- src/actions/transactions.test.js | 2 +- src/components/app/index.test.js | 18 +-- src/components/forging/delegateStats.test.js | 4 +- src/components/forging/forgedBlocks.test.js | 4 +- src/components/forging/forging.js | 6 +- src/components/forging/forging.test.js | 4 +- src/components/forging/forgingTitle.js | 1 - src/components/forging/forgingTitle.test.js | 6 +- src/components/header/header.js | 4 +- src/components/login/login.js | 36 +++--- src/components/passphrase/passphrase.js | 10 +- .../passphrase/passphraseVerifier.test.js | 4 +- src/components/pricedButton/index.js | 2 +- src/components/privateRoute/index.js | 8 +- src/components/privateWrapper/index.js | 2 +- src/components/privateWrapper/index.test.js | 6 +- src/components/transactions/amount.test.js | 6 +- src/components/transactions/transactionRow.js | 8 +- .../transactions/transactionRow.test.js | 34 +++--- src/components/transactions/transactions.js | 2 +- src/components/verifyMessage/index.js | 35 +++--- src/components/voteDialog/voteAutocomplete.js | 8 +- .../voteDialog/voteAutocomplete.test.js | 30 ++--- src/components/voting/voting.js | 2 +- src/components/voting/votingRow.test.js | 30 ++--- src/store/reducers/voting.js | 2 +- src/utils/api/delegate.js | 16 +-- src/utils/notification.test.js | 2 +- src/utils/passphrase.js | 2 +- src/utils/passphrase.test.js | 110 +++++++++--------- src/utils/polyfills.js | 2 +- 34 files changed, 219 insertions(+), 221 deletions(-) diff --git a/features/step_definitions/hooks.js b/features/step_definitions/hooks.js index fbe42fa4b..6ab5acd9b 100644 --- a/features/step_definitions/hooks.js +++ b/features/step_definitions/hooks.js @@ -10,11 +10,11 @@ function writeScreenShot(data, filename) { function slugify(text) { return text.toString().toLowerCase() - .replace(/\s+/g, '-') // Replace spaces with - - .replace(/[^\w-]+/g, '') // Remove all non-word chars - .replace(/--+/g, '-') // Replace multiple - with single - - .replace(/^-+/, '') // Trim - from start of text - .replace(/-+$/, ''); // Trim - from end of text + .replace(/\s+/g, '-') // Replace spaces with - + .replace(/[^\w-]+/g, '') // Remove all non-word chars + .replace(/--+/g, '-') // Replace multiple - with single - + .replace(/^-+/, '') // Trim - from start of text + .replace(/-+$/, ''); // Trim - from end of text } defineSupportCode(({ After }) => { diff --git a/src/actions/forging.js b/src/actions/forging.js index cc51457e3..651912ef1 100644 --- a/src/actions/forging.js +++ b/src/actions/forging.js @@ -9,9 +9,9 @@ export const forgedBlocksUpdated = data => ({ export const fetchAndUpdateForgedBlocks = ({ activePeer, limit, offset, generatorPublicKey }) => (dispatch) => { getForgedBlocks(activePeer, limit, offset, generatorPublicKey) - .then(response => - dispatch(forgedBlocksUpdated(response.blocks)), - ); + .then(response => + dispatch(forgedBlocksUpdated(response.blocks)), + ); }; export const forgingStatsUpdated = data => ({ @@ -22,7 +22,7 @@ export const forgingStatsUpdated = data => ({ export const fetchAndUpdateForgedStats = ({ activePeer, key, startMoment, generatorPublicKey }) => (dispatch) => { getForgedStats(activePeer, startMoment, generatorPublicKey) - .then(response => - dispatch(forgingStatsUpdated({ [key]: response.forged })), - ); + .then(response => + dispatch(forgingStatsUpdated({ [key]: response.forged })), + ); }; diff --git a/src/actions/transactions.js b/src/actions/transactions.js index bf580304f..bf88a67c2 100644 --- a/src/actions/transactions.js +++ b/src/actions/transactions.js @@ -35,10 +35,10 @@ export const transactionsLoaded = data => ({ export const transactionsRequested = ({ activePeer, address, limit, offset }) => (dispatch) => { transactions(activePeer, address, limit, offset) - .then((response) => { - dispatch(transactionsLoaded({ - count: parseInt(response.count, 10), - confirmed: response.transactions, - })); - }); + .then((response) => { + dispatch(transactionsLoaded({ + count: parseInt(response.count, 10), + confirmed: response.transactions, + })); + }); }; diff --git a/src/actions/transactions.test.js b/src/actions/transactions.test.js index a4a2c0c65..fcc9f87f5 100644 --- a/src/actions/transactions.test.js +++ b/src/actions/transactions.test.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import sinon from 'sinon'; import actionTypes from '../constants/actions'; import { transactionAdded, transactionsUpdated, - transactionsLoaded, transactionsRequested } from './transactions'; + transactionsLoaded, transactionsRequested } from './transactions'; import * as accountApi from '../utils/api/account'; describe('actions: transactions', () => { diff --git a/src/components/app/index.test.js b/src/components/app/index.test.js index b249a7275..5c8b11fda 100644 --- a/src/components/app/index.test.js +++ b/src/components/app/index.test.js @@ -15,15 +15,15 @@ import Forging from '../forging'; const fakeStore = configureStore(); const addRouter = Component => (props, path) => - mount( - - - - - - - , - ); + mount( + + + + + + + , + ); const publicComponent = [ { route: '/', component: Login }, diff --git a/src/components/forging/delegateStats.test.js b/src/components/forging/delegateStats.test.js index 155dbdd81..b1c952e91 100644 --- a/src/components/forging/delegateStats.test.js +++ b/src/components/forging/delegateStats.test.js @@ -17,8 +17,8 @@ describe('DelegateStats', () => { beforeEach(() => { wrapper = mount( - - ); + + ); }); it('should render 3 Card components', () => { diff --git a/src/components/forging/forgedBlocks.test.js b/src/components/forging/forgedBlocks.test.js index 2de160696..b52da23df 100644 --- a/src/components/forging/forgedBlocks.test.js +++ b/src/components/forging/forgedBlocks.test.js @@ -35,8 +35,8 @@ describe('ForgedBlocks', () => { beforeEach(() => { wrapper = mount( - - ); + + ); }); it('should render 1 Table component', () => { diff --git a/src/components/forging/forging.js b/src/components/forging/forging.js index b9bf75fcc..e46087202 100644 --- a/src/components/forging/forging.js +++ b/src/components/forging/forging.js @@ -42,9 +42,9 @@ const Forging = ({
loadForgedBlocks(20, forgedBlocks.length) } /> + scrollableAncestor={window} + key={forgedBlocks.length} + onEnter={() => loadForgedBlocks(20, forgedBlocks.length) } />
: null } diff --git a/src/components/forging/forging.test.js b/src/components/forging/forging.test.js index 92cc2a2f6..e7ce164f3 100644 --- a/src/components/forging/forging.test.js +++ b/src/components/forging/forging.test.js @@ -29,8 +29,8 @@ describe('Forging', () => { }; wrapper = mount( - - ); + + ); }); it('should render ForgingTitle', () => { diff --git a/src/components/forging/forgingTitle.js b/src/components/forging/forgingTitle.js index 5c6746cfb..8279bdf41 100644 --- a/src/components/forging/forgingTitle.js +++ b/src/components/forging/forgingTitle.js @@ -8,7 +8,6 @@ import style from './forging.css'; class ForgingTitle extends React.Component { - componentDidMount() { this.props.loadStats('total', moment('2016-04-24 17:00')); } diff --git a/src/components/forging/forgingTitle.test.js b/src/components/forging/forgingTitle.test.js index ee6c55482..cf1aa0a56 100644 --- a/src/components/forging/forgingTitle.test.js +++ b/src/components/forging/forgingTitle.test.js @@ -23,9 +23,9 @@ describe('ForgingTitle', () => { beforeEach(() => { wrapper = mount( - - ); + + ); }); it('should render 1 Card component', () => { diff --git a/src/components/header/header.js b/src/components/header/header.js index 84c5e6a37..55b159996 100644 --- a/src/components/header/header.js +++ b/src/components/header/header.js @@ -51,9 +51,9 @@ const Header = props => ( {props.t('Receive LSK')} + to='receive'>{props.t('Receive LSK')} {props.t('send')} + to='send'>{props.t('send')}
-
diff --git a/src/components/passphrase/passphrase.js b/src/components/passphrase/passphrase.js index fb73b0da7..9c2f46d13 100644 --- a/src/components/passphrase/passphrase.js +++ b/src/components/passphrase/passphrase.js @@ -29,12 +29,12 @@ class Passphrase extends React.Component { // Step 1: Information/introduction templates.info = Please click Next, then move around your mouse randomly to generate a random passphrase. -
-
+
+
Note: After registration completes, { this.props.useCaseNote } -
- { this.props.securityNote } Please keep it safe! -
; +
+ { this.props.securityNote } Please keep it safe! + ; // step 2: Generator, binds mouse events templates.generate = { const spyFn = spy(props, 'updateAnswer'); const value = 'sample'; const wrapper = shallow(); + updateAnswer={props.updateAnswer}/>); wrapper.instance().changeHandler(value); expect(spyFn).to.have.been.calledWith(); props.updateAnswer.restore(); @@ -36,7 +36,7 @@ describe('PassphraseVerifier', () => { describe('hideRandomWord', () => { it('should break passphrase, hide a word and store all in state', () => { const wrapper = shallow(); + updateAnswer={props.updateAnswer}/>); const randomIndex = 0.6; const expectedValues = { diff --git a/src/components/pricedButton/index.js b/src/components/pricedButton/index.js index 568a43172..0dfd54b6a 100644 --- a/src/components/pricedButton/index.js +++ b/src/components/pricedButton/index.js @@ -15,7 +15,7 @@ export const PricedButtonComponent = ({ ( { hasFunds ? `Fee: ${fromRawLsk(fee)} LSK` : - `Insufficient funds for ${fromRawLsk(fee)} LSK fee` + `Insufficient funds for ${fromRawLsk(fee)} LSK fee` } ) } diff --git a/src/components/privateRoute/index.js b/src/components/privateRoute/index.js index 5bac28fdf..186e55b8a 100644 --- a/src/components/privateRoute/index.js +++ b/src/components/privateRoute/index.js @@ -3,10 +3,10 @@ import { Route, Redirect, withRouter } from 'react-router-dom'; import { connect } from 'react-redux'; export const PrivateRouteRender = ({ render, isAuthenticated, ...rest }) => ( - ( - isAuthenticated ? render(matchProps) : - )}/> - ); + ( + isAuthenticated ? render(matchProps) : + )}/> +); const mapStateToProps = state => ({ isAuthenticated: !!state.account.publicKey, diff --git a/src/components/privateWrapper/index.js b/src/components/privateWrapper/index.js index 4e504bfb5..5776869ba 100644 --- a/src/components/privateWrapper/index.js +++ b/src/components/privateWrapper/index.js @@ -2,7 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; export const PrivateWrapperComponent = ({ isAuthenticated, children }) => ( - isAuthenticated && { children } + isAuthenticated && { children } ); const mapStateToProps = state => ({ diff --git a/src/components/privateWrapper/index.test.js b/src/components/privateWrapper/index.test.js index 23f6ae4b8..c6015c68f 100644 --- a/src/components/privateWrapper/index.test.js +++ b/src/components/privateWrapper/index.test.js @@ -8,9 +8,9 @@ const Private = () =>

Private

; describe('PrivateWrapperComponent', () => { const isAuth = isAuthenticated => ( shallow( - - - , + + + , ) ); it('should render children components if user is authenticated', () => { diff --git a/src/components/transactions/amount.test.js b/src/components/transactions/amount.test.js index b121f0b1d..a24e3f516 100644 --- a/src/components/transactions/amount.test.js +++ b/src/components/transactions/amount.test.js @@ -28,7 +28,7 @@ describe('Amount', () => { }); const html = wrapper.find('#transactionAmount').html(); expect(html.match(expectedValue)) - .to.have.lengthOf(1); + .to.have.lengthOf(1); }); it('should have className "transactions__inButton" for type 1', () => { @@ -50,7 +50,7 @@ describe('Amount', () => { }); const html = wrapper.find('#transactionAmount').html(); expect(html.match(expectedValue)) - .to.have.lengthOf(1); + .to.have.lengthOf(1); }); it('should have className "transactions__outButton" for outgoing transaction', () => { @@ -72,6 +72,6 @@ describe('Amount', () => { }); const html = wrapper.find('#transactionAmount').html(); expect(html.match(expectedValue)) - .to.have.lengthOf(1); + .to.have.lengthOf(1); }); }); diff --git a/src/components/transactions/transactionRow.js b/src/components/transactions/transactionRow.js index 2f2e5118c..26f78338e 100644 --- a/src/components/transactions/transactionRow.js +++ b/src/components/transactions/transactionRow.js @@ -24,11 +24,11 @@ class TransactionRow extends React.Component { } - - {props.value.id} - + {props.value.id} + diff --git a/src/components/transactions/transactionRow.test.js b/src/components/transactions/transactionRow.test.js index a75cef6d4..ea3928618 100644 --- a/src/components/transactions/transactionRow.test.js +++ b/src/components/transactions/transactionRow.test.js @@ -42,29 +42,29 @@ describe('TransactionRow', () => { it('should render 6 "td"', () => { const wrapper = mount( - - - - - - , options); + + + + + + , options); expect(wrapper.find('td')).to.have.lengthOf(6); }); it('should render Spinner if no value.confirmations" ', () => { rowData.confirmations = undefined; const wrapper = mount( - - - - - - - , options); + + + + + + + , options); expect(wrapper.find('Spinner')).to.have.lengthOf(1); }); }); diff --git a/src/components/transactions/transactions.js b/src/components/transactions/transactions.js index e70e9490b..07511eae5 100644 --- a/src/components/transactions/transactions.js +++ b/src/components/transactions/transactions.js @@ -49,7 +49,7 @@ class Transactions extends React.Component {

There are no transactions, yet.   Receive LSK + to='receive'>Receive LSK

} - + When you have the signature, you only need the publicKey of the signer in order to verify that the message came from the right private/publicKey pair. Be aware, everybody knowing the signature and the publicKey can verify the message. If ever there is a dispute, everybody can take the publicKey and signature to a judge and prove that the message is coming from the specific private/publicKey pair. - -
- - -
- {this.state.result ? - : - null - } +
+
+ + +
+ {this.state.result ? + : + null + }
); } diff --git a/src/components/voteDialog/voteAutocomplete.js b/src/components/voteDialog/voteAutocomplete.js index d727d0277..ed70a4583 100644 --- a/src/components/voteDialog/voteAutocomplete.js +++ b/src/components/voteDialog/voteAutocomplete.js @@ -179,8 +179,8 @@ export default class VoteAutocomplete extends React.Component { deletable onDeleteClick={this.props.voteToggled.bind(this, { username: item, publicKey: votes[item].publicKey })}> - {item} - , + {item} + , )}
@@ -211,8 +211,8 @@ export default class VoteAutocomplete extends React.Component { deletable onDeleteClick={this.props.voteToggled.bind(this, { username: item, publicKey: votes[item].publicKey })}> - {item} - , + {item} + , )}
diff --git a/src/components/voteDialog/voteAutocomplete.test.js b/src/components/voteDialog/voteAutocomplete.test.js index 3b5961954..3bd3d574c 100644 --- a/src/components/voteDialog/voteAutocomplete.test.js +++ b/src/components/voteDialog/voteAutocomplete.test.js @@ -80,7 +80,7 @@ describe('VoteAutocomplete', () => { it('search should call "voteAutocomplete" when name is equal to "votedListSearch"', () => { const clock = sinon.useFakeTimers(); voteAutocompleteApiMock.returnsPromise().resolves({ success: true }) - .returnsPromise().resolves([]); + .returnsPromise().resolves([]); // sinon.stub(delegateApi, 'listDelegates').returnsPromise().resolves({ success: true }); wrapper.instance().search('votedListSearch', 'val'); clock.tick(250); @@ -155,21 +155,21 @@ describe('VoteAutocomplete', () => { it(`should keyPress call "addToVoted" when event.keyCode is equal to 13 and list name is equal to votedResult`, () => { - const list = [{ address: 'address 1', hovered: true }]; - wrapper.setState({ votedResult: list }); - const returnValue = wrapper.instance() - .keyPress({ keyCode: 13 }, 'votedSuggestionClass', 'votedResult'); - expect(props.voteToggled).to.have.property('callCount', 1); - expect(returnValue).to.be.equal(false); - }); + const list = [{ address: 'address 1', hovered: true }]; + wrapper.setState({ votedResult: list }); + const returnValue = wrapper.instance() + .keyPress({ keyCode: 13 }, 'votedSuggestionClass', 'votedResult'); + expect(props.voteToggled).to.have.property('callCount', 1); + expect(returnValue).to.be.equal(false); + }); it(`should keyPress call "voteToggled" when event.keyCode is equal to 13 and list name is equal to unvotedResult`, () => { - const list = [{ address: 'address 1', hovered: true }]; - wrapper.setState({ unvotedResult: list }); - const returnValue = wrapper.instance() - .keyPress({ keyCode: 13 }, 'unvotedSuggestionClass', 'unvotedResult'); - expect(props.voteToggled).to.have.property('callCount', 2); - expect(returnValue).to.be.equal(false); - }); + const list = [{ address: 'address 1', hovered: true }]; + wrapper.setState({ unvotedResult: list }); + const returnValue = wrapper.instance() + .keyPress({ keyCode: 13 }, 'unvotedSuggestionClass', 'unvotedResult'); + expect(props.voteToggled).to.have.property('callCount', 2); + expect(returnValue).to.be.equal(false); + }); }); diff --git a/src/components/voting/voting.js b/src/components/voting/voting.js index d5151c638..1d71a46ab 100644 --- a/src/components/voting/voting.js +++ b/src/components/voting/voting.js @@ -40,7 +40,7 @@ class Voting extends React.Component { } loadVotedDelegates(refresh) { - /* istanbul-ignore-else */ + /* istanbul-ignore-else */ if (!this.freezeLoading) { this.props.votesFetched({ activePeer: this.props.activePeer, diff --git a/src/components/voting/votingRow.test.js b/src/components/voting/votingRow.test.js index d303b048b..2d07e0af9 100644 --- a/src/components/voting/votingRow.test.js +++ b/src/components/voting/votingRow.test.js @@ -28,25 +28,25 @@ describe('VotingRow', () => { it(`should TableRow has class name of "votedRow" when voteStatus.unconfirmed and confirmed are true`, () => { - const wrapper = mount(, options); - const expectedClass = '_votedRow'; - const className = wrapper.find('tr').prop('className'); - expect(className).to.contain(expectedClass); - }); + const wrapper = mount(, options); + const expectedClass = '_votedRow'; + const className = wrapper.find('tr').prop('className'); + expect(className).to.contain(expectedClass); + }); it(`should TableRow has class name of "downVoteRow" when voteStatus.unconfirmed is false but confirmed is true`, () => { - const wrapper = mount(, options); - const expectedClass = '_downVoteRow'; - const className = wrapper.find('tr').prop('className'); - expect(className).to.contain(expectedClass); - }); + const wrapper = mount(, options); + const expectedClass = '_downVoteRow'; + const className = wrapper.find('tr').prop('className'); + expect(className).to.contain(expectedClass); + }); it(`should TableRow has class name of "upVoteRow" when voteStatus.unconfirmed is false but confirmed is true`, () => { - const wrapper = mount(, options); - const expectedClass = '_upVoteRow'; - const className = wrapper.find('tr').prop('className'); - expect(className).to.contain(expectedClass); - }); + const wrapper = mount(, options); + const expectedClass = '_upVoteRow'; + const className = wrapper.find('tr').prop('className'); + expect(className).to.contain(expectedClass); + }); }); diff --git a/src/store/reducers/voting.js b/src/store/reducers/voting.js index 7578397c1..01926943e 100644 --- a/src/store/reducers/voting.js +++ b/src/store/reducers/voting.js @@ -18,7 +18,7 @@ const mergeVotes = (newList, oldDict) => { const { confirmed, unconfirmed, pending } = oldDict[username]; if (// we've voted but it's not in the new list (pending && unconfirmed && newDict[username] === undefined) || - // we've un-voted but it still exists in the new list + // we've un-voted but it still exists in the new list (pending && !unconfirmed && newDict[username] !== undefined) || // dirty, not voted for and not updated in other client (!pending && unconfirmed !== confirmed && diff --git a/src/utils/api/delegate.js b/src/utils/api/delegate.js index 22f24a5d7..79a4649ff 100644 --- a/src/utils/api/delegate.js +++ b/src/utils/api/delegate.js @@ -25,12 +25,12 @@ export const voteAutocomplete = (activePeer, username, votedDict) => { return new Promise((resolve, reject) => listDelegates(activePeer, options) - .then((response) => { - resolve(response.delegates.filter(delegate => - Object.keys(votedDict).filter(item => item === delegate.username).length === 0, - )); - }) - .catch(reject), + .then((response) => { + resolve(response.delegates.filter(delegate => + Object.keys(votedDict).filter(item => item === delegate.username).length === 0, + )); + }) + .catch(reject), ); }; @@ -38,8 +38,8 @@ export const unvoteAutocomplete = (username, votedDict) => new Promise((resolve) => { resolve( Object.keys(votedDict) - .filter(delegate => delegate.indexOf(username) !== -1) - .map(element => ({ username: element, publicKey: votedDict[element].publicKey }))); + .filter(delegate => delegate.indexOf(username) !== -1) + .map(element => ({ username: element, publicKey: votedDict[element].publicKey }))); }); export const registerDelegate = (activePeer, username, secret, secondSecret = null) => { diff --git a/src/utils/notification.test.js b/src/utils/notification.test.js index 7d85e79c0..f5694f651 100644 --- a/src/utils/notification.test.js +++ b/src/utils/notification.test.js @@ -28,7 +28,7 @@ describe('Notification', () => { notify.isFocused = false; notify.about('deposit', amount); expect(mockNotification).to.have.been.calledWith( - 'LSK received', { body: msg }, + 'LSK received', { body: msg }, ); mockNotification.reset(); }); diff --git a/src/utils/passphrase.js b/src/utils/passphrase.js index 7e1c046d9..fe75785a7 100644 --- a/src/utils/passphrase.js +++ b/src/utils/passphrase.js @@ -77,7 +77,7 @@ export const generateSeed = ({ byte, seed, percentage, step } = init(), rand = M */ export const generatePassphrase = ({ seed }) => (new mnemonic(new Buffer(seed.join(''), 'hex'))).toString(); - /** +/** * Checks if passphrase is valid using mnemonic * * @param {string} passphrase diff --git a/src/utils/passphrase.test.js b/src/utils/passphrase.test.js index b7fe6cd77..01ec25fc7 100644 --- a/src/utils/passphrase.test.js +++ b/src/utils/passphrase.test.js @@ -36,61 +36,61 @@ describe('Passphrase', () => { describe('generateSeed', () => { it('should generate a predictable sequence of bytes for given list of randoms', () => { const bytes = [ - [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], - [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1], - [1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1], - [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1], - [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], - [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], - [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0], - [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0], - [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0], - [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1], - [1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1], - [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], - [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], - [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], - [1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], - [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], - [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], - [0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], - [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], - [0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], - [1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], - [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], - [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1], + [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1], + [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0], + [1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1], + [1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1], + [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1], + [1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1], + [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1], + [1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], + [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], + [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], + [0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], + [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0], + [0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], + [1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], + [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], + [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0], ]; let data; diff --git a/src/utils/polyfills.js b/src/utils/polyfills.js index b9ef8a1ed..043865f5c 100644 --- a/src/utils/polyfills.js +++ b/src/utils/polyfills.js @@ -8,7 +8,7 @@ * @param {any} ref2 - Value to compare equality * @returns {Boolean} Whether two parameters are equal or not */ - /* eslint-disable import/prefer-default-export */ +/* eslint-disable import/prefer-default-export */ export const deepEquals = (ref1, ref2) => { /* eslint-disable eqeqeq */ From b7861d07afab278fb1fa4a35a4c0723c175132bc Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 10:55:30 +0200 Subject: [PATCH 20/36] Rremove the explicit calls to #!/bin/bash in Jenkinsfile --- Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 99adac927..bac0c180f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,7 +30,7 @@ node('lisk-nano-01'){ } try { - sh '''#!/bin/bash + sh ''' cd ~/lisk-test-nano bash lisk.sh rebuild -f /home/lisk/lisk-test-nano/blockchain_explorer.db.gz ''' @@ -41,7 +41,7 @@ node('lisk-nano-01'){ stage ('Install npm dependencies') { try { - sh '''#!/bin/bash + sh ''' npm install # Build nano cd $WORKSPACE @@ -68,7 +68,7 @@ node('lisk-nano-01'){ stage ('Build Nano') { try { - sh '''#!/bin/bash + sh ''' # Add coveralls config file cp ~/.coveralls.yml-nano .coveralls.yml From baf06de0db0bc202392359ad8c1cecfc03809827 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 11:17:33 +0200 Subject: [PATCH 21/36] Remove forgotten console.log --- src/store/middlewares/voting.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/store/middlewares/voting.js b/src/store/middlewares/voting.js index 9e0f4bc55..51e8cfb64 100644 --- a/src/store/middlewares/voting.js +++ b/src/store/middlewares/voting.js @@ -9,7 +9,6 @@ const votingMiddleware = store => next => (action) => { const voteCount = Object.keys(votes).filter( key => votes[key].confirmed !== votes[key].unconfirmed).length; const currentVote = votes[action.data.username] || { unconfirmed: true, confirmed: false }; - console.log(voteCount, votingConst.maxCountOfVotesInOneTurn, currentVote); if (voteCount === votingConst.maxCountOfVotesInOneTurn + 1 && currentVote.unconfirmed !== currentVote.confirmed) { const label = `Maximum of ${votingConst.maxCountOfVotesInOneTurn} votes in one transaction exceeded.`; From a9c40b41a11b87a082087fe636dcd674a2d869bc Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Tue, 26 Sep 2017 12:53:14 +0200 Subject: [PATCH 22/36] Add a toast when maximum of votes exceeded --- src/store/middlewares/voting.js | 16 ++++++++-- src/store/middlewares/voting.test.js | 45 ++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/store/middlewares/voting.js b/src/store/middlewares/voting.js index 51e8cfb64..ce12e7cd2 100644 --- a/src/store/middlewares/voting.js +++ b/src/store/middlewares/voting.js @@ -6,15 +6,25 @@ const votingMiddleware = store => next => (action) => { next(action); if (action.type === actionTypes.voteToggled) { const { votes } = store.getState().voting; - const voteCount = Object.keys(votes).filter( - key => votes[key].confirmed !== votes[key].unconfirmed).length; const currentVote = votes[action.data.username] || { unconfirmed: true, confirmed: false }; - if (voteCount === votingConst.maxCountOfVotesInOneTurn + 1 && + + const newVoteCount = Object.keys(votes).filter( + key => votes[key].confirmed !== votes[key].unconfirmed).length; + if (newVoteCount === votingConst.maxCountOfVotesInOneTurn + 1 && currentVote.unconfirmed !== currentVote.confirmed) { const label = `Maximum of ${votingConst.maxCountOfVotesInOneTurn} votes in one transaction exceeded.`; const newAction = errorToastDisplayed({ label }); store.dispatch(newAction); } + + const voteCount = Object.keys(votes).filter( + key => (votes[key].confirmed && !votes[key].unconfirmed) || votes[key].unconfirmed).length; + if (voteCount === votingConst.maxCountOfVotes + 1 && + currentVote.unconfirmed !== currentVote.confirmed) { + const label = `Maximum of ${votingConst.maxCountOfVotes} votes exceeded.`; + const newAction = errorToastDisplayed({ label }); + store.dispatch(newAction); + } } }; diff --git a/src/store/middlewares/voting.test.js b/src/store/middlewares/voting.test.js index 1237fbecc..f0bfbeb5e 100644 --- a/src/store/middlewares/voting.test.js +++ b/src/store/middlewares/voting.test.js @@ -9,21 +9,21 @@ describe('voting middleware', () => { let store; let next; const label = `Maximum of ${votingConst.maxCountOfVotesInOneTurn} votes in one transaction exceeded.`; + const label2 = `Maximum of ${votingConst.maxCountOfVotes} votes exceeded.`; - const generateNVotes = n => ( + const generateNVotes = (n, vote) => ( [...Array(n)].map((item, i) => i).reduce( (dict, value) => { - dict[`genesis_${value}`] = { confirmed: false, unconfirmed: true }; + dict[`genesis_${value}`] = vote; return dict; }, {}) ); - beforeEach(() => { - store = stub(); + const initStoreWithNVotes = (n, vote) => { store.getState = () => ({ voting: { votes: { - ...generateNVotes(votingConst.maxCountOfVotesInOneTurn + 1), + ...generateNVotes(n, vote), test2: { unconfirmed: false, confirmed: false, @@ -31,6 +31,13 @@ describe('voting middleware', () => { }, }, }); + }; + + beforeEach(() => { + store = stub(); + initStoreWithNVotes( + votingConst.maxCountOfVotesInOneTurn + 1, + { confirmed: false, unconfirmed: true }); store.dispatch = spy(); next = spy(); }); @@ -65,4 +72,32 @@ describe('voting middleware', () => { middleware(store)(next)(givenAction); expect(store.dispatch).to.not.have.been.calledWith(errorToastDisplayed({ label })); }); + + it('should dispatch errorToastDisplayed if 102 votes and new vote unconfirmed !== confirmed ', () => { + initStoreWithNVotes( + votingConst.maxCountOfVotes + 1, + { confirmed: true, unconfirmed: true }); + const givenAction = { + type: actionTypes.voteToggled, + data: { + username: 'test', + }, + }; + middleware(store)(next)(givenAction); + expect(store.dispatch).to.have.been.calledWith(errorToastDisplayed({ label: label2 })); + }); + + it('should not dispatch errorToastDisplayed if 102 votes and new vote unconfirmed === confirmed ', () => { + initStoreWithNVotes( + votingConst.maxCountOfVotes + 1, + { confirmed: true, unconfirmed: true }); + const givenAction = { + type: actionTypes.voteToggled, + data: { + username: 'genesis_42', + }, + }; + middleware(store)(next)(givenAction); + expect(store.dispatch).to.not.have.been.calledWith(errorToastDisplayed({ label: label2 })); + }); }); From d6f4816f133146084e5e19908b7e9ec3daa03a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Tue, 26 Sep 2017 14:16:33 +0200 Subject: [PATCH 23/36] Remove node_modules directory after build --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 570497a6e..4d181fe11 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -140,7 +140,7 @@ node('lisk-nano-01'){ rsync -axl --delete "$WORKSPACE/app/dist/" "jenkins@master-01:/var/www/test/lisk-nano/$BRANCH_NAME/" # Cleanup - delete all files on success - rm -rf "$WORKSPACE/*" + rm -rf "$WORKSPACE/node_modules/" ''' } catch (err) { fail('Stopping build, End to End Test suite failed') From ca820328d79b5512fe44be6630219a495f53ebb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Tue, 26 Sep 2017 14:36:43 +0200 Subject: [PATCH 24/36] Remove node_modules directory on failure --- Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4d181fe11..9be576c22 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,7 @@ def fail(reason) { slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> (${env.BRANCH_NAME}) failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' currentBuild.result = 'FAILURE' + sh 'rm -rf "$WORKSPACE/node_modules/"' milestone 1 error(${reason}) } @@ -140,7 +141,7 @@ node('lisk-nano-01'){ rsync -axl --delete "$WORKSPACE/app/dist/" "jenkins@master-01:/var/www/test/lisk-nano/$BRANCH_NAME/" # Cleanup - delete all files on success - rm -rf "$WORKSPACE/node_modules/" + rm -rf "$WORKSPACE/*" ''' } catch (err) { fail('Stopping build, End to End Test suite failed') From c3c4fbf38295a266c6143886ea84b4cc344ad4d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Tue, 26 Sep 2017 15:56:04 +0200 Subject: [PATCH 25/36] Cast ${reason} to string to prevent "No such DSL method '$'" errors. --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9be576c22..cf5ed4b30 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,7 +3,7 @@ def fail(reason) { currentBuild.result = 'FAILURE' sh 'rm -rf "$WORKSPACE/node_modules/"' milestone 1 - error(${reason}) + error("${reason}") } node('lisk-nano-01'){ From a18915108bc47c00424e10078e6801f9d51aa8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Tue, 26 Sep 2017 16:05:14 +0200 Subject: [PATCH 26/36] Add PR branch name to Slack failure notification --- Jenkinsfile | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index cf5ed4b30..61a5051dc 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,9 +1,13 @@ def fail(reason) { - slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> (${env.BRANCH_NAME}) failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' - currentBuild.result = 'FAILURE' - sh 'rm -rf "$WORKSPACE/node_modules/"' - milestone 1 - error("${reason}") + if (env.CHANGE_BRANCH == null) { + slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' + } else { + slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> (${env.CHANGE_BRANCH}) failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' + } + currentBuild.result = 'FAILURE' + sh 'rm -rf "$WORKSPACE/node_modules/"' + milestone 1 + error("${reason}") } node('lisk-nano-01'){ From 266a25c178f46ce190b569b6f3dccef8e448ace4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Tue, 26 Sep 2017 16:21:20 +0200 Subject: [PATCH 27/36] less code duplication --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 61a5051dc..dfe350373 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,9 +1,9 @@ def fail(reason) { - if (env.CHANGE_BRANCH == null) { - slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' - } else { - slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> (${env.CHANGE_BRANCH}) failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' + def pr_branch = '' + if (env.CHANGE_BRANCH != null) { + pr_branch = " ($BRANCH_NAME)" } + slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}>${pr_branch} failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' currentBuild.result = 'FAILURE' sh 'rm -rf "$WORKSPACE/node_modules/"' milestone 1 From 8ca91c977a255f1d9c368557e87b86dbfea020bb Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 27 Sep 2017 11:18:15 +0200 Subject: [PATCH 28/36] Fix plurals and context in i18n scanner --- src/i18n-scanner.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/i18n-scanner.js b/src/i18n-scanner.js index cb60cf114..ba537666b 100644 --- a/src/i18n-scanner.js +++ b/src/i18n-scanner.js @@ -7,8 +7,15 @@ const outputFilePath = './src/locales/en/common.json'; const parser = new Parser(); -const customHandler = function (key) { - parser.set(key, key); +const customHandler = function (key, options) { + const value = key; + if (options.context) { + key += `_${options.context}`; + } + parser.set(key, value); + if (options.count !== undefined) { + parser.set(`${key}_plural`); + } }; const files = glob.sync('./src/**/*.js', {}); From 5a7f2ea5e952a09002a83368bf6ac8222f384567 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 27 Sep 2017 11:18:50 +0200 Subject: [PATCH 29/36] Redefine i18n separators The defaults were '.' and ',' which we used in our texts sometimes --- src/i18n-scanner.js | 6 +++++- src/i18n.js | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/i18n-scanner.js b/src/i18n-scanner.js index ba537666b..8fbbc08ed 100644 --- a/src/i18n-scanner.js +++ b/src/i18n-scanner.js @@ -5,7 +5,11 @@ const Parser = require('i18next-scanner').Parser; const translationFunctionNames = ['i18next.t', 'props.t', 'this.props.t', 't']; const outputFilePath = './src/locales/en/common.json'; -const parser = new Parser(); +const parser = new Parser({ + keySeparator: '>', + nsSeparator: '|', +}); + const customHandler = function (key, options) { const value = key; diff --git a/src/i18n.js b/src/i18n.js index d45f2f59b..d5c399a9e 100755 --- a/src/i18n.js +++ b/src/i18n.js @@ -17,6 +17,9 @@ i18n ns: ['common'], defaultNS: 'common', + keySeparator: '>', + nsSeparator: '|', + debug: false, // cache: { From 114b62f10951310640074c24787db9e835fb65f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Wed, 27 Sep 2017 16:30:15 +0200 Subject: [PATCH 30/36] Actually show PR branch name in Slack failure notification --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index fa8274db5..2d97f5e11 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,7 +1,7 @@ def fail(reason) { def pr_branch = '' if (env.CHANGE_BRANCH != null) { - pr_branch = " ($BRANCH_NAME)" + pr_branch = " (${env.CHANGE_BRANCH})" } slackSend color: 'danger', message: "Build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}>${pr_branch} failed (<${env.BUILD_URL}/console|console>, <${env.BUILD_URL}/changes|changes>)\nCause: ${reason}", channel: '#lisk-nano-jenkins' currentBuild.result = 'FAILURE' From cb840beaa920c7f0310fdd0aef96545a753ca980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chavant?= Date: Wed, 27 Sep 2017 17:15:56 +0200 Subject: [PATCH 31/36] Send Slack sucess notification when job recovers --- Jenkinsfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 2d97f5e11..73c104ba8 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -147,6 +147,10 @@ node('lisk-nano-01'){ fail('Stopping build, Deploy failed') } milestone 1 + /* notify of success if previous build failed */ + if (currentBuild.getPreviousBuild().result == 'FAILURE') { + slackSend color: 'good', message: "Recovery: build #${env.BUILD_NUMBER} of <${env.BUILD_URL}|${env.JOB_NAME}> was sucessful.", channel: '#lisk-nano-jenkins' + } } } } From 8b71c171b8891c87947d484f6a3c701ab1943418 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Wed, 27 Sep 2017 14:13:23 +0200 Subject: [PATCH 32/36] Fix forging stats unit tests --- src/components/forging/forgingStats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/forging/forgingStats.js b/src/components/forging/forgingStats.js index ead417167..92867d455 100644 --- a/src/components/forging/forgingStats.js +++ b/src/components/forging/forgingStats.js @@ -31,7 +31,7 @@ class ForgingStats extends React.Component { statCardObjects[0].label = this.props.t('Last 24 hours'); [1, 2, 3].forEach((i) => { statCardObjects[i].label = this.props.t( - 'Last x days', { count: statCardObjects[i].days }); + 'Last {{count}} days', { count: statCardObjects[i].days }); }); return ( From 6ed42bb0d622ddbc86c938f63824e9df99684507 Mon Sep 17 00:00:00 2001 From: reyraa Date: Thu, 28 Sep 2017 10:56:09 +0200 Subject: [PATCH 33/36] Enhance the routing of dialog --- src/components/dialog/dialog.js | 82 ++++++++++++++++++++------------ src/components/dialog/dialogs.js | 5 ++ 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index e1bdfa7ac..65adec27b 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -10,56 +10,81 @@ class DialogElement extends Component { constructor() { super(); this.state = {}; - this.path = { - name: '/', + this.routesReg = [ + { + regex: /\/main\/transactions(?:\/[^/]*)?$/, + path: '/main/transactions/', + params: 'dialog', + name: 'transactions', + }, { + regex: /\/main\/voting(?:\/[^/]*)?$/, + path: '/main/voting/', + params: 'dialog', + name: 'voting', + }, { + regex: /\/main\/forging(?:\/[^/]*)?$/, + path: '/main/forging/', + params: 'dialog', + name: 'forging', + }, { + regex: /\/(\w+)?$/, + path: '/', + params: 'dialog', + name: 'login', + }, + ]; + this.current = { + pathname: '/', + reg: this.routesReg[3], list: [], dialog: '', }; } componentDidMount() { - this.checkForDialog(this.props.history.location); + this.checkForDialog(); } componentDidUpdate() { - if (this.path.name !== this.props.history.location.pathname) { - this.path.name = this.props.history.location.pathname; - this.checkForDialog(this.props.history.location); + this.checkForDialog(); + } + + checkForDialog() { + if (this.current.pathname !== this.props.history.location.pathname) { + this.current.reg = this.routesReg.find(item => + item.regex.test(this.props.history.location.pathname)); + this.current.pathname = this.props.history.location.pathname; + const dialogName = this.props.history.location.pathname.replace(this.current.reg.path, ''); + if (dialogs[dialogName] !== undefined) { + this.open(this.current.reg, dialogs[dialogName]); + } else { + this.close(); + } } } - checkForDialog(location) { - const parseParams = search => search.replace(/^\?/, '').split('&&').reduce((acc, param) => { + // eslint-disable-next-line class-methods-use-this + parseParams(search) { + return search.replace(/^\?/, '').split('&&').reduce((acc, param) => { const keyValue = param.split('='); if (keyValue[0] !== '' && keyValue[1] !== 'undefined') { acc[keyValue[0]] = keyValue[1]; } return acc; }, {}); - - this.path.list = location.pathname.replace(/\/$/, '').split('/'); - this.dialog = this.path.list[3]; - - if (this.path.list.length === 5) { - this.props.history.push(`/${this.path.list[1]}/${this.path.list[2]}/${this.path.list[4]}`); - } else if (this.path.list.length === 4 && Object.keys(dialogs).includes(this.dialog)) { - this.routeWithDialog(dialogs[this.dialog], parseParams(location.search)); - } else { - this.routeWithOutDialog(); - } } - routeWithDialog(dialog, childComponentProps) { + open(config, dialog) { clearTimeout(this.timeout); this.setState({ hidden: false }); this.props.dialogDisplayed({ title: dialog.title, childComponent: dialog.component, - childComponentProps, + childComponentProps: this.parseParams(this.props.history.location.search), }); } - routeWithOutDialog() { + close() { this.timeout = setTimeout(() => { this.props.dialogHidden(); this.setState({ hidden: false }); @@ -67,13 +92,8 @@ class DialogElement extends Component { this.setState({ hidden: true }); } - closeDialog() { - if (this.props.dialog.childComponentProps.noRouter) { - this.routeWithOutDialog(); - } else { - const upperRoute = this.path.name.replace(/\/$/, '').replace(this.dialog, ''); - this.props.history.push(upperRoute); - } + goBack() { + this.props.history.push(this.current.reg.path); } render() { @@ -85,14 +105,14 @@ class DialogElement extends Component { - +
{this.props.dialog.childComponent ? : null } diff --git a/src/components/dialog/dialogs.js b/src/components/dialog/dialogs.js index 89f81eeda..9256dbb27 100644 --- a/src/components/dialog/dialogs.js +++ b/src/components/dialog/dialogs.js @@ -6,6 +6,7 @@ import SecondPassphrase from '../secondPassphrase'; import VoteDialog from '../voteDialog'; import ReceiveDialog from '../receiveDialog'; import SaveAccount from '../saveAccount'; +import Register from '../register'; export default { send: { @@ -36,6 +37,10 @@ export default { title: 'Receive LSK', component: ReceiveDialog, }, + register: { + title: 'New Account', + component: Register, + }, 'save-account': { title: 'Remember this account', component: SaveAccount, From caa6a56ac791805d2c39f94d6bf722707a95a120 Mon Sep 17 00:00:00 2001 From: reyraa Date: Thu, 28 Sep 2017 10:57:58 +0200 Subject: [PATCH 34/36] Use routing for the register dialog --- src/components/app/index.js | 1 + src/components/login/login.js | 18 ++----- src/components/register/index.js | 15 ++++++ src/components/register/index.test.js | 31 ++++++++++++ src/components/register/register.css | 3 ++ src/components/register/register.js | 61 ++++++++++++++++++++++++ src/components/register/register.test.js | 56 ++++++++++++++++++++++ 7 files changed, 170 insertions(+), 15 deletions(-) create mode 100644 src/components/register/index.js create mode 100644 src/components/register/index.test.js create mode 100644 src/components/register/register.css create mode 100644 src/components/register/register.js create mode 100644 src/components/register/register.test.js diff --git a/src/components/app/index.js b/src/components/app/index.js index 8f516fa21..25f392af0 100644 --- a/src/components/app/index.js +++ b/src/components/app/index.js @@ -31,6 +31,7 @@ const App = () => ( )} /> + diff --git a/src/components/login/login.js b/src/components/login/login.js index 1ce655891..29304ccfa 100644 --- a/src/components/login/login.js +++ b/src/components/login/login.js @@ -7,7 +7,7 @@ import networksRaw from './networks'; import PassphraseInput from '../passphraseInput'; import styles from './login.css'; import env from '../../constants/env'; -import Passphrase from '../passphrase'; +import RelativeLink from '../relativeLink'; /** * The container component containing login @@ -188,20 +188,8 @@ class Login extends React.Component { onChange={this.changeHandler.bind(this, 'passphrase')} />