From 78b9ae101ea81021ebf310879b472f9e28e4b66f Mon Sep 17 00:00:00 2001 From: Rick Watson Date: Sat, 30 Nov 2019 12:34:52 +0000 Subject: [PATCH] Add restart service for esp8266 and esp32 Add restart feature to status screen Upgrade material-ui Add icons to buttons --- interface/package-lock.json | 188 ++++++++++---------- interface/package.json | 6 +- interface/src/App.js | 39 ++-- interface/src/constants/Endpoints.js | 1 + interface/src/containers/APStatus.js | 3 +- interface/src/containers/NTPStatus.js | 3 +- interface/src/containers/SystemStatus.js | 77 +++++++- interface/src/containers/WiFiStatus.js | 3 +- interface/src/forms/APSettingsForm.js | 3 +- interface/src/forms/ManageUsersForm.js | 6 +- interface/src/forms/NTPSettingsForm.js | 3 +- interface/src/forms/OTASettingsForm.js | 3 +- interface/src/forms/SecuritySettingsForm.js | 3 +- interface/src/forms/WiFiNetworkSelector.js | 3 +- interface/src/forms/WiFiSettingsForm.js | 3 +- interface/src/project/DemoController.js | 3 +- lib/framework/ESP8266React.cpp | 1 + lib/framework/ESP8266React.h | 3 + lib/framework/RestartService.cpp | 14 ++ lib/framework/RestartService.h | 29 +++ 20 files changed, 265 insertions(+), 129 deletions(-) create mode 100644 lib/framework/RestartService.cpp create mode 100644 lib/framework/RestartService.h diff --git a/interface/package-lock.json b/interface/package-lock.json index 37b3767..f5b38b4 100644 --- a/interface/package-lock.json +++ b/interface/package-lock.json @@ -1184,21 +1184,19 @@ } }, "@material-ui/core": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.4.3.tgz", - "integrity": "sha512-Lz8sMFeCrtq5/pbhqClWFHpveL0huixjca0tw7uvh9xKKB7VyyYOyTu7RamSZLxb34UCSMPlobR+KK25Nqzkqw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.7.0.tgz", + "integrity": "sha512-mwLehUo0Q9ZxjuWo7J1uy1/Grh3nRxlOAaWJ3EtKeJP2HwqlSy8bWrcvRQYlapaYIPXa5jN8zWbTwi8Pk30VQg==", "requires": { "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.4.3", - "@material-ui/system": "^4.4.3", + "@material-ui/styles": "^4.6.0", + "@material-ui/system": "^4.5.2", "@material-ui/types": "^4.1.1", - "@material-ui/utils": "^4.4.0", + "@material-ui/utils": "^4.5.2", "@types/react-transition-group": "^4.2.0", "clsx": "^1.0.2", "convert-css-length": "^2.0.1", - "deepmerge": "^4.0.0", "hoist-non-react-statics": "^3.2.1", - "is-plain-object": "^3.0.0", "normalize-scroll-left": "^0.2.0", "popper.js": "^1.14.1", "prop-types": "^15.7.2", @@ -1206,44 +1204,43 @@ } }, "@material-ui/icons": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.4.3.tgz", - "integrity": "sha512-HVVvUyc/78kmaBd93LkfWyGkXMM+zOMKzUfulWXxaV/fFAZ3N0pD0oHjWUd94zrOoF3tZP9JC7EPlIpIcZSNow==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.5.1.tgz", + "integrity": "sha512-YZ/BgJbXX4a0gOuKWb30mBaHaoXRqPanlePam83JQPZ/y4kl+3aW0Wv9tlR70hB5EGAkEJGW5m4ktJwMgxQAeA==", "requires": { "@babel/runtime": "^7.4.4" } }, "@material-ui/styles": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.4.3.tgz", - "integrity": "sha512-kNUdHFWsrvWKIEPx8Xy2/qayqsGMrYmCMq+FIiJiYczVZl5hiS8j5+KayonnpVta/O+Dktk+cxWkVcgwtxMrHg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.6.0.tgz", + "integrity": "sha512-lqqh4UEMdIYcU1Yth4pQyMTah02uAkg3NOT3MirN9FUexdL8pNA6zCHigEgDSfwmvnXyxHhxTkphfy0DRfnt9w==", "requires": { "@babel/runtime": "^7.4.4", "@emotion/hash": "^0.7.1", "@material-ui/types": "^4.1.1", - "@material-ui/utils": "^4.1.0", + "@material-ui/utils": "^4.5.2", "clsx": "^1.0.2", "csstype": "^2.5.2", - "deepmerge": "^4.0.0", "hoist-non-react-statics": "^3.2.1", - "jss": "10.0.0-alpha.25", - "jss-plugin-camel-case": "10.0.0-alpha.25", - "jss-plugin-default-unit": "10.0.0-alpha.25", - "jss-plugin-global": "10.0.0-alpha.25", - "jss-plugin-nested": "10.0.0-alpha.25", - "jss-plugin-props-sort": "10.0.0-alpha.25", - "jss-plugin-rule-value-function": "10.0.0-alpha.25", - "jss-plugin-vendor-prefixer": "10.0.0-alpha.25", + "jss": "^10.0.0", + "jss-plugin-camel-case": "^10.0.0", + "jss-plugin-default-unit": "^10.0.0", + "jss-plugin-global": "^10.0.0", + "jss-plugin-nested": "^10.0.0", + "jss-plugin-props-sort": "^10.0.0", + "jss-plugin-rule-value-function": "^10.0.0", + "jss-plugin-vendor-prefixer": "^10.0.0", "prop-types": "^15.7.2" } }, "@material-ui/system": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.4.3.tgz", - "integrity": "sha512-Cb05vLXsaCzssXD/iZKa0/qC6YOwbFWnYdnOEdkXZ3Fn2Ytz7rsnMgFejUSQV1luVhUBlEIm8DVz40N25WwW7w==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.5.2.tgz", + "integrity": "sha512-h9RWvdM9XKlHHqwiuhyvWdobptQkHli+m2jJFs7i1AI/hmGsIc4reDmS7fInhETgt/Txx7uiAIznfRNIIVHmQw==", "requires": { "@babel/runtime": "^7.4.4", - "deepmerge": "^4.0.0", + "@material-ui/utils": "^4.5.2", "prop-types": "^15.7.2" } }, @@ -1256,9 +1253,9 @@ } }, "@material-ui/utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.4.0.tgz", - "integrity": "sha512-UXoQVwArQEQWXxf2FPs0iJGT+MePQpKr0Qh0CPoLc1OdF0GSMTmQczcqCzwZkeHxHAOq/NkIKM1Pb/ih1Avicg==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.5.2.tgz", + "integrity": "sha512-zhbNfHd1gLa8At6RPDG7uMZubHxbY+LtM6IkSfeWi6Lo4Ax80l62YaN1QmUpO1IvGCkn/j62tQX3yObiQZrJsQ==", "requires": { "@babel/runtime": "^7.4.4", "prop-types": "^15.7.2", @@ -1486,18 +1483,18 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" }, "@types/react": { - "version": "16.9.4", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.4.tgz", - "integrity": "sha512-ItGNmJvQ0IvWt8rbk5PLdpdQhvBVxAaXI9hDlx7UMd8Ie1iMIuwMNiKeTfmVN517CdplpyXvA22X4zm4jGGZnw==", + "version": "16.9.13", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.13.tgz", + "integrity": "sha512-LikzRslbiufJYHyzbHSW0GrAiff8QYLMBFeZmSxzCYGXKxi8m/1PHX+rsVOwhr7mJNq+VIu2Dhf7U6mjFERK6w==", "requires": { "@types/prop-types": "*", "csstype": "^2.2.0" } }, "@types/react-transition-group": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.2.tgz", - "integrity": "sha512-YfoaTNqBwbIqpiJ5NNfxfgg5kyFP1Hqf/jqBtSWNv0E+EkkxmN+3VD6U2fu86tlQvdAc1o0SdWhnWFwcRMTn9A==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.2.3.tgz", + "integrity": "sha512-Hk8jiuT7iLOHrcjKP/ZVSyCNXK73wJAUz60xm0mVhiRujrdiI++j4duLiL282VGxwAgxetHQFfqA29LgEeSkFA==", "requires": { "@types/react": "*" } @@ -4210,11 +4207,6 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, - "deepmerge": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.0.0.tgz", - "integrity": "sha512-YZ1rOP5+kHor4hMAH+HRQnBQHg+wvS1un1hAOuIcxcBy0hzcUf6Jg2a1w65kpoOUnurOfZbERwjI1TfZxNjcww==" - }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -4439,12 +4431,27 @@ } }, "dom-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.0.tgz", - "integrity": "sha512-zRRYDhpiKuAJHasOqCm7lBnsd22nrM4+OYI4ASWCxen+ocTMl7BIAKgGag97TlLiTl6rrau5aPe1VGUm9jQBng==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.3.tgz", + "integrity": "sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw==", "requires": { - "@babel/runtime": "^7.5.5", - "csstype": "^2.6.6" + "@babel/runtime": "^7.6.3", + "csstype": "^2.6.7" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.4.tgz", + "integrity": "sha512-r24eVUUr0QqNZa+qrImUk8fn5SPhHq+IfYvIoIMg0do3GdK9sMdiLKP3GYVVaxpPKORgm8KRKaNTEhAjgIpLMw==", + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "csstype": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.7.tgz", + "integrity": "sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==" + } } }, "dom-serializer": { @@ -6548,14 +6555,6 @@ "path-is-inside": "^1.0.1" } }, - "is-plain-object": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", - "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", - "requires": { - "isobject": "^4.0.0" - } - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -6630,11 +6629,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==" - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -7889,9 +7883,9 @@ } }, "jss": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.25.tgz", - "integrity": "sha512-zqKnXv181B9vue2yYhmVhc+6ggbbxHF/33rjXfXEjaa22nOvknTI21QDfq3oZ8uCC50kcFp3Z8KU1ghUXdFvIA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0.tgz", + "integrity": "sha512-TPpDFsiBjuERiL+dFDq8QCdiF9oDasPcNqCKLGCo/qED3fNYOQ8PX2lZhknyTiAt3tZrfOFbb0lbQ9lTjPZxsQ==", "requires": { "@babel/runtime": "^7.3.1", "csstype": "^2.6.5", @@ -7900,13 +7894,13 @@ } }, "jss-plugin-camel-case": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0-alpha.25.tgz", - "integrity": "sha512-J5ZEGDTy9ddqdTUPAF4SJQ25u5kiG1ORP8F+ZPEZAkkiMQJp+/Aol4I7xhTS2aW1Lhg8xNxdhdRfBi5yU7wOvg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0.tgz", + "integrity": "sha512-yALDL00+pPR4FJh+k07A8FeDvfoPPuXU48HLy63enAubcVd3DnS+2rgqPXglHDGixIDVkCSXecl/l5GAMjzIbA==", "requires": { "@babel/runtime": "^7.3.1", "hyphenate-style-name": "^1.0.3", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-plugin-compose": { @@ -7933,12 +7927,12 @@ } }, "jss-plugin-default-unit": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0-alpha.25.tgz", - "integrity": "sha512-auOG459B+yEqkojgaXH02SYO9+xjmAxlmP+WbzhVpXqOFJ2CN/kaxd8P4NJZLdj3BQxHiM7WIyMVh786StE+EA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0.tgz", + "integrity": "sha512-sURozIOdCtGg9ap18erQ+ijndAfEGtTaetxfU3H4qwC18Bi+fdvjlY/ahKbuu0ASs7R/+WKCP7UaRZOjUDMcdQ==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-plugin-expand": { @@ -7987,40 +7981,40 @@ } }, "jss-plugin-global": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.0-alpha.25.tgz", - "integrity": "sha512-cS98Q8X8jwltuaBZd9eYuxMXxkUL+mJGl2Ok3/nmJzH9nLzj6i7kLxSoDtuJNqsRmbP7ogIXVozJUq9lUu2hlQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.0.tgz", + "integrity": "sha512-80ofWKSQUo62bxLtRoTNe0kFPtHgUbAJeOeR36WEGgWIBEsXLyXOnD5KNnjPqG4heuEkz9eSLccjYST50JnI7Q==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-plugin-nested": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.0-alpha.25.tgz", - "integrity": "sha512-7sk7/6mX1YTgXe+AyeD1zEyKTgIGbbhYtg+wWQcHJlE1flW2JHfcQ5mw84FgHcHQRQ8Dq3l9I3aEY51ev0J1Wg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.0.tgz", + "integrity": "sha512-waxxwl/po1hN3azTyixKnr8ReEqUv5WK7WsO+5AWB0bFndML5Yqnt8ARZ90HEg8/P6WlqE/AB2413TkCRZE8bA==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.0.0-alpha.25", + "jss": "10.0.0", "tiny-warning": "^1.0.2" } }, "jss-plugin-props-sort": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0-alpha.25.tgz", - "integrity": "sha512-8B/6QLQuUX8cIlZbXdjEm5l0jCX4EgacYMcFJhdKwDKEZYeAghpgQQrCKl0/CYHW7iFge5wim67P+uL6QxMzyw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0.tgz", + "integrity": "sha512-41mf22CImjwNdtOG3r+cdC8+RhwNm616sjHx5YlqTwtSJLyLFinbQC/a4PIFk8xqf1qpFH1kEAIw+yx9HaqZ3g==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-plugin-rule-value-function": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0-alpha.25.tgz", - "integrity": "sha512-CQQtWO+/OZRGaFRBSGQUgAci9YlVtdoXcWQKBNo70tmpp+kaXKlFNCYaL3jmHbJHMiwKQYG2RYFQNIrwJ9SGmA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0.tgz", + "integrity": "sha512-Jw+BZ8JIw1f12V0SERqGlBT1JEPWax3vuZpMym54NAXpPb7R1LYHiCTIlaJUyqvIfEy3kiHMtgI+r2whGgRIxQ==", "requires": { "@babel/runtime": "^7.3.1", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-plugin-rule-value-observable": { @@ -8070,13 +8064,13 @@ } }, "jss-plugin-vendor-prefixer": { - "version": "10.0.0-alpha.25", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0-alpha.25.tgz", - "integrity": "sha512-5FXpB/TiwckbrkoDCmd27YsWCESl1K4hAX/oro2/geEXgnVQvDgQOf2eWCsjYO2K1lYPPXtskMfws/Q3eKmbYg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0.tgz", + "integrity": "sha512-qslqvL0MUbWuzXJWdUxpj6mdNUX8jr4FFTo3aZnAT65nmzWL7g8oTr9ZxmTXXgdp7ANhS1QWE7036/Q2isFBpw==", "requires": { "@babel/runtime": "^7.3.1", "css-vendor": "^2.0.6", - "jss": "10.0.0-alpha.25" + "jss": "10.0.0" } }, "jss-preset-default": { @@ -8940,9 +8934,9 @@ "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==" }, "notistack": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/notistack/-/notistack-0.8.9.tgz", - "integrity": "sha512-nRHQVWUfgHnvnKrjRbRX9f+YAnbyh96yRyO5bEP/FCLVLuTZcJOwUr0GZ7Xr/8wK3+hXa9JYpXUkUhSxj1K8NQ==", + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/notistack/-/notistack-0.9.6.tgz", + "integrity": "sha512-vo1zOwhQBxwWiMxwVjeSDXNzJuaM/nfkayv4uRo+9ON9CAtaPSNt15QHeELKkbOSLH29fb7zmoZl4AlkCqhGsA==", "requires": { "classnames": "^2.2.6", "hoist-non-react-statics": "^3.3.0", @@ -9526,9 +9520,9 @@ } }, "popper.js": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz", - "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA==" + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.0.tgz", + "integrity": "sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw==" }, "portfinder": { "version": "1.0.24", diff --git a/interface/package.json b/interface/package.json index c89bd10..e91090c 100644 --- a/interface/package.json +++ b/interface/package.json @@ -3,12 +3,12 @@ "version": "0.1.0", "private": true, "dependencies": { - "@material-ui/core": "^4.4.3", - "@material-ui/icons": "^4.4.3", + "@material-ui/core": "^4.7.0", + "@material-ui/icons": "^4.5.1", "compression-webpack-plugin": "^2.0.0", "jwt-decode": "^2.2.0", "moment": "^2.24.0", - "notistack": "^0.8.9", + "notistack": "^0.9.6", "prop-types": "^15.7.2", "react": "^16.10.1", "react-dom": "^16.10.1", diff --git a/interface/src/App.js b/interface/src/App.js index d26b8a4..06e9a65 100644 --- a/interface/src/App.js +++ b/interface/src/App.js @@ -2,22 +2,16 @@ import React, { Component } from 'react'; import { Redirect, Route, Switch } from 'react-router'; import AppRouting from './AppRouting'; +import { PROJECT_NAME } from './constants/Env'; + import { SnackbarProvider } from 'notistack'; - -import CssBaseline from '@material-ui/core/CssBaseline'; -import blueGrey from '@material-ui/core/colors/blueGrey'; -import indigo from '@material-ui/core/colors/indigo'; -import orange from '@material-ui/core/colors/orange'; -import red from '@material-ui/core/colors/red'; -import green from '@material-ui/core/colors/green'; - import { create } from 'jss'; -import { StylesProvider, jssPreset } from '@material-ui/styles'; -import { - MuiThemeProvider, - createMuiTheme -} from '@material-ui/core/styles'; +import { CssBaseline, IconButton, MuiThemeProvider, createMuiTheme } from '@material-ui/core'; +import { StylesProvider, jssPreset } from '@material-ui/styles'; +import { blueGrey, indigo, orange, red, green } from '@material-ui/core/colors'; +import CloseIcon from '@material-ui/icons/Close'; + // Our theme const theme = createMuiTheme({ @@ -38,11 +32,28 @@ const jss = create(jssPreset()); const unauthorizedRedirect = () => ; class App extends Component { + + notistackRef = React.createRef(); + + componentDidMount() { + document.title = PROJECT_NAME; + } + + onClickDismiss = (key) => () => { + this.notistackRef.current.closeSnackbar(key); + } + render() { return ( - + ( + + + + )}> diff --git a/interface/src/constants/Endpoints.js b/interface/src/constants/Endpoints.js index 5474bdf..2fc772d 100644 --- a/interface/src/constants/Endpoints.js +++ b/interface/src/constants/Endpoints.js @@ -13,3 +13,4 @@ export const SYSTEM_STATUS_ENDPOINT = ENDPOINT_ROOT + "systemStatus"; export const SIGN_IN_ENDPOINT = ENDPOINT_ROOT + "signIn"; export const VERIFY_AUTHORIZATION_ENDPOINT = ENDPOINT_ROOT + "verifyAuthorization"; export const SECURITY_SETTINGS_ENDPOINT = ENDPOINT_ROOT + "securitySettings"; +export const RESTART_ENDPOINT = ENDPOINT_ROOT + "restart"; diff --git a/interface/src/containers/APStatus.js b/interface/src/containers/APStatus.js index eadaf9b..d4ced8e 100644 --- a/interface/src/containers/APStatus.js +++ b/interface/src/containers/APStatus.js @@ -11,6 +11,7 @@ import Divider from '@material-ui/core/Divider'; import SettingsInputAntennaIcon from '@material-ui/icons/SettingsInputAntenna'; import DeviceHubIcon from '@material-ui/icons/DeviceHub'; import ComputerIcon from '@material-ui/icons/Computer'; +import RefreshIcon from '@material-ui/icons/Refresh'; import { restComponent } from '../components/RestComponent'; import LoadingNotification from '../components/LoadingNotification'; @@ -93,7 +94,7 @@ class APStatus extends Component { {this.createListItems(data, classes)} - diff --git a/interface/src/containers/NTPStatus.js b/interface/src/containers/NTPStatus.js index f58e467..77e35cf 100644 --- a/interface/src/containers/NTPStatus.js +++ b/interface/src/containers/NTPStatus.js @@ -14,6 +14,7 @@ import DNSIcon from '@material-ui/icons/Dns'; import TimerIcon from '@material-ui/icons/Timer'; import UpdateIcon from '@material-ui/icons/Update'; import AvTimerIcon from '@material-ui/icons/AvTimer'; +import RefreshIcon from '@material-ui/icons/Refresh'; import { isSynchronized, ntpStatusHighlight, ntpStatus } from '../constants/NTPStatus'; import * as Highlight from '../constants/Highlight'; @@ -118,7 +119,7 @@ class NTPStatus extends Component { {this.createListItems(data, classes)} - diff --git a/interface/src/containers/SystemStatus.js b/interface/src/containers/SystemStatus.js index 560c936..b2ae237 100644 --- a/interface/src/containers/SystemStatus.js +++ b/interface/src/containers/SystemStatus.js @@ -1,4 +1,5 @@ import React, { Component, Fragment } from 'react'; +import { withSnackbar } from 'notistack'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; @@ -8,16 +9,24 @@ import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemText from '@material-ui/core/ListItemText'; import Avatar from '@material-ui/core/Avatar'; import Divider from '@material-ui/core/Divider'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import DialogContent from '@material-ui/core/DialogContent'; + import DevicesIcon from '@material-ui/icons/Devices'; import MemoryIcon from '@material-ui/icons/Memory'; import ShowChartIcon from '@material-ui/icons/ShowChart'; import SdStorageIcon from '@material-ui/icons/SdStorage'; import DataUsageIcon from '@material-ui/icons/DataUsage'; +import AutorenewIcon from '@material-ui/icons/Autorenew'; +import RefreshIcon from '@material-ui/icons/Refresh'; -import { SYSTEM_STATUS_ENDPOINT } from '../constants/Endpoints'; +import { SYSTEM_STATUS_ENDPOINT, RESTART_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; import LoadingNotification from '../components/LoadingNotification'; import SectionContent from '../components/SectionContent'; +import { redirectingAuthorizedFetch } from '../authentication/Authentication'; const styles = theme => ({ button: { @@ -28,6 +37,16 @@ const styles = theme => ({ class SystemStatus extends Component { + + constructor(props) { + super(props); + + this.state = { + confirmRestart: false, + processing: false + } + } + componentDidMount() { this.props.loadData(); } @@ -90,13 +109,63 @@ class SystemStatus extends Component { {this.createListItems(data, classes)} - + ); } + onRestart = () => { + this.setState({ confirmRestart: true }); + } + + onRestartRejected = () => { + this.setState({ confirmRestart: false }); + } + + onRestartConfirmed = () => { + this.setState({ processing: true }); + redirectingAuthorizedFetch(RESTART_ENDPOINT, { method: 'POST' }) + .then(response => { + if (response.status === 200) { + this.props.enqueueSnackbar("Device is restarting", { variant: 'info' }); + this.setState({ processing: false, confirmRestart: false }); + } else { + throw Error("Invalid status code: " + response.status); + } + }) + .catch(error => { + this.props.enqueueSnackbar(error.message || "Problem restarting device", { variant: 'error' }); + this.setState({ processing: false, confirmRestart: false }); + }); + } + + renderRestartDialog() { + return ( + + Confirm Restart + + Are you sure you want to restart the device? + + + + + + + ) + } + render() { const { data, fetched, errorMessage, loadData, classes } = this.props; return ( @@ -109,9 +178,11 @@ class SystemStatus extends Component { () => this.renderSystemStatus(data, classes) } /> + {this.renderRestartDialog()} ) } + } -export default restComponent(SYSTEM_STATUS_ENDPOINT, withStyles(styles)(SystemStatus)); +export default withSnackbar(restComponent(SYSTEM_STATUS_ENDPOINT, withStyles(styles)(SystemStatus))); diff --git a/interface/src/containers/WiFiStatus.js b/interface/src/containers/WiFiStatus.js index 43724d9..419105c 100644 --- a/interface/src/containers/WiFiStatus.js +++ b/interface/src/containers/WiFiStatus.js @@ -13,6 +13,7 @@ import DNSIcon from '@material-ui/icons/Dns'; import SettingsInputComponentIcon from '@material-ui/icons/SettingsInputComponent'; import SettingsInputAntennaIcon from '@material-ui/icons/SettingsInputAntenna'; import DeviceHubIcon from '@material-ui/icons/DeviceHub'; +import RefreshIcon from '@material-ui/icons/Refresh'; import SectionContent from '../components/SectionContent'; import { WIFI_STATUS_ENDPOINT } from '../constants/Endpoints'; @@ -130,7 +131,7 @@ class WiFiStatus extends Component { {this.createListItems(data, classes)} - diff --git a/interface/src/forms/APSettingsForm.js b/interface/src/forms/APSettingsForm.js index e708884..e8d1521 100644 --- a/interface/src/forms/APSettingsForm.js +++ b/interface/src/forms/APSettingsForm.js @@ -8,6 +8,7 @@ import PasswordValidator from '../components/PasswordValidator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; import MenuItem from '@material-ui/core/MenuItem'; +import SaveIcon from '@material-ui/icons/Save'; const styles = theme => ({ textField: { @@ -61,7 +62,7 @@ class APSettingsForm extends React.Component { /> } - @@ -176,7 +178,7 @@ class ManageUsersForm extends React.Component { } - diff --git a/interface/src/forms/WiFiSettingsForm.js b/interface/src/forms/WiFiSettingsForm.js index eb365ae..0bf2859 100644 --- a/interface/src/forms/WiFiSettingsForm.js +++ b/interface/src/forms/WiFiSettingsForm.js @@ -16,6 +16,7 @@ import IconButton from '@material-ui/core/IconButton'; import LockIcon from '@material-ui/icons/Lock'; import LockOpenIcon from '@material-ui/icons/LockOpen'; import DeleteIcon from '@material-ui/icons/Delete'; +import SaveIcon from '@material-ui/icons/Save'; import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; import { isNetworkOpen, networkSecurityMode } from '../constants/WiFiSecurityModes'; @@ -175,7 +176,7 @@ class WiFiSettingsForm extends React.Component { /> } -