diff --git a/ui/src/components/DailyStatsChart.tsx b/ui/src/components/DailyStatsChart.tsx new file mode 100644 index 0000000..4beb756 --- /dev/null +++ b/ui/src/components/DailyStatsChart.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { + LineChart, + Line, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + Legend, + ResponsiveContainer, +} from "recharts"; +import { useTheme, Theme } from "@material-ui/core/styles"; +import { DailyStat } from "../api"; + +interface Props { + data: { [qname: string]: DailyStat[] }; + numDays: number; +} + +interface ChartData { + succeeded: number; + failed: number; + date: string; +} + +export default function DailyStatsChart(props: Props) { + const data = makeChartData(props.data, props.numDays); + const theme = useTheme(); + return ( + + + + + + + + + + + + ); +} + +function makeChartData( + queueStats: { [qname: string]: DailyStat[] }, + numDays: number +): ChartData[] { + const dataByDate: { [date: string]: ChartData } = {}; + for (const qname in queueStats) { + for (const stat of queueStats[qname]) { + if (!dataByDate.hasOwnProperty(stat.date)) { + dataByDate[stat.date] = { succeeded: 0, failed: 0, date: stat.date }; + } + dataByDate[stat.date].succeeded += stat.processed - stat.failed; + dataByDate[stat.date].failed += stat.failed; + } + } + return Object.values(dataByDate).sort(sortByDate).slice(-numDays); +} + +function sortByDate(x: ChartData, y: ChartData): number { + return Date.parse(x.date) - Date.parse(y.date); +} diff --git a/ui/src/views/DashboardView.tsx b/ui/src/views/DashboardView.tsx index ca668cc..b8ffaca 100644 --- a/ui/src/views/DashboardView.tsx +++ b/ui/src/views/DashboardView.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { connect, ConnectedProps } from "react-redux"; import Container from "@material-ui/core/Container"; import { makeStyles } from "@material-ui/core/styles"; @@ -19,8 +19,8 @@ import ProcessedTasksChart from "../components/ProcessedTasksChart"; import QueuesOverviewTable from "../components/QueuesOverviewTable"; import Tooltip from "../components/Tooltip"; import SplitButton from "../components/SplitButton"; -import { getCurrentUTCDate } from "../utils"; import { usePolling } from "../hooks"; +import DailyStatsChart from "../components/DailyStatsChart"; const useStyles = makeStyles((theme) => ({ container: { @@ -68,6 +68,7 @@ function mapStateToProps(state: AppState) { requestPending: q.requestPending, })), pollInterval: state.settings.pollInterval, + queueStats: state.queueStats.data, }; } @@ -83,9 +84,15 @@ const connector = connect(mapStateToProps, mapDispatchToProps); type Props = ConnectedProps; +type DailyStatsKey = "today" | "last-7d" | "last-30d" | "last-90d"; +const initialStatsKey = "last-7d"; + function DashboardView(props: Props) { const { pollInterval, listQueuesAsync, queues, listQueueStatsAsync } = props; const classes = useStyles(); + const [dailyStatsKey, setDailyStatsKey] = useState( + initialStatsKey + ); usePolling(listQueuesAsync, pollInterval); @@ -161,16 +168,15 @@ function DashboardView(props: Props) { title={
- Total number of tasks processed today ( - {getCurrentUTCDate()} UTC) + Total number of tasks processed in a given day (UTC)
Succeeded: number of tasks successfully - processed from the queue + processed
Failed: number of tasks failed to be - processed from the queue + processed
} @@ -186,13 +192,24 @@ function DashboardView(props: Props) { { label: "Last 30d", key: "last-30d" }, { label: "Last 90d", key: "last-90d" }, ]} - initialSelectedKey="today" - onSelect={(key) => console.log("option selected:", key)} + initialSelectedKey={initialStatsKey} + onSelect={(key) => setDailyStatsKey(key as DailyStatsKey)} />
- + {dailyStatsKey === "today" && ( + + )} + {dailyStatsKey === "last-7d" && ( + + )} + {dailyStatsKey === "last-30d" && ( + + )} + {dailyStatsKey === "last-90d" && ( + + )}