From e0022d95adccacb1e6c69605ae3c0d10d08a6ea1 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 11:46:27 +0800 Subject: [PATCH 1/9] Keep track of bot is_running status globally --- src/botPage/bot/Interpreter.js | 4 +++- src/botPage/bot/TradeEngine/index.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/botPage/bot/Interpreter.js b/src/botPage/bot/Interpreter.js index 57854d4428..f7e13d06ae 100644 --- a/src/botPage/bot/Interpreter.js +++ b/src/botPage/bot/Interpreter.js @@ -149,8 +149,10 @@ export default class Interpreter { } terminateSession() { this.$scope.api.disconnect(); - globalObserver.emit('bot.stop'); this.stopped = true; + + globalObserver.emit('bot.stop'); + globalObserver.setState({ is_running: false }); } stop() { if (this.bot.tradeEngine.isSold === false && !this.isErrorTriggered) { diff --git a/src/botPage/bot/TradeEngine/index.js b/src/botPage/bot/TradeEngine/index.js index aaec4f3c65..015b215d1f 100644 --- a/src/botPage/bot/TradeEngine/index.js +++ b/src/botPage/bot/TradeEngine/index.js @@ -92,6 +92,7 @@ export default class TradeEngine extends Balance(Purchase(Sell(OpenContract(Prop } globalObserver.emit('bot.running'); + globalObserver.setState({ is_running: true }); this.tradeOptions = expectTradeOptions(tradeOptions); From 4527c2d001a83c5a17d188f07bb43b7448013046 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 11:48:33 +0800 Subject: [PATCH 2/9] Ensure correct button status --- src/botPage/view/View.js | 52 ++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index 690a9552ae..4788e81aba 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -511,11 +511,17 @@ export default class View { }); const startBot = limitations => { - const $runButtons = $('#runButton, #summaryRunButton'); - const $stopButtons = $('#stopButton, #summaryStopButton'); - $stopButtons.show(); - $runButtons.hide(); - $runButtons.prop('disabled', true); + const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); + const el_stop_buttons = document.querySelectorAll('#stopButton, #summaryStopButton'); + + el_run_buttons.forEach(el_run_button => { + el_run_button.style.display = 'none'; + el_run_button.setAttributeNode(document.createAttribute('disabled')); + }); + el_stop_buttons.forEach(el_stop_button => { + el_stop_button.style.display = 'initial'; + }); + globalObserver.emit('summary.disable_clear'); showSummary(); this.blockly.run(limitations); @@ -627,6 +633,9 @@ export default class View { this.blockly.stop(); } addEventHandlers() { + const getRunButtonElements = () => document.querySelectorAll('#runButton, #summaryRunButton'); + const getStopButtonElements = () => document.querySelectorAll('#stopButton, #summaryStopButton'); + window.addEventListener('storage', e => { window.onbeforeunload = null; if (e.key === 'activeToken' && !e.newValue) window.location.reload(); @@ -634,7 +643,8 @@ export default class View { }); globalObserver.register('Error', error => { - $('#runButton, #summaryRunButton').prop('disabled', false); + getRunButtonElements().forEach(el_run_button => el_run_button.removeAttribute('disabled')); + if (error.error && error.error.error.code === 'InvalidToken') { removeAllTokens(); updateTokenList(); @@ -642,16 +652,28 @@ export default class View { } }); + globalObserver.register('bot.running', () => { + getRunButtonElements().forEach(el_run_button => { + el_run_button.style.display = 'none'; + el_run_button.setAttributeNode(document.createAttribute('disabled')); + }); + getStopButtonElements().forEach(el_stop_button => { + el_stop_button.style.display = 'inline-block'; + el_stop_button.removeAttribute('disabled'); + }); + }); + globalObserver.register('bot.stop', () => { - const $runButtons = $('#runButton, #summaryRunButton'); - const $stopButtons = $('#stopButton, #summaryStopButton'); - if ($runButtons.is(':visible') || $stopButtons.is(':visible')) { - $runButtons.show(); - $stopButtons.hide(); - - $stopButtons.prop('disabled', false); - $runButtons.prop('disabled', false); - } + // Enable run button, this event is emitted after the interpreter + // killed the API connection. + getStopButtonElements().forEach(el_stop_button => { + el_stop_button.style.display = 'none'; + el_stop_button.removeAttribute('disabled'); + }); + getRunButtonElements().forEach(el_run_button => { + el_run_button.style.display = null; + el_run_button.removeAttribute('disabled'); + }); }); globalObserver.register('bot.info', info => { From f5cc80cfddf0933b5a7cc125be395c5433b803da Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 11:50:26 +0800 Subject: [PATCH 3/9] Refactor disableRunButton function --- src/botPage/view/blockly/blocks/shared.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/botPage/view/blockly/blocks/shared.js b/src/botPage/view/blockly/blocks/shared.js index 80406ad6e2..cf16369302 100644 --- a/src/botPage/view/blockly/blocks/shared.js +++ b/src/botPage/view/blockly/blocks/shared.js @@ -410,6 +410,21 @@ export const getPredictionForContracts = (contracts, selectedContractType) => { return predictionRange; }; -export const disableRunButton = isDisabled => { - $('#runButton, #summaryRunButton').attr('disabled', isDisabled); +export const disableRunButton = should_disable => { + const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); + const is_running = globalObserver.getState('is_running'); + + el_run_buttons.forEach(el_run_button => { + if (is_running) { + if (should_disable) { + el_run_button.setAttributeNode(document.createAttribute('disabled')); + } else { + // Do not enable. The bot is running. + } + } else if (should_disable) { + el_run_button.setAttributeNode(document.createAttribute('disabled')); + } else { + el_run_button.removeAttribute('disabled'); + } + }); }; From 280a90224c4d02b5115db8412913e80bfe0dc774 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 11:52:32 +0800 Subject: [PATCH 4/9] Restore display on stopBeforeStart --- src/botPage/view/blockly/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/botPage/view/blockly/index.js b/src/botPage/view/blockly/index.js index f5d9c60fd4..880251f950 100644 --- a/src/botPage/view/blockly/index.js +++ b/src/botPage/view/blockly/index.js @@ -440,7 +440,11 @@ while(true) { } stop(stopBeforeStart) { if (!stopBeforeStart) { - $('#stopButton, #summaryStopButton').prop('disabled', true); + const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); + const el_stop_buttons = document.querySelectorAll('#stopButton, #summaryStopButton'); + + el_run_buttons.forEach(el_run_button => (el_run_button.style.display = 'initial')); + el_stop_buttons.forEach(el_stop_button => (el_stop_button.style.display = 'none')); } if (this.interpreter) { this.interpreter.stop(); From e550184705cf87111ae056b3f55c496669caccdb Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 12:00:02 +0800 Subject: [PATCH 5/9] Convert everything to camelCase --- src/botPage/bot/Interpreter.js | 2 +- src/botPage/bot/TradeEngine/index.js | 2 +- src/botPage/view/View.js | 46 +++++++++++++---------- src/botPage/view/blockly/blocks/shared.js | 22 +++++------ src/botPage/view/blockly/index.js | 14 +++++-- 5 files changed, 49 insertions(+), 37 deletions(-) diff --git a/src/botPage/bot/Interpreter.js b/src/botPage/bot/Interpreter.js index f7e13d06ae..1f0959e5a1 100644 --- a/src/botPage/bot/Interpreter.js +++ b/src/botPage/bot/Interpreter.js @@ -152,7 +152,7 @@ export default class Interpreter { this.stopped = true; globalObserver.emit('bot.stop'); - globalObserver.setState({ is_running: false }); + globalObserver.setState({ isRunning: false }); } stop() { if (this.bot.tradeEngine.isSold === false && !this.isErrorTriggered) { diff --git a/src/botPage/bot/TradeEngine/index.js b/src/botPage/bot/TradeEngine/index.js index 015b215d1f..8ad3f62180 100644 --- a/src/botPage/bot/TradeEngine/index.js +++ b/src/botPage/bot/TradeEngine/index.js @@ -92,7 +92,7 @@ export default class TradeEngine extends Balance(Purchase(Sell(OpenContract(Prop } globalObserver.emit('bot.running'); - globalObserver.setState({ is_running: true }); + globalObserver.setState({ isRunning: true }); this.tradeOptions = expectTradeOptions(tradeOptions); diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index 4788e81aba..bae088a63c 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -511,15 +511,17 @@ export default class View { }); const startBot = limitations => { - const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); - const el_stop_buttons = document.querySelectorAll('#stopButton, #summaryStopButton'); + const elRunButtons = document.querySelectorAll('#runButton, #summaryRunButton'); + const elStopButtons = document.querySelectorAll('#stopButton, #summaryStopButton'); - el_run_buttons.forEach(el_run_button => { - el_run_button.style.display = 'none'; - el_run_button.setAttributeNode(document.createAttribute('disabled')); + elRunButtons.forEach(el => { + const elRunButton = el; + elRunButton.style.display = 'none'; + elRunButton.setAttributeNode(document.createAttribute('disabled')); }); - el_stop_buttons.forEach(el_stop_button => { - el_stop_button.style.display = 'initial'; + elStopButtons.forEach(el => { + const elStopButton = el; + elStopButton.style.display = 'initial'; }); globalObserver.emit('summary.disable_clear'); @@ -643,7 +645,7 @@ export default class View { }); globalObserver.register('Error', error => { - getRunButtonElements().forEach(el_run_button => el_run_button.removeAttribute('disabled')); + getRunButtonElements().forEach(elRunButton => elRunButton.removeAttribute('disabled')); if (error.error && error.error.error.code === 'InvalidToken') { removeAllTokens(); @@ -653,26 +655,30 @@ export default class View { }); globalObserver.register('bot.running', () => { - getRunButtonElements().forEach(el_run_button => { - el_run_button.style.display = 'none'; - el_run_button.setAttributeNode(document.createAttribute('disabled')); + getRunButtonElements().forEach(el => { + const elRunButton = el; + elRunButton.style.display = 'none'; + elRunButton.setAttributeNode(document.createAttribute('disabled')); }); - getStopButtonElements().forEach(el_stop_button => { - el_stop_button.style.display = 'inline-block'; - el_stop_button.removeAttribute('disabled'); + getStopButtonElements().forEach(el => { + const elStopButton = el; + elStopButton.style.display = 'inline-block'; + elStopButton.removeAttribute('disabled'); }); }); globalObserver.register('bot.stop', () => { // Enable run button, this event is emitted after the interpreter // killed the API connection. - getStopButtonElements().forEach(el_stop_button => { - el_stop_button.style.display = 'none'; - el_stop_button.removeAttribute('disabled'); + getStopButtonElements().forEach(el => { + const elStopButton = el; + elStopButton.style.display = 'none'; + elStopButton.removeAttribute('disabled'); }); - getRunButtonElements().forEach(el_run_button => { - el_run_button.style.display = null; - el_run_button.removeAttribute('disabled'); + getRunButtonElements().forEach(el => { + const elRunButton = el; + elRunButton.style.display = null; + elRunButton.removeAttribute('disabled'); }); }); diff --git a/src/botPage/view/blockly/blocks/shared.js b/src/botPage/view/blockly/blocks/shared.js index cf16369302..7e5ed841fe 100644 --- a/src/botPage/view/blockly/blocks/shared.js +++ b/src/botPage/view/blockly/blocks/shared.js @@ -410,21 +410,21 @@ export const getPredictionForContracts = (contracts, selectedContractType) => { return predictionRange; }; -export const disableRunButton = should_disable => { - const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); - const is_running = globalObserver.getState('is_running'); - - el_run_buttons.forEach(el_run_button => { - if (is_running) { - if (should_disable) { - el_run_button.setAttributeNode(document.createAttribute('disabled')); +export const disableRunButton = shouldDisable => { + const elRunButtons = document.querySelectorAll('#runButton, #summaryRunButton'); + const isRunning = globalObserver.getState('isRunning'); + + elRunButtons.forEach(elRunButton => { + if (isRunning) { + if (shouldDisable) { + elRunButton.setAttributeNode(document.createAttribute('disabled')); } else { // Do not enable. The bot is running. } - } else if (should_disable) { - el_run_button.setAttributeNode(document.createAttribute('disabled')); + } else if (shouldDisable) { + elRunButton.setAttributeNode(document.createAttribute('disabled')); } else { - el_run_button.removeAttribute('disabled'); + elRunButton.removeAttribute('disabled'); } }); }; diff --git a/src/botPage/view/blockly/index.js b/src/botPage/view/blockly/index.js index 880251f950..cf92dd5e2c 100644 --- a/src/botPage/view/blockly/index.js +++ b/src/botPage/view/blockly/index.js @@ -440,11 +440,17 @@ while(true) { } stop(stopBeforeStart) { if (!stopBeforeStart) { - const el_run_buttons = document.querySelectorAll('#runButton, #summaryRunButton'); - const el_stop_buttons = document.querySelectorAll('#stopButton, #summaryStopButton'); + const elRunButtons = document.querySelectorAll('#runButton, #summaryRunButton'); + const elStopButtons = document.querySelectorAll('#stopButton, #summaryStopButton'); - el_run_buttons.forEach(el_run_button => (el_run_button.style.display = 'initial')); - el_stop_buttons.forEach(el_stop_button => (el_stop_button.style.display = 'none')); + elRunButtons.forEach(el => { + const elRunButton = el; + elRunButton.style.display = 'initial'; + }); + elStopButtons.forEach(el => { + const elStopButton = el; + elStopButton.style.display = null; + }); } if (this.interpreter) { this.interpreter.stop(); From b603e314cc9ef80dcf47be5ca91c863cc13d692f Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 13:19:33 +0800 Subject: [PATCH 6/9] Don't manipulate passed argument directly --- src/botPage/view/View.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index bae088a63c..3f5ed7f976 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -645,7 +645,10 @@ export default class View { }); globalObserver.register('Error', error => { - getRunButtonElements().forEach(elRunButton => elRunButton.removeAttribute('disabled')); + getRunButtonElements().forEach(el => { + const elRunButton = el; + elRunButton.removeAttribute('disabled'); + }); if (error.error && error.error.error.code === 'InvalidToken') { removeAllTokens(); From 481305dc860cc78952f9991a847ce43fb89c977f Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 13:19:55 +0800 Subject: [PATCH 7/9] Set #summaryStopButton to display: none by default --- static/css/bot.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/css/bot.scss b/static/css/bot.scss index a4a2063f26..76111ace27 100644 --- a/static/css/bot.scss +++ b/static/css/bot.scss @@ -169,7 +169,7 @@ body { background: black; } -#stopButton { +#stopButton, #summaryStopButton { display: none; } From a2c80015ef3ec31812683c460ae7d8243f7e6ef0 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 13:35:13 +0800 Subject: [PATCH 8/9] Be consistent in display values --- src/botPage/view/View.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index 3f5ed7f976..3000071b5f 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -521,7 +521,7 @@ export default class View { }); elStopButtons.forEach(el => { const elStopButton = el; - elStopButton.style.display = 'initial'; + elStopButton.style.display = 'inline-block'; }); globalObserver.emit('summary.disable_clear'); @@ -675,7 +675,7 @@ export default class View { // killed the API connection. getStopButtonElements().forEach(el => { const elStopButton = el; - elStopButton.style.display = 'none'; + elStopButton.style.display = null; elStopButton.removeAttribute('disabled'); }); getRunButtonElements().forEach(el => { From a62ebcae910c5034cec6b39c87a95b3fa7c4ebf3 Mon Sep 17 00:00:00 2001 From: Aaron Imming Date: Tue, 9 Jul 2019 11:44:53 +0800 Subject: [PATCH 9/9] Create global state in observer --- src/common/utils/observer.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/utils/observer.js b/src/common/utils/observer.js index 9fded6642a..d0f06d51f6 100644 --- a/src/common/utils/observer.js +++ b/src/common/utils/observer.js @@ -3,6 +3,7 @@ import { Map, List } from 'immutable'; export default class Observer { constructor() { this.eam = new Map(); // event action map + this.state = {}; } register(event, _action, once, unregisterIfError, unregisterAllBefore) { if (unregisterAllBefore) { @@ -53,6 +54,12 @@ export default class Observer { this.eam.get(event).forEach(action => action.action(data)); } } + setState(state = {}) { + this.state = Object.assign({}, this.state, state); + } + getState(key) { + return this.state[key]; + } } export const observer = new Observer();