mirror of
https://github.com/hibiken/asynqmon.git
synced 2025-01-19 03:05:53 +08:00
Use icons for table row actions
This commit is contained in:
parent
50639cabb8
commit
1a3c3ffbdd
@ -6,18 +6,19 @@ import TableBody from "@material-ui/core/TableBody";
|
|||||||
import TableCell from "@material-ui/core/TableCell";
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
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 Button from "@material-ui/core/Button";
|
|
||||||
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";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
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 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 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 CancelIcon from "@material-ui/icons/Cancel";
|
import CancelIcon from "@material-ui/icons/Cancel";
|
||||||
|
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
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";
|
||||||
@ -38,6 +39,7 @@ import TableActions from "./TableActions";
|
|||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { ActiveTaskExtended } from "../reducers/tasksReducer";
|
import { ActiveTaskExtended } from "../reducers/tasksReducer";
|
||||||
import { uuidPrefix } from "../utils";
|
import { uuidPrefix } from "../utils";
|
||||||
|
import { TableColumn } from "../types/table";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
table: {
|
table: {
|
||||||
@ -76,6 +78,7 @@ function ActiveTasksTable(props: Props & ReduxProps) {
|
|||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [pageSize, setPageSize] = useState(defaultPageSize);
|
const [pageSize, setPageSize] = useState(defaultPageSize);
|
||||||
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
||||||
|
const [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -126,11 +129,12 @@ function ActiveTasksTable(props: Props & ReduxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns: { label: string; align: "left" | "center" | "right" }[] = [
|
const columns: TableColumn[] = [
|
||||||
{ label: "", align: "left" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ label: "ID", align: "left" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ label: "Type", align: "left" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
{ label: "Actions", align: "center" },
|
{ key: "status", label: "Status", align: "left" },
|
||||||
|
{ key: "actions", label: "Actions", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
@ -175,7 +179,7 @@ function ActiveTasksTable(props: Props & ReduxProps) {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{columns.map((col) => (
|
{columns.map((col) => (
|
||||||
<TableCell key={col.label} align={col.align}>
|
<TableCell key={col.key} align={col.align}>
|
||||||
{col.label}
|
{col.label}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
@ -198,6 +202,9 @@ function ActiveTasksTable(props: Props & ReduxProps) {
|
|||||||
onCancelClick={() => {
|
onCancelClick={() => {
|
||||||
props.cancelActiveTaskAsync(queue, task.id);
|
props.cancelActiveTaskAsync(queue, task.id);
|
||||||
}}
|
}}
|
||||||
|
onActionCellEnter={() => setActiveTaskId(task.id)}
|
||||||
|
onActionCellLeave={() => setActiveTaskId("")}
|
||||||
|
showActions={activeTaskId === task.id}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -238,6 +245,9 @@ interface RowProps {
|
|||||||
isSelected: boolean;
|
isSelected: boolean;
|
||||||
onSelectChange: (checked: boolean) => void;
|
onSelectChange: (checked: boolean) => void;
|
||||||
onCancelClick: () => void;
|
onCancelClick: () => void;
|
||||||
|
showActions: boolean;
|
||||||
|
onActionCellEnter: () => void;
|
||||||
|
onActionCellLeave: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Row(props: RowProps) {
|
function Row(props: RowProps) {
|
||||||
@ -272,14 +282,29 @@ function Row(props: RowProps) {
|
|||||||
{uuidPrefix(task.id)}
|
{uuidPrefix(task.id)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{task.type}</TableCell>
|
<TableCell>{task.type}</TableCell>
|
||||||
<TableCell align="center">
|
<TableCell>{task.canceling ? "Canceling" : "Running"}</TableCell>
|
||||||
<Button
|
<TableCell
|
||||||
color="primary"
|
align="center"
|
||||||
|
onMouseEnter={props.onActionCellEnter}
|
||||||
|
onMouseLeave={props.onActionCellLeave}
|
||||||
|
>
|
||||||
|
{props.showActions ? (
|
||||||
|
<React.Fragment>
|
||||||
|
<Tooltip title="Cancel">
|
||||||
|
<IconButton
|
||||||
onClick={props.onCancelClick}
|
onClick={props.onCancelClick}
|
||||||
disabled={task.requestPending || task.canceling}
|
disabled={task.requestPending || task.canceling}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
{task.canceling ? "Canceling..." : "Cancel"}
|
<CancelIcon fontSize="small" />
|
||||||
</Button>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<IconButton size="small" onClick={props.onActionCellEnter}>
|
||||||
|
<MoreHorizIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow selected={props.isSelected}>
|
<TableRow selected={props.isSelected}>
|
||||||
|
@ -1,20 +1,22 @@
|
|||||||
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";
|
||||||
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 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";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
|
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 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 PlayArrowIcon from "@material-ui/icons/PlayArrow";
|
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
|
||||||
import DeleteIcon from "@material-ui/icons/Delete";
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
|
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
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";
|
||||||
@ -42,6 +44,7 @@ import TableActions from "./TableActions";
|
|||||||
import { timeAgo, uuidPrefix } from "../utils";
|
import { timeAgo, uuidPrefix } from "../utils";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { DeadTaskExtended } from "../reducers/tasksReducer";
|
import { DeadTaskExtended } from "../reducers/tasksReducer";
|
||||||
|
import { TableColumn } from "../types/table";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
table: {
|
table: {
|
||||||
@ -55,6 +58,13 @@ const useRowStyles = makeStyles({
|
|||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
actionCell: {
|
||||||
|
width: "96px",
|
||||||
|
},
|
||||||
|
activeActionCell: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function mapStateToProps(state: AppState) {
|
function mapStateToProps(state: AppState) {
|
||||||
@ -92,6 +102,7 @@ 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 [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -152,13 +163,13 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = [
|
const columns: TableColumn[] = [
|
||||||
{ label: "" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ label: "ID" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ label: "Type" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
{ label: "Last Failed" },
|
{ key: "last_failed", label: "Last Failed", align: "left" },
|
||||||
{ label: "Last Error" },
|
{ key: "last_error", label: "Last Error", align: "left" },
|
||||||
{ label: "Actions" },
|
{ key: "actions", label: "Actions", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
@ -214,7 +225,9 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{columns.map((col) => (
|
{columns.map((col) => (
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
<TableCell key={col.key} align={col.align}>
|
||||||
|
{col.label}
|
||||||
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@ -240,6 +253,9 @@ function DeadTasksTable(props: Props & ReduxProps) {
|
|||||||
props.deleteDeadTaskAsync(queue, task.key);
|
props.deleteDeadTaskAsync(queue, task.key);
|
||||||
}}
|
}}
|
||||||
allActionPending={props.allActionPending}
|
allActionPending={props.allActionPending}
|
||||||
|
onActionCellEnter={() => setActiveTaskId(task.id)}
|
||||||
|
onActionCellLeave={() => setActiveTaskId("")}
|
||||||
|
showActions={activeTaskId === task.id}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -274,6 +290,9 @@ interface RowProps {
|
|||||||
onRunClick: () => void;
|
onRunClick: () => void;
|
||||||
onDeleteClick: () => void;
|
onDeleteClick: () => void;
|
||||||
allActionPending: boolean;
|
allActionPending: boolean;
|
||||||
|
showActions: boolean;
|
||||||
|
onActionCellEnter: () => void;
|
||||||
|
onActionCellLeave: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Row(props: RowProps) {
|
function Row(props: RowProps) {
|
||||||
@ -310,19 +329,41 @@ function Row(props: RowProps) {
|
|||||||
<TableCell>{task.type}</TableCell>
|
<TableCell>{task.type}</TableCell>
|
||||||
<TableCell>{timeAgo(task.last_failed_at)}</TableCell>
|
<TableCell>{timeAgo(task.last_failed_at)}</TableCell>
|
||||||
<TableCell>{task.error_message}</TableCell>
|
<TableCell>{task.error_message}</TableCell>
|
||||||
<TableCell>
|
<TableCell
|
||||||
<Button
|
align="center"
|
||||||
onClick={props.onRunClick}
|
className={clsx(
|
||||||
disabled={task.requestPending || props.allActionPending}
|
classes.actionCell,
|
||||||
|
props.showActions && classes.activeActionCell
|
||||||
|
)}
|
||||||
|
onMouseEnter={props.onActionCellEnter}
|
||||||
|
onMouseLeave={props.onActionCellLeave}
|
||||||
>
|
>
|
||||||
Run
|
{props.showActions ? (
|
||||||
</Button>
|
<React.Fragment>
|
||||||
<Button
|
<Tooltip title="Delete">
|
||||||
|
<IconButton
|
||||||
onClick={props.onDeleteClick}
|
onClick={props.onDeleteClick}
|
||||||
disabled={task.requestPending || props.allActionPending}
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
Delete
|
<DeleteIcon fontSize="small" />
|
||||||
</Button>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Run">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onRunClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<PlayArrowIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<IconButton size="small" onClick={props.onActionCellEnter}>
|
||||||
|
<MoreHorizIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow selected={props.isSelected}>
|
<TableRow selected={props.isSelected}>
|
||||||
|
@ -6,7 +6,6 @@ import TableBody from "@material-ui/core/TableBody";
|
|||||||
import TableCell from "@material-ui/core/TableCell";
|
import TableCell from "@material-ui/core/TableCell";
|
||||||
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 Button from "@material-ui/core/Button";
|
|
||||||
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";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
@ -30,6 +29,7 @@ import { AppState } from "../store";
|
|||||||
import { PendingTask } from "../api";
|
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";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
table: {
|
table: {
|
||||||
@ -92,11 +92,10 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = [
|
const columns: TableColumn[] = [
|
||||||
{ label: "" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ label: "ID" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ label: "Type" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
{ label: "Actions" },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -110,7 +109,9 @@ function PendingTasksTable(props: Props & ReduxProps) {
|
|||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{columns.map((col) => (
|
{columns.map((col) => (
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
<TableCell key={col.key} align={col.align}>
|
||||||
|
{col.label}
|
||||||
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@ -170,9 +171,6 @@ function Row(props: { task: PendingTask }) {
|
|||||||
{uuidPrefix(task.id)}
|
{uuidPrefix(task.id)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{task.type}</TableCell>
|
<TableCell>{task.type}</TableCell>
|
||||||
<TableCell>
|
|
||||||
<Button>Cancel</Button>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={8}>
|
||||||
|
@ -18,7 +18,7 @@ import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
|||||||
import DeleteQueueConfirmationDialog from "./DeleteQueueConfirmationDialog";
|
import DeleteQueueConfirmationDialog from "./DeleteQueueConfirmationDialog";
|
||||||
import { Queue } from "../api";
|
import { Queue } from "../api";
|
||||||
import { queueDetailsPath } from "../paths";
|
import { queueDetailsPath } from "../paths";
|
||||||
import { SortDirection, ColumnConfig } from "../types/table";
|
import { SortDirection, SortableTableColumn } from "../types/table";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
table: {
|
table: {
|
||||||
@ -71,7 +71,7 @@ enum SortBy {
|
|||||||
None, // no sort support
|
None, // no sort support
|
||||||
}
|
}
|
||||||
|
|
||||||
const colConfigs: ColumnConfig<SortBy>[] = [
|
const colConfigs: SortableTableColumn<SortBy>[] = [
|
||||||
{ label: "Queue", key: "queue", sortBy: SortBy.Queue, align: "left" },
|
{ label: "Queue", key: "queue", sortBy: SortBy.Queue, align: "left" },
|
||||||
{ label: "Size", key: "size", sortBy: SortBy.Size, align: "right" },
|
{ label: "Size", key: "size", sortBy: SortBy.Size, align: "right" },
|
||||||
{ label: "Active", key: "active", sortBy: SortBy.Active, align: "right" },
|
{ label: "Active", key: "active", sortBy: SortBy.Active, align: "right" },
|
||||||
|
@ -4,7 +4,6 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||||||
import Table from "@material-ui/core/Table";
|
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 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";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
@ -12,12 +11,14 @@ import TableFooter from "@material-ui/core/TableFooter";
|
|||||||
import TablePagination from "@material-ui/core/TablePagination";
|
import TablePagination from "@material-ui/core/TablePagination";
|
||||||
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 Tooltip from "@material-ui/core/Tooltip";
|
||||||
import Checkbox from "@material-ui/core/Checkbox";
|
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 PlayArrowIcon from "@material-ui/icons/PlayArrow";
|
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
|
||||||
import DeleteIcon from "@material-ui/icons/Delete";
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
import ArchiveIcon from "@material-ui/icons/Archive";
|
import ArchiveIcon from "@material-ui/icons/Archive";
|
||||||
|
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
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";
|
||||||
@ -46,6 +47,8 @@ import TableActions from "./TableActions";
|
|||||||
import { durationBefore, uuidPrefix } from "../utils";
|
import { durationBefore, uuidPrefix } from "../utils";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { RetryTaskExtended } from "../reducers/tasksReducer";
|
import { RetryTaskExtended } from "../reducers/tasksReducer";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { TableColumn } from "../types/table";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
table: {
|
table: {
|
||||||
@ -91,6 +94,7 @@ function RetryTasksTable(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 [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -161,15 +165,15 @@ function RetryTasksTable(props: Props & ReduxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = [
|
const columns: TableColumn[] = [
|
||||||
{ label: "" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ label: "ID" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ label: "Type" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
{ label: "Retry In" },
|
{ key: "retry_in", label: "Retry In", align: "left" },
|
||||||
{ label: "Last Error" },
|
{ key: "last_error", label: "Last Error", align: "left" },
|
||||||
{ label: "Retried" },
|
{ key: "retried", label: "Retried", align: "left" },
|
||||||
{ label: "Max Retry" },
|
{ key: "max_retry", label: "Max Retry", align: "left" },
|
||||||
{ label: "Actions" },
|
{ key: "actions", label: "Actions", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
@ -236,7 +240,9 @@ function RetryTasksTable(props: Props & ReduxProps) {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{columns.map((col) => (
|
{columns.map((col) => (
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
<TableCell key={col.label} align={col.align}>
|
||||||
|
{col.label}
|
||||||
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@ -265,6 +271,9 @@ function RetryTasksTable(props: Props & ReduxProps) {
|
|||||||
onKillClick={() => {
|
onKillClick={() => {
|
||||||
props.killRetryTaskAsync(task.queue, task.key);
|
props.killRetryTaskAsync(task.queue, task.key);
|
||||||
}}
|
}}
|
||||||
|
onActionCellEnter={() => setActiveTaskId(task.id)}
|
||||||
|
onActionCellLeave={() => setActiveTaskId("")}
|
||||||
|
showActions={activeTaskId === task.id}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -298,6 +307,13 @@ const useRowStyles = makeStyles({
|
|||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
actionCell: {
|
||||||
|
width: "140px",
|
||||||
|
},
|
||||||
|
activeActionCell: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
@ -308,6 +324,9 @@ interface RowProps {
|
|||||||
onRunClick: () => void;
|
onRunClick: () => void;
|
||||||
onKillClick: () => void;
|
onKillClick: () => void;
|
||||||
allActionPending: boolean;
|
allActionPending: boolean;
|
||||||
|
showActions: boolean;
|
||||||
|
onActionCellEnter: () => void;
|
||||||
|
onActionCellLeave: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Row(props: RowProps) {
|
function Row(props: RowProps) {
|
||||||
@ -346,25 +365,50 @@ function Row(props: RowProps) {
|
|||||||
<TableCell>{task.error_message}</TableCell>
|
<TableCell>{task.error_message}</TableCell>
|
||||||
<TableCell>{task.retried}</TableCell>
|
<TableCell>{task.retried}</TableCell>
|
||||||
<TableCell>{task.max_retry}</TableCell>
|
<TableCell>{task.max_retry}</TableCell>
|
||||||
<TableCell>
|
<TableCell
|
||||||
<Button
|
align="center"
|
||||||
onClick={props.onRunClick}
|
className={clsx(
|
||||||
disabled={task.requestPending || props.allActionPending}
|
classes.actionCell,
|
||||||
|
props.showActions && classes.activeActionCell
|
||||||
|
)}
|
||||||
|
onMouseEnter={props.onActionCellEnter}
|
||||||
|
onMouseLeave={props.onActionCellLeave}
|
||||||
>
|
>
|
||||||
Run
|
{props.showActions ? (
|
||||||
</Button>
|
<React.Fragment>
|
||||||
<Button
|
<Tooltip title="Delete">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onDeleteClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<DeleteIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Kill">
|
||||||
|
<IconButton
|
||||||
onClick={props.onKillClick}
|
onClick={props.onKillClick}
|
||||||
disabled={task.requestPending || props.allActionPending}
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
Kill
|
<ArchiveIcon fontSize="small" />
|
||||||
</Button>
|
</IconButton>
|
||||||
<Button
|
</Tooltip>
|
||||||
disabled={task.requestPending}
|
<Tooltip title="Run">
|
||||||
onClick={props.onDeleteClick || props.allActionPending}
|
<IconButton
|
||||||
|
onClick={props.onRunClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
Delete
|
<PlayArrowIcon fontSize="small" />
|
||||||
</Button>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<IconButton size="small" onClick={props.onActionCellEnter}>
|
||||||
|
<MoreHorizIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow selected={props.isSelected}>
|
<TableRow selected={props.isSelected}>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { useState, useCallback } from "react";
|
import React, { useState, useCallback } 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";
|
||||||
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 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";
|
||||||
import TableRow from "@material-ui/core/TableRow";
|
import TableRow from "@material-ui/core/TableRow";
|
||||||
@ -12,6 +12,7 @@ import TableFooter from "@material-ui/core/TableFooter";
|
|||||||
import TablePagination from "@material-ui/core/TablePagination";
|
import TablePagination from "@material-ui/core/TablePagination";
|
||||||
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 Tooltip from "@material-ui/core/Tooltip";
|
||||||
import Checkbox from "@material-ui/core/Checkbox";
|
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";
|
||||||
@ -20,6 +21,7 @@ import DeleteIcon from "@material-ui/icons/Delete";
|
|||||||
import ArchiveIcon from "@material-ui/icons/Archive";
|
import ArchiveIcon from "@material-ui/icons/Archive";
|
||||||
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 MoreHorizIcon from "@material-ui/icons/MoreHoriz";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
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";
|
||||||
@ -46,6 +48,7 @@ import TableActions from "./TableActions";
|
|||||||
import { durationBefore, uuidPrefix } from "../utils";
|
import { durationBefore, uuidPrefix } from "../utils";
|
||||||
import { usePolling } from "../hooks";
|
import { usePolling } from "../hooks";
|
||||||
import { ScheduledTaskExtended } from "../reducers/tasksReducer";
|
import { ScheduledTaskExtended } from "../reducers/tasksReducer";
|
||||||
|
import { TableColumn } from "../types/table";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
table: {
|
table: {
|
||||||
@ -91,6 +94,7 @@ function ScheduledTasksTable(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 [activeTaskId, setActiveTaskId] = useState<string>("");
|
||||||
|
|
||||||
const handleChangePage = (
|
const handleChangePage = (
|
||||||
event: React.MouseEvent<HTMLButtonElement> | null,
|
event: React.MouseEvent<HTMLButtonElement> | null,
|
||||||
@ -161,12 +165,12 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const columns = [
|
const columns: TableColumn[] = [
|
||||||
{ label: "" },
|
{ key: "icon", label: "", align: "left" },
|
||||||
{ label: "ID" },
|
{ key: "id", label: "ID", align: "left" },
|
||||||
{ label: "Type" },
|
{ key: "type", label: "Type", align: "left" },
|
||||||
{ label: "Process In" },
|
{ key: "process_in", label: "Process In", align: "left" },
|
||||||
{ label: "Actions" },
|
{ key: "actions", label: "Actions", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
const rowCount = props.tasks.length;
|
const rowCount = props.tasks.length;
|
||||||
@ -233,7 +237,9 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
|
|||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{columns.map((col) => (
|
{columns.map((col) => (
|
||||||
<TableCell key={col.label}>{col.label}</TableCell>
|
<TableCell key={col.label} align={col.align}>
|
||||||
|
{col.label}
|
||||||
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@ -262,6 +268,9 @@ function ScheduledTasksTable(props: Props & ReduxProps) {
|
|||||||
onKillClick={() => {
|
onKillClick={() => {
|
||||||
props.killScheduledTaskAsync(queue, task.key);
|
props.killScheduledTaskAsync(queue, task.key);
|
||||||
}}
|
}}
|
||||||
|
onActionCellEnter={() => setActiveTaskId(task.id)}
|
||||||
|
onActionCellLeave={() => setActiveTaskId("")}
|
||||||
|
showActions={activeTaskId === task.id}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -295,6 +304,13 @@ const useRowStyles = makeStyles({
|
|||||||
borderBottom: "unset",
|
borderBottom: "unset",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
actionCell: {
|
||||||
|
width: "140px",
|
||||||
|
},
|
||||||
|
activeActionCell: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
@ -305,6 +321,9 @@ interface RowProps {
|
|||||||
onDeleteClick: () => void;
|
onDeleteClick: () => void;
|
||||||
onKillClick: () => void;
|
onKillClick: () => void;
|
||||||
allActionPending: boolean;
|
allActionPending: boolean;
|
||||||
|
showActions: boolean;
|
||||||
|
onActionCellEnter: () => void;
|
||||||
|
onActionCellLeave: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Row(props: RowProps) {
|
function Row(props: RowProps) {
|
||||||
@ -340,25 +359,50 @@ function Row(props: RowProps) {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>{task.type}</TableCell>
|
<TableCell>{task.type}</TableCell>
|
||||||
<TableCell>{durationBefore(task.next_process_at)}</TableCell>
|
<TableCell>{durationBefore(task.next_process_at)}</TableCell>
|
||||||
<TableCell>
|
<TableCell
|
||||||
<Button
|
align="center"
|
||||||
onClick={props.onRunClick}
|
className={clsx(
|
||||||
disabled={task.requestPending || props.allActionPending}
|
classes.actionCell,
|
||||||
|
props.showActions && classes.activeActionCell
|
||||||
|
)}
|
||||||
|
onMouseEnter={props.onActionCellEnter}
|
||||||
|
onMouseLeave={props.onActionCellLeave}
|
||||||
>
|
>
|
||||||
Run
|
{props.showActions ? (
|
||||||
</Button>
|
<React.Fragment>
|
||||||
<Button
|
<Tooltip title="Delete">
|
||||||
onClick={props.onKillClick}
|
<IconButton
|
||||||
disabled={task.requestPending || props.allActionPending}
|
|
||||||
>
|
|
||||||
Kill
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={props.onDeleteClick}
|
onClick={props.onDeleteClick}
|
||||||
disabled={task.requestPending || props.allActionPending}
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
Delete
|
<DeleteIcon fontSize="small" />
|
||||||
</Button>
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Kill">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onKillClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<ArchiveIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Run">
|
||||||
|
<IconButton
|
||||||
|
onClick={props.onRunClick}
|
||||||
|
disabled={task.requestPending || props.allActionPending}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<PlayArrowIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
<IconButton size="small" onClick={props.onActionCellEnter}>
|
||||||
|
<MoreHorizIcon fontSize="small" />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow selected={props.isSelected}>
|
<TableRow selected={props.isSelected}>
|
||||||
|
@ -11,7 +11,7 @@ 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";
|
||||||
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github";
|
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github";
|
||||||
import { SortDirection, ColumnConfig } from "../types/table";
|
import { SortDirection, SortableTableColumn } from "../types/table";
|
||||||
import TableSortLabel from "@material-ui/core/TableSortLabel";
|
import TableSortLabel from "@material-ui/core/TableSortLabel";
|
||||||
import { SchedulerEntry } from "../api";
|
import { SchedulerEntry } from "../api";
|
||||||
import { timeAgo, durationBefore } from "../utils";
|
import { timeAgo, durationBefore } from "../utils";
|
||||||
@ -41,7 +41,7 @@ enum SortBy {
|
|||||||
PrevEnqueue,
|
PrevEnqueue,
|
||||||
}
|
}
|
||||||
|
|
||||||
const colConfigs: ColumnConfig<SortBy>[] = [
|
const colConfigs: SortableTableColumn<SortBy>[] = [
|
||||||
{
|
{
|
||||||
label: "Entry ID",
|
label: "Entry ID",
|
||||||
key: "entry_id",
|
key: "entry_id",
|
||||||
|
@ -4,12 +4,17 @@ export enum SortDirection {
|
|||||||
Desc = "desc",
|
Desc = "desc",
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColumnConfig is a config for a table column.
|
// TableColumn is a config for a table column.
|
||||||
//
|
export interface TableColumn {
|
||||||
// T is the enum of sort keys.
|
|
||||||
export interface ColumnConfig<T> {
|
|
||||||
label: string;
|
|
||||||
key: string;
|
key: string;
|
||||||
sortBy: T;
|
label: string;
|
||||||
align: "left" | "right" | "center";
|
align: "left" | "right" | "center";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortableTableColumn is a config for a table column
|
||||||
|
// for table with sorting support.
|
||||||
|
//
|
||||||
|
// T is the enum of sort keys.
|
||||||
|
export interface SortableTableColumn<T> extends TableColumn {
|
||||||
|
sortBy: T;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user