From 56b932d8d71310a27c755d84eca3c96478bf2150 Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 22 Jul 2024 15:49:47 +0200 Subject: [PATCH 1/8] Add language and track to create_talk --- wafer/talks/tests/fixtures.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/wafer/talks/tests/fixtures.py b/wafer/talks/tests/fixtures.py index 01235db1..20eb317c 100644 --- a/wafer/talks/tests/fixtures.py +++ b/wafer/talks/tests/fixtures.py @@ -7,7 +7,8 @@ def create_talk_type(name, **kwargs): return TalkType.objects.create(name=name, **kwargs) -def create_talk(title, status, username=None, user=None, talk_type=None): +def create_talk(title, status, username=None, user=None, talk_type=None, + talk_track=None, language=None): if sum((user is None, username is None)) != 1: raise ValueError('One of user OR username must be specified') if username: @@ -21,4 +22,10 @@ def create_talk(title, status, username=None, user=None, talk_type=None): if talk_type: talk.talk_type = talk_type talk.save() + if talk_track: + talk.track = talk_track + talk.save() + if language: + talk.language = language + talk.save() return talk From 9a79f103269eaaa8ea8e659e6eb563e6e29fc50d Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 22 Jul 2024 15:50:11 +0200 Subject: [PATCH 2/8] Add parameter to sort talks --- wafer/talks/views.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/wafer/talks/views.py b/wafer/talks/views.py index 5f22f4f0..6ed04ca7 100644 --- a/wafer/talks/views.py +++ b/wafer/talks/views.py @@ -45,7 +45,6 @@ class UsersTalks(PaginatedBuildableListView): build_prefix = 'talks' paginate_by = 100 - @order_results_by('talk_type', 'talk_id') def get_queryset(self): # self.request will be None when we come here via the static site # renderer @@ -57,8 +56,20 @@ def get_queryset(self): | Q(status__in=(SUBMITTED, UNDER_CONSIDERATION, PROVISIONAL), talk_type__show_pending_submissions=True) ) + if self.request: + if self.request.GET.get('sort') == 'track' and Track.objects.count() > 0: + talks = talks.order_by('talk_type', 'track') + elif self.request.GET.get('sort') == 'lang' and Talk.LANGUAGES: + talks = talks.order_by('talk_type', 'language') + elif self.request.GET.get('sort') == 'title': + talks = talks.order_by('talk_type', 'title') + else: + talks = talks.order_by('talk_type', 'talk_id') + else: + talks = talks.order_by('talk_type', 'talk_id') return talks.prefetch_related( - "talk_type", "corresponding_author", "authors", "authors__userprofile" + "talk_type", "corresponding_author", "authors", "authors__userprofile", + "track" ) def get_context_data(self, **kwargs): From ccd47f07982bf7fcd81cd313ef7e94abe442510b Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 22 Jul 2024 15:50:25 +0200 Subject: [PATCH 3/8] Add test for sorting behavior --- wafer/talks/tests/test_views.py | 76 +++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/wafer/talks/tests/test_views.py b/wafer/talks/tests/test_views.py index 9ab8f987..0d103308 100644 --- a/wafer/talks/tests/test_views.py +++ b/wafer/talks/tests/test_views.py @@ -89,8 +89,8 @@ def test_no_options(self): self.assertNotContains(response, 'Language', html=True) self.assertNotContains(response, '\nNo talks accepted yet.\n', html=True) - def test_langauge(self): - """Test that we have the right layout if langauges, but no tracks""" + def test_language(self): + """Test that we have the right layout if languages, but no tracks""" Talk.LANGUAGES = (('en', 'English'),) response = self.client.get('/talks/') @@ -114,7 +114,7 @@ def test_langauge(self): def test_track(self): """Test that we have the right layout if tracks, but no languages""" - track1 = Track.objects.create(name="Test Trakc 1") + track1 = Track.objects.create(name="Test Track 1") response = self.client.get('/talks/') self.assertTrue(response.context['tracks']) self.assertEqual(len(response.context['languages']), 0) @@ -137,7 +137,7 @@ def test_track(self): def test_track_and_language(self): """Test that we have the right layout if we have tracks and languages""" - track1 = Track.objects.create(name="Test Trakc 1") + track1 = Track.objects.create(name="Test Track 1") Talk.LANGUAGES = (('en', 'English'),) response = self.client.get('/talks/') @@ -160,6 +160,74 @@ def test_track_and_language(self): self.assertNotContains(response, '\nNo talks accepted yet.\n', html=True) +class TalksListSortingTests(TestCase): + """Test the table sorting options. + + This monkey-patches TALKS.languages for the same reason as the layout tests. + """ + + def setUp(self): + """Create talks and tracks""" + self.client = Client() + Talk.LANGUAGES = (('en', 'English'), ('de', 'German')) + + author = create_user('author_a') + + # We choose the names so that they sort differently from creation order + track2 = Track.objects.create(name="Test Track 2", order=2) + track1 = Track.objects.create(name="Test Track 1", order=1) + + talk_d = create_talk('Talk D', ACCEPTED, user=author, talk_track=track1, + language='en') + talk_c = create_talk('Talk C', ACCEPTED, user=author, talk_track=track2, + language='de') + talk_b = create_talk('Talk B', ACCEPTED, user=author, talk_track=track1, + language='de') + talk_a = create_talk('Talk A', ACCEPTED, user=author, talk_track=track2, + language='en') + + def tearDown(self): + """Ensure Talk monkey-patching doesn't leak""" + Talk.LANGUAGES = () + + def test_sort_title(self): + response = self.client.get('/talks/?sort=title') + # We check via find to avoid hardcoding too much HTML here + pos_talk_a = response.content.find(b'Talk A') + pos_talk_b = response.content.find(b'Talk B') + pos_talk_c = response.content.find(b'Talk C') + pos_talk_d = response.content.find(b'Talk D') + self.assertGreater(pos_talk_b, pos_talk_a) + self.assertGreater(pos_talk_c, pos_talk_b) + self.assertGreater(pos_talk_d, pos_talk_c) + + def test_sort_track(self): + response = self.client.get('/talks/?sort=track') + pos_talk_a = response.content.find(b'Talk A') + pos_talk_b = response.content.find(b'Talk B') + pos_talk_c = response.content.find(b'Talk C') + pos_talk_d = response.content.find(b'Talk D') + + # track 1 (B, D) should sort before track 2 (A, C) + self.assertGreater(pos_talk_a, pos_talk_b) + self.assertGreater(pos_talk_c, pos_talk_b) + self.assertGreater(pos_talk_a, pos_talk_d) + self.assertGreater(pos_talk_c, pos_talk_d) + + def test_sort_lang(self): + response = self.client.get('/talks/?sort=lang') + pos_talk_a = response.content.find(b'Talk A') + pos_talk_b = response.content.find(b'Talk B') + pos_talk_c = response.content.find(b'Talk C') + pos_talk_d = response.content.find(b'Talk D') + + # de (B, C) should sort before en (A, D) + self.assertGreater(pos_talk_a, pos_talk_b) + self.assertGreater(pos_talk_a, pos_talk_c) + self.assertGreater(pos_talk_d, pos_talk_b) + self.assertGreater(pos_talk_d, pos_talk_c) + + class TalkViewTests(TestCase): def setUp(self): public_type = create_talk_type(name="BoF", show_pending_submissions=True) From 479ceba9b185b0acc43768d16fc01adda233ed62 Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Wed, 24 Jul 2024 13:23:02 +0200 Subject: [PATCH 4/8] Add unsorted case to tests --- wafer/talks/tests/test_views.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/wafer/talks/tests/test_views.py b/wafer/talks/tests/test_views.py index 0d103308..584305e4 100644 --- a/wafer/talks/tests/test_views.py +++ b/wafer/talks/tests/test_views.py @@ -190,13 +190,25 @@ def tearDown(self): """Ensure Talk monkey-patching doesn't leak""" Talk.LANGUAGES = () + def test_no_sorting(self): + response = self.client.get('/talks/') + # We check via find to avoid hardcoding too much HTML here + pos_talk_a = response.content.find(b'Talk A') + pos_talk_b = response.content.find(b'Talk B') + pos_talk_c = response.content.find(b'Talk C') + pos_talk_d = response.content.find(b'Talk D') + # Order should be D, C, B, A (id order) + self.assertGreater(pos_talk_a, pos_talk_b) + self.assertGreater(pos_talk_b, pos_talk_c) + self.assertGreater(pos_talk_c, pos_talk_d) + def test_sort_title(self): response = self.client.get('/talks/?sort=title') - # We check via find to avoid hardcoding too much HTML here pos_talk_a = response.content.find(b'Talk A') pos_talk_b = response.content.find(b'Talk B') pos_talk_c = response.content.find(b'Talk C') pos_talk_d = response.content.find(b'Talk D') + # Should be A, B, C, D self.assertGreater(pos_talk_b, pos_talk_a) self.assertGreater(pos_talk_c, pos_talk_b) self.assertGreater(pos_talk_d, pos_talk_c) From 62aded5cef8e8148748a3c5c7663ace27e4e9a33 Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 19 Aug 2024 15:12:53 +0200 Subject: [PATCH 5/8] Pass sorted flag back to template for links --- wafer/talks/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wafer/talks/views.py b/wafer/talks/views.py index 6ed04ca7..cbbdb6fc 100644 --- a/wafer/talks/views.py +++ b/wafer/talks/views.py @@ -77,6 +77,10 @@ def get_context_data(self, **kwargs): context["languages"] = Talk.LANGUAGES context["tracks"] = Track.objects.count() > 0 context["see_all"] = Talk.can_view_all(self.request.user) + if self.request.GET.get('sort'): + context['sort'] = self.request.GET.get('sort') + else: + context['sort'] = 'default' return context From 390d633807a7757bda4d327bb21dc861674be04a Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 19 Aug 2024 15:41:35 +0200 Subject: [PATCH 6/8] Add clickable headers to the table for sorting --- wafer/talks/templates/wafer.talks/talks.html | 28 +++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/wafer/talks/templates/wafer.talks/talks.html b/wafer/talks/templates/wafer.talks/talks.html index 6c87c81e..f5f6a1e4 100644 --- a/wafer/talks/templates/wafer.talks/talks.html +++ b/wafer/talks/templates/wafer.talks/talks.html @@ -18,14 +18,28 @@

{% trans "Accepted Talks" %}

- {% if type %} - {{ type }} - {% else %} - {% trans "Talk" %} - {% endif %} + + {% if type %} + {{ type }} + {% else %} + {% trans "Talk" %} + {% endif %} + - {% if tracks %}{% trans "Track" %}{% endif %} - {% if languages %}{% trans "Language" %}{% endif %} + {% if tracks %} + + + {% trans "Track" %} + + + {% endif %} + {% if languages %} + + + {% trans "Language" %} + + + {% endif %} {% trans "Speakers" %} From 4b8f37c47467340dd9e08a276e37ee5e8c8849ae Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 19 Aug 2024 15:42:30 +0200 Subject: [PATCH 7/8] Pass sort flag through to pagination --- wafer/talks/templates/wafer.talks/talks.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wafer/talks/templates/wafer.talks/talks.html b/wafer/talks/templates/wafer.talks/talks.html index f5f6a1e4..0d4fe9ae 100644 --- a/wafer/talks/templates/wafer.talks/talks.html +++ b/wafer/talks/templates/wafer.talks/talks.html @@ -104,15 +104,15 @@

{% trans "Accepted Talks" %}

    {% if page_obj.has_previous %} -
  • «
  • +
  • «
  • {% else %}
  • «
  • {% endif %} {% for page in paginator.page_range %} -
  • {{ page }}
  • +
  • {{ page }}
  • {% endfor %} {% if page_obj.has_next %} -
  • »
  • +
  • »
  • {% else %}
  • »
  • {% endif %} From 4edc96df5b29c6f5aea4cb44c862588c00d4e38f Mon Sep 17 00:00:00 2001 From: Neil Muller Date: Mon, 19 Aug 2024 18:26:08 +0200 Subject: [PATCH 8/8] Update wafer/talks/views.py Appy feedback from PR Co-authored-by: Stefano Rivera --- wafer/talks/views.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/wafer/talks/views.py b/wafer/talks/views.py index cbbdb6fc..72d7e00d 100644 --- a/wafer/talks/views.py +++ b/wafer/talks/views.py @@ -77,10 +77,7 @@ def get_context_data(self, **kwargs): context["languages"] = Talk.LANGUAGES context["tracks"] = Track.objects.count() > 0 context["see_all"] = Talk.can_view_all(self.request.user) - if self.request.GET.get('sort'): - context['sort'] = self.request.GET.get('sort') - else: - context['sort'] = 'default' + context['sort'] = self.request.GET.get('sort', 'default') return context