Skip to content

Commit b90820e

Browse files
authored
fix: Hide last modified field in agenda when unavailable (ietf-tools#7722)
* test: Update tests to check for Updated field in agenda.txt * fix: Hide Updated in agenda.txt if too old * test: Remove confusing tests on CSV agenda * refactor: Make updated() return None when no valid timestamp found * refactor: Remove walrus operator
1 parent 9ef7bff commit b90820e

5 files changed

Lines changed: 61 additions & 9 deletions

File tree

client/agenda/Agenda.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ const meetingUpdated = computed(() => {
323323
if (!agendaStore.meeting.updated) { return false }
324324
325325
const updatedDatetime = DateTime.fromISO(agendaStore.meeting.updated).setZone(agendaStore.timezone)
326-
if (!updatedDatetime.isValid || updatedDatetime < DateTime.fromISO('1980-01-01')) {
326+
if (!updatedDatetime.isValid) {
327327
return false
328328
}
329329

ietf/meeting/models.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,13 +369,14 @@ def vtimezone(self):
369369

370370
def updated(self):
371371
# should be Meeting.modified, but we don't have that
372-
min_time = pytz.utc.localize(datetime.datetime(1970, 1, 1, 0, 0, 0))
373-
timeslots_updated = self.timeslot_set.aggregate(Max('modified'))["modified__max"] or min_time
374-
sessions_updated = self.session_set.aggregate(Max('modified'))["modified__max"] or min_time
375-
assignments_updated = min_time
372+
timeslots_updated = self.timeslot_set.aggregate(Max('modified'))["modified__max"]
373+
sessions_updated = self.session_set.aggregate(Max('modified'))["modified__max"]
374+
assignments_updated = None
376375
if self.schedule:
377-
assignments_updated = SchedTimeSessAssignment.objects.filter(schedule__in=[self.schedule, self.schedule.base if self.schedule else None]).aggregate(Max('modified'))["modified__max"] or min_time
378-
return max(timeslots_updated, sessions_updated, assignments_updated)
376+
assignments_updated = SchedTimeSessAssignment.objects.filter(schedule__in=[self.schedule, self.schedule.base if self.schedule else None]).aggregate(Max('modified'))["modified__max"]
377+
dts = [timeslots_updated, sessions_updated, assignments_updated]
378+
valid_only = [dt for dt in dts if dt is not None]
379+
return max(valid_only) if valid_only else None
379380

380381
@memoize
381382
def previous_meeting(self):

ietf/meeting/tests_views.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ def test_meeting_agenda(self):
294294
(slot.time + slot.duration).astimezone(meeting.tz()).strftime("%H%M"),
295295
))
296296
self.assertContains(r, f"shown in the {meeting.tz()} time zone")
297+
updated = meeting.updated().astimezone(meeting.tz()).strftime("%Y-%m-%d %H:%M:%S %Z")
298+
self.assertContains(r, f"Updated {updated}")
297299

298300
# text, UTC
299301
r = self.client.get(urlreverse(
@@ -309,6 +311,16 @@ def test_meeting_agenda(self):
309311
(slot.time + slot.duration).astimezone(datetime.timezone.utc).strftime("%H%M"),
310312
))
311313
self.assertContains(r, "shown in UTC")
314+
updated = meeting.updated().astimezone(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S %Z")
315+
self.assertContains(r, f"Updated {updated}")
316+
317+
# text, invalid updated (none)
318+
with patch("ietf.meeting.models.Meeting.updated", return_value=None):
319+
r = self.client.get(urlreverse(
320+
"ietf.meeting.views.agenda_plain",
321+
kwargs=dict(num=meeting.number, ext=".txt", utc="-utc"),
322+
))
323+
self.assertNotContains(r, "Updated ")
312324

313325
# future meeting, no agenda
314326
r = self.client.get(urlreverse("ietf.meeting.views.agenda_plain", kwargs=dict(num=future_meeting.number, ext=".txt")))
@@ -859,6 +871,24 @@ def test_important_dates_ical(self):
859871
for d in meeting.importantdate_set.all():
860872
self.assertContains(r, d.date.isoformat())
861873

874+
updated = meeting.updated()
875+
self.assertIsNotNone(updated)
876+
expected_updated = updated.astimezone(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
877+
self.assertContains(r, f"DTSTAMP:{expected_updated}")
878+
dtstamps_count = r.content.decode("utf-8").count(f"DTSTAMP:{expected_updated}")
879+
self.assertEqual(dtstamps_count, meeting.importantdate_set.count())
880+
881+
# With default cached_updated, 1970-01-01
882+
with patch("ietf.meeting.models.Meeting.updated", return_value=None):
883+
r = self.client.get(url)
884+
for d in meeting.importantdate_set.all():
885+
self.assertContains(r, d.date.isoformat())
886+
887+
expected_updated = "19700101T000000Z"
888+
self.assertContains(r, f"DTSTAMP:{expected_updated}")
889+
dtstamps_count = r.content.decode("utf-8").count(f"DTSTAMP:{expected_updated}")
890+
self.assertEqual(dtstamps_count, meeting.importantdate_set.count())
891+
862892
def test_group_ical(self):
863893
meeting = make_meeting_test_data()
864894
s1 = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
@@ -4952,7 +4982,23 @@ def test_upcoming_ical(self):
49524982
expected_event_count=len(expected_event_summaries))
49534983
self.assertNotContains(r, 'Remote instructions:')
49544984

4955-
def test_upcoming_ical_filter(self):
4985+
updated = meeting.updated()
4986+
self.assertIsNotNone(updated)
4987+
expected_updated = updated.astimezone(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
4988+
self.assertContains(r, f"DTSTAMP:{expected_updated}")
4989+
4990+
# With default cached_updated, 1970-01-01
4991+
with patch("ietf.meeting.models.Meeting.updated", return_value=None):
4992+
r = self.client.get(url)
4993+
self.assertEqual(r.status_code, 200)
4994+
4995+
self.assertEqual(meeting.type_id, "ietf")
4996+
4997+
expected_updated = "19700101T000000Z"
4998+
self.assertEqual(1, r.content.decode("utf-8").count(f"DTSTAMP:{expected_updated}"))
4999+
5000+
@patch("ietf.meeting.utils.preprocess_meeting_important_dates")
5001+
def test_upcoming_ical_filter(self, mock_preprocess_meeting_important_dates):
49565002
# Just a quick check of functionality - details tested by test_js.InterimTests
49575003
make_meeting_test_data(create_interims=True)
49585004
url = urlreverse("ietf.meeting.views.upcoming_ical")
@@ -4974,6 +5020,8 @@ def test_upcoming_ical_filter(self):
49745020
],
49755021
expected_event_count=2)
49765022

5023+
# Verify preprocess_meeting_important_dates isn't being called
5024+
mock_preprocess_meeting_important_dates.assert_not_called()
49775025

49785026
def test_upcoming_json(self):
49795027
make_meeting_test_data(create_interims=True)

ietf/meeting/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,8 @@ def bulk_create_timeslots(meeting, times, locations, other_props):
609609

610610
def preprocess_meeting_important_dates(meetings):
611611
for m in meetings:
612-
m.cached_updated = m.updated()
612+
# cached_updated must be present, set it to 1970-01-01 if necessary
613+
m.cached_updated = m.updated() or pytz.utc.localize(datetime.datetime(1970, 1, 1, 0, 0, 0))
613614
m.important_dates = m.importantdate_set.prefetch_related("name")
614615
for d in m.important_dates:
615616
d.midnight_cutoff = "UTC 23:59" in d.name.name

ietf/templates/meeting/agenda.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
{% filter center:72 %}{{ schedule.meeting.agenda_info_note|striptags|wordwrap:72|safe }}{% endfilter %}
88
{% endif %}
99
{% filter center:72 %}{{ schedule.meeting.date|date:"F j" }}-{% if schedule.meeting.date.month != schedule.meeting.end_date.month %}{{ schedule.meeting.end_date|date:"F " }}{% endif %}{{ schedule.meeting.end_date|date:"j, Y" }}{% endfilter %}
10+
{% if updated %}
1011
{% filter center:72 %}Updated {{ updated|date:"Y-m-d H:i:s T" }}{% endfilter %}
12+
{% endif %}
1113

1214
{% filter center:72 %}IETF agendas are subject to change, up to and during the meeting.{% endfilter %}
1315
{% filter center:72 %}Times are shown in {% if display_timezone.lower == "utc" %}UTC{% else %}the {{ display_timezone }} time zone{% endif %}.{% endfilter %}

0 commit comments

Comments
 (0)