feat: show meeting requests beyond rg/wg groups (#4134)

* feat: show session requests for all "has_meetings" groups

* test: test changes to groups whose session requests are shown

Note the change in capitalization for the 'active' group state fixes
the test but does not seem to affect production (which I guess uses
case insensitive matching?)

* test: remove leftover debug statement

* feature: exclude admin/social sessions from meeting requests view

* test: test exclusion of admin/social sessions from meeting requests view

* feat: group all non-area groups as "other" on meeting requests page

* fix: prevent doubling of first section header

* test: verify that more of the sreqs are / are not linked
This commit is contained in:
Jennifer Richards 2022-06-29 11:49:33 -03:00 committed by GitHub
parent aa8e4e6e5e
commit ba7d468a4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 17 deletions

View file

@ -6398,17 +6398,86 @@ class SessionTests(TestCase):
def test_meeting_requests(self):
meeting = MeetingFactory(type_id='ietf')
# a couple non-wg group types, confirm that their has_meetings features are as expected
group_type_with_meetings = 'adhoc'
self.assertTrue(GroupFeatures.objects.get(pk=group_type_with_meetings).has_meetings)
group_type_without_meetings = 'editorial'
self.assertFalse(GroupFeatures.objects.get(pk=group_type_without_meetings).has_meetings)
area = GroupFactory(type_id='area')
requested_session = SessionFactory(meeting=meeting,group__parent=area,status_id='schedw',add_to_schedule=False)
conflicting_session = SessionFactory(meeting=meeting,group__parent=area,status_id='schedw',add_to_schedule=False)
ConstraintFactory(name_id='key_participant',meeting=meeting,source=requested_session.group,target=conflicting_session.group)
not_meeting = SessionFactory(meeting=meeting,group__parent=area,status_id='notmeet',add_to_schedule=False)
has_meetings = SessionFactory(
meeting=meeting,
group__type_id=group_type_with_meetings,
status_id='schedw',
add_to_schedule=False,
)
has_meetings_not_meeting = SessionFactory(
meeting=meeting,
group__type_id=group_type_with_meetings,
status_id='notmeet',
add_to_schedule=False,
)
# admin and social sessions are not to be shown on the requests page
has_meetings_admin_session = SessionFactory(
meeting=meeting,
group__type_id=group_type_with_meetings,
status_id='schedw',
purpose_id='admin',
type_id='other',
add_to_schedule=False,
)
has_meetings_social_session = SessionFactory(
meeting=meeting,
group__type_id=group_type_with_meetings,
status_id='schedw',
purpose_id='social',
type_id='break',
add_to_schedule=False,
)
not_has_meetings = SessionFactory(
meeting=meeting,
group__type_id=group_type_without_meetings,
status_id='schedw',
add_to_schedule=False,
)
def _sreq_edit_link(sess):
return urlreverse(
'ietf.secr.sreq.views.edit',
kwargs={
'num': meeting.number,
'acronym': sess.group.acronym,
},
)
url = urlreverse('ietf.meeting.views.meeting_requests',kwargs={'num':meeting.number})
r = self.client.get(url)
# requested_session group should be listed with a link to the request
self.assertContains(r, requested_session.group.acronym)
self.assertContains(r, _sreq_edit_link(requested_session)) # link to the session request
self.assertContains(r, not_meeting.group.acronym)
# The admin/social session groups should be listed under "no timeslot request received"; it's easier
# to check that the group is listed but that there is no link to the session request than to try to
# parse the HTML. If the view is changed to link to the "no timeslot request received" session requests,
# then need to revisit.
self.assertContains(r, has_meetings_admin_session.group.acronym)
self.assertNotContains(r, _sreq_edit_link(has_meetings_admin_session)) # no link to the session request
self.assertContains(r, has_meetings_social_session.group.acronym)
self.assertNotContains(r, _sreq_edit_link(has_meetings_social_session)) # no link to the session request
self.assertContains(r, requested_session.constraints().first().name)
self.assertContains(r, conflicting_session.group.acronym)
self.assertContains(r, _sreq_edit_link(conflicting_session)) # link to the session request
self.assertContains(r, has_meetings.group.acronym)
self.assertContains(r, _sreq_edit_link(has_meetings)) # link to the session request
self.assertContains(r, has_meetings_not_meeting.group.acronym)
self.assertContains(r, _sreq_edit_link(has_meetings_not_meeting)) # link to the session request
self.assertNotContains(r, not_has_meetings.group.acronym)
self.assertNotContains(r, _sreq_edit_link(not_has_meetings)) # no link to the session request
def test_request_minutes(self):
meeting = MeetingFactory(type_id='ietf')

View file

@ -2137,15 +2137,18 @@ def agenda_json(request, num=None):
def meeting_requests(request, num=None):
meeting = get_meeting(num)
sessions = Session.objects.requests().filter(
meeting__number=meeting.number,
group__parent__isnull=False
).with_current_status().with_requested_by().exclude(
requested_by=0
).order_by(
"group__parent__acronym", "current_status", "group__acronym"
).prefetch_related(
"group","group__ad_role__person"
groups_to_show = Group.objects.filter(state_id='active', type__features__has_meetings=True)
sessions = list(
Session.objects.requests().filter(
meeting__number=meeting.number,
group__in=groups_to_show,
).exclude(
purpose__in=('admin', 'social'),
).with_current_status().with_requested_by().exclude(
requested_by=0
).prefetch_related(
"group","group__ad_role__person"
)
)
status_names = {n.slug: n.name for n in SessionStatusName.objects.all()}
@ -2154,12 +2157,34 @@ def meeting_requests(request, num=None):
for s in sessions:
s.current_status_name = status_names.get(s.current_status, s.current_status)
s.requested_by_person = session_requesters.get(s.requested_by)
if s.group.parent and s.group.parent.type.slug == 'area':
s.display_area = s.group.parent
else:
s.display_area = None
sessions.sort(
key=lambda s: (
s.display_area.acronym if s.display_area is not None else 'zzzz',
s.current_status,
s.group.acronym,
),
)
groups_not_meeting = Group.objects.filter(state='Active',type__in=['wg','rg','ag','rag','bof','program']).exclude(acronym__in = [session.group.acronym for session in sessions]).order_by("parent__acronym","acronym").prefetch_related("parent")
groups_not_meeting = groups_to_show.exclude(
acronym__in = [session.group.acronym for session in sessions]
).order_by(
"parent__acronym",
"acronym",
).prefetch_related("parent")
return render(request, "meeting/requests.html",
{"meeting": meeting, "sessions":sessions,
"groups_not_meeting": groups_not_meeting})
return render(
request,
"meeting/requests.html",
{
"meeting": meeting,
"sessions": sessions,
"groups_not_meeting": groups_not_meeting,
},
)
def get_sessions(num, acronym):

View file

@ -15,10 +15,14 @@
{% if meeting.venue_name %} {{ meeting.venue_name }}{% endif %}
</small>
</h1>
{% regroup sessions by group.parent as area_sessions %}
{% regroup sessions by display_area as area_sessions %}
{% for area in area_sessions %}
<h2 class="mt-5" id="{{ area.grouper.acronym }}">
{{ area.grouper.acronym|upper }} <small class="text-muted">{{ area.grouper.name }}</small>
<h2 class="mt-5" id="{% firstof area.grouper.acronym "other-groups" %}">
{% if area.grouper is not None %}
{{ area.grouper.acronym|upper }} <small class="text-muted">{{ area.grouper.name }}</small>
{% else %}
Other Groups
{% endif %}
</h2>
<p class="alert alert-info my-3">
<b>No timeslot request received for:</b>
@ -39,7 +43,7 @@
</tr>
</thead>
{% for session in area.list %}
{% ifchanged %}
{% ifchanged session.current_status_name %}
{% if not forloop.first %}</tbody>{% endif %}
<tbody>
<tr>