mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-04-20 15:50:12 +08:00
Add delete and archive action buttons to PendingTasksTable
This commit is contained in:
parent
15bd0a142e
commit
caae17a230
@ -1,4 +1,5 @@
|
|||||||
import React, { useCallback, useState } from "react";
|
import React, { useCallback, useState } from "react";
|
||||||
|
import clsx from "clsx";
|
||||||
import { connect, ConnectedProps } from "react-redux";
|
import { connect, ConnectedProps } from "react-redux";
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import Table from "@material-ui/core/Table";
|
import Table from "@material-ui/core/Table";
|
||||||
@ -12,6 +13,7 @@ import TableRow from "@material-ui/core/TableRow";
|
|||||||
import Tooltip from "@material-ui/core/Tooltip";
|
import Tooltip from "@material-ui/core/Tooltip";
|
||||||
import Paper from "@material-ui/core/Paper";
|
import Paper from "@material-ui/core/Paper";
|
||||||
import Box from "@material-ui/core/Box";
|
import Box from "@material-ui/core/Box";
|
||||||
|
import Checkbox from "@material-ui/core/Checkbox";
|
||||||
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 KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
|
import KeyboardArrowUpIcon from "@material-ui/icons/KeyboardArrowUp";
|
||||||
@ -19,17 +21,29 @@ 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 DeleteIcon from "@material-ui/icons/Delete";
|
||||||
|
import ArchiveIcon from "@material-ui/icons/Archive";
|
||||||
|
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
import SyntaxHighlighter from "./SyntaxHighlighter";
|
import SyntaxHighlighter from "./SyntaxHighlighter";
|
||||||
import TablePaginationActions, {
|
import TablePaginationActions, {
|
||||||
defaultPageSize,
|
defaultPageSize,
|
||||||
rowsPerPageOptions,
|
rowsPerPageOptions,
|
||||||
} from "./TablePaginationActions";
|
} from "./TablePaginationActions";
|
||||||
import { listPendingTasksAsync } from "../actions/tasksActions";
|
import TableActions from "./TableActions";
|
||||||
|
import {
|
||||||
|
listPendingTasksAsync,
|
||||||
|
deletePendingTaskAsync,
|
||||||
|
batchDeletePendingTasksAsync,
|
||||||
|
deleteAllPendingTasksAsync,
|
||||||
|
archivePendingTaskAsync,
|
||||||
|
batchArchivePendingTasksAsync,
|
||||||
|
archiveAllPendingTasksAsync,
|
||||||
|
} from "../actions/tasksActions";
|
||||||
import { AppState } from "../store";
|
import { AppState } from "../store";
|
||||||
import { PendingTask } from "../api";
|
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { uuidPrefix } from "../utils";
|
import { uuidPrefix } from "../utils";
|
||||||
import { TableColumn } from "../types/table";
|
import { TableColumn } from "../types/table";
|
||||||
|
import { PendingTaskExtended } from "../reducers/tasksReducer";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
table: {
|
table: {
|
||||||
@ -44,11 +58,21 @@ function mapStateToProps(state: AppState) {
|
|||||||
return {
|
return {
|
||||||
loading: state.tasks.pendingTasks.loading,
|
loading: state.tasks.pendingTasks.loading,
|
||||||
tasks: state.tasks.pendingTasks.data,
|
tasks: state.tasks.pendingTasks.data,
|
||||||
|
batchActionPending: state.tasks.pendingTasks.batchActionPending,
|
||||||
|
allActionPending: state.tasks.pendingTasks.allActionPending,
|
||||||
pollInterval: state.settings.pollInterval,
|
pollInterval: state.settings.pollInterval,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = { listPendingTasksAsync };
|
const mapDispatchToProps = {
|
||||||
|
listPendingTasksAsync,
|
||||||
|
deletePendingTaskAsync,
|
||||||
|
batchDeletePendingTasksAsync,
|
||||||
|
deleteAllPendingTasksAsync,
|
||||||
|
archivePendingTaskAsync,
|
||||||
|
batchArchivePendingTasksAsync,
|
||||||
|
archiveAllPendingTasksAsync,
|
||||||
|
};
|
||||||
|
|
||||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
|
||||||
@ -64,6 +88,8 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
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 [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -79,6 +105,35 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
setPage(0);
|
setPage(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
const newSelected = props.tasks.map((t) => t.key);
|
||||||
|
setSelectedKeys(newSelected);
|
||||||
|
} else {
|
||||||
|
setSelectedKeys([]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteAllClick = () => {
|
||||||
|
props.deleteAllPendingTasksAsync(queue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleArchiveAllClick = () => {
|
||||||
|
props.archiveAllPendingTasksAsync(queue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBatchDeleteClick = () => {
|
||||||
|
props
|
||||||
|
.batchDeletePendingTasksAsync(queue, selectedKeys)
|
||||||
|
.then(() => setSelectedKeys([]));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBatchArchiveClick = () => {
|
||||||
|
props
|
||||||
|
.batchArchivePendingTasksAsync(queue, selectedKeys)
|
||||||
|
.then(() => setSelectedKeys([]));
|
||||||
|
};
|
||||||
|
|
||||||
const fetchData = useCallback(() => {
|
const fetchData = useCallback(() => {
|
||||||
const pageOpts = { page: page + 1, size: pageSize };
|
const pageOpts = { page: page + 1, size: pageSize };
|
||||||
listPendingTasksAsync(queue, pageOpts);
|
listPendingTasksAsync(queue, pageOpts);
|
||||||
@ -99,9 +154,42 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
{ key: "icon", label: "", align: "left" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ key: "id", label: "ID", align: "left" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ key: "type", label: "Type", align: "left" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
|
{ key: "actions", label: "Actions", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const rowCount = props.tasks.length;
|
||||||
|
const numSelected = selectedKeys.length;
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
|
<TableActions
|
||||||
|
showIconButtons={numSelected > 0}
|
||||||
|
iconButtonActions={[
|
||||||
|
{
|
||||||
|
tooltip: "Delete",
|
||||||
|
icon: <DeleteIcon />,
|
||||||
|
onClick: handleBatchDeleteClick,
|
||||||
|
disabled: props.batchActionPending,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tooltip: "Archive",
|
||||||
|
icon: <ArchiveIcon />,
|
||||||
|
onClick: handleBatchArchiveClick,
|
||||||
|
disabled: props.batchActionPending,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
menuItemActions={[
|
||||||
|
{
|
||||||
|
label: "Delete All",
|
||||||
|
onClick: handleDeleteAllClick,
|
||||||
|
disabled: props.allActionPending,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Archive All",
|
||||||
|
onClick: handleArchiveAllClick,
|
||||||
|
disabled: props.allActionPending,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<TableContainer component={Paper}>
|
<TableContainer component={Paper}>
|
||||||
<Table
|
<Table
|
||||||
stickyHeader={true}
|
stickyHeader={true}
|
||||||
@ -111,6 +199,19 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
>
|
>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
padding="checkbox"
|
||||||
|
classes={{ stickyHeader: classes.stickyHeaderCell }}
|
||||||
|
>
|
||||||
|
<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) => (
|
{columns.map((col) => (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={col.key}
|
key={col.key}
|
||||||
@ -124,14 +225,37 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{props.tasks.map((task) => (
|
{props.tasks.map((task) => (
|
||||||
<Row key={task.id} task={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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
allActionPending={props.allActionPending}
|
||||||
|
onDeleteClick={() =>
|
||||||
|
props.deletePendingTaskAsync(queue, task.key)
|
||||||
|
}
|
||||||
|
onArchiveClick={() => {
|
||||||
|
props.archivePendingTaskAsync(queue, task.key);
|
||||||
|
}}
|
||||||
|
onActionCellEnter={() => setActiveTaskId(task.id)}
|
||||||
|
onActionCellLeave={() => setActiveTaskId("")}
|
||||||
|
showActions={activeTaskId === task.id}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
<TableFooter>
|
<TableFooter>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TablePagination
|
<TablePagination
|
||||||
rowsPerPageOptions={rowsPerPageOptions}
|
rowsPerPageOptions={rowsPerPageOptions}
|
||||||
colSpan={columns.length}
|
colSpan={columns.length + 1}
|
||||||
count={props.totalTaskCount}
|
count={props.totalTaskCount}
|
||||||
rowsPerPage={pageSize}
|
rowsPerPage={pageSize}
|
||||||
page={page}
|
page={page}
|
||||||
@ -147,6 +271,7 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
</TableFooter>
|
</TableFooter>
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,15 +281,46 @@ const useRowStyles = makeStyles({
|
|||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
actionCell: {
|
||||||
|
width: "96px",
|
||||||
|
},
|
||||||
|
activeActionCell: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function Row(props: { task: PendingTask }) {
|
interface RowProps {
|
||||||
|
task: PendingTaskExtended;
|
||||||
|
isSelected: boolean;
|
||||||
|
onSelectChange: (checked: boolean) => void;
|
||||||
|
onDeleteClick: () => void;
|
||||||
|
onArchiveClick: () => void;
|
||||||
|
allActionPending: boolean;
|
||||||
|
showActions: boolean;
|
||||||
|
onActionCellEnter: () => void;
|
||||||
|
onActionCellLeave: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Row(props: RowProps) {
|
||||||
const { task } = props;
|
const { task } = props;
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const classes = useRowStyles();
|
const classes = useRowStyles();
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<TableRow key={task.id} className={classes.root}>
|
<TableRow
|
||||||
|
key={task.id}
|
||||||
|
className={classes.root}
|
||||||
|
selected={props.isSelected}
|
||||||
|
>
|
||||||
|
<TableCell padding="checkbox">
|
||||||
|
<Checkbox
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||||
|
props.onSelectChange(event.target.checked)
|
||||||
|
}
|
||||||
|
checked={props.isSelected}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Tooltip title={open ? "Hide Details" : "Show Details"}>
|
<Tooltip title={open ? "Hide Details" : "Show Details"}>
|
||||||
<IconButton
|
<IconButton
|
||||||
@ -180,6 +336,42 @@ function Row(props: { task: PendingTask }) {
|
|||||||
{uuidPrefix(task.id)}
|
{uuidPrefix(task.id)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{task.type}</TableCell>
|
<TableCell>{task.type}</TableCell>
|
||||||
|
<TableCell
|
||||||
|
align="center"
|
||||||
|
className={clsx(
|
||||||
|
classes.actionCell,
|
||||||
|
props.showActions && classes.activeActionCell
|
||||||
|
)}
|
||||||
|
onMouseEnter={props.onActionCellEnter}
|
||||||
|
onMouseLeave={props.onActionCellLeave}
|
||||||
|
>
|
||||||
|
{props.showActions ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<Tooltip title="Delete">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onDeleteClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<DeleteIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Archive">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onArchiveClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<ArchiveIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<IconButton size="small" onClick={props.onActionCellEnter}>
|
||||||
|
<MoreHorizIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
||||||
|
@ -44,6 +44,12 @@ import {
|
|||||||
RUN_RETRY_TASK_SUCCESS,
|
RUN_RETRY_TASK_SUCCESS,
|
||||||
RUN_SCHEDULED_TASK_SUCCESS,
|
RUN_SCHEDULED_TASK_SUCCESS,
|
||||||
TasksActionTypes,
|
TasksActionTypes,
|
||||||
|
ARCHIVE_PENDING_TASK_SUCCESS,
|
||||||
|
DELETE_PENDING_TASK_SUCCESS,
|
||||||
|
BATCH_ARCHIVE_PENDING_TASKS_SUCCESS,
|
||||||
|
BATCH_DELETE_PENDING_TASKS_SUCCESS,
|
||||||
|
ARCHIVE_ALL_PENDING_TASKS_SUCCESS,
|
||||||
|
DELETE_ALL_PENDING_TASKS_SUCCESS,
|
||||||
} from "../actions/tasksActions";
|
} from "../actions/tasksActions";
|
||||||
import { Queue } from "../api";
|
import { Queue } from "../api";
|
||||||
|
|
||||||
@ -217,6 +223,23 @@ function queuesReducer(
|
|||||||
return { ...state, data: newData };
|
return { ...state, data: newData };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ARCHIVE_PENDING_TASK_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
archived: queueInfo.currentStats.archived + 1,
|
||||||
|
pending: queueInfo.currentStats.pending - 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
case ARCHIVE_SCHEDULED_TASK_SUCCESS: {
|
case ARCHIVE_SCHEDULED_TASK_SUCCESS: {
|
||||||
const newData = state.data.map((queueInfo) => {
|
const newData = state.data.map((queueInfo) => {
|
||||||
if (queueInfo.name !== action.queue) {
|
if (queueInfo.name !== action.queue) {
|
||||||
@ -251,6 +274,22 @@ function queuesReducer(
|
|||||||
return { ...state, data: newData };
|
return { ...state, data: newData };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DELETE_PENDING_TASK_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
pending: queueInfo.currentStats.pending - 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
case DELETE_SCHEDULED_TASK_SUCCESS: {
|
case DELETE_SCHEDULED_TASK_SUCCESS: {
|
||||||
const newData = state.data.map((queueInfo) => {
|
const newData = state.data.map((queueInfo) => {
|
||||||
if (queueInfo.name !== action.queue) {
|
if (queueInfo.name !== action.queue) {
|
||||||
@ -267,6 +306,79 @@ function queuesReducer(
|
|||||||
return { ...state, data: newData };
|
return { ...state, data: newData };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BATCH_ARCHIVE_PENDING_TASKS_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
archived:
|
||||||
|
queueInfo.currentStats.archived +
|
||||||
|
action.payload.archived_keys.length,
|
||||||
|
pending:
|
||||||
|
queueInfo.currentStats.pending -
|
||||||
|
action.payload.archived_keys.length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
|
case BATCH_DELETE_PENDING_TASKS_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
pending:
|
||||||
|
queueInfo.currentStats.pending -
|
||||||
|
action.payload.deleted_keys.length,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
|
case ARCHIVE_ALL_PENDING_TASKS_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
archived:
|
||||||
|
queueInfo.currentStats.archived + queueInfo.currentStats.pending,
|
||||||
|
pending: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
|
case DELETE_ALL_PENDING_TASKS_SUCCESS: {
|
||||||
|
const newData = state.data.map((queueInfo) => {
|
||||||
|
if (queueInfo.name !== action.queue) {
|
||||||
|
return queueInfo;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...queueInfo,
|
||||||
|
currentStats: {
|
||||||
|
...queueInfo.currentStats,
|
||||||
|
pending: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { ...state, data: newData };
|
||||||
|
}
|
||||||
|
|
||||||
case BATCH_RUN_SCHEDULED_TASKS_SUCCESS: {
|
case BATCH_RUN_SCHEDULED_TASKS_SUCCESS: {
|
||||||
const newData = state.data.map((queueInfo) => {
|
const newData = state.data.map((queueInfo) => {
|
||||||
if (queueInfo.name !== action.queue) {
|
if (queueInfo.name !== action.queue) {
|
||||||
|
@ -133,6 +133,12 @@ export interface ActiveTaskExtended extends ActiveTask {
|
|||||||
canceling: boolean;
|
canceling: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PendingTaskExtended extends PendingTask {
|
||||||
|
// Indicates that a request has been sent for this
|
||||||
|
// task and awaiting for a response.
|
||||||
|
requestPending: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScheduledTaskExtended extends ScheduledTask {
|
export interface ScheduledTaskExtended extends ScheduledTask {
|
||||||
// Indicates that a request has been sent for this
|
// Indicates that a request has been sent for this
|
||||||
// task and awaiting for a response.
|
// task and awaiting for a response.
|
||||||
@ -164,7 +170,7 @@ interface TasksState {
|
|||||||
batchActionPending: boolean;
|
batchActionPending: boolean;
|
||||||
allActionPending: boolean;
|
allActionPending: boolean;
|
||||||
error: string;
|
error: string;
|
||||||
data: PendingTask[];
|
data: PendingTaskExtended[];
|
||||||
};
|
};
|
||||||
scheduledTasks: {
|
scheduledTasks: {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -284,7 +290,10 @@ function tasksReducer(
|
|||||||
...state.pendingTasks,
|
...state.pendingTasks,
|
||||||
loading: false,
|
loading: false,
|
||||||
error: "",
|
error: "",
|
||||||
data: action.payload.tasks,
|
data: action.payload.tasks.map((task) => ({
|
||||||
|
...task,
|
||||||
|
requestPending: false,
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user