From 5b28f4a7d6438388933e8e493a2be46339a09b48 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 15:44:59 +0800 Subject: [PATCH 01/17] Revamp Limits-dialog to enforce self-exclusion limits --- src/botPage/view/Dialogs/Limits.js | 187 ++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 59 deletions(-) diff --git a/src/botPage/view/Dialogs/Limits.js b/src/botPage/view/Dialogs/Limits.js index 33332b2b59..051b931ee9 100644 --- a/src/botPage/view/Dialogs/Limits.js +++ b/src/botPage/view/Dialogs/Limits.js @@ -1,59 +1,115 @@ +import { LiveApi } from 'binary-live-api'; import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { translate } from '../../../common/i18n'; -import * as style from '../style'; import Dialog from './Dialog'; import { restrictInputCharacter } from '../shared'; +import * as style from '../style'; +import { getToken } from '../../../common/utils/storageManager'; +import { showSpinnerInButton, removeSpinnerInButton, createUrl, translate } from '../../../common/utils/tools'; class LimitsContent extends PureComponent { constructor() { super(); this.state = { error : '', - maxLoss : '', - maxTrades: '', + maxTrades: 0, + maxLosses: null, }; } + submit() { - const maxLoss = parseFloat(this.state.maxLoss || 0); - const maxTrades = parseInt(this.state.maxTrades || 0); this.setState({ error: '' }); - if (maxTrades <= 0 || maxTrades > 100) { - this.setState({ error: 'Maximum number of trades should be between 1 and 100.' }); + + if (!this.state.maxLosses) { + this.updateMaxLosses() + .then(() => { + this.props.onSave({ maxTrades: this.state.maxTrades }); + }) + .catch(() => { + this.setState({ + error: translate( + 'Please set your daily loss limit in the Self-Exclusion Facilities page to allow trading.' + ), + }); + }); return; } - if (!maxLoss) { - this.setState({ error: 'Please enter a Maximum Loss amount greater than zero.' }); + + if (this.state.maxTrades <= 0 || this.state.maxTrades > 100) { + this.setState({ error: translate('Maximum consecutive trades should be between 1 and 100') }); return; } - this.props.onSave({ - maxLoss, - maxTrades, + + this.props.onSave({ maxTrades: this.state.maxTrades }); + } + + updateMaxLosses() { + return new Promise((resolve, reject) => { + const { api } = this.props; + const $startButton = $('#submit-trade-limits'); + const initialText = $startButton.text(); + + showSpinnerInButton($startButton); + + api.getSelfExclusion() + .then(response => { + const { max_losses: maxLosses } = response.get_self_exclusion; + let callback; + + if (maxLosses) { + this.setState({ maxLosses }); + callback = resolve; + } else { + callback = reject; + } + + removeSpinnerInButton($startButton, initialText); + callback(); + }) + .catch(() => { + removeSpinnerInButton($startButton, initialText); + reject(); + }); }); } + componentDidMount() { const cleanupLayout = () => { this.setState({ - maxTrades: '', - maxLoss : '', + maxTrades: 0, error : '', }); }; + + const onDialogOpen = () => { + this.updateMaxLosses().catch(() => {}); + }; + $('#limits-dialog-component').dialog({ + open : onDialogOpen, close : cleanupLayout, autoOpen: false, }); } + onMaxTradeChange(e) { if (restrictInputCharacter({ input: e.target.value, whitelistRegEx: '^[\\d]*$' })) { this.setState({ maxTrades: e.target.value }); } } - onMaxLossChange(e) { - if (restrictInputCharacter({ input: e.target.value, whitelistRegEx: '^\\d*\\.?\\d*$' })) { - this.setState({ maxLoss: e.target.value }); + + getDailyLossesLimit() { + if (this.state.maxLosses) { + const token = $('.account-id') + .first() + .attr('value'); + const tokenObj = getToken(token); + const currency = tokenObj && tokenObj.loginInfo.currency; + return currency ? `${this.state.maxLosses} ${currency}` : `${this.state.maxLosses}`; } + return translate('Not set'); } + render() { return (
-
-
- -
-
- -
- {this.state.error ?

{this.state.error}

: null} -

{translate( - 'Trade limitations are required by our regulators. Your bot will conclude trading when one or both of the conditions are met.' + 'We require you to set trade limitations in compliance with business regulations. Please note that your bot will only stop trading if any or both of the conditions below are met.' )}

-
- +
+ +
+ {translate([ + 'This is the threshold that limits your potential losses for the day in all Binary.com platforms. Once your total loss reaches or exceeds this amount, your bot will stop trading. Please set a value in the [_1]Self-Exclusion Facilities page[_2].', + ``, + '', + ])} +
+
+
+ +
+ {translate( + 'This is the maximum number of trades that you allow your bot to execute for this run.' + )} +
+
+
+ { + this.maxTradesDiv = el; + }} + type="text" + id="limitation-max-trades" + step="1" + maxLength="3" + value={this.state.maxTrades} + onChange={(...args) => this.onMaxTradeChange(...args)} + data-lpignore={true} + /> +
+ {this.state.error &&

{this.state.error}

} +
+
); } static props = { onSave: PropTypes.func, + api : PropTypes.instanceOf(LiveApi), }; } export default class Limits extends Dialog { - constructor() { + constructor(api) { const onSave = limits => { this.limitsPromise(limits); this.close(); }; - super('limits-dialog', translate('Trade Limitations'), , style.dialogLayout); + super( + 'limits-dialog', + translate('Trade Limitations'), + , + style.dialogLayout + ); + this.registerCloseOnOtherDialog(); } getLimits() { this.open(); From 0c9a05201ee851f95437e91ecc6370b7206aba4e Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 15:50:08 +0800 Subject: [PATCH 02/17] Create Limits-dialog only when required, and catch uncaught Promise rejection --- src/botPage/view/View.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index cb626fbd12..dbbcca6148 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -142,7 +142,6 @@ const clearRealityCheck = () => { stopRealityCheck(); }; -const limits = new Limits(); const integrationsDialog = new IntegrationsDialog(); const loadDialog = new LoadDialog(); const saveDialog = new SaveDialog(); @@ -518,8 +517,13 @@ export default class View { .attr('value'); const tokenObj = getToken(token); initRealityCheck(() => $('#stopButton').triggerHandler('click')); + if (tokenObj && tokenObj.hasTradeLimitation) { - limits.getLimits().then(startBot); + const limits = new Limits(api); + limits + .getLimits() + .then(startBot) + .catch(() => {}); } else { startBot(); } From 208a52d590c08480940586b69fbd28217b8b8e99 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 15:59:20 +0800 Subject: [PATCH 03/17] Create rules for panel elements --- static/css/_panel.scss | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/static/css/_panel.scss b/static/css/_panel.scss index 27cc5c61ca..56037bc5df 100644 --- a/static/css/_panel.scss +++ b/static/css/_panel.scss @@ -320,6 +320,24 @@ $disabled-color: #F2F2F2; .ui-dialog-content { padding: 0px !important; + + &.ui-widget-content { + input[type=text] { + height: 40px; + width: 100%; + } + .description { + font-size: 75%; + margin: 0.5em 0; + } + .input-row { + margin: 1em 0; + + &.last { + margin-bottom: 0; + } + } + } } #load-dialog, #save-dialog { @@ -328,23 +346,7 @@ $disabled-color: #F2F2F2; } } -#load-dialog, #save-dialog, #integrations-dialog { - .input-row { - margin: 1em 0; - } - .input-row.last { - margin-bottom: 0; - } - & .description { - font-size: 75%; - } -} - #save-dialog { - #save-filename { - width: 100%; - height: 40px; - } #collection { padding: 1.2em; border: 1px solid $brand-gray; @@ -367,9 +369,6 @@ $disabled-color: #F2F2F2; font-size: 20px; margin: 0 0 0.2em 0; } - .description { - margin: 0 0 0.2em 0; - } .left { width: 60%; display: table-cell; From 12b7020c265e5c2adc6d431c516e43eff4cb8ee3 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 16:20:23 +0800 Subject: [PATCH 04/17] Set node to v10.15.3 and force npm to 6.9.0 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e9a7dd52cc..6c6e7f05a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: node_js -node_js: node +node_js: "10.15.3" +before_install: npm i -g npm@6.9.0 +install: npm ci cache: directories: - node_modules From 784e06e47c9a960dcba9e31aed8e9d965373e0af Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 19:14:44 +0800 Subject: [PATCH 05/17] Pass maxLoss to TradeEngine --- src/botPage/view/Dialogs/Limits.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/botPage/view/Dialogs/Limits.js b/src/botPage/view/Dialogs/Limits.js index 051b931ee9..e0b87119c5 100644 --- a/src/botPage/view/Dialogs/Limits.js +++ b/src/botPage/view/Dialogs/Limits.js @@ -20,10 +20,17 @@ class LimitsContent extends PureComponent { submit() { this.setState({ error: '' }); + const onSave = () => { + this.props.onSave({ + maxTrades: this.state.maxTrades, + maxLoss : this.state.maxLosses, + }); + }; + if (!this.state.maxLosses) { this.updateMaxLosses() .then(() => { - this.props.onSave({ maxTrades: this.state.maxTrades }); + onSave(); }) .catch(() => { this.setState({ @@ -40,7 +47,7 @@ class LimitsContent extends PureComponent { return; } - this.props.onSave({ maxTrades: this.state.maxTrades }); + onSave(); } updateMaxLosses() { From 61c9cdc6d0bc3011666b843521c0abe18de651c4 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Fri, 26 Apr 2019 09:47:51 +0800 Subject: [PATCH 06/17] Update jQuery --- package-lock.json | 311 ++++++++++++++++------------------------------ package.json | 2 +- 2 files changed, 109 insertions(+), 204 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9efde45659..a47d191ce6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9832,9 +9832,9 @@ } }, "handlebars": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", - "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", "dev": true, "requires": { "neo-async": "^2.6.0", @@ -10771,136 +10771,26 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-api": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", - "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.6.tgz", + "integrity": "sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==", "dev": true, "requires": { - "async": "^2.6.1", - "compare-versions": "^3.2.1", + "async": "^2.6.2", + "compare-versions": "^3.4.0", "fileset": "^2.0.3", - "istanbul-lib-coverage": "^2.0.3", - "istanbul-lib-hook": "^2.0.3", - "istanbul-lib-instrument": "^3.1.0", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.2", - "istanbul-reports": "^2.1.1", - "js-yaml": "^3.12.0", - "make-dir": "^1.3.0", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", "minimatch": "^3.0.4", "once": "^1.4.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/generator": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.0.tgz", - "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", - "dev": true, - "requires": { - "@babel/types": "^7.4.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz", - "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", - "dev": true, - "requires": { - "@babel/types": "^7.4.0" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "@babel/template": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.0.tgz", - "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.0", - "@babel/types": "^7.4.0" - } - }, - "@babel/traverse": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.3.tgz", - "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/types": "^7.4.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" - } - }, - "@babel/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", - "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", @@ -10910,17 +10800,6 @@ "lodash": "^4.17.11" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -10930,38 +10809,57 @@ "ms": "^2.1.1" } }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, "istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true }, "istanbul-lib-instrument": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", - "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", "dev": true, "requires": { - "@babel/generator": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "istanbul-lib-coverage": "^2.0.3", - "semver": "^5.5.0" + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" } }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } }, "ms": { "version": "2.1.1", @@ -10969,25 +10867,16 @@ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "semver": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", "dev": true } } @@ -10999,9 +10888,9 @@ "dev": true }, "istanbul-lib-hook": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz", - "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", "dev": true, "requires": { "append-transform": "^1.0.0" @@ -11023,20 +10912,36 @@ } }, "istanbul-lib-report": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", - "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "supports-color": "^6.0.0" + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" }, "dependencies": { "istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, "supports-color": { @@ -11087,12 +10992,12 @@ } }, "istanbul-reports": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", - "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.4.tgz", + "integrity": "sha512-QCHGyZEK0bfi9GR215QSm+NJwFKEShbtc7tfbUdLAEzn3kKhLDDZqvljn8rPZM9v8CEOhzL1nlYoO4r1ryl67w==", "dev": true, "requires": { - "handlebars": "^4.1.0" + "handlebars": "^4.1.2" } }, "jest": { @@ -13921,9 +13826,9 @@ } }, "jquery": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz", - "integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c=", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.0.tgz", + "integrity": "sha512-ggRCXln9zEqv6OqAGXFEcshF5dSBvCkzj6Gm2gzuR5fWawaX8t7cxKVkkygKODrDAzKdoYw3l/e3pm3vlT4IbQ==", "dev": true }, "jquery-mousewheel": { @@ -13984,9 +13889,9 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", - "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -20226,9 +20131,9 @@ "dev": true }, "uglify-js": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.4.tgz", - "integrity": "sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA==", + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.8.tgz", + "integrity": "sha512-GFSjB1nZIzoIq70qvDRtWRORHX3vFkAnyK/rDExc0BN7r9+/S+Voz3t/fwJuVfjppAMz+ceR2poE7tkhvnVwQQ==", "dev": true, "optional": true, "requires": { diff --git a/package.json b/package.json index 1e1b842710..895c9f81bd 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "i18next-scanner": "1.9.4", "immutable": "^3.8.2", "jest": "^24.7.1", - "jquery": "3.2.1", + "jquery": "^3.4.0", "jquery-ui": "1.12.1", "jquery-ui-css": "1.11.4", "js-interpreter": "^1.4.6", From 1e7cee6cf1341e3f4869cda2b9fe80438c388fd2 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Fri, 26 Apr 2019 18:30:10 +0800 Subject: [PATCH 07/17] added auto refresh of contracts --- gulpfile.babel.js | 2 +- src/botPage/bot/TradeEngine/OpenContract.js | 8 +- src/botPage/bot/broadcast.js | 2 + src/botPage/view/TradeInfoPanel/TradeTable.js | 97 ++++++++++++++++++- src/botPage/view/TradeInfoPanel/index.js | 2 +- src/botPage/view/View.js | 2 +- 6 files changed, 104 insertions(+), 9 deletions(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index e0c39d11fa..18765b8a4a 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -12,7 +12,7 @@ gulp.task( gulp.series(done => { connect.server({ root : 'www', - port : 8080, + port : 80, livereload: true, }); done(); diff --git a/src/botPage/bot/TradeEngine/OpenContract.js b/src/botPage/bot/TradeEngine/OpenContract.js index 6f6a36fe8f..94effe6f64 100644 --- a/src/botPage/bot/TradeEngine/OpenContract.js +++ b/src/botPage/bot/TradeEngine/OpenContract.js @@ -1,6 +1,6 @@ import { roundBalance } from '../../common/tools'; import { doUntilDone } from '../tools'; -import { contractStatus, contract as broadcastContract } from '../broadcast'; +import { contractStatus, contractSettled, contract as broadcastContract } from '../broadcast'; import { sell, openContractReceived } from './state/actions'; const AFTER_FINISH_TIMEOUT = 5; @@ -27,7 +27,9 @@ export default Engine => contractStatus({ id : 'contract.sold', data: contract.transaction_ids.sell, + contract, }); + contractSettled(contract); this.contractId = ''; this.updateTotals(contract); if (this.afterPromise) { @@ -67,7 +69,9 @@ export default Engine => this.unsubscribeOpenContract(); doUntilDone(() => this.api.subscribeToOpenContract(contractId)).then(r => { - ({ proposal_open_contract: { id: this.openContractId } } = r); + ({ + proposal_open_contract: { id: this.openContractId }, + } = r); }); } resetSubscriptionTimeout(timeout = this.getContractDuration() + AFTER_FINISH_TIMEOUT) { diff --git a/src/botPage/bot/broadcast.js b/src/botPage/bot/broadcast.js index 7ffc8f3d03..4c9a236ac6 100644 --- a/src/botPage/bot/broadcast.js +++ b/src/botPage/bot/broadcast.js @@ -4,6 +4,8 @@ export const contract = c => globalObserver.emit('bot.contract', c); export const contractStatus = c => globalObserver.emit('contract.status', c); +export const contractSettled = c => globalObserver.emit('contract.settled', c); + export const info = i => globalObserver.emit('bot.info', i); export const notify = (className, message) => globalObserver.emit('Notify', { className, message, position: 'right' }); diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index fe5bdef7b1..05b87f0d0f 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -1,3 +1,4 @@ +/* eslint-disable no-debugger */ import json2csv from 'json2csv'; import React, { Component } from 'react'; import ReactDataGrid from 'react-data-grid'; @@ -19,6 +20,13 @@ const getProfit = ({ sell_price: sellPrice, buy_price: buyPrice, currency }) => return ''; }; +const getTimestamp = date => { + const buyDate = new Date(date * 1000); + return `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ + buyDate.toTimeString().split(' ')[1] + }`; +}; + const minHeight = 290; const rowHeight = 25; @@ -36,6 +44,7 @@ export default class TradeTable extends Component { id : 0, rows: [], }, + test: {}, }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, @@ -48,6 +57,8 @@ export default class TradeTable extends Component { ]; } componentWillMount() { + const { api } = this.props; + globalObserver.register('summary.export', () => { const accountData = this.state[this.props.accountID]; if (accountData && accountData.rows.length > 0) { @@ -68,10 +79,7 @@ export default class TradeTable extends Component { if (!info) { return; } - const buyDate = new Date(info.date_start * 1000); - const timestamp = `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ - buyDate.toTimeString().split(' ')[1] - }`; + const timestamp = getTimestamp(info.date_start); const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; const { accountID } = tradeObj; @@ -93,6 +101,87 @@ export default class TradeTable extends Component { this.setState({ [accountID]: appendRow(trade, accountStat) }); } }); + globalObserver.register('contract.settled', contract => { + const registerTimeout = contract => { + setTimeout(() => { + const contractID = contract.contract_id; + this.refreshContract(api, contractID); + // globalObserver.emit('ui.log.success', contractId); + + // const accountStat = this.getAccountStat(this.props.accountID); + // const { id } = this.state[this.props.accountID]; + + // const rows = accountStat.rows.slice(); + // const updatedRows = rows.map(row => { + // if (row.contract_id === contractId) { + // row.contract_type = 'Settled'; + // return row; + // } + // return row; + // }); + // this.setState({ [this.props.accountID]: { id, 'rows': updatedRows } }); + }, 3000); + }; + + registerTimeout(contract); + }); + } + refreshContract(api, contractID) { + api.getContractInfo(contractID).then(r => { + const contract = r.proposal_open_contract; + // this.updateTable(contract); + + const timestamp = getTimestamp(contract.date_start); + const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; + const { accountID } = this.props; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); + }); + } + updateTable(info) { + const timestamp = getTimestamp(info.date_start); + const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; + const { accountID } = tradeObj; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); } rowGetter(i) { const { accountID } = this.props; diff --git a/src/botPage/view/TradeInfoPanel/index.js b/src/botPage/view/TradeInfoPanel/index.js index 20c70827a9..125828dc4c 100644 --- a/src/botPage/view/TradeInfoPanel/index.js +++ b/src/botPage/view/TradeInfoPanel/index.js @@ -171,7 +171,7 @@ export default class TradeInfoPanel extends Component {
- +
diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index cb626fbd12..d7a345798b 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -684,6 +684,6 @@ function renderReactComponents() { />, $('#footer')[0] ); - ReactDOM.render(, $('#summaryPanel')[0]); + ReactDOM.render(, $('#summaryPanel')[0]); ReactDOM.render(, $('#logTable')[0]); } From ed5551d4b04e9f9f033370cfe738536ca0019d4f Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Thu, 25 Apr 2019 16:20:23 +0800 Subject: [PATCH 08/17] Set node to v10.15.3 and force npm to 6.9.0 --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e9a7dd52cc..6c6e7f05a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: node_js -node_js: node +node_js: "10.15.3" +before_install: npm i -g npm@6.9.0 +install: npm ci cache: directories: - node_modules From a9b2ee3de3fc20f4b6196e38fcaf7a42f42bf030 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Fri, 26 Apr 2019 18:30:10 +0800 Subject: [PATCH 09/17] added auto refresh of contracts --- gulpfile.babel.js | 2 +- src/botPage/bot/TradeEngine/OpenContract.js | 8 +- src/botPage/bot/broadcast.js | 2 + src/botPage/view/TradeInfoPanel/TradeTable.js | 97 ++++++++++++++++++- src/botPage/view/TradeInfoPanel/index.js | 2 +- src/botPage/view/View.js | 2 +- 6 files changed, 104 insertions(+), 9 deletions(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index e0c39d11fa..18765b8a4a 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -12,7 +12,7 @@ gulp.task( gulp.series(done => { connect.server({ root : 'www', - port : 8080, + port : 80, livereload: true, }); done(); diff --git a/src/botPage/bot/TradeEngine/OpenContract.js b/src/botPage/bot/TradeEngine/OpenContract.js index 6f6a36fe8f..94effe6f64 100644 --- a/src/botPage/bot/TradeEngine/OpenContract.js +++ b/src/botPage/bot/TradeEngine/OpenContract.js @@ -1,6 +1,6 @@ import { roundBalance } from '../../common/tools'; import { doUntilDone } from '../tools'; -import { contractStatus, contract as broadcastContract } from '../broadcast'; +import { contractStatus, contractSettled, contract as broadcastContract } from '../broadcast'; import { sell, openContractReceived } from './state/actions'; const AFTER_FINISH_TIMEOUT = 5; @@ -27,7 +27,9 @@ export default Engine => contractStatus({ id : 'contract.sold', data: contract.transaction_ids.sell, + contract, }); + contractSettled(contract); this.contractId = ''; this.updateTotals(contract); if (this.afterPromise) { @@ -67,7 +69,9 @@ export default Engine => this.unsubscribeOpenContract(); doUntilDone(() => this.api.subscribeToOpenContract(contractId)).then(r => { - ({ proposal_open_contract: { id: this.openContractId } } = r); + ({ + proposal_open_contract: { id: this.openContractId }, + } = r); }); } resetSubscriptionTimeout(timeout = this.getContractDuration() + AFTER_FINISH_TIMEOUT) { diff --git a/src/botPage/bot/broadcast.js b/src/botPage/bot/broadcast.js index 7ffc8f3d03..4c9a236ac6 100644 --- a/src/botPage/bot/broadcast.js +++ b/src/botPage/bot/broadcast.js @@ -4,6 +4,8 @@ export const contract = c => globalObserver.emit('bot.contract', c); export const contractStatus = c => globalObserver.emit('contract.status', c); +export const contractSettled = c => globalObserver.emit('contract.settled', c); + export const info = i => globalObserver.emit('bot.info', i); export const notify = (className, message) => globalObserver.emit('Notify', { className, message, position: 'right' }); diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index fe5bdef7b1..05b87f0d0f 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -1,3 +1,4 @@ +/* eslint-disable no-debugger */ import json2csv from 'json2csv'; import React, { Component } from 'react'; import ReactDataGrid from 'react-data-grid'; @@ -19,6 +20,13 @@ const getProfit = ({ sell_price: sellPrice, buy_price: buyPrice, currency }) => return ''; }; +const getTimestamp = date => { + const buyDate = new Date(date * 1000); + return `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ + buyDate.toTimeString().split(' ')[1] + }`; +}; + const minHeight = 290; const rowHeight = 25; @@ -36,6 +44,7 @@ export default class TradeTable extends Component { id : 0, rows: [], }, + test: {}, }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, @@ -48,6 +57,8 @@ export default class TradeTable extends Component { ]; } componentWillMount() { + const { api } = this.props; + globalObserver.register('summary.export', () => { const accountData = this.state[this.props.accountID]; if (accountData && accountData.rows.length > 0) { @@ -68,10 +79,7 @@ export default class TradeTable extends Component { if (!info) { return; } - const buyDate = new Date(info.date_start * 1000); - const timestamp = `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ - buyDate.toTimeString().split(' ')[1] - }`; + const timestamp = getTimestamp(info.date_start); const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; const { accountID } = tradeObj; @@ -93,6 +101,87 @@ export default class TradeTable extends Component { this.setState({ [accountID]: appendRow(trade, accountStat) }); } }); + globalObserver.register('contract.settled', contract => { + const registerTimeout = contract => { + setTimeout(() => { + const contractID = contract.contract_id; + this.refreshContract(api, contractID); + // globalObserver.emit('ui.log.success', contractId); + + // const accountStat = this.getAccountStat(this.props.accountID); + // const { id } = this.state[this.props.accountID]; + + // const rows = accountStat.rows.slice(); + // const updatedRows = rows.map(row => { + // if (row.contract_id === contractId) { + // row.contract_type = 'Settled'; + // return row; + // } + // return row; + // }); + // this.setState({ [this.props.accountID]: { id, 'rows': updatedRows } }); + }, 3000); + }; + + registerTimeout(contract); + }); + } + refreshContract(api, contractID) { + api.getContractInfo(contractID).then(r => { + const contract = r.proposal_open_contract; + // this.updateTable(contract); + + const timestamp = getTimestamp(contract.date_start); + const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; + const { accountID } = this.props; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); + }); + } + updateTable(info) { + const timestamp = getTimestamp(info.date_start); + const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; + const { accountID } = tradeObj; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); } rowGetter(i) { const { accountID } = this.props; diff --git a/src/botPage/view/TradeInfoPanel/index.js b/src/botPage/view/TradeInfoPanel/index.js index 20c70827a9..125828dc4c 100644 --- a/src/botPage/view/TradeInfoPanel/index.js +++ b/src/botPage/view/TradeInfoPanel/index.js @@ -171,7 +171,7 @@ export default class TradeInfoPanel extends Component {
- +
diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index cb626fbd12..d7a345798b 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -684,6 +684,6 @@ function renderReactComponents() { />, $('#footer')[0] ); - ReactDOM.render(, $('#summaryPanel')[0]); + ReactDOM.render(, $('#summaryPanel')[0]); ReactDOM.render(, $('#logTable')[0]); } From 05ccace099ded86156209f186e49d17cf6d64fdc Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Mon, 29 Apr 2019 14:07:11 +0800 Subject: [PATCH 10/17] code cleanup --- src/botPage/view/TradeInfoPanel/TradeTable.js | 58 +++---------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index 05b87f0d0f..641c3da353 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -44,7 +44,6 @@ export default class TradeTable extends Component { id : 0, rows: [], }, - test: {}, }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, @@ -102,35 +101,18 @@ export default class TradeTable extends Component { } }); globalObserver.register('contract.settled', contract => { - const registerTimeout = contract => { - setTimeout(() => { - const contractID = contract.contract_id; - this.refreshContract(api, contractID); - // globalObserver.emit('ui.log.success', contractId); - - // const accountStat = this.getAccountStat(this.props.accountID); - // const { id } = this.state[this.props.accountID]; - - // const rows = accountStat.rows.slice(); - // const updatedRows = rows.map(row => { - // if (row.contract_id === contractId) { - // row.contract_type = 'Settled'; - // return row; - // } - // return row; - // }); - // this.setState({ [this.props.accountID]: { id, 'rows': updatedRows } }); - }, 3000); - }; - - registerTimeout(contract); + this.registerTimeout(api, contract); }); } + registerTimeout = (api, contract) => { + setTimeout(() => { + const contractID = contract.contract_id; + this.refreshContract(api, contractID); + }, 3000); + }; refreshContract(api, contractID) { api.getContractInfo(contractID).then(r => { const contract = r.proposal_open_contract; - // this.updateTable(contract); - const timestamp = getTimestamp(contract.date_start); const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; const { accountID } = this.props; @@ -157,32 +139,6 @@ export default class TradeTable extends Component { this.setState({ [accountID]: { id, rows: updatedRows } }); }); } - updateTable(info) { - const timestamp = getTimestamp(info.date_start); - const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; - const { accountID } = tradeObj; - - const trade = { - ...tradeObj, - profit: getProfit(tradeObj), - }; - - if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; - - const { id } = this.state[accountID]; - const rows = this.state[accountID].rows.slice(); - const updatedRows = rows.map(row => { - const { reference } = row; - if (reference === trade.reference) { - return { - reference, - ...trade, - }; - } - return row; - }); - this.setState({ [accountID]: { id, rows: updatedRows } }); - } rowGetter(i) { const { accountID } = this.props; const { rows } = this.state[accountID]; From 2aa1e56af88138bef069ceb033c41bb7772fc64d Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Mon, 29 Apr 2019 14:16:35 +0800 Subject: [PATCH 11/17] port update --- gulpfile.babel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 18765b8a4a..e0c39d11fa 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -12,7 +12,7 @@ gulp.task( gulp.series(done => { connect.server({ root : 'www', - port : 80, + port : 8080, livereload: true, }); done(); From 01bbe738fddd11cdf676b0fd4aacdbabef429d77 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Fri, 26 Apr 2019 18:30:10 +0800 Subject: [PATCH 12/17] added auto refresh of contracts --- gulpfile.babel.js | 2 +- src/botPage/bot/TradeEngine/OpenContract.js | 8 +- src/botPage/bot/broadcast.js | 2 + src/botPage/view/TradeInfoPanel/TradeTable.js | 97 ++++++++++++++++++- src/botPage/view/TradeInfoPanel/index.js | 2 +- src/botPage/view/View.js | 2 +- 6 files changed, 104 insertions(+), 9 deletions(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index e0c39d11fa..18765b8a4a 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -12,7 +12,7 @@ gulp.task( gulp.series(done => { connect.server({ root : 'www', - port : 8080, + port : 80, livereload: true, }); done(); diff --git a/src/botPage/bot/TradeEngine/OpenContract.js b/src/botPage/bot/TradeEngine/OpenContract.js index 6f6a36fe8f..94effe6f64 100644 --- a/src/botPage/bot/TradeEngine/OpenContract.js +++ b/src/botPage/bot/TradeEngine/OpenContract.js @@ -1,6 +1,6 @@ import { roundBalance } from '../../common/tools'; import { doUntilDone } from '../tools'; -import { contractStatus, contract as broadcastContract } from '../broadcast'; +import { contractStatus, contractSettled, contract as broadcastContract } from '../broadcast'; import { sell, openContractReceived } from './state/actions'; const AFTER_FINISH_TIMEOUT = 5; @@ -27,7 +27,9 @@ export default Engine => contractStatus({ id : 'contract.sold', data: contract.transaction_ids.sell, + contract, }); + contractSettled(contract); this.contractId = ''; this.updateTotals(contract); if (this.afterPromise) { @@ -67,7 +69,9 @@ export default Engine => this.unsubscribeOpenContract(); doUntilDone(() => this.api.subscribeToOpenContract(contractId)).then(r => { - ({ proposal_open_contract: { id: this.openContractId } } = r); + ({ + proposal_open_contract: { id: this.openContractId }, + } = r); }); } resetSubscriptionTimeout(timeout = this.getContractDuration() + AFTER_FINISH_TIMEOUT) { diff --git a/src/botPage/bot/broadcast.js b/src/botPage/bot/broadcast.js index 7ffc8f3d03..4c9a236ac6 100644 --- a/src/botPage/bot/broadcast.js +++ b/src/botPage/bot/broadcast.js @@ -4,6 +4,8 @@ export const contract = c => globalObserver.emit('bot.contract', c); export const contractStatus = c => globalObserver.emit('contract.status', c); +export const contractSettled = c => globalObserver.emit('contract.settled', c); + export const info = i => globalObserver.emit('bot.info', i); export const notify = (className, message) => globalObserver.emit('Notify', { className, message, position: 'right' }); diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index fe5bdef7b1..05b87f0d0f 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -1,3 +1,4 @@ +/* eslint-disable no-debugger */ import json2csv from 'json2csv'; import React, { Component } from 'react'; import ReactDataGrid from 'react-data-grid'; @@ -19,6 +20,13 @@ const getProfit = ({ sell_price: sellPrice, buy_price: buyPrice, currency }) => return ''; }; +const getTimestamp = date => { + const buyDate = new Date(date * 1000); + return `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ + buyDate.toTimeString().split(' ')[1] + }`; +}; + const minHeight = 290; const rowHeight = 25; @@ -36,6 +44,7 @@ export default class TradeTable extends Component { id : 0, rows: [], }, + test: {}, }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, @@ -48,6 +57,8 @@ export default class TradeTable extends Component { ]; } componentWillMount() { + const { api } = this.props; + globalObserver.register('summary.export', () => { const accountData = this.state[this.props.accountID]; if (accountData && accountData.rows.length > 0) { @@ -68,10 +79,7 @@ export default class TradeTable extends Component { if (!info) { return; } - const buyDate = new Date(info.date_start * 1000); - const timestamp = `${buyDate.toISOString().split('T')[0]} ${buyDate.toTimeString().slice(0, 8)} ${ - buyDate.toTimeString().split(' ')[1] - }`; + const timestamp = getTimestamp(info.date_start); const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; const { accountID } = tradeObj; @@ -93,6 +101,87 @@ export default class TradeTable extends Component { this.setState({ [accountID]: appendRow(trade, accountStat) }); } }); + globalObserver.register('contract.settled', contract => { + const registerTimeout = contract => { + setTimeout(() => { + const contractID = contract.contract_id; + this.refreshContract(api, contractID); + // globalObserver.emit('ui.log.success', contractId); + + // const accountStat = this.getAccountStat(this.props.accountID); + // const { id } = this.state[this.props.accountID]; + + // const rows = accountStat.rows.slice(); + // const updatedRows = rows.map(row => { + // if (row.contract_id === contractId) { + // row.contract_type = 'Settled'; + // return row; + // } + // return row; + // }); + // this.setState({ [this.props.accountID]: { id, 'rows': updatedRows } }); + }, 3000); + }; + + registerTimeout(contract); + }); + } + refreshContract(api, contractID) { + api.getContractInfo(contractID).then(r => { + const contract = r.proposal_open_contract; + // this.updateTable(contract); + + const timestamp = getTimestamp(contract.date_start); + const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; + const { accountID } = this.props; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); + }); + } + updateTable(info) { + const timestamp = getTimestamp(info.date_start); + const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; + const { accountID } = tradeObj; + + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + const updatedRows = rows.map(row => { + const { reference } = row; + if (reference === trade.reference) { + return { + reference, + ...trade, + }; + } + return row; + }); + this.setState({ [accountID]: { id, rows: updatedRows } }); } rowGetter(i) { const { accountID } = this.props; diff --git a/src/botPage/view/TradeInfoPanel/index.js b/src/botPage/view/TradeInfoPanel/index.js index 20c70827a9..125828dc4c 100644 --- a/src/botPage/view/TradeInfoPanel/index.js +++ b/src/botPage/view/TradeInfoPanel/index.js @@ -171,7 +171,7 @@ export default class TradeInfoPanel extends Component {
- +
diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index dbbcca6148..d54b3df8ce 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -688,6 +688,6 @@ function renderReactComponents() { />, $('#footer')[0] ); - ReactDOM.render(, $('#summaryPanel')[0]); + ReactDOM.render(, $('#summaryPanel')[0]); ReactDOM.render(, $('#logTable')[0]); } From 077b7460ef5807722bbabe6ba945bc407e2bc5f3 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Mon, 29 Apr 2019 14:07:11 +0800 Subject: [PATCH 13/17] code cleanup --- src/botPage/view/TradeInfoPanel/TradeTable.js | 58 +++---------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index 05b87f0d0f..641c3da353 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -44,7 +44,6 @@ export default class TradeTable extends Component { id : 0, rows: [], }, - test: {}, }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, @@ -102,35 +101,18 @@ export default class TradeTable extends Component { } }); globalObserver.register('contract.settled', contract => { - const registerTimeout = contract => { - setTimeout(() => { - const contractID = contract.contract_id; - this.refreshContract(api, contractID); - // globalObserver.emit('ui.log.success', contractId); - - // const accountStat = this.getAccountStat(this.props.accountID); - // const { id } = this.state[this.props.accountID]; - - // const rows = accountStat.rows.slice(); - // const updatedRows = rows.map(row => { - // if (row.contract_id === contractId) { - // row.contract_type = 'Settled'; - // return row; - // } - // return row; - // }); - // this.setState({ [this.props.accountID]: { id, 'rows': updatedRows } }); - }, 3000); - }; - - registerTimeout(contract); + this.registerTimeout(api, contract); }); } + registerTimeout = (api, contract) => { + setTimeout(() => { + const contractID = contract.contract_id; + this.refreshContract(api, contractID); + }, 3000); + }; refreshContract(api, contractID) { api.getContractInfo(contractID).then(r => { const contract = r.proposal_open_contract; - // this.updateTable(contract); - const timestamp = getTimestamp(contract.date_start); const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; const { accountID } = this.props; @@ -157,32 +139,6 @@ export default class TradeTable extends Component { this.setState({ [accountID]: { id, rows: updatedRows } }); }); } - updateTable(info) { - const timestamp = getTimestamp(info.date_start); - const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; - const { accountID } = tradeObj; - - const trade = { - ...tradeObj, - profit: getProfit(tradeObj), - }; - - if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; - - const { id } = this.state[accountID]; - const rows = this.state[accountID].rows.slice(); - const updatedRows = rows.map(row => { - const { reference } = row; - if (reference === trade.reference) { - return { - reference, - ...trade, - }; - } - return row; - }); - this.setState({ [accountID]: { id, rows: updatedRows } }); - } rowGetter(i) { const { accountID } = this.props; const { rows } = this.state[accountID]; From a2672cf84a497e45d8c79fc0c5390388027fb5b8 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Mon, 29 Apr 2019 14:16:35 +0800 Subject: [PATCH 14/17] port update --- gulpfile.babel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 18765b8a4a..e0c39d11fa 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -12,7 +12,7 @@ gulp.task( gulp.series(done => { connect.server({ root : 'www', - port : 80, + port : 8080, livereload: true, }); done(); From a808528e6697f0fe1b2eca57302431b52f00effd Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Thu, 2 May 2019 17:22:41 +0800 Subject: [PATCH 15/17] added contract settled message --- src/botPage/view/TradeInfoPanel/TradeTable.js | 14 +++++++++----- src/botPage/view/style.js | 4 ++-- static/css/_panel.scss | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index 641c3da353..fd19493c6e 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -31,6 +31,7 @@ const minHeight = 290; const rowHeight = 25; const ProfitColor = ({ value }) =>
0 ? style.green : style.red}>{value}
; +const StatusColor = ({ value }) =>
{value}
; export default class TradeTable extends Component { constructor({ accountID }) { @@ -47,12 +48,13 @@ export default class TradeTable extends Component { }; this.columns = [ { key: 'timestamp', width: 192, resizable: true, name: translate('Timestamp') }, - { key: 'reference', width: 142, resizable: true, name: translate('Reference') }, - { key: 'contract_type', width: 104, resizable: true, name: translate('Trade type') }, - { key: 'entry_tick', width: 80, resizable: true, name: translate('Entry spot') }, - { key: 'exit_tick', width: 70, resizable: true, name: translate('Exit spot') }, + { key: 'reference', width: 110, resizable: true, name: translate('Reference') }, + { key: 'contract_type', width: 70, resizable: true, name: translate('Trade type') }, + { key: 'entry_tick', width: 75, resizable: true, name: translate('Entry spot') }, + { key: 'exit_tick', width: 75, resizable: true, name: translate('Exit spot') }, { key: 'buy_price', width: 80, resizable: true, name: translate('Buy price') }, { key: 'profit', width: 80, resizable: true, name: translate('Profit/Loss'), formatter: ProfitColor }, + { key: 'contract_status', width: 65, resizable: true, name: translate('Status'), formatter: StatusColor }, ]; } componentWillMount() { @@ -84,7 +86,8 @@ export default class TradeTable extends Component { const trade = { ...tradeObj, - profit: getProfit(tradeObj), + profit : getProfit(tradeObj), + contract_status: 'Pending', }; const accountStat = this.getAccountStat(accountID); @@ -130,6 +133,7 @@ export default class TradeTable extends Component { const { reference } = row; if (reference === trade.reference) { return { + contract_status: 'Settled', reference, ...trade, }; diff --git a/src/botPage/view/style.js b/src/botPage/view/style.js index 9061ff5507..dbc1cea536 100644 --- a/src/botPage/view/style.js +++ b/src/botPage/view/style.js @@ -73,9 +73,9 @@ export const bottomWarning = { export const bottomWarningLink = { textDecoration: 'underline' }; -export const green = { color: 'green' }; +export const green = { color: 'green', float: 'left' }; -export const red = { color: 'red' }; +export const red = { color: 'red', float: 'left' }; export const tradePanelAccount = { float: 'right' }; diff --git a/static/css/_panel.scss b/static/css/_panel.scss index 56037bc5df..e4b7dcd604 100644 --- a/static/css/_panel.scss +++ b/static/css/_panel.scss @@ -53,7 +53,7 @@ $disabled-color: #F2F2F2; margin-bottom: 1em; } p { - margin: 0em; + margin: 0em; } #sync-warning { font-size: 11px; From 25b5e53a33525c8aa812eb25abf7c0ea32ce4b4b Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Fri, 3 May 2019 11:33:48 +0800 Subject: [PATCH 16/17] added translate and fixed style --- src/botPage/view/TradeInfoPanel/TradeTable.js | 13 +++++++------ src/botPage/view/style.js | 8 ++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index fd19493c6e..76cda663aa 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -1,4 +1,3 @@ -/* eslint-disable no-debugger */ import json2csv from 'json2csv'; import React, { Component } from 'react'; import ReactDataGrid from 'react-data-grid'; @@ -30,8 +29,10 @@ const getTimestamp = date => { const minHeight = 290; const rowHeight = 25; -const ProfitColor = ({ value }) =>
0 ? style.green : style.red}>{value}
; -const StatusColor = ({ value }) =>
{value}
; +const ProfitColor = ({ value }) =>
0 ? style.greenLeft : style.redLeft}>{value}
; +const StatusColor = ({ value }) => ( +
{value}
+); export default class TradeTable extends Component { constructor({ accountID }) { @@ -54,7 +55,7 @@ export default class TradeTable extends Component { { key: 'exit_tick', width: 75, resizable: true, name: translate('Exit spot') }, { key: 'buy_price', width: 80, resizable: true, name: translate('Buy price') }, { key: 'profit', width: 80, resizable: true, name: translate('Profit/Loss'), formatter: ProfitColor }, - { key: 'contract_status', width: 65, resizable: true, name: translate('Status'), formatter: StatusColor }, + { key: 'contract_status', width: 70, resizable: true, name: translate('Status'), formatter: StatusColor }, ]; } componentWillMount() { @@ -87,7 +88,7 @@ export default class TradeTable extends Component { const trade = { ...tradeObj, profit : getProfit(tradeObj), - contract_status: 'Pending', + contract_status: translate('Pending'), }; const accountStat = this.getAccountStat(accountID); @@ -133,7 +134,7 @@ export default class TradeTable extends Component { const { reference } = row; if (reference === trade.reference) { return { - contract_status: 'Settled', + contract_status: translate('Settled'), reference, ...trade, }; diff --git a/src/botPage/view/style.js b/src/botPage/view/style.js index dbc1cea536..522502c9e5 100644 --- a/src/botPage/view/style.js +++ b/src/botPage/view/style.js @@ -73,9 +73,13 @@ export const bottomWarning = { export const bottomWarningLink = { textDecoration: 'underline' }; -export const green = { color: 'green', float: 'left' }; +export const green = { color: 'green' }; -export const red = { color: 'red', float: 'left' }; +export const greenLeft = { color: 'green', float: 'left' }; + +export const red = { color: 'red' }; + +export const redLeft = { color: 'red', float: 'left' }; export const tradePanelAccount = { float: 'right' }; From 65cedfb8bd145bb6a904e3684e8764ba7c17f4e7 Mon Sep 17 00:00:00 2001 From: Khalid Ibrahim Date: Mon, 6 May 2019 12:20:21 +0800 Subject: [PATCH 17/17] status color --- src/botPage/view/TradeInfoPanel/TradeTable.js | 6 ++---- src/botPage/view/style.js | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index 76cda663aa..adb7881c28 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -30,9 +30,7 @@ const minHeight = 290; const rowHeight = 25; const ProfitColor = ({ value }) =>
0 ? style.greenLeft : style.redLeft}>{value}
; -const StatusColor = ({ value }) => ( -
{value}
-); +const StatusFormat = ({ value }) =>
{value}
; export default class TradeTable extends Component { constructor({ accountID }) { @@ -55,7 +53,7 @@ export default class TradeTable extends Component { { key: 'exit_tick', width: 75, resizable: true, name: translate('Exit spot') }, { key: 'buy_price', width: 80, resizable: true, name: translate('Buy price') }, { key: 'profit', width: 80, resizable: true, name: translate('Profit/Loss'), formatter: ProfitColor }, - { key: 'contract_status', width: 70, resizable: true, name: translate('Status'), formatter: StatusColor }, + { key: 'contract_status', width: 70, resizable: true, name: translate('Status'), formatter: StatusFormat }, ]; } componentWillMount() { diff --git a/src/botPage/view/style.js b/src/botPage/view/style.js index 522502c9e5..ca2935034c 100644 --- a/src/botPage/view/style.js +++ b/src/botPage/view/style.js @@ -83,6 +83,8 @@ export const redLeft = { color: 'red', float: 'left' }; export const tradePanelAccount = { float: 'right' }; +export const left = { float: 'left' }; + export const warningText = { 'font-size': '12px', color : 'lightgray',