Repository: Cloud-CV/EvalAI

Issue:
Add the functionality to disable the Challenge
### Objective

A challenge host should be able to delete the challenge using the UI. At the backend, set the flag `is_disabled` whenever a challenge host submits a request to delete the challenge.


Discussion:
Can i contribute to this?
@rishabhja yes sure. Go ahead.
Can you assign the issue to me?
@deshraj: I would prefer that you call this issue as "Add functionality to disable a Challenge" since at the backend you are disabling the challenge. It does not make sense to introduce an inconsistency in actions at backend and frontend. 
Where is the disable button to be shown?
The disable button should be shown right below the challenge description in a card where if the challenge host clicks on that button then a dialog box opens that asks the challenge host to enter the challenge name and then press submit in that dialog box. Does that sound good @rishabhja ? 
Why do i need to ask for the challenge name if he is pressing the disable button on a specific challenge?
We are doing this to make sure that the challenge host is not pressing the button by mistake. 
A confirmation dialog maybe better
We have thought about both the approaches earlier and we wanted to go with this approach similar to what Github follows. :) 
okay, sure. I am assuming this disable button is not shown on the all challenges screen?
Cool. @rishabhja please let us know if you have other doubts about this. 
Disabling the challenge doesnt hide it. Is it expected?
Can you give me access to push?
@rishabhja yes, disabling a challenge must hide it from the list of all challenges.
Moreover, please create a pull request with the changes that you have done.
I am not able to push my branch. So, how will i create a PR?
For creating a PR, please fork the repository then you can push your local branch to your origin and then create a PR from there. Please ask if something is not clear. Please refer here for more details https://help.github.com/articles/creating-a-pull-request-from-a-fork/
@rishabhja Any update on this ?
@RishabhJain2018 If nobody is working on this, can I work on this?

Sure @anuj-rathore please go ahead. Assigning this to you.
@anuj-rathore Are you working on this?
I think @anuj-rathore is inactive. You can work on this @isht3
I am up for this...

On 08-Jan-2018 12:29 PM, "Akash Jain" <notifications@github.com> wrote:

> I think @anuj-rathore <https://github.com/anuj-rathore> is inactive. You
> can work on this @isht3 <https://github.com/isht3>
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/Cloud-CV/EvalAI/issues/1080#issuecomment-355894409>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AMIQ0M7rgh6cpUabER5IFD6YuP5C3CIBks5tIby5gaJpZM4OQ9KU>
> .
>

@isht3 you have started working on this?
@aka-jain Nope!
Wow, lot of comments. I think the final conclusion is that @anuj-rathore you can start working on this. :) Feel free to ask questions if you have any. 
I am really sorry, as I am quite busy these days! It would be really good if you could assign this to someone else @deshraj @aka-jain 
Can I claim this assignment?
Sure @codervivek. :) 

Resolving patch:
diff --git a/apps/challenges/views.py b/apps/challenges/views.py
--- a/apps/challenges/views.py
+++ b/apps/challenges/views.py
@@ -237,6 +237,9 @@ def get_all_challenges(request, challenge_time):
         q_params['start_date__gt'] = timezone.now()
     # for `all` we dont need any condition in `q_params`
 
+    # don't return disabled challenges
+    q_params['is_disabled'] = False
+
     challenge = Challenge.objects.filter(**q_params)
     paginator, result_page = paginated_queryset(challenge, request)
     serializer = ChallengeSerializer(result_page, many=True, context={'request': request})
@@ -252,6 +255,9 @@ def get_challenge_by_pk(request, pk):
     """
     try:
         challenge = Challenge.objects.get(pk=pk)
+        if (challenge.is_disabled):
+            response_data = {'error': 'Sorry, the challenge was removed!'}
+            return Response(response_data, status=status.HTTP_406_NOT_ACCEPTABLE)
         serializer = ChallengeSerializer(challenge, context={'request': request})
         response_data = serializer.data
         return Response(response_data, status=status.HTTP_200_OK)


Test patch:
diff --git a/tests/unit/challenges/test_views.py b/tests/unit/challenges/test_views.py
--- a/tests/unit/challenges/test_views.py
+++ b/tests/unit/challenges/test_views.py
@@ -619,7 +619,7 @@ def setUp(self):
         # Past Challenge challenge
         self.challenge3 = Challenge.objects.create(
             title='Test Challenge 3',
-            short_description='Short description for test challenge 2',
+            short_description='Short description for test challenge 3',
             description='Description for test challenge 3',
             terms_and_conditions='Terms and conditions for test challenge 3',
             submission_guidelines='Submission guidelines for test challenge 3',
@@ -648,6 +648,23 @@ def setUp(self):
             end_date=timezone.now() + timedelta(days=1),
         )
 
+        # Disabled challenge
+        self.challenge5 = Challenge.objects.create(
+            title='Test Challenge 5',
+            short_description='Short description for test challenge 5',
+            description='Description for test challenge 5',
+            terms_and_conditions='Terms and conditions for test challenge 5',
+            submission_guidelines='Submission guidelines for test challenge 5',
+            creator=self.challenge_host_team,
+            published=True,
+            enable_forum=True,
+            approved_by_admin=True,
+            anonymous_leaderboard=False,
+            start_date=timezone.now() + timedelta(days=2),
+            end_date=timezone.now() + timedelta(days=1),
+            is_disabled=True
+        )
+
     def test_get_past_challenges(self):
         expected = [
             {
@@ -839,6 +856,21 @@ def setUp(self):
             end_date=timezone.now() + timedelta(days=1),
         )
 
+        self.challenge4 = Challenge.objects.create(
+            title='Test Challenge 4',
+            short_description='Short description for test challenge 4',
+            description='Description for test challenge 4',
+            terms_and_conditions='Terms and conditions for test challenge 4',
+            submission_guidelines='Submission guidelines for test challenge 4',
+            creator=self.challenge_host_team,
+            published=True,
+            enable_forum=True,
+            anonymous_leaderboard=False,
+            start_date=timezone.now() - timedelta(days=2),
+            end_date=timezone.now() + timedelta(days=1),
+            is_disabled=True
+        )
+
     def test_get_challenge_by_pk_when_challenge_does_not_exists(self):
         self.url = reverse_lazy('challenges:get_challenge_by_pk',
                                 kwargs={'pk': self.challenge3.pk + 10})
@@ -849,6 +881,16 @@ def test_get_challenge_by_pk_when_challenge_does_not_exists(self):
         self.assertEqual(response.data, expected)
         self.assertEqual(response.status_code, status.HTTP_406_NOT_ACCEPTABLE)
 
+    def test_get_challenge_by_pk_when_challenge_is_disabled(self):
+        self.url = reverse_lazy('challenges:get_challenge_by_pk',
+                                kwargs={'pk': self.challenge4.pk})
+        expected = {
+            'error': 'Sorry, the challenge was removed!'
+        }
+        response = self.client.get(self.url, {})
+        self.assertEqual(response.data, expected)
+        self.assertEqual(response.status_code, status.HTTP_406_NOT_ACCEPTABLE)
+
 
 class GetChallengeBasedOnTeams(BaseAPITestClass):
 
@@ -2324,6 +2366,7 @@ def test_update_dataset_split_with_no_data(self):
 
 
 class StarChallengesTest(BaseAPITestClass):
+
     def setUp(self):
         super(StarChallengesTest, self).setUp()
         self.url = reverse_lazy('challenges:star_challenge',