diff options
author | Michael Muré <batolettre@gmail.com> | 2020-02-14 22:56:59 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2020-02-14 22:56:59 +0100 |
commit | e9aff2a2a103b43852ecf7b57ae9ab297890eeed (patch) | |
tree | d66cb75151e42ada31e1d0179f8dba0ace388989 /webui/src/list/FilterToolbar.tsx | |
parent | b2ca506210b3eb63c4964e5bb47203fd5341ddf4 (diff) | |
parent | 2df72942f2b057956c7873f908b64880ab647331 (diff) | |
download | git-bug-e9aff2a2a103b43852ecf7b57ae9ab297890eeed.tar.gz |
Merge remote-tracking branch 'origin/master' into cheshirekow-jira
Diffstat (limited to 'webui/src/list/FilterToolbar.tsx')
-rw-r--r-- | webui/src/list/FilterToolbar.tsx | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/webui/src/list/FilterToolbar.tsx b/webui/src/list/FilterToolbar.tsx new file mode 100644 index 00000000..b95b10bc --- /dev/null +++ b/webui/src/list/FilterToolbar.tsx @@ -0,0 +1,128 @@ +import { pipe } from '@arrows/composition'; +import Toolbar from '@material-ui/core/Toolbar'; +import { makeStyles } from '@material-ui/core/styles'; +import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; +import ErrorOutline from '@material-ui/icons/ErrorOutline'; +import { LocationDescriptor } from 'history'; +import React from 'react'; + +import { + FilterDropdown, + FilterProps, + Filter, + parse, + stringify, + Query, +} from './Filter'; +import { useBugCountQuery } from './FilterToolbar.generated'; + +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, + }, +})); + +// This prepends the filter text with a count +type CountingFilterProps = { + query: string; + children: React.ReactNode; +} & FilterProps; +function CountingFilter({ query, children, ...props }: CountingFilterProps) { + const { data, loading, error } = useBugCountQuery({ + variables: { query }, + }); + + var prefix; + if (loading) prefix = '...'; + else if (error || !data?.repository) prefix = '???'; + // TODO: better prefixes & error handling + else prefix = data.repository.bugs.totalCount; + + return ( + <Filter {...props}> + {prefix} {children} + </Filter> + ); +} + +type Props = { + query: string; + queryLocation: (query: string) => LocationDescriptor; +}; +function FilterToolbar({ query, queryLocation }: Props) { + const classes = useStyles(); + const params: Query = parse(query); + + const hasKey = (key: string): boolean => + params[key] && params[key].length > 0; + const hasValue = (key: string, value: string): boolean => + hasKey(key) && params[key].includes(value); + const loc = pipe(stringify, queryLocation); + const replaceParam = (key: string, value: string) => ( + params: Query + ): Query => ({ + ...params, + [key]: [value], + }); + const clearParam = (key: string) => (params: Query): Query => ({ + ...params, + [key]: [], + }); + + // TODO: author/label filters + return ( + <Toolbar className={classes.toolbar}> + <CountingFilter + active={hasValue('status', 'open')} + query={pipe( + replaceParam('status', 'open'), + clearParam('sort'), + stringify + )(params)} + to={pipe(replaceParam('status', 'open'), loc)(params)} + icon={ErrorOutline} + > + open + </CountingFilter> + <CountingFilter + active={hasValue('status', 'closed')} + query={pipe( + replaceParam('status', 'closed'), + clearParam('sort'), + stringify + )(params)} + to={pipe(replaceParam('status', 'closed'), loc)(params)} + icon={CheckCircleOutline} + > + closed + </CountingFilter> + <div className={classes.spacer} /> + {/* + <Filter active={hasKey('author')}>Author</Filter> + <Filter active={hasKey('label')}>Label</Filter> + */} + <FilterDropdown + dropdown={[ + ['id', 'ID'], + ['creation', 'Newest'], + ['creation-asc', 'Oldest'], + ['edit', 'Recently updated'], + ['edit-asc', 'Least recently updated'], + ]} + itemActive={key => hasValue('sort', key)} + to={key => pipe(replaceParam('sort', key), loc)(params)} + > + Sort + </FilterDropdown> + </Toolbar> + ); +} + +export default FilterToolbar; |