refactor: clarify handling what groups looked like at past session times (#4767)
* refactor: clarify handling what groups looked like at past session times * fix: replace missed instance of historic_parent reference * fix: reflect that group_at_the_time always returns something * chore: update copyright lines
This commit is contained in:
parent
6293e61287
commit
0b3f9f5dc5
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2015-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2015-2022, All Rights Reserved
|
||||
import datetime
|
||||
import debug # pyflakes:ignore
|
||||
import factory
|
||||
|
@ -78,16 +78,38 @@ class GroupHistoryFactory(factory.django.DjangoModelFactory):
|
|||
class Meta:
|
||||
model=GroupHistory
|
||||
|
||||
name = factory.LazyAttribute(lambda obj: obj.group.name)
|
||||
state_id = 'active'
|
||||
type_id = factory.LazyAttribute(lambda obj: obj.group.type_id)
|
||||
list_email = factory.LazyAttribute(lambda obj: '%s@ietf.org'% obj.group.acronym)
|
||||
uses_milestone_dates = True
|
||||
used_roles = [] # type: List[str]
|
||||
time = lambda: timezone.now()
|
||||
group = factory.SubFactory(GroupFactory, state_id='active')
|
||||
|
||||
group = factory.SubFactory(GroupFactory)
|
||||
name = factory.LazyAttribute(lambda obj: obj.group.name)
|
||||
state_id = factory.LazyAttribute(lambda obj: obj.group.state_id)
|
||||
type_id = factory.LazyAttribute(lambda obj: obj.group.type_id)
|
||||
parent = factory.LazyAttribute(lambda obj: obj.group.parent)
|
||||
uses_milestone_dates = factory.LazyAttribute(lambda obj: obj.group.uses_milestone_dates)
|
||||
used_roles = factory.LazyAttribute(lambda obj: obj.group.used_roles)
|
||||
description = factory.LazyAttribute(lambda obj: obj.group.description)
|
||||
list_email = factory.LazyAttribute(lambda obj: '%s@ietf.org'% obj.group.acronym) #TODO : move this to GroupFactory
|
||||
list_subscribe = factory.LazyAttribute(lambda obj: obj.group.list_subscribe)
|
||||
list_archive = factory.LazyAttribute(lambda obj: obj.group.list_archive)
|
||||
comments = factory.LazyAttribute(lambda obj: obj.group.comments)
|
||||
meeting_seen_as_area = factory.LazyAttribute(lambda obj: obj.group.meeting_seen_as_area)
|
||||
acronym = factory.LazyAttribute(lambda obj: obj.group.acronym)
|
||||
|
||||
@factory.post_generation
|
||||
def unused_states(obj, create, extracted, **kwargs):
|
||||
if create:
|
||||
if extracted:
|
||||
obj.unused_states.set(extracted)
|
||||
else:
|
||||
obj.unused_states.set(obj.group.unused_states.all())
|
||||
@factory.post_generation
|
||||
def unused_tags(obj, create, extracted, **kwargs):
|
||||
if create:
|
||||
if extracted:
|
||||
obj.unused_tags.set(extracted)
|
||||
else:
|
||||
obj.unused_tags.set(obj.group.unused_states.all())
|
||||
|
||||
class RoleHistoryFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model=RoleHistory
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2013-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2013-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
@ -22,7 +22,6 @@ from django.utils import timezone
|
|||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import Document
|
||||
from ietf.group.models import Group
|
||||
from ietf.group.utils import can_manage_some_groups, can_manage_group
|
||||
from ietf.ietfauth.utils import has_role, user_is_person
|
||||
from ietf.liaisons.utils import get_person_for_user
|
||||
|
@ -32,7 +31,6 @@ from ietf.meeting.models import Meeting, Schedule, TimeSlot, SchedTimeSessAssign
|
|||
from ietf.meeting.utils import session_requested_by, add_event_info_to_session_qs
|
||||
from ietf.name.models import ImportantDateName, SessionPurposeName
|
||||
from ietf.utils import log, meetecho
|
||||
from ietf.utils.history import find_history_replacements_active_at
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.text import xslugify
|
||||
|
@ -92,8 +90,6 @@ def preprocess_assignments_for_agenda(assignments_queryset, meeting, extra_prefe
|
|||
For each assignment a, adds
|
||||
a.start_timestamp
|
||||
a.end_timestamp
|
||||
a.session.historic_group
|
||||
a.session.historic_parent
|
||||
a.session.rescheduled_to (if rescheduled)
|
||||
a.session.prefetched_active_materials
|
||||
a.session.order_number
|
||||
|
@ -119,16 +115,10 @@ def preprocess_assignments_for_agenda(assignments_queryset, meeting, extra_prefe
|
|||
# assignments = list(assignments_queryset) # make sure we're set in stone
|
||||
assignments = assignments_queryset
|
||||
|
||||
# meeting_time is meeting-local midnight at the start of the meeting date
|
||||
meeting_time = meeting.tz().localize(
|
||||
datetime.datetime.combine(meeting.date, datetime.time())
|
||||
)
|
||||
|
||||
# replace groups with historic counterparts
|
||||
groups = [ ]
|
||||
for a in assignments:
|
||||
if a.session:
|
||||
a.session.historic_group = None
|
||||
a.session.order_number = None
|
||||
|
||||
if a.session.group and a.session.group not in groups:
|
||||
|
@ -139,30 +129,15 @@ def preprocess_assignments_for_agenda(assignments_queryset, meeting, extra_prefe
|
|||
if a.session and a.session.group:
|
||||
sessions_for_groups[(a.session.group, a.session.type_id)].append(a)
|
||||
|
||||
group_replacements = find_history_replacements_active_at(groups, meeting_time)
|
||||
|
||||
parent_id_set = set()
|
||||
for a in assignments:
|
||||
if a.session and a.session.group:
|
||||
a.session.historic_group = group_replacements.get(a.session.group_id)
|
||||
|
||||
if a.session.historic_group:
|
||||
a.session.historic_group.historic_parent = None
|
||||
|
||||
if a.session.historic_group.parent_id:
|
||||
parent_id_set.add(a.session.historic_group.parent_id)
|
||||
|
||||
l = sessions_for_groups.get((a.session.group, a.session.type_id), [])
|
||||
a.session.order_number = l.index(a) + 1 if a in l else 0
|
||||
|
||||
parents = Group.objects.filter(pk__in=parent_id_set)
|
||||
parent_replacements = find_history_replacements_active_at(parents, meeting_time)
|
||||
|
||||
timeslot_by_session_pk = {a.session_id: a.timeslot for a in assignments}
|
||||
|
||||
for a in assignments:
|
||||
if a.session and a.session.historic_group and a.session.historic_group.parent_id:
|
||||
a.session.historic_group.historic_parent = parent_replacements.get(a.session.historic_group.parent_id)
|
||||
|
||||
if a.session.current_status == 'resched':
|
||||
a.session.rescheduled_to = timeslot_by_session_pk.get(a.session.tombstone_for_id)
|
||||
|
@ -211,12 +186,15 @@ class AgendaKeywordTool:
|
|||
@staticmethod
|
||||
def _get_group(s):
|
||||
"""Get group of a session, handling historic groups"""
|
||||
return getattr(s, 'historic_group', s.group)
|
||||
return s.group_at_the_time()
|
||||
|
||||
def _get_group_parent(self, s):
|
||||
"""Get parent of a group or parent of a session's group, handling historic groups"""
|
||||
g = self._get_group(s) if isinstance(s, Session) else s # accept a group or a session arg
|
||||
return getattr(g, 'historic_parent', g.parent)
|
||||
if isinstance(s, Session):
|
||||
return s.group_parent_at_the_time()
|
||||
else:
|
||||
# Assumption is that s is a group...
|
||||
return s and s.parent
|
||||
|
||||
def _purpose_keyword(self, purpose):
|
||||
"""Get the keyword corresponding to a session purpose"""
|
||||
|
@ -240,8 +218,10 @@ class AgendaFilterOrganizer(AgendaKeywordTool):
|
|||
|
||||
Either assignments or sessions must be specified (but not both). Keywords should be applied
|
||||
to these items before calling either of the 'get_' methods, otherwise some special filters
|
||||
may not be included (e.g., 'BoF' or 'Plenary'). If historic_group and/or historic_parent
|
||||
attributes are present, these will be used instead of group/parent.
|
||||
may not be included (e.g., 'BoF' or 'Plenary'). If the session's group has a GroupHistory
|
||||
object active at the time of the start of the session's meeting, and/or the session's group
|
||||
parent had an active GroupHistory object active at the time, these will be used instead of
|
||||
the group or parent.
|
||||
|
||||
The organizer will process its inputs once, when one of its get_ methods is first called.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2007-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2007-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
@ -39,6 +39,7 @@ from ietf.name.models import (
|
|||
)
|
||||
from ietf.person.models import Person
|
||||
from ietf.utils.decorators import memoize
|
||||
from ietf.utils.history import find_history_replacements_active_at
|
||||
from ietf.utils.storage import NoLocationMigrationFileSystemStorage
|
||||
from ietf.utils.text import xslugify
|
||||
from ietf.utils.timezone import datetime_from_date, date_today
|
||||
|
@ -408,6 +409,19 @@ class Meeting(models.Model):
|
|||
def uses_notes(self):
|
||||
return self.date>=datetime.date(2020,7,6)
|
||||
|
||||
def groups_at_the_time(self):
|
||||
if not hasattr(self,'cached_groups_at_the_time'):
|
||||
all_group_pks = set(self.session_set.values_list('group__pk', flat=True))
|
||||
all_group_pks.update(self.session_set.values_list('group__parent__pk', flat=True))
|
||||
all_group_pks.discard(None)
|
||||
# meeting_time is meeting-local midnight at the start of the meeting date
|
||||
meeting_start = self.tz().localize(
|
||||
datetime.datetime.combine(self.date, datetime.time())
|
||||
)
|
||||
self.cached_groups_at_the_time = find_history_replacements_active_at(Group.objects.filter(pk__in=all_group_pks), meeting_start)
|
||||
return self.cached_groups_at_the_time
|
||||
|
||||
|
||||
class Meta:
|
||||
ordering = ["-date", "-id"]
|
||||
indexes = [
|
||||
|
@ -824,12 +838,12 @@ class SchedTimeSessAssignment(models.Model):
|
|||
if not self.timeslot:
|
||||
components.append("unknown")
|
||||
|
||||
if not self.session or not (getattr(self.session, "historic_group", None) or self.session.group):
|
||||
if not self.session or not self.session.group_at_the_time():
|
||||
components.append("unknown")
|
||||
else:
|
||||
components.append(self.timeslot.time.strftime("%Y-%m-%d-%a-%H%M"))
|
||||
|
||||
g = getattr(self.session, "historic_group", None) or self.session.group
|
||||
g = self.session.group_at_the_time()
|
||||
|
||||
if self.timeslot.type.slug in ('break', 'reg', 'other'):
|
||||
components.append(g.acronym)
|
||||
|
@ -839,7 +853,7 @@ class SchedTimeSessAssignment(models.Model):
|
|||
if self.timeslot.type.slug == "plenary":
|
||||
components.append("1plenary")
|
||||
else:
|
||||
p = getattr(g, "historic_parent", None) or g.parent
|
||||
p = self.session.group_parent_at_the_time()
|
||||
if p and p.type_id in ("area", "irtf", 'ietf'):
|
||||
components.append(p.acronym)
|
||||
|
||||
|
@ -1263,10 +1277,8 @@ class Session(models.Model):
|
|||
def chat_room_name(self):
|
||||
if self.type_id=='plenary':
|
||||
return 'plenary'
|
||||
elif hasattr(self, 'historic_group'):
|
||||
return self.historic_group.acronym
|
||||
else:
|
||||
return self.group.acronym
|
||||
return self.group_at_the_time().acronym
|
||||
|
||||
def chat_room_url(self):
|
||||
return settings.CHAT_URL_PATTERN.format(chat_room_name=self.chat_room_name())
|
||||
|
@ -1288,6 +1300,13 @@ class Session(models.Model):
|
|||
def notes_url(self):
|
||||
return urljoin(settings.IETF_NOTES_URL, self.notes_id())
|
||||
|
||||
def group_at_the_time(self):
|
||||
return self.meeting.groups_at_the_time()[self.group.pk]
|
||||
|
||||
def group_parent_at_the_time(self):
|
||||
if self.group_at_the_time().parent:
|
||||
return self.meeting.groups_at_the_time()[self.group_at_the_time().parent.pk]
|
||||
|
||||
class SchedulingEvent(models.Model):
|
||||
session = ForeignKey(Session)
|
||||
time = models.DateTimeField(default=timezone.now, help_text="When the event happened")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2013-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2013-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
@ -72,9 +72,10 @@ def webcal_url(context, viewname, *args, **kwargs):
|
|||
@register.simple_tag
|
||||
def assignment_display_name(assignment):
|
||||
"""Get name for an assignment"""
|
||||
if assignment.session.type.slug == 'regular' and getattr(assignment.session, 'historic_group', None):
|
||||
return assignment.session.historic_group.name
|
||||
return assignment.session.name or assignment.timeslot.name
|
||||
if assignment.session.type.slug == 'regular':
|
||||
return assignment.session.group_at_the_time().name
|
||||
else:
|
||||
return assignment.session.name or assignment.timeslot.name
|
||||
|
||||
|
||||
class AnchorNode(template.Node):
|
||||
|
@ -149,4 +150,4 @@ def location_anchor(parser, token):
|
|||
raise template.TemplateSyntaxError('location_anchor requires a single argument')
|
||||
nodelist = parser.parse(('end_location_anchor',))
|
||||
parser.delete_first_token() # delete the end tag
|
||||
return LocationAnchorNode(ts_var, nodelist)
|
||||
return LocationAnchorNode(ts_var, nodelist)
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
# Copyright The IETF Trust 2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2020-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
|
||||
import debug # pyflakes:ignore
|
||||
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.messages.storage.fallback import FallbackStorage
|
||||
from django.test import override_settings, RequestFactory
|
||||
|
||||
from ietf.group.factories import GroupFactory
|
||||
from ietf.group.factories import GroupFactory, GroupHistoryFactory
|
||||
from ietf.group.models import Group
|
||||
from ietf.meeting.factories import SessionFactory, MeetingFactory, TimeSlotFactory
|
||||
from ietf.meeting.helpers import (AgendaFilterOrganizer, AgendaKeywordTagger,
|
||||
|
@ -28,7 +30,8 @@ class AgendaKeywordTaggerTests(TestCase):
|
|||
"""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.
|
||||
with no GroupHistory active at the time of the Session's meeting,
|
||||
with such a GroupHistory active, no GroupHistory for the parent, or both.
|
||||
"""
|
||||
# decide whether meeting should use legacy keywords (for office hours)
|
||||
legacy_keywords = meeting_num <= 111
|
||||
|
@ -38,14 +41,19 @@ class AgendaKeywordTaggerTests(TestCase):
|
|||
group_state_id = 'bof' if bof else 'active'
|
||||
group = GroupFactory(state_id=group_state_id)
|
||||
|
||||
|
||||
# Set up the historic group and parent if needed. Keep track of these as expected_*
|
||||
# for later reference. If not using historic group or parent, fall back to the non-historic
|
||||
# groups.
|
||||
|
||||
if historic:
|
||||
expected_group = GroupFactory(state_id=group_state_id)
|
||||
history_time = meeting.tz().localize(
|
||||
datetime.datetime.combine(meeting.date, datetime.time())
|
||||
- datetime.timedelta(days=1)
|
||||
)
|
||||
expected_group = GroupHistoryFactory(group=group, time=history_time)
|
||||
if historic == 'parent':
|
||||
expected_area = GroupFactory(type_id='area')
|
||||
expected_group.historic_parent = expected_area
|
||||
expected_area = GroupHistoryFactory(group=group.parent,time=history_time)
|
||||
else:
|
||||
expected_area = expected_group.parent
|
||||
else:
|
||||
|
@ -112,11 +120,6 @@ class AgendaKeywordTaggerTests(TestCase):
|
|||
|
||||
assignments = meeting.schedule.assignments.all()
|
||||
|
||||
# Set up historic groups if needed.
|
||||
if historic:
|
||||
for a in assignments:
|
||||
a.session.historic_group = expected_group
|
||||
|
||||
# Execute the method under test
|
||||
AgendaKeywordTagger(assignments=assignments).apply()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2007-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2007-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
@ -89,7 +89,6 @@ from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process,
|
|||
from ietf.utils import markdown
|
||||
from ietf.utils.decorators import require_api_key
|
||||
from ietf.utils.hedgedoc import Note, NoteError
|
||||
from ietf.utils.history import find_history_replacements_active_at
|
||||
from ietf.utils.log import assertion
|
||||
from ietf.utils.mail import send_mail_message, send_mail_text
|
||||
from ietf.utils.mime import get_mime_type
|
||||
|
@ -1712,15 +1711,13 @@ def agenda_extract_schedule (item):
|
|||
"startDateTime": item.timeslot.time.isoformat(),
|
||||
"status": item.session.current_status,
|
||||
"type": item.session.type.slug,
|
||||
"isBoF": item.session.historic_group.state_id == "bof",
|
||||
"isBoF": item.session.group_at_the_time().state_id == "bof",
|
||||
"filterKeywords": item.filter_keywords,
|
||||
"groupAcronym": item.session.historic_group.acronym if item.session.historic_group else item.session.group.acronym,
|
||||
"groupName": item.session.historic_group.name,
|
||||
"groupAcronym": item.session.group_at_the_time().acronym,
|
||||
"groupName": item.session.group_at_the_time().name,
|
||||
"groupParent": {
|
||||
"acronym": item.session.historic_group.parent.acronym
|
||||
# "name": item.session.historic_group.parent.name,
|
||||
# "description": item.session.historic_group.parent.description
|
||||
} if item.session.historic_group.parent else {},
|
||||
"acronym": item.session.group_parent_at_the_time().acronym
|
||||
} if item.session.group_parent_at_the_time() else {},
|
||||
"note": item.session.agenda_note,
|
||||
"remoteInstructions": item.session.remote_instructions,
|
||||
"flags": {
|
||||
|
@ -1849,15 +1846,15 @@ def agenda_csv(schedule, filtered_assignments):
|
|||
row.append("None")
|
||||
row.append(item.timeslot.location.name if item.timeslot.location else "")
|
||||
row.append("")
|
||||
row.append(item.session.historic_group.acronym)
|
||||
row.append(item.session.historic_group.historic_parent.acronym.upper() if item.session.historic_group.historic_parent else "")
|
||||
row.append(item.session.group_at_the_time().acronym)
|
||||
row.append(item.session.group_parent_at_the_time().acronym.upper() if item.session.group_parent_at_the_time() else "")
|
||||
row.append(item.session.name)
|
||||
row.append(item.session.pk)
|
||||
elif item.slot_type().slug == "plenary":
|
||||
row.append(item.session.name)
|
||||
row.append(item.timeslot.location.name if item.timeslot.location else "")
|
||||
row.append("")
|
||||
row.append(item.session.historic_group.acronym if item.session.historic_group else "")
|
||||
row.append(item.session.group_at_the_time().acronym)
|
||||
row.append("")
|
||||
row.append(item.session.name)
|
||||
row.append(item.session.pk)
|
||||
|
@ -1866,10 +1863,10 @@ def agenda_csv(schedule, filtered_assignments):
|
|||
elif item.slot_type().slug == 'regular':
|
||||
row.append(item.timeslot.name)
|
||||
row.append(item.timeslot.location.name if item.timeslot.location else "")
|
||||
row.append(item.session.historic_group.historic_parent.acronym.upper() if item.session.historic_group.historic_parent else "")
|
||||
row.append(item.session.historic_group.acronym if item.session.historic_group else "")
|
||||
row.append("BOF" if item.session.historic_group.state_id in ("bof", "bof-conc") else item.session.historic_group.type.name)
|
||||
row.append(item.session.historic_group.name if item.session.historic_group else "")
|
||||
row.append(item.session.group_parent_at_the_time().acronym.upper() if item.session.group_parent_at_the_time() else "")
|
||||
row.append(item.session.group_at_the_time().acronym)
|
||||
row.append("BOF" if item.session.group_at_the_time().state_id in ("bof", "bof-conc") else item.session.group_at_the_time().type.name)
|
||||
row.append(item.session.group_at_the_time().name)
|
||||
row.append(item.session.pk)
|
||||
row.append(agenda_field(item))
|
||||
row.append(slides_field(item))
|
||||
|
@ -2029,11 +2026,7 @@ def parse_agenda_filter_params(querydict):
|
|||
|
||||
|
||||
def should_include_assignment(filter_params, assignment):
|
||||
"""Decide whether to include an assignment
|
||||
|
||||
When filtering by wg, uses historic_group if available as an attribute
|
||||
on the session, otherwise falls back to using group.
|
||||
"""
|
||||
"""Decide whether to include an assignment"""
|
||||
shown = len(set(filter_params['show']).intersection(assignment.filter_keywords)) > 0
|
||||
hidden = len(set(filter_params['hide']).intersection(assignment.filter_keywords)) > 0
|
||||
return shown and not hidden
|
||||
|
@ -2080,7 +2073,7 @@ def agenda_ical(request, num=None, name=None, acronym=None, session_id=None):
|
|||
assignments = [a for a in assignments if should_include_assignment(filt_params, a)]
|
||||
|
||||
if acronym:
|
||||
assignments = [ a for a in assignments if a.session.historic_group and a.session.historic_group.acronym == acronym ]
|
||||
assignments = [ a for a in assignments if a.session.group_at_the_time().acronym == acronym ]
|
||||
elif session_id:
|
||||
assignments = [ a for a in assignments if a.session_id == int(session_id) ]
|
||||
|
||||
|
@ -2119,23 +2112,23 @@ def agenda_json(request, num=None):
|
|||
sessdict['objtype'] = 'session'
|
||||
sessdict['id'] = asgn.pk
|
||||
sessdict['is_bof'] = False
|
||||
if asgn.session.historic_group:
|
||||
if asgn.session.group_at_the_time():
|
||||
sessdict['group'] = {
|
||||
"acronym": asgn.session.historic_group.acronym,
|
||||
"name": asgn.session.historic_group.name,
|
||||
"type": asgn.session.historic_group.type_id,
|
||||
"state": asgn.session.historic_group.state_id,
|
||||
"acronym": asgn.session.group_at_the_time().acronym,
|
||||
"name": asgn.session.group_at_the_time().name,
|
||||
"type": asgn.session.group_at_the_time().type_id,
|
||||
"state": asgn.session.group_at_the_time().state_id,
|
||||
}
|
||||
if asgn.session.historic_group.is_bof():
|
||||
if asgn.session.group_at_the_time().is_bof():
|
||||
sessdict['is_bof'] = True
|
||||
if asgn.session.historic_group.type_id in ['wg','rg', 'ag', 'rag'] or asgn.session.historic_group.acronym in ['iesg',]: # TODO: should that first list be groupfeatures driven?
|
||||
if asgn.session.historic_group.historic_parent:
|
||||
sessdict['group']['parent'] = asgn.session.historic_group.historic_parent.acronym
|
||||
parent_acronyms.add(asgn.session.historic_group.historic_parent.acronym)
|
||||
if asgn.session.group_at_the_time().type_id in ['wg','rg', 'ag', 'rag'] or asgn.session.group_at_the_time().acronym in ['iesg',]: # TODO: should that first list be groupfeatures driven?
|
||||
if asgn.session.group_parent_at_the_time():
|
||||
sessdict['group']['parent'] = asgn.session.group_parent_at_the_time().acronym
|
||||
parent_acronyms.add(asgn.session.group_parent_at_the_time().acronym)
|
||||
if asgn.session.name:
|
||||
sessdict['name'] = asgn.session.name
|
||||
else:
|
||||
sessdict['name'] = asgn.session.historic_group.name
|
||||
sessdict['name'] = asgn.session.group_at_the_time().name
|
||||
if asgn.session.short:
|
||||
sessdict['short'] = asgn.session.short
|
||||
if asgn.session.agenda_note:
|
||||
|
@ -2291,24 +2284,9 @@ def session_details(request, num, acronym):
|
|||
if not sessions:
|
||||
raise Http404
|
||||
|
||||
# Find the time of the meeting, so that we can look back historically
|
||||
# for what the group was called at the time.
|
||||
meeting_time = meeting.tz().localize(
|
||||
datetime.datetime.combine(meeting.date, datetime.time())
|
||||
)
|
||||
|
||||
groups = list(set([ s.group for s in sessions ]))
|
||||
group_replacements = find_history_replacements_active_at(groups, meeting_time)
|
||||
|
||||
status_names = {n.slug: n.name for n in SessionStatusName.objects.all()}
|
||||
for session in sessions:
|
||||
|
||||
session.historic_group = None
|
||||
if session.group:
|
||||
session.historic_group = group_replacements.get(session.group_id)
|
||||
if session.historic_group:
|
||||
session.historic_group.historic_parent = None
|
||||
|
||||
session.type_counter = Counter()
|
||||
ss = session.timeslotassignments.filter(schedule__in=[meeting.schedule, meeting.schedule.base if meeting.schedule else None]).order_by('timeslot__time')
|
||||
if ss:
|
||||
|
@ -3475,9 +3453,6 @@ def upcoming(request):
|
|||
)
|
||||
).filter(current_status__in=('sched','canceled'))
|
||||
|
||||
for session in interim_sessions:
|
||||
session.historic_group = session.group
|
||||
|
||||
# Set up for agenda filtering - only one filter_category here
|
||||
AgendaKeywordTagger(sessions=interim_sessions).apply()
|
||||
filter_organizer = AgendaFilterOrganizer(sessions=interim_sessions, single_category=True)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright The IETF Trust 2012-2020, All Rights Reserved
|
||||
# Copyright The IETF Trust 2012-2022, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
|
@ -2476,6 +2476,7 @@ class rfc8989EligibilityTests(TestCase):
|
|||
p1 = RoleHistoryFactory(
|
||||
name_id='chair',
|
||||
group__time=day_before,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
).person
|
||||
eligible.append(p1)
|
||||
|
@ -2483,6 +2484,7 @@ class rfc8989EligibilityTests(TestCase):
|
|||
p2 = RoleHistoryFactory(
|
||||
name_id='secr',
|
||||
group__time=year_before,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
).person
|
||||
eligible.append(p2)
|
||||
|
@ -2490,6 +2492,7 @@ class rfc8989EligibilityTests(TestCase):
|
|||
p3 = RoleHistoryFactory(
|
||||
name_id='secr',
|
||||
group__time=just_after_three_years_before,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
).person
|
||||
eligible.append(p3)
|
||||
|
@ -2497,6 +2500,7 @@ class rfc8989EligibilityTests(TestCase):
|
|||
p4 = RoleHistoryFactory(
|
||||
name_id='chair',
|
||||
group__time=three_years_before,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
).person
|
||||
eligible.append(p4)
|
||||
|
@ -2504,6 +2508,7 @@ class rfc8989EligibilityTests(TestCase):
|
|||
p5 = RoleHistoryFactory(
|
||||
name_id='chair',
|
||||
group__time=just_before_three_years_before,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
).person
|
||||
ineligible.append(p5)
|
||||
|
@ -2723,12 +2728,16 @@ class VolunteerDecoratorUnitTests(TestCase):
|
|||
nomcom.volunteer_set.create(person=meeting_person)
|
||||
|
||||
office_person = PersonFactory()
|
||||
history_time = datetime_from_date(elig_date) - datetime.timedelta(days=365)
|
||||
RoleHistoryFactory(
|
||||
name_id='chair',
|
||||
group__time=datetime_from_date(elig_date) - datetime.timedelta(days=365),
|
||||
group__time=history_time,
|
||||
group__group__time=history_time,
|
||||
group__state_id='active',
|
||||
group__group__state_id='conclude',
|
||||
person=office_person,
|
||||
)
|
||||
|
||||
nomcom.volunteer_set.create(person=office_person)
|
||||
|
||||
author_person = PersonFactory()
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
VERSION:2.0
|
||||
METHOD:PUBLISH
|
||||
PRODID:-//IETF//datatracker.ietf.org ical agenda//EN
|
||||
{{schedule.meeting.vtimezone}}{% for item in assignments %}{% if item.session.historic_group %}BEGIN:VEVENT
|
||||
{{schedule.meeting.vtimezone}}{% for item in assignments %}BEGIN:VEVENT
|
||||
UID:ietf-{{schedule.meeting.number}}-{{item.timeslot.pk}}-{{item.session.group.acronym}}
|
||||
SUMMARY:{% if item.session.name %}{{item.session.name|ics_esc}}{% else %}{% if not item.session.historic_group %}{{item.timeslot.name|ics_esc}}{% else %}{{item.session.historic_group.acronym|lower}} - {{item.session.historic_group.name}}{% endif%}{%endif%}{% if item.session.agenda_note %} ({{item.session.agenda_note}}){% endif %}
|
||||
SUMMARY:{% if item.session.name %}{{item.session.name|ics_esc}}{% else %}{{item.session.group_at_the_time.acronym|lower}} - {{item.session.group_at_the_time.name}}{%endif%}{% if item.session.agenda_note %} ({{item.session.agenda_note}}){% endif %}
|
||||
{% if item.timeslot.show_location %}LOCATION:{{item.timeslot.get_location}}
|
||||
{% endif %}STATUS:{{item.session.ical_status}}
|
||||
STATUS:{{item.session.ical_status}}
|
||||
CLASS:PUBLIC
|
||||
DTSTART{% ics_date_time item.timeslot.local_start_time schedule.meeting.time_zone %}
|
||||
DTEND{% ics_date_time item.timeslot.local_end_time schedule.meeting.time_zone %}
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
{{ item.timeslot.time_desc }} {{ item.session.name }} - {{ item.timeslot.location.name }}
|
||||
|
||||
{{ item.session.agenda_text.strip|indent:"3" }}
|
||||
{% endif %}{% if item.slot_type.slug == 'regular' %}{% if item.session.historic_group %}{% ifchanged %}
|
||||
{% endif %}{% if item.slot_type.slug == 'regular' %}{% ifchanged %}
|
||||
|
||||
{{ item.timeslot.time_desc }} {{ item.timeslot.name }}
|
||||
{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.historic_group.historic_parent.acronym|upper|ljust:4 }} {{ item.session.historic_group.acronym|ljust:10 }} {{ item.session.historic_group.name }} {% if item.session.historic_group.state_id == "bof" %}BOF{% elif item.session.historic_group.type_id == "wg" %}WG{% endif %}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %}{% if item.session.current_status == 'canceled' %} *** CANCELLED ***{% elif item.session.current_status == 'resched' %} *** RESCHEDULED{% if item.session.rescheduled_to %} TO {{ item.session.rescheduled_to.time|date:"l G:i"|upper }}-{{ item.session.rescheduled_to.end_time|date:"G:i" }}{% endif %} ***{% endif %}
|
||||
{% endif %}{% endif %}{% if item.slot_type.slug == "break" %}
|
||||
{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.group_parent_at_the_time.acronym|upper|ljust:4 }} {{ item.session.group_at_the_time.acronym|ljust:10 }} {{ item.session.group_at_the_time.name }} {% if item.session.group_at_the_time.state_id == "bof" %}BOF{% elif item.session.group_at_the_time.type_id == "wg" %}WG{% endif %}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %}{% if item.session.current_status == 'canceled' %} *** CANCELLED ***{% elif item.session.current_status == 'resched' %} *** RESCHEDULED{% if item.session.rescheduled_to %} TO {{ item.session.rescheduled_to.time|date:"l G:i"|upper }}-{{ item.session.rescheduled_to.end_time|date:"G:i" }}{% endif %} ***{% endif %}
|
||||
{% endif %}{% if item.slot_type.slug == "break" %}
|
||||
{{ item.timeslot.time_desc }} {{ item.timeslot.name }}{% if schedule.meeting.break_area and item.timeslot.show_location %} - {{ schedule.meeting.break_area }}{% endif %}{% endif %}{% if item.slot_type.slug == "other" %}
|
||||
{{ item.timeslot.time_desc }} {{ item.timeslot.name }} - {{ item.timeslot.location.name }}{% endif %}{% endfor %}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{# Copyright The IETF Trust 2015-2022, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
{% load static %}
|
||||
{% load textfilters tz %}
|
||||
{% origin %}
|
||||
{% with item=session.official_timeslotassignment acronym=session.historic_group.acronym %}
|
||||
{% with item=session.official_timeslotassignment acronym=session.group_at_the_time.acronym %}
|
||||
<div role="group" class="btn-group btn-group-sm">
|
||||
{% if session.agenda and show_agenda %}
|
||||
{% include "meeting/session_agenda_include.html" with slug=item.slug session=session timeslot=item.timeslot only %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{# Copyright The IETF Trust 2015-2022, All Rights Reserved #}
|
||||
{# expects slug, session, and timeslot to be in the context. Calling template must load the agenda_materials.js script. #}
|
||||
{% load origin %}
|
||||
{% origin %}
|
||||
|
@ -19,7 +19,7 @@
|
|||
{% if timeslot.type.slug == 'plenary' %}
|
||||
{{ timeslot.name }}
|
||||
{% else %}
|
||||
{{ session.historic_group.name }}
|
||||
{{ session.group_at_the_time.name }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<button type="button"
|
||||
|
|
Loading…
Reference in a new issue