From 9705ed3366192702a0209b18d595202de9a5da7d Mon Sep 17 00:00:00 2001 From: GreenAsJade Date: Mon, 5 Aug 2024 17:01:24 +0930 Subject: [PATCH] Give moderators a view of the outcomes over time for each CM. --- package.json | 3 +- src/ogs.styl | 61 ++++++++++++++++ .../ReportsCenter/ReportsCenterCMInfo.styl | 9 +++ .../ReportsCenter/ReportsCenterCMInfo.tsx | 71 ++++++++++++++----- yarn.lock | 13 ++++ 5 files changed, 139 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 3e1c87d2be..20876166b2 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@google-cloud/translate": "^7.0.3", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.2.0", + "@tony.ganchev/eslint-plugin-header": "^3.1.2", "@types/jest": "^29.5.0", "@types/react-linkify": "^1.0.4", "@types/testing-library__jest-dom": "^5.14.5", @@ -49,7 +50,6 @@ "deepl-node": "^1.10.1", "eslint": "^9.7.0", "eslint-config-prettier": "^9.1.0", - "@tony.ganchev/eslint-plugin-header": "^3.1.2", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsdoc": "^46.9.1", "eslint-plugin-prefer-arrow": "^1.2.3", @@ -142,6 +142,7 @@ "react-split": "^2.0.9", "react-switch": "^5.0.1", "react-table": "^6.10.0", + "react-tabs": "^6.0.2", "react-virtualized": "^9.22.3", "redux": "^3.7.2", "sanitize-html": "^2.12.1", diff --git a/src/ogs.styl b/src/ogs.styl index f072aaa765..1bedd340d6 100644 --- a/src/ogs.styl +++ b/src/ogs.styl @@ -528,3 +528,64 @@ nowrap() @require '../node_modules/react-table/react-table.css'; @require '../node_modules/react-dynamic-help/lib/es5/DynamicHelp.css'; + +// @require '../node_modules/react-tabs/style/react-tabs.css'; +// +// Put our theming into react-tabs css: copied from them and modified + +.react-tabs { + -webkit-tap-highlight-color: transparent; +} + +.react-tabs__tab-list { + border-bottom: 1px solid #aaa; + margin: 0 0 10px; + padding: 0; +} + +.react-tabs__tab { + display: inline-block; + border: 1px solid transparent; + border-bottom: none; + bottom: -1px; + position: relative; + list-style: none; + padding: 6px 12px; + cursor: pointer; +} + +.react-tabs__tab--selected { + border-color: #aaa; + themed background bg; + themed color fg; + border-radius: 5px 5px 0 0; +} + +.react-tabs__tab--disabled { + color: GrayText; + cursor: default; +} + +.react-tabs__tab:focus { + outline: none; +} + +.react-tabs__tab:focus:after { + content: ''; + position: absolute; + height: 5px; + left: -4px; + right: -4px; + bottom: -5px; + themed background bg; +} + + +.react-tabs__tab-panel { + display: none; +} + +.react-tabs__tab-panel--selected { + display: block; + padding: 10px; +} \ No newline at end of file diff --git a/src/views/ReportsCenter/ReportsCenterCMInfo.styl b/src/views/ReportsCenter/ReportsCenterCMInfo.styl index 6c59073e3f..44abae3c19 100644 --- a/src/views/ReportsCenter/ReportsCenterCMInfo.styl +++ b/src/views/ReportsCenter/ReportsCenterCMInfo.styl @@ -11,4 +11,13 @@ height: 50% } } + + .individual-overview { + .aggregate-vote-activity-graph { + height: 200px; + } + th { + text-align: center; + } + } } diff --git a/src/views/ReportsCenter/ReportsCenterCMInfo.tsx b/src/views/ReportsCenter/ReportsCenterCMInfo.tsx index 134a711b0d..7e7ab3acf7 100644 --- a/src/views/ReportsCenter/ReportsCenterCMInfo.tsx +++ b/src/views/ReportsCenter/ReportsCenterCMInfo.tsx @@ -23,6 +23,10 @@ import { get } from "requests"; import * as data from "data"; import { ResponsiveLine } from "@nivo/line"; +import { useUser } from "hooks"; +import { PaginatedTable } from "PaginatedTable"; +import { Player } from "Player"; +import { Tab, TabList, TabPanel, Tabs } from "react-tabs"; interface ReportCount { date: string; @@ -37,6 +41,7 @@ interface AggregatedReportsData { interface VoteActivityGraphProps { vote_data: ReportCount[]; + period: number; // days to show leading up to today } /* function round_date(the_date: Date): Date { @@ -51,7 +56,7 @@ function startOfWeek(the_date: Date): Date { return new Date(date.setDate(diff)); } -const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { +const CMVoteActivityGraph = ({ vote_data, period }: VoteActivityGraphProps) => { const aggregateDataByWeek = React.useMemo(() => { const aggregated: { [key: string]: { @@ -192,8 +197,7 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { xScale={{ type: "time", min: format( - startOfWeekDateFns(subDays(new Date(), 120), { weekStartsOn: 1 }), - + startOfWeekDateFns(subDays(new Date(), period), { weekStartsOn: 1 }), "yyyy-MM-dd", ), format: "%Y-%m-%d", @@ -232,8 +236,7 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { xScale={{ type: "time", min: format( - startOfWeekDateFns(subDays(new Date(), 120), { weekStartsOn: 1 }), - + startOfWeekDateFns(subDays(new Date(), period), { weekStartsOn: 1 }), "yyyy-MM-dd", ), format: "%Y-%m-%d", @@ -241,6 +244,7 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { precision: "day", }} axisLeft={{ + format: (d) => `${Math.round(d * 100)}%`, // Format ticks as percentages tickValues: 6, }} yFormat=" >-.0p" @@ -263,6 +267,7 @@ const CMVoteActivityGraph = ({ vote_data }: VoteActivityGraphProps) => { export function ReportsCenterCMInfo(): JSX.Element { const [vote_data, setVoteData] = React.useState(null); + const user = useUser(); // Data fetch useEffect(() => { @@ -282,17 +287,49 @@ export function ReportsCenterCMInfo(): JSX.Element { } return ( -
- {["overall", "escaping", "stalling", "score_cheating"].map((report_type) => ( -
-

{report_type}

- {vote_data[report_type] ? ( - - ) : ( - "no data" - )} -
- ))} -
+ + + Group Outcomes + {user.is_moderator && Individual Outcomes} + + + {["overall", "escaping", "stalling", "score_cheating"].map((report_type) => ( +
+

{report_type}

+ {vote_data[report_type] ? ( + + ) : ( + "no data" + )} +
+ ))} +
+ + "cm-name", + render: (X) => , + }, + { + header: "summaries", + className: () => "votes", + render: (X) => ( + + ), + }, + ]} + /> + +
); } diff --git a/yarn.lock b/yarn.lock index abb7aff038..8585939c8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3507,6 +3507,11 @@ clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +clsx@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -9225,6 +9230,14 @@ react-table@^6.10.0: classnames "^2.2.5" react-is "^16.8.1" +react-tabs@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-6.0.2.tgz#bc1065c3828561fee285a8fd045f22e0fcdde1eb" + integrity sha512-aQXTKolnM28k3KguGDBSAbJvcowOQr23A+CUJdzJtOSDOtTwzEaJA+1U4KwhNL9+Obe+jFS7geuvA7ICQPXOnQ== + dependencies: + clsx "^2.0.0" + prop-types "^15.5.0" + react-themeable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e"