diff --git a/package-lock.json b/package-lock.json index 471f83a..239da64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1115,6 +1115,40 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.30", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.30.tgz", + "integrity": "sha512-TsRwpTuKwFNiPhk1UfKgw7zNPeV5RhNp2Uw3pws+9gDAkPGKrtjR1y2lI3SYn7+YzyfuNknflpBA1LRKjt7hMg==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.30", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.30.tgz", + "integrity": "sha512-E3sAXATKCSVnT17HYmZjjbcmwihrNOCkoU7dVMlasrcwiJAHxSKeZ+4WN5O+ElgO/FaYgJmASl8p9N7/B/RttA==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.30" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.14.0.tgz", + "integrity": "sha512-M933RDM8cecaKMWDSk3FRYdnzWGW7kBBlGNGfvqLVwcwhUPNj9gcw+xZMrqBdRqxnSXdl3zWzTCNNGEtFUq67Q==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.30" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.11.tgz", + "integrity": "sha512-sClfojasRifQKI0OPqTy8Ln8iIhnxR/Pv/hukBhWnBz9kQRmqi6JSH3nghlhAY7SUeIIM7B5/D2G8WjX0iepVg==", + "requires": { + "prop-types": "^15.7.2" + } + }, "@hapi/address": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", @@ -1340,6 +1374,82 @@ "@types/yargs": "^13.0.0" } }, + "@material-ui/core": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz", + "integrity": "sha512-bYo9uIub8wGhZySHqLQ833zi4ZML+XCBE1XwJ8EuUVSpTWWG57Pm+YugQToJNFsEyiKFhPh8DPD0bgupz8n01g==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.10.0", + "@material-ui/system": "^4.9.14", + "@material-ui/types": "^5.1.0", + "@material-ui/utils": "^4.10.2", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0", + "react-transition-group": "^4.4.0" + } + }, + "@material-ui/icons": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.9.1.tgz", + "integrity": "sha512-GBitL3oBWO0hzBhvA9KxqcowRUsA0qzwKkURyC8nppnC3fw54KPKZ+d4V1Eeg/UnDRSzDaI9nGCdel/eh9AQMg==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, + "@material-ui/styles": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.10.0.tgz", + "integrity": "sha512-XPwiVTpd3rlnbfrgtEJ1eJJdFCXZkHxy8TrdieaTvwxNYj42VnnCyFzxYeNW9Lhj4V1oD8YtQ6S5Gie7bZDf7Q==", + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "^5.1.0", + "@material-ui/utils": "^4.9.6", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.0.3", + "jss-plugin-camel-case": "^10.0.3", + "jss-plugin-default-unit": "^10.0.3", + "jss-plugin-global": "^10.0.3", + "jss-plugin-nested": "^10.0.3", + "jss-plugin-props-sort": "^10.0.3", + "jss-plugin-rule-value-function": "^10.0.3", + "jss-plugin-vendor-prefixer": "^10.0.3", + "prop-types": "^15.7.2" + } + }, + "@material-ui/system": { + "version": "4.9.14", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.9.14.tgz", + "integrity": "sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.9.6", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + } + }, + "@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==" + }, + "@material-ui/utils": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.10.2.tgz", + "integrity": "sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -1723,6 +1833,14 @@ "@types/react": "*" } }, + "@types/react-transition-group": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.0.tgz", + "integrity": "sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w==", + "requires": { + "@types/react": "*" + } + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -3526,6 +3644,11 @@ "shallow-clone": "^0.1.2" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4030,6 +4153,15 @@ } } }, + "css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "requires": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, "css-what": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", @@ -4489,6 +4621,15 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.4.tgz", + "integrity": "sha512-TjMyeVUvNEnOnhzs6uAn9Ya47GmMo3qq7m+Lr/3ON0Rs5kHvb8I+SQYjLUSYn7qhEm0QjW0yrBkvz9yOrwwz1A==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^2.6.7" + } + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -6257,6 +6398,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -6267,6 +6421,14 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -6470,6 +6632,11 @@ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -6838,6 +7005,11 @@ "is-extglob": "^2.1.1" } }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -7691,6 +7863,84 @@ "verror": "1.10.0" } }, + "jss": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.3.0.tgz", + "integrity": "sha512-B5sTRW9B6uHaUVzSo9YiMEOEp3UX8lWevU0Fsv+xtRnsShmgCfIYX44bTH8bPJe6LQKqEXku3ulKuHLbxBS97Q==", + "requires": { + "@babel/runtime": "^7.3.1", + "csstype": "^2.6.5", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-camel-case": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.3.0.tgz", + "integrity": "sha512-tadWRi/SLWqLK3EUZEdDNJL71F3ST93Zrl9JYMjV0QDqKPAl0Liue81q7m/nFUpnSTXczbKDy4wq8rI8o7WFqA==", + "requires": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "^10.3.0" + } + }, + "jss-plugin-default-unit": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.3.0.tgz", + "integrity": "sha512-tT5KkIXAsZOSS9WDSe8m8lEHIjoEOj4Pr0WrG0WZZsMXZ1mVLFCSsD2jdWarQWDaRNyMj/I4d7czRRObhOxSuw==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "^10.3.0" + } + }, + "jss-plugin-global": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.3.0.tgz", + "integrity": "sha512-etYTG/y3qIR/vxZnKY+J3wXwObyBDNhBiB3l/EW9/pE3WHE//BZdK8LFvQcrCO48sZW1Z6paHo6klxUPP7WbzA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "^10.3.0" + } + }, + "jss-plugin-nested": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.3.0.tgz", + "integrity": "sha512-qWiEkoXNEkkZ+FZrWmUGpf+zBsnEOmKXhkjNX85/ZfWhH9dfGxUCKuJFuOWFM+rjQfxV4csfesq4hY0jk8Qt0w==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "^10.3.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.3.0.tgz", + "integrity": "sha512-boetORqL/lfd7BWeFD3K+IyPqyIC+l3CRrdZr+NPq7Noqp+xyg/0MR7QisgzpxCEulk+j2CRcEUoZsvgPC4nTg==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "^10.3.0" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.3.0.tgz", + "integrity": "sha512-7WiMrKIHH3rwxTuJki9+7nY11r1UXqaUZRhHvqTD4/ZE+SVhvtD5Tx21ivNxotwUSleucA/8boX+NF21oXzr5Q==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "^10.3.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.3.0.tgz", + "integrity": "sha512-sZQbrcZyP5V0ADjCLwUA1spVWoaZvM7XZ+2fSeieZFBj31cRsnV7X70FFDerMHeiHAXKWzYek+67nMDjhrZAVQ==", + "requires": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "^10.3.0" + } + }, "jsx-ast-utils": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", @@ -8165,6 +8415,15 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, + "mini-create-react-context": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz", + "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==", + "requires": { + "@babel/runtime": "^7.5.5", + "tiny-warning": "^1.0.3" + } + }, "mini-css-extract-plugin": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", @@ -9124,6 +9383,11 @@ "ts-pnp": "^1.1.6" } }, + "popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + }, "portfinder": { "version": "1.0.27", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.27.tgz", @@ -10564,6 +10828,64 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", @@ -10624,6 +10946,17 @@ "workbox-webpack-plugin": "4.3.1" } }, + "react-transition-group": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", + "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -10686,6 +11019,20 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -10926,6 +11273,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -12122,6 +12474,11 @@ "util.promisify": "~1.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -12360,6 +12717,16 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -12731,6 +13098,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index b1efdf0..c01809b 100644 --- a/package.json +++ b/package.json @@ -7,14 +7,16 @@ "@fortawesome/free-solid-svg-icons": "^5.14.0", "@fortawesome/react-fontawesome": "^0.1.11", "@material-ui/core": "^4.11.0", - "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", "react": "^16.13.1", "react-dom": "^16.13.1", + "react-redux": "^7.2.0", "react-router-dom": "^5.2.0", - "react-scripts": "3.4.1" + "react-scripts": "3.4.1", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.css b/src/App.css index adadb75..36f46af 100644 --- a/src/App.css +++ b/src/App.css @@ -3,5 +3,5 @@ overflow: hidden; display: block; position: relative; - padding-bottom: 60px; /* height of your footer + 30px*/ + padding-bottom: 60px; /* height of your footer + 30px*/y } diff --git a/src/App.js b/src/App.js index 17ccc55..5f048c8 100644 --- a/src/App.js +++ b/src/App.js @@ -2,6 +2,9 @@ import React from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; +import { Provider } from 'react-redux'; +import store from './store'; + import { ThemeProvider, createMuiTheme } from '@material-ui/core/styles'; import Navbar from './components/Navbar'; @@ -20,15 +23,17 @@ const theme = createMuiTheme({ function App() { return ( - -
- -
- + + +
+ +
+ +
+
-
-
- + + ); } diff --git a/src/actions/types.js b/src/actions/types.js new file mode 100644 index 0000000..0c9a0a7 --- /dev/null +++ b/src/actions/types.js @@ -0,0 +1,5 @@ +export const NEW_WORKSPACE = 'NEW_WORKSPACE'; +export const CREATE_BLOCK = 'CREATE_BLOCK'; +export const CHANGE_BLOCK = 'CHANGE_BLOCK'; +export const DELETE_BLOCK = 'DELETE_BLOCK'; +export const CLEAR_STATS = 'CLEAR_STATS'; diff --git a/src/actions/workspaceActions.js b/src/actions/workspaceActions.js new file mode 100644 index 0000000..905a699 --- /dev/null +++ b/src/actions/workspaceActions.js @@ -0,0 +1,53 @@ +import { NEW_WORKSPACE, CREATE_BLOCK, CHANGE_BLOCK, DELETE_BLOCK, CLEAR_STATS } from './types'; + +export const onChangeWorkspace = (event) => (dispatch, getState) => { + var oldWorkspace = getState().workspace.new; // stored 'new workspace' is from now on old + var newWorkspace = window.Ardublockly.workspace; + dispatch({ + type: NEW_WORKSPACE, + payload: {new: newWorkspace, old: oldWorkspace} + }); + var stats = getState().workspace.stats; + if (event.type === window.Blockly.Events.CREATE){ + stats.create += event.ids.length; + dispatch({ + type: CREATE_BLOCK, + payload: stats + }); + } + else if (event.type === window.Blockly.Events.CHANGE){ + stats.change += 1; + dispatch({ + type: CHANGE_BLOCK, + payload: stats + }); + } + else if (event.type === window.Blockly.Events.DELETE){ + if(stats.create > 0){ + stats.delete += event.ids.length; + dispatch({ + type: DELETE_BLOCK, + payload: stats + }); + } + } +}; + +export const clearStats = () => (dispatch) => { + var stats = { + create: 0, + change: 0, + delete: 0 + }; + dispatch({ + type: CLEAR_STATS, + payload: stats + }); +}; + +export const setWorkspace = (workspace) => (dispatch, getState) => { + dispatch({ + type: NEW_WORKSPACE, + payload: {new: workspace, old: getState().workspace.new} + }); +}; diff --git a/src/components/ClearWorkspace.js b/src/components/ClearWorkspace.js new file mode 100644 index 0000000..9ab4c57 --- /dev/null +++ b/src/components/ClearWorkspace.js @@ -0,0 +1,39 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { clearStats } from '../actions/workspaceActions'; + +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText from '@material-ui/core/ListItemText'; + +import { faTrashRestore } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +class ClearWorkspace extends Component { + + clearWorkspace = () => { + this.props.newWorkspace.clear(); + this.props.clearStats(); + } + + render() { + return ( + {this.clearWorkspace(); this.props.onClick();}}> + + + + ); + }; +} + +ClearWorkspace.propTypes = { + newWorkspace: PropTypes.object.isRequired, + clearStats: PropTypes.func.isRequired +}; + +const mapStateToProps = state => ({ + newWorkspace: state.workspace.new +}); + +export default connect(mapStateToProps, { clearStats })(ClearWorkspace); diff --git a/src/components/Home.js b/src/components/Home.js index 1491af0..bba01a3 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -1,9 +1,14 @@ import React, { Component } from 'react'; +import WorkspaceStats from './WorkspaceStats'; +import WorkspaceFunc from './WorkspaceFunc'; + class Home extends Component { render() { return (
+ +
); }; diff --git a/src/components/MaxBlocks.js b/src/components/MaxBlocks.js new file mode 100644 index 0000000..014fe2e --- /dev/null +++ b/src/components/MaxBlocks.js @@ -0,0 +1,49 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { setWorkspace } from '../actions/workspaceActions'; + +import TextField from '@material-ui/core/TextField'; +import Button from '@material-ui/core/Button'; + +class MaxBlocks extends Component { + + state = { + max: 1, + } + + onChange = (e) => { + this.setState({ [e.target.name]: e.target.value}); + } + + render() { + // var blockLeft = Object.keys(this.props.newWorkspace).length > 0 ?

{this.props.newWorkspace.remainingCapacity()} verbleibende Blöcke möglich

: null + // var error = this.state.error ?
{this.state.error}
: null; + return ( +
+ + +
+ ); + }; +} + +MaxBlocks.propTypes = { + newWorkspace: PropTypes.object.isRequired, + setWorkspace: PropTypes.func.isRequired +}; + +const mapStateToProps = state => ({ + newWorkspace: state.workspace.new +}); + +export default connect(mapStateToProps, { setWorkspace })(MaxBlocks); diff --git a/src/components/Navbar.js b/src/components/Navbar.js index 3d7e2b4..a72d41a 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -1,28 +1,27 @@ -import React, { Component, Fragment } from 'react'; +import React, { Component } from 'react'; import { Link } from 'react-router-dom'; +import ClearWorkspace from './ClearWorkspace'; + import { withStyles } from '@material-ui/core/styles'; import Drawer from '@material-ui/core/Drawer'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; -import CssBaseline from '@material-ui/core/CssBaseline'; import List from '@material-ui/core/List'; import Typography from '@material-ui/core/Typography'; import Divider from '@material-ui/core/Divider'; import IconButton from '@material-ui/core/IconButton'; -import MenuIcon from '@material-ui/icons/Menu'; -import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; -import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; -import InboxIcon from '@material-ui/icons/MoveToInbox'; -import MailIcon from '@material-ui/icons/Mail'; + +import { faBars, faChevronLeft, faBuilding, faIdCard, faEnvelope, faCog, faChalkboardTeacher } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; const styles = (theme) => ({ drawerWidth: { // color: theme.palette.primary.main, - width: window.innerWidth < 600 ? '100%' : '220px', + width: window.innerWidth < 600 ? '100%' : '240px', borderRight: `1px solid ${theme.palette.primary.main}` }, appBarColor: { @@ -58,7 +57,7 @@ class Navbar extends Component { onClick={this.toggleDrawer} style={{margin: '0 10px'}} > - + @@ -81,23 +80,24 @@ class Navbar extends Component { Menü
- +
- {[{text: 'Tutorials', icon: }, {text: 'Einstellungen', icon: }].map((item, index) => ( + {[{text: 'Tutorials', icon: faChalkboardTeacher}, {text: 'Einstellungen', icon: faCog}].map((item, index) => ( - {item.icon} + ))} + - {[{text: 'Über uns', icon: },{text: 'Kontakt', icon: }, {text: 'Impressum', icon: }].map((item, index) => ( + {[{text: 'Über uns', icon: faBuilding},{text: 'Kontakt', icon: faEnvelope}, {text: 'Impressum', icon: faIdCard}].map((item, index) => ( - {item.icon} + ))} diff --git a/src/components/WorkspaceFunc.js b/src/components/WorkspaceFunc.js new file mode 100644 index 0000000..6dd46b9 --- /dev/null +++ b/src/components/WorkspaceFunc.js @@ -0,0 +1,72 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; + +import MaxBlocks from './MaxBlocks'; + +import Button from '@material-ui/core/Button'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogActions from '@material-ui/core/DialogActions'; +import Dialog from '@material-ui/core/Dialog'; + +class WorkspaceFunc extends Component { + + state={ + title: '', + content: '', + open: false + } + + getArdurinoCode = () => { + var code = window.Ardublockly.generateArduino(); + this.setState({title: 'Ardurino Code', content: code, open: true}); + } + + getXMLCode = () => { + var code = window.Ardublockly.generateXml(); + this.setState({title: 'XML Code', content: code, open: true}); + } + + toggleDialog = () => { + this.setState({open: !this.state}); + } + + render() { + return ( +
+ + {this.state.title} + + {this.state.content} + + + + + + + + + +
+ ); + }; +} + +WorkspaceFunc.propTypes = { + newWorkspace: PropTypes.object.isRequired +}; + +const mapStateToProps = state => ({ + newWorkspace: state.workspace.new +}); + +export default connect(mapStateToProps, null)(WorkspaceFunc); diff --git a/src/components/WorkspaceStats.js b/src/components/WorkspaceStats.js new file mode 100644 index 0000000..7eadd99 --- /dev/null +++ b/src/components/WorkspaceStats.js @@ -0,0 +1,80 @@ +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; + +import { withStyles } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; +import Typography from '@material-ui/core/Typography'; + +import { faPuzzlePiece, faTrash, faPlus, faPen } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +const styles = (theme) => ({ + stats: { + backgroundColor: theme.palette.primary.main, + display: 'inline', + marginLeft: '50px', + padding: '3px 10px', + borderRadius: '25%' + } +}); + +class WorkspaceStats extends Component { + + render() { + // var check = Object.keys(this.props.newWorkspace).length > 0 && this.props.create - this.props.delete !== this.props.newWorkspace.getAllBlocks().length ?

FEHLER!

: null; + return ( +
+ +
+ + {Object.keys(this.props.newWorkspace).length > 0 ? this.props.newWorkspace.getAllBlocks().length : 0} +
+
+ +
+ + + {this.props.create} +
+
+ +
+ + + {this.props.change} +
+
+ +
+ + + {this.props.delete} +
+
+ {Object.keys(this.props.newWorkspace).length > 0 ? this.props.newWorkspace.remainingCapacity() !== Infinity ? + + {this.props.delete} verbleibende Blöcke + : null : null} +
+ ); + }; +} + +WorkspaceStats.propTypes = { + newWorkspace: PropTypes.object.isRequired, + create: PropTypes.number.isRequired, + change: PropTypes.number.isRequired, + delete: PropTypes.number.isRequired, + test: PropTypes.number.isRequired +}; + +const mapStateToProps = state => ({ + newWorkspace: state.workspace.new, + create: state.workspace.stats.create, + change: state.workspace.stats.change, + delete: state.workspace.stats.delete, + test: state.workspace.test +}); + +export default connect(mapStateToProps, null)(withStyles(styles, {withTheme: true})(WorkspaceStats)); diff --git a/src/reducers/index.js b/src/reducers/index.js new file mode 100644 index 0000000..de9944c --- /dev/null +++ b/src/reducers/index.js @@ -0,0 +1,6 @@ +import { combineReducers } from 'redux'; +import workspaceReducer from './workspaceReducer'; + +export default combineReducers({ + workspace: workspaceReducer +}); diff --git a/src/reducers/workspaceReducer.js b/src/reducers/workspaceReducer.js new file mode 100644 index 0000000..df9e4bb --- /dev/null +++ b/src/reducers/workspaceReducer.js @@ -0,0 +1,35 @@ +import { NEW_WORKSPACE, CREATE_BLOCK, CHANGE_BLOCK, DELETE_BLOCK, CLEAR_STATS } from '../actions/types'; + + +const initialState = { + old: {}, + new: {}, + stats: { + create: 0, + change: 0, + delete: 0, + }, + test: 0 +}; + +export default function(state = initialState, action){ + switch(action.type){ + case NEW_WORKSPACE: + return { + ...state, + old: action.payload.old, + new: action.payload.new, + test: state.test += 1 + }; + case CREATE_BLOCK: + case CHANGE_BLOCK: + case DELETE_BLOCK: + case CLEAR_STATS: + return { + ...state, + stats: action.payload + }; + default: + return state; + } +} diff --git a/src/store.js b/src/store.js new file mode 100644 index 0000000..bd28ae1 --- /dev/null +++ b/src/store.js @@ -0,0 +1,18 @@ +import { createStore, applyMiddleware, compose } from 'redux'; +import thunk from 'redux-thunk'; +import rootReducer from './reducers'; + +const initialState = {}; + +const middleware = [thunk]; + +const store = createStore( + rootReducer, + initialState, + compose( + applyMiddleware(...middleware), + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() + ) +); + +export default store;