From 4179d00b7b374319368fa6e72de13fa4b7626065 Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 27 Jan 2021 22:40:34 -0800 Subject: [PATCH] Change values displayed in QueuesOverviewTable --- ui/src/components/QueuesOverviewTable.tsx | 378 ++++++++++------------ 1 file changed, 168 insertions(+), 210 deletions(-) diff --git a/ui/src/components/QueuesOverviewTable.tsx b/ui/src/components/QueuesOverviewTable.tsx index 73e7cce..c964897 100644 --- a/ui/src/components/QueuesOverviewTable.tsx +++ b/ui/src/components/QueuesOverviewTable.tsx @@ -8,7 +8,6 @@ import TableCell from "@material-ui/core/TableCell"; import TableContainer from "@material-ui/core/TableContainer"; import TableHead from "@material-ui/core/TableHead"; import TableRow from "@material-ui/core/TableRow"; -import TableFooter from "@material-ui/core/TableFooter"; import TableSortLabel from "@material-ui/core/TableSortLabel"; import IconButton from "@material-ui/core/IconButton"; import Tooltip from "@material-ui/core/Tooltip"; @@ -20,34 +19,19 @@ import DeleteQueueConfirmationDialog from "./DeleteQueueConfirmationDialog"; import { Queue } from "../api"; import { queueDetailsPath } from "../paths"; import { SortDirection, SortableTableColumn } from "../types/table"; +import prettyBytes from "pretty-bytes"; +import { percentage } from "../utils"; const useStyles = makeStyles((theme) => ({ table: { minWidth: 650, }, - linkCell: { - textDecoration: "none", - color: theme.palette.text.primary, - }, - footerCell: { - fontWeight: 600, - fontSize: "0.875rem", - borderBottom: "none", - }, - boldCell: { - fontWeight: 600, - }, fixedCell: { position: "sticky", zIndex: 1, left: 0, background: theme.palette.background.paper, }, - actionIconsContainer: { - display: "flex", - justifyContent: "center", - minWidth: "100px", - }, })); interface QueueWithMetadata extends Queue { @@ -63,32 +47,42 @@ interface Props { enum SortBy { Queue, + State, Size, - Active, - Pending, - Scheduled, - Retry, - Archived, + MemoryUsage, + Processed, + Failed, + ErrorRate, None, // no sort support } const colConfigs: SortableTableColumn[] = [ { label: "Queue", key: "queue", sortBy: SortBy.Queue, align: "left" }, - { label: "Size", key: "size", sortBy: SortBy.Size, align: "right" }, - { label: "Active", key: "active", sortBy: SortBy.Active, align: "right" }, - { label: "Pending", key: "pending", sortBy: SortBy.Pending, align: "right" }, + { label: "State", key: "state", sortBy: SortBy.State, align: "left" }, { - label: "Scheduled", - key: "scheduled", - sortBy: SortBy.Scheduled, + label: "Size", + key: "size", + sortBy: SortBy.Size, align: "right", }, - { label: "Retry", key: "retry", sortBy: SortBy.Retry, align: "right" }, { - label: "Archived", - key: "archived", - sortBy: SortBy.Archived, + label: "Memory usage", + key: "memory_usage", + sortBy: SortBy.MemoryUsage, + align: "right", + }, + { + label: "Processed", + key: "processed", + sortBy: SortBy.Processed, + align: "right", + }, + { label: "Failed", key: "failed", sortBy: SortBy.Failed, align: "right" }, + { + label: "Error rate", + key: "error_rate", + sortBy: SortBy.ErrorRate, align: "right", }, { label: "Actions", key: "actions", sortBy: SortBy.None, align: "center" }, @@ -109,12 +103,9 @@ export default function QueuesOverviewTable(props: Props) { const classes = useStyles(); const [sortBy, setSortBy] = useState(SortBy.Queue); const [sortDir, setSortDir] = useState(SortDirection.Asc); - const [activeRowIndex, setActiveRowIndex] = useState(-1); const [queueToDelete, setQueueToDelete] = useState( null ); - const total = getAggregateCounts(props.queues); - const createSortClickHandler = (sortKey: SortBy) => (e: React.MouseEvent) => { if (sortKey === sortBy) { // Toggle sort direction. @@ -134,29 +125,31 @@ export default function QueuesOverviewTable(props: Props) { if (q1.queue === q2.queue) return 0; isQ1Smaller = q1.queue < q2.queue; break; + case SortBy.State: + if (q1.paused === q2.paused) return 0; + isQ1Smaller = !q1.paused; + break; case SortBy.Size: if (q1.size === q2.size) return 0; isQ1Smaller = q1.size < q2.size; break; - case SortBy.Active: - if (q1.active === q2.active) return 0; - isQ1Smaller = q1.active < q2.active; + case SortBy.MemoryUsage: + if (q1.memory_usage_bytes === q2.memory_usage_bytes) return 0; + isQ1Smaller = q1.memory_usage_bytes < q2.memory_usage_bytes; break; - case SortBy.Pending: - if (q1.pending === q2.pending) return 0; - isQ1Smaller = q1.pending < q2.pending; + case SortBy.Processed: + if (q1.processed === q2.processed) return 0; + isQ1Smaller = q1.processed < q2.processed; break; - case SortBy.Scheduled: - if (q1.scheduled === q2.scheduled) return 0; - isQ1Smaller = q1.scheduled < q2.scheduled; + case SortBy.Failed: + if (q1.failed === q2.failed) return 0; + isQ1Smaller = q1.failed < q2.failed; break; - case SortBy.Retry: - if (q1.retry === q2.retry) return 0; - isQ1Smaller = q1.retry < q2.retry; - break; - case SortBy.Archived: - if (q1.archived === q2.archived) return 0; - isQ1Smaller = q1.archived < q2.archived; + case SortBy.ErrorRate: + const q1ErrorRate = q1.failed / q1.processed; + const q2ErrorRate = q2.failed / q2.processed; + if (q1ErrorRate === q2ErrorRate) return 0; + isQ1Smaller = q1ErrorRate < q2ErrorRate; break; default: // eslint-disable-next-line no-throw-literal @@ -201,141 +194,15 @@ export default function QueuesOverviewTable(props: Props) { - {sortQueues(props.queues, cmpFunc).map((q, i) => ( - setActiveRowIndex(i)} - onMouseLeave={() => setActiveRowIndex(-1)} - > - - - {q.queue} - {q.paused ? " (paused)" : ""} - - - - {q.size} - - - - {q.active} - - - - - {q.pending} - - - - - {q.scheduled} - - - - - {q.retry} - - - - - {q.archived} - - - -
- {activeRowIndex === i ? ( - - {q.paused ? ( - - props.onResumeClick(q.queue)} - disabled={q.requestPending} - size="small" - > - - - - ) : ( - - props.onPauseClick(q.queue)} - disabled={q.requestPending} - size="small" - > - - - - )} - - setQueueToDelete(q)} - size="small" - > - - - - - ) : ( - - - - )} -
-
-
+ {sortQueues(props.queues, cmpFunc).map((q) => ( + props.onPauseClick(q.queue)} + onResumeClick={() => props.onResumeClick(q.queue)} + onDeleteClick={() => setQueueToDelete(q)} + /> ))}
- - - - Total - - - {total.size} - - - {total.active} - - - {total.pending} - - - {total.scheduled} - - - {total.retry} - - - {total.archived} - - - ({ + row: { + "&:last-child td": { + borderBottomWidth: 0, + }, + "&:last-child th": { + borderBottomWidth: 0, + }, + }, + linkText: { + textDecoration: "none", + color: theme.palette.text.primary, + "&:hover": { + textDecoration: "underline", + }, + }, + textGreen: { + color: theme.palette.success.dark, + }, + textRed: { + color: theme.palette.error.dark, + }, + boldCell: { + fontWeight: 600, + }, + fixedCell: { + position: "sticky", + zIndex: 1, + left: 0, + background: theme.palette.background.paper, + }, + actionIconsContainer: { + display: "flex", + justifyContent: "center", + minWidth: "100px", + }, +})); + +interface RowProps { + queue: QueueWithMetadata; + onPauseClick: () => void; + onResumeClick: () => void; + onDeleteClick: () => void; } -function getAggregateCounts(queues: Queue[]): AggregateCounts { - let total = { - size: 0, - active: 0, - pending: 0, - scheduled: 0, - retry: 0, - archived: 0, - }; - queues.forEach((q) => { - total.size += q.size; - total.active += q.active; - total.pending += q.pending; - total.scheduled += q.scheduled; - total.retry += q.retry; - total.archived += q.archived; - }); - return total; +function Row(props: RowProps) { + const classes = useRowStyles(); + const { queue: q } = props; + const [showIcons, setShowIcons] = useState(false); + return ( + + + + {q.queue} + + + + {q.paused ? ( + paused + ) : ( + run + )} + + {q.size} + {prettyBytes(q.memory_usage_bytes)} + {q.processed} + {q.failed} + {percentage(q.failed, q.processed)} + setShowIcons(true)} + onMouseLeave={() => setShowIcons(false)} + > +
+ {showIcons ? ( + + {q.paused ? ( + + + + + + ) : ( + + + + + + )} + + + + + + + ) : ( + + + + )} +
+
+
+ ); }