diff options
-rw-r--r-- | api/market_config.go | 10 | ||||
-rw-r--r-- | cmd/app/main.go | 1 | ||||
-rw-r--r-- | cmd/web/Makefile | 2 | ||||
-rw-r--r-- | cmd/web/js/account.jsx | 177 | ||||
-rw-r--r-- | cmd/web/js/header_footer.jsx | 14 | ||||
-rw-r--r-- | cmd/web/js/main.jsx | 7 | ||||
-rw-r--r-- | cmd/web/js/poloniex.jsx | 110 | ||||
-rw-r--r-- | cmd/web/static/style.css | 20 |
8 files changed, 234 insertions, 107 deletions
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) { | |||
45 | 45 | ||
46 | } | 46 | } |
47 | 47 | ||
48 | if _, ok := config.Config["key"]; !ok { | ||
49 | config.Config["key"] = "" | ||
50 | } | ||
51 | |||
52 | if _, ok := config.Config["secret"]; !ok { | ||
53 | config.Config["secret"] = "" | ||
54 | } | ||
55 | |||
48 | return config.Config, nil | 56 | return config.Config, nil |
49 | } | 57 | } |
50 | 58 | ||
@@ -76,7 +84,7 @@ func (q MarketBalanceQuery) Run() (interface{}, *Error) { | |||
76 | } | 84 | } |
77 | 85 | ||
78 | if config.Config["key"] == "" || config.Config["secret"] == "" { | 86 | if config.Config["key"] == "" || config.Config["secret"] == "" { |
79 | return nil, &Error{BadRequest, "your credentials for this market are not setup", fmt.Errorf("'%v' credentials are not setup", q.In.Market)} | 87 | return nil, &Error{InvalidMarketCredentials, "your credentials for this market are not setup", fmt.Errorf("'%v' credentials are not setup", q.In.Market)} |
80 | } | 88 | } |
81 | 89 | ||
82 | result := struct { | 90 | 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() { | |||
143 | "/change-password", | 143 | "/change-password", |
144 | "/signout", | 144 | "/signout", |
145 | "/me", | 145 | "/me", |
146 | "/account", | ||
146 | "/otp/enroll", | 147 | "/otp/enroll", |
147 | "/otp/validate", | 148 | "/otp/validate", |
148 | "/not_confirmed", | 149 | "/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 | |||
4 | 4 | ||
5 | SRC_DIR=js | 5 | SRC_DIR=js |
6 | BUILD_DIR=build/js | 6 | BUILD_DIR=build/js |
7 | JSX_SRC= header_footer.jsx main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx password_reset.jsx change_password.jsx | 7 | JSX_SRC= header_footer.jsx main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx password_reset.jsx change_password.jsx account.jsx |
8 | JS_SRC= cookies.js app.js api.js | 8 | JS_SRC= cookies.js app.js api.js |
9 | STATIC_FILES= index.html style.css fontello.css | 9 | STATIC_FILES= index.html style.css fontello.css |
10 | STATIC_FILES+=$(addprefix fonts/, fontello.eot fontello.svg fontello.ttf fontello.woff fontello.woff2) | 10 | 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 @@ | |||
1 | import Api from './api.js'; | ||
2 | import React from 'react'; | ||
3 | |||
4 | class PoloniexConfiguration extends React.Component { | ||
5 | constructor(props) { | ||
6 | super(props); | ||
7 | this.state = {'apiKey': '', 'apiSecret': '', 'apiRequested': false, 'status': 'loading'}; | ||
8 | } | ||
9 | |||
10 | checkCredentials = () => { | ||
11 | Api.Call('MARKET_BALANCE', {'name': 'poloniex', 'currency': 'BTC'}, function(err, status, data) { | ||
12 | if (err) { | ||
13 | console.error(err, data); | ||
14 | if (err.code === 'invalid_market_credentials') { | ||
15 | this.setState({'status': 'invalidCredentials'}); | ||
16 | } else if (err.code === 'ip_restricted_api_key') { | ||
17 | this.setState({'status': 'ipRestricted'}); | ||
18 | } | ||
19 | return; | ||
20 | } | ||
21 | |||
22 | this.setState({'status': 'ok'}); | ||
23 | }.bind(this)); | ||
24 | } | ||
25 | |||
26 | handleCredentialsChange = (key, secret) => { | ||
27 | this.setState({'apiKey': key, 'apiSecret': secret}); | ||
28 | } | ||
29 | |||
30 | handleCredentialsSubmit = () => { | ||
31 | |||
32 | /* | ||
33 | *If (!this.state.apiKey || !this.state.apiSecret) { | ||
34 | * return; | ||
35 | *} | ||
36 | */ | ||
37 | |||
38 | Api.Call('UPDATE_MARKET', {'key': this.state.apiKey, 'secret': this.state.apiSecret, 'name': 'poloniex'}, function(err, status, data) { | ||
39 | if (err) { | ||
40 | console.error(err, data); | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | this.setState({'status': 'loading'}); | ||
45 | this.checkCredentials(); | ||
46 | }.bind(this)); | ||
47 | } | ||
48 | |||
49 | componentDidMount = () => { | ||
50 | Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { | ||
51 | this.setState({'apiRequested': true}); | ||
52 | if (err) { | ||
53 | console.error(err, data); | ||
54 | return; | ||
55 | } | ||
56 | |||
57 | var newStatus = this.state.status; | ||
58 | if (!data.key || !data.secret) { | ||
59 | newStatus = 'emptyCredentials'; | ||
60 | } else { | ||
61 | this.checkCredentials(); | ||
62 | } | ||
63 | |||
64 | this.setState({'apiKey': data.key, 'apiSecret': data.secret, 'status': newStatus}); | ||
65 | }.bind(this)); | ||
66 | } | ||
67 | |||
68 | render = () => { | ||
69 | var displayText = null; | ||
70 | switch (this.state.status) { | ||
71 | case 'loading': | ||
72 | displayText = 'Checking Poloniex credentials...'; | ||
73 | break; | ||
74 | case 'invalidCredentials': | ||
75 | displayText = 'Invalid poloniex credentials'; | ||
76 | break; | ||
77 | case 'ipRestricted': | ||
78 | displayText = 'Your API key is IP restricted.'; | ||
79 | break; | ||
80 | case 'emptyCredentials': | ||
81 | displayText = 'Please provide poloniex credentials'; | ||
82 | break; | ||
83 | case 'ok': | ||
84 | displayText = 'You are all set !'; | ||
85 | break; | ||
86 | default: | ||
87 | console.error('unknown status', this.state.status); | ||
88 | displayText = null; | ||
89 | } | ||
90 | if (this.state.apiRequested === false) { | ||
91 | return <div></div>; | ||
92 | } | ||
93 | return ( | ||
94 | <div> | ||
95 | <PoloniexCredentialsForm onLoadCredentials={this.onLoadCredentials} | ||
96 | onCredentialsSubmit={this.handleCredentialsSubmit} | ||
97 | onCredentialsChange={this.handleCredentialsChange} | ||
98 | apiSecret={this.state.apiSecret} | ||
99 | apiKey={this.state.apiKey} | ||
100 | status={this.state.status} | ||
101 | statusMessage={displayText}/> | ||
102 | </div> | ||
103 | ); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | class PoloniexCredentialsForm extends React.Component { | ||
108 | constructor(props) { | ||
109 | super(props); | ||
110 | this.state = {'editMode': false}; | ||
111 | } | ||
112 | |||
113 | handleSubmit = (e) => { | ||
114 | this.props.onCredentialsSubmit(); | ||
115 | this.setState({'editMode': false}); | ||
116 | e.preventDefault(); | ||
117 | } | ||
118 | |||
119 | handleApiKeyChange = (event) => { | ||
120 | this.props.onCredentialsChange(event.target.value, this.props.apiSecret); | ||
121 | } | ||
122 | |||
123 | handleApiSecretChange = (event) => { | ||
124 | this.props.onCredentialsChange(this.props.apiKey, event.target.value); | ||
125 | } | ||
126 | |||
127 | onEditClick = () => { | ||
128 | this.setState({'editMode': true}); | ||
129 | } | ||
130 | |||
131 | render = () => { | ||
132 | var submitType = this.state.editMode === true ? 'submit' : 'hidden'; | ||
133 | var buttonDisplay = this.state.editMode === true ? 'none' : 'inline'; | ||
134 | var secretDisplayed = this.state.editMode === true ? this.props.apiSecret : 'XXXXXXX'; | ||
135 | var keyDisplayed = this.state.editMode === true ? this.props.apiKey : 'XXXXXXX'; | ||
136 | |||
137 | var iconName = 'icon-cancel-circled'; | ||
138 | switch (this.props.status) { | ||
139 | case 'loading': | ||
140 | iconName = 'icon-hourglass-2'; | ||
141 | break; | ||
142 | case 'ok': | ||
143 | iconName = 'icon-ok-circled'; | ||
144 | break; | ||
145 | } | ||
146 | |||
147 | return ( | ||
148 | <div className="row api-credentials-form"> | ||
149 | <div className="offset-2 col-8 box"> | ||
150 | <span className="text-center">Poloniex credentials</span> | ||
151 | <hr/> | ||
152 | <div className="row config-status"> | ||
153 | <div className="col-12"> | ||
154 | <span><i className={iconName}></i>{this.props.statusMessage}</span> | ||
155 | </div> | ||
156 | </div> | ||
157 | <div className="row"> | ||
158 | <div className="col-12"> | ||
159 | <form role="form" onSubmit={this.handleSubmit}> | ||
160 | <label className="w-100">Key: | ||
161 | <input className="form-control" type="text" placeholder="key" value={keyDisplayed} onChange={this.handleApiKeyChange} disabled={!this.state.editMode}/> | ||
162 | </label> | ||
163 | <label className="w-100">Secret: | ||
164 | <input className="form-control" type="text" placeholder="secret" value={secretDisplayed} onChange={this.handleApiSecretChange} disabled={!this.state.editMode}/> | ||
165 | </label> | ||
166 | <input className="form-control submit" type={submitType} value="Save" /> | ||
167 | <button className="form-control submit" style={{display: buttonDisplay}} onSubmit={null} onClick={this.onEditClick} type="button">Show/Edit</button> | ||
168 | </form> | ||
169 | </div> | ||
170 | </div> | ||
171 | </div> | ||
172 | </div> | ||
173 | ); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | 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 { | |||
6 | } | 6 | } |
7 | } | 7 | } |
8 | 8 | ||
9 | class MyAccount extends React.Component { | ||
10 | render = () => { | ||
11 | return <a href="/account"><u>Account</u></a>; | ||
12 | } | ||
13 | } | ||
14 | |||
9 | class Logo extends React.Component { | 15 | class Logo extends React.Component { |
10 | render() { | 16 | render() { |
11 | return <div id="logo" className="w-100 h-100 align-self-center"> | 17 | return <div id="logo" className="w-100 h-100 align-self-center"> |
@@ -22,6 +28,7 @@ class Footer extends React.Component { | |||
22 | } | 28 | } |
23 | 29 | ||
24 | if (this.props.isLoggedIn === true) { | 30 | if (this.props.isLoggedIn === true) { |
31 | elements = elements.concat(<MyAccount />); | ||
25 | elements = elements.concat(<Signout />); | 32 | elements = elements.concat(<Signout />); |
26 | } | 33 | } |
27 | 34 | ||
@@ -37,7 +44,7 @@ class Footer extends React.Component { | |||
37 | </div>; | 44 | </div>; |
38 | }); | 45 | }); |
39 | return <div id="footer" className="row"> | 46 | return <div id="footer" className="row"> |
40 | <div className="offset-4 col-4 d-sm-none"> | 47 | <div className="offset-4 col-4 d-md-none"> |
41 | {rows} | 48 | {rows} |
42 | </div> | 49 | </div> |
43 | </div>; | 50 | </div>; |
@@ -52,11 +59,12 @@ class Header extends React.Component { | |||
52 | } | 59 | } |
53 | 60 | ||
54 | if (this.props.isLoggedIn === true) { | 61 | if (this.props.isLoggedIn === true) { |
62 | elements = elements.concat(<MyAccount />); | ||
55 | elements = elements.concat(<Signout />); | 63 | elements = elements.concat(<Signout />); |
56 | } | 64 | } |
57 | 65 | ||
58 | elements = elements.map(function(element, i) { | 66 | elements = elements.map(function(element, i) { |
59 | return <div className="text-center" key={'header-el-' + i}> | 67 | return <div className="text-center header-menu-section" key={'header-el-' + i}> |
60 | {element} | 68 | {element} |
61 | </div>; | 69 | </div>; |
62 | }); | 70 | }); |
@@ -65,7 +73,7 @@ class Header extends React.Component { | |||
65 | <div className="offset-3 col-6 offset-md-4 col-md-4"> | 73 | <div className="offset-3 col-6 offset-md-4 col-md-4"> |
66 | <Logo /> | 74 | <Logo /> |
67 | </div> | 75 | </div> |
68 | <div className="col-3 col-md-4 align-self-center h-100 d-none d-sm-flex justify-content-end"> | 76 | <div className="col-3 col-md-4 align-self-center h-100 d-none d-md-flex justify-content-end"> |
69 | {elements} | 77 | {elements} |
70 | </div> | 78 | </div> |
71 | </div>; | 79 | </div>; |
diff --git a/cmd/web/js/main.jsx b/cmd/web/js/main.jsx index 8a4fce8..84b5848 100644 --- a/cmd/web/js/main.jsx +++ b/cmd/web/js/main.jsx | |||
@@ -4,6 +4,7 @@ import PasswordResetForm from './password_reset.js'; | |||
4 | import ChangePasswordForm from './change_password.js'; | 4 | import ChangePasswordForm from './change_password.js'; |
5 | import OtpEnrollForm from './otp.js'; | 5 | import OtpEnrollForm from './otp.js'; |
6 | import PoloniexController from './poloniex.js'; | 6 | import PoloniexController from './poloniex.js'; |
7 | import PoloniexConfiguration from './account.js'; | ||
7 | import App from './app.js'; | 8 | import App from './app.js'; |
8 | import Api from './api.js'; | 9 | import Api from './api.js'; |
9 | import cookies from './cookies.js'; | 10 | import cookies from './cookies.js'; |
@@ -73,6 +74,12 @@ App.page('/me', true, function(context) { | |||
73 | </div>); | 74 | </div>); |
74 | }); | 75 | }); |
75 | 76 | ||
77 | App.page('/account', true, function(context) { | ||
78 | App.mount(<div> | ||
79 | <PoloniexConfiguration/> | ||
80 | </div>); | ||
81 | }); | ||
82 | |||
76 | App.page('/not_confirmed', true, function(context) { | 83 | App.page('/not_confirmed', true, function(context) { |
77 | App.mount(<div> | 84 | App.mount(<div> |
78 | <div className="row"> | 85 | <div className="row"> |
diff --git a/cmd/web/js/poloniex.jsx b/cmd/web/js/poloniex.jsx index db6b1c4..76b68d8 100644 --- a/cmd/web/js/poloniex.jsx +++ b/cmd/web/js/poloniex.jsx | |||
@@ -4,26 +4,7 @@ import React from 'react'; | |||
4 | class PoloniexController extends React.Component { | 4 | class PoloniexController extends React.Component { |
5 | constructor(props) { | 5 | constructor(props) { |
6 | super(props); | 6 | super(props); |
7 | this.state = {'apiKey': '', 'apiSecret': '', 'apiRequested': false, 'flag': 'loading', 'valueCurrency': null, 'balanceValue': null, 'balance': null}; | 7 | this.state = {'apiRequested': false, 'flag': 'loading', 'valueCurrency': null, 'balanceValue': null, 'balance': null}; |
8 | } | ||
9 | |||
10 | handleCredentialsChange = (key, secret) => { | ||
11 | this.setState({'apiKey': key, 'apiSecret': secret}); | ||
12 | } | ||
13 | |||
14 | handleCredentialsSubmit = () => { | ||
15 | if (!this.state.apiKey || !this.state.apiSecret) { | ||
16 | return; | ||
17 | } | ||
18 | Api.Call('UPDATE_MARKET', {'key': this.state.apiKey, 'secret': this.state.apiSecret, 'name': 'poloniex'}, function(err, status, data) { | ||
19 | if (err) { | ||
20 | console.error(err, data); | ||
21 | return; | ||
22 | } | ||
23 | |||
24 | this.setState({'flag': 'loading', 'valueCurrency': null, 'balanceValue': null, 'balance': null}); | ||
25 | this.loadBalance(); | ||
26 | }.bind(this)); | ||
27 | } | 8 | } |
28 | 9 | ||
29 | loadBalance = () => { | 10 | loadBalance = () => { |
@@ -31,34 +12,19 @@ class PoloniexController extends React.Component { | |||
31 | if (err) { | 12 | if (err) { |
32 | console.error(err, data); | 13 | console.error(err, data); |
33 | if (err.code === 'invalid_market_credentials') { | 14 | if (err.code === 'invalid_market_credentials') { |
34 | this.setState({'flag': 'invalidCredentials', 'valueCurrency': null, 'balanceValue': null, 'balance': null}); | 15 | this.setState({'flag': 'invalidCredentials', 'apiRequested': true, 'valueCurrency': null, 'balanceValue': null, 'balance': null}); |
35 | } else if (err.code === 'ip_restricted_api_key') { | 16 | } else if (err.code === 'ip_restricted_api_key') { |
36 | this.setState({'flag': 'ipRestricted', 'valueCurrency': null, 'balanceValue': null, 'balance': null}); | 17 | this.setState({'flag': 'ipRestricted', 'apiRequested': true, 'valueCurrency': null, 'balanceValue': null, 'balance': null}); |
37 | } | 18 | } |
38 | return; | 19 | return; |
39 | } | 20 | } |
40 | 21 | ||
41 | this.setState({'flag': 'ok', 'valueCurrency': data.valueCurrency, 'balanceValue': data.value, 'balance': data.balance}); | 22 | this.setState({'flag': 'ok', 'apiRequested': true, 'valueCurrency': data.valueCurrency, 'balanceValue': data.value, 'balance': data.balance}); |
42 | }.bind(this)); | 23 | }.bind(this)); |
43 | } | 24 | } |
44 | 25 | ||
45 | componentDidMount = () => { | 26 | componentDidMount = () => { |
46 | Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { | 27 | this.loadBalance(); |
47 | this.setState({'apiRequested': true}); | ||
48 | if (err) { | ||
49 | console.error(err, data); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | var flag = this.state.flag; | ||
54 | if (!data.key || !data.secret) { | ||
55 | flag = 'emptyCredentials'; | ||
56 | } else { | ||
57 | this.loadBalance(); | ||
58 | } | ||
59 | |||
60 | this.setState({'apiKey': data.key, 'apiSecret': data.secret, 'flag': flag}); | ||
61 | }.bind(this)); | ||
62 | } | 28 | } |
63 | 29 | ||
64 | render = () => { | 30 | render = () => { |
@@ -68,13 +34,9 @@ class PoloniexController extends React.Component { | |||
68 | displayText = 'Loading data from poloniex...'; | 34 | displayText = 'Loading data from poloniex...'; |
69 | break; | 35 | break; |
70 | case 'invalidCredentials': | 36 | case 'invalidCredentials': |
71 | displayText = 'Invalid poloniex credentials'; | ||
72 | break; | ||
73 | case 'ipRestricted': | 37 | case 'ipRestricted': |
74 | displayText = 'Your API key is IP restricted. Please whitelist us.'; | ||
75 | break; | ||
76 | case 'emptyCredentials': | 38 | case 'emptyCredentials': |
77 | displayText = 'Please provide poloniex credentials'; | 39 | displayText = <div>Please provide poloniex credentials in <a href="/account">Account</a> page.</div>; |
78 | break; | 40 | break; |
79 | default: | 41 | default: |
80 | displayText = null; | 42 | displayText = null; |
@@ -88,11 +50,6 @@ class PoloniexController extends React.Component { | |||
88 | balanceValue={this.state.balanceValue} | 50 | balanceValue={this.state.balanceValue} |
89 | balance={this.state.balance} | 51 | balance={this.state.balance} |
90 | displayText={displayText}/> | 52 | displayText={displayText}/> |
91 | <PoloniexCredentialsForm onLoadCredentials={this.onLoadCredentials} | ||
92 | onCredentialsSubmit={this.handleCredentialsSubmit} | ||
93 | onCredentialsChange={this.handleCredentialsChange} | ||
94 | apiSecret={this.state.apiSecret} | ||
95 | apiKey={this.state.apiKey}/> | ||
96 | </div> | 53 | </div> |
97 | ); | 54 | ); |
98 | } | 55 | } |
@@ -141,14 +98,14 @@ class PoloniexBalance extends React.Component { | |||
141 | </div> | 98 | </div> |
142 | </div> | 99 | </div> |
143 | </div>; | 100 | </div>; |
144 | } else { | 101 | } else { |
145 | dashboard = | 102 | dashboard = |
146 | <div className="row"> | 103 | <div className="row"> |
147 | <div className="col-12 text-center"> | 104 | <div className="col-12 text-center"> |
148 | <span>{this.props.displayText}</span> | 105 | <span>{this.props.displayText}</span> |
149 | </div> | 106 | </div> |
150 | </div>; | 107 | </div>; |
151 | } | 108 | } |
152 | 109 | ||
153 | return ( | 110 | return ( |
154 | <div className="row"> | 111 | <div className="row"> |
@@ -164,55 +121,4 @@ class PoloniexBalance extends React.Component { | |||
164 | } | 121 | } |
165 | } | 122 | } |
166 | 123 | ||
167 | class PoloniexCredentialsForm extends React.Component { | ||
168 | constructor(props) { | ||
169 | super(props); | ||
170 | this.state = {'hideMsg': true, 'msg': '', 'editMode': false, 'msgOk': false}; | ||
171 | } | ||
172 | |||
173 | handleSubmit = (e) => { | ||
174 | this.props.onCredentialsSubmit(); | ||
175 | this.setState({'editMode': false}); | ||
176 | e.preventDefault(); | ||
177 | } | ||
178 | |||
179 | handleApiKeyChange = (event) => { | ||
180 | this.props.onCredentialsChange(event.target.value, this.props.apiSecret); | ||
181 | } | ||
182 | |||
183 | handleApiSecretChange = (event) => { | ||
184 | this.props.onCredentialsChange(this.props.apiKey, event.target.value); | ||
185 | } | ||
186 | |||
187 | onEditClick = () => { | ||
188 | this.setState({'editMode': true}); | ||
189 | } | ||
190 | |||
191 | render = () => { | ||
192 | var submitType = this.state.editMode === true ? 'submit' : 'hidden'; | ||
193 | var buttonDisplay = this.state.editMode === true ? 'none' : 'inline'; | ||
194 | var secretDisplayed = this.state.editMode === true ? this.props.apiSecret : 'XXXXXXX'; | ||
195 | var keyDisplayed = this.state.editMode === true ? this.props.apiKey : 'XXXXXXX'; | ||
196 | |||
197 | return ( | ||
198 | <div className="row api-credentials-form"> | ||
199 | <div className="offset-2 col-8 box"> | ||
200 | <span className="text-center">Poloniex credentials</span> | ||
201 | <hr/> | ||
202 | <form role="form" onSubmit={this.handleSubmit}> | ||
203 | <label className="w-100">Key: | ||
204 | <input className="form-control" type="text" placeholder="key" value={keyDisplayed} onChange={this.handleApiKeyChange} disabled={!this.state.editMode}/> | ||
205 | </label> | ||
206 | <label className="w-100">Secret: | ||
207 | <input className="form-control" type="text" placeholder="secret" value={secretDisplayed} onChange={this.handleApiSecretChange} disabled={!this.state.editMode}/> | ||
208 | </label> | ||
209 | <input className="form-control submit" type={submitType} value="Save" /> | ||
210 | <button className="form-control submit" style={{display: buttonDisplay}} onSubmit={null} onClick={this.onEditClick} type="button">Show/Edit</button> | ||
211 | </form> | ||
212 | </div> | ||
213 | </div> | ||
214 | ); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | export default PoloniexController; | 124 | 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 { | |||
44 | margin-bottom: 30px; | 44 | margin-bottom: 30px; |
45 | } | 45 | } |
46 | 46 | ||
47 | .header-menu-section { | ||
48 | margin-right: 10px; | ||
49 | } | ||
50 | |||
47 | h1 { | 51 | h1 { |
48 | font-size: 1.5em; | 52 | font-size: 1.5em; |
49 | margin-bottom: 5px; | 53 | margin-bottom: 5px; |
@@ -57,6 +61,22 @@ h1 { | |||
57 | background-color: white; | 61 | background-color: white; |
58 | } | 62 | } |
59 | 63 | ||
64 | .config-status { | ||
65 | margin-bottom: 10px; | ||
66 | font-size: 0.9em; | ||
67 | } | ||
68 | |||
69 | .config-status .icon-cancel-circled { | ||
70 | color: red; | ||
71 | } | ||
72 | |||
73 | .config-status .icon-ok-circled { | ||
74 | color: green; | ||
75 | } | ||
76 | .config-status i { | ||
77 | font-size: 1.2em; | ||
78 | } | ||
79 | |||
60 | .sign-in .submit { | 80 | .sign-in .submit { |
61 | background-color: rgb(20, 20, 20); | 81 | background-color: rgb(20, 20, 20); |
62 | color: white; | 82 | color: white; |