From 4d97e3a19a96e2361b35a0ccc0be74e0ba887214 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Sat, 25 Jan 2020 11:40:08 +0100 Subject: webui: implement filtering --- webui/src/list/FilterToolbar.js | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 webui/src/list/FilterToolbar.js (limited to 'webui/src/list/FilterToolbar.js') diff --git a/webui/src/list/FilterToolbar.js b/webui/src/list/FilterToolbar.js new file mode 100644 index 00000000..e6d6f4ed --- /dev/null +++ b/webui/src/list/FilterToolbar.js @@ -0,0 +1,60 @@ +import { makeStyles } from '@material-ui/styles'; +import React from 'react'; +import Toolbar from '@material-ui/core/Toolbar'; +import ErrorOutline from '@material-ui/icons/ErrorOutline'; +import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; +import Filter, { parse, stringify } from './Filter'; + +const useStyles = makeStyles(theme => ({ + toolbar: { + backgroundColor: theme.palette.grey['100'], + borderColor: theme.palette.grey['300'], + borderWidth: '1px 0', + borderStyle: 'solid', + margin: theme.spacing(0, -1), + }, + spacer: { + flex: 1, + }, +})); + +function FilterToolbar({ query, queryLocation }) { + const classes = useStyles(); + const params = parse(query); + const hasKey = key => params[key] && params[key].length > 0; + const hasValue = (key, value) => hasKey(key) && params[key].includes(value); + const replaceParam = (key, value) => { + const p = { + ...params, + [key]: [value], + }; + return queryLocation(stringify(p)); + }; + + // TODO: open/closed count + // TODO: author/label/sort filters + return ( + + + open + + + closed + +
+ Author + Label + Sort + + ); +} + +export default FilterToolbar; -- cgit From ead5bad7854bc2342e0998c8a45f62e9aace7887 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 30 Jan 2020 02:05:36 +0100 Subject: webui: implement issue list sort --- webui/src/list/FilterToolbar.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'webui/src/list/FilterToolbar.js') diff --git a/webui/src/list/FilterToolbar.js b/webui/src/list/FilterToolbar.js index e6d6f4ed..9f5f14c5 100644 --- a/webui/src/list/FilterToolbar.js +++ b/webui/src/list/FilterToolbar.js @@ -32,7 +32,7 @@ function FilterToolbar({ query, queryLocation }) { }; // TODO: open/closed count - // TODO: author/label/sort filters + // TODO: author/label filters return ( Author Label - Sort + hasValue('sort', key)} + to={key => replaceParam('sort', key)} + > + Sort + ); } -- cgit From adb28885a368e4ccffe7bfccdf45931e37f66a72 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Thu, 30 Jan 2020 23:38:25 +0100 Subject: webui: add open/closed issues count --- webui/src/list/FilterToolbar.js | 82 +++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 15 deletions(-) (limited to 'webui/src/list/FilterToolbar.js') diff --git a/webui/src/list/FilterToolbar.js b/webui/src/list/FilterToolbar.js index 9f5f14c5..4d0b52b1 100644 --- a/webui/src/list/FilterToolbar.js +++ b/webui/src/list/FilterToolbar.js @@ -1,10 +1,17 @@ import { makeStyles } from '@material-ui/styles'; +import { useQuery } from '@apollo/react-hooks'; +import gql from 'graphql-tag'; import React from 'react'; import Toolbar from '@material-ui/core/Toolbar'; import ErrorOutline from '@material-ui/icons/ErrorOutline'; import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; import Filter, { parse, stringify } from './Filter'; +// simple pipe operator +// pipe(o, f, g, h) <=> h(g(f(o))) +// TODO: move this out? +const pipe = (initial, ...funcs) => funcs.reduce((acc, f) => f(acc), initial); + const useStyles = makeStyles(theme => ({ toolbar: { backgroundColor: theme.palette.grey['100'], @@ -18,40 +25,85 @@ const useStyles = makeStyles(theme => ({ }, })); +const BUG_COUNT_QUERY = gql` + query($query: String) { + defaultRepository { + bugs: allBugs(query: $query) { + totalCount + } + } + } +`; + +// This prepends the filter text with a count +function CountingFilter({ query, children, ...props }) { + const { data, loading, error } = useQuery(BUG_COUNT_QUERY, { + variables: { query }, + }); + + var prefix; + if (loading) prefix = '...'; + else if (error) prefix = '???'; + // TODO: better prefixes & error handling + else prefix = data.defaultRepository.bugs.totalCount; + + return ( + + {prefix} {children} + + ); +} + function FilterToolbar({ query, queryLocation }) { const classes = useStyles(); const params = parse(query); + const hasKey = key => params[key] && params[key].length > 0; const hasValue = (key, value) => hasKey(key) && params[key].includes(value); - const replaceParam = (key, value) => { - const p = { - ...params, - [key]: [value], - }; - return queryLocation(stringify(p)); - }; + const loc = params => pipe(params, stringify, queryLocation); + const replaceParam = (key, value) => params => ({ + ...params, + [key]: [value], + }); + const clearParam = key => params => ({ + ...params, + [key]: [], + }); - // TODO: open/closed count // TODO: author/label filters return ( - open - - + closed - +
+ {/* Author Label + */} hasValue('sort', key)} - to={key => replaceParam('sort', key)} + to={key => pipe(params, replaceParam('sort', key), loc)} > Sort -- cgit