From 3afe572e08a3ad7044bc41d9d27912ad0bba999b Mon Sep 17 00:00:00 2001 From: Nicolas Boulay Date: Fri, 19 Jan 2024 10:22:35 -0500 Subject: [PATCH] pkp/pkp-lib#9453 Add a new API endpoint for the review round history --- api/v1/reviews/PKPReviewController.php | 165 ++++++++++++++++++ .../review/ReviewRoundModalHandler.php | 145 --------------- locale/en/reviewer.po | 15 +- locale/fr_CA/reviewer.po | 15 +- 4 files changed, 189 insertions(+), 151 deletions(-) create mode 100644 api/v1/reviews/PKPReviewController.php delete mode 100644 controllers/review/ReviewRoundModalHandler.php diff --git a/api/v1/reviews/PKPReviewController.php b/api/v1/reviews/PKPReviewController.php new file mode 100644 index 00000000000..1e491d2d5a0 --- /dev/null +++ b/api/v1/reviews/PKPReviewController.php @@ -0,0 +1,165 @@ +getHistory(...)) + ->name('review.get.submission.round.history') + ->whereNumber(['reviewRoundId', 'submissionId']); + } + + /** + * @copydoc \PKP\core\PKPBaseController::authorize() + */ + public function authorize(PKPRequest $request, array &$args, array $roleAssignments): bool + { + $illuminateRequest = $args[0]; /** @var \Illuminate\Http\Request $illuminateRequest */ + $actionName = static::getRouteActionName($illuminateRequest); + + $this->addPolicy(new UserRolesRequiredPolicy($request), true); + $this->addPolicy(new ContextAccessPolicy($request, $roleAssignments)); + + if ($actionName === 'getHistory') { + $this->addPolicy(new SubmissionAccessPolicy($request, $args, $roleAssignments, 'submissionId', true)); + } + + return parent::authorize($request, $args, $roleAssignments); + } + + /** + * Get reviewer's submission round history + * @throws \Exception + */ + public function getHistory(Request $illuminateRequest): JsonResponse + { + $request = $this->getRequest(); + $context = $request->getContext(); + $contextId = $context->getId(); + + // TODO: get the reviewer ID from the request or from the route? + $reviewerId = $request->getUser()->getId(); + //$reviewerId = $illuminateRequest->route('reviewerId'); + $submissionId = $illuminateRequest->route('submissionId'); + $reviewRoundId = $illuminateRequest->route('reviewRoundId'); + + $reviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterByContextIds([$contextId]) + ->filterBySubmissionIds([$submissionId]) + ->filterByReviewerIds([$reviewerId]) + ->filterByReviewRoundIds([$reviewRoundId]) + ->getMany() + ->first(); + + if (!$reviewAssignment) { + return response()->json([ + 'error' => __('api.404.resourceNotFound'), + ], Response::HTTP_NOT_FOUND); + } + + $submission = Repo::submission()->get($submissionId, $contextId); + $publicationTitle = $submission->getCurrentPublication()->getLocalizedTitle(); + + $declineEmail = null; + if (!$reviewAssignment->getDeclined()) { + $submissionEmailLogDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); + $emailLogs = $submissionEmailLogDao->getBySenderId($submissionId, SubmissionEmailLogEntry::SUBMISSION_EMAIL_REVIEW_DECLINE, $reviewerId)->toArray(); + // TODO: look for the right email log with the right round number. + if ($emailLogs) { + $emailLog = $emailLogs[0]; + $declineEmail = [ + 'subject' => $emailLog->getData('subject'), + 'body' => $emailLog->getData('body'), + ]; + } + } + + $reviewAssignmentProps = Repo::reviewAssignment()->getSchemaMap()->map($reviewAssignment); + + $reviewAssignmentId = $reviewAssignment->getId(); + $submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); + $comments = $submissionCommentDao->getReviewerCommentsByReviewerId($submissionId, $reviewerId, $reviewAssignmentId, true)->toArray(); + $privateComments = $submissionCommentDao->getReviewerCommentsByReviewerId($submissionId, $reviewerId, $reviewAssignmentId, false)->toArray(); + + // TODO: get the comments data... + + $lastReviewAssignment = Repo::reviewAssignment()->getCollector() + ->filterByContextIds([$contextId]) + ->filterBySubmissionIds([$submissionId]) + ->filterByReviewerIds([$reviewerId]) + ->filterByLastReviewRound(true) + ->getMany() + ->first(); + $displayFiles = $lastReviewAssignment->getDeclined() != 1; + + $reviewRoundHistoryProps = [ + 'publicationTitle' => $publicationTitle, + 'declineEmail' => $declineEmail, + 'reviewAssignment' => $reviewAssignmentProps, + 'comments' => $comments, + 'privateComments' => $privateComments, + 'displayFiles' => $displayFiles, + ]; + + return response()->json($reviewRoundHistoryProps, Response::HTTP_OK); + } +} diff --git a/controllers/review/ReviewRoundModalHandler.php b/controllers/review/ReviewRoundModalHandler.php deleted file mode 100644 index dfdd4ff4c3a..00000000000 --- a/controllers/review/ReviewRoundModalHandler.php +++ /dev/null @@ -1,145 +0,0 @@ -addRoleAssignment( - [Role::ROLE_ID_REVIEWER], - ['viewRoundInfo', 'closeModal'] - ); - } - - // - // Implement template methods from PKPHandler. - // - - /** - * @copydoc PKPHandler::authorize() - */ - function authorize($request, &$args, $roleAssignments): bool - { - $this->addPolicy(new RoleBasedHandlerOperationPolicy( - $request, - [Role::ROLE_ID_REVIEWER], - ['viewRoundInfo', 'close'] - )); - - return parent::authorize($request, $args, $roleAssignments); - } - - // - // Public operations - // - - /** - * Display the review round info modal. - * - * @param array $args - * @param PKPRequest $request - * - * @return JSONMessage JSON object - * @throws Exception - */ - function viewRoundInfo($args, $request) - { - $this->setupTemplate($request); - - $submission = Repo::submission()->get($args['submissionId']); - $submissionId = $submission->getId(); - $reviewerId = $request->getUser()->getId(); - - $reviewAssignments = Repo::reviewAssignment()->getCollector() - ->filterByReviewerIds([$reviewerId]) - ->getMany(); - $declinedReviewAssignments = array(); - foreach ($reviewAssignments as $submissionReviewAssignment) { - if ($submissionReviewAssignment->getDeclined() and $submissionId == $submissionReviewAssignment->getSubmissionId()) { - $declinedReviewAssignments[] = $submissionReviewAssignment; - } - } - - $reviewAssignment = Repo::reviewAssignment()->getCollector() - ->filterByReviewRoundIds([$args['reviewRoundId']]) - ->filterByReviewerIds([$reviewerId]) - ->filterByContextIds([$request->getContext()->getId()]) - ->getMany() - ->first(); - $submissionCommentDao = DAORegistry::getDAO('SubmissionCommentDAO'); - $reviewComments = $submissionCommentDao->getReviewerCommentsByReviewerId($submissionId, $reviewerId, $reviewAssignment->getId()); - - $reviewRoundNumber = $args['reviewRoundNumber']; - $submissionEmailLogDao = DAORegistry::getDAO('SubmissionEmailLogDAO'); - $emailLogs = $submissionEmailLogDao - ->getBySenderId($submissionId, SubmissionEmailLogEntry::SUBMISSION_EMAIL_REVIEW_DECLINE, $reviewerId) - ->toArray(); - $declineEmail = null; - $i = 0; - foreach ($declinedReviewAssignments as $declinedReviewAssignment) { - if (isset($emailLogs[$i]) && $reviewRoundNumber == $declinedReviewAssignment->getRound()) { - $declineEmail = $emailLogs[$i]; - } - $i++; - } - - $displayFilesGrid = true; - $lastReviewAssignment = Repo::reviewAssignment()->getCollector() - ->filterBySubmissionIds([$submissionId]) - ->filterByReviewerIds([$reviewerId]) - ->filterByLastReviewRound(true) - ->getMany() - ->first(); - if($lastReviewAssignment->getDeclined() == 1) { - $displayFilesGrid = false; - } - - $templateMgr = TemplateManager::getManager($request); - $templateMgr->assign([ - 'submission' => $submission, - 'reviewAssignment' => $reviewAssignment, - 'reviewRoundNumber' => $reviewRoundNumber, - 'reviewRoundId' => $args['reviewRoundId'], - 'reviewComments' => $reviewComments, - 'declineEmail' => $declineEmail, - 'displayFilesGrid' => $displayFilesGrid - ]); - - return $templateMgr->fetchJson('controllers/modals/reviewRound/reviewRound.tpl'); - } -} diff --git a/locale/en/reviewer.po b/locale/en/reviewer.po index 5e357cf06b6..ccf4ea90350 100644 --- a/locale/en/reviewer.po +++ b/locale/en/reviewer.po @@ -103,15 +103,24 @@ msgstr "Evaluation cycle {$reviewRoundNumber} : {$submissionTitle}" msgid "reviewer.submission.reviewRound.info.history" msgstr "Review history" -msgid "reviewer.submission.comments.authorAndEditor" +msgid "reviewer.submission.reviewRound.comments.authorAndEditor" msgstr "Author and editor" -msgid "reviewer.submission.comments.editorOnly" +msgid "reviewer.submission.reviewRound.comments.editorOnly" msgstr "Editor only" -msgid "reviewer.submission.comments.review" +msgid "reviewer.submission.reviewRound.comments.review" msgstr "Review" +msgid "reviewer.submission.reviewRound.emailLog" +msgstr "Decline reason sent by email" + +msgid "reviewer.submission.reviewRound.emailLog.defaultMessage" +msgstr "No reason given to the decline of the review invitation." + +msgid "reviewer.submission.reviewRound.reviewDeclineDate" +msgstr "Declined Date" + msgid "reviewer.complete" msgstr "Review Submitted" diff --git a/locale/fr_CA/reviewer.po b/locale/fr_CA/reviewer.po index 5dc3e82fdd3..f678fa1a779 100644 --- a/locale/fr_CA/reviewer.po +++ b/locale/fr_CA/reviewer.po @@ -116,15 +116,24 @@ msgstr "Évaluation cycle {$reviewRoundNumber} : {$submissionTitle}" msgid "reviewer.submission.reviewRound.info.history" msgstr "Historique d'évaluation" -msgid "reviewer.submission.comments.authorAndEditor" +msgid "reviewer.submission.reviewRound.comments.authorAndEditor" msgstr "Pour l'auteur et la rédaction" -msgid "reviewer.submission.comments.editorOnly" +msgid "reviewer.submission.reviewRound.comments.editorOnly" msgstr "Pour la rédaction seulement" -msgid "reviewer.submission.comments.review" +msgid "reviewer.submission.reviewRound.comments.review" msgstr "Évaluation" +msgid "reviewer.submission.reviewRound.emailLog" +msgstr "Raison du refus envoyée par courriel" + +msgid "reviewer.submission.reviewRound.emailLog.defaultMessage" +msgstr "Aucune raison fournie pour le refus de l'invitation à évaluer." + +msgid "reviewer.submission.reviewRound.reviewDeclineDate" +msgstr "Date du refus" + msgid "reviewer.complete" msgstr "Évaluation envoyée"