sms verification: use Mobx store

This commit is contained in:
Jannis R 2016-11-15 16:21:53 +01:00
parent bfcc8d33d6
commit 3e879aac35
No known key found for this signature in database
GPG Key ID: 0FE83946296A88A5
2 changed files with 113 additions and 120 deletions

View File

@ -15,14 +15,20 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
import React, { Component, PropTypes } from 'react';
import { observer } from 'mobx-react';
import ActionDoneAll from 'material-ui/svg-icons/action/done-all';
import ContentClear from 'material-ui/svg-icons/content/clear';
import { Button, IdentityIcon, Modal } from '../../ui';
import ABI from '../../contracts/abi/sms-verification.json';
// TODO: move this to a better place
const contract = '0xcE381B876A85A72303f7cA7b3a012f58F4CEEEeB';
import VerificationStore from './store';
const {
GATHERING_DATA, GATHERED_DATA,
POSTING_REQUEST, POSTED_REQUEST,
REQUESTING_SMS, REQUESTED_SMS,
POSTING_CONFIRMATION, POSTED_CONFIRMATION,
DONE
} = VerificationStore;
import GatherData from './GatherData';
import SendRequest from './SendRequest';
@ -30,6 +36,7 @@ import QueryCode from './QueryCode';
import SendConfirmation from './SendConfirmation';
import Done from './Done';
@observer
export default class SMSVerification extends Component {
static contextTypes = {
api: PropTypes.object.isRequired
@ -40,41 +47,51 @@ export default class SMSVerification extends Component {
onClose: PropTypes.func.isRequired
}
static uiSteps = { // mapping (store steps -> steps)
[GATHERING_DATA]: 0, [GATHERED_DATA]: 0,
[POSTING_REQUEST]: 1, [POSTED_REQUEST]: 1, [REQUESTING_SMS]: 1,
[REQUESTED_SMS]: 2,
[POSTING_CONFIRMATION]: 3, [POSTED_CONFIRMATION]: 3,
[DONE]: 4
}
state = {
contract: null,
step: 0,
stepIsValid: false,
data: {}
store: null
}
componentDidMount () {
const { api } = this.context;
const { account } = this.props;
this.setState({
contract: api.newContract(ABI, contract)
const store = new VerificationStore(api, account);
this.setState({ store }, () => {
store.gatherData();
});
}
render () {
const { step } = this.state;
const { store } = this.state;
if (!store) return null;
const step = SMSVerification.uiSteps[store.step];
const { error, isStepValid } = store;
return (
<Modal
actions={ this.renderDialogActions() }
actions={ this.renderDialogActions(step, error, isStepValid) }
title='verify your account via SMS'
visible scroll
current={ step }
steps={ ['Enter Data', 'Request', 'Enter Code', 'Confirm', 'Done!'] }
waiting={ [ 1, 3 ] }
>
{ this.renderStep() }
{ this.renderStep(step, error) }
</Modal>
);
}
renderDialogActions () {
renderDialogActions (step, error, isStepValid) {
const { onClose, account } = this.props;
const { step, stepIsValid } = this.state;
const { store } = this.state;
const cancel = (
<Button
@ -83,6 +100,7 @@ export default class SMSVerification extends Component {
onClick={ onClose }
/>
);
if (error) return (<div>{ cancel }</div>);
if (step === 4) {
return (
@ -90,7 +108,7 @@ export default class SMSVerification extends Component {
{ cancel }
<Button
key='done' label='Done'
disabled={ !stepIsValid }
disabled={ !isStepValid }
icon={ <ActionDoneAll /> }
onClick={ onClose }
/>
@ -98,116 +116,62 @@ export default class SMSVerification extends Component {
);
}
let action;
if (step === 3) {
action = store.done;
} else if (step === 2) {
action = store.sendConfirmation;
} else if (step === 1) {
action = store.queryCode;
} else if (step === 0) {
action = store.sendRequest;
}
return (
<div>
{ cancel }
<Button
key='next' label='Next'
disabled={ !stepIsValid }
disabled={ !isStepValid }
icon={ <IdentityIcon address={ account } button /> }
onClick={ this.next }
onClick={ action }
/>
</div>
);
}
renderStep () {
const { contract } = this.state;
if (!contract) {
return null;
}
renderStep (step, error) {
if (error) return (<p>{ error }</p>);
const {
fee, isNumberValid, isVerified, hasRequested,
requestTx, isCodeValid, confirmationTx,
setNumber, setConsentGiven, setCode
} = this.state.store;
const { step } = this.state;
if (step === 4) {
return this.renderFifthStep();
} else if (step === 3) {
return this.renderFourthStep();
} else if (step === 2) {
return this.renderThirdStep();
} else if (step === 1) {
return this.renderSecondStep();
} else {
return this.renderFirstStep();
return (<Done />);
}
}
onDataIsValid = () => {
this.setState({ stepIsValid: true });
}
onDataIsInvalid = () => {
this.setState({ stepIsValid: false });
}
onData = (data) => {
this.setState({
data: Object.assign({}, this.state.data, data)
});
}
next = () => {
const { stepIsValid } = this.state;
if (stepIsValid) {
this.setState({ step: this.state.step + 1, stepIsValid: false });
if (step === 3) {
return (<SendConfirmation step={ step } tx={ confirmationTx } />);
}
if (step === 2) {
return (<QueryCode fee={ fee } isCodeValid={ isCodeValid } setCode={ setCode } />);
}
if (step === 1) {
return (<SendRequest step={ step } tx={ requestTx } />);
}
if (step === 0) {
const { setNumber, setConsentGiven } = this.state.store;
return (
<GatherData
fee={ fee } isNumberValid={ isNumberValid }
isVerified={ isVerified } hasRequested={ hasRequested }
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
/>
);
}
}
renderFirstStep () {
const { account } = this.props;
const { contract, data } = this.state;
return (
<GatherData
account={ account } contract={ contract } data={ data }
onData={ this.onData }
onDataIsValid={ this.onDataIsValid }
onDataIsInvalid={ this.onDataIsInvalid }
/>
);
}
renderSecondStep () {
const { account } = this.props;
const { contract, data } = this.state;
return (
<SendRequest
account={ account } contract={ contract } data={ data }
onData={ this.onData }
onSuccess={ this.onDataIsValid }
onError={ this.onDataIsInvalid }
nextStep={ this.next }
/>
);
}
renderThirdStep () {
const { data } = this.state;
return (
<QueryCode
data={ data }
onData={ this.onData }
onDataIsValid={ this.onDataIsValid }
onDataIsInvalid={ this.onDataIsInvalid }
/>
);
}
renderFourthStep () {
const { account } = this.props;
const { contract, data } = this.state;
return (
<SendConfirmation
account={ account } contract={ contract } data={ data }
onData={ this.onData }
onSuccess={ this.onDataIsValid }
onError={ this.onDataIsInvalid }
nextStep={ this.next }
/>
);
}
renderFifthStep () {
return (<Done onSuccess={ this.onDataIsValid } />);
return null;
}
}

View File

@ -60,6 +60,39 @@ export default class VerificationStore {
return phone.isValidNumber(this.number);
}
@computed get isStepValid () {
if (this.step === VerificationStore.DONE) {
return true;
}
if (this.error) {
return false;
}
if (this.step === VerificationStore.GATHERED_DATA) {
return this.fee && this.isVerified === false && this.isNumberValid && this.consentGiven;
}
if (this.step === VerificationStore.REQUESTED_SMS) {
return this.requestTx;
}
if (this.step === VerificationStore.QUERY_CODE) {
return this.isCodeValid;
}
if (this.step === VerificationStore.POSTED_CONFIRMATION) {
return this.confirmationTx;
}
return false;
}
@action setNumber = (number) => {
this.number = number;
}
@action setConsentGiven = (consentGiven) => {
this.consentGiven = consentGiven;
}
@action setCode = (code) => {
this.code = code;
}
constructor (api, account) {
this.api = api;
this.account = account;
@ -106,14 +139,6 @@ export default class VerificationStore {
});
}
@action setNumber = (number) => {
this.number = number;
}
@action setConsentGiven = (consentGiven) => {
this.consentGiven = consentGiven;
}
@action sendRequest = () => {
const { api, account, contract, fee, number, hasRequested } = this;
@ -153,8 +178,8 @@ export default class VerificationStore {
});
}
@action setCode = (code) => {
this.code = code;
@action queryCode = () => {
this.step = VerificationStore.QUERY_CODE;
}
@action sendConfirmation = () => {
@ -188,4 +213,8 @@ export default class VerificationStore {
this.error = 'Failed to send the verification code: ' + err.message;
});
}
@action done = () => {
this.step = VerificationStore.DONE;
}
}