import React, { useCallback, useState } from "react"; import { connect, ConnectedProps } from "react-redux"; import { makeStyles } from "@material-ui/core/styles"; import Table from "@material-ui/core/Table"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import Button from "@material-ui/core/Button"; import TableContainer from "@material-ui/core/TableContainer"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; import TableFooter from "@material-ui/core/TableFooter"; import TablePagination from "@material-ui/core/TablePagination"; import Paper from "@material-ui/core/Paper"; import Box from "@material-ui/core/Box"; import Checkbox from "@material-ui/core/Checkbox"; import Collapse from "@material-ui/core/Collapse"; import IconButton from "@material-ui/core/IconButton"; import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp"; import KeyboardArrowDownIcon from "@material-ui/icons/KeyboardArrowDown"; import Typography from "@material-ui/core/Typography"; import Alert from "@material-ui/lab/Alert"; import AlertTitle from "@material-ui/lab/AlertTitle"; import SyntaxHighlighter from "react-syntax-highlighter"; import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github"; import { batchDeleteRetryTasksAsync, batchRunRetryTasksAsync, batchKillRetryTasksAsync, deleteAllRetryTasksAsync, runAllRetryTasksAsync, killAllRetryTasksAsync, listRetryTasksAsync, deleteRetryTaskAsync, runRetryTaskAsync, killRetryTaskAsync, } from "../actions/tasksActions"; import { AppState } from "../store"; import TablePaginationActions, { defaultPageSize, rowsPerPageOptions, } from "./TablePaginationActions"; import TableActions from "./TableActions"; import { durationBefore, uuidPrefix } from "../utils"; import { usePolling } from "../hooks"; import { RetryTaskExtended } from "../reducers/tasksReducer"; const useStyles = makeStyles({ table: { minWidth: 650, }, }); function mapStateToProps(state: AppState) { return { loading: state.tasks.retryTasks.loading, tasks: state.tasks.retryTasks.data, batchActionPending: state.tasks.retryTasks.batchActionPending, allActionPending: state.tasks.retryTasks.allActionPending, pollInterval: state.settings.pollInterval, }; } const mapDispatchToProps = { batchDeleteRetryTasksAsync, batchRunRetryTasksAsync, batchKillRetryTasksAsync, deleteAllRetryTasksAsync, runAllRetryTasksAsync, killAllRetryTasksAsync, listRetryTasksAsync, deleteRetryTaskAsync, runRetryTaskAsync, killRetryTaskAsync, }; const connector = connect(mapStateToProps, mapDispatchToProps); type ReduxProps = ConnectedProps; interface Props { queue: string; // name of the queue. totalTaskCount: number; // totoal number of scheduled tasks. } function RetryTasksTable(props: Props & ReduxProps) { const { pollInterval, listRetryTasksAsync, queue } = props; const classes = useStyles(); const [page, setPage] = useState(0); const [pageSize, setPageSize] = useState(defaultPageSize); const [selectedKeys, setSelectedKeys] = useState([]); const handleChangePage = ( event: React.MouseEvent | null, newPage: number ) => { setPage(newPage); }; const handleChangeRowsPerPage = ( event: React.ChangeEvent ) => { setPageSize(parseInt(event.target.value, 10)); setPage(0); }; const handleSelectAllClick = (event: React.ChangeEvent) => { if (event.target.checked) { const newSelected = props.tasks.map((t) => t.key); setSelectedKeys(newSelected); } else { setSelectedKeys([]); } }; const handleRunAllClick = () => { props.runAllRetryTasksAsync(queue); }; const handleDeleteAllClick = () => { props.deleteAllRetryTasksAsync(queue); }; const handleKillAllClick = () => { props.killAllRetryTasksAsync(queue); }; const handleBatchRunClick = () => { props .batchRunRetryTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; const handleBatchDeleteClick = () => { props .batchDeleteRetryTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; const handleBatchKillClick = () => { props .batchKillRetryTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; const fetchData = useCallback(() => { const pageOpts = { page: page + 1, size: pageSize }; listRetryTasksAsync(queue, pageOpts); }, [page, pageSize, queue, listRetryTasksAsync]); usePolling(fetchData, pollInterval); if (props.tasks.length === 0) { return ( Info No retry tasks at this time. ); } const columns = [ { label: "" }, { label: "ID" }, { label: "Type" }, { label: "Retry In" }, { label: "Last Error" }, { label: "Retried" }, { label: "Max Retry" }, { label: "Actions" }, ]; const rowCount = props.tasks.length; const numSelected = selectedKeys.length; return (
0} onRunAllClick={handleRunAllClick} onDeleteAllClick={handleDeleteAllClick} onKillAllClick={handleKillAllClick} onBatchRunClick={handleBatchRunClick} onBatchDeleteClick={handleBatchDeleteClick} onBatchKillClick={handleBatchKillClick} /> 0 && numSelected < rowCount} checked={rowCount > 0 && numSelected === rowCount} onChange={handleSelectAllClick} inputProps={{ "aria-label": "select all tasks shown in the table", }} /> {columns.map((col) => ( {col.label} ))} {props.tasks.map((task) => ( { if (checked) { setSelectedKeys(selectedKeys.concat(task.key)); } else { setSelectedKeys( selectedKeys.filter((key) => key !== task.key) ); } }} onRunClick={() => { props.runRetryTaskAsync(task.queue, task.key); }} onDeleteClick={() => { props.deleteRetryTaskAsync(task.queue, task.key); }} onKillClick={() => { props.killRetryTaskAsync(task.queue, task.key); }} /> ))}
); } const useRowStyles = makeStyles({ root: { "& > *": { borderBottom: "unset", }, }, }); interface RowProps { task: RetryTaskExtended; isSelected: boolean; onSelectChange: (checked: boolean) => void; onDeleteClick: () => void; onRunClick: () => void; onKillClick: () => void; allActionPending: boolean; } function Row(props: RowProps) { const { task } = props; const [open, setOpen] = React.useState(false); const classes = useRowStyles(); return ( ) => props.onSelectChange(event.target.checked) } checked={props.isSelected} /> setOpen(!open)} > {open ? : } {uuidPrefix(task.id)} {task.type} {durationBefore(task.next_process_at)} {task.error_message} {task.retried} {task.max_retry} Payload {JSON.stringify(task.payload, null, 2)} ); } export default connector(RetryTasksTable);