From bc0255956a834145cd0d8293abded948fc9488f4 Mon Sep 17 00:00:00 2001 From: Sanjeev Singh Date: Tue, 16 Jul 2019 23:56:06 +0530 Subject: [PATCH] Fix #2209: Add a feature to re-run a submission by challenge host using UI(#2340) --- apps/jobs/urls.py | 4 +++ apps/jobs/views.py | 36 +++++++++++++++++++ frontend/src/css/modules/challenge.scss | 22 ++++++++++++ frontend/src/js/controllers/challengeCtrl.js | 20 +++++++++++ .../my-challenge-all-submission.html | 2 ++ 5 files changed, 84 insertions(+) diff --git a/apps/jobs/urls.py b/apps/jobs/urls.py index 372e0f2b52..9e76bf9e74 100644 --- a/apps/jobs/urls.py +++ b/apps/jobs/urls.py @@ -20,6 +20,10 @@ views.get_remaining_submissions, name="get_remaining_submissions", ), + url( + r'^submissions/(?P[0-9]+)/re-run/$', + views.re_run_submission, name='re_run_submission' + ), url( r"^challenge_phase_split/(?P[0-9]+)/leaderboard/$", views.leaderboard, diff --git a/apps/jobs/views.py b/apps/jobs/views.py index 8137a6cce4..c9241fc6c2 100644 --- a/apps/jobs/views.py +++ b/apps/jobs/views.py @@ -958,6 +958,42 @@ def update_submission(request, challenge_pk): return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +@api_view(['POST', ]) +@throttle_classes([UserRateThrottle, ]) +@permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) +@authentication_classes((ExpiringTokenAuthentication,)) +def re_run_submission(request, submission_pk): + """ + API endpoint to re-run a submission. + Only challenge host has access to this endpoint. + """ + try: + submission = Submission.objects.get(pk=submission_pk) + except Submission.DoesNotExist: + response_data = {'error': 'Submission {} does not exist'.format(submission_pk)} + return Response(response_data, status=status.HTTP_404_NOT_FOUND) + + # get the challenge and challenge phase object + challenge_phase = submission.challenge_phase + challenge = challenge_phase.challenge + + if not is_user_a_host_of_challenge(request.user, challenge.pk): + response_data = { + "error": "Only challenge hosts are allowed to re-run a submission" + } + return Response(response_data, status=status.HTTP_403_FORBIDDEN) + + if not challenge.is_active: + response_data = {'error': 'Challenge {} is not active'.format(challenge.title)} + return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE) + + publish_submission_message(challenge.pk, challenge_phase.pk, submission.pk) + response_data = { + 'success': 'Submission is successfully submitted for re-running' + } + return Response(response_data, status=status.HTTP_200_OK) + + @api_view(["GET"]) @throttle_classes([UserRateThrottle]) @permission_classes((permissions.IsAuthenticated, HasVerifiedEmail)) diff --git a/frontend/src/css/modules/challenge.scss b/frontend/src/css/modules/challenge.scss index ec6bfa0c86..52e4b68671 100644 --- a/frontend/src/css/modules/challenge.scss +++ b/frontend/src/css/modules/challenge.scss @@ -187,6 +187,28 @@ md-select.md-default-theme .md-select-value span:first-child:after, md-select .m color: #252833; } +@-webkit-keyframes spin { + from { -webkit-transform: rotate(0deg); } + to { -webkit-transform: rotate(360deg); } +} + +@keyframes spin { + from {transform:rotate(0deg);} + to {transform:rotate(360deg);} +} + + +.spin { + -webkit-animation: spin 1s linear infinite; + animation: spin 1s linear infinite; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; +} + +.progress-indicator { + width: 14px; +} + .btn-switch { position: relative; display: block; diff --git a/frontend/src/js/controllers/challengeCtrl.js b/frontend/src/js/controllers/challengeCtrl.js index ddf6bb4466..aaaace21be 100644 --- a/frontend/src/js/controllers/challengeCtrl.js +++ b/frontend/src/js/controllers/challengeCtrl.js @@ -940,6 +940,26 @@ utilities.sendRequest(parameters); }; + + vm.reRunSubmission = function(submissionObject) { + submissionObject.classList = ['spin', 'progress-indicator']; + parameters.url = 'jobs/submissions/' + submissionObject.id + '/re-run/'; + parameters.method = 'POST'; + parameters.token = userKey; + parameters.callback = { + onSuccess: function(response) { + $rootScope.notify("success", response.data.success); + submissionObject.classList = ['']; + }, + onError: function(response) { + var error = response.data; + $rootScope.notify("error", error); + submissionObject.classList = ['']; + } + }; + utilities.sendRequest(parameters); + }; + vm.refreshLeaderboard = function() { vm.startLoader("Loading Leaderboard Items"); vm.leaderboard = {}; diff --git a/frontend/src/views/web/challenge/my-challenge-all-submission.html b/frontend/src/views/web/challenge/my-challenge-all-submission.html index b458411ea8..e538ff943d 100644 --- a/frontend/src/views/web/challenge/my-challenge-all-submission.html +++ b/frontend/src/views/web/challenge/my-challenge-all-submission.html @@ -82,6 +82,7 @@ Stderr File Result File Metadata File + Re-run Submissions @@ -116,6 +117,7 @@ N/A +