diff --git a/src/components/AnnulQueueModal/AnnulQueueModal.styl b/src/components/AnnulQueueModal/AnnulQueueModal.styl index f6d6d580c3..47ab8c2621 100644 --- a/src/components/AnnulQueueModal/AnnulQueueModal.styl +++ b/src/components/AnnulQueueModal/AnnulQueueModal.styl @@ -100,8 +100,8 @@ width: 85%; } - .actions, .close { - margin: 0 20px; + .modal-actions, .close { + margin: 0 0px; } .strikethrough { diff --git a/src/components/AnnulQueueModal/AnnulQueueModal.tsx b/src/components/AnnulQueueModal/AnnulQueueModal.tsx index 8be728f1e7..cd7443b51b 100644 --- a/src/components/AnnulQueueModal/AnnulQueueModal.tsx +++ b/src/components/AnnulQueueModal/AnnulQueueModal.tsx @@ -22,14 +22,16 @@ import { Goban } from "goban"; import { AIReview, GameTimings, ChatMode, GameChat, GobanContext } from "Game"; import { Player } from "Player"; import { Resizable } from "Resizable"; -import { post } from "requests"; +import { post, put } from "requests"; // Define the AnnulQueueModalProps interface interface AnnulQueueModalProps { annulQueue: any[]; - setSelectModeActive: React.Dispatch; + setSelectModeActive?: React.Dispatch; setAnnulQueue: React.Dispatch; onClose: () => void; + forDetectedAI: boolean; + player?: any; } // Define the AnnulQueueModal component @@ -38,6 +40,8 @@ export function AnnulQueueModal({ setSelectModeActive, setAnnulQueue, onClose, + forDetectedAI, + player, }: AnnulQueueModalProps) { // Declare state variables const [selectedGameIndex, setSelectedGameIndex] = React.useState(0); @@ -66,8 +70,12 @@ export function AnnulQueueModal({ // Close the modal const closeModal = () => { - setAnnulQueue([]); - setSelectModeActive(false); + if (!forDetectedAI) { + setAnnulQueue([]); + if (setSelectModeActive) { + setSelectModeActive(false); + } + } setShowAnnulOverlay(false); setAnnulResponse(null); onClose(); @@ -158,27 +166,33 @@ export function AnnulQueueModal({ // Prompt the user for a moderation note const promptForModerationNote = () => { - let moderation_note: string | null = null; + let moderationNote: string | null = null; + let currentPlayer: any; + if (forDetectedAI) { + currentPlayer = player; + } else { + currentPlayer = currentGame.player; + } do { - moderation_note = prompt( - `Annulling ${validGameIds.length} of ${currentGame.player.username}'s games.\nEnter moderation note: (will be entered with '${currentGame.player.username} mass annull:')`, + moderationNote = prompt( + `Annulling ${validGameIds.length} of ${currentPlayer.username}'s games.\nEnter moderation note: (will be entered with '${currentPlayer.username} mass annull:')`, ); - if (moderation_note == null) { + if (moderationNote == null) { return null; } - moderation_note = moderation_note.trim(); - } while (moderation_note === ""); - return `${currentGame.player.username} mass annul: ${moderation_note}`; + moderationNote = moderationNote.trim(); + } while (moderationNote === ""); + return `player ${currentPlayer.id} mass annul: ${moderationNote}`; }; // Annul the specified games - const annul = (validGameIds: number[], moderation_note: string) => { + const annul = (validGameIds: number[], moderationNote: string) => { setShowAnnulOverlay(true); post("moderation/annul", { games: validGameIds, annul: true, - moderation_note: moderation_note, + moderation_note: moderationNote, }) .then((res) => { const successful = res.done; @@ -207,6 +221,24 @@ export function AnnulQueueModal({ }); }; + const markFalsePositive = () => { + if (confirm("Mark this game as a false positive detection?") === true) { + put("cheat_detection/false_positive", { + game_id: currentGame.id, + player_id: currentGame.player, + false_positive: true, + }) + .then((res) => { + if (res.success) { + setDequeueRequested(true); + } + }) + .catch((err) => { + console.error(err); + }); + } + }; + return ( <>
@@ -239,10 +271,10 @@ export function AnnulQueueModal({ response={annulResponse} />
- {queue[selectedGameIndex] && ( + {currentGame && (
- Black: + Black:
- White: + White:
Game Outcome: {winner} ( @@ -310,7 +342,7 @@ export function AnnulQueueModal({
-
+
@@ -346,6 +378,14 @@ export function AnnulQueueModal({
+ {forDetectedAI && ( + + )} @@ -358,12 +398,7 @@ export function AnnulQueueModal({ } // Open the AnnulQueueModal -export function openAnnulQueueModal( - annulQueue, - setSelectModeActive, - setAnnulQueue, - setIsAnnulQueueModalOpen, -) { +export function openAnnulQueueModal(setIsAnnulQueueModalOpen) { setIsAnnulQueueModalOpen(true); // Disable body scroll diff --git a/src/lib/report_manager.tsx b/src/lib/report_manager.tsx index 34b5ba774f..85d9cfd79e 100644 --- a/src/lib/report_manager.tsx +++ b/src/lib/report_manager.tsx @@ -70,6 +70,7 @@ export interface Report { }; moderator_note: string; system_note: string; + detected_ai_games: Array; automod_to_moderator?: string; // Suggestions from "automod" automod_to_reporter?: string; diff --git a/src/views/ReportsCenter/ReportsCenterHistory.tsx b/src/views/ReportsCenter/ReportsCenterHistory.tsx index 98dcdc22ca..cb9a754b8c 100644 --- a/src/views/ReportsCenter/ReportsCenterHistory.tsx +++ b/src/views/ReportsCenter/ReportsCenterHistory.tsx @@ -70,7 +70,8 @@ export function ReportsCenterHistory(): JSX.Element { { header: "Reporter", className: () => "state", - render: (X) => , + render: (X) => + X.reporting_user ? : "System", }, { header: "Type", diff --git a/src/views/ReportsCenter/ViewReport.styl b/src/views/ReportsCenter/ViewReport.styl index c2920352c4..49db8891e2 100644 --- a/src/views/ReportsCenter/ViewReport.styl +++ b/src/views/ReportsCenter/ViewReport.styl @@ -88,6 +88,10 @@ .actions-right { align-items: flex-end; // put the buttons down close-ish to the send-warning buttons + button { + height: auto; + padding: 7px; + } } .automod-analysis { diff --git a/src/views/ReportsCenter/ViewReport.tsx b/src/views/ReportsCenter/ViewReport.tsx index 4491889679..69c16f380a 100644 --- a/src/views/ReportsCenter/ViewReport.tsx +++ b/src/views/ReportsCenter/ViewReport.tsx @@ -34,6 +34,7 @@ import { AppealView } from "./AppealView"; import { get } from "requests"; import { MessageTemplate, WARNING_TEMPLATES, REPORTER_RESPONSE_TEMPLATES } from "./MessageTemplate"; import { ModerationActionSelector } from "./ModerationActionSelector"; +import { openAnnulQueueModal, AnnulQueueModal } from "AnnulQueueModal"; // Used for saving updates to the report let report_note_id = 0; @@ -56,6 +57,8 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J const [error, setError] = React.useState(null); const [moderator_id, setModeratorId] = React.useState(report?.moderator?.id); const [reportState, setReportState] = React.useState(report?.state); + const [isAnnulQueueModalOpen, setIsAnnulQueueModalOpen] = React.useState(false); + const [annulQueue, setAnnulQueue] = React.useState(report?.detected_ai_games); const related = report_manager.getRelatedReports(report_id); @@ -68,6 +71,7 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J setReport(report); setModeratorId(report?.moderator?.id); setReportState(report?.state); + setAnnulQueue(report?.detected_ai_games); }) .catch((err) => { console.error(err); @@ -229,8 +233,21 @@ export function ViewReport({ report_id, reports, onChange }: ViewReportProps): J } }; + const handleCloseAnnulQueueModal = () => { + setIsAnnulQueueModalOpen(false); + }; + return (
+ {isAnnulQueueModalOpen && ( + + )}
{report_in_reports ? (