From 8759339e655cbb5531e833eaaf99a48e43b63ff9 Mon Sep 17 00:00:00 2001 From: Ole Laursen Date: Fri, 28 Aug 2020 12:28:29 +0000 Subject: [PATCH] Make the upcoming meetings iCal group the IETF meetings into one block and add important dates. Also fix a couple of bugs found by running the generated .ics through the icalendar.org validator. - Legacy-Id: 18434 --- ietf/meeting/tests_views.py | 18 ++++++++++---- ietf/meeting/utils.py | 8 +++++++ ietf/meeting/views.py | 24 ++++++++----------- ietf/templates/meeting/important_dates.ics | 23 +----------------- .../meeting/important_dates_for_meeting.ics | 22 +++++++++++++++++ ietf/templates/meeting/upcoming.ics | 16 ++++++++++--- 6 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 ietf/templates/meeting/important_dates_for_meeting.ics diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index 80cb85bb5..579fd93d9 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -1931,7 +1931,6 @@ class InterimTests(TestCase): make_meeting_test_data(create_interims=True) url = urlreverse("ietf.meeting.views.upcoming") today = datetime.date.today() - add_event_info_to_session_qs(Session.objects.filter(meeting__type='interim', group__acronym='mars')).filter(current_status='apprw').first() mars_interim = add_event_info_to_session_qs(Session.objects.filter(meeting__type='interim', meeting__date__gt=today, group__acronym='mars')).filter(current_status='sched').first().meeting ames_interim = add_event_info_to_session_qs(Session.objects.filter(meeting__type='interim', meeting__date__gt=today, group__acronym='ames')).filter(current_status='canceled').first().meeting r = self.client.get(url) @@ -1944,19 +1943,28 @@ class InterimTests(TestCase): self.check_interim_tabs(url) def test_upcoming_ical(self): - make_meeting_test_data(create_interims=True) + meeting = make_meeting_test_data(create_interims=True) + populate_important_dates(meeting) + url = urlreverse("ietf.meeting.views.upcoming_ical") r = self.client.get(url) self.assertEqual(r.status_code, 200) + + today = datetime.date.today() + mars_interim = add_event_info_to_session_qs(Session.objects.filter(meeting__type='interim', meeting__date__gt=today, group__acronym='mars')).filter(current_status='sched').first().meeting + ames_interim = add_event_info_to_session_qs(Session.objects.filter(meeting__type='interim', meeting__date__gt=today, group__acronym='ames')).filter(current_status='canceled').first().meeting + self.assertContains(r, mars_interim.number) + self.assertContains(r, ames_interim.number) + self.assertContains(r, 'IETF 72') self.assertEqual(r.get('Content-Type'), "text/calendar") - self.assertEqual(r.content.count(b'UID'), 7) + self.assertEqual(r.content.count(b'UID'), 3 + meeting.importantdate_set.count()) + # check filtered output url = url + '?filters=mars' r = self.client.get(url) self.assertEqual(r.status_code, 200) self.assertEqual(r.get('Content-Type'), "text/calendar") - # print r.content - self.assertEqual(r.content.count(b'UID'), 2) + self.assertEqual(r.content.count(b'UID'), 2 + meeting.importantdate_set.count()) def test_upcoming_json(self): diff --git a/ietf/meeting/utils.py b/ietf/meeting/utils.py index 15f97f880..27567541b 100644 --- a/ietf/meeting/utils.py +++ b/ietf/meeting/utils.py @@ -560,3 +560,11 @@ def swap_meeting_schedule_timeslot_assignments(schedule, source_timeslots, targe if not swapped: for a in lts_assignments: a.delete() + +def preprocess_meeting_important_dates(meetings): + for m in meetings: + m.cached_updated = m.updated() + m.important_dates = m.importantdate_set.prefetch_related("name") + for d in m.important_dates: + d.midnight_cutoff = "UTC 23:59" in d.name.name + diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 9f3fc251b..5320970c4 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -81,6 +81,7 @@ from ietf.meeting.utils import data_for_meetings_overview from ietf.meeting.utils import preprocess_constraints_for_meeting_schedule_editor from ietf.meeting.utils import diff_meeting_schedules, prefetch_schedule_diff_objects from ietf.meeting.utils import swap_meeting_schedule_timeslot_assignments +from ietf.meeting.utils import preprocess_meeting_important_dates from ietf.message.utils import infer_message from ietf.secr.proceedings.utils import handle_upload_file from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files, @@ -3246,7 +3247,7 @@ def upcoming_ical(request): assignments = list(SchedTimeSessAssignment.objects.filter( schedule__in=[m.schedule_id for m in meetings] + [m.schedule.base_id for m in meetings if m.schedule], - session__in=[s.pk for m in meetings for s in m.sessions], + session__in=[s.pk for m in meetings for s in m.sessions if m.type_id != 'ietf'], timeslot__time__gte=today, ).order_by( 'schedule__meeting__date', 'session__type', 'timeslot__time' @@ -3270,17 +3271,16 @@ def upcoming_ical(request): a.session = sessions.get(a.session_id) or a.session a.session.ical_status = ical_session_status(a) - # gather vtimezones - vtimezones = set() - for meeting in meetings: - if meeting.vtimezone(): - vtimezones.add(meeting.vtimezone()) - vtimezones = ''.join(vtimezones) + # handle IETFs separately + ietfs = [m for m in meetings if m.type_id == 'ietf'] + preprocess_meeting_important_dates(ietfs) # icalendar response file should have '\r\n' line endings per RFC5545 response = render_to_string('meeting/upcoming.ics', { - 'vtimezones': vtimezones, - 'assignments': assignments}) + 'vtimezones': ''.join({meeting.vtimezone() for meeting in meetings if meeting.vtimezone()}), + 'assignments': assignments, + 'ietfs': ietfs, + }, request=request) response = re.sub("\r(?!\n)|(?