From 40daf93bad8251caaf93244d3757de7ff7ab32e3 Mon Sep 17 00:00:00 2001 From: GreenAsJade Date: Sun, 18 Feb 2024 20:32:28 +1030 Subject: [PATCH] Moderator pref to control report quota --- .../IncidentReportTracker.tsx | 17 ++-- src/lib/preferences.ts | 1 + src/lib/report_manager.tsx | 17 ++-- src/views/ReportsCenter/ReportsCenter.tsx | 21 +++-- src/views/Settings/ModeratorPreferences.tsx | 89 +++++++++++++------ src/views/Settings/Settings.tsx | 5 +- 6 files changed, 98 insertions(+), 52 deletions(-) diff --git a/src/components/IncidentReportTracker/IncidentReportTracker.tsx b/src/components/IncidentReportTracker/IncidentReportTracker.tsx index 6a7cada86d..2396da6c0f 100644 --- a/src/components/IncidentReportTracker/IncidentReportTracker.tsx +++ b/src/components/IncidentReportTracker/IncidentReportTracker.tsx @@ -29,7 +29,7 @@ import { ignore, errorAlerter } from "misc"; import { openReportedConversationModal } from "ReportedConversationModal"; import { AutoTranslate } from "AutoTranslate"; import { report_categories } from "Report"; -import { Report, report_manager, DAILY_REPORT_GOAL } from "report_manager"; +import { Report, report_manager } from "report_manager"; import { useRefresh, useUser } from "hooks"; import * as DynamicHelp from "react-dynamic-help"; @@ -39,6 +39,7 @@ export function IncidentReportTracker(): JSX.Element | null { const [show_incident_list, setShowIncidentList] = React.useState(false); const [normal_ct, setNormalCt] = React.useState(0); const [prefer_hidden] = usePreference("hide-incident-reports"); + const [report_quota] = usePreference("moderator.report-quota"); const refresh = useRefresh(); const { registerTargetItem, triggerFlow, signalUsed } = React.useContext(DynamicHelp.Api); @@ -151,16 +152,16 @@ export function IncidentReportTracker(): JSX.Element | null { return; } - if (user.is_moderator || user.moderator_powers > 0) { + if ((user.is_moderator || user.moderator_powers > 0) && !!report_quota) { const handled_today = user.reports_handled_today || 0; - setNormalCt(Math.max(0, Math.min(count, DAILY_REPORT_GOAL - handled_today))); + setNormalCt(Math.max(0, Math.min(count, report_quota - handled_today))); } else { setNormalCt(count); } } function updateUser() { - updateCt(report_manager.getAvailableReports().length); + updateCt(report_manager.getEligibleReports().length); } data.watch("user", updateUser); @@ -186,7 +187,7 @@ export function IncidentReportTracker(): JSX.Element | null { return null; } - const reports = report_manager.getAvailableReports(); + const reports = report_manager.getEligibleReports(); const hide_indicator = (reports.length === 0 && !user.is_moderator) || prefer_hidden; function getReportType(report: Report): string { @@ -221,11 +222,7 @@ export function IncidentReportTracker(): JSX.Element | null { className={`fa fa-exclamation-triangle ${normal_ct > 0 ? "active" : ""}`} ref={incident_report_indicator} /> - {user.is_moderator && ( - 0 ? "active" : ""}`}> - {normal_ct} - - )} + 0 ? "active" : ""}`}>{normal_ct} )} {show_incident_list && ( diff --git a/src/lib/preferences.ts b/src/lib/preferences.ts index 724a22243e..6261ac5d7f 100644 --- a/src/lib/preferences.ts +++ b/src/lib/preferences.ts @@ -131,6 +131,7 @@ export const defaults = { "moderator.join-games-anonymously": true, "moderator.hide-flags": false, "moderator.hide-profile-information": false, // hide extra moderator information + "moderator.report-quota": 10, "moderator.report-settings": {} as { [category: string]: { priority: number; diff --git a/src/lib/report_manager.tsx b/src/lib/report_manager.tsx index 9867a8274f..40e2729188 100644 --- a/src/lib/report_manager.tsx +++ b/src/lib/report_manager.tsx @@ -35,8 +35,6 @@ import { browserHistory } from "ogsHistory"; import { get, post } from "requests"; import { MODERATOR_POWERS } from "moderation"; -export const DAILY_REPORT_GOAL = 10; - const DONT_OFFER_COMMUNITY_MODERATION_TYPES_TO_MODERATORS = false; interface Vote { @@ -204,7 +202,15 @@ class ReportManager extends EventEmitter { this.emit("update"); } - public getAvailableReports(): Report[] { + public getEligibleReports(): Report[] { + const quota = preferences.get("moderator.report-quota"); + return !quota || this.getHandledTodayCount() < preferences.get("moderator.report-quota") + ? this.getAvailableReports() + : []; + } + + // Clients should use getEligibleReports + private getAvailableReports(): Report[] { const user = data.get("user"); return this.sorted_active_incident_reports.filter((report) => { @@ -226,7 +232,7 @@ class ReportManager extends EventEmitter { } // Community moderators only get to see reports that they have the power for and - // that they have not yet voted on. + // that they have not yet voted on, and are not escalated const has_handle_score_cheat = (user.moderator_powers & MODERATOR_POWERS.HANDLE_SCORE_CHEAT) > 0; const has_handle_escaping = @@ -423,9 +429,10 @@ class ReportManager extends EventEmitter { return data.get("user").reports_handled_today || 0; } public getReportsLeftUntilGoal(): number { + const report_quota = preferences.get("moderator.report-quota"); const count = this.getAvailableReports().length; const handled_today = this.getHandledTodayCount(); - return Math.max(0, Math.min(count, DAILY_REPORT_GOAL - handled_today)); + return Math.max(0, Math.min(count, report_quota - handled_today)); } } diff --git a/src/views/ReportsCenter/ReportsCenter.tsx b/src/views/ReportsCenter/ReportsCenter.tsx index c7fc3e38e9..e5fc2839f3 100644 --- a/src/views/ReportsCenter/ReportsCenter.tsx +++ b/src/views/ReportsCenter/ReportsCenter.tsx @@ -19,13 +19,14 @@ import * as React from "react"; import { useNavigate, useParams } from "react-router-dom"; import { useUser, useRefresh } from "hooks"; import { report_categories, ReportDescription } from "Report"; -import { report_manager, DAILY_REPORT_GOAL } from "report_manager"; +import { report_manager } from "report_manager"; import Select from "react-select"; import { _ } from "translate"; import { ViewReport } from "./ViewReport"; import { ReportsCenterSettings } from "./ReportsCenterSettings"; import { ReportsCenterHistory } from "./ReportsCenterHistory"; import { MOD_POWER_NEEDED } from "moderation"; +import { usePreference } from "preferences"; interface OtherView { special: string; @@ -66,7 +67,10 @@ export function ReportsCenter(): JSX.Element | null { const report_id = parseInt(params["report_id"] || "0"); const category = params["category"] || "all"; - const reports = report_manager.getAvailableReports(); + const [report_quota] = usePreference("moderator.report-quota"); + + const reports = report_manager.getEligibleReports(); + const counts: any = {}; for (const report of reports) { counts[report.report_type] = (counts[report.report_type] || 0) + 1; @@ -89,7 +93,7 @@ export function ReportsCenter(): JSX.Element | null { const setToFirstAvailableReport = () => { if (!report_id) { - const reports = report_manager.getAvailableReports(); + const reports = report_manager.getEligibleReports(); if (reports.length) { for (let i = 0; i < reports.length; ++i) { @@ -146,7 +150,7 @@ export function ReportsCenter(): JSX.Element | null { {_("Reports Center")} - {user.is_moderator && ( + {!!report_quota && (
{report_manager.getHandledTodayCount() === 0 - ? "Daily report goal: " + DAILY_REPORT_GOAL + ? "Daily report goal: " + report_quota : ""}
)} diff --git a/src/views/Settings/ModeratorPreferences.tsx b/src/views/Settings/ModeratorPreferences.tsx index b1c630bd4d..1b0b63766c 100644 --- a/src/views/Settings/ModeratorPreferences.tsx +++ b/src/views/Settings/ModeratorPreferences.tsx @@ -22,6 +22,7 @@ import { usePreference } from "preferences"; import { Toggle } from "Toggle"; import { SettingGroupPageProps, PreferenceLine } from "SettingsCommon"; import { ReportsCenterSettings } from "ReportsCenter"; +import * as preferences from "preferences"; export function ModeratorPreferences(_props: SettingGroupPageProps): JSX.Element | null { const [incident_report_notifications, setIncidentReportNotifications] = usePreference( @@ -38,42 +39,76 @@ export function ModeratorPreferences(_props: SettingGroupPageProps): JSX.Element "moderator.hide-player-card-mod-controls", ); + const [report_quota, _setReportQuota] = React.useState( + preferences.get("moderator.report-quota"), + ); + const user = data.get("user"); - if (!user.is_moderator) { + function updateReportQuota(ev: React.ChangeEvent) { + let quota = parseInt(ev.target.value); + if (!isNaN(quota)) { + quota = Math.min(200, Math.max(0, quota)); + preferences.set("moderator.report-quota", quota); + _setReportQuota(quota); + } else { + _setReportQuota(ev.target.value as any); + } + } + if (!user.is_moderator && !user.moderator_powers) { return null; } return (
- - + - - - - - - - - - - - - - - - - - - - + {user.is_moderator && ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + )}
); } diff --git a/src/views/Settings/Settings.tsx b/src/views/Settings/Settings.tsx index 3cd0f93802..203c9a3cbc 100644 --- a/src/views/Settings/Settings.tsx +++ b/src/views/Settings/Settings.tsx @@ -211,7 +211,10 @@ export function Settings(): JSX.Element {
{groups - .filter((x) => x.key !== "moderator" || user.is_moderator) + .filter( + (x) => + x.key !== "moderator" || user.is_moderator || user.moderator_powers, + ) .map((x) => (