From e44abbf12caa12f34f71543c0bbeaa0f1c52f77c Mon Sep 17 00:00:00 2001 From: GreenAsJade Date: Fri, 29 Mar 2024 10:28:02 +1030 Subject: [PATCH] Make cm graphs by week, and tidy. --- .../ReportsCenter/ReportsCenterCMInfo.tsx | 83 +++++++++++++------ src/views/User/ActivityCard.tsx | 6 +- src/views/User/VoteActivityGraph.tsx | 47 +++++++---- 3 files changed, 94 insertions(+), 42 deletions(-) diff --git a/src/views/ReportsCenter/ReportsCenterCMInfo.tsx b/src/views/ReportsCenter/ReportsCenterCMInfo.tsx index 6af2af239a..f1d85a624d 100644 --- a/src/views/ReportsCenter/ReportsCenterCMInfo.tsx +++ b/src/views/ReportsCenter/ReportsCenterCMInfo.tsx @@ -35,40 +35,66 @@ interface AggregatedReportsData { interface VoteActivityGraphProps { vote_data: ReportCount[]; } - +/* function round_date(the_date: Date): Date { return new Date(the_date.setHours(0, 0, 0, 0)); } +*/ +function startOfWeek(the_date: Date): Date { + const date = new Date(the_date); + const day = date.getDay(); // Get current day of week (0 is Sunday) + const diff = date.getDate() - day; // Calculate difference to the start of the week + + return new Date(date.setDate(diff)); +} const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { + const aggregateDataByWeek = React.useMemo(() => { + const aggregated: { + [key: string]: { escalated: number; consensus: number; non_consensus: number }; + } = {}; + + vote_data.forEach((entry) => { + const weekStart = startOfWeek(new Date(entry.date)).toISOString().slice(0, 10); // Get week start and convert to ISO string for key + if (!aggregated[weekStart]) { + aggregated[weekStart] = { escalated: 0, consensus: 0, non_consensus: 0 }; + } + aggregated[weekStart].escalated += entry.escalated; + aggregated[weekStart].consensus += entry.consensus; + aggregated[weekStart].non_consensus += entry.non_consensus; + }); + + return Object.entries(aggregated).map(([date, counts]) => ({ + date, + ...counts, + })); + }, [vote_data]); + const chart_data = React.useMemo( () => [ { id: "escalated", - data: - vote_data?.map((day) => ({ - x: round_date(new Date(day.date)), - y: day.escalated, - })) ?? [], + data: aggregateDataByWeek.map((week) => ({ + x: week.date, + y: week.escalated, + })), }, { id: "consensus", - data: - vote_data?.map((day) => ({ - x: round_date(new Date(day.date)), - y: day.consensus, - })) ?? [], + data: aggregateDataByWeek.map((week) => ({ + x: week.date, + y: week.consensus, + })), }, { id: "non-consensus", - data: - vote_data?.map((day) => ({ - x: round_date(new Date(day.date)), - y: day.non_consensus, - })) ?? [], + data: aggregateDataByWeek.map((week) => ({ + x: week.date, + y: week.non_consensus, + })), }, ], - [vote_data], + [aggregateDataByWeek], ); const chart_theme = @@ -82,29 +108,36 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { grid: { line: { stroke: "#444444" } }, }; + const line_colors = { + consensus: "green", + "non-consensus": "red", + escalated: "orange", + }; + if (!chart_data[0].data.length) { return
No activity yet
; } - console.log(chart_data); return (
line_colors[id as keyof typeof line_colors]} animate curve="monotoneX" enablePoints={false} enableSlices="x" axisBottom={{ format: "%d %b %g", - tickValues: "every month", + tickValues: "every week", }} xFormat="time:%Y-%m-%d" xScale={{ - format: "%Y-%m-%d", - precision: "day", type: "time", + min: "2023-12-31", + format: "%Y-%m-%d", useUTC: false, + precision: "day", }} axisLeft={{ tickValues: 6, @@ -112,7 +145,7 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { margin={{ bottom: 40, left: 60, - right: 20, + right: 40, top: 5, }} theme={chart_theme} @@ -144,10 +177,10 @@ export function ReportsCenterCMInfo(): JSX.Element { return (
{["overall", "escaping", "stalling", "score_cheating"].map((report_type) => ( - <> +

{report_type}

- - + +
))}
); diff --git a/src/views/User/ActivityCard.tsx b/src/views/User/ActivityCard.tsx index 301088297b..03fa4b279c 100644 --- a/src/views/User/ActivityCard.tsx +++ b/src/views/User/ActivityCard.tsx @@ -156,7 +156,7 @@ export function ActivityCard({
{pgettext( "header for a graph showing how often the moderator voted with the others", - "consensus votes", + "consensus votes (by week)", )}
@@ -178,7 +178,7 @@ export function ActivityCard({ ), ) .map(([report_type, _flag]) => ( - <> +
{interpolate( pgettext( @@ -192,7 +192,7 @@ export function ActivityCard({ user_id={user.id} report_type={report_type as ReportType} /> - +
))} )} diff --git a/src/views/User/VoteActivityGraph.tsx b/src/views/User/VoteActivityGraph.tsx index 4bc88afb30..368490b7b7 100644 --- a/src/views/User/VoteActivityGraph.tsx +++ b/src/views/User/VoteActivityGraph.tsx @@ -35,24 +35,42 @@ interface VoteActivityGraphProps { vote_data: ModeratorVoteCountData; } -function round_date(the_date: Date): Date { - return new Date(the_date.setHours(0, 0, 0, 0)); +function startOfWeek(the_date: Date): Date { + const date = new Date(the_date); + const day = date.getDay(); // Get current day of week (0 is Sunday) + const diff = date.getDate() - day; + return new Date(date.setDate(diff)); } const VoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { - const chart_data = React.useMemo( - () => [ + const chart_data = React.useMemo(() => { + const aggregatedByWeek: { + [key: string]: number; + } = {}; + + vote_data.counts.forEach((day) => { + const weekStart = startOfWeek(new Date(day.date)).toISOString().slice(0, 10); // Format as YYYY-MM-DD + if (!aggregatedByWeek[weekStart]) { + aggregatedByWeek[weekStart] = 0; + } + aggregatedByWeek[weekStart] += day.count; + }); + + const min_date = new Date("2024-02-01"); + const data = Object.entries(aggregatedByWeek) + .filter(([date, _count]) => new Date(date) >= min_date) + .map(([date, count]) => ({ + x: date, // x-axis will use the week start date + y: count, // y-axis will use the aggregated count + })); + + return [ { id: "votes", - data: - vote_data?.counts.map((day) => ({ - x: round_date(new Date(day.date)), - y: day.count, - })) ?? [], + data, }, - ], - [vote_data], - ); + ]; + }, [vote_data]); const chart_theme = data.get("theme") === "light" // (Accessible theme TBD - this assumes accessible is dark for now) @@ -79,10 +97,11 @@ const VoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { enableSlices="x" axisBottom={{ format: "%d %b %g", - tickValues: "every month", + tickValues: "every 2 weeks", }} xFormat="time:%Y-%m-%d" xScale={{ + min: "2024-02-01", format: "%Y-%m-%d", precision: "day", type: "time", @@ -95,7 +114,7 @@ const VoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { margin={{ bottom: 40, left: 60, - right: 20, + right: 40, top: 5, }} theme={chart_theme}