From 0377ebdd289d4a170bbf4af60d486831c8d9a5a3 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Tue, 28 Feb 2023 16:31:07 -0400 Subject: [PATCH] feat: Put agenda.csv in meeting TZ and add agenda-utc.csv endpoint (#5226) * fix: Let csv.writer handle encoding for agenda_csv view * style: Use 'is None' instead of '== None' * feat: Display times in meeting time for agenda.csv * feat: Provide agenda-utc.csv view * test: Test agenda.csv time zone and agenda-utc.csv endpoint --- ietf/meeting/tests_views.py | 27 +++++++++++++++++++++++++++ ietf/meeting/urls.py | 3 +-- ietf/meeting/views.py | 13 +++++++------ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/ietf/meeting/tests_views.py b/ietf/meeting/tests_views.py index ccab55e0a1..8b6fe4cac5 100644 --- a/ietf/meeting/tests_views.py +++ b/ietf/meeting/tests_views.py @@ -315,7 +315,34 @@ def test_meeting_agenda(self): self.assertContains(r, session.group.parent.acronym.upper()) self.assertContains(r, slot.location.name) self.assertContains(r, registration_text) + start_time = slot.time.astimezone(meeting.tz()) + end_time = slot.end_time().astimezone(meeting.tz()) + self.assertContains(r, '"{}","{}","{}"'.format( + start_time.strftime("%Y-%m-%d"), + start_time.strftime("%H%M"), + end_time.strftime("%H%M"), + )) + self.assertContains(r, session.materials.get(type='agenda').uploaded_filename) + self.assertContains(r, session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().uploaded_filename) + self.assertNotContains(r, session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().uploaded_filename) + # CSV, utc + r = self.client.get(urlreverse( + "ietf.meeting.views.agenda_plain", + kwargs=dict(num=meeting.number, ext=".csv", utc="-utc"), + )) + self.assertContains(r, session.group.acronym) + self.assertContains(r, session.group.name) + self.assertContains(r, session.group.parent.acronym.upper()) + self.assertContains(r, slot.location.name) + self.assertContains(r, registration_text) + start_time = slot.time.astimezone(datetime.timezone.utc) + end_time = slot.end_time().astimezone(datetime.timezone.utc) + self.assertContains(r, '"{}","{}","{}"'.format( + start_time.strftime("%Y-%m-%d"), + start_time.strftime("%H%M"), + end_time.strftime("%H%M"), + )) self.assertContains(r, session.materials.get(type='agenda').uploaded_filename) self.assertContains(r, session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().uploaded_filename) self.assertNotContains(r, session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().uploaded_filename) diff --git a/ietf/meeting/urls.py b/ietf/meeting/urls.py index 1406acfadf..26d158dd3d 100644 --- a/ietf/meeting/urls.py +++ b/ietf/meeting/urls.py @@ -69,8 +69,7 @@ def get_redirect_url(self, *args, **kwargs): type_ietf_only_patterns_id_optional = [ url(r'^agenda(?P-utc)?(?P\.html)?/?$', views.agenda, name='agenda'), - url(r'^agenda(?P-utc)?(?P\.txt)$', views.agenda_plain), - url(r'^agenda(?P\.csv)$', views.agenda_plain), + url(r'^agenda(?P-utc)?(?P\.txt|\.csv)$', views.agenda_plain), url(r'^agenda/edit$', RedirectView.as_view(pattern_name='ietf.meeting.views.edit_meeting_schedule', permanent=True), name='ietf.meeting.views.edit_meeting_schedule'), diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 1fb6cca787..37ebc3063b 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -1550,7 +1550,7 @@ def agenda_plain(request, num=None, name=None, base=None, ext=None, owner=None, person = get_person_by_email(owner) schedule = get_schedule_by_name(meeting, person, name) - if schedule == None: + if schedule is None: base = base.replace("-utc", "") return render(request, "meeting/no-"+base+ext, {'meeting':meeting }, content_type=mimetype[ext]) @@ -1565,7 +1565,7 @@ def agenda_plain(request, num=None, name=None, base=None, ext=None, owner=None, # Done processing for CSV output if ext == ".csv": - return agenda_csv(schedule, filtered_assignments) + return agenda_csv(schedule, filtered_assignments, utc=utc is not None) filter_organizer = AgendaFilterOrganizer(assignments=filtered_assignments) @@ -1804,7 +1804,7 @@ def agenda_extract_slide (item): "ext": item.file_extension() } -def agenda_csv(schedule, filtered_assignments): +def agenda_csv(schedule, filtered_assignments, utc=False): encoding = 'utf-8' response = HttpResponse(content_type=f"text/csv; charset={encoding}") writer = csv.writer(response, delimiter=str(','), quoting=csv.QUOTE_ALL) @@ -1830,11 +1830,12 @@ def slides_field(item): write_row(headings) + tz = datetime.timezone.utc if utc else schedule.meeting.tz() for item in filtered_assignments: row = [] - row.append(item.timeslot.time.strftime("%Y-%m-%d")) - row.append(item.timeslot.time.strftime("%H%M")) - row.append(item.timeslot.end_time().strftime("%H%M")) + row.append(item.timeslot.time.astimezone(tz).strftime("%Y-%m-%d")) + row.append(item.timeslot.time.astimezone(tz).strftime("%H%M")) + row.append(item.timeslot.end_time().astimezone(tz).strftime("%H%M")) if item.slot_type().slug == "break": row.append(item.slot_type().name)