Skip to content

Commit

Permalink
Corner case handling for community moderator actions, and let moderat…
Browse files Browse the repository at this point in the history
…ors see all reports for now.
  • Loading branch information
GreenAsJade committed Dec 2, 2023
1 parent 1f3cdd4 commit 688549b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export function IncidentReportTracker(): JSX.Element {
navigate(`/reports-center/all/${report_id}`);
};

const reports = report_manager.sorted_active_incident_reports;
const reports = report_manager.getAvailableReports();
const hide_indicator = (reports.length === 0 && !user.is_moderator) || prefer_hidden;

function getReportType(report: Report): string {
Expand Down
18 changes: 17 additions & 1 deletion src/lib/report_manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { MOD_POWER_HANDLE_SCORE_CHEAT, MOD_POWER_HANDLE_ESCAPING } from "./misc"

export const DAILY_REPORT_GOAL = 10;

const DONT_OFFER_COMMUNITY_MODERATION_TYPES_TO_MODERATORS = false;

interface Vote {
voter_id: number;
action: string;
Expand Down Expand Up @@ -229,13 +231,27 @@ class ReportManager extends EventEmitter<Events> {
// don't hand community moderation reports to full mods unless the report is escalated,
// because community moderators are supposed to do these!
if (
DONT_OFFER_COMMUNITY_MODERATION_TYPES_TO_MODERATORS &&
user.is_moderator &&
!(report.moderator?.id === user.id) && // maybe they already have it, so they need to see it
(report.report_type === "score_cheating" || report.report_type === "escaping") &&
!report.escalated
) {
return false;
}
return !report.moderator || report.moderator?.id === user.id;

// Never give a claimed report to community moderators
if (!user.is_moderator && report.moderator?.id) {
console.log("Not giving to community moderator", report.id);
return false;
}

if (report.moderator && report.moderator.id !== user.id) {
// claimed reports are not given out to others
return false;
}

return true;
});
}

Expand Down
62 changes: 35 additions & 27 deletions src/views/ReportsCenter/ModerationActionSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
*/

import * as React from "react";
import { Report } from "report_manager";
import { pgettext } from "translate";
import { _, pgettext } from "translate";

import * as DynamicHelp from "react-dynamic-help";

interface ModerationActionSelectorProps {
report: Report;
available_actions: string[];
enable: boolean;
claim: () => void;
submit: (action: string) => void;
Expand Down Expand Up @@ -60,7 +59,7 @@ const ACTION_PROMPTS = {
};

export function ModerationActionSelector({
report,
available_actions,
enable,
claim,
submit,
Expand All @@ -76,37 +75,46 @@ export function ModerationActionSelector({
const { ref: voting_pane } = registerTargetItem("voting-pane");
const { ref: escalate_option } = registerTargetItem("escalate-option");

const action_choices = available_actions ? available_actions : ["escalate"];

return (
<div className="voting" ref={voting_pane}>
<div className="voting-pane" ref={voting_pane}>
<h4>
{pgettext(
"The heading for community moderators 'action choices' section",
"Actions",
)}
</h4>
{report.available_actions.map((a) => (
<div
key={a}
className="action-selector"
ref={a === "escalate" ? escalate_option : null}
>
<input
id={a}
name="availableActions"
type="radio"
checked={selectedOption === a}
value={a}
onChange={updateSelectedAction}
/>
<label htmlFor={a}>{ACTION_PROMPTS[a]}</label>
{(!available_actions || null) && (
<div className="no-report-actions-note">
{_("This report has no available actions yet. You can escalate or ignore it.")}
</div>
)}
{!enable && (
<div className="diabled-actions-note">
{_("This report was handled after you decided to look at it!")}
</div>
))}
{(report.available_actions || null) && (
<button
className="success"
disabled={!enable}
onClick={() => submit(selectedOption)}
>
)}
{enable &&
action_choices.map((a) => (
<div
key={a}
className="action-selector"
ref={a === "escalate" ? escalate_option : null}
>
<input
id={a}
name="availableActions"
type="radio"
checked={selectedOption === a}
value={a}
onChange={updateSelectedAction}
/>
<label htmlFor={a}>{ACTION_PROMPTS[a]}</label>
</div>
))}
{((action_choices && enable) || null) && (
<button className="success" onClick={() => submit(selectedOption)}>
{pgettext("A label on a button for submitting a vote", "Vote")}
</button>
)}
Expand Down
9 changes: 9 additions & 0 deletions src/views/ReportsCenter/ReportsCenter.styl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ reports_center_content_width=56rem
}
}


.voting-pane {
padding-bottom: 0.5rem; // intended to create margin for rdh highlighter

.no-report-actions-note, .disabled-actions-note {
padding: 0 1rem 1rem 1rem;
}
}

.actions {
display: grid;
grid-template-columns: 1fr 1fr;
Expand Down
9 changes: 7 additions & 2 deletions src/views/ReportsCenter/ViewReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J
const [reportState, setReportState] = React.useState(report?.state);
const [isAnnulQueueModalOpen, setIsAnnulQueueModalOpen] = React.useState(false);
const [annulQueue, setAnnulQueue] = React.useState<null | any[]>(report?.detected_ai_games);
const [availableActions, setAvailableActions] = React.useState<string[]>(null);

const related = report_manager.getRelatedReports(report_id);

React.useEffect(() => {
if (report_id) {
// For some reason we have to capture the state of the report at the time that report_id goes valid
// It's not clear why, but there are subsequent renders where the report state goes away, so ...
// capture what you want to use here! ...
report_manager
.getReport(report_id)
.then((report) => {
Expand All @@ -72,6 +76,7 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J
setModeratorId(report?.moderator?.id);
setReportState(report?.state);
setAnnulQueue(report?.detected_ai_games);
setAvailableActions(report?.available_actions);
})
.catch((err) => {
console.error(err);
Expand Down Expand Up @@ -448,9 +453,9 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J
{((!user.is_moderator && user.moderator_powers) || null) && (
<div className="voting">
<ModerationActionSelector
report={report}
available_actions={availableActions}
claim={() => {
/* dont claim*/
/* community moderators don't claim reports */
}}
submit={(action) => {
void report_manager.vote(report.id, action);
Expand Down

0 comments on commit 688549b

Please sign in to comment.