diff --git a/apps/challenges/migrations/0113_challenge_disable_private_submission.py b/apps/challenges/migrations/0113_challenge_disable_private_submission.py new file mode 100644 index 0000000000..90d0c76807 --- /dev/null +++ b/apps/challenges/migrations/0113_challenge_disable_private_submission.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.20 on 2024-08-31 06:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('challenges', '0112_challenge_sqs_retention_period'), + ] + + operations = [ + migrations.AddField( + model_name='challenge', + name='disable_private_submission', + field=models.BooleanField(default=False), + ), + ] diff --git a/apps/challenges/models.py b/apps/challenges/models.py index 7539627878..ec660c04d4 100644 --- a/apps/challenges/models.py +++ b/apps/challenges/models.py @@ -222,6 +222,7 @@ def __init__(self, *args, **kwargs): ) worker_image_url = models.CharField(max_length=200, blank=True, null=True, default="") evaluation_module_error = models.TextField(null=True, blank=True) + disable_private_submission = models.BooleanField(default=False) class Meta: app_label = "challenges" diff --git a/apps/challenges/serializers.py b/apps/challenges/serializers.py index 6d81932c15..956c1c09a6 100644 --- a/apps/challenges/serializers.py +++ b/apps/challenges/serializers.py @@ -94,7 +94,8 @@ class Meta: "evaluation_module_error", "worker_image_url", "worker_instance_type", - "sqs_retention_period" + "sqs_retention_period", + "disable_private_submission" ) @@ -311,7 +312,8 @@ class Meta: "ephemeral_storage", "evaluation_module_error", "worker_image_url", - "sqs_retention_period" + "sqs_retention_period", + "disable_private_submission" ) diff --git a/docs/source/configuration.md b/docs/source/configuration.md index 7ab0d0860d..f72e8645bf 100644 --- a/docs/source/configuration.md +++ b/docs/source/configuration.md @@ -51,6 +51,8 @@ Following fields are required (and can be customized) in the [`challenge_config. 3. `metadata`: This field defines additional information about the metrics that are used to evaluate the challenge submissions. +- **disable_private_submission**: True/False (a Boolean field that gives the flexibility to Challenge Hosts to either disable or enable private submissions. Default is `False`) + The leaderboard schema for the [sample challenge configuration](https://github.com/Cloud-CV/EvalAI-Starters/blob/master/challenge_config.yaml) looks like this: ```yaml diff --git a/frontend/src/js/controllers/challengeCtrl.js b/frontend/src/js/controllers/challengeCtrl.js index c8bf18a82b..1b156abf2e 100644 --- a/frontend/src/js/controllers/challengeCtrl.js +++ b/frontend/src/js/controllers/challengeCtrl.js @@ -82,7 +82,7 @@ vm.currentPhaseLeaderboardPublic = false; vm.eligible_to_submit = false; vm.evaluation_module_error = null; - + vm.disable_private_submission = false; vm.filter_all_submission_by_team_name = ''; vm.filter_my_submission_by_team_name = ''; // show loader @@ -396,6 +396,7 @@ vm.has_sponsors = details.has_sponsors; vm.queueName = details.queue; vm.evaluation_module_error = details.evaluation_module_error; + vm.disable_private_submission = details.disable_private_submission; vm.getTeamName(vm.challengeId); if (vm.page.image === null) { vm.page.image = "dist/images/logo.png"; @@ -708,6 +709,9 @@ formData.append("project_url", vm.projectUrl); formData.append("publication_url", vm.publicationUrl); formData.append("submission_metadata", JSON.stringify(vm.metaAttributesforCurrentSubmission)); + if (vm.disable_private_submission) { + vm.isPublicSubmission = true; + } if (vm.isPublicSubmission !== null) { formData.append("is_public", vm.isPublicSubmission); } @@ -2836,7 +2840,48 @@ $mdDialog.hide(); } }; - + vm.toggleDisablePrivateSubmission = function(ev) { + ev.stopPropagation(); + vm.toggleSubmissionState = null; + vm.submissionDesc = null; + if (vm.disable_private_submission) + vm.toggleSubmissionState = "allowed"; + else + vm.toggleSubmissionState = "disabled"; + + var confirm = $mdDialog.confirm() + .title('Make private submissions ' + vm.toggleSubmissionState + '?') + .ariaLabel('') + .targetEvent(ev) + .ok('Yes') + .cancel('No'); + + $mdDialog.show(confirm).then(function() { + parameters.url = "challenges/challenge_host_team/" + vm.page.creator.id + "/challenge/" + vm.page.id; + parameters.method = 'PATCH'; + parameters.data = { + "disable_private_submission": !vm.disable_private_submission, + }; + vm.disable_private_submission = !vm.disable_private_submission; + parameters.callback = { + onSuccess: function(response) { + var status = response.status; + if (status === 200) { + $mdDialog.hide(); + $rootScope.notify("success", "Private submissions were successfully made " + vm.toggleSubmissionState); + } + }, + onError: function(response) { + $mdDialog.hide(); + var error = response.data; + $rootScope.notify("error", error); + } + }; + utilities.sendRequest(parameters); + }, function() { + // Nope + }); + }; vm.publishChallenge = function(ev) { ev.stopPropagation(); vm.toggleChallengeState = null; diff --git a/frontend/src/views/web/challenge/challenge-page.html b/frontend/src/views/web/challenge/challenge-page.html index dd6373771a..c9a5825eff 100644 --- a/frontend/src/views/web/challenge/challenge-page.html +++ b/frontend/src/views/web/challenge/challenge-page.html @@ -56,6 +56,18 @@

{{challenge.page.title}} Not Published +
+ + + Private Submissions Disabled + + + + + + Private Submissions Allowed + +
diff --git a/frontend/src/views/web/challenge/my-submission.html b/frontend/src/views/web/challenge/my-submission.html index f7acdb1d7e..41d0f061c5 100644 --- a/frontend/src/views/web/challenge/my-submission.html +++ b/frontend/src/views/web/challenge/my-submission.html @@ -66,7 +66,7 @@

My Participated Team: {{challenge.participated_team_name}}
Environment Logs Submitted at - Show on leaderboard Baseline @@ -121,7 +121,7 @@
My Participated Team: {{challenge.participated_team_name}}
{{key.submitted_at | date:'medium'}} - + Make Submission
-
+

Select submission visibility:

  • Make Submission
  • -
    Use   --private  or  --public   flag in the submission +
    Use   --private  or  --public   flag in the submission command to make the submission private or public respectively.
  • diff --git a/tests/unit/challenges/test_views.py b/tests/unit/challenges/test_views.py index 5ea9939341..f452b1d72e 100644 --- a/tests/unit/challenges/test_views.py +++ b/tests/unit/challenges/test_views.py @@ -195,6 +195,7 @@ def test_get_challenge(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] @@ -550,6 +551,7 @@ def test_get_particular_challenge(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } response = self.client.get(self.url, {}) self.assertEqual(response.data, expected) @@ -652,6 +654,7 @@ def test_update_challenge_when_user_is_its_creator(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } response = self.client.put( self.url, {"title": new_title, "description": new_description} @@ -780,6 +783,7 @@ def test_particular_challenge_partial_update(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } response = self.client.patch(self.url, self.partial_update_data) self.assertEqual(response.data, expected) @@ -857,6 +861,7 @@ def test_particular_challenge_update(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } response = self.client.put(self.url, self.data) self.assertEqual(response.data, expected) @@ -1450,6 +1455,7 @@ def test_get_past_challenges(self): "worker_image_url": self.challenge3.worker_image_url, "worker_instance_type": self.challenge3.worker_instance_type, "sqs_retention_period": self.challenge3.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] response = self.client.get(self.url, {}, format="json") @@ -1533,6 +1539,7 @@ def test_get_present_challenges(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] response = self.client.get(self.url, {}, format="json") @@ -1616,6 +1623,7 @@ def test_get_future_challenges(self): "worker_image_url": self.challenge4.worker_image_url, "worker_instance_type": self.challenge4.worker_instance_type, "sqs_retention_period": self.challenge4.sqs_retention_period, + "disable_private_submission": self.challenge4.disable_private_submission, } ] response = self.client.get(self.url, {}, format="json") @@ -1699,6 +1707,7 @@ def test_get_all_challenges(self): "worker_image_url": self.challenge3.worker_image_url, "worker_instance_type": self.challenge3.worker_instance_type, "sqs_retention_period": self.challenge3.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, }, { "id": self.challenge3.pk, @@ -1766,6 +1775,7 @@ def test_get_all_challenges(self): "worker_image_url": self.challenge3.worker_image_url, "worker_instance_type": self.challenge3.worker_instance_type, "sqs_retention_period": self.challenge3.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, }, { "id": self.challenge2.pk, @@ -1833,6 +1843,7 @@ def test_get_all_challenges(self): "worker_image_url": self.challenge2.worker_image_url, "worker_instance_type": self.challenge2.worker_instance_type, "sqs_retention_period": self.challenge2.sqs_retention_period, + "disable_private_submission": self.challenge2.disable_private_submission, }, ] response = self.client.get(self.url, {}, format="json") @@ -1971,6 +1982,7 @@ def test_get_featured_challenges(self): "worker_image_url": self.challenge3.worker_image_url, "worker_instance_type": self.challenge3.worker_instance_type, "sqs_retention_period": self.challenge3.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] response = self.client.get(self.url, {}, format="json") @@ -2133,6 +2145,7 @@ def test_get_challenge_by_pk_when_user_is_challenge_host(self): "worker_image_url": self.challenge3.worker_image_url, "worker_instance_type": self.challenge3.worker_instance_type, "sqs_retention_period": self.challenge3.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } response = self.client.get(self.url, {}) @@ -2224,6 +2237,7 @@ def test_get_challenge_by_pk_when_user_is_participant(self): "worker_image_url": self.challenge4.worker_image_url, "worker_instance_type": self.challenge4.worker_instance_type, "sqs_retention_period": self.challenge4.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } self.client.force_authenticate(user=self.user1) @@ -2375,6 +2389,7 @@ def test_get_challenge_when_host_team_is_given(self): "worker_image_url": self.challenge2.worker_image_url, "worker_instance_type": self.challenge2.worker_instance_type, "sqs_retention_period": self.challenge2.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] @@ -2454,6 +2469,7 @@ def test_get_challenge_when_participant_team_is_given(self): "worker_image_url": self.challenge2.worker_image_url, "worker_instance_type": self.challenge2.worker_instance_type, "sqs_retention_period": self.challenge2.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] @@ -2533,6 +2549,7 @@ def test_get_challenge_when_mode_is_participant(self): "worker_image_url": self.challenge2.worker_image_url, "worker_instance_type": self.challenge2.worker_instance_type, "sqs_retention_period": self.challenge2.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, } ] @@ -2610,6 +2627,7 @@ def test_get_challenge_when_mode_is_host(self): "worker_image_url": self.challenge.worker_image_url, "worker_instance_type": self.challenge.worker_instance_type, "sqs_retention_period": self.challenge.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, }, { "id": self.challenge2.pk, @@ -2677,6 +2695,7 @@ def test_get_challenge_when_mode_is_host(self): "worker_image_url": self.challenge2.worker_image_url, "worker_instance_type": self.challenge2.worker_instance_type, "sqs_retention_period": self.challenge2.sqs_retention_period, + "disable_private_submission": self.challenge.disable_private_submission, }, ] diff --git a/tests/unit/participants/test_views.py b/tests/unit/participants/test_views.py index 6004451dd2..2324eb6d69 100644 --- a/tests/unit/participants/test_views.py +++ b/tests/unit/participants/test_views.py @@ -884,6 +884,7 @@ def test_get_teams_and_corresponding_challenges_for_a_participant(self): "worker_image_url": self.challenge1.worker_image_url, "worker_instance_type": self.challenge1.worker_instance_type, "sqs_retention_period": self.challenge1.sqs_retention_period, + "disable_private_submission": self.challenge1.disable_private_submission, }, "participant_team": { "id": self.participant_team.id, @@ -978,6 +979,7 @@ def test_get_participant_team_challenge_list(self): "worker_image_url": self.challenge1.worker_image_url, "worker_instance_type": self.challenge1.worker_instance_type, "sqs_retention_period": self.challenge1.sqs_retention_period, + "disable_private_submission": self.challenge1.disable_private_submission, } ]