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/Filter.js | 77 +++++++++++++++++++++++++++++++++++------ webui/src/list/FilterToolbar.js | 17 +++++++-- webui/src/list/ListQuery.js | 21 +++++++---- 3 files changed, 95 insertions(+), 20 deletions(-) (limited to 'webui/src/list') diff --git a/webui/src/list/Filter.js b/webui/src/list/Filter.js index c93b2d35..a6cf3633 100644 --- a/webui/src/list/Filter.js +++ b/webui/src/list/Filter.js @@ -1,13 +1,16 @@ -import React from 'react'; +import React, { useState, useRef } from 'react'; import { Link } from 'react-router-dom'; import { makeStyles } from '@material-ui/styles'; +import Menu from '@material-ui/core/Menu'; +import MenuItem from '@material-ui/core/MenuItem'; +import ArrowDropDown from '@material-ui/icons/ArrowDropDown'; function parse(query) { // TODO: extract the rest of the query? const params = {}; // TODO: support escaping without quotes - const re = /(\w+):(\w+|(["'])(([^\3]|\\.)*)\3)+/g; + const re = /(\w+):([A-Za-z0-9-]+|(["'])(([^\3]|\\.)*)\3)+/g; let matches; while ((matches = re.exec(query)) !== null) { if (!params[matches[1]]) { @@ -58,20 +61,63 @@ const useStyles = makeStyles(theme => ({ ...theme.typography.body2, color: ({ active }) => (active ? '#333' : '#444'), padding: theme.spacing(0, 1), - fontWeight: ({ active }) => (active ? 500 : 400), + fontWeight: ({ active }) => (active ? 600 : 400), textDecoration: 'none', display: 'flex', - alignSelf: ({ end }) => (end ? 'flex-end' : 'auto'), background: 'none', border: 'none', }, + itemActive: { + fontWeight: 600, + }, icon: { paddingRight: theme.spacing(0.5), }, })); -function Filter({ active, to, children, icon: Icon, end, ...props }) { - const classes = useStyles({ active, end }); +function Dropdown({ children, dropdown, itemActive, to, ...props }) { + const [open, setOpen] = useState(false); + const buttonRef = useRef(); + const classes = useStyles(); + + return ( + <> + + setOpen(false)} + anchorEl={buttonRef.current} + > + {dropdown.map(([key, value]) => ( + setOpen(false)} + key={key} + > + {value} + + ))} + + + ); +} + +function Filter({ active, to, children, icon: Icon, dropdown, ...props }) { + const classes = useStyles({ active }); const content = ( <> @@ -80,6 +126,19 @@ function Filter({ active, to, children, icon: Icon, end, ...props }) { ); + if (dropdown) { + return ( + + {content} + + ); + } + if (to) { return ( @@ -88,11 +147,7 @@ function Filter({ active, to, children, icon: Icon, end, ...props }) { ); } - return ( - - ); + return
{content}
; } export default Filter; 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 + ); } diff --git a/webui/src/list/ListQuery.js b/webui/src/list/ListQuery.js index b6a29702..01113f6c 100644 --- a/webui/src/list/ListQuery.js +++ b/webui/src/list/ListQuery.js @@ -45,11 +45,13 @@ const useStyles = makeStyles(theme => ({ borderWidth: '1px', backgroundColor: fade(theme.palette.primary.main, 0.05), padding: theme.spacing(0, 1), - ':focus': { - // TODO - borderColor: fade(theme.palette.primary.main, 0.4), - backgroundColor: theme.palette.background.paper, - }, + width: ({ searching }) => (searching ? '20rem' : '15rem'), + transition: theme.transitions.create(), + }, + searchFocused: { + borderColor: fade(theme.palette.primary.main, 0.4), + backgroundColor: theme.palette.background.paper, + width: '20rem!important', }, placeholderRow: { padding: theme.spacing(1), @@ -182,7 +184,6 @@ const Error = ({ error }) => { }; function ListQuery() { - const classes = useStyles(); const location = useLocation(); const history = useHistory(); const params = new URLSearchParams(location.search); @@ -190,6 +191,8 @@ function ListQuery() { const [input, setInput] = useState(query); + const classes = useStyles({ searching: !!input }); + // TODO is this the right way to do it? const lastQuery = useRef(); useEffect(() => { @@ -291,9 +294,13 @@ function ListQuery() {

Issues

setInput(e.target.value)} - className={classes.search} + classes={{ + root: classes.search, + focused: classes.searchFocused, + }} />