Rework agenda filters with show/hide keywords in place of 'types' and add bof / AD office hours buttons
- Legacy-Id: 18563
This commit is contained in:
parent
97dd600a9b
commit
1b1bc24744
|
@ -239,6 +239,29 @@ def preprocess_assignments_for_agenda(assignments_queryset, meeting, extra_prefe
|
|||
|
||||
return assignments
|
||||
|
||||
def tag_assignments_with_filter_keywords(assignments):
|
||||
"""Add keywords for agenda filtering
|
||||
|
||||
Keywords are all lower case.
|
||||
"""
|
||||
for a in assignments:
|
||||
a.filter_keywords = [a.timeslot.type.slug.lower()]
|
||||
a.filter_keywords.extend(filter_keywords_for_session(a.session))
|
||||
|
||||
def filter_keywords_for_session(session):
|
||||
keywords = []
|
||||
group = getattr(session, 'historic_group', session.group)
|
||||
if group is not None:
|
||||
if group.state_id == 'bof':
|
||||
keywords.append('bof')
|
||||
keywords.append(group.acronym.lower())
|
||||
area = getattr(group, 'historic_parent', group.parent)
|
||||
if area is not None:
|
||||
keywords.append(area.acronym.lower())
|
||||
if session.name.lower().endswith('office hours'):
|
||||
keywords.append('adofficehours')
|
||||
return keywords
|
||||
|
||||
def read_session_file(type, num, doc):
|
||||
# XXXX FIXME: the path fragment in the code below should be moved to
|
||||
# settings.py. The *_PATH settings should be generalized to format()
|
||||
|
|
96
ietf/meeting/tests_helpers.py
Normal file
96
ietf/meeting/tests_helpers.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
# Copyright The IETF Trust 2020, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
from ietf.group.factories import GroupFactory
|
||||
from ietf.meeting.factories import SessionFactory, MeetingFactory
|
||||
from ietf.meeting.helpers import tag_assignments_with_filter_keywords
|
||||
from ietf.utils.test_utils import TestCase
|
||||
|
||||
|
||||
class HelpersTests(TestCase):
|
||||
def do_test_tag_assignments_with_filter_keywords(self, bof=False, historic=None):
|
||||
"""Assignments should be tagged properly
|
||||
|
||||
The historic param can be None, group, or parent, to specify whether to test
|
||||
with no historic_group, a historic_group but no historic_parent, or both.
|
||||
"""
|
||||
meeting_types = ['regular', 'plenary']
|
||||
group_state_id = 'bof' if bof else 'active'
|
||||
group = GroupFactory(state_id=group_state_id)
|
||||
historic_group = GroupFactory(state_id=group_state_id)
|
||||
historic_parent = GroupFactory(type_id='area')
|
||||
|
||||
if historic == 'parent':
|
||||
historic_group.historic_parent = historic_parent
|
||||
|
||||
# Create meeting and sessions
|
||||
meeting = MeetingFactory()
|
||||
for meeting_type in meeting_types:
|
||||
sess = SessionFactory(group=group, meeting=meeting, type_id=meeting_type)
|
||||
ts = sess.timeslotassignments.first().timeslot
|
||||
ts.type = sess.type
|
||||
ts.save()
|
||||
|
||||
# Create an office hours session in the group's area (i.e., parent). This is not
|
||||
# currently really needed, but will protect against areas and groups diverging
|
||||
# in a way that breaks keywording.
|
||||
office_hours = SessionFactory(
|
||||
name='some office hours',
|
||||
group=group.parent,
|
||||
meeting=meeting,
|
||||
type_id='other'
|
||||
)
|
||||
ts = office_hours.timeslotassignments.first().timeslot
|
||||
ts.type = office_hours.type
|
||||
ts.save()
|
||||
|
||||
assignments = meeting.schedule.assignments.all()
|
||||
orig_num_assignments = len(assignments)
|
||||
|
||||
# Set up historic groups if needed
|
||||
if historic:
|
||||
for a in assignments:
|
||||
if a.session != office_hours:
|
||||
a.session.historic_group = historic_group
|
||||
|
||||
# Execute the method under test
|
||||
tag_assignments_with_filter_keywords(assignments)
|
||||
|
||||
# Assert expected results
|
||||
self.assertEqual(len(assignments), orig_num_assignments, 'Should not change number of assignments')
|
||||
|
||||
if historic:
|
||||
expected_group = historic_group
|
||||
expected_area = historic_parent if historic == 'parent' else historic_group.parent
|
||||
else:
|
||||
expected_group = group
|
||||
expected_area = group.parent
|
||||
|
||||
for assignment in assignments:
|
||||
expected_filter_keywords = [assignment.timeslot.type.slug]
|
||||
|
||||
if assignment.session == office_hours:
|
||||
expected_filter_keywords.extend([
|
||||
group.parent.acronym,
|
||||
'adofficehours',
|
||||
])
|
||||
else:
|
||||
expected_filter_keywords.extend([
|
||||
expected_group.acronym,
|
||||
expected_area.acronym
|
||||
])
|
||||
if bof:
|
||||
expected_filter_keywords.append('bof')
|
||||
|
||||
self.assertCountEqual(
|
||||
assignment.filter_keywords,
|
||||
expected_filter_keywords,
|
||||
'Assignment has incorrect filter keywords'
|
||||
)
|
||||
|
||||
def test_tag_assignments_with_filter_keywords(self):
|
||||
self.do_test_tag_assignments_with_filter_keywords()
|
||||
self.do_test_tag_assignments_with_filter_keywords(historic='group')
|
||||
self.do_test_tag_assignments_with_filter_keywords(historic='parent')
|
||||
self.do_test_tag_assignments_with_filter_keywords(bof=True)
|
||||
self.do_test_tag_assignments_with_filter_keywords(bof=True, historic='group')
|
||||
self.do_test_tag_assignments_with_filter_keywords(bof=True, historic='parent')
|
|
@ -466,6 +466,14 @@ class AgendaTests(MeetingTestCase):
|
|||
area = mars.parent
|
||||
self.do_agenda_view_filter_test('?show=%s' % area.acronym, ['ames', 'mars'])
|
||||
|
||||
def test_agenda_view_filter_bof(self):
|
||||
mars = Group.objects.get(acronym='mars')
|
||||
mars.state_id = 'bof'
|
||||
mars.save()
|
||||
self.do_agenda_view_filter_test('?show=bof', ['mars'])
|
||||
self.do_agenda_view_filter_test('?show=bof,mars', ['mars'])
|
||||
self.do_agenda_view_filter_test('?show=bof,ames', ['mars','ames'])
|
||||
|
||||
def test_agenda_view_filter_show_two(self):
|
||||
"""Filtered agenda view should display only matching rows (two groups selected)"""
|
||||
self.do_agenda_view_filter_test('?show=mars,ames', ['mars', 'ames'])
|
||||
|
@ -482,43 +490,6 @@ class AgendaTests(MeetingTestCase):
|
|||
area = mars.parent
|
||||
self.do_agenda_view_filter_test('?show=mars&hide=%s' % area.acronym, [])
|
||||
|
||||
def test_agenda_view_filter_show_and_hide(self):
|
||||
self.do_agenda_view_filter_test('?show=mars&hide=ietf', ['mars'])
|
||||
|
||||
def test_agenda_view_filter_show_and_hide_same_group(self):
|
||||
self.do_agenda_view_filter_test('?show=mars&hide=mars', [])
|
||||
|
||||
def test_agenda_view_filter_showtypes(self):
|
||||
self.do_agenda_view_filter_test('?showtypes=plenary', ['ietf']) # ietf has a plenary session
|
||||
|
||||
def test_agenda_view_filter_hidetypes(self):
|
||||
self.do_agenda_view_filter_test('?hidetypes=plenary', [])
|
||||
|
||||
def test_agenda_view_filter_showtypes_and_hidetypes(self):
|
||||
self.do_agenda_view_filter_test('?showtypes=plenary&hidetypes=regular', ['ietf']) # ietf has a plenary session
|
||||
|
||||
def test_agenda_view_filter_showtypes_and_hidetypes_same_type(self):
|
||||
self.do_agenda_view_filter_test('?showtypes=plenary&hidetypes=plenary', [])
|
||||
|
||||
def test_agenda_view_filter_show_and_showtypes(self):
|
||||
self.do_agenda_view_filter_test('?show=mars&showtypes=plenary', ['mars', 'ietf']) # ietf has a plenary session
|
||||
|
||||
def test_agenda_view_filter_show_and_hidetypes(self):
|
||||
self.do_agenda_view_filter_test('?show=ietf,mars&hidetypes=plenary', ['mars']) # ietf has a plenary session
|
||||
|
||||
def test_agenda_view_filter_hide_and_hidetypes(self):
|
||||
self.do_agenda_view_filter_test('?hide=ietf,mars&hidetypes=plenary', [])
|
||||
|
||||
def test_agenda_view_filter_show_hide_and_showtypes(self):
|
||||
self.do_agenda_view_filter_test('?show=mars&hide=ames&showtypes=plenary,regular', ['mars', 'ietf']) # ietf has plenary session
|
||||
|
||||
def test_agenda_view_filter_show_hide_and_hidetypes(self):
|
||||
self.do_agenda_view_filter_test('?show=mars,ietf&hide=ames&hidetypes=plenary', ['mars']) # ietf has plenary session
|
||||
|
||||
def test_agenda_view_filter_all_params(self):
|
||||
self.do_agenda_view_filter_test('?show=secretariat,ietf&hide=ames&showtypes=regular&hidetypes=plenary',
|
||||
['secretariat', 'mars'])
|
||||
|
||||
def assert_agenda_item_visibility(self, visible_groups=None):
|
||||
"""Assert that correct items are visible in current browser window
|
||||
|
||||
|
@ -692,19 +663,20 @@ class InterimTests(MeetingTestCase):
|
|||
not_visible = set()
|
||||
unexpected = set()
|
||||
entries = self.driver.find_elements_by_css_selector(
|
||||
'table#upcoming-meeting-table > tbody > tr.entry'
|
||||
'table#upcoming-meeting-table a.ietf-meeting-link, table#upcoming-meeting-table a.interim-meeting-link'
|
||||
)
|
||||
for entry in entries:
|
||||
nums = [n for n in expected if n in entry.text]
|
||||
entry_text = entry.get_attribute('innerHTML').strip() # gets text, even if element is hidden
|
||||
nums = [n for n in expected if n in entry_text]
|
||||
self.assertLessEqual(len(nums), 1, 'Multiple matching meeting numbers')
|
||||
if len(nums) > 0: # asserted that it's at most 1, so if it's not 0, it's 1.
|
||||
expected.remove(nums[0])
|
||||
if not entry.is_displayed():
|
||||
not_visible.add(nums[0])
|
||||
continue
|
||||
# Found an unexpected row - this is ok as long as it's hidden
|
||||
# Found an unexpected row - this is only a problem if it is visible
|
||||
if entry.is_displayed():
|
||||
unexpected.add(entry.text)
|
||||
unexpected.add(entry_text)
|
||||
|
||||
self.assertEqual(expected, set(), "Missing entries for expected iterim meetings.")
|
||||
self.assertEqual(not_visible, set(), "Hidden rows for expected interim meetings.")
|
||||
|
|
|
@ -755,29 +755,6 @@ class MeetingTests(TestCase):
|
|||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_area(self):
|
||||
meeting = make_meeting_test_data()
|
||||
mars = Group.objects.get(acronym='mars')
|
||||
area = mars.parent
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=%s' % area.acronym,
|
||||
expected_session_summaries=[
|
||||
'ames - Asteroid Mining Equipment Standardization Group',
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_hide_area(self):
|
||||
meeting = make_meeting_test_data()
|
||||
mars = Group.objects.get(acronym='mars')
|
||||
area = mars.parent
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=mars&hide=%s' % area.acronym,
|
||||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_and_hide(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
|
@ -796,122 +773,6 @@ class MeetingTests(TestCase):
|
|||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_showtypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
# Show break/plenary types
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?showtypes=break,plenary',
|
||||
expected_session_summaries=[
|
||||
'IETF Plenary',
|
||||
'Morning Break',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_hidetypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?hidetypes=plenary',
|
||||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_showtypes_and_hidetypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?showtypes=break&hidetypes=plenary',
|
||||
expected_session_summaries=[
|
||||
'Morning Break',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_showtypes_and_hidetypes_same_type(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?showtypes=plenary&hidetypes=plenary',
|
||||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_and_showtypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=mars&showtypes=plenary',
|
||||
expected_session_summaries=[
|
||||
'IETF Plenary',
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_hide_and_showtypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?hide=ames&showtypes=regular',
|
||||
expected_session_summaries=[
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_and_hidetypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=ietf,mars&hidetypes=plenary',
|
||||
expected_session_summaries=[
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_hide_and_hidetypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?hide=ietf,mars&hidetypes=plenary',
|
||||
expected_session_summaries=[]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_hide_and_showtypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
# ames regular session should be suppressed
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=ietf&hide=ames&showtypes=regular',
|
||||
expected_session_summaries=[
|
||||
'IETF Plenary',
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_show_hide_and_hidetypes(self):
|
||||
meeting = make_meeting_test_data()
|
||||
# ietf plenary session should be suppressed
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=mars,ietf&hide=ames&hidetypes=plenary',
|
||||
expected_session_summaries=[
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def test_ical_filter_all_params(self):
|
||||
meeting = make_meeting_test_data()
|
||||
# should include Morning Break / Registration due to secretariat in show list
|
||||
# should include mars SIG because regular in showtypes list
|
||||
# should not include IETF plenary because plenary in hidetypes list
|
||||
# should not show ames SIG because ames in hide list
|
||||
self.do_ical_filter_test(
|
||||
meeting,
|
||||
querystring='?show=secretariat,ietf&hide=ames&showtypes=regular&hidetypes=plenary',
|
||||
expected_session_summaries=[
|
||||
'Morning Break',
|
||||
'Registration',
|
||||
'mars - Martian Special Interest Group',
|
||||
]
|
||||
)
|
||||
|
||||
def build_session_setup(self):
|
||||
# This setup is intentionally unusual - the session has one draft attached as a session presentation,
|
||||
# but lists a different on in its agenda. The expectation is that the pdf and tgz views will return both.
|
||||
|
@ -2291,6 +2152,16 @@ class InterimTests(TestCase):
|
|||
],
|
||||
expected_event_count=4 + meeting.importantdate_set.count())
|
||||
|
||||
def test_upcoming_ical_filter_invalid_syntaxes(self):
|
||||
make_meeting_test_data()
|
||||
url = urlreverse('ietf.meeting.views.upcoming_ical')
|
||||
|
||||
r = self.client.get(url + '?unknownparam=mars')
|
||||
self.assertEqual(r.status_code, 400, 'Unknown parameter should be rejected')
|
||||
|
||||
r = self.client.get(url + '?mars')
|
||||
self.assertEqual(r.status_code, 400, 'Missing parameter name should be rejected')
|
||||
|
||||
def test_upcoming_ical_filter_show(self):
|
||||
r = self.do_upcoming_ical_test('show=mars,ames')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
|
@ -2314,111 +2185,6 @@ class InterimTests(TestCase):
|
|||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_showtypes(self):
|
||||
r = self.do_upcoming_ical_test('showtypes=regular')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'ames - Asteroid Mining Equipment Standardization Group',
|
||||
'mars - Martian Special Interest Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=3)
|
||||
|
||||
def test_upcoming_ical_filter_hidetypes(self):
|
||||
r = self.do_upcoming_ical_test('hidetypes=regular')
|
||||
assert_ical_response_is_valid(self, r, expected_event_summaries=['IETF 72'])
|
||||
|
||||
def test_upcoming_ical_filter_showtypes_and_hidetypes(self):
|
||||
r = self.do_upcoming_ical_test('showtypes=plenary,regular&hidetypes=regular')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'sg - Some Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_show_and_showtypes(self):
|
||||
r = self.do_upcoming_ical_test('show=mars&showtypes=plenary')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'mars - Martian Special Interest Group',
|
||||
'sg - Some Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=3)
|
||||
|
||||
def test_upcoming_ical_filter_show_and_hidetypes(self):
|
||||
r = self.do_upcoming_ical_test('show=mars,sg&hidetypes=regular')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'sg - Some Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_hide_and_showtypes(self):
|
||||
r = self.do_upcoming_ical_test('hide=mars&showtypes=regular')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'ames - Asteroid Mining Equipment Standardization Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_hide_and_hidetypes(self):
|
||||
r = self.do_upcoming_ical_test('hide=mars&hidetypes=regular')
|
||||
assert_ical_response_is_valid(self, r, expected_event_summaries=['IETF 72'], expected_event_count=1)
|
||||
|
||||
def test_upcoming_ical_filter_show_hide_and_showtypes(self):
|
||||
r = self.do_upcoming_ical_test('show=ames&hide=mars&showtypes=regular,plenary')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'ames - Asteroid Mining Equipment Standardization Group',
|
||||
'sg - Some Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=3)
|
||||
|
||||
def test_upcoming_ical_filter_show_hide_and_hidetypes(self):
|
||||
r = self.do_upcoming_ical_test('show=ames,sg&hide=mars&hidetypes=regular')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'sg - Some Group',
|
||||
'IETF 72'
|
||||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_all_params(self):
|
||||
r = self.do_upcoming_ical_test('show=sg&hide=ames&showtypes=regular&hidetypes=plenary')
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'mars - Martian Special Interest Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=2)
|
||||
|
||||
def test_upcoming_ical_filter_show_area(self):
|
||||
make_meeting_test_data(create_interims=True)
|
||||
mars = Group.objects.get(acronym='mars')
|
||||
area = mars.parent
|
||||
r = self.do_upcoming_ical_test('show=%s' % area.acronym,
|
||||
create_meeting=False)
|
||||
assert_ical_response_is_valid(self, r,
|
||||
expected_event_summaries=[
|
||||
'ames - Asteroid Mining Equipment Standardization Group',
|
||||
'mars - Martian Special Interest Group',
|
||||
'IETF 72',
|
||||
],
|
||||
expected_event_count=3)
|
||||
|
||||
def test_upcoming_ical_filter_hide_area(self):
|
||||
make_meeting_test_data(create_interims=True)
|
||||
mars = Group.objects.get(acronym='mars')
|
||||
area = mars.parent
|
||||
r = self.do_upcoming_ical_test('show=mars&hide=%s' % area.acronym,
|
||||
create_meeting=False)
|
||||
assert_ical_response_is_valid(self, r, expected_event_summaries=['IETF 72'], expected_event_count=1)
|
||||
|
||||
def test_upcoming_json(self):
|
||||
make_meeting_test_data(create_interims=True)
|
||||
url = urlreverse("ietf.meeting.views.upcoming_json")
|
||||
|
|
|
@ -66,6 +66,7 @@ from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting
|
|||
from ietf.meeting.helpers import get_meeting, get_ietf_meeting, get_current_ietf_meeting_num
|
||||
from ietf.meeting.helpers import get_schedule, schedule_permissions
|
||||
from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file
|
||||
from ietf.meeting.helpers import filter_keywords_for_session, tag_assignments_with_filter_keywords
|
||||
from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session_date
|
||||
from ietf.meeting.helpers import can_view_interim_request, can_approve_interim_request
|
||||
from ietf.meeting.helpers import can_edit_interim_request
|
||||
|
@ -1339,6 +1340,7 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
|
|||
timeslot__type__private=False,
|
||||
)
|
||||
filtered_assignments = preprocess_assignments_for_agenda(filtered_assignments, meeting)
|
||||
tag_assignments_with_filter_keywords(filtered_assignments)
|
||||
|
||||
if ext == ".csv":
|
||||
return agenda_csv(schedule, filtered_assignments)
|
||||
|
@ -1642,7 +1644,8 @@ def week_view(request, num=None, name=None, owner=None):
|
|||
# saturday_after = saturday_before + datetime.timedelta(days=7)
|
||||
# filtered_assignments = filtered_assignments.filter(timeslot__time__gte=saturday_before,timeslot__time__lt=saturday_after)
|
||||
filtered_assignments = preprocess_assignments_for_agenda(filtered_assignments, meeting)
|
||||
|
||||
tag_assignments_with_filter_keywords(filtered_assignments)
|
||||
|
||||
items = []
|
||||
for a in filtered_assignments:
|
||||
# we don't HTML escape any of these as the week-view code is using createTextNode
|
||||
|
@ -1658,7 +1661,8 @@ def week_view(request, num=None, name=None, owner=None):
|
|||
day_of_month=a.timeslot.time.strftime("%d").lstrip("0"),
|
||||
year=a.timeslot.time.strftime("%Y"),
|
||||
),
|
||||
"type": a.timeslot.type.name
|
||||
"type": a.timeslot.type.name,
|
||||
"filter_keywords": ",".join(a.filter_keywords),
|
||||
}
|
||||
|
||||
if a.session:
|
||||
|
@ -3267,9 +3271,11 @@ def upcoming(request):
|
|||
|
||||
for session in interim_sessions:
|
||||
session.historic_group = session.group
|
||||
session.filter_keywords = filter_keywords_for_session(session)
|
||||
|
||||
entries.extend(list(interim_sessions))
|
||||
entries.sort(key = lambda o: pytz.utc.localize(datetime.datetime.combine(o.date, datetime.datetime.min.time())) if isinstance(o,Meeting) else o.official_timeslotassignment().timeslot.utc_start_time())
|
||||
|
||||
|
||||
# add menu entries
|
||||
menu_entries = get_interim_menu_entries(request)
|
||||
selected_menu_entry = 'upcoming'
|
||||
|
@ -3309,7 +3315,10 @@ def upcoming_ical(request):
|
|||
|
||||
Filters by wg name and session type.
|
||||
"""
|
||||
filter_params = parse_agenda_filter_params(request.GET)
|
||||
try:
|
||||
filter_params = parse_agenda_filter_params(request.GET)
|
||||
except ValueError as e:
|
||||
return HttpResponseBadRequest(str(e))
|
||||
today = datetime.date.today()
|
||||
|
||||
# get meetings starting 7 days ago -- we'll filter out sessions in the past further down
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
var agenda_filter_for_testing = {}; // methods to be accessed for automated testing
|
||||
var agenda_filter = function () {
|
||||
var agenda_filter; // public interface
|
||||
var agenda_filter_for_testing; // methods to be accessed for automated testing
|
||||
|
||||
// closure to create private scope
|
||||
(function () {
|
||||
'use strict'
|
||||
|
||||
var update_callback // function(filter_params)
|
||||
var enable_non_area = false // if true, show the non-area filters
|
||||
|
||||
/* Add to list without duplicates */
|
||||
function add_list_item (list, item) {
|
||||
if (list.indexOf(item) === -1) {
|
||||
list.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove from list, if present */
|
||||
function remove_list_item (list, item) {
|
||||
var item_index = list.indexOf(item);
|
||||
|
@ -20,13 +16,18 @@ var agenda_filter = function () {
|
|||
}
|
||||
}
|
||||
|
||||
/* Add to list if not present, remove if present */
|
||||
/* Add to list if not present, remove if present
|
||||
*
|
||||
* Returns true if added to the list, otherwise false.
|
||||
*/
|
||||
function toggle_list_item (list, item) {
|
||||
var item_index = list.indexOf(item);
|
||||
if (item_index === -1) {
|
||||
list.push(item)
|
||||
return true;
|
||||
} else {
|
||||
list.splice(item_index, 1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,101 +49,83 @@ var agenda_filter = function () {
|
|||
if (!qparams[filt] || (qparams[filt] === true)) {
|
||||
return [];
|
||||
}
|
||||
return $.map(qparams[filt].split(','), function(s){return s.trim();});
|
||||
var result = [];
|
||||
var qp = qparams[filt].split(',');
|
||||
|
||||
for (var ii = 0; ii < qp.length; ii++) {
|
||||
result.push(qp[ii].trim());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function get_filter_params (qparams) {
|
||||
var enabled = !!(qparams.show || qparams.hide || qparams.showtypes || qparams.hidetypes);
|
||||
var enabled = !!(qparams.show || qparams.hide);
|
||||
return {
|
||||
enabled: enabled,
|
||||
show_groups: get_filter_from_qparams(qparams, 'show'),
|
||||
hide_groups: get_filter_from_qparams(qparams, 'hide'),
|
||||
show_types: get_filter_from_qparams(qparams, 'showtypes'),
|
||||
hide_types: get_filter_from_qparams(qparams, 'hidetypes'),
|
||||
show: get_filter_from_qparams(qparams, 'show'),
|
||||
hide: get_filter_from_qparams(qparams, 'hide')
|
||||
}
|
||||
}
|
||||
|
||||
function filtering_is_enabled (filter_params) {
|
||||
return filter_params['enabled'];
|
||||
function get_keywords(elt) {
|
||||
var keywords = $(elt).attr('data-filter-keywords');
|
||||
if (keywords) {
|
||||
return keywords.toLowerCase().split(',');
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function get_area_items (area) {
|
||||
var types = [];
|
||||
var groups = [];
|
||||
var neg_groups = [];
|
||||
function get_item(elt) {
|
||||
return elt.text().trim().toLowerCase().replace(/ /g, '');
|
||||
}
|
||||
|
||||
$('.view.' + area).find('button').each(function (index, elt) {
|
||||
elt = $(elt) // jquerify
|
||||
var item = elt.text().trim().toLowerCase()
|
||||
if (elt.hasClass('picktype')) {
|
||||
types.push(item)
|
||||
} else if (elt.hasClass('pickview')) {
|
||||
groups.push(item);
|
||||
} else if (elt.hasClass('pickviewneg')) {
|
||||
neg_groups.push(item)
|
||||
// utility method - is there a match between two lists of keywords?
|
||||
function keyword_match(list1, list2) {
|
||||
for (var ii = 0; ii < list1.length; ii++) {
|
||||
if (list2.indexOf(list1[ii]) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the items corresponding to a keyword
|
||||
function get_items_with_keyword (keyword) {
|
||||
var items = [];
|
||||
|
||||
$('.view button.pickview').filter(function(index, elt) {
|
||||
return keyword_match(get_keywords(elt), [keyword]);
|
||||
}).each(function (index, elt) {
|
||||
items.push(get_item($(elt)));
|
||||
});
|
||||
return { 'groups': groups, 'neg_groups': neg_groups, 'types': types };
|
||||
return items;
|
||||
}
|
||||
|
||||
function filtering_is_enabled (filter_params) {
|
||||
return filter_params.enabled;
|
||||
}
|
||||
|
||||
// Update the filter / customization UI to match the current filter parameters
|
||||
function update_filter_ui (filter_params) {
|
||||
var area_group_buttons = $('.view .pickview, .pick-area');
|
||||
var non_area_header_button = $('button.pick-non-area');
|
||||
var non_area_type_buttons = $('.view.non-area .picktype');
|
||||
var non_area_group_buttons = $('.view.non-area button.pickviewneg');
|
||||
var buttons = $('.pickview');
|
||||
|
||||
if (!filtering_is_enabled(filter_params)) {
|
||||
// Not filtering - set everything to defaults and exit
|
||||
area_group_buttons.removeClass('active');
|
||||
non_area_header_button.removeClass('active');
|
||||
non_area_type_buttons.removeClass('active');
|
||||
non_area_group_buttons.removeClass('active');
|
||||
non_area_group_buttons.addClass('disabled');
|
||||
// Not filtering - set to default and exit
|
||||
buttons.removeClass('active');
|
||||
return;
|
||||
}
|
||||
|
||||
// show the customizer - it will stay visible even if filtering is disabled
|
||||
$('#customize').collapse('show')
|
||||
|
||||
// Group and area buttons - these are all positive selections
|
||||
area_group_buttons.each(function (index, elt) {
|
||||
// Update button state to match visibility
|
||||
buttons.each(function (index, elt) {
|
||||
elt = $(elt);
|
||||
var item = elt.text().trim().toLowerCase();
|
||||
var area = elt.attr('data-group-area');
|
||||
if ((filter_params['hide_groups'].indexOf(item) === -1) // not hidden...
|
||||
&& ((filter_params['show_groups'].indexOf(item) !== -1) // AND shown...
|
||||
|| (area && (filter_params['show_groups'].indexOf(area.trim().toLowerCase()) !== -1))) // OR area shown
|
||||
) {
|
||||
elt.addClass('active');
|
||||
} else {
|
||||
elt.removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Non-area buttons need special handling. Only have positive type and negative group buttons.
|
||||
// Assume non-area heading is disabled, then enable if one of the types is active
|
||||
non_area_header_button.removeClass('active');
|
||||
non_area_group_buttons.addClass('disabled');
|
||||
non_area_type_buttons.each(function (index, elt) {
|
||||
// Positive type selection buttons
|
||||
elt = $(elt);
|
||||
var item = elt.text().trim().toLowerCase();
|
||||
if ((filter_params['show_types'].indexOf(item) !== -1)
|
||||
&& (filter_params['hide_types'].indexOf(item) === -1)){
|
||||
elt.addClass('active');
|
||||
non_area_header_button.addClass('active');
|
||||
non_area_group_buttons.removeClass('disabled');
|
||||
} else {
|
||||
elt.removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
non_area_group_buttons.each(function (index, elt) {
|
||||
// Negative group selection buttons
|
||||
elt = $(elt);
|
||||
var item = elt.text().trim().toLowerCase();
|
||||
if (filter_params['hide_groups'].indexOf(item) === -1) {
|
||||
var keywords = get_keywords(elt);
|
||||
keywords.push(get_item(elt)); // treat item as one of its keywords
|
||||
var hidden = keyword_match(filter_params.hide, keywords);
|
||||
var shown = keyword_match(filter_params.show, keywords);
|
||||
if (shown && !hidden) {
|
||||
elt.addClass('active');
|
||||
} else {
|
||||
elt.removeClass('active');
|
||||
|
@ -163,7 +146,6 @@ var agenda_filter = function () {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Trigger an update so the user will see the page appropriate for given filter_params
|
||||
*
|
||||
* Updates the URL to match filter_params, then updates the history / display to match
|
||||
|
@ -172,17 +154,11 @@ var agenda_filter = function () {
|
|||
function update_filters (filter_params) {
|
||||
var qparams = []
|
||||
var search = ''
|
||||
if (filter_params['show_groups'].length > 0) {
|
||||
qparams.push('show=' + filter_params['show_groups'].join())
|
||||
if (filter_params.show.length > 0) {
|
||||
qparams.push('show=' + filter_params.show.join())
|
||||
}
|
||||
if (filter_params['hide_groups'].length > 0) {
|
||||
qparams.push('hide=' + filter_params['hide_groups'].join())
|
||||
}
|
||||
if (filter_params['show_types'].length > 0) {
|
||||
qparams.push('showtypes=' + filter_params['show_types'].join())
|
||||
}
|
||||
if (filter_params['hide_types'].length > 0) {
|
||||
qparams.push('hidetypes=' + filter_params['hide_types'].join())
|
||||
if (filter_params.hide.length > 0) {
|
||||
qparams.push('hide=' + filter_params.hide.join())
|
||||
}
|
||||
if (qparams.length > 0) {
|
||||
search = '?' + qparams.join('&')
|
||||
|
@ -202,27 +178,41 @@ var agenda_filter = function () {
|
|||
|
||||
/* Helper for pick group/type button handlers - toggles the appropriate parameter entry
|
||||
* elt - the jquery element that was clicked
|
||||
* param_type - key of the filter param to update (show_groups, show_types, etc)
|
||||
* param_type - key of the filter param to update (show, hide)
|
||||
*/
|
||||
function handle_pick_button (elt, param_type) {
|
||||
var area = elt.attr('data-group-area');
|
||||
var item = elt.text().trim().toLowerCase();
|
||||
function handle_pick_button (elt) {
|
||||
var fp = get_filter_params(parse_query_params(window.location.search));
|
||||
var neg_param_type = {
|
||||
show_groups: 'hide_groups',
|
||||
hide_groups: 'show_groups',
|
||||
show_types: 'hide_types',
|
||||
hide_types: 'show_types'
|
||||
}[param_type];
|
||||
var item = get_item(elt);
|
||||
|
||||
if (area && (fp[param_type].indexOf(area.trim().toLowerCase()) !== -1)) {
|
||||
// Area is shown - toggle hide list
|
||||
toggle_list_item(fp[neg_param_type], item);
|
||||
remove_list_item(fp[param_type], item);
|
||||
/* Normally toggle in and out of the 'show' list. If this item is active because
|
||||
* one of its keywords is active, invert the sense and toggle in and out of the
|
||||
* 'hide' list instead. */
|
||||
var inverted = keyword_match(fp.show, get_keywords(elt));
|
||||
var just_showed_item = false;
|
||||
if (inverted) {
|
||||
toggle_list_item(fp.hide, item);
|
||||
remove_list_item(fp.show, item);
|
||||
} else {
|
||||
toggle_list_item(fp[param_type], item);
|
||||
remove_list_item(fp[neg_param_type], item);
|
||||
just_showed_item = toggle_list_item(fp.show, item);
|
||||
remove_list_item(fp.hide, item);
|
||||
}
|
||||
|
||||
/* If we just showed an item, remove its children from the
|
||||
* show/hide lists to keep things consistent. This way, selecting
|
||||
* an area will enable all items in the row as one would expect. */
|
||||
if (just_showed_item) {
|
||||
var children = get_items_with_keyword(item);
|
||||
$.each(children, function(index, child) {
|
||||
remove_list_item(fp.show, child);
|
||||
remove_list_item(fp.hide, child);
|
||||
});
|
||||
}
|
||||
|
||||
// If the show list is empty, clear the hide list because there is nothing to hide
|
||||
if (fp.show.length === 0) {
|
||||
fp.hide = [];
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
|
@ -230,88 +220,49 @@ var agenda_filter = function () {
|
|||
return elt.hasClass('disabled');
|
||||
}
|
||||
|
||||
// Various "pick" button handlers
|
||||
$('.pickview').click(function () {
|
||||
if (is_disabled($(this))) { return; }
|
||||
update_filters(handle_pick_button($(this), 'show_groups'))
|
||||
});
|
||||
|
||||
$('.pickviewneg').click(function () {
|
||||
if (is_disabled($(this))) { return; }
|
||||
update_filters(handle_pick_button($(this), 'hide_groups'))
|
||||
});
|
||||
|
||||
$('.picktype').click(function () {
|
||||
if (is_disabled($(this))) { return; }
|
||||
var fp = handle_pick_button($(this), 'show_types')
|
||||
// If we just disabled the last non-area type, clear out the hide groups list.
|
||||
var items = get_area_items('non-area')
|
||||
var any_left = false
|
||||
$.each(items.types, function (index, session_type) {
|
||||
if (fp['show_types'].indexOf(session_type) !== -1) {
|
||||
any_left = true
|
||||
}
|
||||
})
|
||||
if (!any_left) {
|
||||
fp['hide_groups'] = []
|
||||
}
|
||||
update_filters(fp);
|
||||
});
|
||||
|
||||
// Click handler for an area header button
|
||||
$('.pick-area').click(function() {
|
||||
if (is_disabled($(this))) { return; }
|
||||
var fp = handle_pick_button($(this), 'show_groups');
|
||||
var items = get_area_items($(this).text().trim().toLowerCase());
|
||||
|
||||
// Clear all the individual group show/hide options
|
||||
$.each(items.groups, function(index, group) {
|
||||
remove_list_item(fp['show_groups'], group);
|
||||
remove_list_item(fp['hide_groups'], group);
|
||||
function register_handlers() {
|
||||
$('.pickview').click(function () {
|
||||
if (is_disabled($(this))) { return; }
|
||||
var fp = handle_pick_button($(this));
|
||||
update_filters(fp);
|
||||
});
|
||||
update_filters(fp);
|
||||
});
|
||||
|
||||
// Click handler for the "Non-Area" header button
|
||||
$('.pick-non-area').click(function () {
|
||||
var items = get_area_items('non-area');
|
||||
|
||||
var fp = get_filter_params(parse_query_params(window.location.search))
|
||||
if ($(this).hasClass('active')) {
|
||||
// Were active - disable or hide everything
|
||||
$.each(items.types, function (index, session_type) {
|
||||
remove_list_item(fp['show_types'], session_type)
|
||||
})
|
||||
// When no types are shown, no need to hide groups. Empty hide_groups list.
|
||||
fp['hide_groups'] = []
|
||||
} else {
|
||||
// Were not active - enable or stop hiding everything
|
||||
$.each(items.types, function (index, session_type) {
|
||||
add_list_item(fp['show_types'], session_type)
|
||||
})
|
||||
$.each(items.neg_groups, function (index, group) {
|
||||
remove_list_item(fp['hide_groups'], group)
|
||||
})
|
||||
}
|
||||
update_filters(fp);
|
||||
});
|
||||
|
||||
// Entry point to filtering code when page loads
|
||||
}
|
||||
|
||||
/* Entry point to filtering code when page loads
|
||||
*
|
||||
* This must be called if you are using the HTML template to provide a customization
|
||||
* button UI. Do not call if you only want to use the parameter parsing routines.
|
||||
*/
|
||||
function enable () {
|
||||
$(document).ready(function () {
|
||||
update_view()
|
||||
register_handlers();
|
||||
update_view();
|
||||
})
|
||||
}
|
||||
|
||||
// utility method - filter a jquery set to those matching a keyword
|
||||
function rows_matching_filter_keyword(rows, kw) {
|
||||
return rows.filter(function(index, element) {
|
||||
var row_kws = get_keywords(element);
|
||||
return keyword_match(row_kws, [kw.toLowerCase()]);
|
||||
});
|
||||
}
|
||||
|
||||
// Make private functions available for unit testing
|
||||
agenda_filter_for_testing.toggle_list_item = toggle_list_item;
|
||||
agenda_filter_for_testing.parse_query_params = parse_query_params;
|
||||
agenda_filter_for_testing = {
|
||||
parse_query_params: parse_query_params,
|
||||
toggle_list_item: toggle_list_item
|
||||
};
|
||||
|
||||
// Public interface methods
|
||||
return {
|
||||
// Make public interface methods accessible
|
||||
agenda_filter = {
|
||||
enable: enable,
|
||||
filtering_is_enabled: filtering_is_enabled,
|
||||
get_filter_params: get_filter_params,
|
||||
include_non_area_selectors: function () {enable_non_area = true},
|
||||
keyword_match: keyword_match,
|
||||
parse_query_params: parse_query_params,
|
||||
rows_matching_filter_keyword: rows_matching_filter_keyword,
|
||||
set_update_callback: function (cb) {update_callback = cb}
|
||||
}
|
||||
}();
|
||||
};
|
||||
})();
|
|
@ -125,10 +125,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if item.timeslot.type.slug == 'break' or item.timeslot.type.slug == 'reg' or item.timeslot.type.slug == 'other' %}
|
||||
<tr id="row-{{ item.slug }}"
|
||||
data-item-group="{% if item.session.historic_group %}{{ item.session.historic_group.acronym }}{% endif %}"
|
||||
data-item-area="{% if item.session.historic_group and item.session.historic_group.historic_parent %}{{ item.session.historic_group.historic_parent.acronym }}{% endif %}"
|
||||
data-timeslot-type="{{item.timeslot.type.slug}}">
|
||||
<tr id="row-{{ item.slug }}" data-filter-keywords="{{ item.filter_keywords|join:',' }}">
|
||||
<td class="text-nowrap text-right">
|
||||
<span class="hidden-xs">
|
||||
{% include "meeting/timeslot_start_end.html" %}
|
||||
|
@ -187,11 +184,9 @@
|
|||
|
||||
{% if item.timeslot.type_id == 'regular' or item.timeslot.type.slug == 'plenary' %}
|
||||
{% if item.session.historic_group %}
|
||||
<tr id="row-{{item.slug}}"
|
||||
data-item-group="{{ item.session.historic_group.acronym }}"
|
||||
data-item-area="{% if item.session.historic_group.historic_parent %}{{ item.session.historic_group.historic_parent.acronym }}{% endif %}"
|
||||
data-timeslot-type="{{item.timeslot.type.slug}}"
|
||||
data-ske="row-{{ item.slug }}" {% if item.timeslot.type.slug == 'plenary' %}class="{{item.timeslot.type.slug}}danger"{% endif %}>
|
||||
<tr id="row-{{item.slug}}"
|
||||
{% if item.timeslot.type.slug == 'plenary' %}class="{{item.timeslot.type.slug}}danger"{% endif %}
|
||||
data-filter-keywords="{{ item.filter_keywords|join:',' }}">
|
||||
{% if item.timeslot.type.slug == 'plenary' %}
|
||||
<th class="text-nowrap text-right">
|
||||
<span class="hidden-xs">
|
||||
|
@ -328,26 +323,18 @@
|
|||
}
|
||||
|
||||
// if groups were selected for filtering, hide all rows by default
|
||||
agenda_rows.hide();
|
||||
agenda_rows.filter(function(index, row) {
|
||||
return !!$(row).attr('data-filter-keywords');
|
||||
}).hide();
|
||||
|
||||
// loop through the has items and change the UI element and row visibilities accordingly
|
||||
$.each(filter_params['show_groups'], function (i, v) {
|
||||
$.each(filter_params.show, function (i, v) {
|
||||
// this is a regular item by wg: when present, show these rows
|
||||
agenda_rows.filter('[data-item-group="'+ v +'"]').show();
|
||||
agenda_rows.filter('[data-item-area="'+ v +'"]').show();
|
||||
agenda_filter.rows_matching_filter_keyword(agenda_rows, v).show();
|
||||
});
|
||||
$.each(filter_params['show_types'], function (i, v) {
|
||||
// this is a regular item by type: when present, show these rows
|
||||
agenda_rows.filter('[data-timeslot-type*="' + v + '"]').show();
|
||||
});
|
||||
$.each(filter_params['hide_groups'], function (i, v) {
|
||||
$.each(filter_params.hide, function (i, v) {
|
||||
// this is a "negative" item by wg: when present, hide these rows
|
||||
agenda_rows.filter('[data-item-group="'+ v +'"]').hide();
|
||||
agenda_rows.filter('[data-item-area="'+ v +'"]').hide();
|
||||
});
|
||||
$.each(filter_params['hide_types'], function (i, v) {
|
||||
// this is a "negative" item by type: when present, hide these rows
|
||||
agenda_rows.filter('[data-timeslot-type*="' + v + '"]').hide();
|
||||
agenda_filter.rows_matching_filter_keyword(agenda_rows, v).hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -381,7 +368,7 @@
|
|||
wv_window.history.replaceState({}, '', new_url);
|
||||
wv_window.draw_calendar()
|
||||
} else {
|
||||
// ho history.replaceState, page reload required
|
||||
// either have not yet loaded the iframe or we do not support history replacement
|
||||
wv_iframe.src = new_url;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,13 +24,11 @@
|
|||
<tr>
|
||||
{% for p in group_parents %}
|
||||
<th style="width:{% widthratio 1 group_parents|length|add:1 100 %}%">
|
||||
<button class="btn btn-default btn-block pick-area {{ p.acronym|lower }}">{{ p.acronym|upper }}</button>
|
||||
<button class="btn btn-default btn-block pickview {{ p.acronym|lower }}">{{ p.acronym|upper }}</button>
|
||||
</th>
|
||||
{% endfor %}
|
||||
{% if non_area_filters %}
|
||||
<th style="width:{% widthratio 1 group_parents|length|add:1 100 %}">
|
||||
<button class="btn btn-default btn-block pick-non-area">Non-Area</button>
|
||||
</th>
|
||||
<th style="width:{% widthratio 1 group_parents|length|add:1 100 %}"></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -42,7 +40,7 @@
|
|||
{% for group in p.group_list %}
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickview {{ group.acronym }}"
|
||||
data-group-area="{{ p.acronym|lower }}">
|
||||
data-filter-keywords="{{ p.acronym|lower }}{% if group.is_bof %},bof{% endif %}">
|
||||
{% if group.is_bof %}
|
||||
<i>{{ group.acronym }}</i>
|
||||
{% else %}
|
||||
|
@ -57,37 +55,34 @@
|
|||
<td class="view non-area">
|
||||
<div class="btn-group-vertical btn-block">
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default picktype plenary">Plenary</button>
|
||||
<button class="btn btn-default pickview adofficehours"> AD Office Hours</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default picktype other">Other</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group-vertical btn-block">
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg edu"> EDU</button>
|
||||
<button class="btn btn-default pickview bof"> BOF</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg hackathon"> Hackathon</button>
|
||||
<button class="btn btn-default pickview edu"> EDU</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg iab"> IAB</button>
|
||||
<button class="btn btn-default pickview hackathon"> Hackathon</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg iepg"> IEPG</button>
|
||||
<button class="btn btn-default pickview iepg"> IEPG</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg iesg"> IESG</button>
|
||||
<button class="btn btn-default pickview iesg"> IESG</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg ietf"> IETF</button>
|
||||
<button class="btn btn-default pickview ietf"> IETF</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg secretariat"> Secretariat
|
||||
</button>
|
||||
<button class="btn btn-default pickview plenary"> Plenary</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickviewneg tools"> Tools</button>
|
||||
<button class="btn btn-default pickview secretariat"> Secretariat</button>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs btn-group-justified">
|
||||
<button class="btn btn-default pickview tools"> Tools</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
@ -66,9 +66,8 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{% for entry in entries %}
|
||||
<tr class="entry"
|
||||
data-item-group="{% if entry.group %}{{ entry.group.acronym|lower }}{% endif %}"
|
||||
data-item-area="{% if entry.group and entry.group.parent %}{{ entry.group.parent.acronym|lower }}{% endif %}">
|
||||
<tr class="entry"
|
||||
{% if entry|classname == 'Session' %}data-filter-keywords="{{ entry.filter_keywords|join:',' }}"{% endif %}>
|
||||
{% if entry|classname == 'Meeting' %}
|
||||
{% with meeting=entry %}
|
||||
<td>{{ meeting.date }} - {{ meeting.end }}</td>
|
||||
|
@ -77,11 +76,11 @@
|
|||
<td></td>
|
||||
{% endwith %}
|
||||
{% elif entry|classname == 'Session' %}
|
||||
{% with session=entry meeting=entry.meeting%}
|
||||
{% with session=entry group=entry.group meeting=entry.meeting%}
|
||||
<td>{{ session.official_timeslotassignment.timeslot.utc_start_time | date:"Y-m-d H:i"}} - {{ session.official_timeslotassignment.timeslot.utc_end_time | date:"H:i e" }}</td>
|
||||
<td><a href="{% url 'ietf.group.views.group_home' acronym=session.group.acronym %}">{{ session.group.acronym }}</a></td>
|
||||
<td><a href="{% url 'ietf.group.views.group_home' acronym=group.acronym %}">{{ group.acronym }}</a></td>
|
||||
<td>
|
||||
<a class="interim-meeting-link" href="{% url 'ietf.meeting.views.session_details' num=session.meeting.number acronym=session.group.acronym %}">{{ session.meeting.number }}</a>
|
||||
<a class="interim-meeting-link" href="{% url 'ietf.meeting.views.session_details' num=meeting.number acronym=group.acronym %}"> {{ meeting.number }}</a>
|
||||
</td>
|
||||
{% if session.current_status == 'canceled' %}
|
||||
<td class='text-right'>
|
||||
|
@ -134,7 +133,7 @@
|
|||
{
|
||||
title: '{{session.official_timeslotassignment.timeslot.utc_start_time|date:"H:i"}}-{{session.official_timeslotassignment.timeslot.utc_end_time|date:"H:i"}}',
|
||||
group: '{% if session.group %}{{session.group.acronym}}{% endif %}',
|
||||
area: '{% if session.group and session.group.parent %}{{ session.group.parent.acronym }}{% endif %}',
|
||||
filter_keywords: ["{{ session.filter_keywords|join:'","' }}"],
|
||||
start: '{{session.official_timeslotassignment.timeslot.utc_start_time | date:"Y-m-d H:i"}}',
|
||||
end: '{{session.official_timeslotassignment.timeslot.utc_end_time | date:"Y-m-d H:i"}}',
|
||||
url: '{% url 'ietf.meeting.views.session_details' num=session.meeting.number acronym=session.group.acronym %}'
|
||||
|
@ -148,29 +147,14 @@
|
|||
|
||||
// Test whether an event should be visible given a set of filter parameters
|
||||
function calendar_event_visible(filter_params, event) {
|
||||
// Visible if filtering is disabled or event has no group
|
||||
if (!agenda_filter.filtering_is_enabled(filter_params) || !event.group) {
|
||||
// Visible if filtering is disabled or event has no keywords
|
||||
if (!agenda_filter.filtering_is_enabled(filter_params) || !event.filter_keywords) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Exclude if group or area is in the hide_groups list
|
||||
if (filter_params['hide_groups'].indexOf(event.group) !== -1) {
|
||||
return false;
|
||||
}
|
||||
if (event.area && (filter_params['hide_groups'].indexOf(event.area) !== -1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Include if group or area is in the show_groups list
|
||||
if (filter_params['show_groups'].indexOf(event.group) !== -1) {
|
||||
return true;
|
||||
}
|
||||
if (event.area && (filter_params['show_groups'].indexOf(event.area) !== -1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not selected, exclude by default
|
||||
return false;
|
||||
// Visible if shown and not hidden
|
||||
return (!agenda_filter.keyword_match(filter_params.hide, event.filter_keywords)
|
||||
&& agenda_filter.keyword_match(filter_params.show, event.filter_keywords));
|
||||
}
|
||||
|
||||
// Apply filter_params to the event list and format data for the calendar
|
||||
|
@ -217,24 +201,22 @@
|
|||
}
|
||||
|
||||
function update_meeting_display(filter_params) {
|
||||
var meeting_rows = $("#upcoming-meeting-table tr.entry")
|
||||
var meeting_rows = $("#upcoming-meeting-table tr.entry");
|
||||
if (!agenda_filter.filtering_is_enabled(filter_params)) {
|
||||
meeting_rows.show();
|
||||
return;
|
||||
}
|
||||
|
||||
// hide everything that has a group
|
||||
meeting_rows.filter("[data-item-group!='']").hide();
|
||||
// hide everything that has keywords
|
||||
meeting_rows.filter(function(index, row){
|
||||
return !!$(row).attr('data-filter-keywords');
|
||||
}).hide();
|
||||
|
||||
$.each(filter_params['show_groups'], function (i, v) {
|
||||
// this is a regular item by wg: when present, show these rows
|
||||
meeting_rows.filter('[data-item-group="'+ v +'"]').show();
|
||||
meeting_rows.filter('[data-item-area="'+ v +'"]').show();
|
||||
$.each(filter_params['show'], function (i, v) {
|
||||
agenda_filter.rows_matching_filter_keyword(meeting_rows, v).show();
|
||||
});
|
||||
$.each(filter_params['hide_groups'], function (i, v) {
|
||||
// this is a "negative" item by wg: when present, hide these rows
|
||||
meeting_rows.filter('[data-item-group="'+ v +'"]').hide();
|
||||
meeting_rows.filter('[data-item-area="'+ v +'"]').hide();
|
||||
$.each(filter_params['hide'], function (i, v) {
|
||||
agenda_filter.rows_matching_filter_keyword(meeting_rows, v).hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{% load origin %}{% origin %}
|
||||
{% load static %}
|
||||
<html> <head>
|
||||
<script src="{% static 'ietf/js/agenda/agenda_filter.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var all_items = {{ items|safe }};
|
||||
|
@ -106,62 +107,17 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===========================================================================
|
||||
|
||||
function parse_query_params(qs) {
|
||||
var params = {};
|
||||
qs = qs.replace(/^\?/, '').toLowerCase();
|
||||
if (qs) {
|
||||
var param_strs = qs.split('&');
|
||||
for (var ii = 0; ii < param_strs.length; ii++) {
|
||||
var toks = param_strs[ii].split('=', 2)
|
||||
params[toks[0]] = toks[1] || true;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
function get_filter_from_qparams(qparams, filt) {
|
||||
return qparams[filt] ? qparams[filt].split(',') : [];
|
||||
}
|
||||
|
||||
function get_filter_params(qparams) {
|
||||
return {
|
||||
show_groups: get_filter_from_qparams(qparams, 'show'),
|
||||
hide_groups: get_filter_from_qparams(qparams, 'hide'),
|
||||
show_types: get_filter_from_qparams(qparams, 'showtypes'),
|
||||
hide_types: get_filter_from_qparams(qparams, 'hidetypes'),
|
||||
};
|
||||
}
|
||||
//===========================================================================
|
||||
|
||||
function is_visible(query_params) {
|
||||
function is_visible(filter_params) {
|
||||
// Returns a method to filter objects for visibility
|
||||
// Accepts show, hide, showtypes, and hidetypes filters. Also accepts
|
||||
// Accepts show and hide filters. No longer accepts
|
||||
// '@<state>' to show sessions in a particular state (e.g., @bof).
|
||||
// Current types are:
|
||||
// Session, Other, Break, Plenary
|
||||
var fp = get_filter_params(query_params);
|
||||
|
||||
return function (item) {
|
||||
var item_group = (item.group || '').toLowerCase();
|
||||
var item_type = (item.type || '').toLowerCase();
|
||||
var item_area = (item.area || '').toLowerCase();
|
||||
var item_state = (item.state || '').toLowerCase();
|
||||
|
||||
if ((fp['hide_groups'].indexOf(item_group) >= 0) ||
|
||||
(fp['hide_groups'].indexOf(item_area) >= 0) ||
|
||||
(fp['hide_types'].indexOf(item_type) >= 0)) {
|
||||
return false;
|
||||
}
|
||||
return ((fp['show_groups'].indexOf(item_group) >= 0) ||
|
||||
(fp['show_groups'].indexOf(item_area) >= 0) ||
|
||||
(fp['show_types'].indexOf(item_type) >= 0) ||
|
||||
query_params['@'+item_state]);
|
||||
var filter_keywords = item.filter_keywords.split(',');
|
||||
return (!agenda_filter.keyword_match(filter_keywords, filter_params.hide)
|
||||
&& agenda_filter.keyword_match(filter_keywords, filter_params.show));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,9 +128,12 @@
|
|||
var height = document.body.clientHeight;
|
||||
|
||||
var visible_items = all_items;
|
||||
var qs = window.location.search;
|
||||
if (qs.length > 1) {
|
||||
visible_items = visible_items.filter(is_visible(parse_query_params(qs)));
|
||||
var filter_params = agenda_filter.get_filter_params(
|
||||
agenda_filter.parse_query_params(window.location.search)
|
||||
);
|
||||
|
||||
if (agenda_filter.filtering_is_enabled(filter_params)) {
|
||||
visible_items = visible_items.filter(is_visible(filter_params));
|
||||
}
|
||||
|
||||
var start_day;
|
||||
|
@ -539,9 +498,13 @@
|
|||
|
||||
//===========================================================================
|
||||
// Set up events for drawing the calendar
|
||||
window.addEventListener("resize", draw_calendar, false);
|
||||
window.addEventListener("load", draw_calendar, false);
|
||||
window.addEventListener("hashchange", draw_calendar, false);
|
||||
function redraw_weekview() {
|
||||
draw_calendar();
|
||||
}
|
||||
|
||||
window.addEventListener("resize", redraw_weekview, false);
|
||||
window.addEventListener("load", redraw_weekview, false);
|
||||
window.addEventListener("hashchange", redraw_weekview, false);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
|
Loading…
Reference in a new issue