Skip to content

Commit

Permalink
Merge pull request #2640 from GreenAsJade/cm_info_in_report_center
Browse files Browse the repository at this point in the history
Show some CM overall usage graphs in report center
  • Loading branch information
anoek authored Mar 24, 2024
2 parents b329b92 + 8340f71 commit f0a6414
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 7 deletions.
24 changes: 17 additions & 7 deletions src/views/ReportsCenter/ReportsCenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ import { report_categories, ReportDescription } from "Report";
import { report_manager } from "report_manager";
import Select from "react-select";
import { _ } from "translate";
import { usePreference } from "preferences";
import { community_mod_has_power } from "report_util";

import { ViewReport } from "./ViewReport";
import { ReportsCenterSettings } from "./ReportsCenterSettings";
import { ReportsCenterHistory } from "./ReportsCenterHistory";
import { usePreference } from "preferences";
import { community_mod_has_power } from "report_util";
import { ReportsCenterCMInfo } from "./ReportsCenterCMInfo";

interface OtherView {
special: string;
title: string;
show_cm: boolean;
}

const categories: (ReportDescription | OtherView)[] = [
Expand All @@ -49,9 +52,10 @@ const categories: (ReportDescription | OtherView)[] = [
},
])
.concat([
{ special: "hr", title: "" },
{ special: "history", title: "History" },
{ special: "settings", title: "Settings" },
{ special: "hr", title: "", show_cm: true },
{ special: "history", title: "History", show_cm: false },
{ special: "cm", title: "Community Moderation", show_cm: true },
{ special: "settings", title: "Settings", show_cm: false },
]);

const category_priorities: { [type: string]: number } = {};
Expand Down Expand Up @@ -139,8 +143,11 @@ export function ReportsCenter(): JSX.Element | null {
const visible_categories = user.is_moderator
? categories
: // community moderators supported report types
report_categories.filter((category) =>
community_mod_has_power(user.moderator_powers, category.type),
categories.filter(
(category) =>
("special" in category && category.show_cm) ||
(!("special" in category) &&
community_mod_has_power(user.moderator_powers, category.type)),
);

return (
Expand Down Expand Up @@ -220,6 +227,7 @@ export function ReportsCenter(): JSX.Element | null {
return <hr key={idx} />;
case "settings":
case "history":
case "cm":
return (
<div
key={report_type.special}
Expand Down Expand Up @@ -295,6 +303,8 @@ export function ReportsCenter(): JSX.Element | null {
<ReportsCenterSettings />
) : category === "history" ? (
<ReportsCenterHistory />
) : category === "cm" ? (
<ReportsCenterCMInfo />
) : category === "hr" ? null : (
<ViewReport
reports={
Expand Down
8 changes: 8 additions & 0 deletions src/views/ReportsCenter/ReportsCenterCMInfo.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.ReportsCenterCMInfo {
width: 100%;
margin-left: 2rem;

.aggregate-vote-activity-graph {
height: 200px;
}
}
154 changes: 154 additions & 0 deletions src/views/ReportsCenter/ReportsCenterCMInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright (C) Online-Go.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, { useEffect } from "react";
import { get } from "requests";
import * as data from "data";

import { ResponsiveLine } from "@nivo/line";

interface ReportCount {
date: string;
escalated: number;
consensus: number;
non_consensus: number;
}

interface AggregatedReportsData {
[reportType: string]: ReportCount[];
}

interface VoteActivityGraphProps {
vote_data: ReportCount[];
}

function round_date(the_date: Date): Date {
return new Date(the_date.setHours(0, 0, 0, 0));
}

const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => {
const chart_data = React.useMemo(
() => [
{
id: "escalated",
data:
vote_data?.map((day) => ({
x: round_date(new Date(day.date)),
y: day.escalated,
})) ?? [],
},
{
id: "consensus",
data:
vote_data?.map((day) => ({
x: round_date(new Date(day.date)),
y: day.consensus,
})) ?? [],
},
{
id: "non-consensus",
data:
vote_data?.map((day) => ({
x: round_date(new Date(day.date)),
y: day.non_consensus,
})) ?? [],
},
],
[vote_data],
);

const chart_theme =
data.get("theme") === "light" // (Accessible theme TBD - this assumes accessible is dark for now)
? {
/* nivo defaults work well with our light theme */
}
: {
text: { fill: "#FFFFFF" },
tooltip: { container: { color: "#111111" } },
grid: { line: { stroke: "#444444" } },
};

if (!chart_data[0].data.length) {
return <div className="aggregate-vote-activity-graph">No activity yet</div>;
}

console.log(chart_data);
return (
<div className="aggregate-vote-activity-graph">
<ResponsiveLine
data={chart_data}
animate
curve="monotoneX"
enablePoints={false}
enableSlices="x"
axisBottom={{
format: "%d %b %g",
tickValues: "every month",
}}
xFormat="time:%Y-%m-%d"
xScale={{
format: "%Y-%m-%d",
precision: "day",
type: "time",
useUTC: false,
}}
axisLeft={{
tickValues: 6,
}}
margin={{
bottom: 40,
left: 60,
right: 20,
top: 5,
}}
theme={chart_theme}
/>
</div>
);
};

export function ReportsCenterCMInfo(): JSX.Element {
const [vote_data, setVoteData] = React.useState<AggregatedReportsData | null>(null);

// Data fetch
useEffect(() => {
const fetchData = async () => {
const response = await get(`moderation/cm_vote_summary`);
const fetchedData: AggregatedReportsData = await response;
setVoteData(fetchedData);
};

fetchData().catch((err) => {
console.error(err);
});
}, []);

if (!vote_data) {
return <div>Loading...</div>;
}

return (
<div className="ReportsCenterCMInfo">
{["overall", "escaping", "stalling", "score_cheating"].map((report_type) => (
<>
<h3>{report_type}</h3>
<CMVoteActivityGraph vote_data={vote_data[report_type]} key={report_type} />
</>
))}
</div>
);
}

0 comments on commit f0a6414

Please sign in to comment.