aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src/list/Filter.js
diff options
context:
space:
mode:
authorQuentin Gliech <quentingliech@gmail.com>2020-01-30 02:05:36 +0100
committerQuentin Gliech <quentingliech@gmail.com>2020-01-30 02:05:36 +0100
commitead5bad7854bc2342e0998c8a45f62e9aace7887 (patch)
treef4c38f38ac2d746597ad0b639661cd08cadca6fe /webui/src/list/Filter.js
parent4d97e3a19a96e2361b35a0ccc0be74e0ba887214 (diff)
downloadgit-bug-ead5bad7854bc2342e0998c8a45f62e9aace7887.tar.gz
webui: implement issue list sort
Diffstat (limited to 'webui/src/list/Filter.js')
-rw-r--r--webui/src/list/Filter.js77
1 files changed, 66 insertions, 11 deletions
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 (
+ <>
+ <button ref={buttonRef} onClick={() => setOpen(!open)} {...props}>
+ {children}
+ <ArrowDropDown fontSize="small" />
+ </button>
+ <Menu
+ getContentAnchorEl={null}
+ anchorOrigin={{
+ vertical: 'bottom',
+ horizontal: 'left',
+ }}
+ transformOrigin={{
+ vertical: 'top',
+ horizontal: 'left',
+ }}
+ open={open}
+ onClose={() => setOpen(false)}
+ anchorEl={buttonRef.current}
+ >
+ {dropdown.map(([key, value]) => (
+ <MenuItem
+ component={Link}
+ to={to(key)}
+ className={itemActive(key) ? classes.itemActive : null}
+ onClick={() => setOpen(false)}
+ key={key}
+ >
+ {value}
+ </MenuItem>
+ ))}
+ </Menu>
+ </>
+ );
+}
+
+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 (
+ <Dropdown
+ {...props}
+ to={to}
+ dropdown={dropdown}
+ className={classes.element}
+ >
+ {content}
+ </Dropdown>
+ );
+ }
+
if (to) {
return (
<Link to={to} {...props} className={classes.element}>
@@ -88,11 +147,7 @@ function Filter({ active, to, children, icon: Icon, end, ...props }) {
);
}
- return (
- <button {...props} className={classes.element}>
- {content}
- </button>
- );
+ return <div className={classes.element}>{content}</div>;
}
export default Filter;