Repository: Cloud-CV/EvalAI

Issue:
Change the logic to show featured challenge
## Current behavior

Currently, the challenge whose primary key is 1 is shown as the featured challenge on EvalAI. We would like to change it and show the challenge which has the featured challenge flag set as True in the database.

## Dependency : #1290 

## Deliverables

- [ ] Update the get challenges API to add support for the filtering the featured challenges as a query parameter "featured=True"
- [ ] Update the controller to fetch the featured challenge instead of fetching the first challenge
- [ ] Write unit tests for the updated API endpoint


Discussion:
Also, this depends on #1290 
@deshraj I'm done with #1277. Can I work on this?
@deshraj @xamfy Actually since this issue was related to #1290 I already started working on this as I am finished with #1290 . So should I go through with this?
@sehgalayush1 @xamfy Since this issue requires both front-end and backend changes, we will break it into two PR's.
1. For updating the API and writing its tests.
2. For updating the controller and the view.
Since both of you are interested in working on this. Please let us know which part you are working on. :)
@RishabhJain2018 first one
@RishabhJain2018 I'll work on the second one.
@xamfy Please add a /challenge/featured route in the get_all_challenges API, so that only challenges that have featured=True can be fetched and I'll modify the controller to fetch challenges from that url and display them.
Awesome!
I see!!
Can I work on this?
@codervivek sure, go ahead. 

Resolving patch:
diff --git a/apps/challenges/urls.py b/apps/challenges/urls.py
--- a/apps/challenges/urls.py
+++ b/apps/challenges/urls.py
@@ -19,6 +19,8 @@
     # `A-Za-z` because it accepts either of `all, future, past or present` in either case
     url(r'^challenge/(?P<challenge_time>[A-Za-z]+)$', views.get_all_challenges,
         name='get_all_challenges'),
+    url(r'^featured/$', views.get_featured_challenges,
+        name='get_featured_challenges'),
     url(r'^challenge/(?P<pk>[0-9]+)/$',
         views.get_challenge_by_pk, name='get_challenge_by_pk'),
     url(r'^challenge$', views.get_challenges_based_on_teams,
diff --git a/apps/challenges/views.py b/apps/challenges/views.py
--- a/apps/challenges/views.py
+++ b/apps/challenges/views.py
@@ -285,6 +285,23 @@ def get_all_challenges(request, challenge_time):
     return paginator.get_paginated_response(response_data)
 
 
+@throttle_classes([AnonRateThrottle])
+@api_view(['GET'])
+def get_featured_challenges(request):
+    """
+    Returns the list of featured challenges
+    """
+    challenge = Challenge.objects.filter(
+        featured=True,
+        published=True,
+        approved_by_admin=True,
+        is_disabled=False)
+    paginator, result_page = paginated_queryset(challenge, request)
+    serializer = ChallengeSerializer(result_page, many=True, context={'request': request})
+    response_data = serializer.data
+    return paginator.get_paginated_response(response_data)
+
+
 @throttle_classes([AnonRateThrottle])
 @api_view(['GET'])
 def get_challenge_by_pk(request, pk):


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
@@ -899,6 +899,77 @@ def test_incorrent_url_pattern_challenges(self):
         self.assertEqual(response.data, expected)
 
 
+class GetFeaturedChallengesTest(BaseAPITestClass):
+    url = reverse_lazy('challenges:get_featured_challenges')
+
+    def setUp(self):
+        super(GetFeaturedChallengesTest, self).setUp()
+        self.url = reverse_lazy('challenges:get_featured_challenges')
+
+        # Not a featured challenge
+        self.challenge2 = Challenge.objects.create(
+            title='Test Challenge 2',
+            short_description='Short description for test challenge 2',
+            description='Description for test challenge 2',
+            terms_and_conditions='Terms and conditions for test challenge 2',
+            submission_guidelines='Submission guidelines for test challenge 2',
+            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),
+        )
+
+        # Featured challenge
+        self.challenge3 = Challenge.objects.create(
+            title='Test Challenge 3',
+            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',
+            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),
+            featured=True
+        )
+
+    def test_get_featured_challenges(self):
+        expected = [
+            {
+                "id": self.challenge3.pk,
+                "title": self.challenge3.title,
+                "short_description": self.challenge3.short_description,
+                "description": self.challenge3.description,
+                "terms_and_conditions": self.challenge3.terms_and_conditions,
+                "submission_guidelines": self.challenge3.submission_guidelines,
+                "evaluation_details": self.challenge3.evaluation_details,
+                "image": None,
+                "start_date": "{0}{1}".format(self.challenge3.start_date.isoformat(), 'Z').replace("+00:00", ""),
+                "end_date": "{0}{1}".format(self.challenge3.end_date.isoformat(), 'Z').replace("+00:00", ""),
+                "creator": {
+                    "id": self.challenge3.creator.pk,
+                    "team_name": self.challenge3.creator.team_name,
+                    "created_by": self.challenge3.creator.created_by.username,
+                },
+                "published": self.challenge3.published,
+                "enable_forum": self.challenge3.enable_forum,
+                "anonymous_leaderboard": self.challenge3.anonymous_leaderboard,
+                "is_active": False,
+                "allowed_email_domains": self.challenge3.allowed_email_domains,
+                "blocked_email_domains": self.challenge3.blocked_email_domains,
+            }
+        ]
+        response = self.client.get(self.url, {}, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data['results'], expected)
+
+
 class GetChallengeByPk(BaseAPITestClass):
 
     def setUp(self):