Skip to content
This repository has been archived by the owner on Apr 15, 2019. It is now read-only.

Implement custom alert dialogs in React - Closes #515 #526

Merged
merged 5 commits into from
Jul 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/actions/dialog.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import actionTypes from '../constants/actions';
import Alert from '../components/dialog/alert';

/**
* An action to dispatch to display a dialog
Expand All @@ -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
*
Expand Down
74 changes: 73 additions & 1 deletion src/actions/dialog.test.js
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand All @@ -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 = {
Expand Down
17 changes: 17 additions & 0 deletions src/components/dialog/alert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import Button from 'react-toolbox/lib/button';
import grid from 'flexboxgrid/dist/flexboxgrid.css';


const Alert = props => (
<div>
<p>{props.text}</p>
<br />
<section className={`${grid.row} ${grid['between-xs']}`}>
<span />
<Button label='Ok' onClick={props.closeDialog}/>
</section>
</div>
);

export default Alert;
34 changes: 34 additions & 0 deletions src/components/dialog/alert.test.js
Original file line number Diff line number Diff line change
@@ -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(<Alert text={text} closeDialog={closeSpy} />);
});

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();
});
});
8 changes: 8 additions & 0 deletions src/components/dialog/dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@
}
}
}

.error {
background-color: #c62828;
}

.success {
background-color: #7cb342;
}
3 changes: 2 additions & 1 deletion src/components/dialog/dialogElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class DialogElement extends Component {
<Dialog active={this.props.dialog.childComponent !== undefined && !this.state.hidden}
type='fullscreen'>
<div className={styles.dialog}>
<AppBar title={this.props.dialog.title} flat={true}>
<AppBar title={this.props.dialog.title} flat={true}
className={styles[this.props.dialog.type]}>
<Navigation type='horizontal'>
<IconButton className={`${styles['x-button']} x-button`} onClick={this.closeDialog.bind(this)} icon='close'/>
</Navigation>
Expand Down
27 changes: 27 additions & 0 deletions src/components/dialog/stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => (<div>Hello</div>);

Expand All @@ -15,4 +16,30 @@ storiesOf('Dialog', module)
}}
onCancelClick={ action('onCancelClick') }
/>
))
.add('Success alert', () => (
<Dialog
dialog={{
title: 'Success',
type: 'success',
childComponent: Alert,
childComponentProps: {
text: 'Custom success message',
},
}}
onCancelClick={ action('onCancelClick') }
/>
))
.add('Error alert', () => (
<Dialog
dialog={{
title: 'Error',
type: 'error',
childComponent: Alert,
childComponentProps: {
text: 'Custom error message',
},
}}
onCancelClick={ action('onCancelClick') }
/>
));
2 changes: 1 addition & 1 deletion src/components/forging/delegateStats.js
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/components/forging/forgedBlocks.js
Original file line number Diff line number Diff line change
@@ -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';


Expand Down
2 changes: 1 addition & 1 deletion src/components/forging/forgingStats.js
Original file line number Diff line number Diff line change
@@ -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 = [
Expand Down
2 changes: 1 addition & 1 deletion src/components/forging/forgingTitle.js
Original file line number Diff line number Diff line change
@@ -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';


Expand Down
8 changes: 7 additions & 1 deletion src/components/send/index.js
Original file line number Diff line number Diff line change
@@ -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);

15 changes: 7 additions & 8 deletions src/components/send/send.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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.',
});
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/signVerify/signMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down