on master help sign in
Send invite email on transaction confirmation
commit7029bf479edf3215adcf70c6e5a68121c2f4fd1c authorFang <git@fang.io> dateThu 25 Apr 2019, 22:55 (8 years ago) parentef67dec
2 files changed+75−8
src/bridge/lib/inviteMail.js+27 src/bridge/views/InvitesSend.js+48−8
src/bridge/lib/inviteMail.jsnew file+27
@@ -0,0 +1,27 @@
1+//NOTE if accessing this in a localhost configuration fails with "CORS request
2+// did not succeed", you might need to visit localhost:3001 or whatever
3+// explicitly and tell your browser that's safe to access.
4+// https://stackoverflow.com/a/53011185/1334324
5+const baseUrl = 'https://localhost:3002'
6+
7+function sendMail(recipient, ticket) {
8+ return new Promise((resolve, reject) => {
9+ fetch(baseUrl + '/send-ticket', {
10+ method: "POST",
11+ // mode: "cors", // no-cors, cors, *same-origin
12+ cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
13+ // credentials: "omit", // include, *same-origin, omit
14+ headers: {
15+ "Content-Type": "application/json",
16+ },
17+ body: JSON.stringify({recipient,ticket}),
18+ })
19+ .then(response => resolve(response.ok))
20+ .catch(reject);
21+ });
22+}
23+
24+export {
25+ sendMail
26+}
27+
src/bridge/views/InvitesSend.js+48−8
@@ -16,7 +16,10 @@ import ReactSVGComponents from '../components/ReactSVGComponents'
1616import KeysAndMetadata from './Point/KeysAndMetadata'
1717import Actions from './Point/Actions'
1818import { BRIDGE_ERROR } from '../lib/error'
19−import { Row, Col, Warning, Button, H1, H3 } from '../components/Base'
19+import { sendMail } from '../lib/inviteMail'
20+import { Row, Col, Warning, Button, H1, H3,
21+ Input, InnerLabel
22+} from '../components/Base'
2023import StatelessTransaction from '../components/StatelessTransaction'
2124
2225// for wallet generation
@@ -35,7 +38,6 @@ import {
3538import * as tank from '../lib/tank'
3639import Tx from 'ethereumjs-tx'
3740
38−//TODO needs more work to include email sending in the process
3941class InvitesSend extends React.Component {
4042
4143 constructor(props) {
@@ -46,13 +48,19 @@ class InvitesSend extends React.Component {
4648 fromPool: Nothing(),
4749 haveInvited: Nothing(),
4850 randomPlanet: Nothing(),
49− inviteWallet: Nothing()
51+ inviteWallet: Nothing(),
52+ targetEmail: ''
5053 }
5154
5255 this.findInvited = this.findInvited.bind(this);
5356 this.findRandomPlanet = this.findRandomPlanet.bind(this);
5457 this.generateWallet = this.generateWallet.bind(this);
5558 this.canGenerate = this.canGenerate.bind(this);
59+ this.handleEmailInput = this.handleEmailInput.bind(this);
60+ this.txnConfirmation = this.txnConfirmation.bind(this);
61+ this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
62+
63+ this.promptText = 'The email will be sent on first confirmation. Please wait.';
5664 }
5765
5866 componentDidMount() {
@@ -91,10 +99,11 @@ class InvitesSend extends React.Component {
9199 this.contracts,
92100 this.point
93101 );
94− invited.map(async point => {
102+ invited = invited.map(async point => {
95103 const active = await azimuth.azimuth.isActive(this.contracts, point);
96104 console.log('point active', point, active);
97− return {point: Number(point), active};
105+ const res = {point: Number(point), active:active};
106+ return res;
98107 });
99108 invited = await Promise.all(invited);
100109 this.setState({haveInvited: Just(invited)});
@@ -148,9 +157,13 @@ class InvitesSend extends React.Component {
148157 });
149158 }
150159
160+ handleEmailInput(email) {
161+ //TODO simple .*@.*\..* email validation
162+ this.setState({ targetEmail: email });
163+ }
164+
151165 canGenerate() {
152166 //TODO and canSend()
153− console.log('can generate', this.state.invitesAvailable, this.state.randomPlanet,);
154167 let res = this.state.invitesAvailable.matchWith({
155168 Nothing: () => false,
156169 Just: invites => ((invites.value > 0)
@@ -160,6 +173,24 @@ class InvitesSend extends React.Component {
160173 return res;
161174 }
162175
176+ createUnsignedTxn() {
177+ const txn = azimuth.delegatedSending.sendPoint(
178+ this.contracts,
179+ this.point,
180+ this.state.randomPlanet.value,
181+ this.state.inviteWallet.value.owner
182+ );
183+ return Just(txn)
184+ }
185+
186+ txnConfirmation(txHash, confirmations) {
187+ this.props.setTxnConfirmations(txHash, confirmations);
188+ if (confirmations === 1) {
189+ sendMail(this.state.targetEmail, this.state.inviteWallet.value.ticket)
190+ .then(console.log);
191+ }
192+ }
193+
163194 render() {
164195
165196 const inviteStatus = this.state.invitesAvailable.matchWith({
@@ -180,7 +211,7 @@ class InvitesSend extends React.Component {
180211 Nothing: () => (<li>{'Loading...'}</li>),
181212 Just: (invited) => invited.value.map(i => {
182213 return (<li>
183− <span class="invitee">{ob.patp(i.point)}</span>
214+ <span class="invitee">{ob.patp(i.point)}</span>:
184215 <span class="status">{i.active ? 'accepted' : 'pending'}</span>
185216 </li>);
186217 })
@@ -196,6 +227,14 @@ class InvitesSend extends React.Component {
196227
197228 <ul>{ inviteList }</ul>
198229
230+ <Input
231+ value={ this.state.targetEmail }
232+ onChange={ this.handleEmailInput }>
233+ <InnerLabel>
234+ { 'Recipient email' }
235+ </InnerLabel>
236+ </Input>
237+
199238 <StatelessTransaction
200239 // Upper scope
201240 web3={this.props.web3}
@@ -205,10 +244,11 @@ class InvitesSend extends React.Component {
205244 walletHdPath={this.props.walletHdPath}
206245 networkType={this.props.networkType}
207246 setTxnHashCursor={this.props.setTxnHashCursor}
208− setTxnConfirmations={this.props.setTxnConfirmations}
247+ setTxnConfirmations={this.txnConfirmation}
209248 popRoute={this.props.popRoute}
210249 pushRoute={this.props.pushRoute}
211250 // Other
251+ promptText={this.promptText}
212252 canGenerate={this.canGenerate()}
213253 createUnsignedTxn={this.createUnsignedTxn}
214254 ref={this.statelessRef} />