sms verification: use Mobx store
This commit is contained in:
parent
bfcc8d33d6
commit
3e879aac35
@ -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 } />);
|
||||||
}
|
}
|
||||||
|
if (step === 2) {
|
||||||
onDataIsValid = () => {
|
return (<QueryCode fee={ fee } isCodeValid={ isCodeValid } setCode={ setCode } />);
|
||||||
this.setState({ stepIsValid: true });
|
|
||||||
}
|
}
|
||||||
onDataIsInvalid = () => {
|
if (step === 1) {
|
||||||
this.setState({ stepIsValid: false });
|
return (<SendRequest step={ step } tx={ requestTx } />);
|
||||||
}
|
}
|
||||||
onData = (data) => {
|
if (step === 0) {
|
||||||
this.setState({
|
const { setNumber, setConsentGiven } = this.state.store;
|
||||||
data: Object.assign({}, this.state.data, data)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
next = () => {
|
|
||||||
const { stepIsValid } = this.state;
|
|
||||||
if (stepIsValid) {
|
|
||||||
this.setState({ step: this.state.step + 1, stepIsValid: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFirstStep () {
|
|
||||||
const { account } = this.props;
|
|
||||||
const { contract, data } = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GatherData
|
<GatherData
|
||||||
account={ account } contract={ contract } data={ data }
|
fee={ fee } isNumberValid={ isNumberValid }
|
||||||
onData={ this.onData }
|
isVerified={ isVerified } hasRequested={ hasRequested }
|
||||||
onDataIsValid={ this.onDataIsValid }
|
setNumber={ setNumber } setConsentGiven={ setConsentGiven }
|
||||||
onDataIsInvalid={ this.onDataIsInvalid }
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSecondStep () {
|
return null;
|
||||||
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 } />);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user