feat: add 'IETF Meetings' filter to upcoming meetings page (#4826)

* feat: add 'IETF Meetings' filter to upcoming meetings page

* feat: apply 'ietf-meetings' filter to upcoming.ics

* fix: also filter upcoming IETF meetings in the graphical calendar

* test: update tests to match changes

Includes fixing an error in test_upcoming_view_filter_hide_type().
Due to a copy/paste error, it claimed to be testing with a type
both shown and hidden but was not actually hiding a type at all.
This commit is contained in:
Jennifer Richards 2022-12-05 17:19:36 -04:00 committed by GitHub
parent 562d5cceeb
commit 0abebf2f10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 74 additions and 64 deletions

View file

@ -256,6 +256,10 @@ class AgendaFilterOrganizer(AgendaKeywordTool):
self.special_filters = None
if self._use_legacy_keywords():
self.extra_labels += ('Plenary',) # need this when not using session purpose
self.manual_extra_labels = set()
def add_extra_filter(self, kw):
self.manual_extra_labels.add(kw)
def get_non_area_keywords(self):
"""Get list of any 'non-area' (aka 'special') keywords
@ -436,13 +440,13 @@ class AgendaFilterOrganizer(AgendaKeywordTool):
def _extra_filters(self):
"""Get list of filters corresponding to self.extra_labels"""
item_source = self.assignments or self.sessions or []
candidates = set(self.extra_labels)
candidates = set(self.extra_labels).union(self.manual_extra_labels)
return self._filter_column(
label=None,
keyword=None,
children=[
self._filter_entry(label=label, keyword=xslugify(label), toggled_by=[], is_bof=False)
for label in candidates if any(
for label in candidates if label in self.manual_extra_labels or any(
# Keep only those that will affect at least one session
[label.lower() in item.filter_keywords for item in item_source]
)]

View file

@ -1076,9 +1076,9 @@ class InterimTests(IetfSeleniumTestCase):
unexpected.add(entry.text)
advance_month()
self.assertEqual(seen, visible_meetings, "Expected calendar entries not shown.")
self.assertEqual(not_visible, set(), "Hidden calendar entries for expected interim meetings.")
self.assertEqual(unexpected, set(), "Unexpected calendar entries visible")
self.assertCountEqual(seen, visible_meetings, "Expected calendar entries not shown.")
self.assertCountEqual(not_visible, set(), "Hidden calendar entries for expected interim meetings.")
self.assertCountEqual(unexpected, set(), "Unexpected calendar entries visible")
def do_upcoming_view_filter_test(self, querystring, visible_meetings=()):
self.login()
@ -1152,102 +1152,85 @@ class InterimTests(IetfSeleniumTestCase):
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('', ietf_meetings.union(self.displayed_interims()))
def test_upcoming_view_show_ietf_meetings(self):
self.do_upcoming_view_filter_test('?show=ietf-meetings', self.all_ietf_meetings())
def test_upcoming_view_filter_show_group(self):
# Show none
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?show=', ietf_meetings)
self.do_upcoming_view_filter_test('?show=')
# Show one
self.do_upcoming_view_filter_test('?show=mars',
ietf_meetings.union(
self.displayed_interims(groups=['mars'])
))
self.do_upcoming_view_filter_test('?show=mars', self.displayed_interims(groups=['mars']))
# Show two
self.do_upcoming_view_filter_test('?show=mars,ames',
ietf_meetings.union(
self.displayed_interims(groups=['mars', 'ames'])
))
self.do_upcoming_view_filter_test('?show=mars,ames',self.displayed_interims(groups=['mars', 'ames']))
# Show two plus ietf-meetings
self.do_upcoming_view_filter_test(
'?show=ietf-meetings,mars,ames',
set(self.all_ietf_meetings()).union(self.displayed_interims(groups=['mars', 'ames']))
)
def test_upcoming_view_filter_show_area(self):
mars = Group.objects.get(acronym='mars')
area = mars.parent
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?show=%s' % area.acronym,
ietf_meetings.union(
self.displayed_interims(groups=['mars', 'ames'])
))
self.do_upcoming_view_filter_test('?show=%s' % area.acronym, self.displayed_interims(groups=['mars', 'ames']))
def test_upcoming_view_filter_show_type(self):
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?show=plenary',
ietf_meetings.union(
self.displayed_interims(groups=['sg'])
))
self.do_upcoming_view_filter_test('?show=plenary', self.displayed_interims(groups=['sg']))
def test_upcoming_view_filter_hide_group(self):
mars = Group.objects.get(acronym='mars')
area = mars.parent
# Without anything shown, should see only ietf meetings
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?hide=mars', ietf_meetings)
self.do_upcoming_view_filter_test('?hide=mars')
# With group shown
self.do_upcoming_view_filter_test('?show=ames,mars&hide=mars',
ietf_meetings.union(
self.displayed_interims(groups=['ames'])
))
self.do_upcoming_view_filter_test('?show=ames,mars&hide=mars', self.displayed_interims(groups=['ames']))
# With area shown
self.do_upcoming_view_filter_test('?show=%s&hide=mars' % area.acronym,
ietf_meetings.union(
self.displayed_interims(groups=['ames'])
))
self.do_upcoming_view_filter_test('?show=%s&hide=mars' % area.acronym, self.displayed_interims(groups=['ames']))
# With type shown
self.do_upcoming_view_filter_test('?show=plenary&hide=sg',
ietf_meetings)
self.do_upcoming_view_filter_test('?show=plenary&hide=sg')
def test_upcoming_view_filter_hide_area(self):
mars = Group.objects.get(acronym='mars')
area = mars.parent
# Without anything shown, should see only ietf meetings
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?hide=%s' % area.acronym, ietf_meetings)
# Without anything shown, should see nothing
self.do_upcoming_view_filter_test('?hide=%s' % area.acronym)
# With area shown
self.do_upcoming_view_filter_test('?show=%s&hide=%s' % (area.acronym, area.acronym),
ietf_meetings)
self.do_upcoming_view_filter_test('?show=%s&hide=%s' % (area.acronym, area.acronym))
# With group shown
self.do_upcoming_view_filter_test('?show=mars&hide=%s' % area.acronym, ietf_meetings)
self.do_upcoming_view_filter_test('?show=mars&hide=%s' % area.acronym)
# With type shown
self.do_upcoming_view_filter_test('?show=regular&hide=%s' % area.acronym, ietf_meetings)
self.do_upcoming_view_filter_test('?show=regular&hide=%s' % area.acronym)
# with IETF meetings shown
self.do_upcoming_view_filter_test('?show=ietf-meetings,hide=%s' % area.acronym, self.all_ietf_meetings())
def test_upcoming_view_filter_hide_type(self):
mars = Group.objects.get(acronym='mars')
area = mars.parent
# Without anything shown, should see only ietf meetings
ietf_meetings = set(self.all_ietf_meetings())
self.do_upcoming_view_filter_test('?hide=regular', ietf_meetings)
# Without anything shown, should see nothing
self.do_upcoming_view_filter_test('?hide=regular')
# With group shown
self.do_upcoming_view_filter_test('?show=mars&hide=regular', ietf_meetings)
self.do_upcoming_view_filter_test('?show=mars&hide=regular')
# With type shown
self.do_upcoming_view_filter_test('?show=plenary,regular&hide=%s' % area.acronym,
ietf_meetings.union(
self.do_upcoming_view_filter_test(
'?show=plenary,regular&hide=regular',
self.displayed_interims(groups=['sg'])
))
)
# With interim-meetings shown
self.do_upcoming_view_filter_test('?show=plenary,regular&hide=regular', self.displayed_interims(groups=['sg']))
def test_upcoming_view_filter_whitespace(self):
"""Whitespace in filter lists should be ignored"""
meetings = set(self.all_ietf_meetings())
meetings.update(self.displayed_interims(groups=['mars']))
self.do_upcoming_view_filter_test('?show=mars , ames &hide= ames', meetings)
self.do_upcoming_view_filter_test('?show=mars , ames &hide= ames', self.displayed_interims(groups=['mars']))
def test_upcoming_view_time_zone_selection(self):
def _assert_interim_tz_correct(sessions, tz):

View file

@ -4507,8 +4507,16 @@ class InterimTests(TestCase):
# Just a quick check of functionality - details tested by test_js.InterimTests
make_meeting_test_data(create_interims=True)
url = urlreverse("ietf.meeting.views.upcoming_ical")
r = self.client.get(url + '?show=mars')
r = self.client.get(url + '?show=mars')
self.assertEqual(r.status_code, 200)
assert_ical_response_is_valid(self, r,
expected_event_summaries=[
'mars - Martian Special Interest Group',
],
expected_event_count=1)
r = self.client.get(url + '?show=mars,ietf-meetings')
self.assertEqual(r.status_code, 200)
assert_ical_response_is_valid(self, r,
expected_event_summaries=[

View file

@ -3456,6 +3456,10 @@ def upcoming(request):
# Set up for agenda filtering - only one filter_category here
AgendaKeywordTagger(sessions=interim_sessions).apply()
filter_organizer = AgendaFilterOrganizer(sessions=interim_sessions, single_category=True)
# Allow filtering to show only IETF Meetings. This adds a button labeled "IETF Meetings" to the
# "Other" column of the filter UI. When enabled, this adds the keyword "ietf-meetings" to the "show"
# filter list. The IETF meetings are explicitly labeled with this keyword in upcoming.html.
filter_organizer.add_extra_filter('IETF Meetings')
entries = list(ietf_meetings)
entries.extend(list(interim_sessions))
@ -3544,9 +3548,14 @@ def upcoming_ical(request):
a.session = sessions.get(a.session_id) or a.session
a.session.ical_status = ical_session_status(a)
# handle IETFs separately
# Handle IETFs separately. Manually apply the 'ietf-meetings' filter.
if filter_params is None or (
'ietf-meetings' in filter_params['show'] and 'ietf-meetings' not in filter_params['hide']
):
ietfs = [m for m in meetings if m.type_id == 'ietf']
preprocess_meeting_important_dates(ietfs)
else:
ietfs = []
meeting_vtz = {meeting.vtimezone() for meeting in meetings}
meeting_vtz.discard(None)

View file

@ -46,7 +46,12 @@
<tbody>
{% for entry in entries %}
<tr class="entry"
{% if entry|classname == 'Session' %}data-filter-keywords="{{ entry.filter_keywords|join:',' }}"{% endif %}>
{% if entry|classname == 'Session' %}
data-filter-keywords="{{ entry.filter_keywords|join:',' }}"
{% elif entry|classname == 'Meeting' %}
data-filter-keywords="ietf-meetings"
{% endif %}
>
{% if entry|classname == 'Meeting' %}
{% with meeting=entry %}
<td class="meeting-time"
@ -122,6 +127,7 @@
{% with meeting=entry %}
{
ietf_meeting_number: '{{ meeting.number }}',
filter_keywords: ['ietf-meetings'],
start_moment: moment.tz('{{meeting.date}}', '{{ meeting.time_zone }}').startOf('day'),
end_moment: moment.tz('{{meeting.end_date}}', '{{ meeting.time_zone }}').endOf('day'),
url: '{% url 'agenda' num=meeting.number %}'