mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-01-19 11:15:53 +08:00
Extract TableActions component
This commit is contained in:
parent
95bb6051d0
commit
68738ec962
@ -5,7 +5,6 @@ import Table from "@material-ui/core/Table";
|
|||||||
import TableBody from "@material-ui/core/TableBody";
|
import TableBody from "@material-ui/core/TableBody";
|
||||||
import TableCell from "@material-ui/core/TableCell";
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import ButtonGroup from "@material-ui/core/ButtonGroup";
|
|
||||||
import Checkbox from "@material-ui/core/Checkbox";
|
import Checkbox from "@material-ui/core/Checkbox";
|
||||||
import TableContainer from "@material-ui/core/TableContainer";
|
import TableContainer from "@material-ui/core/TableContainer";
|
||||||
import TableHead from "@material-ui/core/TableHead";
|
import TableHead from "@material-ui/core/TableHead";
|
||||||
@ -14,14 +13,11 @@ import Paper from "@material-ui/core/Paper";
|
|||||||
import Box from "@material-ui/core/Box";
|
import Box from "@material-ui/core/Box";
|
||||||
import Collapse from "@material-ui/core/Collapse";
|
import Collapse from "@material-ui/core/Collapse";
|
||||||
import IconButton from "@material-ui/core/IconButton";
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
import Menu from "@material-ui/core/Menu";
|
|
||||||
import MenuItem from "@material-ui/core/MenuItem";
|
|
||||||
import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
|
import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
|
||||||
import KeyboardArrowDownIcon from "@material-ui/icons/KeyboardArrowDown";
|
import KeyboardArrowDownIcon from "@material-ui/icons/KeyboardArrowDown";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
import TableFooter from "@material-ui/core/TableFooter";
|
import TableFooter from "@material-ui/core/TableFooter";
|
||||||
import TablePagination from "@material-ui/core/TablePagination";
|
import TablePagination from "@material-ui/core/TablePagination";
|
||||||
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
|
||||||
import Alert from "@material-ui/lab/Alert";
|
import Alert from "@material-ui/lab/Alert";
|
||||||
import AlertTitle from "@material-ui/lab/AlertTitle";
|
import AlertTitle from "@material-ui/lab/AlertTitle";
|
||||||
import SyntaxHighlighter from "react-syntax-highlighter";
|
import SyntaxHighlighter from "react-syntax-highlighter";
|
||||||
@ -40,6 +36,7 @@ import TablePaginationActions, {
|
|||||||
defaultPageSize,
|
defaultPageSize,
|
||||||
rowsPerPageOptions,
|
rowsPerPageOptions,
|
||||||
} from "./TablePaginationActions";
|
} from "./TablePaginationActions";
|
||||||
|
import TableActions from "./TableActions";
|
||||||
import { timeAgo } from "../timeutil";
|
import { timeAgo } from "../timeutil";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { DeadTaskExtended } from "../reducers/tasksReducer";
|
import { DeadTaskExtended } from "../reducers/tasksReducer";
|
||||||
@ -48,12 +45,6 @@ const useStyles = makeStyles({
|
|||||||
table: {
|
table: {
|
||||||
minWidth: 650,
|
minWidth: 650,
|
||||||
},
|
},
|
||||||
actionsContainer: {
|
|
||||||
padding: "4px",
|
|
||||||
},
|
|
||||||
moreIcon: {
|
|
||||||
marginRight: "8px",
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const useRowStyles = makeStyles({
|
const useRowStyles = makeStyles({
|
||||||
@ -99,7 +90,6 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [pageSize, setPageSize] = useState(defaultPageSize);
|
const [pageSize, setPageSize] = useState(defaultPageSize);
|
||||||
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
|
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
|
||||||
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
|
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -124,20 +114,24 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
||||||
setMenuAnchor(event.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMenuClose = () => setMenuAnchor(null);
|
|
||||||
|
|
||||||
const handleRunAllClick = () => {
|
const handleRunAllClick = () => {
|
||||||
props.runAllDeadTasksAsync(queue);
|
props.runAllDeadTasksAsync(queue);
|
||||||
setMenuAnchor(null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDeleteAllClick = () => {
|
const handleDeleteAllClick = () => {
|
||||||
props.deleteAllDeadTasksAsync(queue);
|
props.deleteAllDeadTasksAsync(queue);
|
||||||
setMenuAnchor(null);
|
};
|
||||||
|
|
||||||
|
const handleBatchRunClick = () => {
|
||||||
|
props
|
||||||
|
.batchDeleteDeadTasksAsync(queue, selectedKeys)
|
||||||
|
.then(() => setSelectedKeys([]));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBatchDeleteClick = () => {
|
||||||
|
props
|
||||||
|
.batchRunDeadTasksAsync(queue, selectedKeys)
|
||||||
|
.then(() => setSelectedKeys([]));
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchData = useCallback(() => {
|
const fetchData = useCallback(() => {
|
||||||
@ -169,64 +163,15 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
const numSelected = selectedKeys.length;
|
const numSelected = selectedKeys.length;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={classes.actionsContainer}>
|
<TableActions
|
||||||
<IconButton
|
allActionPending={props.allActionPending}
|
||||||
aria-label="actions"
|
batchActionPending={props.batchActionPending}
|
||||||
className={classes.moreIcon}
|
showBatchActions={numSelected > 0}
|
||||||
onClick={handleMenuClick}
|
onRunAllClick={handleRunAllClick}
|
||||||
>
|
onDeleteAllClick={handleDeleteAllClick}
|
||||||
<MoreHorizIcon />
|
onBatchRunClick={handleBatchRunClick}
|
||||||
</IconButton>
|
onBatchDeleteClick={handleBatchDeleteClick}
|
||||||
<Menu
|
/>
|
||||||
id="action-menu"
|
|
||||||
keepMounted
|
|
||||||
anchorEl={menuAnchor}
|
|
||||||
open={Boolean(menuAnchor)}
|
|
||||||
onClose={handleMenuClose}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
onClick={handleRunAllClick}
|
|
||||||
disabled={props.allActionPending}
|
|
||||||
>
|
|
||||||
Run All
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
onClick={handleDeleteAllClick}
|
|
||||||
disabled={props.allActionPending}
|
|
||||||
>
|
|
||||||
Delete All
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
{numSelected > 0 && (
|
|
||||||
<ButtonGroup
|
|
||||||
variant="text"
|
|
||||||
color="primary"
|
|
||||||
aria-label="text primary button group"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
disabled={props.batchActionPending}
|
|
||||||
onClick={() =>
|
|
||||||
props
|
|
||||||
.batchRunDeadTasksAsync(queue, selectedKeys)
|
|
||||||
.then(() => setSelectedKeys([]))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Run
|
|
||||||
</Button>
|
|
||||||
<Button>Kill</Button>
|
|
||||||
<Button
|
|
||||||
disabled={props.batchActionPending}
|
|
||||||
onClick={() =>
|
|
||||||
props
|
|
||||||
.batchDeleteDeadTasksAsync(queue, selectedKeys)
|
|
||||||
.then(() => setSelectedKeys([]))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
<Table
|
<Table
|
||||||
stickyHeader={true}
|
stickyHeader={true}
|
||||||
|
@ -31,6 +31,7 @@ import TablePaginationActions, {
|
|||||||
defaultPageSize,
|
defaultPageSize,
|
||||||
rowsPerPageOptions,
|
rowsPerPageOptions,
|
||||||
} from "./TablePaginationActions";
|
} from "./TablePaginationActions";
|
||||||
|
import TableActions from "./TableActions";
|
||||||
import { durationBefore } from "../timeutil";
|
import { durationBefore } from "../timeutil";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { RetryTaskExtended } from "../reducers/tasksReducer";
|
import { RetryTaskExtended } from "../reducers/tasksReducer";
|
||||||
@ -45,6 +46,8 @@ function mapStateToProps(state: AppState) {
|
|||||||
return {
|
return {
|
||||||
loading: state.tasks.retryTasks.loading,
|
loading: state.tasks.retryTasks.loading,
|
||||||
tasks: state.tasks.retryTasks.data,
|
tasks: state.tasks.retryTasks.data,
|
||||||
|
batchActionPending: state.tasks.retryTasks.batchActionPending,
|
||||||
|
allActionPending: state.tasks.retryTasks.allActionPending,
|
||||||
pollInterval: state.settings.pollInterval,
|
pollInterval: state.settings.pollInterval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -120,71 +123,82 @@ function RetryTasksTable(props: Props & ReduxProps) {
|
|||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
const numSelected = selectedKeys.length;
|
const numSelected = selectedKeys.length;
|
||||||
return (
|
return (
|
||||||
<TableContainer component={Paper}>
|
<div>
|
||||||
<Table
|
<TableActions
|
||||||
stickyHeader={true}
|
allActionPending={props.allActionPending}
|
||||||
className={classes.table}
|
batchActionPending={props.batchActionPending}
|
||||||
aria-label="retry tasks table"
|
showBatchActions={numSelected > 0}
|
||||||
size="small"
|
onRunAllClick={() => console.log("TODO")}
|
||||||
>
|
onDeleteAllClick={() => console.log("TODO")}
|
||||||
<TableHead>
|
onBatchRunClick={() => console.log("TODO")}
|
||||||
<TableRow>
|
onBatchDeleteClick={() => console.log("TODO")}
|
||||||
<TableCell padding="checkbox">
|
/>
|
||||||
<Checkbox
|
<TableContainer component={Paper}>
|
||||||
indeterminate={numSelected > 0 && numSelected < rowCount}
|
<Table
|
||||||
checked={rowCount > 0 && numSelected === rowCount}
|
stickyHeader={true}
|
||||||
onChange={handleSelectAllClick}
|
className={classes.table}
|
||||||
inputProps={{
|
aria-label="retry tasks table"
|
||||||
"aria-label": "select all tasks shown in the table",
|
size="small"
|
||||||
|
>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell padding="checkbox">
|
||||||
|
<Checkbox
|
||||||
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
||||||
|
checked={rowCount > 0 && numSelected === rowCount}
|
||||||
|
onChange={handleSelectAllClick}
|
||||||
|
inputProps={{
|
||||||
|
"aria-label": "select all tasks shown in the table",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
{columns.map((col) => (
|
||||||
|
<TableCell key={col.label}>{col.label}</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{props.tasks.map((task) => (
|
||||||
|
<Row
|
||||||
|
key={task.id}
|
||||||
|
task={task}
|
||||||
|
isSelected={selectedKeys.includes(task.key)}
|
||||||
|
onSelectChange={(checked: boolean) => {
|
||||||
|
if (checked) {
|
||||||
|
setSelectedKeys(selectedKeys.concat(task.key));
|
||||||
|
} else {
|
||||||
|
setSelectedKeys(
|
||||||
|
selectedKeys.filter((key) => key !== task.key)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
props.deleteRetryTaskAsync(task.queue, task.key);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableBody>
|
||||||
</TableHead>
|
<TableFooter>
|
||||||
<TableBody>
|
<TableRow>
|
||||||
{props.tasks.map((task) => (
|
<TablePagination
|
||||||
<Row
|
rowsPerPageOptions={rowsPerPageOptions}
|
||||||
key={task.id}
|
colSpan={columns.length + 1}
|
||||||
task={task}
|
count={props.totalTaskCount}
|
||||||
isSelected={selectedKeys.includes(task.key)}
|
rowsPerPage={pageSize}
|
||||||
onSelectChange={(checked: boolean) => {
|
page={page}
|
||||||
if (checked) {
|
SelectProps={{
|
||||||
setSelectedKeys(selectedKeys.concat(task.key));
|
inputProps: { "aria-label": "rows per page" },
|
||||||
} else {
|
native: true,
|
||||||
setSelectedKeys(
|
}}
|
||||||
selectedKeys.filter((key) => key !== task.key)
|
onChangePage={handleChangePage}
|
||||||
);
|
onChangeRowsPerPage={handleChangeRowsPerPage}
|
||||||
}
|
ActionsComponent={TablePaginationActions}
|
||||||
}}
|
/>
|
||||||
onDeleteClick={() => {
|
</TableRow>
|
||||||
props.deleteRetryTaskAsync(task.queue, task.key);
|
</TableFooter>
|
||||||
}}
|
</Table>
|
||||||
/>
|
</TableContainer>
|
||||||
))}
|
</div>
|
||||||
</TableBody>
|
|
||||||
<TableFooter>
|
|
||||||
<TableRow>
|
|
||||||
<TablePagination
|
|
||||||
rowsPerPageOptions={rowsPerPageOptions}
|
|
||||||
colSpan={columns.length + 1}
|
|
||||||
count={props.totalTaskCount}
|
|
||||||
rowsPerPage={pageSize}
|
|
||||||
page={page}
|
|
||||||
SelectProps={{
|
|
||||||
inputProps: { "aria-label": "rows per page" },
|
|
||||||
native: true,
|
|
||||||
}}
|
|
||||||
onChangePage={handleChangePage}
|
|
||||||
onChangeRowsPerPage={handleChangeRowsPerPage}
|
|
||||||
ActionsComponent={TablePaginationActions}
|
|
||||||
/>
|
|
||||||
</TableRow>
|
|
||||||
</TableFooter>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import TablePaginationActions, {
|
|||||||
defaultPageSize,
|
defaultPageSize,
|
||||||
rowsPerPageOptions,
|
rowsPerPageOptions,
|
||||||
} from "./TablePaginationActions";
|
} from "./TablePaginationActions";
|
||||||
|
import TableActions from "./TableActions";
|
||||||
import { durationBefore } from "../timeutil";
|
import { durationBefore } from "../timeutil";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { ScheduledTaskExtended } from "../reducers/tasksReducer";
|
import { ScheduledTaskExtended } from "../reducers/tasksReducer";
|
||||||
@ -45,6 +46,8 @@ function mapStateToProps(state: AppState) {
|
|||||||
return {
|
return {
|
||||||
loading: state.tasks.scheduledTasks.loading,
|
loading: state.tasks.scheduledTasks.loading,
|
||||||
tasks: state.tasks.scheduledTasks.data,
|
tasks: state.tasks.scheduledTasks.data,
|
||||||
|
batchActionPending: state.tasks.scheduledTasks.batchActionPending,
|
||||||
|
allActionPending: state.tasks.scheduledTasks.allActionPending,
|
||||||
pollInterval: state.settings.pollInterval,
|
pollInterval: state.settings.pollInterval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -120,71 +123,82 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
|
|||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
const numSelected = selectedKeys.length;
|
const numSelected = selectedKeys.length;
|
||||||
return (
|
return (
|
||||||
<TableContainer component={Paper}>
|
<div>
|
||||||
<Table
|
<TableActions
|
||||||
stickyHeader={true}
|
allActionPending={props.allActionPending}
|
||||||
className={classes.table}
|
batchActionPending={props.batchActionPending}
|
||||||
aria-label="scheduled tasks table"
|
showBatchActions={numSelected > 0}
|
||||||
size="small"
|
onRunAllClick={() => console.log("TODO")}
|
||||||
>
|
onDeleteAllClick={() => console.log("TODO")}
|
||||||
<TableHead>
|
onBatchRunClick={() => console.log("TODO")}
|
||||||
<TableRow>
|
onBatchDeleteClick={() => console.log("TODO")}
|
||||||
<TableCell padding="checkbox">
|
/>
|
||||||
<Checkbox
|
<TableContainer component={Paper}>
|
||||||
indeterminate={numSelected > 0 && numSelected < rowCount}
|
<Table
|
||||||
checked={rowCount > 0 && numSelected === rowCount}
|
stickyHeader={true}
|
||||||
onChange={handleSelectAllClick}
|
className={classes.table}
|
||||||
inputProps={{
|
aria-label="scheduled tasks table"
|
||||||
"aria-label": "select all tasks shown in the table",
|
size="small"
|
||||||
|
>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell padding="checkbox">
|
||||||
|
<Checkbox
|
||||||
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
||||||
|
checked={rowCount > 0 && numSelected === rowCount}
|
||||||
|
onChange={handleSelectAllClick}
|
||||||
|
inputProps={{
|
||||||
|
"aria-label": "select all tasks shown in the table",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
{columns.map((col) => (
|
||||||
|
<TableCell key={col.label}>{col.label}</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{props.tasks.map((task) => (
|
||||||
|
<Row
|
||||||
|
key={task.id}
|
||||||
|
task={task}
|
||||||
|
isSelected={selectedKeys.includes(task.key)}
|
||||||
|
onSelectChange={(checked: boolean) => {
|
||||||
|
if (checked) {
|
||||||
|
setSelectedKeys(selectedKeys.concat(task.key));
|
||||||
|
} else {
|
||||||
|
setSelectedKeys(
|
||||||
|
selectedKeys.filter((key) => key !== task.key)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onDeleteClick={() => {
|
||||||
|
props.deleteScheduledTaskAsync(queue, task.key);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
|
||||||
{columns.map((col) => (
|
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableBody>
|
||||||
</TableHead>
|
<TableFooter>
|
||||||
<TableBody>
|
<TableRow>
|
||||||
{props.tasks.map((task) => (
|
<TablePagination
|
||||||
<Row
|
rowsPerPageOptions={rowsPerPageOptions}
|
||||||
key={task.id}
|
colSpan={columns.length + 1}
|
||||||
task={task}
|
count={props.totalTaskCount}
|
||||||
isSelected={selectedKeys.includes(task.key)}
|
rowsPerPage={pageSize}
|
||||||
onSelectChange={(checked: boolean) => {
|
page={page}
|
||||||
if (checked) {
|
SelectProps={{
|
||||||
setSelectedKeys(selectedKeys.concat(task.key));
|
inputProps: { "aria-label": "rows per page" },
|
||||||
} else {
|
native: true,
|
||||||
setSelectedKeys(
|
}}
|
||||||
selectedKeys.filter((key) => key !== task.key)
|
onChangePage={handleChangePage}
|
||||||
);
|
onChangeRowsPerPage={handleChangeRowsPerPage}
|
||||||
}
|
ActionsComponent={TablePaginationActions}
|
||||||
}}
|
/>
|
||||||
onDeleteClick={() => {
|
</TableRow>
|
||||||
props.deleteScheduledTaskAsync(queue, task.key);
|
</TableFooter>
|
||||||
}}
|
</Table>
|
||||||
/>
|
</TableContainer>
|
||||||
))}
|
</div>
|
||||||
</TableBody>
|
|
||||||
<TableFooter>
|
|
||||||
<TableRow>
|
|
||||||
<TablePagination
|
|
||||||
rowsPerPageOptions={rowsPerPageOptions}
|
|
||||||
colSpan={columns.length + 1}
|
|
||||||
count={props.totalTaskCount}
|
|
||||||
rowsPerPage={pageSize}
|
|
||||||
page={page}
|
|
||||||
SelectProps={{
|
|
||||||
inputProps: { "aria-label": "rows per page" },
|
|
||||||
native: true,
|
|
||||||
}}
|
|
||||||
onChangePage={handleChangePage}
|
|
||||||
onChangeRowsPerPage={handleChangeRowsPerPage}
|
|
||||||
ActionsComponent={TablePaginationActions}
|
|
||||||
/>
|
|
||||||
</TableRow>
|
|
||||||
</TableFooter>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
97
ui/src/components/TableActions.tsx
Normal file
97
ui/src/components/TableActions.tsx
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
|
import ButtonGroup from "@material-ui/core/ButtonGroup";
|
||||||
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import Menu from "@material-ui/core/Menu";
|
||||||
|
import MenuItem from "@material-ui/core/MenuItem";
|
||||||
|
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
actionsContainer: {
|
||||||
|
padding: "4px",
|
||||||
|
},
|
||||||
|
moreIcon: {
|
||||||
|
marginRight: "8px",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
allActionPending: boolean;
|
||||||
|
onRunAllClick: () => void;
|
||||||
|
onDeleteAllClick: () => void;
|
||||||
|
showBatchActions: boolean;
|
||||||
|
batchActionPending: boolean;
|
||||||
|
onBatchRunClick: () => void;
|
||||||
|
onBatchDeleteClick: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function TableActions(props: Props) {
|
||||||
|
const classes = useStyles();
|
||||||
|
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
|
||||||
|
|
||||||
|
const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
setMenuAnchor(event.currentTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeMenu = () => setMenuAnchor(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.actionsContainer}>
|
||||||
|
<IconButton
|
||||||
|
aria-label="actions"
|
||||||
|
className={classes.moreIcon}
|
||||||
|
onClick={handleMenuClick}
|
||||||
|
>
|
||||||
|
<MoreHorizIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id="action-menu"
|
||||||
|
keepMounted
|
||||||
|
anchorEl={menuAnchor}
|
||||||
|
open={Boolean(menuAnchor)}
|
||||||
|
onClose={closeMenu}
|
||||||
|
>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
props.onRunAllClick();
|
||||||
|
closeMenu();
|
||||||
|
}}
|
||||||
|
disabled={props.allActionPending}
|
||||||
|
>
|
||||||
|
Run All
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
props.onDeleteAllClick();
|
||||||
|
closeMenu();
|
||||||
|
}}
|
||||||
|
disabled={props.allActionPending}
|
||||||
|
>
|
||||||
|
Delete All
|
||||||
|
</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
{props.showBatchActions && (
|
||||||
|
<ButtonGroup
|
||||||
|
variant="text"
|
||||||
|
color="primary"
|
||||||
|
aria-label="text primary button group"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
disabled={props.batchActionPending}
|
||||||
|
onClick={props.onBatchRunClick}
|
||||||
|
>
|
||||||
|
Run
|
||||||
|
</Button>
|
||||||
|
<Button>Kill</Button>
|
||||||
|
<Button
|
||||||
|
disabled={props.batchActionPending}
|
||||||
|
onClick={props.onBatchDeleteClick}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -92,11 +92,15 @@ interface TasksState {
|
|||||||
};
|
};
|
||||||
scheduledTasks: {
|
scheduledTasks: {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
batchActionPending: boolean;
|
||||||
|
allActionPending: boolean;
|
||||||
error: string;
|
error: string;
|
||||||
data: ScheduledTaskExtended[];
|
data: ScheduledTaskExtended[];
|
||||||
};
|
};
|
||||||
retryTasks: {
|
retryTasks: {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
batchActionPending: boolean;
|
||||||
|
allActionPending: boolean;
|
||||||
error: string;
|
error: string;
|
||||||
data: RetryTaskExtended[];
|
data: RetryTaskExtended[];
|
||||||
};
|
};
|
||||||
@ -122,11 +126,15 @@ const initialState: TasksState = {
|
|||||||
},
|
},
|
||||||
scheduledTasks: {
|
scheduledTasks: {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
batchActionPending: false,
|
||||||
|
allActionPending: false,
|
||||||
error: "",
|
error: "",
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
retryTasks: {
|
retryTasks: {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
batchActionPending: false,
|
||||||
|
allActionPending: false,
|
||||||
error: "",
|
error: "",
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
@ -222,6 +230,7 @@ function tasksReducer(
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
scheduledTasks: {
|
scheduledTasks: {
|
||||||
|
...state.scheduledTasks,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: "",
|
error: "",
|
||||||
data: action.payload.tasks.map((task) => ({
|
data: action.payload.tasks.map((task) => ({
|
||||||
@ -255,6 +264,7 @@ function tasksReducer(
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
retryTasks: {
|
retryTasks: {
|
||||||
|
...state.retryTasks,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: "",
|
error: "",
|
||||||
data: action.payload.tasks.map((task) => ({
|
data: action.payload.tasks.map((task) => ({
|
||||||
|
Loading…
Reference in New Issue
Block a user