diff --git a/webui/package-lock.json b/webui/package-lock.json
index 50f8d7970fcfab8a2b778f6f8267fb4dc66d001e..268525c31f9a151316ece9b69e0602348c970272 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
}
}
},
@@ -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
}
}
},
@@ -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",
diff --git a/webui/package.json b/webui/package.json
index c5ccef9a82176b016b568725410f8cb2ecdda773..e8ebebac8ff8a42d9d64b51d3dc2ccf4dfd613c2 100644
--- a/webui/package.json
+++ b/webui/package.json
@@ -5,6 +5,7 @@
"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",
"moment": "^2.24.0",
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;