From 5be528932611869a4670c524cc0b123f09622184 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 27 Jul 2017 14:35:01 +0200 Subject: [PATCH 1/5] Implement Alert dialogs --- src/actions/dialog.js | 34 ++++++++++++++++++++++++++ src/components/dialog/alert.js | 17 +++++++++++++ src/components/dialog/dialog.css | 8 ++++++ src/components/dialog/dialogElement.js | 3 ++- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/components/dialog/alert.js diff --git a/src/actions/dialog.js b/src/actions/dialog.js index 23d9510bc..cc951babb 100644 --- a/src/actions/dialog.js +++ b/src/actions/dialog.js @@ -1,4 +1,5 @@ import actionTypes from '../constants/actions'; +import Alert from '../components/dialog/alert'; /** * An action to dispatch to display a dialog @@ -9,6 +10,39 @@ export const dialogDisplayed = data => ({ type: actionTypes.dialogDisplayed, }); +/** + * An action to dispatch to display an alert dialog + * + */ +export const alertDialogDisplayed = data => dialogDisplayed({ + title: data.title, + type: data.type, + childComponent: Alert, + childComponentProps: { + text: data.text, + }, +}); + +/** + * An action to dispatch to display a success alert dialog + * + */ +export const successAlertDialogDisplayed = data => alertDialogDisplayed({ + title: 'Success', + text: data.text, + type: 'success', +}); + +/** + * An action to dispatch to display a error alert dialog + * + */ +export const errorAlertDialogDisplayed = data => alertDialogDisplayed({ + title: 'Error', + text: data.text, + type: 'error', +}); + /** * An action to dispatch to hide a dialog * diff --git a/src/components/dialog/alert.js b/src/components/dialog/alert.js new file mode 100644 index 000000000..a3a28831c --- /dev/null +++ b/src/components/dialog/alert.js @@ -0,0 +1,17 @@ +import React from 'react'; +import Button from 'react-toolbox/lib/button'; +import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; + + +const Alert = props => ( +
+

{props.text}

+
+
+ +
+
+); + +export default Alert; diff --git a/src/components/dialog/dialog.css b/src/components/dialog/dialog.css index f1c96bd4e..1a7fe5329 100644 --- a/src/components/dialog/dialog.css +++ b/src/components/dialog/dialog.css @@ -38,3 +38,11 @@ } } } + +.error { + background-color: #c62828; +} + +.success { + background-color: #7cb342; +} diff --git a/src/components/dialog/dialogElement.js b/src/components/dialog/dialogElement.js index d4693ec9c..e690945a1 100644 --- a/src/components/dialog/dialogElement.js +++ b/src/components/dialog/dialogElement.js @@ -25,7 +25,8 @@ class DialogElement extends Component {
- + From 6243f3a79658d5ed244032eee136d10608d864b7 Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 27 Jul 2017 14:35:20 +0200 Subject: [PATCH 2/5] Add alert dialog stories --- src/components/dialog/stories.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/components/dialog/stories.js b/src/components/dialog/stories.js index 47e366a43..c715fd947 100644 --- a/src/components/dialog/stories.js +++ b/src/components/dialog/stories.js @@ -3,6 +3,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import Dialog from './dialogElement'; +import Alert from './alert'; const dialogContent = () => (
Hello
); @@ -15,4 +16,30 @@ storiesOf('Dialog', module) }} onCancelClick={ action('onCancelClick') } /> + )) + .add('Success alert', () => ( + + )) + .add('Error alert', () => ( + )); From 96900e5083b404991542b04e1f2f09bac43d265c Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 27 Jul 2017 14:35:43 +0200 Subject: [PATCH 3/5] Use alert dialogs in send dialog --- src/components/send/index.js | 8 +++++++- src/components/send/send.js | 13 ++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/components/send/index.js b/src/components/send/index.js index ef9cf9df2..cb9f2907e 100644 --- a/src/components/send/index.js +++ b/src/components/send/index.js @@ -1,10 +1,16 @@ import { connect } from 'react-redux'; import Send from './send'; +import { successAlertDialogDisplayed, errorAlertDialogDisplayed } from '../../actions/dialog'; const mapStateToProps = state => ({ account: state.account, activePeer: state.peers.data, }); -export default connect(mapStateToProps)(Send); +const mapDispatchToProps = dispatch => ({ + showSuccessAlert: data => dispatch(successAlertDialogDisplayed(data)), + showErrorAlert: data => dispatch(errorAlertDialogDisplayed(data)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Send); diff --git a/src/components/send/send.js b/src/components/send/send.js index 602d80f3c..cd62abd6a 100644 --- a/src/components/send/send.js +++ b/src/components/send/send.js @@ -68,14 +68,13 @@ class Send extends React.Component { this.props.account.passphrase, this.props.account.sencodPassphrase, ).then(() => { - // TODO implement and use our custom alert dialogs - // eslint-disable-next-line no-alert - alert(`Your transaction of ${this.state.amount.value} LSK to ${this.state.recipient.value} was accepted and will be processed in a few seconds.`); - this.props.closeDialog(); + this.props.showSuccessAlert({ + text: `Your transaction of ${this.state.amount.value} LSK to ${this.state.recipient.value} was accepted and will be processed in a few seconds.`, + }); }).catch((res) => { - // TODO implement and use our custom alert dialogs - // eslint-disable-next-line no-alert - alert(res && res.message ? res.message : 'An error occurred while creating the transaction.'); + this.props.showErrorAlert({ + text: res && res.message ? res.message : 'An error occurred while creating the transaction.', + }); }); } From 7ea3bfb1a185b2bff599024baaeb4de45eda490c Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Thu, 27 Jul 2017 14:54:14 +0200 Subject: [PATCH 4/5] Add unit tests for alert dialogs --- src/actions/dialog.test.js | 74 ++++++++++++++++++++++++++++- src/components/dialog/alert.test.js | 34 +++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/components/dialog/alert.test.js diff --git a/src/actions/dialog.test.js b/src/actions/dialog.test.js index 4ce08ef3b..059f5b93c 100644 --- a/src/actions/dialog.test.js +++ b/src/actions/dialog.test.js @@ -1,6 +1,14 @@ import { expect } from 'chai'; import actionTypes from '../constants/actions'; -import { dialogDisplayed, dialogHidden } from './dialog'; +import { + dialogDisplayed, + alertDialogDisplayed, + successAlertDialogDisplayed, + errorAlertDialogDisplayed, + dialogHidden, +} from './dialog'; +import Alert from '../components/dialog/alert'; + describe('actions: dialog', () => { describe('dialogDisplayed', () => { @@ -18,6 +26,70 @@ describe('actions: dialog', () => { }); }); + describe('alertDialogDisplayed', () => { + it('should create an action to show alert dialog', () => { + const data = { + title: 'success', + text: 'some text', + }; + + const expectedAction = { + data: { + title: data.title, + type: undefined, + childComponent: Alert, + childComponentProps: { + text: data.text, + }, + }, + type: actionTypes.dialogDisplayed, + }; + expect(alertDialogDisplayed(data)).to.be.deep.equal(expectedAction); + }); + }); + + describe('successAlertDialogDisplayed', () => { + it('should create an action to show alert dialog', () => { + const data = { + text: 'some text', + }; + + const expectedAction = { + data: { + title: 'Success', + type: 'success', + childComponent: Alert, + childComponentProps: { + text: data.text, + }, + }, + type: actionTypes.dialogDisplayed, + }; + expect(successAlertDialogDisplayed(data)).to.be.deep.equal(expectedAction); + }); + }); + + describe('errorAlertDialogDisplayed', () => { + it('should create an action to show alert dialog', () => { + const data = { + text: 'some text', + }; + + const expectedAction = { + data: { + title: 'Error', + type: 'error', + childComponent: Alert, + childComponentProps: { + text: data.text, + }, + }, + type: actionTypes.dialogDisplayed, + }; + expect(errorAlertDialogDisplayed(data)).to.be.deep.equal(expectedAction); + }); + }); + describe('dialogHidden', () => { it('should create an action to hide dialog', () => { const expectedAction = { diff --git a/src/components/dialog/alert.test.js b/src/components/dialog/alert.test.js new file mode 100644 index 000000000..2037101f0 --- /dev/null +++ b/src/components/dialog/alert.test.js @@ -0,0 +1,34 @@ +import React from 'react'; +import chai, { expect } from 'chai'; +import { mount } from 'enzyme'; +import sinon from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiEnzyme from 'chai-enzyme'; +import Alert from './alert'; + +chai.use(sinonChai); +chai.use(chaiEnzyme()); // Note the invocation at the end + +describe('Alert', () => { + let wrapper; + let closeSpy; + const text = 'some random text'; + + beforeEach(() => { + closeSpy = sinon.spy(); + wrapper = mount(); + }); + + it('renders paragraph with props.text', () => { + expect(wrapper.find('p').text()).to.equal(text); + }); + + it('renders "Ok" Button', () => { + expect(wrapper.find('Button').text()).to.equal('Ok'); + }); + + it('renders "Ok" Button that calls props.closeDialog on click', () => { + wrapper.find('Button').simulate('click'); + expect(closeSpy).to.have.been.calledWith(); + }); +}); From a4acdd7d44d9134dae1b53b26cce3aea4f8a178b Mon Sep 17 00:00:00 2001 From: Vit Stanislav Date: Fri, 28 Jul 2017 11:49:12 +0200 Subject: [PATCH 5/5] Replace relative flexboxgrid imports with absolute --- src/components/dialog/alert.js | 2 +- src/components/forging/delegateStats.js | 2 +- src/components/forging/forgedBlocks.js | 2 +- src/components/forging/forgingStats.js | 2 +- src/components/forging/forgingTitle.js | 2 +- src/components/send/send.js | 2 +- src/components/signVerify/signMessage.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/dialog/alert.js b/src/components/dialog/alert.js index a3a28831c..538255f1f 100644 --- a/src/components/dialog/alert.js +++ b/src/components/dialog/alert.js @@ -1,6 +1,6 @@ import React from 'react'; import Button from 'react-toolbox/lib/button'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; const Alert = props => ( diff --git a/src/components/forging/delegateStats.js b/src/components/forging/delegateStats.js index f9e72401f..19a5654e8 100644 --- a/src/components/forging/delegateStats.js +++ b/src/components/forging/delegateStats.js @@ -1,7 +1,7 @@ import React from 'react'; import { Card, CardText } from 'react-toolbox/lib/card'; import CircularProgressbar from 'react-circular-progressbar'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import style from './forging.css'; const identity = x => (x); diff --git a/src/components/forging/forgedBlocks.js b/src/components/forging/forgedBlocks.js index d43ee5808..c1c0afb1c 100644 --- a/src/components/forging/forgedBlocks.js +++ b/src/components/forging/forgedBlocks.js @@ -1,10 +1,10 @@ import React from 'react'; import { Card, CardTitle } from 'react-toolbox/lib/card'; import { Table, TableHead, TableRow, TableCell } from 'react-toolbox/lib/table'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import { TooltipTime } from '../timestamp'; import LiskAmount from '../liskAmount'; import FormattedNumber from '../formattedNumber'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; import style from './forging.css'; diff --git a/src/components/forging/forgingStats.js b/src/components/forging/forgingStats.js index ec0cca590..2e90dda21 100644 --- a/src/components/forging/forgingStats.js +++ b/src/components/forging/forgingStats.js @@ -1,8 +1,8 @@ import React from 'react'; import { Card, CardText } from 'react-toolbox/lib/card'; import moment from 'moment'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import LiskAmount from '../liskAmount'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; import style from './forging.css'; const statCardObjects = [ diff --git a/src/components/forging/forgingTitle.js b/src/components/forging/forgingTitle.js index 43802ef18..a8de24a59 100644 --- a/src/components/forging/forgingTitle.js +++ b/src/components/forging/forgingTitle.js @@ -1,8 +1,8 @@ import React from 'react'; import { Card, CardText } from 'react-toolbox/lib/card'; import moment from 'moment'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import LiskAmount from '../liskAmount'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; import style from './forging.css'; diff --git a/src/components/send/send.js b/src/components/send/send.js index cd62abd6a..c05f19a32 100644 --- a/src/components/send/send.js +++ b/src/components/send/send.js @@ -2,12 +2,12 @@ import React from 'react'; import Input from 'react-toolbox/lib/input'; import Button from 'react-toolbox/lib/button'; import { IconMenu, MenuItem } from 'react-toolbox/lib/menu'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import { send } from '../../utils/api/account'; import { fromRawLsk, toRawLsk } from '../../utils/lsk'; import styles from './send.css'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; class Send extends React.Component { constructor() { diff --git a/src/components/signVerify/signMessage.js b/src/components/signVerify/signMessage.js index 7cf2ff2bb..e07f5b9f9 100644 --- a/src/components/signVerify/signMessage.js +++ b/src/components/signVerify/signMessage.js @@ -3,11 +3,11 @@ import Input from 'react-toolbox/lib/input'; import Button from 'react-toolbox/lib/button'; import copy from 'copy-to-clipboard'; import { toastr } from 'react-redux-toastr'; +import grid from 'flexboxgrid/dist/flexboxgrid.css'; import lisk from 'lisk-js'; import InfoParagraph from '../infoParagraph'; import SignVerifyResult from './signVerifyResult'; -import grid from '../../../node_modules/flexboxgrid/dist/flexboxgrid.css'; class SignMessage extends React.Component {