From 295108c9a4ff5c43bc1cfef14019e5e8c9192979 Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 19 Aug 2015 12:28:33 -0400 Subject: [PATCH] Add sorting by last_activity_at. TNL-3011 --- lms/djangoapps/teams/tests/test_views.py | 17 +++++++++++++---- lms/djangoapps/teams/views.py | 19 +++++++++---------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lms/djangoapps/teams/tests/test_views.py b/lms/djangoapps/teams/tests/test_views.py index a2b01c3bcd..a5601856e2 100644 --- a/lms/djangoapps/teams/tests/test_views.py +++ b/lms/djangoapps/teams/tests/test_views.py @@ -436,13 +436,22 @@ class TestListTeamsAPI(TeamAPITestCase): @ddt.data( (None, 200, ['Nuclear Team', u'sólar team', 'Wind Team']), ('name', 200, ['Nuclear Team', u'sólar team', 'Wind Team']), - # Note that "Nuclear Team" and "solar team" have the same number of open slots. - # "Nuclear Team" comes first due to secondary sort by name. - ('open_slots', 200, ['Wind Team', 'Nuclear Team', u'sólar team']), - ('last_activity', 400, []), + # Note that "Nuclear Team" and "solar team" have the same open_slots. + # "solar team" comes first due to secondary sort by last_activity_at. + ('open_slots', 200, ['Wind Team', u'sólar team', 'Nuclear Team']), + # Note that "Wind Team" and "Nuclear Team" have the same last_activity_at. + # "Wind Team" comes first due to secondary sort by open_slots. + ('last_activity_at', 200, [u'sólar team', 'Wind Team', 'Nuclear Team']), ) @ddt.unpack def test_order_by(self, field, status, names): + # Make "solar team" the most recently active team. + # The CourseTeamFactory sets the last_activity_at to a fixed time (in the past), so all of the + # other teams have the same last_activity_at. + solar_team = self.test_team_name_id_map[u'sólar team'] + solar_team.last_activity_at = datetime.utcnow().replace(tzinfo=pytz.utc) + solar_team.save() + data = {'order_by': field} if field else {} self.verify_names(data, status, names) diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index a44d14fc5a..58781d8463 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -175,9 +175,11 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): * name: Orders results by case insensitive team name (default). - * open_slots: Orders results by most open slots (with name as a secondary sort). + * open_slots: Orders results by most open slots (for tie-breaking, + last_activity_at is used, with most recent first). - * last_activity: Currently not supported. + * last_activity_at: Orders result by team activity, with most active first + (for tie-breaking, open_slots is used, with most open slots first). * page_size: Number of results to return per page. @@ -331,20 +333,17 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView): ) queryset = CourseTeam.objects.filter(**result_filter) - # We will always use name as either a primary or secondary sort. - queryset = queryset.extra(select={'lower_name': "lower(name)"}) order_by_input = request.QUERY_PARAMS.get('order_by', 'name') if order_by_input == 'name': + queryset = queryset.extra(select={'lower_name': "lower(name)"}) queryset = queryset.order_by('lower_name') elif order_by_input == 'open_slots': queryset = queryset.annotate(team_size=Count('users')) - queryset = queryset.order_by('team_size', 'lower_name') - elif order_by_input == 'last_activity': - return Response( - build_api_error(ugettext_noop("last_activity is not yet supported")), - status=status.HTTP_400_BAD_REQUEST - ) + queryset = queryset.order_by('team_size', '-last_activity_at') + elif order_by_input == 'last_activity_at': + queryset = queryset.annotate(team_size=Count('users')) + queryset = queryset.order_by('-last_activity_at', 'team_size') else: return Response({ 'developer_message': "unsupported order_by value {ordering}".format(ordering=order_by_input),