(ui): Use TasksTable component for aggregating tasks

This commit is contained in:
Ken Hibino 2022-04-03 15:58:49 -07:00
parent c22c0206d7
commit 7e0ae2b4a6
4 changed files with 206 additions and 434 deletions

View File

@ -1,75 +1,36 @@
import React, { useCallback, useState } from "react";
import { connect, ConnectedProps } from "react-redux";
import { makeStyles } from "@material-ui/core/styles";
import Checkbox from "@material-ui/core/Checkbox"; import Checkbox from "@material-ui/core/Checkbox";
import IconButton from "@material-ui/core/IconButton"; import IconButton from "@material-ui/core/IconButton";
import Paper from "@material-ui/core/Paper";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell"; import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableFooter from "@material-ui/core/TableFooter";
import TableHead from "@material-ui/core/TableHead";
import TablePagination from "@material-ui/core/TablePagination";
import TableRow from "@material-ui/core/TableRow"; import TableRow from "@material-ui/core/TableRow";
import Tooltip from "@material-ui/core/Tooltip"; import Tooltip from "@material-ui/core/Tooltip";
import ArchiveIcon from "@material-ui/icons/Archive"; import ArchiveIcon from "@material-ui/icons/Archive";
import DeleteIcon from "@material-ui/icons/Delete"; import DeleteIcon from "@material-ui/icons/Delete";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import MoreHorizIcon from "@material-ui/icons/MoreHoriz"; import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
import PlayArrowIcon from "@material-ui/icons/PlayArrow"; import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined"; import React from "react";
import Alert from "@material-ui/lab/Alert"; import { connect, ConnectedProps } from "react-redux";
import AlertTitle from "@material-ui/lab/AlertTitle";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { listGroupsAsync } from "../actions/groupsActions"; import { taskRowsPerPageChange } from "../actions/settingsActions";
import GroupSelect from "./GroupSelect";
import TableActions from "./TableActions";
import SyntaxHighlighter from "./SyntaxHighlighter";
import { prettifyPayload, uuidPrefix } from "../utils";
import { usePolling } from "../hooks";
import { taskDetailsPath } from "../paths";
import { AppState } from "../store";
import { TaskInfoExtended } from "../reducers/tasksReducer";
import { GroupInfo } from "../api";
import { TableColumn } from "../types/table";
import TablePaginationActions, {
rowsPerPageOptions,
} from "./TablePaginationActions";
import { import {
listAggregatingTasksAsync, archiveAggregatingTaskAsync,
deleteAllAggregatingTasksAsync,
archiveAllAggregatingTasksAsync, archiveAllAggregatingTasksAsync,
runAllAggregatingTasksAsync, batchArchiveAggregatingTasksAsync,
batchDeleteAggregatingTasksAsync, batchDeleteAggregatingTasksAsync,
batchRunAggregatingTasksAsync, batchRunAggregatingTasksAsync,
batchArchiveAggregatingTasksAsync,
deleteAggregatingTaskAsync, deleteAggregatingTaskAsync,
deleteAllAggregatingTasksAsync,
listAggregatingTasksAsync,
runAggregatingTaskAsync, runAggregatingTaskAsync,
archiveAggregatingTaskAsync, runAllAggregatingTasksAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { taskRowsPerPageChange } from "../actions/settingsActions"; import { PaginationOptions } from "../api";
import { taskDetailsPath } from "../paths";
const useStyles = makeStyles((theme) => ({ import { AppState } from "../store";
groupSelector: { import { TableColumn } from "../types/table";
paddingTop: theme.spacing(1), import { prettifyPayload, uuidPrefix } from "../utils";
paddingBottom: theme.spacing(1), import SyntaxHighlighter from "./SyntaxHighlighter";
paddingLeft: theme.spacing(2), import TasksTable, { RowProps, useRowStyles } from "./TasksTable";
paddingRight: theme.spacing(2),
},
table: {
minWidth: 650,
},
stickyHeaderCell: {
background: theme.palette.background.paper,
},
alert: {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
},
pagination: {
border: "none",
},
}));
function mapStateToProps(state: AppState) { function mapStateToProps(state: AppState) {
return { return {
@ -87,7 +48,6 @@ function mapStateToProps(state: AppState) {
} }
const mapDispatchToProps = { const mapDispatchToProps = {
listGroupsAsync,
listAggregatingTasksAsync, listAggregatingTasksAsync,
deleteAllAggregatingTasksAsync, deleteAllAggregatingTasksAsync,
archiveAllAggregatingTasksAsync, archiveAllAggregatingTasksAsync,
@ -102,9 +62,12 @@ const mapDispatchToProps = {
}; };
const connector = connect(mapStateToProps, mapDispatchToProps); const connector = connect(mapStateToProps, mapDispatchToProps);
type ReduxProps = ConnectedProps<typeof connector>;
interface Props { interface Props {
queue: string; queue: string;
selectedGroup: string;
totalTaskCount: number; // total number of tasks in the group
} }
const columns: TableColumn[] = [ const columns: TableColumn[] = [
@ -115,365 +78,6 @@ const columns: TableColumn[] = [
{ key: "actions", label: "Actions", align: "center" }, { key: "actions", label: "Actions", align: "center" },
]; ];
function AggregatingTasksTable(
props: Props & ConnectedProps<typeof connector>
) {
const [selectedGroup, setSelectedGroup] = useState<GroupInfo | null>(null);
const [page, setPage] = useState(0);
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const [activeTaskId, setActiveTaskId] = useState<string>("");
const {
pollInterval,
listGroupsAsync,
listAggregatingTasksAsync,
queue,
pageSize,
} = props;
const classes = useStyles();
const handlePageChange = (
event: React.MouseEvent<HTMLButtonElement> | null,
newPage: number
) => {
setPage(newPage);
};
const handleRowsPerPageChange = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
props.taskRowsPerPageChange(parseInt(event.target.value, 10));
setPage(0);
};
const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.checked) {
const newSelected = props.tasks.map((t) => t.id);
setSelectedIds(newSelected);
} else {
setSelectedIds([]);
}
};
const handleDeleteAllClick = () => {
if (selectedGroup === null) {
return;
}
props.deleteAllAggregatingTasksAsync(queue, selectedGroup.group);
};
const handleArchiveAllClick = () => {
if (selectedGroup === null) {
return;
}
props.archiveAllAggregatingTasksAsync(queue, selectedGroup.group);
};
const handleRunAllClick = () => {
if (selectedGroup === null) {
return;
}
props.runAllAggregatingTasksAsync(queue, selectedGroup.group);
};
const handleBatchRunClick = () => {
if (selectedGroup === null) {
return;
}
props
.batchRunAggregatingTasksAsync(queue, selectedGroup.group, selectedIds)
.then(() => setSelectedIds([]));
};
const handleBatchDeleteClick = () => {
if (selectedGroup === null) {
return;
}
props
.batchDeleteAggregatingTasksAsync(queue, selectedGroup.group, selectedIds)
.then(() => setSelectedIds([]));
};
const handleBatchArchiveClick = () => {
if (selectedGroup === null) {
return;
}
props
.batchArchiveAggregatingTasksAsync(
queue,
selectedGroup.group,
selectedIds
)
.then(() => setSelectedIds([]));
};
const fetchGroups = useCallback(() => {
listGroupsAsync(queue);
}, [listGroupsAsync, queue]);
const fetchTasks = useCallback(() => {
const pageOpts = { page: page + 1, size: pageSize };
if (selectedGroup !== null) {
listAggregatingTasksAsync(queue, selectedGroup.group, pageOpts);
}
}, [page, pageSize, queue, selectedGroup, listAggregatingTasksAsync]);
usePolling(fetchGroups, pollInterval);
usePolling(fetchTasks, pollInterval);
if (props.error.length > 0) {
return (
<Alert severity="error" className={classes.alert}>
<AlertTitle>Error</AlertTitle>
{props.error}
</Alert>
);
}
if (props.groups.length === 0) {
return (
<Alert severity="info" className={classes.alert}>
<AlertTitle>Info</AlertTitle>
No aggregating tasks at this time.
</Alert>
);
}
const rowCount = props.tasks.length;
const numSelected = selectedIds.length;
return (
<div>
<div className={classes.groupSelector}>
<GroupSelect
selected={selectedGroup}
onSelect={setSelectedGroup}
groups={props.groups}
error={props.groupsError}
/>
</div>
{props.tasks.length > 0 && selectedGroup !== null ? (
<>
{!window.READ_ONLY && (
<TableActions
showIconButtons={numSelected > 0}
iconButtonActions={[
{
tooltip: "Delete",
icon: <DeleteIcon />,
onClick: handleBatchDeleteClick,
disabled: props.batchActionPending,
},
{
tooltip: "Archive",
icon: <ArchiveIcon />,
onClick: handleBatchArchiveClick,
disabled: props.batchActionPending,
},
{
tooltip: "Run",
icon: <PlayArrowIcon />,
onClick: handleBatchRunClick,
disabled: props.batchActionPending,
},
]}
menuItemActions={[
{
label: "Delete All",
onClick: handleDeleteAllClick,
disabled: props.allActionPending,
},
{
label: "Archive All",
onClick: handleArchiveAllClick,
disabled: props.allActionPending,
},
{
label: "Run All",
onClick: handleRunAllClick,
disabled: props.allActionPending,
},
]}
/>
)}
<TableContainer component={Paper}>
<Table
stickyHeader={true}
className={classes.table}
aria-label="pending tasks table"
size="small"
>
<TableHead>
<TableRow>
{!window.READ_ONLY && (
<TableCell
padding="checkbox"
classes={{ stickyHeader: classes.stickyHeaderCell }}
>
<IconButton>
<Checkbox
indeterminate={
numSelected > 0 && numSelected < rowCount
}
checked={rowCount > 0 && numSelected === rowCount}
onChange={handleSelectAllClick}
inputProps={{
"aria-label": "select all tasks shown in the table",
}}
/>
</IconButton>
</TableCell>
)}
{columns
.filter((col) => {
// Filter out actions column in readonly mode.
return !window.READ_ONLY || col.key !== "actions";
})
.map((col) => (
<TableCell
key={col.key}
align={col.align}
classes={{
stickyHeader: classes.stickyHeaderCell,
}}
>
{col.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{props.group === selectedGroup.group &&
props.tasks.map((task) => (
<Row
key={task.id}
task={task}
isSelected={selectedIds.includes(task.id)}
onSelectChange={(checked: boolean) => {
if (checked) {
setSelectedIds(selectedIds.concat(task.id));
} else {
setSelectedIds(
selectedIds.filter((id) => id !== task.id)
);
}
}}
allActionPending={props.allActionPending}
onDeleteClick={() => {
if (selectedGroup === null) return;
props.deleteAggregatingTaskAsync(
queue,
selectedGroup.group,
task.id
);
}}
onArchiveClick={() => {
if (selectedGroup === null) return;
props.archiveAggregatingTaskAsync(
queue,
selectedGroup.group,
task.id
);
}}
onRunClick={() => {
if (selectedGroup === null) return;
props.runAggregatingTaskAsync(
queue,
selectedGroup.group,
task.id
);
}}
onActionCellEnter={() => setActiveTaskId(task.id)}
onActionCellLeave={() => setActiveTaskId("")}
showActions={activeTaskId === task.id}
/>
))}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={rowsPerPageOptions}
colSpan={columns.length + 1}
count={selectedGroup === null ? 0 : selectedGroup.size}
rowsPerPage={pageSize}
page={page}
SelectProps={{
inputProps: { "aria-label": "rows per page" },
native: true,
}}
onPageChange={handlePageChange}
onRowsPerPageChange={handleRowsPerPageChange}
ActionsComponent={TablePaginationActions}
className={classes.pagination}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
</>
) : (
<Alert severity="info" className={classes.alert}>
<AlertTitle>Info</AlertTitle>
{selectedGroup === null ? (
<div>Please select group</div>
) : (
<div>Group {selectedGroup.group} is empty</div>
)}
</Alert>
)}
</div>
);
}
const useRowStyles = makeStyles((theme) => ({
root: {
cursor: "pointer",
"& #copy-button": {
display: "none",
},
"&:hover": {
boxShadow: theme.shadows[2],
"& #copy-button": {
display: "inline-block",
},
},
"&:hover $copyButton": {
display: "inline-block",
},
"&:hover .MuiTableCell-root": {
borderBottomColor: theme.palette.background.paper,
},
},
actionCell: {
width: "96px",
},
actionButton: {
marginLeft: 3,
marginRight: 3,
},
idCell: {
width: "200px",
},
copyButton: {
display: "none",
},
IdGroup: {
display: "flex",
alignItems: "center",
},
}));
interface RowProps {
task: TaskInfoExtended;
isSelected: boolean;
onSelectChange: (checked: boolean) => void;
onDeleteClick: () => void;
onArchiveClick: () => void;
onRunClick: () => void;
allActionPending: boolean;
showActions: boolean;
onActionCellEnter: () => void;
onActionCellLeave: () => void;
}
function Row(props: RowProps) { function Row(props: RowProps) {
const { task } = props; const { task } = props;
const classes = useRowStyles(); const classes = useRowStyles();
@ -576,4 +180,68 @@ function Row(props: RowProps) {
); );
} }
function AggregatingTasksTable(props: Props & ReduxProps) {
const listTasks = (qname: string, pgn?: PaginationOptions) =>
props.listAggregatingTasksAsync(qname, props.selectedGroup, pgn);
const deleteAllTasks = (qname: string) =>
props.deleteAllAggregatingTasksAsync(qname, props.selectedGroup);
const archiveAllTasks = (qname: string) =>
props.archiveAllAggregatingTasksAsync(qname, props.selectedGroup);
const runAllTasks = (qname: string) =>
props.runAllAggregatingTasksAsync(qname, props.selectedGroup);
const batchDeleteTasks = (qname: string, taskIds: string[]) =>
props.batchDeleteAggregatingTasksAsync(qname, props.selectedGroup, taskIds);
const batchArchiveTasks = (qname: string, taskIds: string[]) =>
props.batchArchiveAggregatingTasksAsync(
qname,
props.selectedGroup,
taskIds
);
const batchRunTasks = (qname: string, taskIds: string[]) =>
props.batchRunAggregatingTasksAsync(qname, props.selectedGroup, taskIds);
const deleteTask = (qname: string, taskId: string) =>
props.deleteAggregatingTaskAsync(qname, props.selectedGroup, taskId);
const archiveTask = (qname: string, taskId: string) =>
props.archiveAggregatingTaskAsync(qname, props.selectedGroup, taskId);
const runTask = (qname: string, taskId: string) =>
props.runAggregatingTaskAsync(qname, props.selectedGroup, taskId);
return (
<TasksTable
queue={props.queue}
totalTaskCount={props.totalTaskCount}
taskState="aggregating"
loading={props.loading}
error={props.error}
tasks={props.tasks}
batchActionPending={props.batchActionPending}
allActionPending={props.allActionPending}
pollInterval={props.pollInterval}
pageSize={props.pageSize}
listTasks={listTasks}
deleteAllTasks={deleteAllTasks}
archiveAllTasks={archiveAllTasks}
runAllTasks={runAllTasks}
batchDeleteTasks={batchDeleteTasks}
batchArchiveTasks={batchArchiveTasks}
batchRunTasks={batchRunTasks}
deleteTask={deleteTask}
archiveTask={archiveTask}
runTask={runTask}
taskRowsPerPageChange={props.taskRowsPerPageChange}
columns={columns}
renderRow={(rowProps: RowProps) => <Row {...rowProps} />}
/>
);
}
export default connector(AggregatingTasksTable); export default connector(AggregatingTasksTable);

View File

@ -0,0 +1,100 @@
import { makeStyles } from "@material-ui/core/styles";
import Alert from "@material-ui/lab/Alert";
import AlertTitle from "@material-ui/lab/AlertTitle";
import React, { useCallback, useState } from "react";
import { connect, ConnectedProps } from "react-redux";
import { listGroupsAsync } from "../actions/groupsActions";
import { GroupInfo } from "../api";
import { usePolling } from "../hooks";
import { AppState } from "../store";
import AggregatingTasksTable from "./AggregatingTasksTable";
import GroupSelect from "./GroupSelect";
const useStyles = makeStyles((theme) => ({
groupSelector: {
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1),
paddingLeft: theme.spacing(2),
paddingRight: theme.spacing(2),
},
alert: {
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
},
}));
function mapStateToProps(state: AppState) {
return {
groups: state.groups.data,
groupsError: state.groups.error,
pollInterval: state.settings.pollInterval,
};
}
const mapDispatchToProps = {
listGroupsAsync,
};
const connector = connect(mapStateToProps, mapDispatchToProps);
interface Props {
queue: string;
}
function AggregatingTasksTableContainer(
props: Props & ConnectedProps<typeof connector>
) {
const [selectedGroup, setSelectedGroup] = useState<GroupInfo | null>(null);
const { pollInterval, listGroupsAsync, queue } = props;
const classes = useStyles();
const fetchGroups = useCallback(() => {
listGroupsAsync(queue);
}, [listGroupsAsync, queue]);
usePolling(fetchGroups, pollInterval);
if (props.groupsError.length > 0) {
return (
<Alert severity="error" className={classes.alert}>
<AlertTitle>Error</AlertTitle>
{props.groupsError}
</Alert>
);
}
if (props.groups.length === 0) {
return (
<Alert severity="info" className={classes.alert}>
<AlertTitle>Info</AlertTitle>
No aggregating tasks at this time.
</Alert>
);
}
return (
<div>
<div className={classes.groupSelector}>
<GroupSelect
selected={selectedGroup}
onSelect={setSelectedGroup}
groups={props.groups}
error={props.groupsError}
/>
</div>
{selectedGroup !== null ? (
<AggregatingTasksTable
queue={props.queue}
totalTaskCount={selectedGroup.size}
selectedGroup={selectedGroup.group}
/>
) : (
<Alert severity="info" className={classes.alert}>
<AlertTitle>Info</AlertTitle>
<div>Please select group</div>
</Alert>
)}
</div>
);
}
export default connector(AggregatingTasksTableContainer);

View File

@ -105,17 +105,17 @@ export default function TasksTable(props: Props) {
} }
}; };
function createAllTasksHandler(action: (qname: string) => Promise<void>) { function createAllActionHandler(action: (qname: string) => Promise<void>) {
return () => action(queue); return () => action(queue);
} }
function createBatchTasksHandler( function createBatchActionHandler(
action: (qname: string, taskIds: string[]) => Promise<void> action: (qname: string, taskIds: string[]) => Promise<void>
) { ) {
return () => action(queue, selectedIds).then(() => setSelectedIds([])); return () => action(queue, selectedIds).then(() => setSelectedIds([]));
} }
function createTaskAction( function createSingleActionHandler(
action: (qname: string, taskId: string) => Promise<void>, action: (qname: string, taskId: string) => Promise<void>,
taskId: string taskId: string
) { ) {
@ -126,28 +126,28 @@ export default function TasksTable(props: Props) {
if (props.deleteAllTasks) { if (props.deleteAllTasks) {
allActions.push({ allActions.push({
label: "Delete All", label: "Delete All",
onClick: createAllTasksHandler(props.deleteAllTasks), onClick: createAllActionHandler(props.deleteAllTasks),
disabled: props.allActionPending, disabled: props.allActionPending,
}); });
} }
if (props.archiveAllTasks) { if (props.archiveAllTasks) {
allActions.push({ allActions.push({
label: "Archive All", label: "Archive All",
onClick: createAllTasksHandler(props.archiveAllTasks), onClick: createAllActionHandler(props.archiveAllTasks),
disabled: props.allActionPending, disabled: props.allActionPending,
}); });
} }
if (props.runAllTasks) { if (props.runAllTasks) {
allActions.push({ allActions.push({
label: "Run All", label: "Run All",
onClick: createAllTasksHandler(props.runAllTasks), onClick: createAllActionHandler(props.runAllTasks),
disabled: props.allActionPending, disabled: props.allActionPending,
}); });
} }
if (props.cancelAllTasks) { if (props.cancelAllTasks) {
allActions.push({ allActions.push({
label: "Cancel All", label: "Cancel All",
onClick: createAllTasksHandler(props.cancelAllTasks), onClick: createAllActionHandler(props.cancelAllTasks),
disabled: props.allActionPending, disabled: props.allActionPending,
}); });
} }
@ -158,7 +158,7 @@ export default function TasksTable(props: Props) {
tooltip: "Delete", tooltip: "Delete",
icon: <DeleteIcon />, icon: <DeleteIcon />,
disabled: props.batchActionPending, disabled: props.batchActionPending,
onClick: createBatchTasksHandler(props.batchDeleteTasks), onClick: createBatchActionHandler(props.batchDeleteTasks),
}); });
} }
if (props.batchArchiveTasks) { if (props.batchArchiveTasks) {
@ -166,7 +166,7 @@ export default function TasksTable(props: Props) {
tooltip: "Archive", tooltip: "Archive",
icon: <ArchiveIcon />, icon: <ArchiveIcon />,
disabled: props.batchActionPending, disabled: props.batchActionPending,
onClick: createBatchTasksHandler(props.batchArchiveTasks), onClick: createBatchActionHandler(props.batchArchiveTasks),
}); });
} }
if (props.batchRunTasks) { if (props.batchRunTasks) {
@ -174,7 +174,7 @@ export default function TasksTable(props: Props) {
tooltip: "Run", tooltip: "Run",
icon: <PlayArrowIcon />, icon: <PlayArrowIcon />,
disabled: props.batchActionPending, disabled: props.batchActionPending,
onClick: createBatchTasksHandler(props.batchRunTasks), onClick: createBatchActionHandler(props.batchRunTasks),
}); });
} }
if (props.batchCancelTasks) { if (props.batchCancelTasks) {
@ -182,7 +182,7 @@ export default function TasksTable(props: Props) {
tooltip: "Cancel", tooltip: "Cancel",
icon: <CancelIcon />, icon: <CancelIcon />,
disabled: props.batchActionPending, disabled: props.batchActionPending,
onClick: createBatchTasksHandler(props.batchCancelTasks), onClick: createBatchActionHandler(props.batchCancelTasks),
}); });
} }
@ -205,7 +205,11 @@ export default function TasksTable(props: Props) {
return ( return (
<Alert severity="info" className={classes.alert}> <Alert severity="info" className={classes.alert}>
<AlertTitle>Info</AlertTitle> <AlertTitle>Info</AlertTitle>
No {props.taskState} tasks at this time. {props.taskState === "aggregating" ? (
<div>Selected group is empty.</div>
) : (
<div>No {props.taskState} tasks at this time.</div>
)}
</Alert> </Alert>
); );
} }
@ -278,16 +282,16 @@ export default function TasksTable(props: Props) {
} }
}, },
onRunClick: props.runTask onRunClick: props.runTask
? createTaskAction(props.runTask, task.id) ? createSingleActionHandler(props.runTask, task.id)
: undefined, : undefined,
onDeleteClick: props.deleteTask onDeleteClick: props.deleteTask
? createTaskAction(props.deleteTask, task.id) ? createSingleActionHandler(props.deleteTask, task.id)
: undefined, : undefined,
onArchiveClick: props.archiveTask onArchiveClick: props.archiveTask
? createTaskAction(props.archiveTask, task.id) ? createSingleActionHandler(props.archiveTask, task.id)
: undefined, : undefined,
onCancelClick: props.cancelTask onCancelClick: props.cancelTask
? createTaskAction(props.cancelTask, task.id) ? createSingleActionHandler(props.cancelTask, task.id)
: undefined, : undefined,
onActionCellEnter: () => setActiveTaskId(task.id), onActionCellEnter: () => setActiveTaskId(task.id),
onActionCellLeave: () => setActiveTaskId(""), onActionCellLeave: () => setActiveTaskId(""),
@ -340,7 +344,7 @@ export const useRowStyles = makeStyles((theme) => ({
}, },
}, },
actionCell: { actionCell: {
width: "140px", // TODO: This was 96px for pending/archived/completed row width: "140px",
}, },
actionButton: { actionButton: {
marginLeft: 3, marginLeft: 3,

View File

@ -12,7 +12,7 @@ import ScheduledTasksTable from "./ScheduledTasksTable";
import RetryTasksTable from "./RetryTasksTable"; import RetryTasksTable from "./RetryTasksTable";
import ArchivedTasksTable from "./ArchivedTasksTable"; import ArchivedTasksTable from "./ArchivedTasksTable";
import CompletedTasksTable from "./CompletedTasksTable"; import CompletedTasksTable from "./CompletedTasksTable";
import AggregatingTasksTable from "./AggregatingTasksTable"; import AggregatingTasksTableContainer from "./AggregatingTasksTableContainer";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { queueDetailsPath, taskDetailsPath } from "../paths"; import { queueDetailsPath, taskDetailsPath } from "../paths";
import { QueueInfo } from "../reducers/queuesReducer"; import { QueueInfo } from "../reducers/queuesReducer";
@ -229,7 +229,7 @@ function TasksTableContainer(props: Props & ReduxProps) {
/> />
</TabPanel> </TabPanel>
<TabPanel value="aggregating" selected={props.selected}> <TabPanel value="aggregating" selected={props.selected}>
<AggregatingTasksTable queue={props.queue} /> <AggregatingTasksTableContainer queue={props.queue} />
</TabPanel> </TabPanel>
<TabPanel value="scheduled" selected={props.selected}> <TabPanel value="scheduled" selected={props.selected}>
<ScheduledTasksTable <ScheduledTasksTable