(ui): Add renderRow prop to TasksTable component

This commit is contained in:
Ken Hibino 2022-04-03 06:40:46 -07:00
parent 6387d9cc67
commit 726d58fcda
2 changed files with 152 additions and 141 deletions

View File

@ -1,6 +1,18 @@
import React from "react";
import { connect, ConnectedProps } from "react-redux";
import TasksTable from "./TasksTable";
import { useHistory } from "react-router-dom";
import TableRow from "@material-ui/core/TableRow";
import TableCell from "@material-ui/core/TableCell";
import Checkbox from "@material-ui/core/Checkbox";
import IconButton from "@material-ui/core/IconButton";
import Tooltip from "@material-ui/core/Tooltip";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import DeleteIcon from "@material-ui/icons/Delete";
import ArchiveIcon from "@material-ui/icons/Archive";
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import SyntaxHighlighter from "./SyntaxHighlighter";
import TasksTable, { RowProps, useRowStyles } from "./TasksTable";
import {
batchDeleteScheduledTasksAsync,
batchRunScheduledTasksAsync,
@ -16,6 +28,8 @@ import {
import { taskRowsPerPageChange } from "../actions/settingsActions";
import { AppState } from "../store";
import { TableColumn } from "../types/table";
import { durationBefore, prettifyPayload, uuidPrefix } from "../utils";
import { taskDetailsPath } from "../paths";
function mapStateToProps(state: AppState) {
return {
@ -61,7 +75,116 @@ const columns: TableColumn[] = [
];
function ScheduledTasksTable(props: Props & ReduxProps) {
return <TasksTable taskState="scheduled" columns={columns} {...props} />;
return (
<TasksTable
taskState="scheduled"
columns={columns}
renderRow={(rowProps: RowProps) => <Row {...rowProps} />}
{...props}
/>
);
}
function Row(props: RowProps) {
const { task } = props;
const classes = useRowStyles();
const history = useHistory();
return (
<TableRow
key={task.id}
className={classes.root}
selected={props.isSelected}
onClick={() => history.push(taskDetailsPath(task.queue, task.id))}
>
{!window.READ_ONLY && (
<TableCell padding="checkbox" onClick={(e) => e.stopPropagation()}>
<IconButton>
<Checkbox
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
props.onSelectChange(event.target.checked)
}
checked={props.isSelected}
/>
</IconButton>
</TableCell>
)}
<TableCell component="th" scope="row" className={classes.idCell}>
<div className={classes.IdGroup}>
{uuidPrefix(task.id)}
<Tooltip title="Copy full ID to clipboard">
<IconButton
onClick={(e) => {
e.stopPropagation();
navigator.clipboard.writeText(task.id);
}}
size="small"
className={classes.copyButton}
>
<FileCopyOutlinedIcon fontSize="small" />
</IconButton>
</Tooltip>
</div>
</TableCell>
<TableCell>{task.type}</TableCell>
<TableCell>
<SyntaxHighlighter
language="json"
customStyle={{ margin: 0, maxWidth: 400 }}
>
{prettifyPayload(task.payload)}
</SyntaxHighlighter>
</TableCell>
<TableCell>{durationBefore(task.next_process_at)}</TableCell>
{!window.READ_ONLY && (
<TableCell
align="center"
className={classes.actionCell}
onMouseEnter={props.onActionCellEnter}
onMouseLeave={props.onActionCellLeave}
onClick={(e) => e.stopPropagation()}
>
{props.showActions ? (
<React.Fragment>
<Tooltip title="Delete">
<IconButton
onClick={props.onDeleteClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<DeleteIcon fontSize="small" />
</IconButton>
</Tooltip>
<Tooltip title="Archive">
<IconButton
onClick={props.onArchiveClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<ArchiveIcon fontSize="small" />
</IconButton>
</Tooltip>
<Tooltip title="Run">
<IconButton
onClick={props.onRunClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<PlayArrowIcon fontSize="small" />
</IconButton>
</Tooltip>
</React.Fragment>
) : (
<IconButton size="small" onClick={props.onActionCellEnter}>
<MoreHorizIcon fontSize="small" />
</IconButton>
)}
</TableCell>
)}
</TableRow>
);
}
export default connector(ScheduledTasksTable);

View File

@ -1,5 +1,4 @@
import React, { useState, useCallback } from "react";
import { useHistory } from "react-router-dom";
import { makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
@ -10,26 +9,20 @@ import TableRow from "@material-ui/core/TableRow";
import TableFooter from "@material-ui/core/TableFooter";
import TablePagination from "@material-ui/core/TablePagination";
import Paper from "@material-ui/core/Paper";
import Tooltip from "@material-ui/core/Tooltip";
import Checkbox from "@material-ui/core/Checkbox";
import IconButton from "@material-ui/core/IconButton";
import PlayArrowIcon from "@material-ui/icons/PlayArrow";
import DeleteIcon from "@material-ui/icons/Delete";
import ArchiveIcon from "@material-ui/icons/Archive";
import MoreHorizIcon from "@material-ui/icons/MoreHoriz";
import Alert from "@material-ui/lab/Alert";
import AlertTitle from "@material-ui/lab/AlertTitle";
import SyntaxHighlighter from "./SyntaxHighlighter";
import TablePaginationActions, {
rowsPerPageOptions,
} from "./TablePaginationActions";
import TableActions from "./TableActions";
import { durationBefore, uuidPrefix, prettifyPayload } from "../utils";
import { usePolling } from "../hooks";
import { TaskInfoExtended } from "../reducers/tasksReducer";
import { TableColumn } from "../types/table";
import { taskDetailsPath } from "../paths";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import { PaginationOptions } from "../api";
import { TaskState } from "../types/taskState";
@ -74,6 +67,8 @@ interface Props {
runTask?: (qname: string, taskId: string) => Promise<void>;
archiveTask?: (qname: string, taskId: string) => Promise<void>;
taskRowsPerPageChange: (n: number) => void;
renderRow: (rowProps: RowProps) => JSX.Element;
}
export default function TasksTable(props: Props) {
@ -250,39 +245,33 @@ export default function TasksTable(props: Props) {
</TableRow>
</TableHead>
<TableBody>
{props.tasks.map((task) => (
<Row
key={task.id}
task={task}
allActionPending={props.allActionPending}
isSelected={selectedIds.includes(task.id)}
onSelectChange={(checked: boolean) => {
{props.tasks.map((task) => {
return props.renderRow({
key: task.id,
task: task,
allActionPending: props.allActionPending,
isSelected: selectedIds.includes(task.id),
onSelectChange: (checked: boolean) => {
if (checked) {
setSelectedIds(selectedIds.concat(task.id));
} else {
setSelectedIds(selectedIds.filter((id) => id !== task.id));
}
}}
onRunClick={
props.runTask
? createTaskAction(props.runTask, task.id)
: undefined
}
onDeleteClick={
props.deleteTask
? createTaskAction(props.deleteTask, task.id)
: undefined
}
onArchiveClick={
props.archiveTask
? createTaskAction(props.archiveTask, task.id)
: undefined
}
onActionCellEnter={() => setActiveTaskId(task.id)}
onActionCellLeave={() => setActiveTaskId("")}
showActions={activeTaskId === task.id}
/>
))}
},
onRunClick: props.runTask
? createTaskAction(props.runTask, task.id)
: undefined,
onDeleteClick: props.deleteTask
? createTaskAction(props.deleteTask, task.id)
: undefined,
onArchiveClick: props.archiveTask
? createTaskAction(props.archiveTask, task.id)
: undefined,
onActionCellEnter: () => setActiveTaskId(task.id),
onActionCellLeave: () => setActiveTaskId(""),
showActions: activeTaskId === task.id,
});
})}
</TableBody>
<TableFooter>
<TableRow>
@ -309,7 +298,7 @@ export default function TasksTable(props: Props) {
);
}
const useRowStyles = makeStyles((theme) => ({
export const useRowStyles = makeStyles((theme) => ({
root: {
cursor: "pointer",
"& #copy-button": {
@ -347,7 +336,8 @@ const useRowStyles = makeStyles((theme) => ({
},
}));
interface RowProps {
export interface RowProps {
key: string;
task: TaskInfoExtended;
isSelected: boolean;
onSelectChange: (checked: boolean) => void;
@ -359,105 +349,3 @@ interface RowProps {
onActionCellEnter: () => void;
onActionCellLeave: () => void;
}
function Row(props: RowProps) {
const { task } = props;
const classes = useRowStyles();
const history = useHistory();
return (
<TableRow
key={task.id}
className={classes.root}
selected={props.isSelected}
onClick={() => history.push(taskDetailsPath(task.queue, task.id))}
>
{!window.READ_ONLY && (
<TableCell padding="checkbox" onClick={(e) => e.stopPropagation()}>
<IconButton>
<Checkbox
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
props.onSelectChange(event.target.checked)
}
checked={props.isSelected}
/>
</IconButton>
</TableCell>
)}
<TableCell component="th" scope="row" className={classes.idCell}>
<div className={classes.IdGroup}>
{uuidPrefix(task.id)}
<Tooltip title="Copy full ID to clipboard">
<IconButton
onClick={(e) => {
e.stopPropagation();
navigator.clipboard.writeText(task.id);
}}
size="small"
className={classes.copyButton}
>
<FileCopyOutlinedIcon fontSize="small" />
</IconButton>
</Tooltip>
</div>
</TableCell>
<TableCell>{task.type}</TableCell>
<TableCell>
<SyntaxHighlighter
language="json"
customStyle={{ margin: 0, maxWidth: 400 }}
>
{prettifyPayload(task.payload)}
</SyntaxHighlighter>
</TableCell>
<TableCell>{durationBefore(task.next_process_at)}</TableCell>
{!window.READ_ONLY && (
<TableCell
align="center"
className={classes.actionCell}
onMouseEnter={props.onActionCellEnter}
onMouseLeave={props.onActionCellLeave}
onClick={(e) => e.stopPropagation()}
>
{props.showActions ? (
<React.Fragment>
<Tooltip title="Delete">
<IconButton
onClick={props.onDeleteClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<DeleteIcon fontSize="small" />
</IconButton>
</Tooltip>
<Tooltip title="Archive">
<IconButton
onClick={props.onArchiveClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<ArchiveIcon fontSize="small" />
</IconButton>
</Tooltip>
<Tooltip title="Run">
<IconButton
onClick={props.onRunClick}
disabled={task.requestPending || props.allActionPending}
size="small"
className={classes.actionButton}
>
<PlayArrowIcon fontSize="small" />
</IconButton>
</Tooltip>
</React.Fragment>
) : (
<IconButton size="small" onClick={props.onActionCellEnter}>
<MoreHorizIcon fontSize="small" />
</IconButton>
)}
</TableCell>
)}
</TableRow>
);
}