diff options
author | jloup <jean-loup.jamet@trainline.com> | 2018-02-14 14:19:09 +0100 |
---|---|---|
committer | jloup <jean-loup.jamet@trainline.com> | 2018-02-14 14:19:09 +0100 |
commit | 7a9e5112eaaea58d55f181d3e5296e4ff839921c (patch) | |
tree | 968ed193f42a1fad759cc89ad2f8ad5b0091291e /cmd/web/js | |
download | Front-7a9e5112eaaea58d55f181d3e5296e4ff839921c.tar.gz Front-7a9e5112eaaea58d55f181d3e5296e4ff839921c.tar.zst Front-7a9e5112eaaea58d55f181d3e5296e4ff839921c.zip |
initial commit
Diffstat (limited to 'cmd/web/js')
-rw-r--r-- | cmd/web/js/api.js | 176 | ||||
-rw-r--r-- | cmd/web/js/app.js | 121 | ||||
-rw-r--r-- | cmd/web/js/cookies.js | 65 | ||||
-rw-r--r-- | cmd/web/js/main.jsx | 101 | ||||
-rw-r--r-- | cmd/web/js/otp.jsx | 70 | ||||
-rw-r--r-- | cmd/web/js/poloniex.jsx | 49 | ||||
-rw-r--r-- | cmd/web/js/signin.jsx | 52 | ||||
-rw-r--r-- | cmd/web/js/signup.jsx | 56 |
8 files changed, 690 insertions, 0 deletions
diff --git a/cmd/web/js/api.js b/cmd/web/js/api.js new file mode 100644 index 0000000..e2acd1d --- /dev/null +++ b/cmd/web/js/api.js | |||
@@ -0,0 +1,176 @@ | |||
1 | 'use strict'; | ||
2 | |||
3 | var App = require('./app.js'); | ||
4 | |||
5 | var Api = {}; | ||
6 | |||
7 | Api.API_HOST = process.env.API_HOST; | ||
8 | Api.API_PORT = process.env.API_PORT; | ||
9 | |||
10 | if (process.env.API_HTTPS === 'true') { | ||
11 | Api.API_ROOT = 'https://'; | ||
12 | } else { | ||
13 | Api.API_ROOT = 'http://'; | ||
14 | } | ||
15 | |||
16 | Api.API_ROOT += Api.API_HOST; | ||
17 | if (Api.API_PORT !== '80') { | ||
18 | Api.API_ROOT += ':' + Api.API_PORT; | ||
19 | } | ||
20 | |||
21 | Api.API_ROOT += '/api'; | ||
22 | |||
23 | var ApiEndpoints = { | ||
24 | 'SIGNUP': { | ||
25 | 'type': 'POST', | ||
26 | 'auth': false, | ||
27 | 'parameters': [ | ||
28 | {'name': 'email', 'mandatory': true, 'inquery': true}, | ||
29 | {'name': 'password', 'mandatory': true, 'inquery': true} | ||
30 | ], | ||
31 | 'buildUrl': function(params) { | ||
32 | return '/signup'; | ||
33 | } | ||
34 | }, | ||
35 | 'SIGNIN': { | ||
36 | 'type': 'POST', | ||
37 | 'auth': false, | ||
38 | 'parameters': [ | ||
39 | {'name': 'email', 'mandatory': true, 'inquery': true}, | ||
40 | {'name': 'password', 'mandatory': true, 'inquery': true} | ||
41 | ], | ||
42 | 'buildUrl': function(params) { | ||
43 | return '/signin'; | ||
44 | } | ||
45 | }, | ||
46 | 'MARKET': { | ||
47 | 'type': 'GET', | ||
48 | 'auth': true, | ||
49 | 'parameters': [ | ||
50 | {'name': 'name', 'mandatory': true, 'inquery': false}, | ||
51 | ], | ||
52 | 'buildUrl': function(params) { | ||
53 | return '/market/' + params.name; | ||
54 | } | ||
55 | }, | ||
56 | 'UPDATE_MARKET': { | ||
57 | 'type': 'POST', | ||
58 | 'auth': true, | ||
59 | 'parameters': [ | ||
60 | {'name': 'name', 'mandatory': true, 'inquery': false}, | ||
61 | {'name': 'key', 'mandatory': true, 'inquery': true}, | ||
62 | {'name': 'secret', 'mandatory': true, 'inquery': true}, | ||
63 | ], | ||
64 | 'buildUrl': function(params) { | ||
65 | return '/market/' + params.name + '/update'; | ||
66 | } | ||
67 | }, | ||
68 | 'OTP_ENROLL': { | ||
69 | 'type': 'GET', | ||
70 | 'auth': true, | ||
71 | 'parameters': [], | ||
72 | 'buildUrl': function(params) { | ||
73 | return '/otp/enroll'; | ||
74 | } | ||
75 | }, | ||
76 | 'OTP_VALIDATE': { | ||
77 | 'type': 'POST', | ||
78 | 'auth': true, | ||
79 | 'parameters': [ | ||
80 | {'name': 'pass', 'mandatory': true, 'inquery': true}, | ||
81 | ], | ||
82 | 'buildUrl': function(params) { | ||
83 | return '/otp/validate'; | ||
84 | } | ||
85 | }, | ||
86 | }; | ||
87 | |||
88 | Api.BuildRequest = function(endpointId, params) { | ||
89 | var endpoint = ApiEndpoints[endpointId]; | ||
90 | var query = {}; | ||
91 | var url = ''; | ||
92 | var headers = {}; | ||
93 | var jwt = App.getUserToken(); | ||
94 | |||
95 | if (endpoint === undefined) { | ||
96 | return {'err': 'cannot find endpoint ' + endpointId}; | ||
97 | } | ||
98 | |||
99 | if (endpoint.auth === true && (jwt === undefined || jwt === null)) { | ||
100 | return {'err': 'this endpoint needs auth'}; | ||
101 | } | ||
102 | |||
103 | if (jwt !== undefined && jwt !== null) { | ||
104 | headers.Authorization = 'Bearer ' + jwt; | ||
105 | } | ||
106 | |||
107 | for (var i = 0; i < endpoint.parameters.length; i++) { | ||
108 | var parameter = endpoint.parameters[i]; | ||
109 | if (parameter.mandatory === true && params[parameter.name] === undefined) { | ||
110 | return {'err': 'parameter \'' + parameter.name + '\' is mandatory'}; | ||
111 | } | ||
112 | |||
113 | if (parameter.inquery === true) { | ||
114 | query[parameter.name] = params[parameter.name]; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | url = endpoint.buildUrl(params); | ||
119 | |||
120 | return {'err': null, 'url': Api.API_ROOT + url, 'headers': headers, 'params': query, 'type': endpoint.type}; | ||
121 | }; | ||
122 | |||
123 | Api.Call = function(endpointId, params, fn) { | ||
124 | var request = Api.BuildRequest(endpointId, params); | ||
125 | |||
126 | if (request.err !== null) { | ||
127 | console.error('Api BuildRequest error', request.err); | ||
128 | fn({'err': request.err}, -1, {}); | ||
129 | return null; | ||
130 | } | ||
131 | |||
132 | return Api.DoRequest(request.type, request.url, request.params, request.headers, fn); | ||
133 | }; | ||
134 | |||
135 | Api.DoRequest = function(type, url, params, headers, callback) { | ||
136 | return $.ajax({ | ||
137 | data: params, | ||
138 | headers: headers, | ||
139 | timeout: 30000, | ||
140 | dataType: 'json', | ||
141 | error: function(xhr, status, err) { | ||
142 | if (status === 'abort') { | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | var apiStatus = null; | ||
147 | var apiResponse = null; | ||
148 | var apiCode = null; | ||
149 | if (xhr.responseJSON) { | ||
150 | apiStatus = xhr.responseJSON.status; | ||
151 | apiResponse = xhr.responseJSON.response; | ||
152 | apiCode = xhr.responseJSON.code; | ||
153 | } | ||
154 | |||
155 | if (xhr.status === 401 || xhr.status === 403) { | ||
156 | if (App.onUserNotAuthorized(xhr.status, apiCode) === false) { | ||
157 | return; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | callback({'url': url, 'err': err, 'status': status, 'code': apiCode, 'xhr': xhr}, apiStatus, apiResponse); | ||
162 | }, | ||
163 | success: function(data) { | ||
164 | var err = null; | ||
165 | if (data.status !== 'ok') { | ||
166 | err = {'url': url, 'status': status}; | ||
167 | } | ||
168 | callback(err, data.status, data.response); | ||
169 | }, | ||
170 | type: type, | ||
171 | url: url | ||
172 | }); | ||
173 | }; | ||
174 | |||
175 | module.exports.Api = Api; | ||
176 | |||
diff --git a/cmd/web/js/app.js b/cmd/web/js/app.js new file mode 100644 index 0000000..4946dcc --- /dev/null +++ b/cmd/web/js/app.js | |||
@@ -0,0 +1,121 @@ | |||
1 | 'use strict'; | ||
2 | |||
3 | var cookies = require('./cookies.js'); | ||
4 | var page = require('page'); | ||
5 | |||
6 | var App = {}; | ||
7 | var cookieExpire = 60 * 30; | ||
8 | |||
9 | App.errorCodeToMessage = function(code) { | ||
10 | switch (code) { | ||
11 | case 'invalid_email': | ||
12 | return 'The email is not valid'; | ||
13 | case 'invalid_password': | ||
14 | return 'The password is not valid'; | ||
15 | case 'email_exists': | ||
16 | return 'This email is already registered'; | ||
17 | case 'invalid_credentials': | ||
18 | return 'Invalid credentials'; | ||
19 | case 'invalid_otp': | ||
20 | return 'Invalid code !'; | ||
21 | case 'user_not_confirmed': | ||
22 | return 'Your account is being confirmed. Should be very soon !'; | ||
23 | } | ||
24 | |||
25 | return code; | ||
26 | }; | ||
27 | |||
28 | App.isUserSignedIn = function() { | ||
29 | return cookies.hasItem('jwt'); | ||
30 | }; | ||
31 | |||
32 | App.getUserToken = function() { | ||
33 | return cookies.getItem('jwt'); | ||
34 | }; | ||
35 | |||
36 | App.onUserSignIn = function(token) { | ||
37 | if (!token || token === '') { | ||
38 | page('/signin'); | ||
39 | return; | ||
40 | } | ||
41 | |||
42 | cookies.setItem('jwt', token, cookieExpire); | ||
43 | page('/me'); | ||
44 | }; | ||
45 | |||
46 | App.onUserValidateOtp = function(token) { | ||
47 | if (!token || token === '') { | ||
48 | page('/signin'); | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | cookies.setItem('jwt', token, cookieExpire); | ||
53 | page('/me'); | ||
54 | }; | ||
55 | |||
56 | App.onUserSignUp = function(token) { | ||
57 | if (!token || token === '') { | ||
58 | page('/signin'); | ||
59 | return; | ||
60 | } | ||
61 | |||
62 | cookies.setItem('jwt', token, cookieExpire); | ||
63 | }; | ||
64 | |||
65 | App.getUserJWT = function() { | ||
66 | return cookies.getItem('jwt'); | ||
67 | }; | ||
68 | |||
69 | App.page = function(path, needsAuth, fn) { | ||
70 | page(path, function(context) { | ||
71 | if (needsAuth && !App.isUserSignedIn()) { | ||
72 | page('/signin'); | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | fn(context); | ||
77 | }); | ||
78 | }; | ||
79 | |||
80 | App.go = function(path) { | ||
81 | page(path); | ||
82 | }; | ||
83 | |||
84 | App.start = function() { | ||
85 | page(); | ||
86 | }; | ||
87 | |||
88 | App.onInternNavigation = function(href, e) { | ||
89 | e.preventDefault(); | ||
90 | page(href); | ||
91 | }; | ||
92 | |||
93 | App.onUserNotAuthorized = function(httpCode, apiCode) { | ||
94 | switch (apiCode) { | ||
95 | case 'not_authorized': | ||
96 | cookies.removeItem('jwt'); | ||
97 | page('/signin'); | ||
98 | return false; | ||
99 | case 'otp_not_setup': | ||
100 | page('/otp/setup'); | ||
101 | return false; | ||
102 | case 'need_otp_validation': | ||
103 | page('/otp/validate'); | ||
104 | return false; | ||
105 | default: | ||
106 | return true; | ||
107 | } | ||
108 | }; | ||
109 | |||
110 | App.mount = function(app) { | ||
111 | var root = React.createElement( | ||
112 | 'div', | ||
113 | {className: 'container'}, | ||
114 | app | ||
115 | ); | ||
116 | |||
117 | ReactDOM.unmountComponentAtNode(document.getElementById('app')); | ||
118 | ReactDOM.render(root, document.getElementById('app')); | ||
119 | }; | ||
120 | |||
121 | module.exports = App; | ||
diff --git a/cmd/web/js/cookies.js b/cmd/web/js/cookies.js new file mode 100644 index 0000000..9cc7ca9 --- /dev/null +++ b/cmd/web/js/cookies.js | |||
@@ -0,0 +1,65 @@ | |||
1 | 'use strict'; | ||
2 | |||
3 | /*\ | ||
4 | |*| | ||
5 | |*| :: cookies.js :: | ||
6 | |*| | ||
7 | |*| A complete cookies reader/writer framework with full unicode support. | ||
8 | |*| | ||
9 | |*| Revision #1 - September 4, 2014 | ||
10 | |*| | ||
11 | |*| https://developer.mozilla.org/en-US/docs/Web/API/document.cookie | ||
12 | |*| https://developer.mozilla.org/User:fusionchess | ||
13 | |*| | ||
14 | |*| This framework is released under the GNU Public License, version 3 or later. | ||
15 | |*| http://www.gnu.org/licenses/gpl-3.0-standalone.html | ||
16 | |*| | ||
17 | |*| Syntaxes: | ||
18 | |*| | ||
19 | |*| * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]]) | ||
20 | |*| * docCookies.getItem(name) | ||
21 | |*| * docCookies.removeItem(name[, path[, domain]]) | ||
22 | |*| * docCookies.hasItem(name) | ||
23 | |*| * docCookies.keys() | ||
24 | |*| | ||
25 | \*/ | ||
26 | |||
27 | module.exports = { | ||
28 | getItem: function(sKey) { | ||
29 | if (!sKey) { return null; } | ||
30 | return decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; | ||
31 | }, | ||
32 | setItem: function(sKey, sValue, vEnd, sPath, sDomain, bSecure) { | ||
33 | if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; } | ||
34 | var sExpires = ''; | ||
35 | if (vEnd) { | ||
36 | switch (vEnd.constructor) { | ||
37 | case Number: | ||
38 | sExpires = vEnd === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + vEnd; | ||
39 | break; | ||
40 | case String: | ||
41 | sExpires = '; expires=' + vEnd; | ||
42 | break; | ||
43 | case Date: | ||
44 | sExpires = '; expires=' + vEnd.toUTCString(); | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | document.cookie = encodeURIComponent(sKey) + '=' + encodeURIComponent(sValue) + sExpires + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : ''); | ||
49 | return true; | ||
50 | }, | ||
51 | removeItem: function(sKey, sPath, sDomain) { | ||
52 | if (!this.hasItem(sKey)) { return false; } | ||
53 | document.cookie = encodeURIComponent(sKey) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : ''); | ||
54 | return true; | ||
55 | }, | ||
56 | hasItem: function(sKey) { | ||
57 | if (!sKey) { return false; } | ||
58 | return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(document.cookie); | ||
59 | }, | ||
60 | keys: function() { | ||
61 | var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '').split(/\s*(?:\=[^;]*)?;\s*/); | ||
62 | for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); } | ||
63 | return aKeys; | ||
64 | } | ||
65 | }; | ||
diff --git a/cmd/web/js/main.jsx b/cmd/web/js/main.jsx new file mode 100644 index 0000000..eb53057 --- /dev/null +++ b/cmd/web/js/main.jsx | |||
@@ -0,0 +1,101 @@ | |||
1 | var SignupForm = require('./signup.js').SignupForm; | ||
2 | var SigninForm = require('./signin.js').SigninForm; | ||
3 | var OtpEnrollForm = require('./otp.js').OtpEnrollForm; | ||
4 | var PoloniexForm = require('./poloniex.js').PoloniexForm; | ||
5 | var App = require('./app.js'); | ||
6 | var Api = require('./api.js').Api; | ||
7 | var cookies = require('./cookies.js'); | ||
8 | |||
9 | var Logo = React.createClass({ | ||
10 | render: function() { | ||
11 | return (<div id='logo'> | ||
12 | <a href='/'>Cryptoportfolio</a> | ||
13 | </div>); | ||
14 | } | ||
15 | }); | ||
16 | |||
17 | App.page('/signup', false, function(context) { | ||
18 | if (App.isUserSignedIn()) { | ||
19 | App.go('/me'); | ||
20 | return; | ||
21 | } | ||
22 | |||
23 | App.mount( | ||
24 | <div> | ||
25 | <Logo /> | ||
26 | <SignupForm onSuccess={App.onUserSignUp}/> | ||
27 | </div> | ||
28 | ); | ||
29 | }); | ||
30 | |||
31 | App.page('/signin', false, function(context) { | ||
32 | if (App.isUserSignedIn()) { | ||
33 | App.go('/me'); | ||
34 | return; | ||
35 | } | ||
36 | |||
37 | App.mount( | ||
38 | <div> | ||
39 | <Logo /> | ||
40 | <SigninForm onSuccess={App.onUserSignIn}/> | ||
41 | </div> | ||
42 | ); | ||
43 | }); | ||
44 | |||
45 | App.page('/signout', true, function(context) { | ||
46 | cookies.removeItem('jwt'); | ||
47 | |||
48 | App.go('/'); | ||
49 | }); | ||
50 | |||
51 | App.page('/me', true, function(context) { | ||
52 | Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { | ||
53 | if (err) { | ||
54 | console.error(err, data); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | App.mount( | ||
59 | <div> | ||
60 | <Logo /> | ||
61 | <p>Poloniex</p> | ||
62 | <PoloniexForm apiKey={data.key} apiSecret={data.secret}/> | ||
63 | </div> | ||
64 | ); | ||
65 | |||
66 | }.bind(this)); | ||
67 | }); | ||
68 | |||
69 | App.page('/otp/setup', true, function(context) { | ||
70 | Api.Call('OTP_ENROLL', {}, function(err, status, data) { | ||
71 | if (err) { | ||
72 | console.error(err, data); | ||
73 | return; | ||
74 | } | ||
75 | |||
76 | App.mount( | ||
77 | <div> | ||
78 | <Logo /> | ||
79 | <OtpEnrollForm onSuccess={App.onUserValidateOtp} img={'data:image/png;base64,' + data.base64img} secret={data.secret}/> | ||
80 | </div> | ||
81 | ); | ||
82 | |||
83 | }.bind(this)); | ||
84 | }); | ||
85 | |||
86 | App.page('/otp/validate', true, function(context) { | ||
87 | App.mount( | ||
88 | <div> | ||
89 | <Logo /> | ||
90 | <OtpEnrollForm onSuccess={App.onUserValidateOtp} /> | ||
91 | </div> | ||
92 | ); | ||
93 | }); | ||
94 | |||
95 | App.page('/', false, function(context) { | ||
96 | App.go('/me'); | ||
97 | }); | ||
98 | |||
99 | $(document).ready(function() { | ||
100 | App.start(); | ||
101 | }); | ||
diff --git a/cmd/web/js/otp.jsx b/cmd/web/js/otp.jsx new file mode 100644 index 0000000..2717d9f --- /dev/null +++ b/cmd/web/js/otp.jsx | |||
@@ -0,0 +1,70 @@ | |||
1 | var Api = require('./api.js').Api; | ||
2 | var App = require('./app.js'); | ||
3 | var classNames = require('classnames'); | ||
4 | |||
5 | var OtpQrCode = React.createClass({ | ||
6 | render: function() { | ||
7 | return ( | ||
8 | <div> | ||
9 | <img src={this.props.img} /> | ||
10 | <p>{this.props.secret}</p> | ||
11 | </div> | ||
12 | ); | ||
13 | } | ||
14 | }); | ||
15 | |||
16 | module.exports.OtpEnrollForm = React.createClass({ | ||
17 | getInitialState: function() { | ||
18 | return {'hideMsg': true, 'msg': '', 'msgOk': false, 'pass': ''}; | ||
19 | }, | ||
20 | handleSubmit: function(e) { | ||
21 | Api.Call('OTP_VALIDATE', {'pass': this.state.pass}, function(err, status, data) { | ||
22 | if (err) { | ||
23 | console.error(err, data); | ||
24 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
25 | return; | ||
26 | } | ||
27 | |||
28 | this.displayMessage('OK', true); | ||
29 | this.props.onSuccess(data.token); | ||
30 | |||
31 | }.bind(this)); | ||
32 | |||
33 | e.preventDefault(); | ||
34 | }, | ||
35 | handlePassChange: function(event) { | ||
36 | this.setState({'pass': event.target.value}); | ||
37 | }, | ||
38 | hideMessage: function() { | ||
39 | this.setState({'hideMsg': true}); | ||
40 | }, | ||
41 | displayMessage: function(msg, ok) { | ||
42 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
43 | }, | ||
44 | render: function() { | ||
45 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
46 | var qrCode = null; | ||
47 | |||
48 | if (this.props.img) { | ||
49 | qrCode = ( | ||
50 | <div className='row justify-content-center'> | ||
51 | <OtpQrCode img={this.props.img} secret={this.props.secret} /> | ||
52 | </div> | ||
53 | ); | ||
54 | } | ||
55 | return ( | ||
56 | <div className='row otp-enroll justify-content-center'> | ||
57 | <div className='col-lg-offset-4 col-lg-4 col-md-offset-4 col-md-4 col-sm-offset-4 col-sm-4 col-xs-offset-1 col-xs-10'> | ||
58 | {qrCode} | ||
59 | <div className='row justify-content-center'> | ||
60 | <form role='form' onSubmit={this.handleSubmit}> | ||
61 | <input className='form-control' type='pass' placeholder='pass' onChange={this.handlePassChange} /> | ||
62 | <input className='form-control submit' type='submit' value='Validate' /> | ||
63 | <div className={cName} ref='message'>{this.state.msg}</div> | ||
64 | </form> | ||
65 | </div> | ||
66 | </div> | ||
67 | </div> | ||
68 | ); | ||
69 | } | ||
70 | }); | ||
diff --git a/cmd/web/js/poloniex.jsx b/cmd/web/js/poloniex.jsx new file mode 100644 index 0000000..877198d --- /dev/null +++ b/cmd/web/js/poloniex.jsx | |||
@@ -0,0 +1,49 @@ | |||
1 | var Api = require('./api.js').Api; | ||
2 | var App = require('./app.js'); | ||
3 | var classNames = require('classnames'); | ||
4 | |||
5 | module.exports.PoloniexForm = React.createClass({ | ||
6 | getInitialState: function() { | ||
7 | return {'hideMsg': true, 'msg': '', 'msgOk': false, 'apiSecret': this.props.apiSecret, 'apiKey': this.props.apiKey}; | ||
8 | }, | ||
9 | handleSubmit: function(e) { | ||
10 | Api.Call('UPDATE_MARKET', {'key': this.state.apiKey, 'secret': this.state.apiSecret, 'name': 'poloniex'}, function(err, status, data) { | ||
11 | if (err) { | ||
12 | console.error(err, data); | ||
13 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | this.displayMessage('OK', true); | ||
18 | |||
19 | }.bind(this)); | ||
20 | e.preventDefault(); | ||
21 | }, | ||
22 | handleApiKeyChange: function(event) { | ||
23 | this.setState({'apiKey': event.target.value}); | ||
24 | }, | ||
25 | handleApiSecretChange: function(event) { | ||
26 | this.setState({'apiSecret': event.target.value}); | ||
27 | }, | ||
28 | hideMessage: function() { | ||
29 | this.setState({'hideMsg': true}); | ||
30 | }, | ||
31 | displayMessage: function(msg, ok) { | ||
32 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
33 | }, | ||
34 | render: function() { | ||
35 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
36 | return ( | ||
37 | <div className='row justify-content-center api-credentials-form'> | ||
38 | <div className='col-lg-offset-4 col-lg-4 col-md-offset-4 col-md-4 col-sm-offset-4 col-sm-4 col-xs-offset-1 col-xs-10'> | ||
39 | <form role='form' onSubmit={this.handleSubmit}> | ||
40 | <input className='form-control' type='text' placeholder='apiKey' value={this.state.apiKey} onChange={this.handleApiKeyChange} /> | ||
41 | <input className='form-control' type='text' placeholder='apiSecret' value={this.state.apiSecret} onChange={this.handleApiSecretChange} /> | ||
42 | <input className='form-control submit' type='submit' value='Save' /> | ||
43 | <div className={cName} ref='message'>{this.state.msg}</div> | ||
44 | </form> | ||
45 | </div> | ||
46 | </div> | ||
47 | ); | ||
48 | } | ||
49 | }); | ||
diff --git a/cmd/web/js/signin.jsx b/cmd/web/js/signin.jsx new file mode 100644 index 0000000..443a461 --- /dev/null +++ b/cmd/web/js/signin.jsx | |||
@@ -0,0 +1,52 @@ | |||
1 | var Api = require('./api.js').Api; | ||
2 | var App = require('./app.js'); | ||
3 | var classNames = require('classnames'); | ||
4 | |||
5 | module.exports.SigninForm = React.createClass({ | ||
6 | getInitialState: function() { | ||
7 | return {'hideMsg': true, 'msg': '', 'msgOk': false, 'password': '', 'email': ''}; | ||
8 | }, | ||
9 | handleSubmit: function(e) { | ||
10 | Api.Call('SIGNIN', {'password': this.state.password, 'email': this.state.email}, function(err, status, data) { | ||
11 | if (err) { | ||
12 | console.error(err, data); | ||
13 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
14 | return; | ||
15 | } | ||
16 | |||
17 | this.displayMessage('OK', true); | ||
18 | this.props.onSuccess(data.token); | ||
19 | |||
20 | }.bind(this)); | ||
21 | e.preventDefault(); | ||
22 | }, | ||
23 | handlePasswordChange: function(event) { | ||
24 | this.setState({'password': event.target.value}); | ||
25 | }, | ||
26 | handleEmailChange: function(event) { | ||
27 | this.setState({'email': event.target.value}); | ||
28 | }, | ||
29 | hideMessage: function() { | ||
30 | this.setState({'hideMsg': true}); | ||
31 | }, | ||
32 | displayMessage: function(msg, ok) { | ||
33 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
34 | }, | ||
35 | render: function() { | ||
36 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
37 | return ( | ||
38 | <div className='row justify-content-center sign-in'> | ||
39 | <div className='col-lg-offset-4 col-lg-4 col-md-offset-4 col-md-4 col-sm-offset-4 col-sm-4 col-xs-offset-1 col-xs-10'> | ||
40 | <form role='form' onSubmit={this.handleSubmit}> | ||
41 | <input className='form-control' type='email' placeholder='email' onChange={this.handleEmailChange} /> | ||
42 | <input className='form-control' type='password' placeholder='password' onChange={this.handlePasswordChange} /> | ||
43 | <input className='form-control submit' type='submit' value='Sign In' /> | ||
44 | <div className={cName} ref='message'>{this.state.msg}</div> | ||
45 | </form> | ||
46 | <a href='#' onClick={App.onInternNavigation.bind(this, '/signup')}><u>Sign up</u></a> | ||
47 | </div> | ||
48 | </div> | ||
49 | ); | ||
50 | } | ||
51 | }); | ||
52 | |||
diff --git a/cmd/web/js/signup.jsx b/cmd/web/js/signup.jsx new file mode 100644 index 0000000..149125a --- /dev/null +++ b/cmd/web/js/signup.jsx | |||
@@ -0,0 +1,56 @@ | |||
1 | var Api = require('./api.js').Api; | ||
2 | var App = require('./app.js'); | ||
3 | var classNames = require('classnames'); | ||
4 | |||
5 | module.exports.SignupForm = React.createClass({ | ||
6 | getInitialState: function() { | ||
7 | return {'hideMsg': true, 'msg': '', 'msgOk': false, 'password': '', 'email': ''}; | ||
8 | }, | ||
9 | handleSubmit: function(e) { | ||
10 | Api.Call('SIGNUP', | ||
11 | { | ||
12 | 'password': this.state.password, | ||
13 | 'email': this.state.email | ||
14 | }, | ||
15 | function(err, status, data) { | ||
16 | if (err) { | ||
17 | console.error(err, data); | ||
18 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
19 | return; | ||
20 | } | ||
21 | |||
22 | this.displayMessage('Thank You. Your account is being confirmed. Check your mailbox soon', true); | ||
23 | this.props.onSuccess(data.token); | ||
24 | |||
25 | }.bind(this)); | ||
26 | e.preventDefault(); | ||
27 | }, | ||
28 | handlePasswordChange: function(event) { | ||
29 | this.setState({'password': event.target.value}); | ||
30 | }, | ||
31 | handleEmailChange: function(event) { | ||
32 | this.setState({'email': event.target.value}); | ||
33 | }, | ||
34 | hideMessage: function() { | ||
35 | this.setState({'hideMsg': true}); | ||
36 | }, | ||
37 | displayMessage: function(msg, ok) { | ||
38 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
39 | }, | ||
40 | render: function() { | ||
41 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
42 | return ( | ||
43 | <div className='row justify-content-center sign-in'> | ||
44 | <div className='col-lg-offset-4 col-lg-4 col-md-offset-4 col-md-4 col-sm-offset-4 col-sm-4 col-xs-offset-1 col-xs-10'> | ||
45 | <form role='form' onSubmit={this.handleSubmit}> | ||
46 | <input className='form-control' type='email' placeholder='email' onChange={this.handleEmailChange} /> | ||
47 | <input className='form-control' type='password' placeholder='password' onChange={this.handlePasswordChange} /> | ||
48 | <input className='form-control submit' type='submit' value='Sign Up' /> | ||
49 | <div className={cName} ref='message'>{this.state.msg}</div> | ||
50 | <a href='#' onClick={App.onInternNavigation.bind(this, '/signin')}><u>Sign In</u></a> | ||
51 | </form> | ||
52 | </div> | ||
53 | </div> | ||
54 | ); | ||
55 | } | ||
56 | }); | ||