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

View File

@ -60,6 +60,39 @@ export default class VerificationStore {
return phone.isValidNumber(this.number); 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) { constructor (api, account) {
this.api = api; this.api = api;
this.account = account; 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 = () => { @action sendRequest = () => {
const { api, account, contract, fee, number, hasRequested } = this; const { api, account, contract, fee, number, hasRequested } = this;
@ -153,8 +178,8 @@ export default class VerificationStore {
}); });
} }
@action setCode = (code) => { @action queryCode = () => {
this.code = code; this.step = VerificationStore.QUERY_CODE;
} }
@action sendConfirmation = () => { @action sendConfirmation = () => {
@ -188,4 +213,8 @@ export default class VerificationStore {
this.error = 'Failed to send the verification code: ' + err.message; this.error = 'Failed to send the verification code: ' + err.message;
}); });
} }
@action done = () => {
this.step = VerificationStore.DONE;
}
} }