From d3f297d6122071c0f7df28b08df93369e801d725 Mon Sep 17 00:00:00 2001 From: Rudi Matz Date: Wed, 2 Apr 2025 14:07:59 -0400 Subject: [PATCH 1/2] fix: unexpected chatlog links --- ietf/meeting/templatetags/session_filters.py | 4 ++ ietf/meeting/templatetags/tests.py | 45 ++++++++++++++++++- .../meeting/session_buttons_include.html | 29 +++++++----- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/ietf/meeting/templatetags/session_filters.py b/ietf/meeting/templatetags/session_filters.py index 3846dab49e2..cf99119903a 100644 --- a/ietf/meeting/templatetags/session_filters.py +++ b/ietf/meeting/templatetags/session_filters.py @@ -54,3 +54,7 @@ def describe_with_tz(session): ) ss0name += f" {session.meeting.tz()}" return f"{session.meeting}: {session.group.acronym} {session.name} {ss0name}" + +@register.filter +def get_chatlog(chatlog_and_polls): + return next((poll.document for poll in chatlog_and_polls if poll.document.type_id == 'chatlog'), None) diff --git a/ietf/meeting/templatetags/tests.py b/ietf/meeting/templatetags/tests.py index 5093ecd4bb7..f2a76482998 100644 --- a/ietf/meeting/templatetags/tests.py +++ b/ietf/meeting/templatetags/tests.py @@ -5,9 +5,11 @@ from django.template import Context, Template from pyquery import PyQuery -from ietf.meeting.factories import FloorPlanFactory, RoomFactory, TimeSlotFactory +from ietf.meeting.factories import FloorPlanFactory, RoomFactory, TimeSlotFactory, SessionFactory, SessionPresentationFactory +from ietf.doc.factories import DocumentFactory from ietf.meeting.templatetags.agenda_custom_tags import AnchorNode from ietf.meeting.templatetags.editor_tags import constraint_icon_for +from ietf.meeting.templatetags.session_filters import get_chatlog from ietf.name.models import ConstraintName from ietf.utils.test_utils import TestCase @@ -124,3 +126,44 @@ def test_constraint_icon_for(self): expected, f'Unexpected output for {slug} {params}', ) + +class GetChatlogFilterTest(TestCase): + def test_get_chatlog_returns_chatlog_document(self): + # Test when a chatlog document exists + session = SessionFactory() + chatlog = DocumentFactory(type_id="chatlog", name='chatlog-72-mars-197001010000') + polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') + chatlog_and_polls = [ + SessionPresentationFactory(document=chatlog, session=session), + SessionPresentationFactory(document=polls, session=session) + ] + result = get_chatlog(chatlog_and_polls) + self.assertEqual(result, chatlog) + + def test_get_chatlog_returns_chatlog_document_inverse_order(self): + # Test when a chatlog document exists + session = SessionFactory() + chatlog = DocumentFactory(type_id="chatlog", name='chatlog-72-mars-197001010000') + polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') + chatlog_and_polls = [ + SessionPresentationFactory(document=polls, session=session), + SessionPresentationFactory(document=chatlog, session=session) + ] + result = get_chatlog(chatlog_and_polls) + self.assertEqual(result, chatlog) + + def test_get_chatlog_returns_none_when_no_chatlog(self): + # Test when no chatlog document exists + session = SessionFactory() + polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') + chatlog_and_polls = [ + SessionPresentationFactory(document=polls, session=session) + ] + result = get_chatlog(chatlog_and_polls) + self.assertIsNone(result) + + def test_get_chatlog_returns_none_when_empty_list(self): + # Test when the input list is empty + chatlog_and_polls = [] + result = get_chatlog(chatlog_and_polls) + self.assertIsNone(result) diff --git a/ietf/templates/meeting/session_buttons_include.html b/ietf/templates/meeting/session_buttons_include.html index bb5144b45d6..1851222c4c4 100644 --- a/ietf/templates/meeting/session_buttons_include.html +++ b/ietf/templates/meeting/session_buttons_include.html @@ -2,7 +2,8 @@ {% load origin %} {% load static %} {% load textfilters tz %} -{% load ietf_filters %} +{% load ietf_filters session_filters %} + {% origin %} {% if item and item|should_show_agenda_session_buttons %} {% with slug=item.slug session=item.session timeslot=item.timeslot %} @@ -127,13 +128,17 @@ {% else %} {# chat logs #} {% if meeting.has_chat_logs %} - - - + {% with session.filtered_chatlog_and_polls|get_chatlog as chatlog %} + {% if chatlog %} + + + + {% endif %} + {% endwith %} {% endif %} {# Recordings #} {% if meeting.has_recordings %} @@ -303,13 +308,17 @@ {% else %} {# chat logs #} - {% if meeting.has_chat_logs %} + {% if meeting.has_chat_logs %} + {% with session.filtered_chatlog_and_polls|get_chatlog as chatlog %} + {% if chatlog %}
  • + href="/doc/{{ chatlog.name }}"> Chat logs
  • + {% endif %} + {% endwith %} {% endif %} {# Recordings #} {% if meeting.has_recordings %} From da56ffd422b6ffec6ccada942b984061f468f2b3 Mon Sep 17 00:00:00 2001 From: Rudi Matz Date: Thu, 3 Apr 2025 16:00:56 -0400 Subject: [PATCH 2/2] fix: separate handling of polls and chatlogs --- ietf/meeting/templatetags/session_filters.py | 4 -- ietf/meeting/templatetags/tests.py | 45 +------------------ ietf/meeting/tests_views.py | 38 ++++++++++++++++ ietf/meeting/views.py | 8 +++- .../meeting/session_buttons_include.html | 28 +++++------- 5 files changed, 56 insertions(+), 67 deletions(-) diff --git a/ietf/meeting/templatetags/session_filters.py b/ietf/meeting/templatetags/session_filters.py index cf99119903a..3846dab49e2 100644 --- a/ietf/meeting/templatetags/session_filters.py +++ b/ietf/meeting/templatetags/session_filters.py @@ -54,7 +54,3 @@ def describe_with_tz(session): ) ss0name += f" {session.meeting.tz()}" return f"{session.meeting}: {session.group.acronym} {session.name} {ss0name}" - -@register.filter -def get_chatlog(chatlog_and_polls): - return next((poll.document for poll in chatlog_and_polls if poll.document.type_id == 'chatlog'), None) diff --git a/ietf/meeting/templatetags/tests.py b/ietf/meeting/templatetags/tests.py index f2a76482998..5093ecd4bb7 100644 --- a/ietf/meeting/templatetags/tests.py +++ b/ietf/meeting/templatetags/tests.py @@ -5,11 +5,9 @@ from django.template import Context, Template from pyquery import PyQuery -from ietf.meeting.factories import FloorPlanFactory, RoomFactory, TimeSlotFactory, SessionFactory, SessionPresentationFactory -from ietf.doc.factories import DocumentFactory +from ietf.meeting.factories import FloorPlanFactory, RoomFactory, TimeSlotFactory from ietf.meeting.templatetags.agenda_custom_tags import AnchorNode from ietf.meeting.templatetags.editor_tags import constraint_icon_for -from ietf.meeting.templatetags.session_filters import get_chatlog from ietf.name.models import ConstraintName from ietf.utils.test_utils import TestCase @@ -126,44 +124,3 @@ def test_constraint_icon_for(self): expected, f'Unexpected output for {slug} {params}', ) - -class GetChatlogFilterTest(TestCase): - def test_get_chatlog_returns_chatlog_document(self): - # Test when a chatlog document exists - session = SessionFactory() - chatlog = DocumentFactory(type_id="chatlog", name='chatlog-72-mars-197001010000') - polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') - chatlog_and_polls = [ - SessionPresentationFactory(document=chatlog, session=session), - SessionPresentationFactory(document=polls, session=session) - ] - result = get_chatlog(chatlog_and_polls) - self.assertEqual(result, chatlog) - - def test_get_chatlog_returns_chatlog_document_inverse_order(self): - # Test when a chatlog document exists - session = SessionFactory() - chatlog = DocumentFactory(type_id="chatlog", name='chatlog-72-mars-197001010000') - polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') - chatlog_and_polls = [ - SessionPresentationFactory(document=polls, session=session), - SessionPresentationFactory(document=chatlog, session=session) - ] - result = get_chatlog(chatlog_and_polls) - self.assertEqual(result, chatlog) - - def test_get_chatlog_returns_none_when_no_chatlog(self): - # Test when no chatlog document exists - session = SessionFactory() - polls = DocumentFactory(type_id="polls", name='polls-72-mars-197001010000') - chatlog_and_polls = [ - SessionPresentationFactory(document=polls, session=session) - ] - result = get_chatlog(chatlog_and_polls) - self.assertIsNone(result) - - def test_get_chatlog_returns_none_when_empty_list(self): - # Test when the input list is empty - chatlog_and_polls = [] - result = get_chatlog(chatlog_and_polls) - self.assertIsNone(result) diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 0f91986f77d..90e096b4473 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -7710,6 +7710,44 @@ def test_add_session_recordings(self): self.assertEqual(r.status_code, 404) self.assertFalse(mock_delete.called) + def test_show_chatlog_links(self): + meeting = MeetingFactory(type_id='ietf', number='122') + session = SessionFactory(meeting=meeting) + doc_name = 'chatlog-72-mars-197001010000' + SessionPresentation.objects.create(session=session,document=DocumentFactory(type_id='chatlog', name=doc_name)) + + session_url = urlreverse('ietf.meeting.views.session_details', + kwargs={'num':meeting.number, 'acronym':session.group.acronym}) + + r = self.client.get(session_url) + + self.assertEqual(r.status_code, 200) + + q = PyQuery(r.content) + + # Find the chatlog link in the desktop view + link_chatlog_box = q(f'a[title="Chat logs for {session.group.acronym}"]') + self.assertTrue(link_chatlog_box, 'Expected element with title "Chat logs for {group.acronym}" not found.') + self.assertEqual(link_chatlog_box.attr('href'), '/doc/'+ doc_name) + + # Find the chatlog link in the mobile view + link_chatlog_list = q('li:contains("Chat logs")') + self.assertTrue(link_chatlog_list, 'Expected
  • element containing "Chat logs" not found.') + self.assertEqual(link_chatlog_list.find('a').attr('href'), '/doc/'+ doc_name) + + def test_hide_chatlog_links(self): + # mock meeting and session, but no chatlog document + meeting = MeetingFactory(type_id='ietf', number='122') + session = SessionFactory(meeting=meeting) + + session_url = urlreverse('ietf.meeting.views.session_details', + kwargs={'num':meeting.number, 'acronym':session.group.acronym}) + + r = self.client.get(session_url) + + self.assertEqual(r.status_code, 200) + # validate no links for chat logs exist + self.assertNotContains(r, 'Chat logs') class HasMeetingsTests(TestCase): diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 6a73059d922..45f6842cb8d 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -23,6 +23,7 @@ from urllib.parse import parse_qs, unquote, urlencode, urlsplit, urlunsplit, urlparse from tempfile import mkstemp from wsgiref.handlers import format_date_time +from itertools import chain from django import forms from django.core.cache import caches @@ -2496,7 +2497,12 @@ def session_details(request, num, acronym): session.filtered_artifacts.sort(key=lambda d:artifact_types.index(d.document.type.slug)) session.filtered_slides = session.presentations.filter(document__type__slug='slides').order_by('order') session.filtered_drafts = session.presentations.filter(document__type__slug='draft') - session.filtered_chatlog_and_polls = session.presentations.filter(document__type__slug__in=('chatlog', 'polls')).order_by('document__type__slug') + + filtered_polls = session.presentations.filter(document__type__slug=('polls')) + filtered_chatlogs = session.presentations.filter(document__type__slug=('chatlog')) + session.filtered_chatlog_and_polls = chain(filtered_chatlogs, filtered_polls) + session.chatlog = filtered_chatlogs.first() + # TODO FIXME Deleted materials shouldn't be in the presentations for qs in [session.filtered_artifacts,session.filtered_slides,session.filtered_drafts]: qs = [p for p in qs if p.document.get_state_slug(p.document.type_id)!='deleted'] diff --git a/ietf/templates/meeting/session_buttons_include.html b/ietf/templates/meeting/session_buttons_include.html index 1851222c4c4..b1fd92ba5be 100644 --- a/ietf/templates/meeting/session_buttons_include.html +++ b/ietf/templates/meeting/session_buttons_include.html @@ -127,18 +127,14 @@ {% else %} {# chat logs #} - {% if meeting.has_chat_logs %} - {% with session.filtered_chatlog_and_polls|get_chatlog as chatlog %} - {% if chatlog %} - - - - {% endif %} - {% endwith %} + {% if meeting.has_chat_logs and session.chatlog %} + + + {% endif %} {# Recordings #} {% if meeting.has_recordings %} @@ -308,17 +304,13 @@
  • {% else %} {# chat logs #} - {% if meeting.has_chat_logs %} - {% with session.filtered_chatlog_and_polls|get_chatlog as chatlog %} - {% if chatlog %} + {% if meeting.has_chat_logs and session.chatlog %}
  • + href="/doc/{{ session.chatlog.document.name }}"> Chat logs
  • - {% endif %} - {% endwith %} {% endif %} {# Recordings #} {% if meeting.has_recordings %}