mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-01-19 03:05: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 TableCell from "@material-ui/core/TableCell";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import ButtonGroup from "@material-ui/core/ButtonGroup";
|
||||
import Checkbox from "@material-ui/core/Checkbox";
|
||||
import TableContainer from "@material-ui/core/TableContainer";
|
||||
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 Collapse from "@material-ui/core/Collapse";
|
||||
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 KeyboardArrowDownIcon from "@material-ui/icons/KeyboardArrowDown";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import TableFooter from "@material-ui/core/TableFooter";
|
||||
import TablePagination from "@material-ui/core/TablePagination";
|
||||
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||
import Alert from "@material-ui/lab/Alert";
|
||||
import AlertTitle from "@material-ui/lab/AlertTitle";
|
||||
import SyntaxHighlighter from "react-syntax-highlighter";
|
||||
@ -40,6 +36,7 @@ import TablePaginationActions, {
|
||||
defaultPageSize,
|
||||
rowsPerPageOptions,
|
||||
} from "./TablePaginationActions";
|
||||
import TableActions from "./TableActions";
|
||||
import { timeAgo } from "../timeutil";
|
||||
import { usePolling } from "../hooks";
|
||||
import { DeadTaskExtended } from "../reducers/tasksReducer";
|
||||
@ -48,12 +45,6 @@ const useStyles = makeStyles({
|
||||
table: {
|
||||
minWidth: 650,
|
||||
},
|
||||
actionsContainer: {
|
||||
padding: "4px",
|
||||
},
|
||||
moreIcon: {
|
||||
marginRight: "8px",
|
||||
},
|
||||
});
|
||||
|
||||
const useRowStyles = makeStyles({
|
||||
@ -99,7 +90,6 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
||||
const [page, setPage] = useState(0);
|
||||
const [pageSize, setPageSize] = useState(defaultPageSize);
|
||||
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
|
||||
const [menuAnchor, setMenuAnchor] = useState<null | HTMLElement>(null);
|
||||
|
||||
const handleChangePage = (
|
||||
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 = () => {
|
||||
props.runAllDeadTasksAsync(queue);
|
||||
setMenuAnchor(null);
|
||||
};
|
||||
|
||||
const handleDeleteAllClick = () => {
|
||||
props.deleteAllDeadTasksAsync(queue);
|
||||
setMenuAnchor(null);
|
||||
};
|
||||
|
||||
const handleBatchRunClick = () => {
|
||||
props
|
||||
.batchDeleteDeadTasksAsync(queue, selectedKeys)
|
||||
.then(() => setSelectedKeys([]));
|
||||
};
|
||||
|
||||
const handleBatchDeleteClick = () => {
|
||||
props
|
||||
.batchRunDeadTasksAsync(queue, selectedKeys)
|
||||
.then(() => setSelectedKeys([]));
|
||||
};
|
||||
|
||||
const fetchData = useCallback(() => {
|
||||
@ -169,64 +163,15 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
||||
const numSelected = selectedKeys.length;
|
||||
return (
|
||||
<div>
|
||||
<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={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>
|
||||
<TableActions
|
||||
allActionPending={props.allActionPending}
|
||||
batchActionPending={props.batchActionPending}
|
||||
showBatchActions={numSelected > 0}
|
||||
onRunAllClick={handleRunAllClick}
|
||||
onDeleteAllClick={handleDeleteAllClick}
|
||||
onBatchRunClick={handleBatchRunClick}
|
||||
onBatchDeleteClick={handleBatchDeleteClick}
|
||||
/>
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
stickyHeader={true}
|
||||
|
@ -31,6 +31,7 @@ import TablePaginationActions, {
|
||||
defaultPageSize,
|
||||
rowsPerPageOptions,
|
||||
} from "./TablePaginationActions";
|
||||
import TableActions from "./TableActions";
|
||||
import { durationBefore } from "../timeutil";
|
||||
import { usePolling } from "../hooks";
|
||||
import { RetryTaskExtended } from "../reducers/tasksReducer";
|
||||
@ -45,6 +46,8 @@ 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,
|
||||
};
|
||||
}
|
||||
@ -120,71 +123,82 @@ function RetryTasksTable(props: Props & ReduxProps) {
|
||||
const rowCount = props.tasks.length;
|
||||
const numSelected = selectedKeys.length;
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
stickyHeader={true}
|
||||
className={classes.table}
|
||||
aria-label="retry tasks 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",
|
||||
<div>
|
||||
<TableActions
|
||||
allActionPending={props.allActionPending}
|
||||
batchActionPending={props.batchActionPending}
|
||||
showBatchActions={numSelected > 0}
|
||||
onRunAllClick={() => console.log("TODO")}
|
||||
onDeleteAllClick={() => console.log("TODO")}
|
||||
onBatchRunClick={() => console.log("TODO")}
|
||||
onBatchDeleteClick={() => console.log("TODO")}
|
||||
/>
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
stickyHeader={true}
|
||||
className={classes.table}
|
||||
aria-label="retry tasks 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>
|
||||
</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);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</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>
|
||||
</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>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import TablePaginationActions, {
|
||||
defaultPageSize,
|
||||
rowsPerPageOptions,
|
||||
} from "./TablePaginationActions";
|
||||
import TableActions from "./TableActions";
|
||||
import { durationBefore } from "../timeutil";
|
||||
import { usePolling } from "../hooks";
|
||||
import { ScheduledTaskExtended } from "../reducers/tasksReducer";
|
||||
@ -45,6 +46,8 @@ function mapStateToProps(state: AppState) {
|
||||
return {
|
||||
loading: state.tasks.scheduledTasks.loading,
|
||||
tasks: state.tasks.scheduledTasks.data,
|
||||
batchActionPending: state.tasks.scheduledTasks.batchActionPending,
|
||||
allActionPending: state.tasks.scheduledTasks.allActionPending,
|
||||
pollInterval: state.settings.pollInterval,
|
||||
};
|
||||
}
|
||||
@ -120,71 +123,82 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
|
||||
const rowCount = props.tasks.length;
|
||||
const numSelected = selectedKeys.length;
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
stickyHeader={true}
|
||||
className={classes.table}
|
||||
aria-label="scheduled tasks 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",
|
||||
<div>
|
||||
<TableActions
|
||||
allActionPending={props.allActionPending}
|
||||
batchActionPending={props.batchActionPending}
|
||||
showBatchActions={numSelected > 0}
|
||||
onRunAllClick={() => console.log("TODO")}
|
||||
onDeleteAllClick={() => console.log("TODO")}
|
||||
onBatchRunClick={() => console.log("TODO")}
|
||||
onBatchDeleteClick={() => console.log("TODO")}
|
||||
/>
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
stickyHeader={true}
|
||||
className={classes.table}
|
||||
aria-label="scheduled tasks 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>
|
||||
</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);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</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>
|
||||
</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>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
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: {
|
||||
loading: boolean;
|
||||
batchActionPending: boolean;
|
||||
allActionPending: boolean;
|
||||
error: string;
|
||||
data: ScheduledTaskExtended[];
|
||||
};
|
||||
retryTasks: {
|
||||
loading: boolean;
|
||||
batchActionPending: boolean;
|
||||
allActionPending: boolean;
|
||||
error: string;
|
||||
data: RetryTaskExtended[];
|
||||
};
|
||||
@ -122,11 +126,15 @@ const initialState: TasksState = {
|
||||
},
|
||||
scheduledTasks: {
|
||||
loading: false,
|
||||
batchActionPending: false,
|
||||
allActionPending: false,
|
||||
error: "",
|
||||
data: [],
|
||||
},
|
||||
retryTasks: {
|
||||
loading: false,
|
||||
batchActionPending: false,
|
||||
allActionPending: false,
|
||||
error: "",
|
||||
data: [],
|
||||
},
|
||||
@ -222,6 +230,7 @@ function tasksReducer(
|
||||
return {
|
||||
...state,
|
||||
scheduledTasks: {
|
||||
...state.scheduledTasks,
|
||||
loading: false,
|
||||
error: "",
|
||||
data: action.payload.tasks.map((task) => ({
|
||||
@ -255,6 +264,7 @@ function tasksReducer(
|
||||
return {
|
||||
...state,
|
||||
retryTasks: {
|
||||
...state.retryTasks,
|
||||
loading: false,
|
||||
error: "",
|
||||
data: action.payload.tasks.map((task) => ({
|
||||
|
Loading…
Reference in New Issue
Block a user