Allows the secretariat to manage more meeting types, including leadership meetings.

Backfills those types of meetings from IETF91 and IETF92.
Addresses several facelift issues in the meeting application.
Commit ready for merge.
 - Legacy-Id: 9603
This commit is contained in:
Robert Sparks 2015-05-04 15:58:18 +00:00
commit a85424ad23
42 changed files with 1123 additions and 77 deletions

View file

@ -22,8 +22,8 @@ scheduled = SessionStatusName.objects.get(slug='sched')
for meeting in Meeting.objects.filter(type="ietf").order_by("date"):
print "Checking %s schedules ..." % meeting
brk, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Break', )
reg, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Registration', )
brk, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Break', type_id='break',)
reg, __ = Session.objects.get_or_create(meeting=meeting, group=secretariat, requested_by=system, status=scheduled, name='Registration', type_id='reg',)
for schedule in meeting.schedule_set.all():
print " Checking for missing Break and Reg sessions in %s" % schedule

View file

@ -527,6 +527,7 @@ class DocTestCase(TestCase):
status = SessionStatusName.objects.create(slug='scheduled', name='Scheduled'),
modified = datetime.datetime.now(),
requested_by = Person.objects.get(user__username="marschairman"),
type_id = "session",
)
SessionPresentation.objects.create(session=session, document=doc, rev=doc.rev)

View file

@ -148,6 +148,7 @@ class GroupMaterialTests(TestCase):
status = SessionStatusName.objects.create(slug='scheduled', name='Scheduled'),
modified = datetime.datetime.now(),
requested_by = Person.objects.get(user__username="marschairman"),
type_id="session",
)
SessionPresentation.objects.create(session=session, document=doc, rev=doc.rev)

View file

@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('group', '0003_auto_20150304_0743'),
]
operations = [
migrations.AlterField(
model_name='group',
name='unused_states',
field=models.ManyToManyField(help_text=b'Document states that have been disabled for the group.', to='doc.State', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='group',
name='unused_tags',
field=models.ManyToManyField(help_text=b'Document tags that have been disabled for the group.', to='name.DocTagName', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='grouphistory',
name='unused_states',
field=models.ManyToManyField(help_text=b'Document states that have been disabled for the group.', to='doc.State', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='grouphistory',
name='unused_tags',
field=models.ManyToManyField(help_text=b'Document tags that have been disabled for the group.', to='name.DocTagName', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='groupmilestone',
name='resolved',
field=models.CharField(help_text=b'Explanation of why milestone is resolved (usually "Done"), or empty if still due.', max_length=50, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='groupmilestonehistory',
name='resolved',
field=models.CharField(help_text=b'Explanation of why milestone is resolved (usually "Done"), or empty if still due.', max_length=50, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='role',
name='email',
field=models.ForeignKey(help_text=b'Email address used by person for this role.', to='person.Email'),
preserve_default=True,
),
migrations.AlterField(
model_name='rolehistory',
name='email',
field=models.ForeignKey(help_text=b'Email address used by person for this role.', to='person.Email'),
preserve_default=True,
),
]

View file

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def create_iab_roles(apps, schema_editor):
Role = apps.get_model('group','Role')
Group = apps.get_model('group','Group')
Person = apps.get_model('person','Person')
iab = Group.objects.get(acronym='iab')
iab_names = [
'Jari Arkko',
'Mary Barnes',
'Marc Blanchet',
'Ralph Droms',
'Ted Hardie',
'Joe Hildebrand',
'Russ Housley',
'Erik Nordmark',
'Robert Sparks',
'Andrew Sullivan',
'Dave Thaler',
'Brian Trammell',
'Suzanne Woolf',
]
for name in iab_names:
person = Person.objects.get(name=name)
person.role_set.add(Role(name_id='member',group=iab,person=person,email_id=person.email_set.filter(active=True).order_by('-time').first().address))
class Migration(migrations.Migration):
dependencies = [
('group', '0004_auto_20150430_0847'),
]
operations = [
migrations.RunPython(create_iab_roles),
]

View file

@ -46,6 +46,7 @@ def has_role(user, role_names, *args, **kwargs):
role_qs = {
"Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"),
"Secretariat": Q(person=person, name="secr", group__acronym="secretariat"),
"IAB" : Q(person=person, name="member", group__acronym="iab"),
"IANA": Q(person=person, name="auth", group__acronym="iana"),
"RFC Editor": Q(person=person, name="auth", group__acronym="rfceditor"),
"ISE" : Q(person=person, name="chair", group__acronym="ise"),

View file

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('ipr', '0002_remove_legacy_models'),
]
operations = [
migrations.AlterField(
model_name='genericiprdisclosure',
name='holder_contact_info',
field=models.TextField(help_text=b'Address, phone, etc.', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='holderiprdisclosure',
name='holder_contact_info',
field=models.TextField(help_text=b'Address, phone, etc.', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='iprdisclosurebase',
name='compliant',
field=models.BooleanField(default=True, verbose_name=b'Complies to RFC3979'),
preserve_default=True,
),
migrations.AlterField(
model_name='iprdisclosurebase',
name='notes',
field=models.TextField(verbose_name=b'Additional notes', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='iprdisclosurebase',
name='other_designations',
field=models.CharField(max_length=255, verbose_name=b'Designations for other contributions', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='nondocspecificiprdisclosure',
name='holder_contact_info',
field=models.TextField(help_text=b'Address, phone, etc.', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='thirdpartyiprdisclosure',
name='ietfer_contact_info',
field=models.TextField(help_text=b'Address, phone, etc.', blank=True),
preserve_default=True,
),
]

View file

@ -158,6 +158,8 @@ AddSlotForm = modelform_factory(TimeSlot, exclude=('meeting','name','location','
# no authorization required to list.
def timeslot_slotlist(request, mtg):
slots = mtg.timeslot_set.all()
# Restrict graphical editing to slots of type 'session' for now
slots = slots.filter(type__slug='session')
json_array=[]
for slot in slots:
json_array.append(slot.json_dict(request.build_absolute_uri('/')))

View file

@ -66,7 +66,7 @@ def build_all_agenda_slices(meeting):
time_slices = []
date_slices = {}
for ts in meeting.timeslot_set.exclude(type__in=['reg','break']).order_by('time','name'):
for ts in meeting.timeslot_set.filter(type__in=['session',]).order_by('time','name'):
ymd = ts.time.date()
if ymd not in date_slices and ts.location != None:
@ -80,13 +80,10 @@ def build_all_agenda_slices(meeting):
time_slices.sort()
return time_slices,date_slices
def get_scheduledsessions_from_schedule(schedule):
ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False).exclude(session__isnull = True).order_by('timeslot__time','timeslot__name','session__group__group')
return ss
def get_all_scheduledsessions_from_schedule(schedule):
ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False).order_by('timeslot__time','timeslot__name')
ss = schedule.scheduledsession_set.filter(timeslot__location__isnull = False)
ss = ss.filter(session__type__slug='session')
ss = ss.order_by('timeslot__time','timeslot__name')
return ss

View file

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('meeting', '0004_auto_20150308_0446'),
]
operations = [
migrations.AlterField(
model_name='meeting',
name='agenda_note',
field=models.TextField(help_text=b'Text in this field will be placed at the top of the html agenda page for the meeting. HTML can be used, but will not be validated.', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='schedule',
name='public',
field=models.BooleanField(default=True, help_text='Make this agenda publically available.'),
preserve_default=True,
),
migrations.AlterField(
model_name='schedule',
name='visible',
field=models.BooleanField(default=True, help_text='Make this agenda available to those who know about it.'),
preserve_default=True,
),
migrations.AlterField(
model_name='scheduledsession',
name='extendedfrom',
field=models.ForeignKey(default=None, to='meeting.ScheduledSession', help_text='Timeslot this session is an extension of.', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='scheduledsession',
name='pinned',
field=models.BooleanField(default=False, help_text=b'Do not move session during automatic placement.'),
preserve_default=True,
),
migrations.AlterField(
model_name='scheduledsession',
name='session',
field=models.ForeignKey(default=None, to='meeting.Session', help_text='Scheduled session.', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='session',
name='name',
field=models.CharField(help_text=b'Name of session, in case the session has a purpose rather than just being a group meeting.', max_length=255, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='session',
name='short',
field=models.CharField(help_text=b"Short version of 'name' above, for use in filenames.", max_length=32, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='timeslot',
name='sessions',
field=models.ManyToManyField(related_name='slots', to='meeting.Session', through='meeting.ScheduledSession', blank=True, help_text='Scheduled session, if any.', null=True),
preserve_default=True,
),
migrations.AlterField(
model_name='timeslot',
name='show_location',
field=models.BooleanField(default=True, help_text=b'Show location in agenda.'),
preserve_default=True,
),
]

View file

@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
from django.db import migrations
def backfill_91_other_meetings(apps, schema_editor):
Meeting = apps.get_model('meeting', 'Meeting')
Schedule = apps.get_model('meeting', 'Schedule')
ScheduledSession = apps.get_model('meeting', 'ScheduledSession')
Room = apps.get_model('meeting', 'Room')
Group = apps.get_model('group', 'Group')
Person = apps.get_model('person', 'Person')
ietf91 = Meeting.objects.filter(number=91).first()
if not ietf91:
print "IETF91 not found, no data changed"
else:
agenda91 = Schedule.objects.get(meeting=ietf91,pk=ietf91.agenda.pk)
south_pacific_1 = Room.objects.get(meeting=ietf91,name="South Pacific 1")
south_pacific_2 = Room.objects.get(meeting=ietf91,name="South Pacific 2")
rainbow_12 = Room.objects.get(meeting=ietf91,name="Rainbow Suite 1/2")
lehua_suite = Room.objects.get(meeting=ietf91,name="Lehua Suite")
kahili = Room.objects.get(meeting=ietf91,name="Kahili")
coral_2 = Room.objects.get(meeting=ietf91,name="Coral 2")
south_pacific_3 = Room.objects.create(meeting=ietf91,name="South Pacific 3",capacity=20)
rainbow_suite_3 = Room.objects.create(meeting=ietf91,name="Rainbow Suite 3",capacity=20)
rainbow_23 = Room.objects.create(meeting=ietf91,name="Rainbow Suite 2/3",capacity=210)
south_pacific_34 = Room.objects.create(meeting=ietf91,name="South Pacific 3/4",capacity=210)
iolani_67 = Room.objects.create(meeting=ietf91,name="Iolani 6/7",capacity=40)
sea_pearl_12 = Room.objects.create(meeting=ietf91,name="Sea Pearl 1/2",capacity=40)
sea_pearl_2 = Room.objects.create(meeting=ietf91,name="Sea Pearl 2",capacity=20)
coral_lounge = Room.objects.create(meeting=ietf91,name="Coral Lounge", capacity=1200)
hibiscus = Room.objects.create(meeting=ietf91,name="Hibiscus", capacity=20)
tiare = Room.objects.create(meeting=ietf91,name="Tiare Suite", capacity=20)
iesg = Group.objects.get(acronym='iesg')
iab = Group.objects.get(acronym='iab')
rsoc = Group.objects.get(acronym='rsoc')
iaoc = Group.objects.get(acronym='iaoc')
nomcom = Group.objects.get(acronym='nomcom2014')
isoc = Group.objects.get(acronym='isoc')
secr = Group.objects.get(acronym='secretariat')
isocbot = Group.objects.create(acronym='isocbot',name="Internet Society Board of Trustees",state_id='active',type_id='isoc',parent=isoc)
isocfell = Group.objects.create(acronym='isocfell',name="Internet Society Fellows",state_id='active',type_id='isoc',parent=isoc)
system = Person.objects.get(name='(System)')
for d, h, m, duration, type_id, groups, room, slotname, label in [
( 9, 8, 0, 120, 'offagenda', [secr], rainbow_suite_3, 'WEIRDS Interop', 'WEIRDS Interop'),
( 9, 8, 30, 90, 'lead', [iesg], south_pacific_2, 'Breakfast', None),
( 9, 9, 0, 240, 'offagenda', [secr], lehua_suite, 'RMCAT Interim', 'RMCAT Interim Meeting'),
( 9, 9, 0, 60, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 9, 9, 0, 150, 'lead', [iesg], south_pacific_2, 'Meeting', None),
( 9, 9, 0, 360, 'offagenda', [secr], hibiscus, 'Meeting', 'RootOPS'),
( 9, 9, 30, 360, 'offagenda', [secr], kahili, 'TLS Interim', 'TLS WG Interim'),
( 9, 11, 0, 480, 'offagenda', [secr], coral_lounge, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 9, 11, 30, 150, 'lead', [iesg], south_pacific_2, 'Lunch', 'IESG Lunch with the IAB'),
( 9, 11, 30, 150, 'lead', [iab], south_pacific_2, 'Lunch', 'IAB Lunch with the IESG'),
( 9, 12, 0, 360, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 9, 14, 0, 180, 'lead', [iab], south_pacific_2, 'Meeting', None),
( 9, 16, 0, 120, 'offagenda', [secr], coral_2, 'Meeting', 'Web Object Encryption'),
( 9, 17, 0, 120, 'offagenda', [secr], sea_pearl_12, 'Reception', "Companion's Reception"), # Should this appear on agenda?
( 9, 19, 0, 180, 'offagenda', [isocfell], rainbow_23, 'Dinner', 'ISOC Fellows Reception/Dinner'),
( 9, 19, 0, 180, 'offagenda', [secr], lehua_suite, 'Meeting', 'Huawei'),
( 9, 21, 0, 180, 'lead', [secr], sea_pearl_12, 'Gathering', 'AMS/IESG/IAB/IAOC Gathering'),
( 10, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 10, 7, 0, 120, 'lead', [iesg], south_pacific_2, 'Breakfast', 'IESG Breakfast with the IAB'),
( 10, 7, 0, 120, 'lead', [iab], south_pacific_2, 'Breakfast', 'IAB Breakfast with the IESG'),
( 10, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 10, 8, 0, 600, 'offagenda', [secr], coral_lounge, 'T-shirt Distribution', 'T-shirt Distribution'),
( 10, 11, 30, 90, 'offagenda', [secr], south_pacific_2, 'Meeting', 'OPS Directorate Meeting'),
( 10, 11, 30, 90, 'offagenda', [secr], rainbow_suite_3, 'Meeting', 'IETF/3GPP Meeting'),
( 10, 11, 30, 90, 'offagenda', [secr], lehua_suite, 'Meeting', 'RTG Area Meeting'),
( 10, 19, 0, 240, 'offagenda', [secr], south_pacific_2, 'Meeting', 'Huawei'),
( 11, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 11, 7, 0, 120, 'lead', [iesg], south_pacific_2, 'Breakfast', None),
( 11, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 11, 7, 0, 120, 'lead', [iab], rainbow_suite_3, 'Breakfast', None),
( 11, 7, 0, 60, 'lead', [iab], tiare, 'Meeting', 'Vendor Selection Committee Meeting'),
( 11, 8, 0, 600, 'offagenda', [secr], coral_lounge, 'T-shirt Distribution', 'T-shirt Distribution'),
( 11, 9, 0, 90, 'offagenda', [secr], south_pacific_2, 'Meeting', 'DHCPv6bis Team Meeting'),
( 11, 11, 30, 90, 'offagenda', [secr], south_pacific_2, 'Meeting', 'SECdir Meeting'),
( 11, 11, 30, 90, 'offagenda', [secr], rainbow_suite_3, 'Lunch', 'RSAG/ISEB Lunch'),
( 11, 16, 0, 240, 'offagenda', [secr], south_pacific_2, 'Meeting', 'Verisign Corporate Meeting'),
( 12, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 12, 7, 30, 90, 'lead', [iaoc], south_pacific_3, 'Breakfast', None),
( 12, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 12, 8, 0, 540, 'offagenda', [secr], coral_lounge, 'T-shirt Distribution', 'T-shirt Distribution'),
( 12, 8, 0, 240, 'offagenda', [secr], south_pacific_2, 'Meeting', 'DIME WG'),
( 12, 11, 30, 90, 'offagenda', [secr], rainbow_suite_3, 'Lunch', 'RFC Editor Lunch'),
( 12, 15, 0, 120, 'offagenda', [secr], south_pacific_2, 'Meeting', 'YANG Advice'),
( 12, 17, 0, 240, 'offagenda', [secr], rainbow_suite_3, 'Meeting', 'Huawei (POC Wil Liu)'),
( 12, 20, 0, 150, 'offagenda', [secr], south_pacific_2, 'Meeting', 'ICANN SSAC'),
( 13, 0, 0, 1440, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 13, 7, 0, 120, 'lead', [iab], rainbow_suite_3, 'Breakfast', None),
( 13, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 13, 11, 30, 90, 'lead', [iab], sea_pearl_2, 'Meeting', 'IAB Liaison Oversight'),
( 13, 11, 30, 90, 'lead', [rsoc], rainbow_suite_3, 'Lunch', None),
( 14, 0, 0, 900, 'offagenda', [secr], south_pacific_1, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 14, 7, 0, 120, 'lead', [nomcom], iolani_67, 'Breakfast', 'Nomcom Breakfast'),
( 14, 11, 0, 360, 'offagenda', [isoc], south_pacific_34,'Meeeting', 'ISOC AC Meeting'),
( 14, 13, 30, 90, 'lead', [iesg], south_pacific_2, 'Lunch', 'IESG Lunch with the IAB'),
( 14, 13, 30, 90, 'lead', [iab], south_pacific_2, 'Lunch', 'IAB Lunch with the IESG'),
( 14, 18, 0, 60, 'offagenda', [isocbot], rainbow_23, 'Reception', 'ISOC Board Reception for IETF Leadership'),
( 14, 19, 0, 180, 'offagenda', [isocbot], rainbow_23, 'Dinner', 'ISOC Board Dinner for IETF Leadership'),
( 15, 8, 0, 60, 'offagenda', [isocbot], rainbow_12, 'Breakfast', 'ISOC Board of Trustees Breakfast'),
( 15, 8, 0, 540, 'offagenda', [isocbot], south_pacific_34,'Meeting', 'ISOC Board of Trustees Meeting'),
( 15, 12, 0, 60, 'offagenda', [isocbot], rainbow_12, 'Lunch', 'ISOC Board of Trustees Lunch'),
( 16, 8, 0, 60, 'offagenda', [isocbot], rainbow_12, 'Breakfast', 'ISOC Board of Trustees Breakfast'),
( 16, 8, 0, 540, 'offagenda', [isocbot], south_pacific_34,'Meeting', 'ISOC Board of Trustees Meeting'),
( 16, 12, 0, 60, 'offagenda', [isocbot], rainbow_12, 'Lunch', 'ISOC Board of Trustees Lunch'),
]:
ts = ietf91.timeslot_set.create(type_id=type_id, name=slotname,
time=datetime.datetime(2014,11,d,h,m,0),
duration=datetime.timedelta(minutes=duration),
location=room,show_location=(type_id not in ['lead','offagenda']))
for group in groups:
session = ietf91.session_set.create(name= label or "%s %s"%(group.acronym.upper(),slotname),
group=group, attendees=25,
requested=datetime.datetime(2014,11,1,0,0,0),
requested_by=system, status_id='sched')
ScheduledSession.objects.create(schedule=agenda91, timeslot=ts, session=session)
class Migration(migrations.Migration):
dependencies = [
('meeting', '0005_auto_20150430_0847'),
('name', '0004_auto_20150318_1140'),
('group', '0004_auto_20150430_0847'),
('person', '0004_auto_20150308_0440'),
]
operations = [
migrations.RunPython(backfill_91_other_meetings)
]

View file

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
def extract_session_type_values(apps, schema_editor):
Session = apps.get_model('meeting', 'Session')
for s in Session.objects.all():
t = s.scheduledsession_set.filter(schedule=models.F('schedule__meeting__agenda')).first()
if t and t.timeslot.type.slug != 'session':
s.type = t.timeslot.type
s.save()
class Migration(migrations.Migration):
dependencies = [
('name', '0004_auto_20150318_1140'),
('meeting', '0006_auto_20150318_1116'),
]
operations = [
migrations.AddField(
model_name='session',
name='type',
field=models.ForeignKey(default='session', to='name.TimeSlotTypeName'),
preserve_default=False,
),
migrations.RunPython(extract_session_type_values),
]

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
def extract_room_session_type_values(apps, schema_editor):
Room = apps.get_model('meeting', 'Room')
for r in Room.objects.all():
for ts in r.timeslot_set.all():
if ts.scheduledsession_set.filter(schedule=models.F('schedule__meeting__agenda')):
r.session_types.add(ts.type)
class Migration(migrations.Migration):
dependencies = [
('name', '0004_auto_20150318_1140'),
('meeting', '0007_auto_20150429_1224'),
]
operations = [
migrations.AddField(
model_name='room',
name='session_types',
field=models.ManyToManyField(to='name.TimeSlotTypeName', blank=True),
preserve_default=True,
),
migrations.RunPython(extract_room_session_type_values),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('meeting', '0008_auto_20150429_1346'),
]
operations = [
migrations.AddField(
model_name='room',
name='functional_name',
field=models.CharField(default='', max_length=255, blank=True),
preserve_default=False,
),
]

View file

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def add_91_room_functional_names(apps, schema_editor):
map = {
'Hibiscus': 'Breakout 3',
'South Pacific 2': 'Meeting Room #6',
'South Pacific 1': 'Terminal Room',
'Coral 1': 'Breakout 4',
'Coral 2': 'Breakout 5',
'Coral 5': 'Breakout 6',
'Coral 4': 'Breakout 7',
'Coral 3': 'Breakout 8',
'Great Lawn': 'Welcome Reception',
'Rainbow Suite': 'Not Used',
'Lehua Suite': 'Breakout 1',
'Kahili': 'Breakout 2',
'Rainbow Suite 1/2': 'Meeting Room #2 (IESG Meeting Room)',
'Village Green': 'Meet and Greet',
'South Pacific 3': 'Meeting Room #4 (IAOC/IAD Office)',
'Rainbow Suite 3': 'Meeting Room #7',
'Rainbow Suite 2/3': 'ISOC Dinner',
'South Pacific 3/4': 'ISOC AC Meeting',
'Iolani 6/7': 'Meeting Room #5 (NomCom Office)',
'Sea Pearl 1/2': 'Reception',
'Sea Pearl 2': 'Meeting Room #1 (IAB Meeting Room)',
'Coral Lounge': 'Registration Area and Breaks',
'Tiare Suite': 'Meeting Room #8 (RFC Office)',
}
Room = apps.get_model('meeting', 'Room')
for name,functional_name in map.items():
Room.objects.filter(meeting__number=91,name=name).update(functional_name=functional_name)
class Migration(migrations.Migration):
dependencies = [
('meeting', '0009_room_functional_name'),
]
operations = [
migrations.RunPython(add_91_room_functional_names),
]

View file

@ -0,0 +1,195 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
from django.db import migrations
def backfill_92_other_meetings(apps, schema_editor):
Meeting = apps.get_model('meeting', 'Meeting')
Schedule = apps.get_model('meeting', 'Schedule')
ScheduledSession = apps.get_model('meeting', 'ScheduledSession')
Room = apps.get_model('meeting', 'Room')
Session = apps.get_model('meeting', 'Session')
Group = apps.get_model('group', 'Group')
Person = apps.get_model('person', 'Person')
ietf92 = Meeting.objects.filter(number=92).first()
if not ietf92:
print "IETF92 not found, no data changed"
else:
# Clear out one orphaned ill-configured Session object
qs = Session.objects.filter(meeting__number=92,name__icontains='beverage break').exclude(type_id='break')
if qs.count()==1:
qs.delete()
agenda92 = Schedule.objects.get(meeting=ietf92,pk=ietf92.agenda.pk)
map_existing = {
'Regency Ballroom': 'Lounge',
'Garden Terrace Level': 'Meet and Greet',
'Royal': 'Breakout 1',
'Continental': 'Breakout 2',
'Far East': 'Breakout 3',
'Oak ': 'Breakout 4',
'Parisian': 'Breakout 5',
'Venetian': 'Breakout 6',
'Gold': 'Breakout 7',
'International': 'Breakout 8',
'Brasserie': 'Terminal Room',
'State': 'Office #3 (Secretariat Office)',
'French': 'Meeting Room #2 (IESG Meeting Room)',
}
for name,functional_name in map_existing.items():
Room.objects.filter(meeting__number=92,name=name).update(functional_name=functional_name)
regency = Room.objects.get(meeting=ietf92,name='Regency Ballroom')
garden = Room.objects.get(meeting=ietf92,name='Garden Terrace Level')
royal = Room.objects.get(meeting=ietf92,name='Royal')
continental = Room.objects.get(meeting=ietf92,name='Continental')
far_east = Room.objects.get(meeting=ietf92,name='Far East')
oak = Room.objects.get(meeting=ietf92,name='Oak ')
#parisian = Room.objects.get(meeting=ietf92,name='Parisian')
#venetian = Room.objects.get(meeting=ietf92,name='Venetian')
#gold = Room.objects.get(meeting=ietf92,name='Gold')
#international = Room.objects.get(meeting=ietf92,name='International')
brasserie = Room.objects.get(meeting=ietf92,name='Brasserie')
state = Room.objects.get(meeting=ietf92,name='State')
#french = Room.objects.get(meeting=ietf92,name='French')
executive = Room.objects.create(meeting=ietf92,name='Executive',functional_name='Meeting Room #4 (IAOC/IAD)',capacity=20)
regency_foyer = Room.objects.create(meeting=ietf92,name='Regency Foyer',functional_name='Registration',capacity=1200)
florentine = Room.objects.create(meeting=ietf92,name='Florentine',functional_name='Meeting Room #1 (IAB)', capacity=40)
pavilion = Room.objects.create(meeting=ietf92,name='Pavilion',functional_name='Meeting Room #6', capacity=80)
terrace = Room.objects.create(meeting=ietf92,name='Terrace',functional_name='Meeting Room #7', capacity=80)
panorama = Room.objects.create(meeting=ietf92,name='Panorama',functional_name='Companion Reception', capacity=200)
regency.session_types.add('offagenda')
pavilion.session_types.add('offagenda')
pavilion.session_types.add('lead')
garden.session_types.add('lead')
panorama.session_types.add('offagenda')
executive.session_types.add('lead')
executive.session_types.add('offagenda')
regency_foyer.session_types.add('offagenda')
oak.session_types.add('offagenda')
continental.session_types.add('offagenda')
state.session_types.add('offagenda')
florentine.session_types.add('offagenda')
terrace.session_types.add('lead')
terrace.session_types.add('offagenda')
far_east.session_types.add('offagenda')
brasserie.session_types.add('offagenda')
royal.session_types.add('offagenda')
iesg = Group.objects.get(acronym='iesg')
iab = Group.objects.get(acronym='iab')
iaoc = Group.objects.get(acronym='iaoc')
secr = Group.objects.get(acronym='secretariat')
system = Person.objects.get(name='(System)')
for d, h, m, duration, type_id, groups, room, slotname, label in [
( 20, 13, 0, 480, 'offagenda', [secr], brasserie, 'Setup', 'Hackathon: Setup'),
( 20, 8, 0, 540, 'offagenda', [secr], executive, 'Meeting', 'DNS OARC Meeting'),
( 21, 8, 0, 540, 'offagenda', [secr], executive, 'Meeting', 'DNS OARC Meeting'),
( 22, 12, 0, 720, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 22, 11, 0, 480, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 22, 19, 0, 120, 'offagenda', [secr], state, 'Meeting', 'CJK Generation Panel coordination informal meeting'),
( 22, 19, 0, 120, 'offagenda', [iab], florentine, 'Meeting', 'IAB PrivSec program'),
( 22, 8, 30, 90, 'lead', [iesg], pavilion, 'Breakfast', None),
( 22, 9, 0, 150, 'lead', [iesg], pavilion, 'Meeting', None),
( 22, 11, 30, 150, 'lead', [iab], pavilion, 'Lunch', 'IAB Lunch with the IESG'),
( 22, 11, 30, 150, 'lead', [iesg], pavilion, 'Lunch', 'IESG Lunch with the IAB'),
( 22, 14, 0, 180, 'lead', [iab], pavilion, 'Meeting', None),
( 22, 9, 0, 480, 'offagenda', [secr], terrace, 'Meeting', 'RootOPS'),
( 22, 16, 30, 60, 'offagenda', [secr], panorama, 'Reception', "Companion's Reception"), # Should this appear on agenda?
( 22, 21, 0, 180, 'lead', [secr], garden, 'Gathering', 'AMS/IESG/IAB/IAOC Gathering'),
( 22, 9, 0, 480, 'offagenda', [secr], royal, 'ICNRG', 'ICNRG'),
( 22, 19, 0, 180, 'offagenda', [secr], royal, 'Meeting', 'Huawei'),
( 22, 12, 30, 240, 'offagenda', [secr], continental, 'Meeting', 'Verisign ROA Workshop'),
( 22, 15, 15, 165, 'offagenda', [secr], far_east, 'Meeting', 'RSSAC'),
( 22, 9, 0, 150, 'offagenda', [secr], oak, 'Meeting', 'Ericsson'),
( 23, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 23, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 23, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'),
( 23, 11, 30, 180, 'offagenda', [secr], executive, 'Lunch', 'ICANN Lunch'),
( 23, 7, 0, 120, 'lead', [iesg], pavilion, 'Breakfast', 'IESG Breakfast with the IAB'),
( 23, 7, 0, 120, 'lead', [iab], pavilion, 'Breakfast', 'IAB Breakfast with the IESG'),
( 23, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'OPS Directorate Meeting'),
( 23, 19, 0, 120, 'offagenda', [secr], pavilion, 'Meeting', 'ACE'),
( 23, 7, 30, 90, 'offagenda', [secr], terrace, 'Meeting', 'NRO ECG'),
( 23, 11, 30, 90, 'offagenda', [secr], terrace, 'Meeting', 'IETF/3GPP Meeting'),
( 23, 19, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'I2NSF'),
( 23, 18, 50, 60, 'offagenda', [secr], royal, 'Meeting', 'Captive Portal Bar BOF'),
( 24, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 24, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 24, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'),
( 24, 11, 30, 90, 'offagenda', [secr], state, 'Meeting', 'HIAPS'),
( 24, 16, 30, 120, 'offagenda', [secr], state, 'Meeting', 'PDF Draft Review'),
( 24, 7, 0, 120, 'lead', [iesg], pavilion, 'Breakfast', None),
( 24, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'SECdir Meeting'),
( 24, 7, 0, 120, 'lead', [iab], terrace, 'Breakfast', None),
( 24, 9, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'ICNN DRZK Design Team'),
( 24, 11, 30, 90, 'offagenda', [secr], terrace, 'Lunch', 'RSAG/ISEB Lunch'),
( 24, 13, 0, 120, 'offagenda', [secr], terrace, 'Meeting', 'SACM'),
( 24, 15, 0, 90, 'offagenda', [secr], terrace, 'Meeting', 'RSOC Meeting'),
( 24, 17, 30, 60, 'offagenda', [secr], terrace, 'Meeting', 'SACM'),
( 24, 11, 30, 90, 'offagenda', [secr], royal, 'Meeting', 'IoT Directorate'),
( 25, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 25, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 25, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'),
( 25, 8, 0, 60, 'offagenda', [secr], state, 'Meeting', 'SFC Control Plane Offline Discussion'),
( 25, 19, 0, 240, 'offagenda', [secr], state, 'Meeting', 'WWG'),
( 25, 8, 0, 60, 'offagenda', [secr], florentine, 'Meeting', 'IAB Name Resolution'),
( 25, 6, 45, 135, 'lead', [iaoc], executive, 'Breakfast', None),
( 25, 11, 30, 90, 'offagenda', [secr], pavilion, 'Meeting', 'RMCAT'),
( 25, 19, 0, 120, 'offagenda', [secr], pavilion, 'Meeting', 'I2NSF'),
( 25, 8, 0, 60, 'offagenda', [secr], terrace, 'Meeting', 'IETF/IEEE 802 Coordination'),
( 25, 11, 30, 90, 'offagenda', [secr], terrace, 'Lunch', 'RFC Editor Lunch'),
( 25, 19, 30, 120, 'offagenda', [secr], terrace, 'Dinner', 'SSAC Dinner'),
( 26, 0, 0, 1440, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 26, 8, 0, 600, 'offagenda', [secr], regency_foyer, 'T-Shirt Distribution', 'T-shirt Distribution'),
( 26, 0, 0, 1440, 'offagenda', [secr], regency, 'Lounge', 'Lounge'),
( 26, 7, 30, 90, 'offagenda', [secr], state, 'Breakfast', 'EDU Team Breakfast'),
( 26, 14, 0, 120, 'offagenda', [secr], state, 'Meeting', 'JJB'),
( 26, 11, 30, 90, 'offagenda', [secr], florentine, 'Meeting', 'IAB Liaison Oversight'),
( 26, 18, 0, 150, 'offagenda', [secr], pavilion, 'Meeting', '6LO Security Discussion'),
( 26, 7, 0, 120, 'lead', [iab], terrace, 'Breakfast', None),
( 26, 17, 40, 60, 'offagenda', [secr], terrace, 'Meeting', 'SACM'),
( 26, 19, 30, 150, 'offagenda', [secr], royal, 'Meeting', 'Lavabit'),
( 27, 0, 0, 900, 'offagenda', [secr], brasserie, 'Terminal Room', 'Terminal Room Open to Attendees'),
( 27, 7, 30, 90, 'offagenda', [secr], executive, 'Meeting', 'Post-Con with Ray'),
( 27, 7, 30, 75, 'offagenda', [secr], state, 'Breakfast', 'Gen-art'),
( 27, 13, 30, 90, 'lead', [iab], pavilion, 'Lunch', 'IAB Lunch with the IESG'),
( 27, 13, 30, 90, 'lead', [iesg], pavilion, 'Lunch', 'IESG Lunch with the IAB'),
]:
ts = ietf92.timeslot_set.create(type_id=type_id, name=slotname,
time=datetime.datetime(2015,3,d,h,m,0),
duration=datetime.timedelta(minutes=duration),
location=room,show_location=(type_id not in ['lead','offagenda']))
for group in groups:
session = ietf92.session_set.create(name= label or "%s %s"%(group.acronym.upper(),slotname),
group=group, attendees=25,
requested=datetime.datetime(2014,11,1,0,0,0),
requested_by=system, status_id='sched',type_id=type_id)
ScheduledSession.objects.create(schedule=agenda92, timeslot=ts, session=session)
class Migration(migrations.Migration):
dependencies = [
('meeting', '0010_auto_20150501_0732'),
('name', '0004_auto_20150318_1140'),
('group', '0004_auto_20150430_0847'),
('person', '0004_auto_20150308_0440'),
]
operations = [
migrations.RunPython(backfill_92_other_meetings)
]

View file

@ -161,7 +161,10 @@ class Meeting(models.Model):
@property
def sessions_that_can_meet(self):
return self.session_set.exclude(status__slug='notmeet').exclude(status__slug='disappr').exclude(status__slug='deleted').exclude(status__slug='apprw')
qs = self.session_set.exclude(status__slug='notmeet').exclude(status__slug='disappr').exclude(status__slug='deleted').exclude(status__slug='apprw')
# Restrict graphical scheduling to meeting requests (Sessions) of type 'session' for now
qs = qs.filter(type__slug='session')
return qs
def sessions_that_can_be_placed(self):
from django.db.models import Q
@ -284,8 +287,10 @@ class ResourceAssociation(models.Model):
class Room(models.Model):
meeting = models.ForeignKey(Meeting)
name = models.CharField(max_length=255)
functional_name = models.CharField(max_length=255, blank = True)
capacity = models.IntegerField(null=True, blank=True)
resources = models.ManyToManyField(ResourceAssociation, blank = True)
session_types = models.ManyToManyField(TimeSlotTypeName, blank = True)
def __unicode__(self):
return "%s size: %s" % (self.name, self.capacity)
@ -370,7 +375,8 @@ class TimeSlot(models.Model):
return u"%s: %s-%s %s, %s" % (self.meeting.number, self.time.strftime("%m-%d %H:%M"), (self.time + self.duration).strftime("%H:%M"), self.name, location)
def end_time(self):
return self.time + self.duration
def get_location(self):
def get_hidden_location(self):
location = self.location
if location:
location = location.name
@ -378,10 +384,24 @@ class TimeSlot(models.Model):
location = self.meeting.reg_area
elif self.type_id == "break":
location = self.meeting.break_area
return location
def get_location(self):
location = self.get_hidden_location()
if not self.show_location:
location = ""
return location
def get_functional_location(self):
name_parts = []
room = self.location
if room and room.functional_name:
name_parts.append(room.functional_name)
location = self.get_hidden_location()
if location:
name_parts.append(location)
return ' - '.join(name_parts)
@property
def tz(self):
if self.meeting.time_zone:
@ -626,8 +646,7 @@ class Schedule(models.Model):
.distinct() )
def groups(self):
return Group.objects.filter(type__slug__in=['wg', 'rg', 'ag', 'iab'], parent__isnull=False,
session__scheduledsession__schedule=self).distinct().order_by('parent__acronym', 'acronym')
return Group.objects.filter(type__slug__in=['wg', 'rg', 'ag', 'iab'], parent__isnull=False, session__scheduledsession__schedule=self).exclude(session__scheduledsession__timeslot__type__in=['lead','offagenda']).distinct().order_by('parent__acronym', 'acronym')
# calculate badness of entire schedule
def calc_badness(self):
@ -848,7 +867,8 @@ class Session(models.Model):
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.")
short = models.CharField(blank=True, max_length=32, help_text="Short version of 'name' above, for use in filenames.")
group = models.ForeignKey(Group) # The group type determines the session type. BOFs also need to be added as a group.
type = models.ForeignKey(TimeSlotTypeName)
group = models.ForeignKey(Group) # The group type historically determined the session type. BOFs also need to be added as a group. Note that not all meeting requests have a natural group to associate with.
attendees = models.IntegerField(null=True, blank=True)
agenda_note = models.CharField(blank=True, max_length=255)
requested = models.DateTimeField(default=datetime.datetime.now)
@ -1004,7 +1024,13 @@ class Session(models.Model):
else:
return "The agenda has not been uploaded yet."
def type(self):
# FIXME - This used to be called 'type'. It is only used in agenda.csv and agenda.txt.
# It will return the _wrong thing_ if you look back at an agenda of an earlier meeting
# where group X was a BOF at the time, but is now a WG.
# It also doesn't return anything useful for RG, area sessions, or anything that's not group type 'wg'.
# A better thing to do is find a way to note when a meeting was a BoF meeting and use that, removing this
# function altogether.
def lame_description(self):
if self.group.type.slug in [ "wg" ]:
return "BOF" if self.group.state.slug in ["bof", "bof-conc"] else "WG"
else:

View file

@ -20,6 +20,9 @@ def make_meeting_test_data():
pname = RoomResourceName.objects.create(name='projector',slug='proj')
projector = ResourceAssociation.objects.create(name=pname,icon="notfound.png",desc="Basic projector")
room = Room.objects.create(meeting=meeting, name="Test Room", capacity=123)
breakfast_room = Room.objects.create(meeting=meeting, name="Breakfast Room", capacity=40)
room.session_types.add("session")
breakfast_room.session_types.add("lead")
room.resources = [projector]
# mars WG
@ -29,7 +32,7 @@ def make_meeting_test_data():
mars_session = Session.objects.create(meeting=meeting, group=mars,
attendees=10, requested_by=system_person,
requested_duration=20, status_id="schedw",
scheduled=datetime.datetime.now())
scheduled=datetime.datetime.now(),type_id="session")
mars_session.resources = [projector]
ScheduledSession.objects.create(timeslot=slot, session=mars_session, schedule=schedule)
@ -39,26 +42,37 @@ def make_meeting_test_data():
ames_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="ames"),
attendees=10, requested_by=system_person,
requested_duration=20, status_id="schedw",
scheduled=datetime.datetime.now())
scheduled=datetime.datetime.now(),type_id="session")
ScheduledSession.objects.create(timeslot=slot, session=ames_session, schedule=schedule)
# IESG breakfast
breakfast_slot = TimeSlot.objects.create(meeting=meeting, type_id="lead", duration=90 * 60,
location=breakfast_room,
time=datetime.datetime.combine(datetime.date.today(),datetime.time(7,0)))
iesg_session = Session.objects.create(meeting=meeting, group=Group.objects.get(acronym="iesg"),
name="IESG Breakfast",
attendees=25, requested_by=system_person,
requested_duration=20, status_id="schedw",
scheduled=datetime.datetime.now(),type_id="lead")
ScheduledSession.objects.create(timeslot=breakfast_slot, session=iesg_session, schedule=schedule)
meeting.agenda = schedule
meeting.save()
doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars.txt",group=mars)
doc = Document.objects.create(name='agenda-mars-ietf-42', type_id='agenda', title="Agenda", external_url="agenda-mars.txt",group=mars,rev='00')
doc.set_state(State.objects.get(type=doc.type_id, slug="active"))
mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev))
doc = Document.objects.create(name='minutes-mars-ietf-42', type_id='minutes', title="Minutes", external_url="minutes-mars.txt",group=mars)
doc = Document.objects.create(name='minutes-mars-ietf-42', type_id='minutes', title="Minutes", external_url="minutes-mars.txt",group=mars,rev='00')
doc.set_state(State.objects.get(type=doc.type_id, slug="active"))
mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev))
doc = Document.objects.create(name='slides-mars-ietf-42', type_id='slides', title="Slideshow", external_url="slides-mars.txt",group=mars)
doc = Document.objects.create(name='slides-mars-ietf-42', type_id='slides', title="Slideshow", external_url="slides-mars.txt",group=mars,rev='00')
doc.set_state(State.objects.get(type=doc.type_id, slug="active"))
doc.set_state(State.objects.get(type='reuse_policy',slug='single'))
mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev))
doc = Document.objects.create(name='slides-mars-ietf-42-deleted', type_id='slides', title="Bad Slideshow", external_url="slides-mars-deleted.txt",group=mars)
doc = Document.objects.create(name='slides-mars-ietf-42-deleted', type_id='slides', title="Bad Slideshow", external_url="slides-mars-deleted.txt",group=mars,rev='00')
doc.set_state(State.objects.get(type=doc.type_id, slug="deleted"))
doc.set_state(State.objects.get(type='reuse_policy',slug='single'))
mars_session.sessionpresentation_set.add(SessionPresentation(session=mars_session,document=doc,rev=doc.rev))

View file

@ -138,7 +138,7 @@ class ApiTests(TestCase):
timeslots_before = meeting.timeslot_set.count()
url = urlreverse("ietf.meeting.ajax.timeslot_roomsurl", kwargs=dict(num=meeting.number))
post_data = { "name": "new room", "capacity": "50" , "resources": []}
post_data = { "name": "new room", "capacity": "50" , "resources": [], "session_types":["session"]}
# unauthorized post
r = self.client.post(url, post_data)
@ -152,7 +152,10 @@ class ApiTests(TestCase):
self.assertTrue(meeting.room_set.filter(name="new room"))
timeslots_after = meeting.timeslot_set.count()
self.assertEqual((timeslots_after - timeslots_before), (meeting.room_set.count() - 1) * timeslots_before)
# It's not clear that what that ajax function is doing is the right thing to do,
# but it currently makes a new timeslot for any existing timeslot.
# The condition tested below relies on the timeslots before this test all having different start and end times
self.assertEqual( timeslots_after, 2 * timeslots_before)
def test_delete_room(self):
meeting = make_meeting_test_data()
@ -201,7 +204,7 @@ class ApiTests(TestCase):
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = json.loads(r.content)
self.assertEqual(set([x['short_name'] for x in info]),set(['mars','ames']))
self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.agenda.scheduledsession_set.filter(session__type_id='session')]))
schedule = meeting.agenda
url = urlreverse("ietf.meeting.ajax.scheduledsessions_json",
@ -209,7 +212,7 @@ class ApiTests(TestCase):
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = json.loads(r.content)
self.assertEqual(len(info),2)
self.assertEqual(len(info),schedule.scheduledsession_set.count())
def test_slot_json(self):

View file

@ -11,7 +11,7 @@ from pyquery import PyQuery
from ietf.doc.models import Document
from ietf.meeting.models import Session, TimeSlot
from ietf.meeting.test_data import make_meeting_test_data
from ietf.utils.test_utils import TestCase
from ietf.utils.test_utils import TestCase, login_testing_unauthorized
class MeetingTests(TestCase):
def setUp(self):
@ -124,6 +124,38 @@ class MeetingTests(TestCase):
self.assertTrue(session.group.acronym in agenda_content)
self.assertTrue(slot.location.name in agenda_content)
def test_agenda_by_room(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number))
login_testing_unauthorized(self,"secretary",url)
r = self.client.get(url)
self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
def test_agenda_by_type(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number))
login_testing_unauthorized(self,"secretary",url)
r = self.client.get(url)
self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='session'))
r = self.client.get(url)
self.assertTrue(all([x in r.content for x in ['mars','Test Room']]))
self.assertFalse(any([x in r.content for x in ['IESG Breakfast','Breakfast Room']]))
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='lead'))
r = self.client.get(url)
self.assertFalse(any([x in r.content for x in ['mars','Test Room']]))
self.assertTrue(all([x in r.content for x in ['IESG Breakfast','Breakfast Room']]))
def test_session_details(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.views.session_details", kwargs=dict(num=meeting.number, acronym="mars"))
r = self.client.get(url)
self.assertTrue(all([x in r.content for x in ('slides','agenda','minutes')]))
self.assertFalse('deleted' in r.content)
def test_materials(self):
meeting = make_meeting_test_data()
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()

View file

@ -33,6 +33,10 @@ urlpatterns = patterns('',
(r'^(?P<num>\d+)/agenda(?P<ext>.txt)$', views.agenda),
(r'^(?P<num>\d+)/agenda.ics$', views.ical_agenda),
(r'^(?P<num>\d+)/agenda(?P<ext>.csv)$', views.agenda),
(r'^(?P<num>\d+)/agenda/by-room$', views.agenda_by_room),
(r'^(?P<num>\d+)/agenda/by-type$', views.agenda_by_type),
(r'^(?P<num>\d+)/agenda/by-type/(?P<type>[a-z]+)$', views.agenda_by_type),
(r'^(?P<num>\d+)/agenda/by-type/(?P<type>[a-z]+)/ics$', views.agenda_by_type_ics),
(r'^(?P<num>\d+)/agendas/edit$', views.edit_agendas),
(r'^(?P<num>\d+)/timeslots/edit$', views.edit_timeslots),
(r'^(?P<num>\d+)/rooms$', ajax.timeslot_roomsurl),

View file

@ -6,6 +6,7 @@ import re
import tarfile
import urllib
from tempfile import mkstemp
from collections import OrderedDict
import debug # pyflakes:ignore
@ -258,8 +259,7 @@ def edit_agenda(request, num=None, owner=None, name=None):
meeting_base_url = request.build_absolute_uri(meeting.base_url())
site_base_url = request.build_absolute_uri('/')[:-1] # skip the trailing slash
rooms = meeting.room_set.order_by("capacity")
rooms = rooms.all()
rooms = meeting.room_set.filter(session_types__slug='session').distinct().order_by("capacity")
saveas = SaveAsForm()
saveasurl=reverse(edit_agenda,
args=[meeting.number, schedule.owner_email(), schedule.name])
@ -367,6 +367,7 @@ def edit_agendas(request, num=None, order=None):
def agenda(request, num=None, name=None, base=None, ext=None):
base = base if base else 'agenda'
ext = ext if ext else '.html'
# This is misleading - urls.py doesn't send ics through here anymore
mimetype = {
".html":"text/html; charset=%s"%settings.DEFAULT_CHARSET,
".txt": "text/plain; charset=%s"%settings.DEFAULT_CHARSET,
@ -380,7 +381,39 @@ def agenda(request, num=None, name=None, base=None, ext=None):
return render(request, "meeting/no-"+base+ext, {'meeting':meeting }, content_type=mimetype[ext])
updated = meeting_updated(meeting)
return render(request, "meeting/"+base+ext, {"schedule":schedule, "updated": updated}, content_type=mimetype[ext])
filtered_assignments = schedule.assignments.exclude(timeslot__type__in=['lead','offagenda'])
return render(request, "meeting/"+base+ext, {"schedule":schedule, "filtered_assignments":filtered_assignments, "updated": updated}, content_type=mimetype[ext])
@role_required('Area Director','Secretariat','IAB')
def agenda_by_room(request,num=None):
meeting = get_meeting(num)
schedule = get_schedule(meeting)
ss_by_day = OrderedDict()
for day in schedule.scheduledsession_set.dates('timeslot__time','day'):
ss_by_day[day]=[]
for ss in schedule.scheduledsession_set.order_by('timeslot__location__functional_name','timeslot__location__name','timeslot__time'):
day = ss.timeslot.time.date()
ss_by_day[day].append(ss)
return render(request,"meeting/agenda_by_room.html",{"meeting":meeting,"ss_by_day":ss_by_day})
@role_required('Area Director','Secretariat','IAB')
def agenda_by_type(request,num=None,type=None):
meeting = get_meeting(num)
schedule = get_schedule(meeting)
scheduledsessions = schedule.scheduledsession_set.order_by('session__type__slug','timeslot__time')
if type:
scheduledsessions = scheduledsessions.filter(session__type__slug=type)
return render(request,"meeting/agenda_by_type.html",{"meeting":meeting,"scheduledsessions":scheduledsessions})
@role_required('Area Director','Secretariat','IAB')
def agenda_by_type_ics(request,num=None,type=None):
meeting = get_meeting(num)
schedule = get_schedule(meeting)
scheduledsessions = schedule.scheduledsession_set.order_by('session__type__slug','timeslot__time')
if type:
scheduledsessions = scheduledsessions.filter(session__type__slug=type)
updated = meeting_updated(meeting)
return render(request,"meeting/agenda.ics",{"schedule":schedule,"updated":updated,"assignments":scheduledsessions},content_type="text/calendar")
def read_agenda_file(num, doc):
# XXXX FIXME: the path fragment in the code below should be moved to
@ -611,7 +644,7 @@ def ical_agenda(request, num=None, name=None, ext=None):
elif item[0] == '~':
include_types |= set([item[1:]])
assignments = schedule.assignments.filter(
assignments = schedule.assignments.exclude(timeslot__type__in=['lead','offagenda']).filter(
Q(timeslot__type__slug__in = include_types) |
Q(session__group__acronym__in = include) |
Q(session__group__parent__acronym__in = include)
@ -626,7 +659,7 @@ def ical_agenda(request, num=None, name=None, ext=None):
def meeting_requests(request, num=None) :
meeting = get_meeting(num)
sessions = Session.objects.filter(meeting__number=meeting.number,group__parent__isnull = False).exclude(requested_by=0).order_by("group__parent__acronym","status__slug","group__acronym")
sessions = Session.objects.filter(meeting__number=meeting.number, type__slug='session', group__parent__isnull = False).exclude(requested_by=0).order_by("group__parent__acronym","status__slug","group__acronym")
groups_not_meeting = Group.objects.filter(state='Active',type__in=['WG','RG','BOF']).exclude(acronym__in = [session.group.acronym for session in sessions]).order_by("parent__acronym","acronym")
@ -637,7 +670,7 @@ def meeting_requests(request, num=None) :
def session_details(request, num, acronym, date=None, week_day=None, seq=None) :
meeting = get_meeting(num)
sessions = Session.objects.filter(meeting=meeting,group__acronym=acronym)
sessions = Session.objects.filter(meeting=meeting,group__acronym=acronym,type__in=['session','plenary','other'])
if not sessions:
sessions = Session.objects.filter(meeting=meeting,short=acronym)
@ -684,11 +717,14 @@ def session_details(request, num, acronym, date=None, week_day=None, seq=None) :
ss = session.scheduledsession_set.filter(schedule=meeting.agenda).order_by('timeslot__time')
if ss:
scheduled_time = ','.join([x.timeslot.time.strftime("%A %b-%d %H%M") for x in ss])
# TODO FIXME Deleted materials shouldn't be in the sessionpresentation_set
filtered_sessionpresentation_set = [p for p in session.sessionpresentation_set.all() if p.document.get_state_slug(p.document.type_id)!='deleted']
return render(request, "meeting/session_details.html",
{ 'session':sessions[0] ,
'meeting' :meeting ,
'acronym' :acronym,
'time': scheduled_time,
'filtered_sessionpresentation_set': filtered_sessionpresentation_set
})
else:
return render(request, "meeting/session_list.html",

View file

@ -1414,7 +1414,7 @@
"order": 0,
"used": true,
"name": "None Selected",
"desc": ""
"desc": "[None selected]"
},
"model": "name.iprlicensetypename",
"pk": "none-selected"
@ -2079,6 +2079,26 @@
"model": "name.timeslottypename",
"pk": "reserved"
},
{
"fields": {
"order": 0,
"used": true,
"name": "Leadership",
"desc": "Leadership Meetings"
},
"model": "name.timeslottypename",
"pk": "lead"
},
{
"fields": {
"order": 0,
"used": true,
"name": "Off Agenda",
"desc": "Other Meetings Not Published on Agenda"
},
"model": "name.timeslottypename",
"pk": "offagenda"
},
{
"fields": {
"label": "State"

View file

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def make_new_slot_types(apps, schema_editor):
TimeSlotTypeName = apps.get_model("name","TimeSlotTypeName")
TimeSlotTypeName.objects.create(slug='lead',name='Leadership',desc='Leadership Meetings',used=True)
TimeSlotTypeName.objects.create(slug='offagenda',name='Off Agenda',desc='Other Meetings Not Published on Agenda',used=True)
class Migration(migrations.Migration):
dependencies = [
('name', '0003_fix_ipr_none_selected_choice'),
]
operations = [
migrations.RunPython(make_new_slot_types)
]

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('nomcom', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='nomcom',
name='reminder_interval',
field=models.PositiveIntegerField(help_text=b'If the nomcom user sets the interval field then a cron command will send reminders to the nominees who have not responded using the following formula: (today - nomination_date) % interval == 0.', null=True, blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='nomcom',
name='send_questionnaire',
field=models.BooleanField(default=False, help_text=b'If you check this box, questionnaires are sent automatically after nominations.', verbose_name=b'Send questionnaires automatically'),
preserve_default=True,
),
]

View file

@ -38,9 +38,9 @@ class NomCom(models.Model):
group = models.ForeignKey(Group)
send_questionnaire = models.BooleanField(verbose_name='Send questionnaires automatically', default=False,
help_text='If you check this box, questionnaires are sent automatically after nominations.')
reminder_interval = models.PositiveIntegerField(help_text='If the nomcom user sets the interval field then a cron command will \
send reminders to the nominees who have not responded using \
the following formula: (today - nomination_date) % interval == 0.',
reminder_interval = models.PositiveIntegerField(help_text='If the nomcom user sets the interval field then a cron command will '
'send reminders to the nominees who have not responded using '
'the following formula: (today - nomination_date) % interval == 0.',
blank=True, null=True)
initial_text = models.TextField(verbose_name='Help text for nomination form',
blank=True)

View file

@ -180,6 +180,7 @@ class TimeSlotForm(forms.Form):
class NonSessionForm(TimeSlotForm):
short = forms.CharField(max_length=32,label='Short Name',help_text='Enter an abbreviated session name (used for material file names)',required=False)
type = forms.ModelChoiceField(queryset=TimeSlotTypeName.objects.filter(slug__in=('other','reg','break','plenary')),empty_label=None)
type = forms.ModelChoiceField(queryset=TimeSlotTypeName.objects.filter(used=True).exclude(slug__in=('session',)),empty_label=None)
group = forms.ModelChoiceField(queryset=Group.objects.filter(acronym__in=('edu','ietf','iepg','tools','iesg','iab','iaoc')),help_text='Required for Session types: other, plenary',required=False)
show_location = forms.BooleanField(required=False)

View file

@ -147,21 +147,21 @@ class MainTestCase(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
q = PyQuery(response.content)
self.assertEqual(len(q("#id_rooms_table tr")),2)
self.assertEqual(len(q("#id_rooms_table tr input[type='checkbox']")),meeting.room_set.count())
# test delete
# first unschedule sessions so we can delete
ScheduledSession.objects.filter(schedule=meeting.agenda).delete()
self.client.login(username="secretary", password="secretary+password")
response = self.client.post(url, {
post_dict = {
'room-TOTAL_FORMS': q('input[name="room-TOTAL_FORMS"]').val(),
'room-INITIAL_FORMS': q('input[name="room-INITIAL_FORMS"]').val(),
'room-0-meeting': q('input[name="room-0-meeting"]').val(),
'room-0-id': q('input[name="room-0-id"]').val(),
'room-0-name': q('input[name="room-0-name"]').val(),
'room-0-capacity': q('input[name="room-0-capacity"]').val(),
'room-0-DELETE': 'on'
})
}
for i in range(meeting.room_set.count()):
for attr in ['meeting','id','name','capacity','DELETE']:
key = 'room-%d-%s' % (i,attr)
post_dict[key] = q('input[name="%s"]' % key).val()
response = self.client.post(url, post_dict)
self.assertEqual(response.status_code, 302)
self.assertEqual(Room.objects.filter(meeting=meeting).count(),0)
@ -176,6 +176,7 @@ class MainTestCase(TestCase):
meeting = make_meeting_test_data()
qs = TimeSlot.objects.filter(meeting=meeting,type='session')
before = qs.count()
expected_deletion_count = qs.filter(time=qs.first().time).count()
url = reverse('meetings_times_delete',kwargs={
'meeting_id':42,
'schedule_name':'test-agenda',
@ -185,7 +186,7 @@ class MainTestCase(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 302)
after = TimeSlot.objects.filter(meeting=meeting,type='session').count()
self.assertEqual(after,before - (Room.objects.filter(meeting=meeting).count()))
self.assertEqual(after,before - expected_deletion_count)
def test_meetings_times_edit(self):
meeting = make_meeting_test_data()

View file

@ -53,10 +53,15 @@ def build_timeslots(meeting,room=None):
or adding a room.
'''
slots = meeting.timeslot_set.filter(type='session')
# Don't do anything if the room is not capable of handling sessions
if room and not room.session_types.filter(slug='session'):
return
if room:
rooms = [room]
else:
rooms = meeting.room_set.all()
rooms = meeting.room_set.filter(session_types__slug='session')
if not slots or room:
# if we are just building timeslots for a new room, the room argument was passed,
# then we need to use current meeting times as a template, not the last meeting times
@ -95,7 +100,7 @@ def build_nonsession(meeting,schedule):
system = Person.objects.get(name='(system)')
secretariat = Group.objects.get(acronym='secretariat')
for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary')):
for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary','lead')):
new_time = slot.time + delta
session = None
# create Session object for Tutorials to hold materials
@ -105,13 +110,17 @@ def build_nonsession(meeting,schedule):
short=get_session(slot).short,
group=get_session(slot).group,
requested_by=system,
status_id='sched')
status_id='sched',
type=slot.type,
)
else:
session, __ = Session.objects.get_or_create(meeting=meeting,
name=slot.name,
group=secretariat,
requested_by=system,
status_id='sched')
status_id='sched',
type=slot.type,
)
session.save()
ts = TimeSlot.objects.create(type=slot.type,
@ -128,15 +137,17 @@ def check_nonsession(meeting,schedule):
Ensure non-session timeslots exist and have appropriate ScheduledSession objects
for the specified schedule.
'''
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary'))
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary','lead','offagenda'))
if not slots:
build_nonsession(meeting,schedule)
return None
scheduledsessions = slots.filter(type='plenary').first().scheduledsession_set.all()
if not scheduledsessions.filter(schedule=schedule):
source = scheduledsessions.first().schedule
copy_scheduledsessions(slots,source,schedule)
plenary = slots.filter(type='plenary').first()
if plenary:
scheduledsessions = plenary.scheduledsession_set.all()
if not scheduledsessions.filter(schedule=schedule):
source = scheduledsessions.first().schedule
copy_scheduledsessions(slots,source,schedule)
def copy_scheduledsessions(slots,source,target):
'''
@ -435,7 +446,7 @@ def non_session(request, meeting_id, schedule_name):
check_nonsession(meeting,schedule)
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary')).order_by('-type__name','time')
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary','lead')).order_by('-type__name','time')
if request.method == 'POST':
form = NonSessionForm(request.POST)
@ -458,7 +469,7 @@ def non_session(request, meeting_id, schedule_name):
duration=duration,
show_location=form.cleaned_data['show_location'])
if timeslot.type.slug not in ('other','plenary'):
if timeslot.type.slug not in ('other','plenary','lead'):
group = Group.objects.get(acronym='secretariat')
# create associated Session object
@ -467,7 +478,9 @@ def non_session(request, meeting_id, schedule_name):
short=short,
group=group,
requested_by=Person.objects.get(name='(system)'),
status_id='sched')
status_id='sched',
type=type,
)
session.save()
# create association
@ -501,7 +514,7 @@ def non_session_delete(request, meeting_id, schedule_name, slot_id):
meeting = get_object_or_404(Meeting, number=meeting_id)
# schedule = get_object_or_404(Schedule, meeting=meeting, name=schedule_name)
slot = get_object_or_404(TimeSlot, id=slot_id)
if slot.type_id in ('other','plenary'):
if slot.type_id in ('other','plenary','lead'):
scheduledsessions = slot.scheduledsession_set.filter(schedule__meeting=meeting)
session_objects = [ x.session for x in scheduledsessions ]
for session in session_objects:

View file

@ -75,7 +75,7 @@ class BluesheetTestCase(TestCase):
make_test_data()
meeting = Meeting.objects.filter(type='interim').first()
group = Group.objects.get(acronym='mars')
Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched')
Session.objects.create(meeting=meeting,group=group,requested_by_id=1,status_id='sched',type_id='session')
url = reverse('proceedings_upload_unified', kwargs={'meeting_num':meeting.number,'acronym':'mars'})
upfile = StringIO('dummy file')
upfile.name = "scan1.pdf"

View file

@ -438,7 +438,9 @@ def interim(request, acronym):
Session.objects.create(meeting=meeting,
group=group,
requested_by=request.user.person,
status_id='sched')
status_id='sched',
type_id='session',
)
create_interim_directory()
make_directories(meeting)

View file

@ -270,7 +270,9 @@ def confirm(request, acronym):
requested_by=login,
requested_duration=datetime.timedelta(0,int(duration)),
comments=form['comments'],
status=SessionStatusName.objects.get(slug=slug))
status=SessionStatusName.objects.get(slug=slug),
type_id='session',
)
session_save(new_session)
if 'resources' in form:
new_session.resources = form['resources']
@ -383,7 +385,9 @@ def edit_mtg(request, num, acronym):
requested_by=login,
requested_duration=duration,
comments=form.cleaned_data['comments'],
status=SessionStatusName.objects.get(slug='schedw'))
status=SessionStatusName.objects.get(slug='schedw'),
type_id='session',
)
new_session.save()
else:
duration = datetime.timedelta(0,int(form.cleaned_data['length_session2']))
@ -405,7 +409,9 @@ def edit_mtg(request, num, acronym):
requested_by=login,
requested_duration=duration,
comments=form.cleaned_data['comments'],
status=SessionStatusName.objects.get(slug='apprw'))
status=SessionStatusName.objects.get(slug='apprw'),
type_id='session',
)
new_session.save()
else:
duration = datetime.timedelta(0,int(form.cleaned_data['length_session3']))

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('submit', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='submission',
name='authors',
field=models.TextField(help_text=b'List of author names and emails, one author per line, e.g. "John Doe &lt;john@example.org&gt;".', blank=True),
preserve_default=True,
),
migrations.AlterField(
model_name='submission',
name='submitter',
field=models.CharField(help_text=b'Name and email of submitter, e.g. "John Doe &lt;john@example.org&gt;".', max_length=255, blank=True),
preserve_default=True,
),
]

View file

@ -1,7 +1,7 @@
{% load humanize %}{% autoescape off %}{% load ietf_filters %}"Date","Start","End","Session","Room","Area","Acronym","Type","Description","Session ID","Agenda","Slides"
{% for item in schedule.assignments.all.distinct %}{% if item.timeslot.type.slug == "break" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","Break","{{ schedule.meeting.break_area}}","","","","{{ item.timeslot.name }}","b{{ item.timeslot.pk }}","",""
{% for item in filtered_assignments.all.distinct %}{% if item.timeslot.type.slug == "break" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","Break","{{ schedule.meeting.break_area}}","","","","{{ item.timeslot.name }}","b{{ item.timeslot.pk }}","",""
{% endif %}{% if item.timeslot.type.slug == "reg" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.type.name }}","{{ schedule.meeting.reg_area }}","","","","{{ item.timeslot.name }}","r{{item.timeslot.pk}}","",""
{% endif %}{% if item.timeslot.type.slug == "other" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","None","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","{% if item.session.group.parent %}{{item.session.group.parent.acronym|upper}}{% endif %}","{{ item.session.name }}","{{item.session.pk}}","",""
{% endif %}{% if item.timeslot.type.slug == "plenary" %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.session.name }}","{{ item.timeslot.location.name }}","","{{ item.session.group.acronym }}","","{{ item.session.name }}","{{item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}"
{% endif %}{% if item.timeslot.type.slug == "session" and item.session.group %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.name }}","{{ item.timeslot.location.name }}","{{ item.session.group.parent.acronym|upper }}","{{ item.session.group.acronym }}","{{ item.session.type }}","{{ item.session.group.name }}","{{ item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}"
{% endif %}{% if item.timeslot.type.slug == "session" and item.session.group %}"{{ item.timeslot.time|date:"Y-m-d" }}","{{ item.timeslot.time_desc|slice:":4" }}","{{ item.timeslot.time_desc|slice:"5:9" }}","{{ item.timeslot.name }}","{{ item.timeslot.location.name }}","{{ item.session.group.parent.acronym|upper }}","{{ item.session.group.acronym }}","{{ item.session.lame_description }}","{{ item.session.group.name }}","{{ item.session.pk}}","{% if item.session.agenda %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/agenda/{{ item.session.agenda.external_url }}{% endif %}","{% if item.session.slides %}{% for slide in item.session.slides %}http://www.ietf.org/proceedings/{{ schedule.meeting.number }}/slides/{{ slide.external_url }}{% if not forloop.last %}|{% endif %}{% endfor %}{% endif %}"
{% endif %}{% endfor %}{% endautoescape %}
Can't render this file because it contains an unexpected character in line 1 and column 63.

View file

@ -146,7 +146,7 @@
<iframe seamless class="hidden" id="weekview"></iframe>
<table class="table table-condensed table-striped">
{% for item in schedule.assignments.all %}
{% for item in filtered_assignments.all %}
{% ifchanged item.timeslot.time|date:"Y-m-d" %}
<tr><th class="gap" colspan="6"></th></tr>
@ -335,7 +335,7 @@
</div>
<div class="col-md-2 hidden-print bs-docs-sidebar" id="affix">
<ul class="nav nav-pills nav-stacked small" data-spy="affix">
{% for item in schedule.assignments.all %}
{% for item in filtered_assignments.all %}
{% ifchanged item.timeslot.time|date:"Y-m-d" %}
<li><a href="#{{item.timeslot.time|slugify}}">{{ item.timeslot.time|date:"l, F j, Y" }}</a></li>
{% endifchanged %}

View file

@ -8,7 +8,7 @@
{% filter center:72 %}Updated {{ updated|date:"Y-m-d H:i:s T" }}{% endfilter %}
{% filter center:72 %}IETF agendas are subject to change, up to and during the meeting.{% endfilter %}
{% for item in schedule.assignments.all.distinct %}{% ifchanged %}
{% for item in filtered_assignments.all.distinct %}{% ifchanged %}
{{ item.timeslot.time|date:"l"|upper }}, {{ item.timeslot.time|date:"F j, Y" }}
@ -20,7 +20,7 @@
{% endif %}{% if item.timeslot.type.slug == "session" %}{% if item.session.group %}{% ifchanged %}
{{ item.timeslot.time_desc }} {{ item.timeslot.name }}
{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.group.parent.acronym|upper|ljust:4 }} {{ item.session.group.acronym|ljust:10 }} {{ item.session.group.name }} {{ item.session.type }}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %}
{% endifchanged %}{{ item.timeslot.location.name|ljust:14 }} {{ item.session.group.parent.acronym|upper|ljust:4 }} {{ item.session.group.acronym|ljust:10 }} {{ item.session.group.name }} {{ item.session.lame_description }}{% if item.session.agenda_note %} - {{ item.session.agenda_note }}{% endif %}
{% endif %}{% endif %}{% if item.timeslot.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.timeslot.type.slug == "other" %}
{{ item.timeslot.time_desc }} {{ item.timeslot.name }} - {{ item.timeslot.location.name }}{% endif %}{% endfor %}

View file

@ -0,0 +1,40 @@
{% extends "base.html" %}
{% block morecss %}
ul.daylist { list-style:none; padding-left:0; }
li.daylistentry { font-size:162%; font-weight:700; }
li.even { background-color:#EDF5FF; }
li.odd { background-color:white; }
ul.roomlist {list-style:none; padding-left:0; margin-bottom:20px;}
li.roomlistentry { font-weight: 400; }
ul.sessionlist { list-style:none; padding-left:2em; margin-bottom:10px;}
li.sessionlistentry { font-size:62%; }
.type-lead:after { content: " (DO NOT POST)"; color:red; }
.type-offagenda:after { content:" (not published on agenda)"; }
{% endblock %}
{% block title %}Agenda for {{meeting}} by Room{% endblock %}
{% block content %}
<h1>Agenda for {{meeting}} by Room</h1>
<ul class="daylist">
{% for day,sessions in ss_by_day.items %}
<li class="daylistentry {% cycle 'even' 'odd' %}">{{day|date:'l, j F Y'}}
{% regroup sessions by timeslot.get_functional_location as room_list %}
<ul class="roomlist">
{% for room in room_list %}
<li class="roomlistentry">{{room.grouper|default:"Location Unavailable"}}
<ul class="sessionlist">
{% for ss in room.list %}
<li class="sessionlistentry type-{{ss.timeslot.type.slug}}">{{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}} {{ss.session.short_name}}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -0,0 +1,54 @@
{% extends "base.html" %}
{% block morecss %}
ul.typelist { list-style:none; padding-left:0; }
li.typelistentry { font-size:162%; font-weight:700; }
li.even { background-color:#EDF5FF; }
li.odd { background-color:white; }
ul.daylist {list-style:none; padding-left:0; margin-bottom:20px;}
li.daylistentry { margin-left:2em; font-weight: 400; }
.sessiontable {margin-left:2em; font-size:62%;}
.sessiontable td {padding-right: 1em;}
.typelabel { font-size:162%; font-weight:700; }
.daylabel { font-size:162%; font-weight:400; }
.even { background-color:#EDF5FF; }
.odd { background-color:white; }
{% comment %}li.sessionlistentry { font-size:62%; }{% endcomment %}
.type-lead:after { content: " (DO NOT POST)"; color:red; }
.type-offagenda:after { content:" (not published on agenda)"; }
{% endblock %}
{% block title %}Agenda for {{meeting}} by Session Type{% endblock %}
{% block content %}
<h1>Agenda for {{meeting}} by Session Type</h1>
{% regroup scheduledsessions by session.type.slug as type_list %}
<ul class="typelist">
{% for type in type_list %}
<li class="typelistentry {% cycle 'even' 'odd' %}">
{{type.grouper}} <a id="ical-link" class="btn btn-primary" href="{% url "ietf.meeting.views.agenda_by_type_ics" num=meeting.number type=type.grouper %}">Download to Calendar</a>
<ul class="daylist">
{% regroup type.list by timeslot.time|date:"l Y-M-d" as daylist %}
{% for day in daylist %}
<li class="daylistentry">
{{ day.grouper }}
<table class="sessiontable">
{% for ss in day.list %}
<tr>
<td>{{ss.timeslot.time|date:"H:i"}}-{{ss.timeslot.end_time|date:"H:i"}}</td>
<td>{{ss.timeslot.get_hidden_location}}</td>
<td class="type-{{ss.session.type.slug}}">{{ss.session.short_name}}</td>
</tr>
{% endfor %}
</table>
</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
{% endblock %}

View file

@ -110,6 +110,8 @@ promiselist.push(ss_promise);
<p>Please save this agenda to your account first.</p>
</div>
<div class="content"> {% comment %} For preserving styling across the facelift {% endcomment %}
<div class="wrapper custom_text_stuff">
@ -206,10 +208,11 @@ promiselist.push(ss_promise);
</div>
<table id="meetings" class="ietf-navbar" style="width:100%">
{%comment%}<table id="meetings" class="ietf-navbar" style="width:100%">{%endcomment%}
<table id="meetings" class="ietf-navbar" >
<tr>
<th class="schedule_title"><div id="pageloaded" style="display:none">loaded</div><div id="spinner"><!-- spinney goes here --></div></th>
<th></th>
{% comment %}<th></th>{% endcomment %}
{% for day in time_slices %}
<th colspan="{{date_slices|colWidth:day}}" id="{{day|date:'Y-m-d'}}-btn" class=" day_{{day}} agenda_slot_title agenda_slot_unavailable">
<div id="close_{{day|date:'Y-m-d'}}" class="close top_left very_small close_day">x</div>
@ -226,7 +229,7 @@ promiselist.push(ss_promise);
<tr>
<th class="th_column"><button id="show_all_button" class="styled_button">show all</button></th>
<th><!-- resources --></th>
{% comment %}<th><!-- resources --></th>{% endcomment %}
{% for day in time_slices %}
{% for slot in date_slices|lookup:day %}
<th class="day_{{day}}-{{slot.0|date:'Hi'}} day_{{day}} room_title ">{{slot.0|date:'Hi'}}-{{slot.1|date:'Hi'}} </th>
@ -246,6 +249,7 @@ promiselist.push(ss_promise);
<div class="close very_small close_room top_left small_button" id="close_{{r.name|to_acceptable_id}}">X</div>
<div class="right room_name">{{r.name}} <span class="capacity">({{r.capacity}})</span></div>
</th>
{% comment 'The secretariat is not using these features' %}
<th class="room_features">
<div class="resource_list">
{% for resource in r.resources.all %}
@ -255,6 +259,7 @@ promiselist.push(ss_promise);
{% endfor %}
</div>
</th>
{% endcomment %}
{% for day in time_slices %}
{% for slot in date_slices|lookup:day %}
<td id="{{r.dom_id}}_{{day}}_{{slot.0|date:'Hi'}}" class="day_{{day}} agenda-column-{{day}}-{{slot.0|date:'Hi'}} agenda_slot agenda_slot_unavailable" capacity="{{r.capacity}}" ></td>
@ -372,4 +377,6 @@ promiselist.push(ss_promise);
</div>
</div> {% comment %} End of .content div {% endcomment %}
{% endblock %}

View file

@ -12,11 +12,11 @@
<h2>{{ session.name }}</h2>
{% endif %}
{% if session.sessionpresentation_set.all.count %}
{% if filtered_sessionpresentation_set %}
<p>Materials:</p>
<ul>
{% for pres in session.sessionpresentation_set.all %}
{% for pres in filtered_sessionpresentation_set %}
<li><a href="{% url 'doc_view' name=pres.document.name rev=pres.rev%}">{{ pres.document.name }}-{{ pres.rev }}</a></li>
{% endfor %}
</ul>

View file

@ -18,6 +18,8 @@
.content table { border-collapse: separate; border-spacing: 2px; }
.container-fluid {padding-right: 0; padding-left:0;}
.ietf-navbar { background-color: #edf5ff; padding:0; border: 1px solid #89d; margin-top:4px; width: 130px; }
.ietf-navbar ul { padding: 0; margin: 0; }
.ietf-navbar ul li { list-style: none; padding: 0; margin: 0; font-size: 93%; padding: 2px 0px 2px 0px; }
@ -69,6 +71,7 @@
background-color:#2647A0;
width:100px; /* otherwise we get overlap */
min-width:100px;
min-height:40px;
font-size:12px;
position:absolute; /* makes it float independent of scroll */
z-index:100; /* meeting events will be on top otherwise */
@ -242,7 +245,7 @@ tr.agenda_slot{
td.agenda_slot{
/* overflow-y:auto; */
/* height:20px; */
height: 40px;
height: 45px;
/* min-height:20px; */
}

View file

@ -1172,6 +1172,10 @@ Session.prototype.event_template = function() {
}
//console.log("acronym", groupacronym, this.group.acronym, this.visible_title());
var durationstring="";
if (this.requested_duration!="0.0") {
durationstring = " ("+this.requested_duration+")"
}
// see comment in ietf.ccs, and
// http://stackoverflow.com/questions/5148041/does-firefox-support-position-relative-on-table-elements
return "<div class='meeting_box_container' session_id=\""+this.session_id+"\"><div class=\"meeting_box "+bucket_list_style+"\" ><table class='meeting_event "+
@ -1183,7 +1187,7 @@ Session.prototype.event_template = function() {
this.wg_scheme()+" "+
this.area_scheme() +" meeting_obj'>"+
this.visible_title()+
"<span> ("+this.requested_duration+")</span>" +
"<span>" + durationstring + "</span>" +
"</th><td class=\"ourconflicts\"></td>"+pinned+"</tr></table>"+ area_mark +"</div></div>";
};