From 5b9b22cbd0e486cfd50bc41990c424207f5133ac Mon Sep 17 00:00:00 2001 From: lowwor Date: Tue, 28 May 2019 14:54:43 +0800 Subject: [PATCH 1/7] feat: add show all to orders panel --- orko-ui/.gitignore | 2 + orko-ui/src/containers/OpenOrdersContainer.js | 7 ++- orko-ui/src/containers/OrdersContainer.js | 59 ++++++++++++------ orko-ui/src/selectors/coins.js | 62 ++++++++++++------- 4 files changed, 87 insertions(+), 43 deletions(-) diff --git a/orko-ui/.gitignore b/orko-ui/.gitignore index 61274b308..0cb070838 100644 --- a/orko-ui/.gitignore +++ b/orko-ui/.gitignore @@ -21,3 +21,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* /target/ + +.idea \ No newline at end of file diff --git a/orko-ui/src/containers/OpenOrdersContainer.js b/orko-ui/src/containers/OpenOrdersContainer.js index 3776a89f7..4c41a55bc 100644 --- a/orko-ui/src/containers/OpenOrdersContainer.js +++ b/orko-ui/src/containers/OpenOrdersContainer.js @@ -23,7 +23,7 @@ import WithCoin from "./WithCoin" import WhileLoading from "../components/WhileLoading" import * as exchangeActions from "../store/exchanges/actions" import * as jobActions from "../store/job/actions" -import { getOrdersForSelectedCoin } from "../selectors/coins" +import { getOrdersForAllCoin, getOrdersForSelectedCoin } from '../selectors/coins' class OpenOrdersContainer extends React.Component { onCancelExchange = (id, coin) => { @@ -42,7 +42,7 @@ class OpenOrdersContainer extends React.Component { {() => ( this.onCancelExchange(id, coin)} onCancelServer={this.onCancelServer} onWatch={this.onWatch} @@ -59,7 +59,8 @@ class OpenOrdersContainer extends React.Component { function mapStateToProps(state, props) { return { - orders: getOrdersForSelectedCoin(state) + orders: getOrdersForSelectedCoin(state), + allOrders: getOrdersForAllCoin(state) } } diff --git a/orko-ui/src/containers/OrdersContainer.js b/orko-ui/src/containers/OrdersContainer.js index a6c0b05bb..27355a507 100644 --- a/orko-ui/src/containers/OrdersContainer.js +++ b/orko-ui/src/containers/OrdersContainer.js @@ -15,40 +15,61 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import React from "react" -import Section from "../components/primitives/Section" -import Tab from "../components/primitives/Tab" -import OpenOrdersContainer from "./OpenOrdersContainer" -import UserTradeHistoryContainer from "./UserTradeHistoryContainer" -import GetPageVisibility from "../components/GetPageVisibility" -import RenderIf from "../components/RenderIf" +import React from 'react' +import Section from '../components/primitives/Section' +import Tab from '../components/primitives/Tab' +import OpenOrdersContainer from './OpenOrdersContainer' +import UserTradeHistoryContainer from './UserTradeHistoryContainer' +import GetPageVisibility from '../components/GetPageVisibility' +import RenderIf from '../components/RenderIf' +import { Checkbox } from 'semantic-ui-react' +import { getValueFromLS, saveValueToLS } from '../util/localStorage' + +const ORDER_STORAGE_KEY = 'OrdersContainer.order_show_all' class OrdersContainer extends React.Component { - constructor(props) { + constructor (props) { super(props) - this.state = { selected: "open" } + var showAll = getValueFromLS(ORDER_STORAGE_KEY) !== 'false' + if (showAll === null) showAll = false + this.state = { + selected: 'open', + showAll + } } buttons = () => ( + { + this.setState( + prev => ({showAll: !prev.showAll}), + () => saveValueToLS(ORDER_STORAGE_KEY, this.state.showAll) + ) + }} + title="Show orders for all coins or selected coins" + > + Show All + this.setState({ selected: "open" })} - title="Show open orders for the selected coin" + selected={this.state.selected === 'open'} + onClick={() => this.setState({selected: 'open'})} + title={this.state.showAll ? 'Show open orders for all coin' : 'Show open orders for the selected coin'} > Open this.setState({ selected: "history" })} - title="Show order history for the selected coin" + selected={this.state.selected === 'history'} + onClick={() => this.setState({selected: 'history'})} + title={this.state.showAll ? 'Show order history for all coin' : 'Show order history for the selected coin'} > History ) - render() { + render () { return ( {visible => ( @@ -59,10 +80,10 @@ class OrdersContainer extends React.Component { heading="Orders" buttons={this.buttons} > - {this.state.selected === "open" ? ( - + {this.state.selected === 'open' ? ( + ) : ( - + )} diff --git a/orko-ui/src/selectors/coins.js b/orko-ui/src/selectors/coins.js index 17fdd1d55..f434cb67b 100644 --- a/orko-ui/src/selectors/coins.js +++ b/orko-ui/src/selectors/coins.js @@ -65,6 +65,30 @@ function jobTriggerMatchesCoin(job, coin) { ) } +function serverJobDecorate(job) { + return { + runningAt: "SERVER", + jobId: job.id, + type: job.high + ? job.high.job.direction === "BUY" + ? "BID" + : "ASK" + : job.low.job.direction === "BUY" + ? "BID" + : "ASK", + stopPrice: job.high + ? Number(job.high.thresholdAsString) + : Number(job.low.thresholdAsString), + limitPrice: job.high + ? Number(job.high.job.limitPrice) + : Number(job.low.job.limitPrice), + originalAmount: job.high + ? Number(job.high.job.amount) + : Number(job.low.job.amount), + cumulativeAmount: "--" + } +} + export const getOrdersForSelectedCoin = createSelector( [getOrders, getStopJobs, getSelectedCoin], (orders, stopJobs, selectedCoin) => { @@ -74,27 +98,23 @@ export const getOrdersForSelectedCoin = createSelector( const server = stopJobs .filter(job => jobTriggerMatchesCoin(job, selectedCoin)) - .map(job => ({ - runningAt: "SERVER", - jobId: job.id, - type: job.high - ? job.high.job.direction === "BUY" - ? "BID" - : "ASK" - : job.low.job.direction === "BUY" - ? "BID" - : "ASK", - stopPrice: job.high - ? Number(job.high.thresholdAsString) - : Number(job.low.thresholdAsString), - limitPrice: job.high - ? Number(job.high.job.limitPrice) - : Number(job.low.job.limitPrice), - originalAmount: job.high - ? Number(job.high.job.amount) - : Number(job.low.job.amount), - cumulativeAmount: "--" - })) + .map(job => serverJobDecorate(job)) + + result = result.concat(server) + + if (result.length === 0 && !orders) return null + + return result + } +) + +export const getOrdersForAllCoin = createSelector( + [getOrders, getStopJobs], + (orders, stopJobs) => { + var result = !orders ? [] : orders.filter(o => !o.deleted) + + const server = stopJobs + .map(job => serverJobDecorate(job)) result = result.concat(server) From eee414bdfa9190520f71d25727e6292c2705ec03 Mon Sep 17 00:00:00 2001 From: lowwor Date: Tue, 28 May 2019 15:03:10 +0800 Subject: [PATCH 2/7] fix: fix unused import --- orko-ui/src/containers/OrdersContainer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/orko-ui/src/containers/OrdersContainer.js b/orko-ui/src/containers/OrdersContainer.js index 27355a507..fb7083f49 100644 --- a/orko-ui/src/containers/OrdersContainer.js +++ b/orko-ui/src/containers/OrdersContainer.js @@ -22,7 +22,6 @@ import OpenOrdersContainer from './OpenOrdersContainer' import UserTradeHistoryContainer from './UserTradeHistoryContainer' import GetPageVisibility from '../components/GetPageVisibility' import RenderIf from '../components/RenderIf' -import { Checkbox } from 'semantic-ui-react' import { getValueFromLS, saveValueToLS } from '../util/localStorage' const ORDER_STORAGE_KEY = 'OrdersContainer.order_show_all' From ab28ca5491458fd5fde5b05e743908ab680a566f Mon Sep 17 00:00:00 2001 From: lowwor Date: Tue, 28 May 2019 15:34:13 +0800 Subject: [PATCH 3/7] style: add prettier to dev and reformat --- orko-ui/package-lock.json | 37 ++++------ orko-ui/package.json | 2 +- orko-ui/src/containers/OpenOrdersContainer.js | 11 ++- orko-ui/src/containers/OrdersContainer.js | 70 +++++++++++-------- orko-ui/src/selectors/coins.js | 7 +- 5 files changed, 66 insertions(+), 61 deletions(-) diff --git a/orko-ui/package-lock.json b/orko-ui/package-lock.json index 2f0365f76..045c7dbc3 100644 --- a/orko-ui/package-lock.json +++ b/orko-ui/package-lock.json @@ -10043,8 +10043,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -10081,8 +10080,7 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", @@ -10091,8 +10089,7 @@ }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -10195,8 +10192,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -10206,7 +10202,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -10232,7 +10227,6 @@ "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -10249,7 +10243,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -10333,7 +10326,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -10409,8 +10401,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -10440,7 +10431,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -10458,7 +10448,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -10497,13 +10486,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } } @@ -11969,7 +11956,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -11978,8 +11964,7 @@ "yallist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "optional": true + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" } } }, @@ -16914,6 +16899,12 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, + "prettier": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.1.tgz", + "integrity": "sha512-TzGRNvuUSmPgwivDqkZ9tM/qTGW9hqDKWOE9YHiyQdixlKbv7kvEqsmDPrcHJTKwthU774TQwZXVtaQ/mMsvjg==", + "dev": true + }, "pretty-bytes": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.2.0.tgz", diff --git a/orko-ui/package.json b/orko-ui/package.json index e1f9f52d1..8004d9fa1 100644 --- a/orko-ui/package.json +++ b/orko-ui/package.json @@ -55,6 +55,6 @@ ], "devDependencies": { "gulp": "^4.0.2", - "fomantic-ui": "^2.7.5" + "prettier": "1.17.1" } } diff --git a/orko-ui/src/containers/OpenOrdersContainer.js b/orko-ui/src/containers/OpenOrdersContainer.js index 4c41a55bc..ec771af91 100644 --- a/orko-ui/src/containers/OpenOrdersContainer.js +++ b/orko-ui/src/containers/OpenOrdersContainer.js @@ -23,7 +23,10 @@ import WithCoin from "./WithCoin" import WhileLoading from "../components/WhileLoading" import * as exchangeActions from "../store/exchanges/actions" import * as jobActions from "../store/job/actions" -import { getOrdersForAllCoin, getOrdersForSelectedCoin } from '../selectors/coins' +import { + getOrdersForAllCoin, + getOrdersForSelectedCoin +} from "../selectors/coins" class OpenOrdersContainer extends React.Component { onCancelExchange = (id, coin) => { @@ -42,7 +45,11 @@ class OpenOrdersContainer extends React.Component { {() => ( this.onCancelExchange(id, coin)} onCancelServer={this.onCancelServer} onWatch={this.onWatch} diff --git a/orko-ui/src/containers/OrdersContainer.js b/orko-ui/src/containers/OrdersContainer.js index fb7083f49..eab2d542d 100644 --- a/orko-ui/src/containers/OrdersContainer.js +++ b/orko-ui/src/containers/OrdersContainer.js @@ -15,60 +15,68 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import React from 'react' -import Section from '../components/primitives/Section' -import Tab from '../components/primitives/Tab' -import OpenOrdersContainer from './OpenOrdersContainer' -import UserTradeHistoryContainer from './UserTradeHistoryContainer' -import GetPageVisibility from '../components/GetPageVisibility' -import RenderIf from '../components/RenderIf' -import { getValueFromLS, saveValueToLS } from '../util/localStorage' +import React from "react" +import Section from "../components/primitives/Section" +import Tab from "../components/primitives/Tab" +import OpenOrdersContainer from "./OpenOrdersContainer" +import UserTradeHistoryContainer from "./UserTradeHistoryContainer" +import GetPageVisibility from "../components/GetPageVisibility" +import RenderIf from "../components/RenderIf" +import { getValueFromLS, saveValueToLS } from "../util/localStorage" -const ORDER_STORAGE_KEY = 'OrdersContainer.order_show_all' +const ORDER_STORAGE_KEY = "OrdersContainer.order_show_all" class OrdersContainer extends React.Component { - constructor (props) { + constructor(props) { super(props) - var showAll = getValueFromLS(ORDER_STORAGE_KEY) !== 'false' + var showAll = getValueFromLS(ORDER_STORAGE_KEY) !== "false" if (showAll === null) showAll = false this.state = { - selected: 'open', + selected: "open", showAll } } buttons = () => ( - { - this.setState( - prev => ({showAll: !prev.showAll}), - () => saveValueToLS(ORDER_STORAGE_KEY, this.state.showAll) - ) - }} - title="Show orders for all coins or selected coins" + { + this.setState( + prev => ({ showAll: !prev.showAll }), + () => saveValueToLS(ORDER_STORAGE_KEY, this.state.showAll) + ) + }} + title="Show orders for all coins or selected coins" > Show All this.setState({selected: 'open'})} - title={this.state.showAll ? 'Show open orders for all coin' : 'Show open orders for the selected coin'} + selected={this.state.selected === "open"} + onClick={() => this.setState({ selected: "open" })} + title={ + this.state.showAll + ? "Show open orders for all coin" + : "Show open orders for the selected coin" + } > Open this.setState({selected: 'history'})} - title={this.state.showAll ? 'Show order history for all coin' : 'Show order history for the selected coin'} + selected={this.state.selected === "history"} + onClick={() => this.setState({ selected: "history" })} + title={ + this.state.showAll + ? "Show order history for all coin" + : "Show order history for the selected coin" + } > History ) - render () { + render() { return ( {visible => ( @@ -79,10 +87,10 @@ class OrdersContainer extends React.Component { heading="Orders" buttons={this.buttons} > - {this.state.selected === 'open' ? ( - + {this.state.selected === "open" ? ( + ) : ( - + )} diff --git a/orko-ui/src/selectors/coins.js b/orko-ui/src/selectors/coins.js index f434cb67b..2152b4b45 100644 --- a/orko-ui/src/selectors/coins.js +++ b/orko-ui/src/selectors/coins.js @@ -74,8 +74,8 @@ function serverJobDecorate(job) { ? "BID" : "ASK" : job.low.job.direction === "BUY" - ? "BID" - : "ASK", + ? "BID" + : "ASK", stopPrice: job.high ? Number(job.high.thresholdAsString) : Number(job.low.thresholdAsString), @@ -113,8 +113,7 @@ export const getOrdersForAllCoin = createSelector( (orders, stopJobs) => { var result = !orders ? [] : orders.filter(o => !o.deleted) - const server = stopJobs - .map(job => serverJobDecorate(job)) + const server = stopJobs.map(job => serverJobDecorate(job)) result = result.concat(server) From 80d6e5a9441b79034068c9243a245be3cd668bae Mon Sep 17 00:00:00 2001 From: lowwor Date: Tue, 28 May 2019 16:19:22 +0800 Subject: [PATCH 4/7] perf: improve orders fetching --- orko-ui/src/containers/OpenOrdersContainer.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/orko-ui/src/containers/OpenOrdersContainer.js b/orko-ui/src/containers/OpenOrdersContainer.js index ec771af91..c85219550 100644 --- a/orko-ui/src/containers/OpenOrdersContainer.js +++ b/orko-ui/src/containers/OpenOrdersContainer.js @@ -45,11 +45,7 @@ class OpenOrdersContainer extends React.Component { {() => ( this.onCancelExchange(id, coin)} onCancelServer={this.onCancelServer} onWatch={this.onWatch} @@ -66,8 +62,9 @@ class OpenOrdersContainer extends React.Component { function mapStateToProps(state, props) { return { - orders: getOrdersForSelectedCoin(state), - allOrders: getOrdersForAllCoin(state) + orders: this.props.showAll + ? getOrdersForAllCoin(state) + : getOrdersForSelectedCoin(state) } } From 6e744c2ef9437e71171b4c482aa801ae8ec33157 Mon Sep 17 00:00:00 2001 From: lowwor Date: Wed, 29 May 2019 10:27:31 +0800 Subject: [PATCH 5/7] fix: fix typo --- orko-ui/package.json | 1 + orko-ui/semantic.json | 2 +- orko-ui/src/containers/OpenOrdersContainer.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/orko-ui/package.json b/orko-ui/package.json index 8004d9fa1..b557e43e4 100644 --- a/orko-ui/package.json +++ b/orko-ui/package.json @@ -54,6 +54,7 @@ "not op_mini all" ], "devDependencies": { + "fomantic-ui": "^2.7.5", "gulp": "^4.0.2", "prettier": "1.17.1" } diff --git a/orko-ui/semantic.json b/orko-ui/semantic.json index 5a67bfa87..63806f5f6 100644 --- a/orko-ui/semantic.json +++ b/orko-ui/semantic.json @@ -19,5 +19,5 @@ "autoInstall": false, "rtl": false, "components": ["reset", "site", "button", "container", "divider", "flag", "header", "icon", "image", "input", "label", "list", "loader", "placeholder", "rail", "reveal", "segment", "step", "breadcrumb", "form", "grid", "menu", "message", "table", "ad", "card", "comment", "feed", "item", "statistic", "accordion", "checkbox", "dimmer", "dropdown", "embed", "modal", "nag", "popup", "progress", "rating", "search", "shape", "sidebar", "sticky", "tab", "transition", "api", "form", "state", "visibility"], - "version": "2.7.2" + "version": "2.7.5" } \ No newline at end of file diff --git a/orko-ui/src/containers/OpenOrdersContainer.js b/orko-ui/src/containers/OpenOrdersContainer.js index c85219550..e1015396a 100644 --- a/orko-ui/src/containers/OpenOrdersContainer.js +++ b/orko-ui/src/containers/OpenOrdersContainer.js @@ -62,7 +62,7 @@ class OpenOrdersContainer extends React.Component { function mapStateToProps(state, props) { return { - orders: this.props.showAll + orders: props.showAll ? getOrdersForAllCoin(state) : getOrdersForSelectedCoin(state) } From 1e3672ddb270482e64db5d0a5c3a9387ad7f468f Mon Sep 17 00:00:00 2001 From: lowwor Date: Wed, 12 Jun 2019 13:56:31 +0800 Subject: [PATCH 6/7] feat: add state update to all orders and add coin name and exchange column --- orko-ui/package-lock.json | 5 ++ orko-ui/package.json | 1 + orko-ui/src/App.js | 3 +- orko-ui/src/components/OpenOrders.js | 43 ++++++++++++ orko-ui/src/selectors/coins.js | 50 ++++++++++---- orko-ui/src/store/coin/actions.js | 4 +- orko-ui/src/store/coin/reducer.js | 97 +++++++++++++++++++--------- orko-ui/src/store/socket/connect.js | 55 ++++++++-------- orko-ui/src/worker/socket.client.js | 4 +- 9 files changed, 187 insertions(+), 75 deletions(-) diff --git a/orko-ui/package-lock.json b/orko-ui/package-lock.json index 045c7dbc3..c0cc975f4 100644 --- a/orko-ui/package-lock.json +++ b/orko-ui/package-lock.json @@ -17853,6 +17853,11 @@ "resolved": "https://registry.npmjs.org/redux-batched-actions/-/redux-batched-actions-0.4.1.tgz", "integrity": "sha512-r6tLDyBP3U9cXNLEHs0n1mX5TQfmk6xE0Y9uinYZ5HOyAWDgIJxYqRRkU/bC6XrJ4nS7tasNbxaHJHVmf9UdkA==" }, + "redux-devtools-extension": { + "version": "2.13.8", + "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz", + "integrity": "sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==" + }, "redux-thunk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", diff --git a/orko-ui/package.json b/orko-ui/package.json index b557e43e4..1b68cb3e0 100644 --- a/orko-ui/package.json +++ b/orko-ui/package.json @@ -26,6 +26,7 @@ "reconnecting-websocket": "^4.1.10", "redux": "^4.0.1", "redux-batched-actions": "^0.4.1", + "redux-devtools-extension": "^2.13.8", "redux-thunk": "^2.3.0", "reselect": "^4.0.0", "seamless-immutable": "^7.1.4", diff --git a/orko-ui/src/App.js b/orko-ui/src/App.js index 029d7bc58..e2a7b1c4a 100644 --- a/orko-ui/src/App.js +++ b/orko-ui/src/App.js @@ -36,6 +36,7 @@ import * as socket from "./store/socket/connect" import ErrorContainer from "./containers/ErrorContainer" import AuthContainer from "./containers/AuthContainer" import FrameworkContainer from "./FrameworkContainer" +import { composeWithDevTools } from "redux-devtools-extension" import * as authActions from "./store/auth/actions" @@ -43,7 +44,7 @@ const history = createHistory() const store = createStore( enableBatching(createRootReducer(history)), - compose( + composeWithDevTools( applyMiddleware(routerMiddleware(history), thunk.withExtraArgument(socket)) ) ) diff --git a/orko-ui/src/components/OpenOrders.js b/orko-ui/src/components/OpenOrders.js index 0e0d8b338..bb06a61d1 100644 --- a/orko-ui/src/components/OpenOrders.js +++ b/orko-ui/src/components/OpenOrders.js @@ -22,6 +22,7 @@ import Href from "../components/primitives/Href" import * as dateUtils from "../util/dateUtils" import Price from "../components/primitives/Price" import Amount from "../components/primitives/Amount" +import { Link } from "react-router-dom" const textStyle = { textAlign: "left" @@ -83,6 +84,46 @@ const runningAtColumn = { width: 32 } +const exchangeColumn = { + id: "exchange", + Header: "Exchange", + accessor: "exchange", + Cell: ({ original }) => ( + + {original.exchangeMeta + ? original.exchangeMeta.name + : original.coin.exchange} + + ), + headerStyle: textStyle, + style: textStyle, + resizable: true, + minWidth: 40 +} + +const nameColumn = { + id: "name", + Header: "Name", + accessor: "shortName", + Cell: ({ original }) => ( + + {original.coin.shortName} + + ), + headerStyle: textStyle, + style: textStyle, + resizable: true, + minWidth: 50 +} + const createdDateColumn = { id: "createdDate", accessor: "timestamp", @@ -228,6 +269,8 @@ const OpenOrders = props => ( cancelColumn(props.onCancelExchange, props.onCancelServer), orderTypeColumn, runningAtColumn, + exchangeColumn, + nameColumn, createdDateColumn, limitPriceColumn(props.coin), stopPriceColumn(props.coin), diff --git a/orko-ui/src/selectors/coins.js b/orko-ui/src/selectors/coins.js index 2152b4b45..769aa12b8 100644 --- a/orko-ui/src/selectors/coins.js +++ b/orko-ui/src/selectors/coins.js @@ -18,7 +18,7 @@ import { createSelector } from "reselect" import { getRouterLocation } from "./router" import { getAlertJobs, getStopJobs } from "./jobs" -import { coinFromKey } from "../util/coinUtils" +import { coinFromKey, coinFromTicker } from "../util/coinUtils" const getCoins = state => state.coins.coins const getReferencePrices = state => state.coins.referencePrices @@ -65,7 +65,14 @@ function jobTriggerMatchesCoin(job, coin) { ) } -function serverJobDecorate(job) { +function orderDecorate(order, exchanges) { + return { + ...order, + exchangeMeta: exchanges.find(e => e.code === order.coin.exchange) + } +} + +function serverJobDecorate(job, exchanges) { return { runningAt: "SERVER", jobId: job.id, @@ -85,40 +92,55 @@ function serverJobDecorate(job) { originalAmount: job.high ? Number(job.high.job.amount) : Number(job.low.job.amount), - cumulativeAmount: "--" + cumulativeAmount: "--", + coin: coinFromTicker(job.tickTrigger), + exchangeMeta: exchanges.find(e => e.code === job.tickTrigger.exchange) } } export const getOrdersForSelectedCoin = createSelector( - [getOrders, getStopJobs, getSelectedCoin], - (orders, stopJobs, selectedCoin) => { + [getOrders, getStopJobs, getExchanges, getSelectedCoin], + (orders, stopJobs, exchanges, selectedCoin) => { if (!selectedCoin) return null - - var result = !orders ? [] : orders.filter(o => !o.deleted) + var result = !(orders && orders[selectedCoin.key]) + ? [] + : orders[selectedCoin.key] + .filter(o => !o.deleted) + .map(order => orderDecorate(order, exchanges)) const server = stopJobs .filter(job => jobTriggerMatchesCoin(job, selectedCoin)) - .map(job => serverJobDecorate(job)) + .map(job => serverJobDecorate(job, exchanges)) result = result.concat(server) if (result.length === 0 && !orders) return null - return result } ) export const getOrdersForAllCoin = createSelector( - [getOrders, getStopJobs], - (orders, stopJobs) => { - var result = !orders ? [] : orders.filter(o => !o.deleted) + [getOrders, getStopJobs, getExchanges], + (orders, stopJobs, exchanges) => { + if (!orders) return null + let mergeOrders = [] + Object.keys(orders).forEach(function(key) { + orders[key].forEach(function(item) { + mergeOrders.push(item) + }) + }) - const server = stopJobs.map(job => serverJobDecorate(job)) + var result = !mergeOrders + ? [] + : mergeOrders + .filter(o => !o.deleted) + .map(order => orderDecorate(order, exchanges)) + + const server = stopJobs.map(job => serverJobDecorate(job, exchanges)) result = result.concat(server) if (result.length === 0 && !orders) return null - return result } ) diff --git a/orko-ui/src/store/coin/actions.js b/orko-ui/src/store/coin/actions.js index d836caf86..0679343db 100644 --- a/orko-ui/src/store/coin/actions.js +++ b/orko-ui/src/store/coin/actions.js @@ -45,8 +45,8 @@ export function clearBalances() { return { type: types.CLEAR_BALANCES } } -export function orderUpdated(order, timestamp) { - return { type: types.ORDER_UPDATED, payload: { order, timestamp } } +export function orderUpdated(coin, order, timestamp) { + return { type: types.ORDER_UPDATED, payload: { coin, order, timestamp } } } export function clearOrders() { diff --git a/orko-ui/src/store/coin/reducer.js b/orko-ui/src/store/coin/reducer.js index 235eb5705..84ba125a9 100644 --- a/orko-ui/src/store/coin/reducer.js +++ b/orko-ui/src/store/coin/reducer.js @@ -68,7 +68,12 @@ export default function reduce(state = initialState, action = {}) { userTradeHistory: undefined }) case types.ORDER_UPDATED: - return orderUpdated(state, action.payload.order, action.payload.timestamp) + return orderUpdated( + state, + action.payload.coin, + action.payload.order, + action.payload.timestamp + ) case types.CLEAR_ORDERS: return Immutable.merge(state, { orders: undefined @@ -90,52 +95,75 @@ export default function reduce(state = initialState, action = {}) { }) } - function orderUpdated(state, order, timestamp) { + function orderUpdated(state, coin, order, timestamp) { if (order === null) { - return Immutable.merge(state, { - orders: [] - }) + return Immutable.merge( + state, + { + orders: { + [coin.key]: [] + } + }, + { deep: true } + ) } + // add coin property to order + order.coin = coin + const isRemoval = order.status === "EXPIRED" || order.status === "CANCELED" || order.status === "FILLED" - // No orders at all yet - if (!state.orders) { + // No orders for this con at all yet + if (!state.orders[coin.key]) { if (isRemoval) return state - return Immutable.merge(state, { - orders: [ - { - ...order, - deleted: false, - serverTimestamp: timestamp + return Immutable.merge( + state, + { + orders: { + [coin.key]: [ + { + ...order, + deleted: false, + serverTimestamp: timestamp + } + ] } - ] - }) + }, + { deep: true } + ) } // This order never seen before - const index = state.orders.findIndex(o => o.id === order.id) + const index = state.orders[coin.key].findIndex(o => o.id === order.id) if (index === -1) { if (isRemoval) return state - return Immutable.merge(state, { - orders: state.orders.concat({ - ...order, - deleted: false, - serverTimestamp: timestamp - }) - }) + return Immutable.merge( + state, + { + orders: { + [coin.key]: [ + state.orders[coin.key].concat({ + ...order, + deleted: false, + serverTimestamp: timestamp + }) + ] + } + }, + { deep: true } + ) } // If we've previously registered the order as removed, then assume // this update is late and stop - const prevVersion = state.orders[index] + const prevVersion = state.orders[coin.key][index] if (prevVersion.deleted) return state // If it's a removal, remove - if (isRemoval) return replaceOrderContent(index, { deleted: true }) + if (isRemoval) return replaceOrderContent(index, coin, { deleted: true }) // If the previous version is derived from a later timestamp than // this update, stop @@ -143,11 +171,14 @@ export default function reduce(state = initialState, action = {}) { // Overwrite existing state with any values provided in the // update - return replaceOrderContent(index, { ...order, serverTimestamp: timestamp }) + return replaceOrderContent(index, coin, { + ...order, + serverTimestamp: timestamp + }) } - function replaceOrderContent(index, replacement) { - const orders = Immutable.asMutable(state.orders, { deep: true }) + function replaceOrderContent(index, coin, replacement) { + const orders = Immutable.asMutable(state.orders[coin.key], { deep: true }) const existing = orders[index] for (const key of Object.keys(replacement)) { const val = replacement[key] @@ -155,6 +186,14 @@ export default function reduce(state = initialState, action = {}) { existing[key] = val } } - return Immutable.merge(state, { orders }) + return Immutable.merge( + state, + { + orders: { + [coin.key]: orders + } + }, + { deep: true } + ) } } diff --git a/orko-ui/src/store/socket/connect.js b/orko-ui/src/store/socket/connect.js index 606d742f7..5010d8a7e 100644 --- a/orko-ui/src/store/socket/connect.js +++ b/orko-ui/src/store/socket/connect.js @@ -159,41 +159,42 @@ export function initialise(s, history) { bufferAllActions(coinActions.addUserTrade(trade)) }) socketClient.onOrderUpdate((coin, order, timestamp) => { - if (sameCoin(coin, selectedCoin())) - store.dispatch(coinActions.orderUpdated(order, timestamp)) + store.dispatch(coinActions.orderUpdated(coin, order, timestamp)) }) // This is a bit hacky. The intent is to move this logic server side, // so the presence of a snapshot/poll loop is invisible to the client. // In the meantime, I'm not polluting the reducer with it. socketClient.onOrdersSnapshot((coin, orders, timestamp) => { - if (sameCoin(coin, selectedCoin())) { - var idsPresent = [] - if (orders.length === 0) { - // Update that there are no orders - store.dispatch(coinActions.orderUpdated(null, timestamp)) - } else { - // Updates for every order mentioned - orders.forEach(o => { - idsPresent.push(o.id) - store.dispatch(coinActions.orderUpdated(o, timestamp)) - }) - } + var idsPresent = [] + if (orders.length === 0) { + // Update that there are no orders + store.dispatch(coinActions.orderUpdated(coin, null, timestamp)) + } else { + // Updates for every order mentioned + orders.forEach(o => { + idsPresent.push(o.id) + store.dispatch(coinActions.orderUpdated(coin, o, timestamp)) + }) + } - // Any order not mentioned should be removed - if (store.getState().coin.orders) { - store - .getState() - .coin.orders.filter(o => !idsPresent.includes(o.id)) - .forEach(o => { - store.dispatch( - coinActions.orderUpdated( - { id: o.id, status: "CANCELED" }, - timestamp - ) + // Any order not mentioned should be removed + if ( + store.getState().coin.orders && + store.getState().coin.orders[coin.key] + ) { + store + .getState() + .coin.orders[coin.key].filter(o => !idsPresent.includes(o.id)) + .forEach(o => { + store.dispatch( + coinActions.orderUpdated( + coin, + { id: o.id, status: "CANCELED" }, + timestamp ) - }) - } + ) + }) } }) } diff --git a/orko-ui/src/worker/socket.client.js b/orko-ui/src/worker/socket.client.js index 6afa4f24f..ac029f3d1 100644 --- a/orko-ui/src/worker/socket.client.js +++ b/orko-ui/src/worker/socket.client.js @@ -152,7 +152,7 @@ export function resubscribe() { }) send({ command: socketMessages.CHANGE_OPEN_ORDERS, - tickers: serverSelectedCoinTickers + tickers: subscribedCoins.map(coin => webCoinToServerCoin(coin)) }) send({ command: socketMessages.CHANGE_ORDER_BOOK, @@ -164,7 +164,7 @@ export function resubscribe() { }) send({ command: socketMessages.CHANGE_ORDER_STATUS_CHANGE, - tickers: serverSelectedCoinTickers + tickers: subscribedCoins.map(coin => webCoinToServerCoin(coin)) }) send({ command: socketMessages.CHANGE_USER_TRADES, From c9bba6b323d6fe0924d6892852c8b348bee6e1e0 Mon Sep 17 00:00:00 2001 From: lowwor Date: Wed, 12 Jun 2019 14:25:10 +0800 Subject: [PATCH 7/7] style: remove not use import --- orko-ui/src/App.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orko-ui/src/App.js b/orko-ui/src/App.js index e2a7b1c4a..0b5b13c22 100644 --- a/orko-ui/src/App.js +++ b/orko-ui/src/App.js @@ -22,7 +22,7 @@ import theme from "./theme" import { GlobalStyle } from "./theme" import { Provider as ReduxProvider } from "react-redux" -import { compose, createStore, applyMiddleware } from "redux" +import { createStore, applyMiddleware } from "redux" import createHistory from "history/createBrowserHistory" import { ConnectedRouter, routerMiddleware } from "connected-react-router"