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:
parent
562d5cceeb
commit
0abebf2f10
|
@ -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]
|
||||
)]
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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=[
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 %}'
|
||||
|
|
Loading…
Reference in a new issue