diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..208fa65b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. +.scannerwork + +\.env + +\.nyc_output/ + +coverage/ + +node_modules/** + +test/activeCloneList\.js diff --git a/client/package-lock.json b/client/package-lock.json index 2f4b4a7ba..5e17d3b9d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,6 +1,6 @@ { "name": "@superalgos/operations-client", - "version": "0.0.2", + "version": "0.0.29", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -9,7 +9,7 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", "requires": { - "regenerator-runtime": "0.12.1" + "regenerator-runtime": "^0.12.0" }, "dependencies": { "regenerator-runtime": { @@ -25,31 +25,31 @@ "integrity": "sha512-wDTJyR76+OBdlltiPs3lc1gD6zR+dSA6nITtgkBeLf1NvWfNotMWdvldIDnF3bu24ySAX9imfzDfkBu4Edtqww==", "requires": { "@babel/runtime": "7.1.2", - "@types/jss": "9.5.6", - "@types/react-transition-group": "2.0.14", - "brcast": "3.0.1", - "classnames": "2.2.6", - "csstype": "2.5.7", - "debounce": "1.2.0", - "deepmerge": "2.2.1", - "dom-helpers": "3.3.1", - "hoist-non-react-statics": "2.5.5", - "is-plain-object": "2.0.4", - "jss": "9.8.7", - "jss-camel-case": "6.1.0", - "jss-default-unit": "8.0.2", - "jss-global": "3.0.0", - "jss-nested": "6.0.1", - "jss-props-sort": "6.0.0", - "jss-vendor-prefixer": "7.0.0", - "keycode": "2.2.0", - "normalize-scroll-left": "0.1.2", - "popper.js": "1.14.4", - "prop-types": "15.6.2", - "react-event-listener": "0.6.4", - "react-transition-group": "2.5.0", - "recompose": "0.30.0", - "warning": "4.0.2" + "@types/jss": "^9.5.6", + "@types/react-transition-group": "^2.0.8", + "brcast": "^3.0.1", + "classnames": "^2.2.5", + "csstype": "^2.5.2", + "debounce": "^1.1.0", + "deepmerge": "^2.0.1", + "dom-helpers": "^3.2.1", + "hoist-non-react-statics": "^2.5.0", + "is-plain-object": "^2.0.4", + "jss": "^9.3.3", + "jss-camel-case": "^6.0.0", + "jss-default-unit": "^8.0.2", + "jss-global": "^3.0.0", + "jss-nested": "^6.0.1", + "jss-props-sort": "^6.0.0", + "jss-vendor-prefixer": "^7.0.0", + "keycode": "^2.1.9", + "normalize-scroll-left": "^0.1.2", + "popper.js": "^1.14.1", + "prop-types": "^15.6.0", + "react-event-listener": "^0.6.2", + "react-transition-group": "^2.2.1", + "recompose": "0.28.0 - 0.30.0", + "warning": "^4.0.1" }, "dependencies": { "@babel/runtime": { @@ -57,7 +57,7 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.2.tgz", "integrity": "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg==", "requires": { - "regenerator-runtime": "0.12.1" + "regenerator-runtime": "^0.12.0" } } } @@ -68,7 +68,7 @@ "integrity": "sha512-1kNcxYiIT1x8iDPEAlgmKrfRTIV8UyK6fLVcZ9kMHIKGWft9I451V5mvSrbCjbf7MX1TbLWzZjph0aVCRf9MqQ==", "requires": { "@babel/runtime": "7.0.0", - "recompose": "0.29.0" + "recompose": "^0.29.0" }, "dependencies": { "recompose": { @@ -76,12 +76,12 @@ "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.29.0.tgz", "integrity": "sha512-J/qLXNU4W+AeHCDR70ajW8eMd1uroqZaECTj6qqDLPMILz3y0EzpYlvrnxKB9DnqcngWrtGwjXY9JeXaW9kS1A==", "requires": { - "@babel/runtime": "7.0.0", - "change-emitter": "0.1.6", - "fbjs": "0.8.17", - "hoist-non-react-statics": "2.5.5", - "react-lifecycles-compat": "3.0.4", - "symbol-observable": "1.2.0" + "@babel/runtime": "^7.0.0", + "change-emitter": "^0.1.2", + "fbjs": "^0.8.1", + "hoist-non-react-statics": "^2.3.1", + "react-lifecycles-compat": "^3.0.2", + "symbol-observable": "^1.0.4" } } } @@ -97,8 +97,8 @@ "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.6.tgz", "integrity": "sha512-7TWmR5y1jYG4ka4wTZt65RR0kw4WgALFUWktQIWbLnDd6/z/0SQZ/4+UeH0rhdp+HEdIfmzPBH0VwE/4Z9Evzw==", "requires": { - "csstype": "2.5.7", - "indefinite-observable": "1.0.1" + "csstype": "^2.0.0", + "indefinite-observable": "^1.0.1" } }, "@types/prop-types": { @@ -111,8 +111,8 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.16.tgz", "integrity": "sha512-lxyoipLWweAnLnSsV4Ho2NAZTKKmxeYgkTQ6PaDiPDU9JJBUY2zJVVGiK1smzYv8+ZgbqEmcm5xM74GCpunSEA==", "requires": { - "@types/prop-types": "15.5.6", - "csstype": "2.5.7" + "@types/prop-types": "*", + "csstype": "^2.2.0" } }, "@types/react-transition-group": { @@ -120,7 +120,7 @@ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.0.14.tgz", "integrity": "sha512-pa7qB0/mkhwWMBFoXhX8BcntK8G4eQl4sIfSrJCxnivTYRQWjOWf2ClR9bWdm0EUFBDHzMbKYS+QYfDtBzkY4w==", "requires": { - "@types/react": "16.4.16" + "@types/react": "*" } }, "@types/zen-observable": { @@ -133,7 +133,7 @@ "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.1.17.tgz", "integrity": "sha512-7sp24n2HZO4vXgTaKNomLyIfGxG4gDdDkBB0jkRzRi7HhnKmfwhiF/RCiKNbgLdrPX151INdls0KwIVliD0dHQ==", "requires": { - "apollo-utilities": "1.0.21" + "apollo-utilities": "^1.0.21" } }, "apollo-client": { @@ -142,13 +142,13 @@ "integrity": "sha512-g1z23umaVSoKLj9xNl0aAnk2KBF4JeBi7MeKFc9CGTixH7TkqeQUQtxcjrC7j2h4KmDbuhOAHOFUGf8YshN+ag==", "requires": { "@types/async": "2.0.49", - "@types/zen-observable": "0.8.0", + "@types/zen-observable": "^0.8.0", "apollo-cache": "1.1.17", - "apollo-link": "1.2.3", - "apollo-link-dedup": "1.0.10", + "apollo-link": "^1.0.0", + "apollo-link-dedup": "^1.0.0", "apollo-utilities": "1.0.21", - "symbol-observable": "1.2.0", - "zen-observable": "0.8.9" + "symbol-observable": "^1.0.2", + "zen-observable": "^0.8.0" } }, "apollo-link": { @@ -156,8 +156,8 @@ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.3.tgz", "integrity": "sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==", "requires": { - "apollo-utilities": "1.0.21", - "zen-observable-ts": "0.8.10" + "apollo-utilities": "^1.0.0", + "zen-observable-ts": "^0.8.10" } }, "apollo-link-dedup": { @@ -165,7 +165,7 @@ "resolved": "https://registry.npmjs.org/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz", "integrity": "sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==", "requires": { - "apollo-link": "1.2.3" + "apollo-link": "^1.2.3" } }, "apollo-utilities": { @@ -173,8 +173,8 @@ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.21.tgz", "integrity": "sha512-ZcxELlEl+sDCYBgEMdNXJAsZtRVm8wk4HIA58bMsqYfd1DSAJQEtZ93F0GZgYNAGy3QyaoBeZtbb0/01++G8JQ==", "requires": { - "fast-json-stable-stringify": "2.0.0", - "fclone": "1.0.11" + "fast-json-stable-stringify": "^2.0.0", + "fclone": "^1.0.11" } }, "asap": { @@ -207,7 +207,7 @@ "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz", "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=", "requires": { - "is-in-browser": "1.1.3" + "is-in-browser": "^1.0.2" } }, "csstype": { @@ -241,7 +241,7 @@ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", "requires": { - "iconv-lite": "0.4.24" + "iconv-lite": "~0.4.13" } }, "fast-json-stable-stringify": { @@ -260,13 +260,13 @@ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.18" + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" } }, "fbjs-css-vars": { @@ -285,8 +285,8 @@ "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", "dev": true, "requires": { - "min-document": "2.19.0", - "process": "0.5.2" + "min-document": "^2.19.0", + "process": "~0.5.1" } }, "graphql": { @@ -294,7 +294,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.2.tgz", "integrity": "sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==", "requires": { - "iterall": "1.2.2" + "iterall": "^1.2.2" } }, "graphql-tag": { @@ -307,11 +307,11 @@ "resolved": "https://registry.npmjs.org/history/-/history-4.7.2.tgz", "integrity": "sha512-1zkBRWW6XweO0NBcjiphtVJVsIQ+SXF29z9DVkceeaSLVMFXHool+fdCZD4spDCfZJCILPILc3bm7Bc+HRi0nA==", "requires": { - "invariant": "2.2.4", - "loose-envify": "1.4.0", - "resolve-pathname": "2.2.0", - "value-equal": "0.4.0", - "warning": "3.0.0" + "invariant": "^2.2.1", + "loose-envify": "^1.2.0", + "resolve-pathname": "^2.2.0", + "value-equal": "^0.4.0", + "warning": "^3.0.0" }, "dependencies": { "warning": { @@ -319,7 +319,7 @@ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } } } @@ -339,7 +339,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "requires": { - "safer-buffer": "2.1.2" + "safer-buffer": ">= 2.1.2 < 3" } }, "indefinite-observable": { @@ -362,7 +362,7 @@ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } }, "is-in-browser": { @@ -375,7 +375,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" }, "dependencies": { "isobject": { @@ -395,8 +395,8 @@ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "node-fetch": "1.7.3", - "whatwg-fetch": "2.0.4" + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" } }, "iterall": { @@ -414,9 +414,9 @@ "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz", "integrity": "sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ==", "requires": { - "is-in-browser": "1.1.3", - "symbol-observable": "1.2.0", - "warning": "3.0.0" + "is-in-browser": "^1.1.3", + "symbol-observable": "^1.1.0", + "warning": "^3.0.0" }, "dependencies": { "warning": { @@ -424,7 +424,7 @@ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } } } @@ -434,7 +434,7 @@ "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz", "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==", "requires": { - "hyphenate-style-name": "1.0.2" + "hyphenate-style-name": "^1.0.2" } }, "jss-default-unit": { @@ -452,7 +452,7 @@ "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz", "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==", "requires": { - "warning": "3.0.0" + "warning": "^3.0.0" }, "dependencies": { "warning": { @@ -460,7 +460,7 @@ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } } } @@ -475,7 +475,7 @@ "resolved": "https://registry.npmjs.org/jss-vendor-prefixer/-/jss-vendor-prefixer-7.0.0.tgz", "integrity": "sha512-Agd+FKmvsI0HLcYXkvy8GYOw3AAASBUpsmIRvVQheps+JWaN892uFOInTr0DRydwaD91vSSUCU4NssschvF7MA==", "requires": { - "css-vendor": "0.3.8" + "css-vendor": "^0.3.8" } }, "keycode": { @@ -498,7 +498,7 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "requires": { - "js-tokens": "4.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" } }, "luxon": { @@ -511,12 +511,12 @@ "resolved": "https://registry.npmjs.org/material-ui-pickers/-/material-ui-pickers-1.0.1.tgz", "integrity": "sha512-FRJwgeFUQdQxzNAybZvf11204KFBxqKS6sg4JvAO0cWmHULXJhrc9kuEDT8F7Pomwnv6+AyfxygsoMgIRcBMNg==", "requires": { - "classnames": "2.2.6", - "keycode": "2.2.0", - "react-event-listener": "0.6.4", - "react-text-mask": "5.4.1", - "react-transition-group": "2.5.0", - "tslib": "1.9.3" + "classnames": "^2.2.6", + "keycode": "^2.2.0", + "react-event-listener": "^0.6.4", + "react-text-mask": "=5.4.1", + "react-transition-group": "^2.5.0", + "tslib": "^1.9.3" } }, "min-document": { @@ -525,7 +525,7 @@ "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", "dev": true, "requires": { - "dom-walk": "0.1.1" + "dom-walk": "^0.1.0" } }, "node-fetch": { @@ -533,8 +533,8 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" + "encoding": "^0.1.11", + "is-stream": "^1.0.1" } }, "normalize-scroll-left": { @@ -578,7 +578,7 @@ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" } }, "prop-types": { @@ -586,8 +586,8 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", "requires": { - "loose-envify": "1.4.0", - "object-assign": "4.1.1" + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" } }, "react": { @@ -595,10 +595,10 @@ "resolved": "https://registry.npmjs.org/react/-/react-16.6.1.tgz", "integrity": "sha512-OtawJThYlvRgm9BXK+xTL7BIlDx8vv21j+fbQDjRRUyok6y7NyjlweGorielTahLZHYIdKUoK2Dp9ByVWuMqxw==", "requires": { - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "prop-types": "15.6.2", - "scheduler": "0.11.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.11.0" } }, "react-apollo": { @@ -606,12 +606,12 @@ "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.2.4.tgz", "integrity": "sha512-haS5R30Qvteb65ZLfWomUZQh47VU4ld4Kof3zlqdbLOrYPt3/DdVZC8ZFPZSxd5zPeIJtZqpUfAxD1WHVoMPIA==", "requires": { - "fbjs": "1.0.0", - "hoist-non-react-statics": "3.0.1", - "invariant": "2.2.4", - "lodash.flowright": "3.5.0", - "lodash.isequal": "4.5.0", - "prop-types": "15.6.2" + "fbjs": "^1.0.0", + "hoist-non-react-statics": "^3.0.0", + "invariant": "^2.2.2", + "lodash.flowright": "^3.5.0", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.6.0" }, "dependencies": { "core-js": { @@ -624,14 +624,14 @@ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-1.0.0.tgz", "integrity": "sha512-MUgcMEJaFhCaF1QtWGnmq9ZDRAzECTCRAF7O6UZIlAlkTs1SasiX9aP0Iw7wfD2mJ7wDTNfg2w7u5fSCwJk1OA==", "requires": { - "core-js": "2.5.7", - "fbjs-css-vars": "1.0.1", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.18" + "core-js": "^2.4.1", + "fbjs-css-vars": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" } }, "hoist-non-react-statics": { @@ -639,7 +639,7 @@ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.0.1.tgz", "integrity": "sha512-1kXwPsOi0OGQIZNVMPvgWJ9tSnGMiMfJdihqEzrPEXlHOBh9AAHXX/QYmAJTXztnz/K+PQ8ryCb4eGaN6HlGbQ==", "requires": { - "react-is": "16.5.2" + "react-is": "^16.3.2" } } } @@ -649,10 +649,10 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.1.tgz", "integrity": "sha512-zm+wBuEMGm009Wt1uE4Zw5KcXOW7qC4E/xW/fpJsCsbOco4U/R84u+DzzO/S4SYSdNBcqcaulcp4w3FXl8pImw==", "requires": { - "loose-envify": "1.4.0", - "object-assign": "4.1.1", - "prop-types": "15.6.2", - "scheduler": "0.11.0" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.11.0" } }, "react-event-listener": { @@ -661,8 +661,8 @@ "integrity": "sha512-t7VSjIuUFmN+GeyKb+wm025YLeojVB85kJL6sSs0wEBJddfmKBEQz+CNBZ2zBLKVWkPy/fZXM6U5yvojjYBVYQ==", "requires": { "@babel/runtime": "7.0.0", - "prop-types": "15.6.2", - "warning": "4.0.2" + "prop-types": "^15.6.0", + "warning": "^4.0.1" } }, "react-hot-loader": { @@ -671,12 +671,12 @@ "integrity": "sha512-T0G5jURyTsFLoiW6MTr5Q35UHC/B2pmYJ7+VBjk8yMDCEABRmCGy4g6QwxoB4pWg4/xYvVTa/Pbqnsgx/+NLuA==", "dev": true, "requires": { - "fast-levenshtein": "2.0.6", - "global": "4.3.2", - "hoist-non-react-statics": "2.5.5", - "prop-types": "15.6.2", - "react-lifecycles-compat": "3.0.4", - "shallowequal": "1.1.0" + "fast-levenshtein": "^2.0.6", + "global": "^4.3.0", + "hoist-non-react-statics": "^2.5.0", + "prop-types": "^15.6.1", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.0.2" } }, "react-is": { @@ -694,7 +694,7 @@ "resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-4.0.6.tgz", "integrity": "sha512-WfBlqYRD0fGZpQxRy1apxsPeaqtxhzo7CnUVFKBoGDsQbc89+DQNhjG/D3IxgGYM47oKB+W/Su9ol/vVS6Wc2Q==", "requires": { - "prop-types": "15.6.2" + "prop-types": "^15.6.0" } }, "react-router": { @@ -702,13 +702,13 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz", "integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==", "requires": { - "history": "4.7.2", - "hoist-non-react-statics": "2.5.5", - "invariant": "2.2.4", - "loose-envify": "1.4.0", - "path-to-regexp": "1.7.0", - "prop-types": "15.6.2", - "warning": "4.0.2" + "history": "^4.7.2", + "hoist-non-react-statics": "^2.5.0", + "invariant": "^2.2.4", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.1", + "warning": "^4.0.1" } }, "react-router-dom": { @@ -716,12 +716,12 @@ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz", "integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==", "requires": { - "history": "4.7.2", - "invariant": "2.2.4", - "loose-envify": "1.4.0", - "prop-types": "15.6.2", - "react-router": "4.3.1", - "warning": "4.0.2" + "history": "^4.7.2", + "invariant": "^2.2.4", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.1", + "react-router": "^4.3.1", + "warning": "^4.0.1" } }, "react-text-mask": { @@ -729,7 +729,7 @@ "resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.4.1.tgz", "integrity": "sha512-mGx1n0x0skktwsKcpgAGnrgExFlXDflbWEHh8PC1UaQP8+EdHkW7JYczTghsBo2rnVwU9/4A9x/2bVt3HY46/w==", "requires": { - "prop-types": "15.6.2" + "prop-types": "^15.5.6" } }, "react-transition-group": { @@ -737,10 +737,10 @@ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.0.tgz", "integrity": "sha512-qYB3JBF+9Y4sE4/Mg/9O6WFpdoYjeeYqx0AFb64PTazVy8RPMiE3A47CG9QmM4WJ/mzDiZYslV+Uly6O1Erlgw==", "requires": { - "dom-helpers": "3.3.1", - "loose-envify": "1.4.0", - "prop-types": "15.6.2", - "react-lifecycles-compat": "3.0.4" + "dom-helpers": "^3.3.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" } }, "recompose": { @@ -748,12 +748,12 @@ "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz", "integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==", "requires": { - "@babel/runtime": "7.0.0", - "change-emitter": "0.1.6", - "fbjs": "0.8.17", - "hoist-non-react-statics": "2.5.5", - "react-lifecycles-compat": "3.0.4", - "symbol-observable": "1.2.0" + "@babel/runtime": "^7.0.0", + "change-emitter": "^0.1.2", + "fbjs": "^0.8.1", + "hoist-non-react-statics": "^2.3.1", + "react-lifecycles-compat": "^3.0.2", + "symbol-observable": "^1.0.4" } }, "regenerator-runtime": { @@ -776,8 +776,8 @@ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.11.0.tgz", "integrity": "sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg==", "requires": { - "loose-envify": "1.4.0", - "object-assign": "4.1.1" + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" } }, "setimmediate": { @@ -816,7 +816,7 @@ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.2.tgz", "integrity": "sha512-wbTp09q/9C+jJn4KKJfJfoS6VleK/Dti0yqWSm6KMvJ4MRCXFQNapHuJXutJIrWV0Cf4AhTdeIe4qdKHR1+Hug==", "requires": { - "loose-envify": "1.4.0" + "loose-envify": "^1.0.0" } }, "whatwg-fetch": { @@ -834,7 +834,7 @@ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz", "integrity": "sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==", "requires": { - "zen-observable": "0.8.9" + "zen-observable": "^0.8.0" } } } diff --git a/client/package.json b/client/package.json index 43a89253f..a79bd9079 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "@superalgos/operations-client", - "version": "0.0.13", + "version": "0.0.31", "description": "Superalgos Operations client-side web app", "main": "src/index.js", "dependencies": { diff --git a/client/src/GraphQL/Calls/clones.js b/client/src/GraphQL/Calls/clones.js index cf6c8d7b8..b215a578d 100644 --- a/client/src/GraphQL/Calls/clones.js +++ b/client/src/GraphQL/Calls/clones.js @@ -1,5 +1,5 @@ -import gql from 'graphql-tag'; -import { clone } from '../Fragments'; +import gql from 'graphql-tag' +import { clone } from '../Fragments' const OPERATIONS_ADD_CLONE = gql` mutation Operations_AddClone($clone: operations_CloneInput!) { @@ -8,35 +8,35 @@ const OPERATIONS_ADD_CLONE = gql` } } ${clone} -`; +` const OPERATIONS_LIST_CLONES = gql` query Operations_Clones{ - operations_Clones { + operations_Clones(queryLogs: true) { ...clone } } ${clone} -`; +` const OPERATIONS_HISTORY_CLONES = gql` query Operations_HistoryClones{ - operations_HistoryClones { + operations_HistoryClones(botType: "Trading") { ...clone } } ${clone} -`; +` const OPERATIONS_REMOVE_CLONE = gql` mutation Operations_RemoveClone($id: ID!){ operations_RemoveClone( id: $id) } -`; +` export default { OPERATIONS_LIST_CLONES, OPERATIONS_HISTORY_CLONES, OPERATIONS_ADD_CLONE, OPERATIONS_REMOVE_CLONE -}; +} diff --git a/client/src/GraphQL/Calls/index.js b/client/src/GraphQL/Calls/index.js index f410adf89..619c6f158 100644 --- a/client/src/GraphQL/Calls/index.js +++ b/client/src/GraphQL/Calls/index.js @@ -1,7 +1,9 @@ -import clones from './clones'; -import teams from './teams'; +import clones from './clones' +import teams from './teams' +import keys from './keys' export { clones, - teams -}; + teams, + keys +} diff --git a/client/src/GraphQL/Calls/keys.js b/client/src/GraphQL/Calls/keys.js new file mode 100644 index 000000000..23d3ffed3 --- /dev/null +++ b/client/src/GraphQL/Calls/keys.js @@ -0,0 +1,16 @@ +import gql from 'graphql-tag' + +export const GET_ALL_KEYS = gql` + query { + keyVault_AvailableKeys { + id + key + description + exchange + } + } +` + +export default { + GET_ALL_KEYS +} diff --git a/client/src/GraphQL/Calls/teams.js b/client/src/GraphQL/Calls/teams.js index 0a27afd3c..2785ede48 100644 --- a/client/src/GraphQL/Calls/teams.js +++ b/client/src/GraphQL/Calls/teams.js @@ -1,4 +1,4 @@ -import gql from 'graphql-tag'; +import gql from 'graphql-tag' export const GET_ALL_TEAMS_QUERY = gql` query { @@ -18,4 +18,4 @@ export const GET_ALL_TEAMS_QUERY = gql` export default { GET_ALL_TEAMS_QUERY -}; +} diff --git a/client/src/GraphQL/Fragments/clone.js b/client/src/GraphQL/Fragments/clone.js deleted file mode 100644 index 42022c0bd..000000000 --- a/client/src/GraphQL/Fragments/clone.js +++ /dev/null @@ -1,34 +0,0 @@ -import gql from 'graphql-tag'; - -export const clone = gql` - fragment clone on operations_Clone { - id - authId - teamId - botId - mode - resumeExecution - beginDatetime - endDatetime - waitTime - state - stateDatetime - createDatetime - lastLogs - runAsTeam - summaryDate - buyAverage - sellAverage - marketRate - combinedProfitsA - combinedProfitsB - assetA - assetB - botType - teamName - botName - botAvatar - teamAvatar - processName - } -`; diff --git a/client/src/GraphQL/Fragments/index.js b/client/src/GraphQL/Fragments/index.js index 2ee040281..3fc772000 100644 --- a/client/src/GraphQL/Fragments/index.js +++ b/client/src/GraphQL/Fragments/index.js @@ -1,6 +1,36 @@ -import { clone } from './clone' +import gql from 'graphql-tag' - -export { - clone -}; +export const clone = gql` + fragment clone on operations_Clone { + id + authId + teamId + botId + mode + resumeExecution + beginDatetime + endDatetime + waitTime + state + stateDatetime + createDatetime + lastLogs + runAsTeam + summaryDate + buyAverage + sellAverage + marketRate + combinedProfitsA + combinedProfitsB + assetA + assetB + botType + teamName + botName + botAvatar + teamAvatar + processName + keyId + botSlug + } +` diff --git a/client/src/GraphQL/index.js b/client/src/GraphQL/index.js deleted file mode 100644 index 8b1378917..000000000 --- a/client/src/GraphQL/index.js +++ /dev/null @@ -1 +0,0 @@ - diff --git a/client/src/GraphQL/models.js b/client/src/GraphQL/models.js index c7a5df51b..997c57bc1 100644 --- a/client/src/GraphQL/models.js +++ b/client/src/GraphQL/models.js @@ -1,25 +1,63 @@ -const availableMonths = ["January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December"] +const availableMonths = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' +] -const tradingStartModes ={ - live: "Live", - competition: "Competition", - backtest: "Backtest" +const availableTimePeriods = ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs", "45-min", "40-min", "30-min", "20-min", "15-min", "10-min", "05-min", "04-min", "03-min", "02-min", "01-min"] + +const tradingStartModes = { + live: 'Live', + backtest: 'Backtest' +} + +const tradingStartModesList = { + live: 'Live', + backtest: 'Backtest', + competition: 'Competition' } const indicatorStartModes = { - allMonths: "All Months", - oneMonth: "One Month", - noTime: "No Time" + allMonths: 'All Months', + oneMonth: 'One Month', + noTime: 'Head of the Market' } -const exchanges = [ - { - id: '1', - name: 'Poloniex' - } -] +const sensorProcessNames = { + Live: "Live-Trades", + HoleFixing: "Hole-Fixing" +} +const indicatorProcessNames = { + Daily: 'Multi-Period-Daily', + Market: 'Multi-Period-Market' +} +const tradingProcessNames = { + TradingProcess: "Trading-Process" +} -export { tradingStartModes, exchanges, indicatorStartModes, availableMonths } +const botTypes = { + Trading: "Trading", + Indicator: "Indicator", + Sensor: "Sensor" +} + +const exchanges = { + Coss: "Coss", + Poloniex: "Poloniex" +} + +export { + tradingStartModes, tradingStartModesList, exchanges, indicatorStartModes, availableMonths, + availableTimePeriods, sensorProcessNames, indicatorProcessNames, tradingProcessNames, botTypes +} diff --git a/client/src/index.js b/client/src/index.js index 970c534aa..dbc3944b5 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -1,9 +1,7 @@ -import React, { Component } from 'react' +import React from 'react' import { Route, Switch } from 'react-router-dom' - import { MuiPickersUtilsProvider } from 'material-ui-pickers' import LuxonUtils from 'material-ui-pickers/utils/luxon-utils' - import BrowseClones from './views/Clone/List' import HistoryClones from './views/Clone/History' import AddClone from './views/Clone/Add' @@ -12,10 +10,10 @@ import Home from './views/Home' const App = () => ( - - - - + + + + ) diff --git a/client/src/utils/index.js b/client/src/utils/index.js index e5e223f3c..a12aa4fa9 100644 --- a/client/src/utils/index.js +++ b/client/src/utils/index.js @@ -10,13 +10,13 @@ export function toLocalTime (epoch) { } export function toUTCTimestamp (localDate) { - if(isDefined(localDate)){ + if (isDefined(localDate)) { const date = new Date(localDate.valueOf()) const utcDate = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()) - return utcDate.valueOf() / 1000|0 + return utcDate.valueOf() / 1000 | 0 } } @@ -77,7 +77,7 @@ export function getIndicatorYears () { const localDate = new Date() let availableYears = [] for (var i = 2015; i <= localDate.getUTCFullYear(); i++) { - availableYears[i-2015] = i + availableYears[i - 2015] = i } return availableYears } diff --git a/client/src/views/Clone/Add/index.js b/client/src/views/Clone/Add/index.js index 3db9ccfdd..013b752f9 100644 --- a/client/src/views/Clone/Add/index.js +++ b/client/src/views/Clone/Add/index.js @@ -1,40 +1,34 @@ import React, { Component } from 'react' import { graphql, compose, Query } from 'react-apollo' -import { clones, teams } from '../../../GraphQL/Calls' +import { clones, teams, keys } from '../../../GraphQL/Calls' import { DateTime } from 'luxon'; - import TopBar from '../../BannerTopBar' - import { withStyles } from '@material-ui/core/styles' import classNames from 'classnames' import styles from './styles' - -import { tradingStartModes, indicatorStartModes, availableMonths, processNames } from '../../../GraphQL/models' import { isDefined, getIndicatorYears } from '../../../utils' +import { + tradingStartModes, indicatorStartModes, availableMonths, availableTimePeriods, + sensorProcessNames, indicatorProcessNames, tradingProcessNames, botTypes, exchanges +} from '../../../GraphQL/models' import { - MenuItem, Button, TextField, FormControl, InputLabel, Input, Typography, - Paper, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, - Select, FormControlLabel, Checkbox, FormHelperText + MenuItem, Button, TextField, FormControl, InputLabel, Input, Typography, + Paper, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, + Select, FormControlLabel, Checkbox, FormHelperText } from '@material-ui/core' - -import NumberFormat from 'react-number-format' - import { DateTimePicker } from 'material-ui-pickers' -import { - ChevronLeft, - ChevronRight, -} from '@material-ui/icons' +import { ChevronLeft, ChevronRight } from '@material-ui/icons' class AddClone extends Component { - constructor(props){ + constructor(props) { super(props) let user = localStorage.getItem('user') this.state = { user: JSON.parse(user), - selectedBot: {'id':''}, - mode: '', + selectedBot: { 'id': '' }, + mode: "noTime", resumeExecution: false, beginDatetime: DateTime.local().minus({ days: 8 }).startOf('day'), endDatetime: DateTime.local(), @@ -45,12 +39,17 @@ class AddClone extends Component { runAsTeam: false, teams: [], teamId: '', + keyId: '', + exchangeName: exchanges.Coss, + processName: indicatorProcessNames.Daily, // Indicator Bot startYear: 2019, endYear: 2019, month: 1, - processName: '', + + //TradingBot + timePeriod: '01-hs', //Error handlers nameError: false, @@ -60,34 +59,35 @@ class AddClone extends Component { isNewCloneConfirmationOpen: false, serverResponse: '', serverError: false, - processNameError: false + processNameError: false, + keyIdError: false, } } render() { const { classes } = this.props - if( !isDefined(this.state.user) ) { + if (!isDefined(this.state.user)) { return ( ) } else return ( - - + + -
+
-
+ Create a Bot Clone @@ -119,31 +119,31 @@ class AddClone extends Component { ) } - if(!isDefined(data.teams_TeamsByOwner)){ - return ( - - ) - } else{ + if (!isDefined(data.teams_TeamsByOwner)) { + return ( + + ) + } else { this.teams = data.teams_TeamsByOwner } return ( - this.setState({ botError: false })} + error={this.state.botError} + onChange={e => this.setSelectedBot(e.target.value)} + > { data.teams_TeamsByOwner.map(team => ( team.fb.map(financialBeing => ( @@ -153,236 +153,262 @@ class AddClone extends Component { )) )) } - + ) }} {this.state.selectedBot.kind} - { this.state.selectedBot.kind === "TRADER" && - - - At the moment Live Trading Clones trade by default 0.001 BTC on Poloniex. - + this.setState({ exchangeName: e.target.value })} + fullWidth + > + {Object.keys(exchanges).map((option, index) => ( + + {option} + + ))} + - this.setState({mode:e.target.value})} - onBlur={(e)=>this.setState({modeError:false})} - error={this.state.modeError} - fullWidth - > - {Object.keys(tradingStartModes).map(option => ( - - {tradingStartModes[option]} - - ))} - + {this.state.selectedBot.kind === botTypes.Trading && + + + Available Running Modes are Backtest and Live. +
    +
  • Backtest mode does NOT put real orders at the exchange; + it simulates the order execution at the specified price. +
  • +
  • + Live mode DOES put real orders at the exchange. +
  • +
+
- { this.state.mode == "backtest" && - - } - rightArrowIcon={} - value={this.state.beginDatetime} - label='Backtest Start Date' - onChange={newVal => this.setState({ beginDatetime: newVal })} - className={classNames(classes.form, classes.textField)} - fullWidth - /> - } - rightArrowIcon={} - value={this.state.endDatetime} - label='Backtest End Date' - onChange={newVal => this.setState({ endDatetime: newVal })} - className={classNames(classes.form, classes.textField)} - fullWidth - /> + this.setState({ mode: e.target.value })} + onBlur={(e) => this.setState({ modeError: false })} + error={this.state.modeError} + fullWidth + > + {Object.keys(tradingStartModes).map(option => ( + + {tradingStartModes[option]} + + ))} + - - The Wait Time represent the number of miliseconds the bot will wait between executions. + {this.state.mode == "backtest" && + + } + rightArrowIcon={} + value={this.state.beginDatetime} + label='Backtest Start Date' + onChange={newVal => this.setState({ beginDatetime: newVal })} + className={classNames(classes.form, classes.textField)} + fullWidth + /> + + } + rightArrowIcon={} + value={this.state.endDatetime} + label='Backtest End Date' + onChange={newVal => this.setState({ endDatetime: newVal })} + className={classNames(classes.form, classes.textField)} + fullWidth + /> + + } + + {this.state.mode == "live" && + + + Select one of your available Exchange API Keys to be used by this clone. - this.setState({waitTime:e.target.value})} - fullWidth - /> - - } - - - If Run as Team is selected, the clone will be taken from the - team respository instead of your own team member folder. - Competitions runs from the team respository. - - this.setState({runAsTeam:e.target.checked })} - value="runAsTeam" - color="primary" - /> - } - label="Run as Team" - className={classNames(classes.form, classes.textField)} - /> - - - The Resume Execution option let's you pick up the context of - the last execution and continue from there. - - this.setState({resumeExecution:e.target.checked })} - value="resumeExecution" - color="primary" - /> - } - label="Resume Execution" - className={classNames(classes.form, classes.textField)} - /> - - } - - { (this.state.selectedBot.kind === "INDICATOR" - || this.state.selectedBot.kind === "EXTRACTOR") && - - this.setState({processName:e.target.value})} - onBlur={(e)=>this.setState({processNameError:false})} - error={this.state.processNameError} - fullWidth - /> - - this.setState({mode:e.target.value})} - onBlur={(e)=>this.setState({modeError:false})} - error={this.state.modeError} - fullWidth - > - {Object.keys(indicatorStartModes).map(option => ( - - {indicatorStartModes[option]} - - ))} - - - { this.state.mode === "allMonths" && - - this.setState({startYear:e.target.value})} - fullWidth - > - {getIndicatorYears().map((option, index) => ( - - {option} - - ))} - - + + {({ loading, error, data }) => { + if (loading) return ( this.setState({endYear:e.target.value})} - fullWidth - > - {getIndicatorYears().map((option, index) => ( - - {option} - - ))} - - - } - - { this.state.mode === "oneMonth" && - - this.setState({startYear:e.target.value})} + label="Exchange API Key" + className={classNames(classes.margin, classes.textField, classes.form)} + value={this.state.keyId} + onChange={(e) => this.setState({ keyId: e.target.value })} + onBlur={(e) => this.setState({ keyIdError: false })} + error={this.state.keyIdError} fullWidth - > - {getIndicatorYears().map((option, index) => ( - - {option} - - ))} + > + + 'Loading keys...' + - + ); + if (error) return `Error! ${error.message}`; + const list = data.keyVault_AvailableKeys.map((key) => ( + + {key.key.substr(0, 32) + "..." + " - " + key.exchange} + + )); + return ( this.setState({month:e.target.value})} - fullWidth - > - {availableMonths.map(option => ( - - {option} - - ))} - - - } - + select + label="Exchange API Key" + className={classNames(classes.margin, classes.textField, classes.form)} + value={this.state.keyId} + onChange={(e) => this.setState({ keyId: e.target.value })} + onBlur={(e) => this.setState({ keyIdError: false })} + error={this.state.keyIdError} + fullWidth + > + {list} + + ); + }} + + + + Because we are still in early alpha-testing phase, + Live Trading Clones are limited to an initial investment + of 0.001 BTC. If you choose to run this bot or any modified + version of the code, you are doing it at your own risk. + + +
+ } + + + The Time Period in which the bot will operate. + + + this.setState({ timePeriod: e.target.value })} + fullWidth + > + {availableTimePeriods.map((option, index) => ( + + {option} + + ))} + + +
} + {this.state.selectedBot.kind === botTypes.Indicator && + + this.setState({ processName: e.target.value })} + onBlur={(e) => this.setState({ processNameError: false })} + error={this.state.processNameError} + fullWidth + > + {Object.keys(indicatorProcessNames).map((option, index) => ( + + {indicatorProcessNames[option]} + + ))} + + + } - - You will be able to query your clone information under Active Clones until it finishes the execution, then it will moved to the History. + {this.state.selectedBot.kind === botTypes.Sensor && + + this.setState({ processName: e.target.value })} + onBlur={(e) => this.setState({ processNameError: false })} + error={this.state.processNameError} + fullWidth + > + {Object.keys(sensorProcessNames).map((option, index) => ( + + {sensorProcessNames[option]} + + ))} + + + } + + {(this.state.mode === "noTime" && this.state.selectedBot.kind !== botTypes.Sensor) && + + + The Resume Execution option let's you pick up the context of + the last execution and continue from there. + + this.setState({ resumeExecution: e.target.checked })} + value="resumeExecution" + color="primary" + /> + } + label="Resume Execution" + className={classNames(classes.form, classes.textField)} + /> + {!this.state.resumeExecution && + } + rightArrowIcon={} + value={this.state.beginDatetime} + label='Start Date' + onChange={newVal => this.setState({ beginDatetime: newVal })} + className={classNames(classes.form, classes.textField)} + fullWidth + /> + } + + + } + + + You will be able to see the clone information under Active Clones. + Whenever you decide to stop the clone you can delete it. On History Clones will find all deleted clones.
- -
+
@@ -399,24 +425,25 @@ class AddClone extends Component { - - +
); } - setSelectedBot(botId){ - if(isDefined(this.teams)){ + setSelectedBot(botId) { + if (isDefined(this.teams)) { for (var j = 0; j < this.teams.length; j++) { for (var i = 0; i < this.teams[j].fb.length; i++) { - if(this.teams[j].fb[i].id === botId){ - this.setState({selectedBot:this.teams[j].fb[i]}) - this.setState({teamId:this.teams[j].id}) + if (this.teams[j].fb[i].id === botId) { + this.setState({ selectedBot: this.teams[j].fb[i] }) + this.setState({ teamId: this.teams[j].id }) return } } @@ -424,16 +451,16 @@ class AddClone extends Component { } } - async submitForm(e){ + async submitForm(e) { e.preventDefault() let error = this.validate() - if (!error){ + if (!error) { let serverResponse = await this.createCloneOnServer() error = serverResponse.errors || !isDefined(serverResponse.data.operations_AddClone) - if(error){ - this.state.serverResponse = serverResponse.errors[0].message + if (error) { + this.state.serverResponse = serverResponse.errors[0].message || serverResponse.errors[0] this.state.serverError = true - }else{ + } else { this.state.serverResponse = "The new clone was sucessfully created." this.state.serverError = false } @@ -442,32 +469,36 @@ class AddClone extends Component { } } - async createCloneOnServer(){ + async createCloneOnServer() { let variables = { - clone:{ + clone: { teamId: this.state.teamId, botId: this.state.selectedBot.id, mode: this.state.mode, resumeExecution: this.state.resumeExecution, - botType: this.getBotTypeFromKind(this.state.selectedBot.kind) + botType: this.state.selectedBot.kind, + exchangeName: this.state.exchangeName } } - if(this.state.mode === "backtest"){ - variables.clone.beginDatetime = this.state.beginDatetime.valueOf() / 1000|0 - variables.clone.endDatetime = this.state.endDatetime.valueOf() / 1000|0 - variables.clone.waitTime = this.state.waitTime - } - - if(this.state.selectedBot.kind === "TRADER"){ + if (this.state.selectedBot.kind === "Trading") { variables.clone.runAsTeam = this.state.runAsTeam variables.clone.processName = 'Trading-Process' + variables.clone.timePeriod = this.state.timePeriod + if (this.state.mode === "backtest") { + variables.clone.beginDatetime = this.state.beginDatetime.valueOf() / 1000 | 0 + variables.clone.endDatetime = this.state.endDatetime.valueOf() / 1000 | 0 + variables.clone.waitTime = this.state.waitTime + } else { + variables.clone.keyId = this.state.keyId + } } else { variables.clone.processName = this.state.processName variables.clone.startYear = this.state.startYear variables.clone.endYear = this.state.endYear variables.clone.month = this.state.month variables.clone.runAsTeam = true + variables.clone.beginDatetime = this.state.beginDatetime.valueOf() / 1000 | 0 } return this.props.addCloneMutation({ @@ -475,15 +506,6 @@ class AddClone extends Component { }) } - getBotTypeFromKind(kind){ - if(kind === 'TRADER') - return 'Trading' - else if(kind === 'INDICATOR') - return 'Indicator' - else if(kind === 'EXTRACTOR') - return 'Extraction' - } - handleNewCloneConfirmationOpen = () => { this.setState({ isNewCloneConfirmationOpen: true }) }; @@ -493,21 +515,31 @@ class AddClone extends Component { isNewCloneConfirmationOpen: false }) - if(!this.state.serverError) + if (!this.state.serverError) this.setState({ - selectedBot: {'id':''}, - mode: '', + selectedBot: { 'id': '' }, + mode: 'noTime', resumeExecution: false, beginDatetime: DateTime.local().minus({ days: 8 }).startOf('day'), endDatetime: DateTime.local(), waitTime: 1, - state : '', + state: '', stateDatetime: 0, createDatetime: 0, runAsTeam: false, - processName: '', + exchangeName: exchanges.Coss, + processName: indicatorProcessNames.Daily, teams: [], teamId: '', + keyId: '', + + // Indicator Bot + startYear: 2019, + endYear: 2019, + month: 1, + + //TradingBot + timePeriod: '01-hs', //Error handlers nameError: false, @@ -517,25 +549,26 @@ class AddClone extends Component { isNewCloneConfirmationOpen: false, serverResponse: '', serverError: false, - processNameError: false + processNameError: false, + keyIdError: false }) }; - validate(){ + validate() { let isError = false - if(this.state.selectedBot.length < 1) { + if (this.state.selectedBot.length < 1) { isError = true this.setState(state => ({ selectedBotError: true })); } - if(this.state.mode.length < 1) { + if (this.state.mode.length < 1) { isError = true this.setState(state => ({ modeError: true })); } - if(this.state.selectedBot.kind !== "TRADER" - && this.state.processName.length < 1 ) { + if (this.state.selectedBot.kind !== "Trading" + && this.state.processName.length < 1) { isError = true this.setState(state => ({ processNameError: true })); } @@ -546,6 +579,6 @@ class AddClone extends Component { } export default compose( - graphql(clones.OPERATIONS_ADD_CLONE, { name:'addCloneMutation' }), + graphql(clones.OPERATIONS_ADD_CLONE, { name: 'addCloneMutation' }), withStyles(styles) )(AddClone) diff --git a/client/src/views/Clone/Add/styles.js b/client/src/views/Clone/Add/styles.js index c9339ec38..b5533fe95 100644 --- a/client/src/views/Clone/Add/styles.js +++ b/client/src/views/Clone/Add/styles.js @@ -14,7 +14,7 @@ const styles = theme => ({ }, textField: { width: '80%', - marginLeft:'10%', + marginLeft: '10%', marginBottom: 10 }, actionButton: { @@ -24,14 +24,14 @@ const styles = theme => ({ typography: { width: '80%', marginLeft: '10%', - marginTop: 40 + marginTop: 20 }, form: { marginTop: 20 }, selectEmpty: { - marginTop: theme.spacing.unit * 2, - }, -}); + marginTop: theme.spacing.unit * 2 + } +}) -export default styles; +export default styles diff --git a/client/src/views/Clone/History/index.js b/client/src/views/Clone/History/index.js index 7a1c103e3..170c34094 100644 --- a/client/src/views/Clone/History/index.js +++ b/client/src/views/Clone/History/index.js @@ -2,12 +2,8 @@ import React, { Component } from 'react' import { graphql } from 'react-apollo' import { clones } from '../../../GraphQL/Calls' import TopBar from '../../BannerTopBar' -//import CloneDialog from './CloneDialog' import ListClones from '../List/ListClones' -// Material-ui -import { Typography, Paper } from '@material-ui/core' - class HistoryClones extends Component { constructor (props) { @@ -27,7 +23,7 @@ class HistoryClones extends Component { size='big' title='Bot Clone History' text='Loading your Bot Clones...' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } else if (data.operations_HistoryClones && data.operations_HistoryClones.length > 0) { @@ -37,14 +33,14 @@ class HistoryClones extends Component { size='medium' title='Bot Clone History' text='All your Bot Clones are here.' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' />
{ data.operations_HistoryClones.map((clone, i) => { return ( - + ) }) } @@ -57,7 +53,7 @@ class HistoryClones extends Component { size='big' title='Bot Clone History' text='Please login to gain access to your Bot Clones.' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } else { @@ -66,7 +62,7 @@ class HistoryClones extends Component { size='big' title='Bot Clone History' text="You don't have any Clone yet. Once you create one you will find it here." - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } @@ -79,7 +75,7 @@ class HistoryClones extends Component { size='big' title='Manage your Bot Clones' text='Loading Bot Clones...' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } else if (data.operations_HistoryClones && data.operations_HistoryClones.length > 0) { @@ -89,7 +85,7 @@ class HistoryClones extends Component { size='big' title='Manage your Bot Clones' text='Loading Bot Clones...' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' />
@@ -109,7 +105,7 @@ class HistoryClones extends Component { size='big' title='No Bot Clones to display' text='Please Login to access your Bot Clones.' - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } else { @@ -119,7 +115,7 @@ class HistoryClones extends Component { size='big' title='No Bot Clones to display' text="You don't have any Bot Clone yet. After you create a new Clone, it will be listed here." - backgroundUrl='https://superalgos.org/img/photos/ecosystem.jpg' + backgroundUrl='https://superalgos.org/img/photos/clones-original.jpg' /> ) } diff --git a/client/src/views/Clone/List/CloneDialog.js b/client/src/views/Clone/List/CloneDialog.js index 46525d2c1..90998f09a 100644 --- a/client/src/views/Clone/List/CloneDialog.js +++ b/client/src/views/Clone/List/CloneDialog.js @@ -1,12 +1,9 @@ import React, { Component } from 'react' import AddClone from './AddClone' - -import AddIcon from '@material-ui/icons/Add' import { withStyles } from '@material-ui/core/styles' import styles from './styles' - import { - Button, Dialog, DialogContent, DialogContentText, DialogTitle, Paper, Typography + Button, Dialog, DialogContent, DialogContentText, DialogTitle } from '@material-ui/core' class CloneDialog extends Component { diff --git a/client/src/views/Clone/List/ListClones.js b/client/src/views/Clone/List/ListClones.js index 7eea28c18..3591965e9 100644 --- a/client/src/views/Clone/List/ListClones.js +++ b/client/src/views/Clone/List/ListClones.js @@ -1,20 +1,17 @@ import React, { Component } from 'react' import { graphql, compose } from 'react-apollo' +import {withRouter} from "react-router-dom"; import { clones } from '../../../GraphQL/Calls' -import Poloniex from '../../../img/poloniex.png' -import Binance from '../../../img/binance.png' - import { - Grid, Paper, Typography, Button, TextField, Dialog, DialogContent, + Typography, Button, TextField, Dialog, DialogContent, DialogContentText, DialogTitle, DialogActions, ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, - ExpansionPanelActions, Chip, Divider + ExpansionPanelActions, Divider } from '@material-ui/core' import Avatar from '@material-ui/core/Avatar'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; - -import { tradingStartModes, indicatorStartModes } from '../../../GraphQL/models' +import { tradingStartModesList, indicatorStartModes } from '../../../GraphQL/models' import { isDefined, toLocalTime } from '../../../utils' import classNames from 'classnames' import { withStyles } from '@material-ui/core/styles' @@ -47,7 +44,7 @@ class ListClones extends Component {
- { clone.processName } / { clone.botType === 'TRADER' ? tradingStartModes[clone.mode] : indicatorStartModes[clone.mode] } + { clone.processName } / { clone.botType === 'Trading' ? tradingStartModesList[clone.mode] : indicatorStartModes[clone.mode] }
@@ -93,7 +90,7 @@ class ListClones extends Component {
Last Execution: - { (clone.botType === 'TRADER' && isDefined(clone.assetA) ) && + { (clone.botType === 'Trading' && isDefined(clone.assetA) ) && Buy Average: Sell Average: @@ -105,7 +102,7 @@ class ListClones extends Component {
{ toLocalTime(clone.summaryDate) } - { (clone.botType === 'TRADER' && isDefined(clone.assetA) ) && + { (clone.botType === 'Trading' && isDefined(clone.assetA) ) && {clone.buyAverage} {clone.sellAverage} @@ -148,6 +145,12 @@ class ListClones extends Component { className={classes.buttonList} variant='contained' color='secondary' size='small' onClick={() => this.setState({ isLogsDialogOpen: true })}> + View Process Output + +