Upgrade to material ui 4
Add user management and roles - TBA Menu Label Renames - TBA
This commit is contained in:
		
							
								
								
									
										571
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										571
									
								
								interface/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -890,68 +890,105 @@ | ||||
|       "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", | ||||
|       "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" | ||||
|     }, | ||||
|     "@emotion/hash": { | ||||
|       "version": "0.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.7.1.tgz", | ||||
|       "integrity": "sha512-OYpa/Sg+2GDX+jibUfpZVn1YqSVRpYmTLF2eyAfrFTIJSbwyIrc+YscayoykvaOME/wV4BV0Sa0yqdMrgse6mA==" | ||||
|     }, | ||||
|     "@material-ui/core": { | ||||
|       "version": "3.9.3", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.9.3.tgz", | ||||
|       "integrity": "sha512-REIj62+zEvTgI/C//YL4fZxrCVIySygmpZglsu/Nl5jPqy3CDjZv1F9ubBYorHqmRgeVPh64EghMMWqk4egmfg==", | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.0.0.tgz", | ||||
|       "integrity": "sha512-mLEGTuzgUALRKFI3hkRcS0gi/cB3XV0JA4F5PT3rGUt7Dc4liu8/IGiHF7iQh+p337FMk8vkEMxMVdYd9JXKMQ==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.2.0", | ||||
|         "@material-ui/system": "^3.0.0-alpha.0", | ||||
|         "@material-ui/utils": "^3.0.0-alpha.2", | ||||
|         "@types/jss": "^9.5.6", | ||||
|         "@types/react-transition-group": "^2.0.8", | ||||
|         "brcast": "^3.0.1", | ||||
|         "classnames": "^2.2.5", | ||||
|         "@material-ui/styles": "^4.0.0", | ||||
|         "@material-ui/system": "^4.0.0", | ||||
|         "@material-ui/types": "^4.0.0", | ||||
|         "@material-ui/utils": "^4.0.0", | ||||
|         "@types/react-transition-group": "^2.0.16", | ||||
|         "clsx": "^1.0.2", | ||||
|         "convert-css-length": "^1.0.2", | ||||
|         "csstype": "^2.5.2", | ||||
|         "debounce": "^1.1.0", | ||||
|         "deepmerge": "^3.0.0", | ||||
|         "dom-helpers": "^3.2.1", | ||||
|         "hoist-non-react-statics": "^3.2.1", | ||||
|         "is-plain-object": "^2.0.4", | ||||
|         "jss": "^9.8.7", | ||||
|         "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", | ||||
|         "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", | ||||
|         "prop-types": "^15.7.2", | ||||
|         "react-event-listener": "^0.6.6", | ||||
|         "react-transition-group": "^4.0.0", | ||||
|         "warning": "^4.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "@material-ui/icons": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-3.0.2.tgz", | ||||
|       "integrity": "sha512-QY/3gJnObZQ3O/e6WjH+0ah2M3MOgLOzCy8HTUoUx9B6dDrS18vP7Ycw3qrDEKlB6q1KNxy6CZHm5FCauWGy2g==", | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.0.0.tgz", | ||||
|       "integrity": "sha512-hXoKnVLmVer+kic84ypoyG3Amym3a8q3pvDg4KYjeKW9fxGru7x/IkelBJODQL0jO+nAPz1+9RNpFWC75v35dg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "@material-ui/styles": { | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.0.0.tgz", | ||||
|       "integrity": "sha512-TUpmXlyZDVOl6E2//+UzsZxgi2E+2L753QY02nNkbAC6PPx8FUBqvnjYSGqX0V/BjTJ/fD4CkoS6ZpY3lHf+Gg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.2.0", | ||||
|         "recompose": "0.28.0 - 0.30.0" | ||||
|         "@emotion/hash": "^0.7.1", | ||||
|         "@material-ui/types": "^4.0.0", | ||||
|         "@material-ui/utils": "^4.0.0", | ||||
|         "clsx": "^1.0.2", | ||||
|         "deepmerge": "^3.0.0", | ||||
|         "hoist-non-react-statics": "^3.2.1", | ||||
|         "jss": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-camel-case": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-default-unit": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-global": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-nested": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-props-sort": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-rule-value-function": "^10.0.0-alpha.16", | ||||
|         "jss-plugin-vendor-prefixer": "^10.0.0-alpha.16", | ||||
|         "prop-types": "^15.7.2", | ||||
|         "warning": "^4.0.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@material-ui/system": { | ||||
|       "version": "3.0.0-alpha.2", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-3.0.0-alpha.2.tgz", | ||||
|       "integrity": "sha512-odmxQ0peKpP7RQBQ8koly06YhsPzcoVib1vByVPBH4QhwqBXuYoqlCjt02846fYspAqkrWzjxnWUD311EBbxOA==", | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.0.0.tgz", | ||||
|       "integrity": "sha512-SIsqIwjix98Mqw9LVAmRqTs10E4S/SP5n5mlBlhHVHI+2XG2c+MaCPzOF2Zxq0KdqOMgTb7/aevR3mG9UmODxg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.2.0", | ||||
|         "deepmerge": "^3.0.0", | ||||
|         "prop-types": "^15.6.0", | ||||
|         "prop-types": "^15.7.2", | ||||
|         "warning": "^4.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "@material-ui/types": { | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-4.0.0.tgz", | ||||
|       "integrity": "sha512-wuiQMo8nSljZR1oWh57UQYssdtFqaU+Cbhr16uLohzzTllpCAK4LkH0slnH3n+5vCa2dgOdNlZTrmsIDDwvRJQ==" | ||||
|     }, | ||||
|     "@material-ui/utils": { | ||||
|       "version": "3.0.0-alpha.3", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.3.tgz", | ||||
|       "integrity": "sha512-rwMdMZptX0DivkqBuC+Jdq7BYTXwqKai5G5ejPpuEDKpWzi1Oxp+LygGw329FrKpuKeiqpcymlqJTjmy+quWng==", | ||||
|       "version": "4.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.0.0.tgz", | ||||
|       "integrity": "sha512-gjz52hO1hkIbKPMng1diQybVgtfgCptOCrulUs4emSCHHKUoR1zfT+IUrjgOaKIpYZNOgS/CI7KDMp689+FzeQ==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.2.0", | ||||
|         "prop-types": "^15.6.0", | ||||
|         "react-is": "^16.6.3" | ||||
|         "prop-types": "^15.7.2", | ||||
|         "react-is": "^16.8.0" | ||||
|       } | ||||
|     }, | ||||
|     "@mrmlnc/readdir-enhanced": { | ||||
| @@ -1107,24 +1144,15 @@ | ||||
|         "loader-utils": "^1.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "@types/jss": { | ||||
|       "version": "9.5.8", | ||||
|       "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.8.tgz", | ||||
|       "integrity": "sha512-bBbHvjhm42UKki+wZpR89j73ykSXg99/bhuKuYYePtpma3ZAnmeGnl0WxXiZhPGsIfzKwCUkpPC0jlrVMBfRxA==", | ||||
|       "requires": { | ||||
|         "csstype": "^2.0.0", | ||||
|         "indefinite-observable": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "@types/node": { | ||||
|       "version": "11.13.4", | ||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.4.tgz", | ||||
|       "integrity": "sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==" | ||||
|     }, | ||||
|     "@types/prop-types": { | ||||
|       "version": "15.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.0.tgz", | ||||
|       "integrity": "sha512-eItQyV43bj4rR3JPV0Skpl1SncRCdziTEK9/v8VwXmV6d/qOUO8/EuWeHBbCZcsfSHfzI5UyMJLCSXtxxznyZg==" | ||||
|       "version": "15.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", | ||||
|       "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==" | ||||
|     }, | ||||
|     "@types/q": { | ||||
|       "version": "1.5.2", | ||||
| @@ -1132,18 +1160,18 @@ | ||||
|       "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" | ||||
|     }, | ||||
|     "@types/react": { | ||||
|       "version": "16.8.13", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.13.tgz", | ||||
|       "integrity": "sha512-otJ4ntMuHGrvm67CdDJMAls4WqotmAmW0g3HmWi9LCjSWXrxoXY/nHXrtmMfvPEEmGFNm6NdgMsJmnfH820Qaw==", | ||||
|       "version": "16.8.18", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.18.tgz", | ||||
|       "integrity": "sha512-lUXdKzRqWR4FebR5tGHkLCqnvQJS4fdXKCBrNGGbglqZg2gpU+J82pMONevQODUotATs9fc9k66bx3/St8vReg==", | ||||
|       "requires": { | ||||
|         "@types/prop-types": "*", | ||||
|         "csstype": "^2.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "@types/react-transition-group": { | ||||
|       "version": "2.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.9.0.tgz", | ||||
|       "integrity": "sha512-hP7vUaZMVSWKxo133P8U51U6UZ7+pbY+eAQb8+p6SZ2rB1rj3mOTDgTzhhi+R2SCB4S+sWekAAGoxdiZPG0ReQ==", | ||||
|       "version": "2.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.9.1.tgz", | ||||
|       "integrity": "sha512-1usq4DRUVBFnxc9KGJAlJO9EpQrLZGDDEC8wDOn2+2ODSyudYo8FiIzPDRaX/hfQjHqGeeoNaNdA2bj0l35hZQ==", | ||||
|       "requires": { | ||||
|         "@types/react": "*" | ||||
|       } | ||||
| @@ -2686,11 +2714,6 @@ | ||||
|         "repeat-element": "^1.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "brcast": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.1.tgz", | ||||
|       "integrity": "sha512-eI3yqf9YEqyGl9PCNTR46MGvDylGtaHjalcz6Q3fAPnP/PhpKkkve52vFdfGpwp4VUvK6LUr4TQN+2stCrEwTg==" | ||||
|     }, | ||||
|     "brorand": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", | ||||
| @@ -2960,11 +2983,6 @@ | ||||
|         "supports-color": "^5.3.0" | ||||
|       } | ||||
|     }, | ||||
|     "change-emitter": { | ||||
|       "version": "0.1.6", | ||||
|       "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", | ||||
|       "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" | ||||
|     }, | ||||
|     "chardet": { | ||||
|       "version": "0.7.0", | ||||
|       "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", | ||||
| @@ -3616,11 +3634,6 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "classnames": { | ||||
|       "version": "2.2.6", | ||||
|       "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", | ||||
|       "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" | ||||
|     }, | ||||
|     "clean-css": { | ||||
|       "version": "4.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", | ||||
| @@ -3679,6 +3692,11 @@ | ||||
|         "shallow-clone": "^0.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "clsx": { | ||||
|       "version": "1.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.0.4.tgz", | ||||
|       "integrity": "sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg==" | ||||
|     }, | ||||
|     "co": { | ||||
|       "version": "4.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", | ||||
| @@ -3859,6 +3877,11 @@ | ||||
|         "date-now": "^0.1.4" | ||||
|       } | ||||
|     }, | ||||
|     "console-polyfill": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/console-polyfill/-/console-polyfill-0.1.2.tgz", | ||||
|       "integrity": "sha1-ls/tUcr3gYn2mVcubxgnHcN8DjA=" | ||||
|     }, | ||||
|     "constants-browserify": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", | ||||
| @@ -3879,6 +3902,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", | ||||
|       "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" | ||||
|     }, | ||||
|     "convert-css-length": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/convert-css-length/-/convert-css-length-1.0.2.tgz", | ||||
|       "integrity": "sha512-ecV7j3hXyXN1X2XfJBzhMR0o1Obv0v3nHmn0UiS3ACENrzbxE/EknkiunS/fCwQva0U62X1GChi8GaPh4oTlLg==", | ||||
|       "requires": { | ||||
|         "console-polyfill": "^0.1.2", | ||||
|         "parse-unit": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "convert-source-map": { | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", | ||||
| @@ -4257,14 +4289,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", | ||||
|       "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=" | ||||
|     }, | ||||
|     "css-vendor": { | ||||
|       "version": "0.3.8", | ||||
|       "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz", | ||||
|       "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=", | ||||
|       "requires": { | ||||
|         "is-in-browser": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "css-what": { | ||||
|       "version": "2.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", | ||||
| @@ -4449,9 +4473,9 @@ | ||||
|       } | ||||
|     }, | ||||
|     "csstype": { | ||||
|       "version": "2.6.3", | ||||
|       "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.3.tgz", | ||||
|       "integrity": "sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg==" | ||||
|       "version": "2.6.4", | ||||
|       "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.4.tgz", | ||||
|       "integrity": "sha512-lAJUJP3M6HxFXbqtGRc0iZrdyeN+WzOWeY0q/VnFzI+kqVrYIzC7bWlKqCW7oCIdzoPkvfp82EVvrTlQ8zsWQg==" | ||||
|     }, | ||||
|     "cyclist": { | ||||
|       "version": "0.2.2", | ||||
| @@ -7993,14 +8017,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", | ||||
|       "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" | ||||
|     }, | ||||
|     "indefinite-observable": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.2.tgz", | ||||
|       "integrity": "sha512-Mps0898zEduHyPhb7UCgNmfzlqNZknVmaFz5qzr0mm04YQ5FGLhAyK/dJ+NaRxGyR6juQXIxh5Ev0xx+qq0nYA==", | ||||
|       "requires": { | ||||
|         "symbol-observable": "1.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "indexes-of": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", | ||||
| @@ -8230,11 +8246,6 @@ | ||||
|       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", | ||||
|       "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" | ||||
|     }, | ||||
|     "is-function": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", | ||||
|       "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" | ||||
|     }, | ||||
|     "is-generator-fn": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", | ||||
| @@ -9195,148 +9206,242 @@ | ||||
|       } | ||||
|     }, | ||||
|     "jss": { | ||||
|       "version": "9.8.7", | ||||
|       "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz", | ||||
|       "integrity": "sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ==", | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "is-in-browser": "^1.1.3", | ||||
|         "symbol-observable": "^1.1.0", | ||||
|         "warning": "^3.0.0" | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-camel-case": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-nki+smHEsFyoZ0OlOYtaxVqcQA0ZHVJCE1slRnk+1TklbmxbBiO4TwITMTEaNIDv0U0Uyb0Z8wVgFgRwCCIFog==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "hyphenate-style-name": "^1.0.3", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "warning": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", | ||||
|           "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "loose-envify": "^1.0.0" | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-camel-case": { | ||||
|       "version": "6.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz", | ||||
|       "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==", | ||||
|     "jss-plugin-compose": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-compose/-/jss-plugin-compose-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-MeOc5RuDSqB3czoUFM32pBq370+sKKjG1K4aamVWpAUWpsphLi/YlotrFOkk/FCb2So1ga4W7/zrCc/50OeRAQ==", | ||||
|       "requires": { | ||||
|         "hyphenate-style-name": "^1.0.2" | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "jss-compose": { | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-compose/-/jss-compose-5.0.0.tgz", | ||||
|       "integrity": "sha512-YofRYuiA0+VbeOw0VjgkyO380sA4+TWDrW52nSluD9n+1FWOlDzNbgpZ/Sb3Y46+DcAbOS21W5jo6SAqUEiuwA==", | ||||
|     "jss-plugin-default-unit": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-jjGW4F/r9yKvoyUk22M8nWhdMfvoWzJw/oFO2cDRXCk2onnWFiRALfqeUsEDyocwdZbyVF9WhZbSHn4GL03kSw==", | ||||
|       "requires": { | ||||
|         "warning": "^3.0.0" | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "warning": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", | ||||
|           "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "loose-envify": "^1.0.0" | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-default-unit": { | ||||
|       "version": "8.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/jss-default-unit/-/jss-default-unit-8.0.2.tgz", | ||||
|       "integrity": "sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg==" | ||||
|     }, | ||||
|     "jss-expand": { | ||||
|       "version": "5.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-expand/-/jss-expand-5.3.0.tgz", | ||||
|       "integrity": "sha512-NiM4TbDVE0ykXSAw6dfFmB1LIqXP/jdd0ZMnlvlGgEMkMt+weJIl8Ynq1DsuBY9WwkNyzWktdqcEW2VN0RAtQg==" | ||||
|     }, | ||||
|     "jss-extend": { | ||||
|       "version": "6.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-extend/-/jss-extend-6.2.0.tgz", | ||||
|       "integrity": "sha512-YszrmcB6o9HOsKPszK7NeDBNNjVyiW864jfoiHoMlgMIg2qlxKw70axZHqgczXHDcoyi/0/ikP1XaHDPRvYtEA==", | ||||
|     "jss-plugin-expand": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-expand/-/jss-plugin-expand-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-Q3m0PDWGojfcmWBCkegRJxonq2q9lI6ZfixoFgvTvi+b9zKza0KXkHBUzGjeFyM36U/WRWj43SC33dajcI9jAg==", | ||||
|       "requires": { | ||||
|         "warning": "^3.0.0" | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-extend": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-extend/-/jss-plugin-extend-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-nJ8H5b/dBZlqaPYCLNmcaHRQgzSlnAwhZUcIo30s0IgvhTtN/TaiRtEbrJZjfXPzatTsnFoRwZzJqs8Sakev+A==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-global": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-B1mm2ZF9OEsWPmzkG5ZUXqV88smDqpc4unILLXhWVuj0U5JeT0DNitH+QbXFrSueDJzkWVfvqyckvWDR/0qeDg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "warning": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", | ||||
|           "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "loose-envify": "^1.0.0" | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-global": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-global/-/jss-global-3.0.0.tgz", | ||||
|       "integrity": "sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q==" | ||||
|     }, | ||||
|     "jss-nested": { | ||||
|       "version": "6.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz", | ||||
|       "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==", | ||||
|     "jss-plugin-nested": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-3l/MB6COnIpq4GOXQFae6UydoaIPa81UxhuBTEQuiAojgTeUla9L7nB3h18Q4zAhQQpjxaEsyppAKuEzIP7kPQ==", | ||||
|       "requires": { | ||||
|         "warning": "^3.0.0" | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "warning": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", | ||||
|           "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "loose-envify": "^1.0.0" | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-props-sort": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-+Yn9nugHAH58nf/d43H2uxMvlCFPDgLKRSmKO4Q4m1IGYjMbHsWt1Rk2HfC9IiCanqcqpc8hstwtzf+HG7PWFQ==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-rule-value-function": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-MQap9ne6ZGZH0NlpSQTMSm6QalBTF0hYpd2uaGQwam+GlT7IKeO+sTjd46I1WgO3kyOmwb0pIY6CnuLQGXKtSA==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-rule-value-observable": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-observable/-/jss-plugin-rule-value-observable-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-Gmj1sVKWM2KVZpG0Wn3Z+SArvskdXEtSCrww43g/OO+j8DN9O+UEV47tM/HYfdiyLICnvKHc2XGmhNz9LHcpNQ==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "symbol-observable": "^1.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-template": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-template/-/jss-plugin-template-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-L1epTMTDINJPUZkFuyohCXQtJDTMj1CNTBv9ysqVyMc3qjkifAvPEws6XuoRSC9jy1ZvqDTWlxPfbmoJ2r6BWg==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "jss-plugin-vendor-prefixer": { | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-70yJ6QE5dN8VlPUGKld5jK2SKyrteheEL/ismexpybIufunMs6iJgkhDndbOfv8ia13yZgUVqeakMdhRKYwK1A==", | ||||
|       "requires": { | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "css-vendor": "^2.0.1", | ||||
|         "jss": "10.0.0-alpha.16" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "css-vendor": { | ||||
|           "version": "2.0.2", | ||||
|           "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.2.tgz", | ||||
|           "integrity": "sha512-Xn5ZAlI00d8HaQ8/oQ8d+iBzSF//NCc77LPzsucM32X/R/yTqmXy6otVsAM0XleXk6HjPuXoVZwXsayky/fsFQ==", | ||||
|           "requires": { | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.0.2" | ||||
|           } | ||||
|         }, | ||||
|         "jss": { | ||||
|           "version": "10.0.0-alpha.16", | ||||
|           "resolved": "https://registry.npmjs.org/jss/-/jss-10.0.0-alpha.16.tgz", | ||||
|           "integrity": "sha512-HmKNNnr82TR5jkWjBcbrx/uim2ief588pWp7zsf4GQpL125zRkEaWYL1SXv5bR6bBvAoTtvJsTAOxDIlLxUNZg==", | ||||
|           "requires": { | ||||
|             "@babel/runtime": "^7.3.1", | ||||
|             "is-in-browser": "^1.1.3", | ||||
|             "tiny-warning": "^1.0.2" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-preset-default": { | ||||
|       "version": "4.5.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-4.5.0.tgz", | ||||
|       "integrity": "sha512-qZbpRVtHT7hBPpZEBPFfafZKWmq3tA/An5RNqywDsZQGrlinIF/mGD9lmj6jGqu8GrED2SMHZ3pPKLmjCZoiaQ==", | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/jss-preset-default/-/jss-preset-default-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-YBq2XE4iJdl16klxfw0xTaKksfAIXSoC2kPZQ4dmw4n/KMFOz/A26eN30FwWixyObfDMKyZp94vwCKal7711IQ==", | ||||
|       "requires": { | ||||
|         "jss-camel-case": "^6.1.0", | ||||
|         "jss-compose": "^5.0.0", | ||||
|         "jss-default-unit": "^8.0.2", | ||||
|         "jss-expand": "^5.3.0", | ||||
|         "jss-extend": "^6.2.0", | ||||
|         "jss-global": "^3.0.0", | ||||
|         "jss-nested": "^6.0.1", | ||||
|         "jss-props-sort": "^6.0.0", | ||||
|         "jss-template": "^1.0.1", | ||||
|         "jss-vendor-prefixer": "^7.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "jss-props-sort": { | ||||
|       "version": "6.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz", | ||||
|       "integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g==" | ||||
|     }, | ||||
|     "jss-template": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/jss-template/-/jss-template-1.0.1.tgz", | ||||
|       "integrity": "sha512-m5BqEWha17fmIVXm1z8xbJhY6GFJxNB9H68GVnCWPyGYfxiAgY9WTQyvDAVj+pYRgrXSOfN5V1T4+SzN1sJTeg==", | ||||
|       "requires": { | ||||
|         "warning": "^3.0.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "warning": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", | ||||
|           "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", | ||||
|           "requires": { | ||||
|             "loose-envify": "^1.0.0" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "jss-vendor-prefixer": { | ||||
|       "version": "7.0.0", | ||||
|       "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" | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "jss-plugin-camel-case": "10.0.0-alpha.16", | ||||
|         "jss-plugin-compose": "10.0.0-alpha.16", | ||||
|         "jss-plugin-default-unit": "10.0.0-alpha.16", | ||||
|         "jss-plugin-expand": "10.0.0-alpha.16", | ||||
|         "jss-plugin-extend": "10.0.0-alpha.16", | ||||
|         "jss-plugin-global": "10.0.0-alpha.16", | ||||
|         "jss-plugin-nested": "10.0.0-alpha.16", | ||||
|         "jss-plugin-props-sort": "10.0.0-alpha.16", | ||||
|         "jss-plugin-rule-value-function": "10.0.0-alpha.16", | ||||
|         "jss-plugin-rule-value-observable": "10.0.0-alpha.16", | ||||
|         "jss-plugin-template": "10.0.0-alpha.16", | ||||
|         "jss-plugin-vendor-prefixer": "10.0.0-alpha.16" | ||||
|       } | ||||
|     }, | ||||
|     "jsx-ast-utils": { | ||||
| @@ -10455,6 +10560,11 @@ | ||||
|         "json-parse-better-errors": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "parse-unit": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", | ||||
|       "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" | ||||
|     }, | ||||
|     "parse5": { | ||||
|       "version": "5.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", | ||||
| @@ -13013,6 +13123,11 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "react-display-name": { | ||||
|       "version": "0.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.4.tgz", | ||||
|       "integrity": "sha512-zvU6iouW+SWwHTyThwxGICjJYCMZFk/6r/+jmOdC7ntQoPlS/Pqb81MkxaMf2bHTSq9TN3K3zX2/ayMW/jCtyA==" | ||||
|     }, | ||||
|     "react-dom": { | ||||
|       "version": "16.8.6", | ||||
|       "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", | ||||
| @@ -13054,22 +13169,17 @@ | ||||
|       "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" | ||||
|     }, | ||||
|     "react-jss": { | ||||
|       "version": "8.6.1", | ||||
|       "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz", | ||||
|       "integrity": "sha512-SH6XrJDJkAphp602J14JTy3puB2Zxz1FkM3bKVE8wON+va99jnUTKWnzGECb3NfIn9JPR5vHykge7K3/A747xQ==", | ||||
|       "version": "10.0.0-alpha.16", | ||||
|       "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-10.0.0-alpha.16.tgz", | ||||
|       "integrity": "sha512-nGIerGVDV9V6cpRXhkJZgoV0MsoJbKMdAiCoPzCDnsdR+om6zLyhQEvVHNtd0mB16dO+pzNaovhBvElhdj/3ug==", | ||||
|       "requires": { | ||||
|         "hoist-non-react-statics": "^2.5.0", | ||||
|         "jss": "^9.7.0", | ||||
|         "jss-preset-default": "^4.3.0", | ||||
|         "@babel/runtime": "^7.3.1", | ||||
|         "hoist-non-react-statics": "^3.2.0", | ||||
|         "jss": "10.0.0-alpha.16", | ||||
|         "jss-preset-default": "10.0.0-alpha.16", | ||||
|         "prop-types": "^15.6.0", | ||||
|         "theming": "^1.3.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "hoist-non-react-statics": { | ||||
|           "version": "2.5.5", | ||||
|           "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", | ||||
|           "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" | ||||
|         } | ||||
|         "theming": "^3.0.3", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "react-lifecycles-compat": { | ||||
| @@ -13171,14 +13281,13 @@ | ||||
|       } | ||||
|     }, | ||||
|     "react-transition-group": { | ||||
|       "version": "2.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", | ||||
|       "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", | ||||
|       "version": "4.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.0.1.tgz", | ||||
|       "integrity": "sha512-SsLcBYhO4afXJC9esL8XMxi/y0ZvEc7To0TvtrBELqzpjXQHPZOTxvuPh2/4EhYc0uSMfp2SExIxsyJ0pBdNzg==", | ||||
|       "requires": { | ||||
|         "dom-helpers": "^3.4.0", | ||||
|         "loose-envify": "^1.4.0", | ||||
|         "prop-types": "^15.6.2", | ||||
|         "react-lifecycles-compat": "^3.0.4" | ||||
|         "prop-types": "^15.6.2" | ||||
|       } | ||||
|     }, | ||||
|     "read-pkg": { | ||||
| @@ -13514,26 +13623,6 @@ | ||||
|         "util.promisify": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "recompose": { | ||||
|       "version": "0.30.0", | ||||
|       "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.2", | ||||
|         "fbjs": "^0.8.1", | ||||
|         "hoist-non-react-statics": "^2.3.1", | ||||
|         "react-lifecycles-compat": "^3.0.2", | ||||
|         "symbol-observable": "^1.0.4" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "hoist-non-react-statics": { | ||||
|           "version": "2.5.5", | ||||
|           "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", | ||||
|           "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "recursive-readdir": { | ||||
|       "version": "2.2.2", | ||||
|       "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", | ||||
| @@ -15184,14 +15273,14 @@ | ||||
|       "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" | ||||
|     }, | ||||
|     "theming": { | ||||
|       "version": "1.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/theming/-/theming-1.3.0.tgz", | ||||
|       "integrity": "sha512-ya5Ef7XDGbTPBv5ENTwrwkPUexrlPeiAg/EI9kdlUAZhNlRbCdhMKRgjNX1IcmsmiPcqDQZE6BpSaH+cr31FKw==", | ||||
|       "version": "3.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/theming/-/theming-3.2.0.tgz", | ||||
|       "integrity": "sha512-n0fSNYXkX63rcFBBeAthy14IcgPZLHp0OGkGZheaj64j7cBoP7INLd6+7HIXqWVjFn1M5cYSiZ1nszi+jo/Szg==", | ||||
|       "requires": { | ||||
|         "brcast": "^3.0.1", | ||||
|         "is-function": "^1.0.1", | ||||
|         "is-plain-object": "^2.0.1", | ||||
|         "prop-types": "^15.5.8" | ||||
|         "hoist-non-react-statics": "^3.3.0", | ||||
|         "prop-types": "^15.5.8", | ||||
|         "react-display-name": "^0.2.4", | ||||
|         "tiny-warning": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "throat": { | ||||
|   | ||||
| @@ -3,8 +3,8 @@ | ||||
|   "version": "0.1.0", | ||||
|   "private": true, | ||||
|   "dependencies": { | ||||
|     "@material-ui/core": "^3.9.3", | ||||
|     "@material-ui/icons": "^3.0.2", | ||||
|     "@material-ui/core": "^4.0.0", | ||||
|     "@material-ui/icons": "^4.0.0", | ||||
|     "compression-webpack-plugin": "^2.0.0", | ||||
|     "jwt-decode": "^2.2.0", | ||||
|     "moment": "^2.24.0", | ||||
| @@ -12,7 +12,7 @@ | ||||
|     "react": "^16.8.6", | ||||
|     "react-dom": "^16.8.6", | ||||
|     "react-form-validator-core": "^0.6.2", | ||||
|     "react-jss": "^8.6.1", | ||||
|     "react-jss": "^10.0.0-alpha.16", | ||||
|     "react-material-ui-form-validator": "^2.0.7", | ||||
|     "react-router": "^5.0.0", | ||||
|     "react-router-dom": "^5.0.0", | ||||
|   | ||||
| @@ -10,14 +10,12 @@ 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 JssProvider from 'react-jss/lib/JssProvider'; | ||||
| import { create } from 'jss'; | ||||
| import { StylesProvider, jssPreset } from '@material-ui/styles'; | ||||
|  | ||||
| import { | ||||
|   MuiThemeProvider, | ||||
|   createMuiTheme, | ||||
|   createGenerateClassName, | ||||
|   jssPreset, | ||||
|   createMuiTheme | ||||
| } from '@material-ui/core/styles'; | ||||
|  | ||||
| // Our theme | ||||
| @@ -35,20 +33,17 @@ const theme = createMuiTheme({ | ||||
| // JSS instance | ||||
| const jss = create(jssPreset()); | ||||
|  | ||||
| // Class name generator. | ||||
| const generateClassName = createGenerateClassName(); | ||||
|  | ||||
| class App extends Component { | ||||
| 	render() { | ||||
| 	   return ( | ||||
| 		 <JssProvider jss={jss} generateClassName={generateClassName}> | ||||
| 		 <StylesProvider jss={jss}> | ||||
| 			<MuiThemeProvider theme={theme}> | ||||
|         <SnackbarNotification> | ||||
| 				  <CssBaseline /> | ||||
|           <AppRouting /> | ||||
|         </SnackbarNotification> | ||||
| 			</MuiThemeProvider> | ||||
| 		 </JssProvider> | ||||
| 		 </StylesProvider> | ||||
| 		) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import NTPConfiguration from './containers/NTPConfiguration'; | ||||
| import OTAConfiguration from './containers/OTAConfiguration'; | ||||
| import APConfiguration from './containers/APConfiguration'; | ||||
| import SignInPage from './containers/SignInPage'; | ||||
| import UserConfiguration from './containers/UserConfiguration'; | ||||
| import Security from './containers/Security'; | ||||
|  | ||||
| class AppRouting extends Component { | ||||
|  | ||||
| @@ -31,7 +31,7 @@ class AppRouting extends Component { | ||||
|           <AuthenticatedRoute exact path="/ap-configuration" component={APConfiguration} /> | ||||
|           <AuthenticatedRoute exact path="/ntp-configuration" component={NTPConfiguration} /> | ||||
|           <AuthenticatedRoute exact path="/ota-configuration" component={OTAConfiguration} /> | ||||
|           <AuthenticatedRoute exact path="/user-configuration" component={UserConfiguration} /> | ||||
|           <AuthenticatedRoute exact path="/security" component={Security} /> | ||||
|           <Redirect to="/" /> | ||||
|         </Switch> | ||||
|       </AuthenticationWrapper> | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import SystemUpdateIcon from  '@material-ui/icons/SystemUpdate'; | ||||
| import AccessTimeIcon from '@material-ui/icons/AccessTime'; | ||||
| import AccountCircleIcon from '@material-ui/icons/AccountCircle'; | ||||
| import SettingsInputAntennaIcon from '@material-ui/icons/SettingsInputAntenna'; | ||||
| import PeopleIcon from '@material-ui/icons/People'; | ||||
| import LockIcon from '@material-ui/icons/Lock'; | ||||
|  | ||||
| import { APP_NAME } from '../constants/App'; | ||||
| import { withAuthenticationContext } from '../authentication/Context.js'; | ||||
| @@ -112,31 +112,31 @@ class MenuAppBar extends React.Component { | ||||
|             <ListItemIcon> | ||||
|               <WifiIcon /> | ||||
|             </ListItemIcon> | ||||
|             <ListItemText primary="WiFi Configuration" /> | ||||
|             <ListItemText primary="WiFi Connection" /> | ||||
|           </ListItem> | ||||
|           <ListItem button component={Link} to='/ap-configuration'> | ||||
|             <ListItemIcon> | ||||
|               <SettingsInputAntennaIcon /> | ||||
|             </ListItemIcon> | ||||
|             <ListItemText primary="AP Configuration" /> | ||||
|             <ListItemText primary="Access Point" /> | ||||
|           </ListItem> | ||||
|           <ListItem button component={Link} to='/ntp-configuration'> | ||||
|             <ListItemIcon> | ||||
|               <AccessTimeIcon /> | ||||
|             </ListItemIcon> | ||||
|             <ListItemText primary="NTP Configuration" /> | ||||
|             <ListItemText primary="Network Time" /> | ||||
|           </ListItem> | ||||
|           <ListItem button component={Link} to='/ota-configuration'> | ||||
|             <ListItemIcon> | ||||
|               <SystemUpdateIcon /> | ||||
|             </ListItemIcon> | ||||
|             <ListItemText primary="OTA Configuration" /> | ||||
|             <ListItemText primary="OTA Updates" /> | ||||
|           </ListItem> | ||||
|           <ListItem button component={Link} to='/user-configuration'> | ||||
|           <ListItem button component={Link} to='/security'> | ||||
|             <ListItemIcon> | ||||
|               <PeopleIcon /> | ||||
|               <LockIcon /> | ||||
|             </ListItemIcon> | ||||
|             <ListItemText primary="User Configuration" /> | ||||
|             <ListItemText primary="Security" /> | ||||
|           </ListItem>           | ||||
|           <Divider /> | ||||
|           <ListItem button onClick={authenticationContext.signOut}> | ||||
|   | ||||
| @@ -16,7 +16,7 @@ function SectionContent(props) { | ||||
|   const { children, classes, title } = props; | ||||
|   return ( | ||||
|       <Paper className={classes.content}> | ||||
|         <Typography variant="h4"> | ||||
|         <Typography variant="h6"> | ||||
|           {title} | ||||
|         </Typography> | ||||
|         {children} | ||||
|   | ||||
| @@ -7,17 +7,18 @@ import Typography from '@material-ui/core/Typography'; | ||||
| import List from '@material-ui/core/List'; | ||||
| import ListItem from '@material-ui/core/ListItem'; | ||||
| import ListItemText from '@material-ui/core/ListItemText'; | ||||
| import ListItemAvatar from '@material-ui/core/ListItemAvatar'; | ||||
| import Avatar from '@material-ui/core/Avatar'; | ||||
| 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 {restComponent} from '../components/RestComponent'; | ||||
| import { restComponent } from '../components/RestComponent'; | ||||
| import SectionContent from '../components/SectionContent' | ||||
|  | ||||
| import * as Highlight from '../constants/Highlight'; | ||||
| import { AP_STATUS_ENDPOINT }  from  '../constants/Endpoints'; | ||||
| import { AP_STATUS_ENDPOINT } from '../constants/Endpoints'; | ||||
|  | ||||
| const styles = theme => ({ | ||||
|   ["apStatus_" + Highlight.SUCCESS]: { | ||||
| @@ -42,40 +43,48 @@ class APStatus extends Component { | ||||
|     this.props.loadData(); | ||||
|   } | ||||
|  | ||||
|   apStatusHighlight(data){ | ||||
|   apStatusHighlight(data) { | ||||
|     return data.active ? Highlight.SUCCESS : Highlight.IDLE; | ||||
|   } | ||||
|  | ||||
|   apStatus(data){ | ||||
|   apStatus(data) { | ||||
|     return data.active ? "Active" : "Inactive"; | ||||
|   } | ||||
|  | ||||
|   createListItems(data, classes){ | ||||
|   createListItems(data, classes) { | ||||
|     return ( | ||||
|       <Fragment> | ||||
|         <ListItem> | ||||
|           <Avatar className={classes["apStatus_" + this.apStatusHighlight(data)]}> | ||||
|             <SettingsInputAntennaIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar className={classes["apStatus_" + this.apStatusHighlight(data)]}> | ||||
|               <SettingsInputAntennaIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="Status" secondary={this.apStatus(data)} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         <ListItem> | ||||
|           <Avatar>IP</Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar>IP</Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="IP Address" secondary={data.ip_address} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         <ListItem> | ||||
|           <Avatar> | ||||
|             <DeviceHubIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar> | ||||
|               <DeviceHubIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="MAC Address" secondary={data.mac_address} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         <ListItem> | ||||
|           <Avatar> | ||||
|             <ComputerIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar> | ||||
|               <ComputerIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="AP Clients" secondary={data.station_num} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
| @@ -83,8 +92,8 @@ class APStatus extends Component { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   renderAPStatus(data, classes){ | ||||
|     return  ( | ||||
|   renderAPStatus(data, classes) { | ||||
|     return ( | ||||
|       <div> | ||||
|         <List> | ||||
|           <Fragment> | ||||
| @@ -99,30 +108,30 @@ class APStatus extends Component { | ||||
|   } | ||||
|  | ||||
|   render() { | ||||
|     const { data, fetched, errorMessage, classes }  = this.props; | ||||
|     const { data, fetched, errorMessage, classes } = this.props; | ||||
|  | ||||
|     return ( | ||||
|       <SectionContent title="AP Status"> | ||||
|         { | ||||
|          !fetched ? | ||||
|          <div> | ||||
|            <LinearProgress className={classes.fetching}/> | ||||
|            <Typography variant="h4" className={classes.fetching}> | ||||
|              Loading... | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|            </Typography> | ||||
|          </div> | ||||
|        : | ||||
|         data ? this.renderAPStatus(data, classes) | ||||
|        : | ||||
|         <div> | ||||
|           <Typography variant="h4" className={classes.fetching}> | ||||
|             {errorMessage} | ||||
|           </Typography> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|             Refresh | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderAPStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|           </Button> | ||||
|         </div> | ||||
|       } | ||||
|               </div> | ||||
|         } | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -1,30 +1,27 @@ | ||||
| import React, { Component } from 'react'; | ||||
|  | ||||
| import { USERS_ENDPOINT }  from  '../constants/Endpoints'; | ||||
| import {restComponent} from '../components/RestComponent'; | ||||
| import SectionContent from '../components/SectionContent'; | ||||
| import { USERS_ENDPOINT } from '../constants/Endpoints'; | ||||
| import { restComponent } from '../components/RestComponent'; | ||||
| import ManageUsersForm from '../forms/ManageUsersForm'; | ||||
|  | ||||
| class ManageUsers extends Component { | ||||
|  | ||||
|   componentDidMount() { | ||||
|       this.props.loadData(); | ||||
|     this.props.loadData(); | ||||
|   } | ||||
|  | ||||
|   render() { | ||||
|     const { data, fetched, errorMessage } = this.props; | ||||
|     return ( | ||||
|       <SectionContent title="Manage Users"> | ||||
|       	<ManageUsersForm | ||||
|           users={data} | ||||
|           usersFetched={fetched} | ||||
|           errorMessage={errorMessage} | ||||
|           onSubmit={this.props.saveData} | ||||
|           onReset={this.props.loadData} | ||||
|           handleValueChange={this.props.handleValueChange} | ||||
|           handleCheckboxChange={this.props.handleCheckboxChange} | ||||
|         /> | ||||
|       </SectionContent> | ||||
|       <ManageUsersForm | ||||
|         userData={data} | ||||
|         userDataFetched={fetched} | ||||
|         errorMessage={errorMessage} | ||||
|         onSubmit={this.props.saveData} | ||||
|         onReset={this.props.loadData} | ||||
|         setData={this.props.setData} | ||||
|         handleValueChange={this.props.handleValueChange} | ||||
|       /> | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import LinearProgress from '@material-ui/core/LinearProgress'; | ||||
| import Typography from '@material-ui/core/Typography'; | ||||
| import List from '@material-ui/core/List'; | ||||
| import ListItem from '@material-ui/core/ListItem'; | ||||
| 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'; | ||||
| @@ -16,10 +17,10 @@ import TimerIcon from '@material-ui/icons/Timer'; | ||||
| import UpdateIcon from '@material-ui/icons/Update'; | ||||
| import AvTimerIcon from '@material-ui/icons/AvTimer'; | ||||
|  | ||||
| import { isSynchronized, ntpStatusHighlight, ntpStatus }  from  '../constants/NTPStatus'; | ||||
| import { isSynchronized, ntpStatusHighlight, ntpStatus } from '../constants/NTPStatus'; | ||||
| import * as Highlight from '../constants/Highlight'; | ||||
| import { unixTimeToTimeAndDate } from '../constants/TimeFormat'; | ||||
| import { NTP_STATUS_ENDPOINT }  from  '../constants/Endpoints'; | ||||
| import { NTP_STATUS_ENDPOINT } from '../constants/Endpoints'; | ||||
| import { restComponent } from '../components/RestComponent'; | ||||
| import SectionContent from '../components/SectionContent'; | ||||
|  | ||||
| @@ -51,52 +52,61 @@ class NTPStatus extends Component { | ||||
|     this.props.loadData(); | ||||
|   } | ||||
|  | ||||
|   createListItems(data, classes){ | ||||
|   createListItems(data, classes) { | ||||
|     return ( | ||||
|       <Fragment> | ||||
|         <ListItem> | ||||
|           <Avatar className={classes["ntpStatus_" + ntpStatusHighlight(data)]}> | ||||
|             <UpdateIcon /> | ||||
|           </Avatar> | ||||
|         <ListItem > | ||||
|           <ListItemAvatar> | ||||
|             <Avatar className={classes["ntpStatus_" + ntpStatusHighlight(data)]}> | ||||
|               <UpdateIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="Status" secondary={ntpStatus(data)} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         { isSynchronized(data) && | ||||
|         {isSynchronized(data) && | ||||
|           <Fragment> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <AccessTimeIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <AccessTimeIcon /> | ||||
|                 </Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="Time Now" secondary={unixTimeToTimeAndDate(data.now)} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <SwapVerticalCircleIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemText primary="Last Sync" secondary={data.last_sync > 0 ? unixTimeToTimeAndDate(data.last_sync) : "never" } /> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <SwapVerticalCircleIcon /> | ||||
|                 </Avatar></ListItemAvatar> | ||||
|               <ListItemText primary="Last Sync" secondary={data.last_sync > 0 ? unixTimeToTimeAndDate(data.last_sync) : "never"} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|           </Fragment> | ||||
|         } | ||||
|         <ListItem> | ||||
|           <Avatar> | ||||
|             <DNSIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar> | ||||
|               <DNSIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="NTP Server" secondary={data.server} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         <ListItem> | ||||
|           <Avatar> | ||||
|             <TimerIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar> | ||||
|               <TimerIcon /> | ||||
|             </Avatar></ListItemAvatar> | ||||
|           <ListItemText primary="Sync Interval" secondary={moment.duration(data.interval, 'seconds').humanize()} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
|         <ListItem> | ||||
|           <Avatar> | ||||
|             <AvTimerIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar> | ||||
|               <AvTimerIcon /> | ||||
|             </Avatar></ListItemAvatar> | ||||
|           <ListItemText primary="Uptime" secondary={moment.duration(data.uptime, 'seconds').humanize()} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
| @@ -104,8 +114,8 @@ class NTPStatus extends Component { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   renderNTPStatus(data, classes){ | ||||
|     return  ( | ||||
|   renderNTPStatus(data, classes) { | ||||
|     return ( | ||||
|       <div> | ||||
|         <List> | ||||
|           {this.createListItems(data, classes)} | ||||
| @@ -118,30 +128,30 @@ class NTPStatus extends Component { | ||||
|   } | ||||
|  | ||||
|   render() { | ||||
|     const { data, fetched, errorMessage, classes }  = this.props; | ||||
|     const { data, fetched, errorMessage, classes } = this.props; | ||||
|  | ||||
|     return ( | ||||
|       <SectionContent title="NTP Status"> | ||||
|         { | ||||
|          !fetched ? | ||||
|          <div> | ||||
|            <LinearProgress className={classes.fetching}/> | ||||
|            <Typography variant="h4" className={classes.fetching}> | ||||
|              Loading... | ||||
|           !fetched ? | ||||
|             <div> | ||||
|               <LinearProgress className={classes.fetching} /> | ||||
|               <Typography variant="h4" className={classes.fetching}> | ||||
|                 Loading... | ||||
|            </Typography> | ||||
|          </div> | ||||
|        : | ||||
|         data ? this.renderNTPStatus(data, classes) | ||||
|        : | ||||
|         <div> | ||||
|           <Typography variant="h4" className={classes.fetching}> | ||||
|             {errorMessage} | ||||
|           </Typography> | ||||
|           <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|             Refresh | ||||
|             </div> | ||||
|             : | ||||
|             data ? this.renderNTPStatus(data, classes) | ||||
|               : | ||||
|               <div> | ||||
|                 <Typography variant="h4" className={classes.fetching}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={this.props.loadData}> | ||||
|                   Refresh | ||||
|           </Button> | ||||
|         </div> | ||||
|       } | ||||
|               </div> | ||||
|         } | ||||
|       </SectionContent> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -2,14 +2,14 @@ import React, { Component } from 'react'; | ||||
| import MenuAppBar from '../components/MenuAppBar'; | ||||
| import ManageUsers from './ManageUsers'; | ||||
| 
 | ||||
| class UserConfiguration extends Component { | ||||
| class Security extends Component { | ||||
|   render() { | ||||
|     return ( | ||||
|         <MenuAppBar sectionTitle="User Configuration"> | ||||
|         <MenuAppBar sectionTitle="Security"> | ||||
|           <ManageUsers /> | ||||
|         </MenuAppBar> | ||||
|     ) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default UserConfiguration | ||||
| export default Security | ||||
| @@ -8,6 +8,7 @@ import Typography from '@material-ui/core/Typography'; | ||||
| import List from '@material-ui/core/List'; | ||||
| import ListItem from '@material-ui/core/ListItem'; | ||||
| import ListItemText from '@material-ui/core/ListItemText'; | ||||
| import ListItemAvatar from '@material-ui/core/ListItemAvatar'; | ||||
|  | ||||
| import Avatar from '@material-ui/core/Avatar'; | ||||
| import Divider from '@material-ui/core/Divider'; | ||||
| @@ -63,9 +64,11 @@ class WiFiStatus extends Component { | ||||
|     return ( | ||||
|       <Fragment> | ||||
|         <ListItem> | ||||
|           <Avatar className={classes["wifiStatus_" + connectionStatusHighlight(data)]}> | ||||
|             <WifiIcon /> | ||||
|           </Avatar> | ||||
|           <ListItemAvatar> | ||||
|             <Avatar className={classes["wifiStatus_" + connectionStatusHighlight(data)]}> | ||||
|               <WifiIcon /> | ||||
|             </Avatar> | ||||
|           </ListItemAvatar> | ||||
|           <ListItemText primary="Connection Status" secondary={connectionStatus(data)} /> | ||||
|         </ListItem> | ||||
|         <Divider variant="inset" component="li" /> | ||||
| @@ -73,40 +76,52 @@ class WiFiStatus extends Component { | ||||
|           isConnected(data) && | ||||
|           <Fragment> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <SettingsInputAntennaIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <SettingsInputAntennaIcon /> | ||||
|                 </Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="SSID" secondary={data.ssid} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar>IP</Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar>IP</Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="IP Address" secondary={data.local_ip} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <DeviceHubIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <DeviceHubIcon /> | ||||
|                 </Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="MAC Address" secondary={data.mac_address} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar>#</Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar>#</Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="Subnet Mask" secondary={data.subnet_mask} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <SettingsInputComponentIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <SettingsInputComponentIcon /> | ||||
|                 </Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="Gateway IP" secondary={data.gateway_ip ? data.gateway_ip : "none"} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|             <ListItem> | ||||
|               <Avatar> | ||||
|                 <DNSIcon /> | ||||
|               </Avatar> | ||||
|               <ListItemAvatar> | ||||
|                 <Avatar> | ||||
|                   <DNSIcon /> | ||||
|                 </Avatar> | ||||
|               </ListItemAvatar> | ||||
|               <ListItemText primary="DNS Server IP" secondary={this.dnsServers(data)} /> | ||||
|             </ListItem> | ||||
|             <Divider variant="inset" component="li" /> | ||||
|   | ||||
| @@ -1,23 +1,26 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
|  | ||||
| import { ValidatorForm } from 'react-material-ui-form-validator'; | ||||
| import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; | ||||
|  | ||||
| import { withStyles } from '@material-ui/core/styles'; | ||||
| import Button from '@material-ui/core/Button'; | ||||
| import LinearProgress from '@material-ui/core/LinearProgress'; | ||||
| import Typography from '@material-ui/core/Typography'; | ||||
|  | ||||
| import Table from '@material-ui/core/Table'; | ||||
| import TableBody from '@material-ui/core/TableBody'; | ||||
| import TableCell from '@material-ui/core/TableCell'; | ||||
| import TableFooter from '@material-ui/core/TableFooter'; | ||||
| import TableHead from '@material-ui/core/TableHead'; | ||||
| import TableRow from '@material-ui/core/TableRow'; | ||||
| import IconButton from '@material-ui/core/IconButton'; | ||||
| import Chip from '@material-ui/core/Chip'; | ||||
|  | ||||
| import EditIcon from '@material-ui/icons/Edit'; | ||||
| import DeleteIcon from '@material-ui/icons/Delete'; | ||||
| import Chip from '@material-ui/core/Chip'; | ||||
| import IconButton from '@material-ui/core/IconButton'; | ||||
|  | ||||
| import SectionContent from '../components/SectionContent'; | ||||
| import UserForm from './UserForm'; | ||||
|  | ||||
| const styles = theme => ({ | ||||
|   loadingSettings: { | ||||
| @@ -43,95 +46,198 @@ const styles = theme => ({ | ||||
|     margin: theme.spacing.unit, | ||||
|   }, | ||||
|   table: { | ||||
|     '& td, & th': {padding: theme.spacing.unit}     | ||||
|   }     | ||||
|     '& td, & th': { padding: theme.spacing.unit } | ||||
|   }, | ||||
|   actions: { | ||||
|     color: theme.palette.text.secondary, | ||||
|   } | ||||
| }); | ||||
|  | ||||
| function compareUsers(a, b) { | ||||
|   if (a.username < b.username) { | ||||
|     return -1; | ||||
|   } | ||||
|   if (a.username > b.username) { | ||||
|     return 1; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| class ManageUsersForm extends React.Component { | ||||
|  | ||||
|   render() { | ||||
|     const { classes, users, usersFetched, errorMessage, onSubmit, onReset } = this.props; | ||||
|     return ( | ||||
|       <div> | ||||
|         { | ||||
|           !usersFetched ? | ||||
|   constructor(props) { | ||||
|     super(props); | ||||
|     this.state = {}; | ||||
|   } | ||||
|  | ||||
|   createUser = () => { | ||||
|     this.setState({ | ||||
|       creating: true, | ||||
|       user: { | ||||
|         username: "", | ||||
|         password: "", | ||||
|         roles: [] | ||||
|       } | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   uniqueUsername = username => { | ||||
|     return !this.props.userData.users.find(u => u.username === username); | ||||
|   } | ||||
|  | ||||
|   usersValid = username => { | ||||
|     return !!this.props.userData.users.find(u => u.roles.includes("admin")); | ||||
|   } | ||||
|  | ||||
|   startEditingUser = user => { | ||||
|     this.setState({ | ||||
|       creating: false, | ||||
|       user | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   cancelEditingUser = () => { | ||||
|     this.setState({ | ||||
|       user: undefined | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   sortedUsers(users) { | ||||
|     return users.sort(compareUsers); | ||||
|   } | ||||
|  | ||||
|   doneEditingUser = () => { | ||||
|     const { user } = this.state; | ||||
|     const { userData } = this.props; | ||||
|     let { users } = userData; | ||||
|     users = users.filter(u => u.username !== user.username); | ||||
|     users.push(user); | ||||
|     this.props.setData({ ...userData, users }); | ||||
|     this.setState({ | ||||
|       user: undefined | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   handleUserValueChange = name => event => { | ||||
|     const { user } = this.state; | ||||
|     if (user) { | ||||
|       this.setState({ | ||||
|         user: { | ||||
|           ...user, [name]: event.target.value | ||||
|         } | ||||
|       }); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   render() { | ||||
|     const { classes, userData, userDataFetched, errorMessage, onSubmit, onReset, handleValueChange } = this.props; | ||||
|     const { user, creating } = this.state; | ||||
|     return ( | ||||
|       <SectionContent title="Manage Users"> | ||||
|         { | ||||
|           !userDataFetched ? | ||||
|             <div className={classes.loadingSettings}> | ||||
|               <LinearProgress className={classes.loadingSettingsDetails} /> | ||||
|               <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|                 Loading... | ||||
|               </Typography> | ||||
|             </div> | ||||
|  | ||||
|             : users ? | ||||
|  | ||||
|               <ValidatorForm onSubmit={onSubmit}> | ||||
|                 <Table className={classes.table}> | ||||
|                   <TableHead> | ||||
|                     <TableRow> | ||||
|                       <TableCell>Username</TableCell> | ||||
|                       <TableCell>Password</TableCell> | ||||
|                       <TableCell align="center">Role(s)</TableCell> | ||||
|                       <TableCell align="center">Action</TableCell> | ||||
|                     </TableRow> | ||||
|                   </TableHead> | ||||
|                   <TableBody> | ||||
|                     {users.users.map(user => ( | ||||
|                       <TableRow key={user.username}> | ||||
|                         <TableCell component="th" scope="row"> | ||||
|                           {user.username} | ||||
|                         </TableCell> | ||||
|                         <TableCell>{user.password}</TableCell> | ||||
|                         <TableCell align="center"> | ||||
|                           <Chip label={user.role} className={classes.chip} /> | ||||
|             : | ||||
|             userData ? | ||||
|               user ? | ||||
|                 <UserForm | ||||
|                   user={user} | ||||
|                   creating={creating} | ||||
|                   roles={userData.roles} | ||||
|                   onDoneEditing={this.doneEditingUser} | ||||
|                   onCancelEditing={this.cancelEditingUser} | ||||
|                   handleValueChange={this.handleUserValueChange} | ||||
|                   uniqueUsername={this.uniqueUsername} | ||||
|                 /> | ||||
|                 : | ||||
|                 <ValidatorForm onSubmit={onSubmit}>   | ||||
|                   <Table className={classes.table}> | ||||
|                     <TableHead> | ||||
|                       <TableRow> | ||||
|                         <TableCell>Username</TableCell> | ||||
|                         <TableCell align="center">Role(s)</TableCell> | ||||
|                         <TableCell align="center">Action</TableCell> | ||||
|                       </TableRow> | ||||
|                     </TableHead> | ||||
|                     <TableBody> | ||||
|                       {this.sortedUsers(userData.users).map(user => ( | ||||
|                         <TableRow key={user.username}> | ||||
|                           <TableCell component="th" scope="row"> | ||||
|                             {user.username} | ||||
|                           </TableCell> | ||||
|                           <TableCell align="center"> | ||||
|                             { | ||||
|                               user.roles.map(role => ( | ||||
|                                 <Chip label={role} className={classes.chip} /> | ||||
|                               )) | ||||
|                             } | ||||
|                           </TableCell> | ||||
|                           <TableCell align="center"> | ||||
|                             <IconButton aria-label="Delete"> | ||||
|                               <DeleteIcon /> | ||||
|                             </IconButton> | ||||
|                             <IconButton aria-label="Edit" onClick={() => this.startEditingUser(user)}> | ||||
|                               <EditIcon /> | ||||
|                             </IconButton> | ||||
|                           </TableCell> | ||||
|                         </TableRow> | ||||
|                       ))} | ||||
|                     </TableBody> | ||||
|                     <TableFooter> | ||||
|                       <TableRow> | ||||
|                         <TableCell colSpan={2}> | ||||
|                           { | ||||
|                             !this.usersValid() && | ||||
|                             <Typography variant="body1" color="error"> | ||||
|                               You must have at least one admin user configured. | ||||
|                             </Typography> | ||||
|                           } | ||||
|                         </TableCell> | ||||
|                         <TableCell align="center"> | ||||
|                           <IconButton aria-label="Delete"> | ||||
|                             <DeleteIcon /> | ||||
|                           </IconButton> | ||||
|                           <IconButton aria-label="Edit"> | ||||
|                             <EditIcon /> | ||||
|                           </IconButton> | ||||
|                           <Button variant="contained" color="secondary" className={classes.button} onClick={this.createUser}> | ||||
|                             Add User | ||||
|                         </Button> | ||||
|                         </TableCell> | ||||
|                       </TableRow> | ||||
|                     ))} | ||||
|                   </TableBody> | ||||
|                 </Table> | ||||
|  | ||||
|                 <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|                   Save | ||||
|                 </Button> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                   Reset | ||||
|       		      </Button> | ||||
|  | ||||
|               </ValidatorForm> | ||||
|  | ||||
|                     </TableFooter> | ||||
|                   </Table> | ||||
|                   <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|                     Save | ||||
|                   </Button> | ||||
|                   <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                     Reset | ||||
|       		        </Button> | ||||
|                 </ValidatorForm> | ||||
|               : | ||||
|  | ||||
|               <div className={classes.loadingSettings}> | ||||
|               <SectionContent title="Manage Users"> | ||||
|                 <Typography variant="h4" className={classes.loadingSettingsDetails}> | ||||
|                   {errorMessage} | ||||
|                 </Typography> | ||||
|                 <Button variant="contained" color="secondary" className={classes.button} onClick={onReset}> | ||||
|                   Reset | ||||
|       		</Button> | ||||
|               </div> | ||||
|       		      </Button> | ||||
|               </SectionContent> | ||||
|         } | ||||
|       </div> | ||||
|       </SectionContent> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| ManageUsersForm.propTypes = { | ||||
|   classes: PropTypes.object.isRequired, | ||||
|   users: PropTypes.object, | ||||
|   usersFetched: PropTypes.bool.isRequired, | ||||
|   userData: PropTypes.object, | ||||
|   userDataFetched: PropTypes.bool.isRequired, | ||||
|   errorMessage: PropTypes.string, | ||||
|   onSubmit: PropTypes.func.isRequired, | ||||
|   onReset: PropTypes.func.isRequired, | ||||
|   handleValueChange: PropTypes.func.isRequired, | ||||
|   handleCheckboxChange: PropTypes.func.isRequired, | ||||
|   setData: PropTypes.func.isRequired, | ||||
|   handleValueChange: PropTypes.func.isRequired | ||||
| }; | ||||
|  | ||||
| export default withStyles(styles)(ManageUsersForm); | ||||
|   | ||||
							
								
								
									
										112
									
								
								interface/src/forms/UserForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								interface/src/forms/UserForm.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
|  | ||||
| import { withStyles } from '@material-ui/core/styles'; | ||||
| import Button from '@material-ui/core/Button'; | ||||
|  | ||||
| import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; | ||||
| import PasswordValidator from '../components/PasswordValidator'; | ||||
|  | ||||
| import Input from '@material-ui/core/Input'; | ||||
| import InputLabel from '@material-ui/core/InputLabel'; | ||||
| import MenuItem from '@material-ui/core/MenuItem'; | ||||
| import FormControl from '@material-ui/core/FormControl'; | ||||
| import Select from '@material-ui/core/Select'; | ||||
| import Chip from '@material-ui/core/Chip'; | ||||
|  | ||||
| const styles = theme => ({ | ||||
|   textField: { | ||||
|     width: "100%" | ||||
|   }, | ||||
|   checkboxControl: { | ||||
|     width: "100%" | ||||
|   }, | ||||
|   chips: { | ||||
|     display: 'flex', | ||||
|     flexWrap: 'wrap', | ||||
|   }, | ||||
|   chip: { | ||||
|     marginRight: theme.spacing.unit, | ||||
|   }, | ||||
|   button: { | ||||
|     marginRight: theme.spacing.unit * 2, | ||||
|     marginTop: theme.spacing.unit * 2, | ||||
|   } | ||||
| }); | ||||
|  | ||||
| class UserForm extends React.Component { | ||||
|  | ||||
|   componentWillMount() { | ||||
|     ValidatorForm.addValidationRule('uniqueUsername', this.props.uniqueUsername); | ||||
|   } | ||||
|  | ||||
|   render() { | ||||
|     const { classes, user, roles, creating, handleValueChange, onDoneEditing, onCancelEditing } = this.props; | ||||
|     return ( | ||||
|       <ValidatorForm onSubmit={onDoneEditing}> | ||||
|         <TextValidator | ||||
|           validators={creating ? ['required', 'uniqueUsername', 'matchRegexp:^[a-zA-Z0-9_\\.]{1,24}$'] : []} | ||||
|           errorMessages={creating ? ['Username is required', "That username already exists", "Must be 1-24 characters: alpha numberic, '_' or '.'"] : []} | ||||
|           name="username" | ||||
|           label="Username" | ||||
|           className={classes.textField} | ||||
|           value={user.username} | ||||
|           disabled={!creating} | ||||
|           onChange={handleValueChange('username')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <PasswordValidator | ||||
|           validators={['required', 'matchRegexp:^.{0,64}$']} | ||||
|           errorMessages={['Password is required', 'Password must be 64 characters or less']} | ||||
|           name="password" | ||||
|           label="Password" | ||||
|           className={classes.textField} | ||||
|           value={user.password} | ||||
|           onChange={handleValueChange('password')} | ||||
|           margin="normal" | ||||
|         /> | ||||
|         <FormControl className={classes.textField}> | ||||
|           <InputLabel htmlFor="roles">Roles</InputLabel> | ||||
|           <Select | ||||
|             multiple | ||||
|             value={user.roles} | ||||
|             onChange={handleValueChange('roles')} | ||||
|             input={<Input id="roles" />} | ||||
|             renderValue={selected => ( | ||||
|               <div className={classes.chips}> | ||||
|                 {selected.map(value => ( | ||||
|                   <Chip key={value} label={value} className={classes.chip} /> | ||||
|                 ))} | ||||
|               </div> | ||||
|             )} | ||||
|           > | ||||
|             {roles.map(name => ( | ||||
|               <MenuItem key={name} value={name}> | ||||
|                 {name} | ||||
|               </MenuItem> | ||||
|             ))} | ||||
|           </Select> | ||||
|         </FormControl> | ||||
|         <Button variant="contained" color="primary" className={classes.button} type="submit"> | ||||
|           Save | ||||
|         </Button> | ||||
|         <Button variant="contained" color="secondary" className={classes.button} onClick={onCancelEditing}> | ||||
|           Back | ||||
|       	</Button> | ||||
|       </ValidatorForm> | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| UserForm.propTypes = { | ||||
|   classes: PropTypes.object.isRequired, | ||||
|   user: PropTypes.object.isRequired, | ||||
|   creating: PropTypes.bool.isRequired, | ||||
|   roles: PropTypes.array.isRequired, | ||||
|   onDoneEditing: PropTypes.func.isRequired, | ||||
|   onCancelEditing: PropTypes.func.isRequired, | ||||
|   uniqueUsername: PropTypes.func.isRequired, | ||||
|   handleValueChange: PropTypes.func.isRequired | ||||
| }; | ||||
|  | ||||
| export default withStyles(styles)(UserForm); | ||||
		Reference in New Issue
	
	Block a user