diff --git a/webui/package-lock.json b/webui/package-lock.json index 50f8d7970fcfab8a2b778f6f8267fb4dc66d001e..fc2bc0b258d3699b2bc079a58d8d1b109fabc409 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -849,6 +849,11 @@ "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", @@ -892,6 +897,41 @@ "recompose": "0.28.0 - 0.30.0" } }, + "@material-ui/styles": { + "version": "3.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-3.0.0-alpha.10.tgz", + "integrity": "sha512-qJ5eiupBPRCNlMCDZ2G5h8auBtBtm8uT/oCUAJ/FqhO5oC7POLmmvDN1Cq1cgAmqQnaL6uN5mAM1Gc90GpKr9A==", + "requires": { + "@babel/runtime": "^7.2.0", + "@emotion/hash": "^0.7.1", + "@material-ui/utils": "^3.0.0-alpha.2", + "classnames": "^2.2.5", + "deepmerge": "^3.0.0", + "hoist-non-react-statics": "^3.2.1", + "jss": "^10.0.0-alpha.7", + "jss-plugin-camel-case": "^10.0.0-alpha.7", + "jss-plugin-default-unit": "^10.0.0-alpha.7", + "jss-plugin-global": "^10.0.0-alpha.7", + "jss-plugin-nested": "^10.0.0-alpha.7", + "jss-plugin-props-sort": "^10.0.0-alpha.7", + "jss-plugin-rule-value-function": "^10.0.0-alpha.7", + "jss-plugin-vendor-prefixer": "^10.0.0-alpha.7", + "prop-types": "^15.6.0", + "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", @@ -3103,7 +3143,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -3121,11 +3162,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3138,15 +3181,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3249,7 +3295,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3259,6 +3306,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3271,17 +3319,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3298,6 +3349,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -3370,7 +3422,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -3380,6 +3433,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -3455,7 +3509,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -3485,6 +3540,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3502,6 +3558,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3540,11 +3597,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -5225,9 +5284,9 @@ } }, "eslint-config-prettier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz", - "integrity": "sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz", + "integrity": "sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA==", "dev": true, "requires": { "get-stdin": "^6.0.0" @@ -5437,9 +5496,9 @@ } }, "eslint-plugin-prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", - "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz", + "integrity": "sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -6721,7 +6780,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -6739,11 +6799,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6756,15 +6818,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -6867,7 +6932,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -6877,6 +6943,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -6889,17 +6956,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -6916,6 +6986,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -6988,7 +7059,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -6998,6 +7070,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -7073,7 +7146,8 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -7103,6 +7177,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7120,6 +7195,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7158,11 +7234,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.2", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -7307,9 +7385,9 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "graphql": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.2.0.tgz", - "integrity": "sha512-dlFHRtxsL4sBy1C1e3v64IUd5ndZhAOHZ/z3Dr4Nm6+cvr9elrnz4BhMF9h9mRBBnhUCGLc4GH4xvPbKG6sUeA==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.3.0.tgz", + "integrity": "sha512-MdfI4v7kSNC3NhB7cF8KNijDsifuWO2XOtzpyququqaclO8wVuChYv+KogexDwgP5sp7nFI9Z6N4QHgoLkfjrg==", "requires": { "iterall": "^1.2.2" } @@ -9380,6 +9458,76 @@ } } }, + "jss-plugin-camel-case": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.0.0-alpha.7.tgz", + "integrity": "sha512-Bwrav1ZB0XywdJW6TaEuFhKe1ZpZvUlESh3jsFOvebA9aFTYNCkmHMEqjA5+u9VMxksl3u77nnZHtukpxkzrBA==", + "requires": { + "@babel/runtime": "^7.0.0", + "hyphenate-style-name": "^1.0.2" + } + }, + "jss-plugin-default-unit": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.0.0-alpha.7.tgz", + "integrity": "sha512-auuJUbQaWMxoHOVFPrfZNZpZm9ab8PZeDyvey8nMt2lbokkmZ53UyAnM/1kNsg5BdAXTItcLDxDB3I4gwNU84g==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-global": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.0.0-alpha.7.tgz", + "integrity": "sha512-OWeoW4szLDgRUKviST+xfilqa8O5uXJCW+O3YonheCRTRJg6rRzlE/b5pfYPoU9UtwvY9n7JvwBX5r3c1lMsEQ==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-nested": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.0.0-alpha.7.tgz", + "integrity": "sha512-wsRzuIZXAc6WMjc61mREW9cUrDxgSI7dK/fx5c7a06IDUfSn+83NJ30J/RB4oBnbQW9SijV/muujz7IJqpn9Gw==", + "requires": { + "@babel/runtime": "^7.0.0", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.0.0-alpha.7.tgz", + "integrity": "sha512-KXOCaHUk1+KXqE0z3q66/w1fDoy+VsZvI77gLxOqTsTrvIKFLX0jarwXogW3CDlaPQQFTZ6JykJJXtPRTBlstA==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.0.0-alpha.7.tgz", + "integrity": "sha512-ett83hvIM69/LknmrWndrrdiDlfLfP+rneU5qP7gTOWJ7g1P9GuEL1Tc4CWdZUWBX+T58tgIBP0V1pzWCkP0QA==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.0.0-alpha.7", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.0.0-alpha.7.tgz", + "integrity": "sha512-YbIVgqq+dLimOBOEYggho1Iuc0roz4PJSZYyaok9n8JnXVIqPnxYJbr8+bMbvzJ5CL3eeJij/e7L2IPCceRKrA==", + "requires": { + "@babel/runtime": "^7.0.0", + "css-vendor": "^1.1.0" + }, + "dependencies": { + "css-vendor": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-1.2.1.tgz", + "integrity": "sha512-ZpwiWxn5jWNJ7NF3DAb/Dc/+c2lRu+fnovej/adCv3VJsULJSjdXEpUwRcq4fnpAAh98Hi7b0GDnlyoNFcdv1g==", + "requires": { + "@babel/runtime": "^7.3.1", + "is-in-browser": "^1.0.2" + } + } + } + }, "jss-props-sort": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz", @@ -13096,9 +13244,9 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" }, "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.17.1.tgz", + "integrity": "sha512-TzGRNvuUSmPgwivDqkZ9tM/qTGW9hqDKWOE9YHiyQdixlKbv7kvEqsmDPrcHJTKwthU774TQwZXVtaQ/mMsvjg==", "dev": true }, "prettier-linter-helpers": { @@ -13381,24 +13529,26 @@ } }, "react-apollo": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.5.3.tgz", - "integrity": "sha512-sBh7M3h4xdbck8NFnn1nlUG0mD0hCTeIcvov4A8hagxjOyTVSakoum+DP6rYNaHuAZFDS3oNurNNSbGZmgoU6g==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/react-apollo/-/react-apollo-2.5.6.tgz", + "integrity": "sha512-WWX5UykTtmW6+awjqEsSWSdvVyZv/vsavUgpdI4ddn4CBdz47INC+iTdJBnYaUFMB24GmqjFFSoSd98gu1xqKA==", "requires": { - "apollo-utilities": "^1.2.1", + "apollo-utilities": "^1.3.0", "hoist-non-react-statics": "^3.3.0", "lodash.isequal": "^4.5.0", "prop-types": "^15.7.2", - "ts-invariant": "^0.3.2", + "ts-invariant": "^0.4.2", "tslib": "^1.9.3" }, "dependencies": { - "hoist-non-react-statics": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz", - "integrity": "sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==", + "apollo-utilities": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.0.tgz", + "integrity": "sha512-wQjV+FdWcTWmWUFlChG5rS0vHKy5OsXC6XlV9STRstQq6VbXANwHy6DHnTEQAfLXWAbNcPgBu+nBUpR3dFhwrA==", "requires": { - "react-is": "^16.7.0" + "fast-json-stable-stringify": "^2.0.0", + "ts-invariant": "^0.4.0", + "tslib": "^1.9.3" } }, "prop-types": { @@ -13412,9 +13562,9 @@ } }, "ts-invariant": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.3.2.tgz", - "integrity": "sha512-QsY8BCaRnHiB5T6iE4DPlJMAKEG3gzMiUco9FEt1jUXQf0XP6zi0idT0i0rMTu8A326JqNSDsmlkA9dRSh1TRg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.2.tgz", + "integrity": "sha512-PTAAn8lJPEdRBJJEs4ig6MVZWfO12yrFzV7YaPslmyhG7+4MA279y4BXT3f72gXeVl0mC1aAWq2rMX4eKTWU/Q==", "requires": { "tslib": "^1.9.3" } diff --git a/webui/package.json b/webui/package.json index c5ccef9a82176b016b568725410f8cb2ecdda773..f3138a49f9851ed320bbd73dfa80610be8db4ebd 100644 --- a/webui/package.json +++ b/webui/package.json @@ -5,20 +5,21 @@ "dependencies": { "@material-ui/core": "^3.9.3", "@material-ui/icons": "^3.0.2", + "@material-ui/styles": "^3.0.0-alpha.10", "apollo-boost": "^0.3.1", - "graphql": "^14.2.0", + "graphql": "^14.3.0", "moment": "^2.24.0", "react": "^16.8.6", - "react-apollo": "^2.5.3", + "react-apollo": "^2.5.6", "react-dom": "^16.8.6", "react-router": "^5.0.0", "react-router-dom": "^5.0.0", "react-scripts": "^2.1.8" }, "devDependencies": { - "eslint-config-prettier": "^4.1.0", - "eslint-plugin-prettier": "^3.0.1", - "prettier": "^1.16.4" + "eslint-config-prettier": "^4.3.0", + "eslint-plugin-prettier": "^3.1.0", + "prettier": "^1.17.1" }, "scripts": { "start": "react-scripts start", diff --git a/webui/src/App.js b/webui/src/App.js index 3a693dcb06794f81424ec14e9bc61aa10eeb28da..b2eb6bf0d27d2bcfb195a8e108ddb872fb6a71bb 100644 --- a/webui/src/App.js +++ b/webui/src/App.js @@ -1,39 +1,39 @@ import AppBar from '@material-ui/core/AppBar'; import CssBaseline from '@material-ui/core/CssBaseline'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import Toolbar from '@material-ui/core/Toolbar'; -import Typography from '@material-ui/core/Typography'; import React from 'react'; -import { Route, Switch, withRouter } from 'react-router'; +import { Route, Switch } from 'react-router'; import { Link } from 'react-router-dom'; import BugQuery from './bug/BugQuery'; import ListQuery from './list/ListQuery'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ appTitle: { + ...theme.typography.title, color: 'white', textDecoration: 'none', }, -}); +})); -const App = ({ location, classes }) => ( - - - - - - - git-bug webui - - - - - - - - - -); +export default function App() { + const classes = useStyles(); -export default withStyles(styles)(withRouter(App)); + return ( + <> + + + + + git-bug webui + + + + + + + + + ); +} diff --git a/webui/src/Label.js b/webui/src/Label.js index e7c25c237f231afff9c3b9ee4faecbed09bc88bb..826d21f55daf509f4db5ab84b58367d7129a68dc 100644 --- a/webui/src/Label.js +++ b/webui/src/Label.js @@ -1,5 +1,5 @@ import React from 'react'; -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import { getContrastRatio, darken, @@ -42,7 +42,7 @@ const _genStyle = background => ({ // Generate a style object (text, background and border colors) from the label const genStyle = label => _genStyle(getColor(label)); -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ label: { ...theme.typography.body2, padding: '0 6px', @@ -53,12 +53,15 @@ const styles = theme => ({ borderBottom: 'solid 1.5px', verticalAlign: 'bottom', }, -}); +})); -const Label = ({ label, classes }) => ( - - {label} - -); +function Label({ label }) { + const classes = useStyles(); + return ( + + {label} + + ); +} -export default withStyles(styles)(Label); +export default Label; diff --git a/webui/src/bug/Bug.js b/webui/src/bug/Bug.js index 9b5f84ad19a77fd0d31005dcfc1cdd15fb193e28..829a4af2d7b876b4821f504b90e93782b92d5bb9 100644 --- a/webui/src/bug/Bug.js +++ b/webui/src/bug/Bug.js @@ -1,4 +1,4 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import Typography from '@material-ui/core/Typography/Typography'; import gql from 'graphql-tag'; import React from 'react'; @@ -7,7 +7,7 @@ import Date from '../Date'; import TimelineQuery from './TimelineQuery'; import Label from '../Label'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { maxWidth: 800, margin: 'auto', @@ -48,38 +48,41 @@ const styles = theme => ({ display: 'block', }, }, -}); +})); -const Bug = ({ bug, classes }) => ( -
-
- {bug.title} - {bug.humanId} +function Bug({ bug }) { + const classes = useStyles(); + return ( +
+
+ {bug.title} + {bug.humanId} - - - {' opened this bug '} - - -
- -
-
- + + + {' opened this bug '} + +
-
- Labels -
    - {bug.labels.map(l => ( -
  • -
  • - ))} -
+ +
+
+ +
+
+ Labels +
    + {bug.labels.map(l => ( +
  • +
  • + ))} +
+
-
-
-); +
+ ); +} Bug.fragment = gql` fragment Bug on Bug { @@ -97,4 +100,4 @@ Bug.fragment = gql` } `; -export default withStyles(styles)(Bug); +export default Bug; diff --git a/webui/src/bug/LabelChange.js b/webui/src/bug/LabelChange.js index 6301f35f36a8ed73dab9b1fc2137a57665346889..76b6e6e28f0d2b6bf481b3db1416b5bfb2a8c4bc 100644 --- a/webui/src/bug/LabelChange.js +++ b/webui/src/bug/LabelChange.js @@ -1,11 +1,11 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import gql from 'graphql-tag'; import React from 'react'; import Author from '../Author'; import Date from '../Date'; import Label from '../Label'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { ...theme.typography.body2, marginLeft: theme.spacing.unit + 40, @@ -13,10 +13,11 @@ const styles = theme => ({ author: { fontWeight: 'bold', }, -}); +})); -const LabelChange = ({ op, classes }) => { +function LabelChange({ op }) { const { added, removed } = op; + const classes = useStyles(); return (
@@ -37,7 +38,7 @@ const LabelChange = ({ op, classes }) => {
); -}; +} LabelChange.fragment = gql` fragment LabelChange on TimelineItem { @@ -54,4 +55,4 @@ LabelChange.fragment = gql` } `; -export default withStyles(styles)(LabelChange); +export default LabelChange; diff --git a/webui/src/bug/Message.js b/webui/src/bug/Message.js index 493de8ee86857018b8d5a09f1fd8d80bd0d69736..ff03944496461095c7af154b00e8a0247c22f5a9 100644 --- a/webui/src/bug/Message.js +++ b/webui/src/bug/Message.js @@ -1,4 +1,4 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import Paper from '@material-ui/core/Paper'; import gql from 'graphql-tag'; import React from 'react'; @@ -6,7 +6,7 @@ import Author from '../Author'; import { Avatar } from '../Author'; import Date from '../Date'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ author: { fontWeight: 'bold', }, @@ -44,24 +44,27 @@ const styles = theme => ({ padding: '1rem', whiteSpace: 'pre-wrap', }, -}); +})); -const Message = ({ op, classes }) => ( -
- - -
-
- - commented - -
- {op.edited &&
Edited
} -
-
{op.message}
-
-
-); +function Message({ op }) { + const classes = useStyles(); + return ( +
+ + +
+
+ + commented + +
+ {op.edited &&
Edited
} +
+
{op.message}
+
+
+ ); +} Message.createFragment = gql` fragment Create on TimelineItem { @@ -95,4 +98,4 @@ Message.commentFragment = gql` } `; -export default withStyles(styles)(Message); +export default Message; diff --git a/webui/src/bug/SetStatus.js b/webui/src/bug/SetStatus.js index 58b81630010d27e582d60dc3626384547f4bc9d3..ab591038e3f4ce21fd7da6dc47a6f8ff203db5ec 100644 --- a/webui/src/bug/SetStatus.js +++ b/webui/src/bug/SetStatus.js @@ -1,17 +1,18 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import gql from 'graphql-tag'; import React from 'react'; import Author from '../Author'; import Date from '../Date'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { ...theme.typography.body2, marginLeft: theme.spacing.unit + 40, }, -}); +})); -const SetStatus = ({ op, classes }) => { +function SetStatus({ op }) { + const classes = useStyles(); return (
@@ -19,7 +20,7 @@ const SetStatus = ({ op, classes }) => {
); -}; +} SetStatus.fragment = gql` fragment SetStatus on TimelineItem { @@ -35,4 +36,4 @@ SetStatus.fragment = gql` } `; -export default withStyles(styles)(SetStatus); +export default SetStatus; diff --git a/webui/src/bug/SetTitle.js b/webui/src/bug/SetTitle.js index f5c48568de0431c331da986acb2eda174517164c..d9a09ad54d73e446daf6e2a393a70af3e194f4fe 100644 --- a/webui/src/bug/SetTitle.js +++ b/webui/src/bug/SetTitle.js @@ -1,10 +1,10 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import gql from 'graphql-tag'; import React from 'react'; import Author from '../Author'; import Date from '../Date'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { ...theme.typography.body2, marginLeft: theme.spacing.unit + 40, @@ -12,9 +12,10 @@ const styles = theme => ({ bold: { fontWeight: 'bold', }, -}); +})); -const SetTitle = ({ op, classes }) => { +function SetTitle({ op }) { + const classes = useStyles(); return (
@@ -25,7 +26,7 @@ const SetTitle = ({ op, classes }) => {
); -}; +} SetTitle.fragment = gql` fragment SetTitle on TimelineItem { @@ -42,4 +43,4 @@ SetTitle.fragment = gql` } `; -export default withStyles(styles)(SetTitle); +export default SetTitle; diff --git a/webui/src/bug/Timeline.js b/webui/src/bug/Timeline.js index 3123f45f9628822a48b6d0491b7b37a690bf0403..d77e0d4b554847d21fddb7b9cac54485a1202b96 100644 --- a/webui/src/bug/Timeline.js +++ b/webui/src/bug/Timeline.js @@ -1,51 +1,43 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import React from 'react'; import LabelChange from './LabelChange'; import Message from './Message'; import SetStatus from './SetStatus'; import SetTitle from './SetTitle'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { '& > *:not(:last-child)': { marginBottom: theme.spacing.unit * 2, }, }, -}); +})); -class Timeline extends React.Component { - props: { - ops: Array, - fetchMore: any => any, - classes: any, - }; +const componentMap = { + CreateTimelineItem: Message, + AddCommentTimelineItem: Message, + LabelChangeTimelineItem: LabelChange, + SetTitleTimelineItem: SetTitle, + SetStatusTimelineItem: SetStatus, +}; - render() { - const { ops, classes } = this.props; +function Timeline({ ops }) { + const classes = useStyles(); - return ( -
- {ops.map((op, index) => { - switch (op.__typename) { - case 'CreateTimelineItem': - return ; - case 'AddCommentTimelineItem': - return ; - case 'LabelChangeTimelineItem': - return ; - case 'SetTitleTimelineItem': - return ; - case 'SetStatusTimelineItem': - return ; + return ( +
+ {ops.map((op, index) => { + const Component = componentMap[op.__typename]; - default: - console.log('unsupported operation type ' + op.__typename); - return null; - } - })} -
- ); - } + if (!Component) { + console.warn('unsupported operation type ' + op.__typename); + return null; + } + + return ; + })} +
+ ); } -export default withStyles(styles)(Timeline); +export default Timeline; diff --git a/webui/src/index.js b/webui/src/index.js index f5d95ccc289c6dc4b096b4d8c850c2c952223661..885911f5cef774b768840c36b751a1de51e8de1f 100644 --- a/webui/src/index.js +++ b/webui/src/index.js @@ -1,22 +1,31 @@ +import { install } from '@material-ui/styles'; +import ThemeProvider from '@material-ui/styles/ThemeProvider'; +import { createMuiTheme } from '@material-ui/core/styles'; import ApolloClient from 'apollo-boost'; import React from 'react'; import { ApolloProvider } from 'react-apollo'; import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; -import App from './App'; +install(); + +// TODO(sandhose): this is temporary until Material-UI v4 goes out +const App = React.lazy(() => import('./App')); + +const theme = createMuiTheme(); const client = new ApolloClient({ uri: '/graphql', - connectToDevTools: true, }); ReactDOM.render( - - - + + + + + , document.getElementById('root') diff --git a/webui/src/list/BugRow.js b/webui/src/list/BugRow.js index a045770b96e854984a46085c6a916f6ff49eada5..e82d81db091ba786d4c282a81886990ff6e0d614 100644 --- a/webui/src/list/BugRow.js +++ b/webui/src/list/BugRow.js @@ -1,4 +1,4 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; import TableCell from '@material-ui/core/TableCell/TableCell'; import TableRow from '@material-ui/core/TableRow/TableRow'; import Tooltip from '@material-ui/core/Tooltip/Tooltip'; @@ -33,7 +33,7 @@ const Status = ({ status, className }) => { } }; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ cell: { display: 'flex', alignItems: 'center', @@ -53,36 +53,39 @@ const styles = theme => ({ labels: { paddingLeft: theme.spacing.unit, }, -}); +})); -const BugRow = ({ bug, classes }) => ( - - - -
- -
- - {bug.title} - - {bug.labels.length > 0 && ( - - {bug.labels.map(l => ( - - )} -
- - - {bug.humanId} opened - - by {bug.author.displayName} - -
-
-
-); +function BugRow({ bug }) { + const classes = useStyles(); + return ( + + + +
+ +
+ + {bug.title} + + {bug.labels.length > 0 && ( + + {bug.labels.map(l => ( + + )} +
+ + + {bug.humanId} opened + + by {bug.author.displayName} + +
+
+
+ ); +} BugRow.fragment = gql` fragment BugRow on Bug { @@ -99,4 +102,4 @@ BugRow.fragment = gql` } `; -export default withStyles(styles)(BugRow); +export default BugRow; diff --git a/webui/src/list/List.js b/webui/src/list/List.js index d36be8a1464b4f30028c40b397fedd3b1a609eaf..45c2c963f0c90ed174062d2639ffb936486fe06a 100644 --- a/webui/src/list/List.js +++ b/webui/src/list/List.js @@ -1,134 +1,50 @@ -import { withStyles } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/styles'; +import IconButton from '@material-ui/core/IconButton'; import Table from '@material-ui/core/Table/Table'; import TableBody from '@material-ui/core/TableBody/TableBody'; -import TablePagination from '@material-ui/core/TablePagination/TablePagination'; +import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft'; +import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight'; import React from 'react'; import BugRow from './BugRow'; -const styles = theme => ({ +const useStyles = makeStyles(theme => ({ main: { maxWidth: 600, margin: 'auto', marginTop: theme.spacing.unit * 4, }, -}); - -class List extends React.Component { - props: { - bugs: Array, - fetchMore: any => any, - classes: any, - }; - - state = { - page: 0, - rowsPerPage: 10, - lastQuery: {}, - }; - - handleChangePage = (event, page) => { - const { bugs, fetchMore } = this.props; - const { rowsPerPage } = this.state; - const pageInfo = bugs.pageInfo; - - if (page === this.state.page + 1) { - if (!pageInfo.hasNextPage) { - return; - } - - const variables = { - after: pageInfo.endCursor, - first: rowsPerPage, - }; - - fetchMore({ - variables, - updateQuery: this.updateQuery, - }); - - this.setState({ page, lastQuery: variables }); - return; - } - - if (page === this.state.page - 1) { - if (!pageInfo.hasPreviousPage) { - return; - } - - const variables = { - before: pageInfo.startCursor, - last: rowsPerPage, - }; - - fetchMore({ - variables, - updateQuery: this.updateQuery, - }); - - this.setState({ page, lastQuery: variables }); - return; - } - - throw new Error('non neighbour page pagination is not supported'); - }; - - handleChangeRowsPerPage = event => { - const { fetchMore } = this.props; - const { lastQuery } = this.state; - const rowsPerPage = event.target.value; - - const variables = lastQuery; - - if (lastQuery.first) { - variables.first = rowsPerPage; - } else if (lastQuery.last) { - variables.last = rowsPerPage; - } else { - variables.first = rowsPerPage; - } - - fetchMore({ - variables, - updateQuery: this.updateQuery, - }); - - this.setState({ rowsPerPage, lastQuery: variables }); - }; - - updateQuery = (previousResult, { fetchMoreResult }) => { - return fetchMoreResult ? fetchMoreResult : previousResult; - }; - - render() { - const { classes, bugs } = this.props; - const { page, rowsPerPage } = this.state; - - return ( -
- - - {bugs.edges.map(({ cursor, node }) => ( - - ))} - -
- -
- ); - } + pagination: { + ...theme.typography.overline, + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-end', + }, +})); + +function List({ bugs, nextPage, prevPage }) { + const classes = useStyles(); + const { hasNextPage, hasPreviousPage } = bugs.pageInfo; + return ( +
+ + + {bugs.edges.map(({ cursor, node }) => ( + + ))} + +
+ +
+
Total: {bugs.totalCount}
+ + + + + + +
+
+ ); } -export default withStyles(styles)(List); +export default List; diff --git a/webui/src/list/ListQuery.js b/webui/src/list/ListQuery.js index 9dbe4e53d670f26fa42cbbebe8a04e8aa9b319a6..869bca79824334de3fed0c1a355c3010aeb71321 100644 --- a/webui/src/list/ListQuery.js +++ b/webui/src/list/ListQuery.js @@ -1,13 +1,13 @@ // @flow import CircularProgress from '@material-ui/core/CircularProgress'; import gql from 'graphql-tag'; -import React from 'react'; +import React, { useState } from 'react'; import { Query } from 'react-apollo'; import BugRow from './BugRow'; import List from './List'; const QUERY = gql` - query($first: Int = 10, $last: Int, $after: String, $before: String) { + query($first: Int, $last: Int, $after: String, $before: String) { defaultRepository { bugs: allBugs( first: $first @@ -35,14 +35,31 @@ const QUERY = gql` ${BugRow.fragment} `; -const ListQuery = () => ( - - {({ loading, error, data, fetchMore }) => { - if (loading) return ; - if (error) return

Error: {error}

; - return ; - }} -
-); +function ListQuery() { + const [page, setPage] = useState({ first: 10, after: null }); + + const perPage = page.first || page.last; + const nextPage = pageInfo => + setPage({ first: perPage, after: pageInfo.endCursor }); + const prevPage = pageInfo => + setPage({ last: perPage, before: pageInfo.startCursor }); + + return ( + + {({ loading, error, data }) => { + if (loading) return ; + if (error) return

Error: {error}

; + const bugs = data.defaultRepository.bugs; + return ( + nextPage(bugs.pageInfo)} + prevPage={() => prevPage(bugs.pageInfo)} + /> + ); + }} +
+ ); +} export default ListQuery;