Add SplitButton component

This commit is contained in:
Ken Hibino 2020-12-27 09:47:15 -08:00
parent 26ebeea582
commit 3587acaa33
2 changed files with 191 additions and 49 deletions

View File

@ -0,0 +1,120 @@
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import ButtonGroup from "@material-ui/core/ButtonGroup";
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import Grow from "@material-ui/core/Grow";
import Paper from "@material-ui/core/Paper";
import Popper from "@material-ui/core/Popper";
import MenuItem from "@material-ui/core/MenuItem";
import MenuList from "@material-ui/core/MenuList";
interface Option {
label: string;
key: string;
}
interface Props {
options: Option[];
initialSelectedKey: string;
onSelect: (key: string) => void;
}
const useStyles = makeStyles({
popper: {
zIndex: 2,
},
});
export default function SplitButton(props: Props) {
const classes = useStyles();
const [open, setOpen] = React.useState<boolean>(false);
const anchorRef = React.useRef<HTMLDivElement>(null);
const [selectedKey, setSelectedKey] = React.useState<string>(
props.initialSelectedKey
);
const handleMenuItemClick = (
event: React.MouseEvent<HTMLLIElement, MouseEvent>,
key: string
) => {
setSelectedKey(key);
setOpen(false);
props.onSelect(key);
};
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event: React.MouseEvent<Document, MouseEvent>) => {
if (
anchorRef.current &&
anchorRef.current.contains(event.target as HTMLElement)
) {
return;
}
setOpen(false);
};
const selectedOpt = props.options.find((opt) => opt.key === selectedKey);
return (
<>
<ButtonGroup
variant="contained"
ref={anchorRef}
aria-label="split button"
size="small"
disableElevation
>
<Button>{selectedOpt ? selectedOpt.label : "Select Option"}</Button>
<Button
size="small"
aria-controls={open ? "split-button-menu" : undefined}
aria-expanded={open ? "true" : undefined}
aria-label="select option"
aria-haspopup="menu"
onClick={handleToggle}
>
<ArrowDropDownIcon />
</Button>
</ButtonGroup>
<Popper
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
className={classes.popper}
>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin:
placement === "bottom" ? "center top" : "center bottom",
}}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList id="split-button-menu">
{props.options.map((opt) => (
<MenuItem
key={opt.key}
selected={opt.key === selectedKey}
onClick={(event) => handleMenuItemClick(event, opt.key)}
>
{opt.label}
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</>
);
}

View File

@ -17,6 +17,7 @@ import QueueSizeChart from "../components/QueueSizeChart";
import ProcessedTasksChart from "../components/ProcessedTasksChart";
import QueuesOverviewTable from "../components/QueuesOverviewTable";
import Tooltip from "../components/Tooltip";
import SplitButton from "../components/SplitButton";
import { getCurrentUTCDate } from "../utils";
import { usePolling } from "../hooks";
@ -34,8 +35,13 @@ const useStyles = makeStyles((theme) => ({
chartHeader: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
marginBottom: theme.spacing(2),
},
chartHeaderTitle: {
display: "flex",
alignItems: "center",
},
chartContainer: {
width: "100%",
height: "300px",
@ -93,38 +99,40 @@ function DashboardView(props: Props) {
<Grid item xs={6}>
<Paper className={classes.paper} variant="outlined">
<div className={classes.chartHeader}>
<Typography variant="h6">Queue Size</Typography>
<Tooltip
title={
<div>
<div className={classes.tooltipSection}>
Total number of tasks in the queue
</div>
<div className={classes.tooltipSection}>
<strong>Active</strong>: number of tasks currently being
processed
</div>
<div className={classes.tooltipSection}>
<strong>Pending</strong>: number of tasks ready to be
processed
</div>
<div className={classes.tooltipSection}>
<strong>Scheduled</strong>: number of tasks scheduled to
be processed in the future
</div>
<div className={classes.tooltipSection}>
<strong>Retry</strong>: number of tasks scheduled to be
retried in the future
</div>
<div className={classes.chartHeaderTitle}>
<Typography variant="h6">Queue Size</Typography>
<Tooltip
title={
<div>
<strong>Dead</strong>: number of tasks exhausted their
retries
<div className={classes.tooltipSection}>
Total number of tasks in the queue
</div>
<div className={classes.tooltipSection}>
<strong>Active</strong>: number of tasks currently being
processed
</div>
<div className={classes.tooltipSection}>
<strong>Pending</strong>: number of tasks ready to be
processed
</div>
<div className={classes.tooltipSection}>
<strong>Scheduled</strong>: number of tasks scheduled to
be processed in the future
</div>
<div className={classes.tooltipSection}>
<strong>Retry</strong>: number of tasks scheduled to be
retried in the future
</div>
<div>
<strong>Dead</strong>: number of tasks exhausted their
retries
</div>
</div>
</div>
}
>
<InfoIcon fontSize="small" className={classes.infoIcon} />
</Tooltip>
}
>
<InfoIcon fontSize="small" className={classes.infoIcon} />
</Tooltip>
</div>
</div>
<div className={classes.chartContainer}>
<QueueSizeChart data={queues} />
@ -135,27 +143,41 @@ function DashboardView(props: Props) {
<Grid item xs={6}>
<Paper className={classes.paper} variant="outlined">
<div className={classes.chartHeader}>
<Typography variant="h6">Tasks Processed</Typography>
<Tooltip
title={
<div>
<div className={classes.tooltipSection}>
Total number of tasks processed today (
{getCurrentUTCDate()} UTC)
</div>
<div className={classes.tooltipSection}>
<strong>Succeeded</strong>: number of tasks successfully
processed from the queue
</div>
<div className={classes.chartHeaderTitle}>
<Typography variant="h6">Tasks Processed</Typography>
<Tooltip
title={
<div>
<strong>Failed</strong>: number of tasks failed to be
processed from the queue
<div className={classes.tooltipSection}>
Total number of tasks processed today (
{getCurrentUTCDate()} UTC)
</div>
<div className={classes.tooltipSection}>
<strong>Succeeded</strong>: number of tasks successfully
processed from the queue
</div>
<div>
<strong>Failed</strong>: number of tasks failed to be
processed from the queue
</div>
</div>
</div>
}
>
<InfoIcon fontSize="small" className={classes.infoIcon} />
</Tooltip>
}
>
<InfoIcon fontSize="small" className={classes.infoIcon} />
</Tooltip>
</div>
<div>
<SplitButton
options={[
{ label: "Today", key: "today" },
{ label: "Last 7d", key: "last-7d" },
{ label: "Last 30d", key: "last-30d" },
{ label: "Last 90d", key: "last-90d" },
]}
initialSelectedKey="today"
onSelect={(key) => console.log("option selected:", key)}
/>
</div>
</div>
<div className={classes.chartContainer}>
<ProcessedTasksChart data={processedStats} />