diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index b6f2e88be..a4e22d2bb 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -91,8 +91,7 @@ class TimeSlot(models.Model): duration = TimedeltaField() location = models.ForeignKey(Room, blank=True, null=True) show_location = models.BooleanField(default=True, help_text="Show location in agenda") - materials = models.ManyToManyField(Document, blank=True) - session = models.ForeignKey('Session', null=True, blank=True, help_text=u"Scheduled group session, if any") + session = models.ForeignKey('Session', null=True, blank=True, help_text=u"Scheduled session, if any") modified = models.DateTimeField(default=datetime.datetime.now) def __unicode__(self): @@ -130,31 +129,25 @@ class Constraint(models.Model): class Session(models.Model): """Session records that a group should have a session on the - meeting (the actual period of time and location is stored in - TimeSlot) - if multiple timeslots are needed, multiple sessions - will have to be created.""" + meeting (time and location is stored in a TimeSlot) - if multiple + timeslots are needed, multiple sessions will have to be created. + Training sessions and similar are modeled by filling in a + responsible group (e.g. Edu team) and filling in the name""" meeting = models.ForeignKey(Meeting) + name = models.CharField(blank=True, max_length=255, help_text="Name of session, in case the session has a purpose rather than just being a group meeting") group = models.ForeignKey(Group) # The group type determines the session type. BOFs also need to be added as a group. attendees = models.IntegerField(null=True, blank=True) agenda_note = models.CharField(blank=True, max_length=255) - # requested = models.DateTimeField(default=datetime.datetime.now) requested_by = models.ForeignKey(Person) requested_duration = TimedeltaField() comments = models.TextField() - # status = models.ForeignKey(SessionStatusName) scheduled = models.DateTimeField(null=True, blank=True) modified = models.DateTimeField(default=datetime.datetime.now) - # contains the materials while the session is being requested, - # when it is scheduled, timeslot.materials should be used materials = models.ManyToManyField(Document, blank=True) def __unicode__(self): timeslots = self.timeslot_set.order_by('time') return u"%s: %s %s" % (self.meeting, self.group.acronym, timeslots[0].time.strftime("%H%M") if timeslots else "(unscheduled)") - -# IESG history is extracted from GroupHistory, rather than hand coded in a -# separate table. - diff --git a/ietf/meeting/proxy.py b/ietf/meeting/proxy.py index e9d0a534b..3430f6bc1 100644 --- a/ietf/meeting/proxy.py +++ b/ietf/meeting/proxy.py @@ -360,7 +360,12 @@ class WgMeetingSessionProxy(TimeSlot): return "%s at %s" % (self.acronym(), self.meeting) def agenda_file(self,interimvar=0): if not hasattr(self, '_agenda_file'): - docs = self.materials.filter(type="agenda", states__type="agenda", states__slug="active") + self._agenda_file = "" + + if not self.session: + return "" + + docs = self.session.materials.filter(type="agenda", states__type="agenda", states__slug="active") if not docs: return "" @@ -371,7 +376,10 @@ class WgMeetingSessionProxy(TimeSlot): return self._agenda_file def minute_file(self,interimvar=0): - docs = self.materials.filter(type="minutes", states__type="minutes", states__slug="active") + if not self.session: + return "" + + docs = self.session.materials.filter(type="minutes", states__type="minutes", states__slug="active") if not docs: return "" @@ -404,17 +412,17 @@ class WgMeetingSessionProxy(TimeSlot): # from ResolveAcronym: def acronym(self): - if not self.session: - if self.type_id == "plenary": - if "Operations and Administration" in self.name: + if self.type_id == "plenary": + if "Operations and Administration" in self.name: + return "plenaryw" + if "Technical" in self.name: + return "plenaryt" + for m in self.materials.filter(type="agenda", states__type="agenda", states__slug="active"): + if "plenaryw" in m.name: return "plenaryw" - if "Technical" in self.name: + if "plenaryt" in m.name: return "plenaryt" - for m in self.materials.filter(type="agenda", states__type="agenda", states__slug="active"): - if "plenaryw" in m.name: - return "plenaryw" - if "plenaryt" in m.name: - return "plenaryt" + if not self.session: return "%s" % self.pk if hasattr(self, "interim"): return "i" + self.session.group.acronym @@ -427,6 +435,8 @@ class WgMeetingSessionProxy(TimeSlot): return self.name if hasattr(self, "interim"): return self.session.group.name + " (interim)" + elif self.session.name: + return self.session.name else: return self.session.group.name def area(self): @@ -510,8 +520,8 @@ class IESGHistoryProxy(Person): #meeting = models.ForeignKey(Meeting, db_column='meeting_num') def from_role(self, role, time): from ietf.utils.history import find_history_active_at - personhistory = find_history_active_at(role.email.person, time) - self.from_object(personhistory or role.email.person) + personhistory = find_history_active_at(role.person, time) + self.from_object(personhistory or role.person) from redesign.group.proxy import Area self.area = Area().from_object(role.group) return self diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 9ffa70a3b..5e114e23a 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -26,6 +26,10 @@ from ietf.utils.pipe import pipe from ietf.proceedings.models import Meeting, MeetingTime, WgMeetingSession, MeetingVenue, IESGHistory, Proceeding, Switches, WgProceedingsActivities, SessionConflict +from redesign.group.models import Group +from ietf.utils.history import find_history_active_at +from redesign.doc.models import Document + @decorator_from_middleware(GZipMiddleware) def show_html_materials(request, meeting_num=None): @@ -141,19 +145,16 @@ def agenda_infoREDESIGN(num=None): ads = [] meeting_time = datetime.datetime.combine(meeting.date, datetime.time(0, 0, 0)) - from redesign.group.models import Group - from ietf.utils.history import find_history_active_at for g in Group.objects.filter(type="area").order_by("acronym"): history = find_history_active_at(g, meeting_time) if history: if history.state_id == "active": - ads.extend(IESGHistory().from_role(x, meeting_time) for x in history.rolehistory_set.filter(name="ad")) + ads.extend(IESGHistory().from_role(x, meeting_time) for x in history.rolehistory_set.filter(name="ad").select_related()) else: if g.state_id == "active": - ads.extend(IESGHistory().from_role(x, meeting_time) for x in g.role_set.filter(name="ad")) + ads.extend(IESGHistory().from_role(x, meeting_time) for x in g.role_set.filter(name="ad").select_related('group', 'person')) - from redesign.doc.models import Document - plenary_agendas = Document.objects.filter(timeslot__meeting=meeting, timeslot__type="plenary", type="agenda").distinct() + plenary_agendas = Document.objects.filter(session__meeting=meeting, session__timeslot__type="plenary", type="agenda").distinct() plenaryw_agenda = plenaryt_agenda = "The Plenary has not been scheduled" for agenda in plenary_agendas: # we use external_url at the moment, should probably regularize @@ -165,12 +166,12 @@ def agenda_infoREDESIGN(num=None): f.close() except IOError: s = "THE AGENDA HAS NOT BEEN UPLOADED YET" - - if "plenaryw" in agenda.name: - plenaryw_agenda = s - elif "plenaryt" in agenda.name: + + if "technical" in agenda.title.lower(): plenaryt_agenda = s - + else: + plenaryw_agenda = s + return timeslots, update, meeting, venue, ads, plenaryw_agenda, plenaryt_agenda if settings.USE_DB_REDESIGN_PROXY_CLASSES: diff --git a/redesign/importing/import-groups.py b/redesign/importing/import-groups.py index 552f5f684..e97b60719 100755 --- a/redesign/importing/import-groups.py +++ b/redesign/importing/import-groups.py @@ -106,6 +106,14 @@ iana_group.state = state_names["active"] iana_group.type = type_names["ietf"] iana_group.save() +# create IEPG for use with meetings +iepg_group, _ = Group.objects.get_or_create(acronym="iepg") +iepg_group.name = "IEPG" +iepg_group.state = state_names["active"] +iepg_group.type = type_names["ietf"] +iepg_group.save() + + system = Person.objects.get(name="(System)") # NomCom diff --git a/redesign/importing/import-meetings.py b/redesign/importing/import-meetings.py index ee6741c56..257982bc7 100755 --- a/redesign/importing/import-meetings.py +++ b/redesign/importing/import-meetings.py @@ -54,7 +54,6 @@ session_slot = name(TimeSlotTypeName, "session", "Session") break_slot = name(TimeSlotTypeName, "break", "Break") registration_slot = name(TimeSlotTypeName, "reg", "Registration") plenary_slot = name(TimeSlotTypeName, "plenary", "Plenary") -other_slot = name(TimeSlotTypeName, "other", "Other") conflict_constraints = { 1: name(ConstraintName, "conflict", "Conflicts with"), @@ -171,14 +170,54 @@ requested_length_mapping = { "4": 150 * 60, } -def import_materials(wg_meeting_session, timeslot=None, session=None): - if timeslot: - meeting = timeslot.meeting - materials = timeslot.materials - else: - meeting = session.meeting - materials = session.materials +non_group_mapping = { + "plenaryw": "ietf", + "plenaryt": "ietf", + "newcomer": "edu", + "editor": "edu", + "wgchair": "edu", + "sectut": "edu", + "protut": "edu", + "iepg": "iepg", + "rfc": "edu", + "wgleader": "edu", + "xml2rfc": "edu", + "rbst": "edu", + "recp": "ietf", + "MIBDOC": "edu", + "IE": "iepg", + "newcomF": "edu", + "WritRFC": "edu", + "Orien": "edu", + "newwork": "edu", + "leadership": "edu", + "ipv6spec": "edu", + "Wel": "ietf", + "IDRTut": "edu", + "ToolsTut": "edu", + "cosp": "tools", + "doclife": "edu", + "dnstut": "edu", + "xmltut": "edu", + "RFCEd": "edu", + "IDRBasics": "edu", + "newcomSWED": "edu", + "MIBTut": "edu", + "IDR75": "edu", + "NewcomerJP": "edu", + "MIBT": "edu", + "DNSProg": "edu", + "natTUT": "edu", + "NewcomerCHINA": "edu", + "CreatingID": "edu", + "NewMeetGreet": "ietf", + "appsprepmeeting": "edu", + "NewcomersFrench": "edu", + "NewComMandar": "edu", + "AdminP": "ietf", + } +def import_materials(wg_meeting_session, session): def import_material_kind(kind, doctype): # import agendas irtf = 0 @@ -190,14 +229,13 @@ def import_materials(wg_meeting_session, timeslot=None, session=None): interim=0) for o in found: - if session: - acronym = session.group.acronym - else: - acronym = wg_meeting_session.acronym() - name = "%s-%s-%s" % (doctype.slug, meeting.number, acronym) + name = "%s-%s-%s" % (doctype.slug, session.meeting.number, acronym) if kind == Slide: name += "-%s" % o.slide_num + if session.name: + name += "-%s" % slugify(session.name) + name = name.lower() try: @@ -205,21 +243,17 @@ def import_materials(wg_meeting_session, timeslot=None, session=None): except Document.DoesNotExist: d = Document(type=doctype, name=name) - if session: - session_name = session.group.acronym.upper() - else: - session_name = timeslot.name - if kind == Slide: d.title = o.slide_name.strip() l = o.file_loc() d.external_url = l[l.find("slides/") + len("slides/"):] d.order = o.order_num or 1 else: - d.title = u"%s for %s at %s" % (doctype.name, session_name, meeting) + session_name = session.name if session.name else session.group.acronym.upper() + d.title = u"%s for %s at %s" % (doctype.name, session_name, session.meeting) d.external_url = o.filename # save filenames for now as they don't appear to be quite regular d.rev = "01" - d.group = session.group if session else None + d.group = session.group d.save() @@ -227,7 +261,7 @@ def import_materials(wg_meeting_session, timeslot=None, session=None): DocAlias.objects.get_or_create(document=d, name=name) - materials.add(d) + session.materials.add(d) # try to create a doc event to figure out who uploaded it t = d.type_id @@ -258,6 +292,8 @@ def import_materials(wg_meeting_session, timeslot=None, session=None): import_material_kind(Minute, minutes_doctype) import_material_kind(Slide, slides_doctype) +obviously_bogus_date = datetime.date(1970, 1, 1) + for o in WgMeetingSession.objects.all().order_by("pk").iterator(): # num_session is unfortunately not quite reliable, seems to be # right for 1 or 2 but not 3 and it's sometimes null @@ -302,30 +338,22 @@ for o in WgMeetingSession.objects.all().order_by("pk").iterator(): acronym = Acronym.objects.get(pk=o.group_acronym_id) if o.group_acronym_id < 0: # this wasn't actually a WG session, but rather a tutorial - # or similar, don't create a session but instead modify - # the time slot appropriately - if not timeslot: - print "IGNORING unscheduled non-WG-session", acronym.name - continue - - meeting_time = getattr(o, "sched_time_id%s" % i) - if meeting_time.session_name_id: - timeslot.name = meeting_time.session_name.session_name - else: - timeslot.name = acronym.name + # or similar + a = non_group_mapping.get(acronym.acronym) + if not a: + a = "ietf" + print "UNKNOWN phony group", o.group_acronym_id, acronym.acronym, "falling back to '%s'" % a + s.group = Group.objects.get(acronym=a) + s.name = acronym.name - if "Plenary" in timeslot.name: - timeslot.type = plenary_slot - else: - timeslot.type = other_slot - timeslot.modified = o.last_modified_date - timeslot.save() - - import_materials(o, timeslot=timeslot) - - continue + if timeslot: + if timeslot.name == "Unknown": + timeslot.name = acronym.name - s.group = Group.objects.get(acronym=acronym.acronym) + if "Plenary" in timeslot.name: + timeslot.type = plenary_slot + else: + s.group = Group.objects.get(acronym=acronym.acronym) s.attendees = o.number_attendee s.agenda_note = (o.special_agenda_note or "").strip() s.requested = o.requested_date or obviously_bogus_date @@ -340,7 +368,7 @@ for o in WgMeetingSession.objects.all().order_by("pk").iterator(): s.status = session_status_mapping[o.status_id or 5] s.scheduled = o.scheduled_date - s.modified = o.last_modified_date + s.modified = o.last_modified_date or obviously_bogus_date s.save() @@ -349,7 +377,7 @@ for o in WgMeetingSession.objects.all().order_by("pk").iterator(): timeslot.modified = s.modified timeslot.save() - import_materials(o, timeslot=timeslot, session=s) + import_materials(o, s) # some sessions have been scheduled over multiple time slots if i < 3: @@ -358,7 +386,6 @@ for o in WgMeetingSession.objects.all().order_by("pk").iterator(): timeslot.session = s timeslot.modified = s.modified timeslot.save() - import_materials(o, timeslot=timeslot, session=s) for i in (1, 2, 3):