diff --git a/webapp/public/js/domjudge.js b/webapp/public/js/domjudge.js index f25233fb88..7a6b61976a 100644 --- a/webapp/public/js/domjudge.js +++ b/webapp/public/js/domjudge.js @@ -660,7 +660,7 @@ function toggleRefresh($url, $after, usingAjax) { $('#refresh-toggle').text(text); } -function updateClarifications() +function updateTeamNotifications() { $.ajax({ url: $('#menuDefault').data('update-url'), @@ -677,6 +677,14 @@ function updateClarifications() 'link': domjudge_base_url + '/team/clarifications/'+data[i].clarid, 'body': data[i].body }); } + data = json['unread_submissions']; + num = data.length; + for (let i = 0; i < num; i++) { + sendNotification('New result for submission', + {'tag': 'sub_' + data[i].submissionid + '_judge_' + data[i].judgingid, + 'link': domjudge_base_url + '/team/submissions/'+data[i].submissionid, + 'body': data[i].body }); + } } }) } diff --git a/webapp/src/Controller/Team/MiscController.php b/webapp/src/Controller/Team/MiscController.php index 1ad3d4e7a1..84c3885d6a 100644 --- a/webapp/src/Controller/Team/MiscController.php +++ b/webapp/src/Controller/Team/MiscController.php @@ -143,7 +143,10 @@ public function homeAction(Request $request): Response #[Route(path: '/updates', methods: ['GET'], name: 'team_ajax_updates')] public function updatesAction(): JsonResponse { - return $this->json(['unread_clarifications' => $this->dj->getUnreadClarifications()]); + return $this->json([ + 'unread_clarifications' => $this->dj->getUnreadClarifications(), + 'unread_submissions' => $this->dj->getUnreadJudgements(), + ]); } #[Route(path: '/change-contest/{contestId<-?\d+>}', name: 'team_change_contest')] diff --git a/webapp/src/Service/DOMJudgeService.php b/webapp/src/Service/DOMJudgeService.php index 132beee23c..db18eb0102 100644 --- a/webapp/src/Service/DOMJudgeService.php +++ b/webapp/src/Service/DOMJudgeService.php @@ -320,6 +320,53 @@ public function getUnreadClarifications(): array return $unreadClarifications; } + /** + * @return array + */ + + public function getUnreadJudgements(): array + { + $user = $this->getUser(); + $team = $user->getTeam(); + $contest = $this->getCurrentContest($team->getTeamId()); + $unreadJudgements = []; + if ($contest === null) { + return $unreadJudgements; + } + + $queryBuilder = $this->em->createQueryBuilder() + ->from(Judging::class, 'j') + ->select('j, c, s') + ->leftJoin('j.contest', 'c') + ->leftJoin('j.submission', 's') + ->groupBy('j.judgingid') + ->orderBy('j.judgingid') + ->andWhere('j.contest = :cid') + ->setParameter('cid', $contest->getCid()) + ->andWhere('j.result IS NOT NULL') + ->andWhere('s.team = :team') + ->setParameter('team', $team) + ->andWhere('s.submittime < c.endtime') + ->andWhere('j.valid = 1') + ->andWhere('j.seen = 0'); + + if ($this->config->get('verification_required')) { + $queryBuilder->andWhere('j.verified = 1'); + } + + /** @var Judging[] $judgings */ + $judgings = $queryBuilder->getQuery()->getResult(); + + foreach ($judgings as $j) { + $unreadJudgements[] = [ + 'submissionid' => $j->getSubmissionId(), + 'judgingid' => $j->getJudgingid(), + 'body' => 'Submission ' . $j->getSubmissionId() . ' received a new result: ' . $j->getResult() + ]; + } + return $unreadJudgements; + } + /** * @return array{clarifications: array, * judgehosts: array, diff --git a/webapp/templates/team/base.html.twig b/webapp/templates/team/base.html.twig index 50ca40bdc4..33837ce123 100644 --- a/webapp/templates/team/base.html.twig +++ b/webapp/templates/team/base.html.twig @@ -43,8 +43,8 @@ $('#notify_disable').removeClass('d-none'); } } - updateClarifications(); - setInterval(updateClarifications, 20000); + updateTeamNotifications(); + setInterval(updateTeamNotifications, 20000); });