From 16e43cc77935a979c48e75f1ec8ed792952a4ae8 Mon Sep 17 00:00:00 2001 From: jloup Date: Mon, 7 May 2018 17:39:58 +0200 Subject: Account page. --- api/market_config.go | 10 ++- cmd/app/main.go | 1 + cmd/web/Makefile | 2 +- cmd/web/js/account.jsx | 177 +++++++++++++++++++++++++++++++++++++++++++ cmd/web/js/header_footer.jsx | 14 +++- cmd/web/js/main.jsx | 7 ++ cmd/web/js/poloniex.jsx | 110 ++------------------------- cmd/web/static/style.css | 20 +++++ 8 files changed, 234 insertions(+), 107 deletions(-) create mode 100644 cmd/web/js/account.jsx diff --git a/api/market_config.go b/api/market_config.go index 25e390d..c2248b3 100644 --- a/api/market_config.go +++ b/api/market_config.go @@ -45,6 +45,14 @@ func (q MarketConfigQuery) Run() (interface{}, *Error) { } + if _, ok := config.Config["key"]; !ok { + config.Config["key"] = "" + } + + if _, ok := config.Config["secret"]; !ok { + config.Config["secret"] = "" + } + return config.Config, nil } @@ -76,7 +84,7 @@ func (q MarketBalanceQuery) Run() (interface{}, *Error) { } if config.Config["key"] == "" || config.Config["secret"] == "" { - return nil, &Error{BadRequest, "your credentials for this market are not setup", fmt.Errorf("'%v' credentials are not setup", q.In.Market)} + return nil, &Error{InvalidMarketCredentials, "your credentials for this market are not setup", fmt.Errorf("'%v' credentials are not setup", q.In.Market)} } result := struct { diff --git a/cmd/app/main.go b/cmd/app/main.go index a0463d2..28eb775 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -143,6 +143,7 @@ func main() { "/change-password", "/signout", "/me", + "/account", "/otp/enroll", "/otp/validate", "/not_confirmed", diff --git a/cmd/web/Makefile b/cmd/web/Makefile index 02ff826..3b100d1 100644 --- a/cmd/web/Makefile +++ b/cmd/web/Makefile @@ -4,7 +4,7 @@ export PATH := $(PATH):./node_modules/.bin SRC_DIR=js BUILD_DIR=build/js -JSX_SRC= header_footer.jsx main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx password_reset.jsx change_password.jsx +JSX_SRC= header_footer.jsx main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx password_reset.jsx change_password.jsx account.jsx JS_SRC= cookies.js app.js api.js STATIC_FILES= index.html style.css fontello.css STATIC_FILES+=$(addprefix fonts/, fontello.eot fontello.svg fontello.ttf fontello.woff fontello.woff2) diff --git a/cmd/web/js/account.jsx b/cmd/web/js/account.jsx new file mode 100644 index 0000000..43e7083 --- /dev/null +++ b/cmd/web/js/account.jsx @@ -0,0 +1,177 @@ +import Api from './api.js'; +import React from 'react'; + +class PoloniexConfiguration extends React.Component { + constructor(props) { + super(props); + this.state = {'apiKey': '', 'apiSecret': '', 'apiRequested': false, 'status': 'loading'}; + } + + checkCredentials = () => { + Api.Call('MARKET_BALANCE', {'name': 'poloniex', 'currency': 'BTC'}, function(err, status, data) { + if (err) { + console.error(err, data); + if (err.code === 'invalid_market_credentials') { + this.setState({'status': 'invalidCredentials'}); + } else if (err.code === 'ip_restricted_api_key') { + this.setState({'status': 'ipRestricted'}); + } + return; + } + + this.setState({'status': 'ok'}); + }.bind(this)); + } + + handleCredentialsChange = (key, secret) => { + this.setState({'apiKey': key, 'apiSecret': secret}); + } + + handleCredentialsSubmit = () => { + + /* + *If (!this.state.apiKey || !this.state.apiSecret) { + * return; + *} + */ + + Api.Call('UPDATE_MARKET', {'key': this.state.apiKey, 'secret': this.state.apiSecret, 'name': 'poloniex'}, function(err, status, data) { + if (err) { + console.error(err, data); + return; + } + + this.setState({'status': 'loading'}); + this.checkCredentials(); + }.bind(this)); + } + + componentDidMount = () => { + Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { + this.setState({'apiRequested': true}); + if (err) { + console.error(err, data); + return; + } + + var newStatus = this.state.status; + if (!data.key || !data.secret) { + newStatus = 'emptyCredentials'; + } else { + this.checkCredentials(); + } + + this.setState({'apiKey': data.key, 'apiSecret': data.secret, 'status': newStatus}); + }.bind(this)); + } + + render = () => { + var displayText = null; + switch (this.state.status) { + case 'loading': + displayText = 'Checking Poloniex credentials...'; + break; + case 'invalidCredentials': + displayText = 'Invalid poloniex credentials'; + break; + case 'ipRestricted': + displayText = 'Your API key is IP restricted.'; + break; + case 'emptyCredentials': + displayText = 'Please provide poloniex credentials'; + break; + case 'ok': + displayText = 'You are all set !'; + break; + default: + console.error('unknown status', this.state.status); + displayText = null; + } + if (this.state.apiRequested === false) { + return
; + } + return ( +
+ +
+ ); + } +} + +class PoloniexCredentialsForm extends React.Component { + constructor(props) { + super(props); + this.state = {'editMode': false}; + } + + handleSubmit = (e) => { + this.props.onCredentialsSubmit(); + this.setState({'editMode': false}); + e.preventDefault(); + } + + handleApiKeyChange = (event) => { + this.props.onCredentialsChange(event.target.value, this.props.apiSecret); + } + + handleApiSecretChange = (event) => { + this.props.onCredentialsChange(this.props.apiKey, event.target.value); + } + + onEditClick = () => { + this.setState({'editMode': true}); + } + + render = () => { + var submitType = this.state.editMode === true ? 'submit' : 'hidden'; + var buttonDisplay = this.state.editMode === true ? 'none' : 'inline'; + var secretDisplayed = this.state.editMode === true ? this.props.apiSecret : 'XXXXXXX'; + var keyDisplayed = this.state.editMode === true ? this.props.apiKey : 'XXXXXXX'; + + var iconName = 'icon-cancel-circled'; + switch (this.props.status) { + case 'loading': + iconName = 'icon-hourglass-2'; + break; + case 'ok': + iconName = 'icon-ok-circled'; + break; + } + + return ( +
+
+ Poloniex credentials +
+
+
+ {this.props.statusMessage} +
+
+
+
+
+ + + + +
+
+
+
+
+ ); + } +} + +export default PoloniexConfiguration; diff --git a/cmd/web/js/header_footer.jsx b/cmd/web/js/header_footer.jsx index 3cb9937..f11ed06 100644 --- a/cmd/web/js/header_footer.jsx +++ b/cmd/web/js/header_footer.jsx @@ -6,6 +6,12 @@ class Signout extends React.Component { } } +class MyAccount extends React.Component { + render = () => { + return Account; + } +} + class Logo extends React.Component { render() { return ; }); return ; -} else { + } else { dashboard =
{this.props.displayText}
; -} + } return (
@@ -164,55 +121,4 @@ class PoloniexBalance extends React.Component { } } -class PoloniexCredentialsForm extends React.Component { - constructor(props) { - super(props); - this.state = {'hideMsg': true, 'msg': '', 'editMode': false, 'msgOk': false}; - } - - handleSubmit = (e) => { - this.props.onCredentialsSubmit(); - this.setState({'editMode': false}); - e.preventDefault(); - } - - handleApiKeyChange = (event) => { - this.props.onCredentialsChange(event.target.value, this.props.apiSecret); - } - - handleApiSecretChange = (event) => { - this.props.onCredentialsChange(this.props.apiKey, event.target.value); - } - - onEditClick = () => { - this.setState({'editMode': true}); - } - - render = () => { - var submitType = this.state.editMode === true ? 'submit' : 'hidden'; - var buttonDisplay = this.state.editMode === true ? 'none' : 'inline'; - var secretDisplayed = this.state.editMode === true ? this.props.apiSecret : 'XXXXXXX'; - var keyDisplayed = this.state.editMode === true ? this.props.apiKey : 'XXXXXXX'; - - return ( -
-
- Poloniex credentials -
-
- - - - -
-
-
- ); - } -} - export default PoloniexController; diff --git a/cmd/web/static/style.css b/cmd/web/static/style.css index 5e49c55..2212168 100644 --- a/cmd/web/static/style.css +++ b/cmd/web/static/style.css @@ -44,6 +44,10 @@ i.cc { margin-bottom: 30px; } +.header-menu-section { + margin-right: 10px; +} + h1 { font-size: 1.5em; margin-bottom: 5px; @@ -57,6 +61,22 @@ h1 { background-color: white; } +.config-status { + margin-bottom: 10px; + font-size: 0.9em; +} + +.config-status .icon-cancel-circled { + color: red; +} + +.config-status .icon-ok-circled { + color: green; +} +.config-status i { + font-size: 1.2em; +} + .sign-in .submit { background-color: rgb(20, 20, 20); color: white; -- cgit v1.2.3