Revert to pre-agenda tool db schema. Change sec static files subdirectory to 'secretariat'. Branch ready for merge.

- Legacy-Id: 6148
This commit is contained in:
Ryan Cross 2013-09-12 16:58:44 +00:00
parent 54ca99c1bf
commit 4f98ac157c
6 changed files with 127 additions and 170 deletions

View file

@ -90,7 +90,7 @@ class TimeChoiceField(forms.ChoiceField):
class MeetingModelForm(forms.ModelForm):
class Meta:
model = Meeting
exclude = ('type','agenda')
exclude = ('type')
def clean_number(self):
number = self.cleaned_data['number']

View file

@ -12,7 +12,7 @@ from django.utils.functional import curry
from django.utils import simplejson
from ietf.utils.mail import send_mail
from ietf.meeting.models import Meeting, Session, Room, TimeSlot, Schedule, ScheduledSession
from ietf.meeting.models import Meeting, Session, Room, TimeSlot
from ietf.group.models import Group
from ietf.name.models import SessionStatusName, TimeSlotTypeName
from ietf.person.models import Person
@ -21,48 +21,24 @@ from ietf.secr.proceedings.views import build_choices, handle_upload_file
from ietf.secr.sreq.forms import GroupSelectForm
from ietf.secr.sreq.views import get_initial_session, session_conflicts_as_string
from ietf.secr.utils.mail import get_cc_list
from ietf.secr.utils.meeting import get_upload_root, get_session, get_timeslot
from ietf.secr.utils.meeting import get_upload_root
from forms import *
import os
import datetime
# prep for agenda changes
# --------------------------------------------------
# Helper Functions
# --------------------------------------------------
def assign(session,timeslot,meeting):
'''
Robust function to assign a session to a timeslot
'''
qs = timeslot.scheduledsession_set.filter(schedule=meeting.agenda)
# this should never happen, but just in case
if not qs:
ScheduledSession.objects.create(schedule=meeting.agenda,
session=session,
timeslot=timeslot)
else:
# find the first unassigned scheduled session or create a new one
for ss in qs:
if not ss.session:
ss.session = session
ss.save()
break
else:
ScheduledSession.objects.create(schedule=meeting.agenda,
session=session,
timeslot=timeslot)
session.status_id = 'sched'
session.save()
def build_timeslots(request,meeting,room=None):
def build_timeslots(meeting,room=None):
'''
This function takes a Meeting object and an optional room argument. If room isn't passed we
pre-create the full set of timeslot records using the last meeting as a template.
If room is passed pre-create timeslots for the new room. Call this after saving new rooms
or adding a room.
'''
schedule = get_schedule(request,meeting)
slots = meeting.timeslot_set.filter(type='session')
if room:
rooms = [room]
@ -87,15 +63,14 @@ def build_timeslots(request,meeting,room=None):
for t in timeslots:
new_time = t.time + delta
for room in rooms:
ts = TimeSlot.objects.create(type_id='session',
TimeSlot.objects.create(type_id='session',
meeting=meeting,
name=t.name,
time=new_time,
location=room,
duration=t.duration)
ScheduledSession.objects.create(schedule=schedule,timeslot=ts)
def build_nonsession(request, meeting):
def build_nonsession(meeting):
'''
This function takes a meeting object and creates non-session records
for a new meeting, based on the last meeting
@ -103,8 +78,6 @@ def build_nonsession(request, meeting):
last_meeting = get_last_meeting(meeting)
delta = meeting.date - last_meeting.date
system = Person.objects.get(name='(system)')
schedule = get_schedule(request, meeting)
for slot in TimeSlot.objects.filter(meeting=last_meeting,type__in=('break','reg','other','plenary')):
new_time = slot.time + delta
session = None
@ -112,48 +85,29 @@ def build_nonsession(request, meeting):
if slot.type.slug in ('other','plenary'):
session = Session(meeting=meeting,
name=slot.name,
short=get_session(slot).short,
group=get_session(slot).group,
short=slot.session.short,
group=slot.session.group,
requested_by=system,
status_id='sched')
session.save()
ts = TimeSlot.objects.create(type=slot.type,
TimeSlot.objects.create(type=slot.type,
meeting=meeting,
session=session,
name=slot.name,
time=new_time,
duration=slot.duration,
show_location=slot.show_location)
ScheduledSession.create(schedule=schedule,session=session,timeslot=ts)
def get_last_meeting(meeting):
last_number = int(meeting.number) - 1
return Meeting.objects.get(number=last_number)
def get_schedule(request,meeting):
'''
This function takes a Request object and Meeting object and returns the Official
Schdeule for the meeting. It will create the Schedule if it doesn't already
exist. Call this function after creating a new meeting.
'''
schedule = meeting.agenda
if schedule is None:
name = "mtg:%s" % meeting.number
person = request.user.get_profile()
schedule, created = Schedule.objects.get_or_create(meeting=meeting,
name=name,
defaults={'owner':person,
'visible':True,
'public':True})
meeting.agenda = schedule
meeting.save()
return schedule
def is_combined(session, meeting):
def is_combined(session):
'''
Check to see if this session is using two combined timeslots
'''
if session.scheduledsession_set.filter(schedule=meeting.agenda).count() > 1:
if session.timeslot_set.count() > 1:
return True
else:
return False
@ -172,8 +126,7 @@ def make_directories(meeting):
def send_notification(request, sessions):
'''
This view generates notifications for schedule sessions. It takes an HttpRequest object and
a query set, sessions, consisting of one or more sessions scheduled for a particular group.
This view generates notifications for schedule sessions
'''
session_info_template = '''{0} Session {1} ({2})
{3}, {4} {5}
@ -193,7 +146,7 @@ def send_notification(request, sessions):
# easier to populate template from timeslot perspective. assuming one-to-one timeslot-session
count = 0
session_info = ''
data = [ (s,get_timeslot(s)) for s in sessions ]
data = [ (s,s.timeslot_set.all()[0]) for s in sessions ]
for s,t in data:
count += 1
session_info += session_info_template.format(group.acronym,
@ -222,16 +175,18 @@ def send_notification(request, sessions):
def sort_groups(meeting):
'''
Similar to sreq.views.sort_groups
Takes a Meeting object and returns a tuple scheduled_groups, unscheduled groups.
Takes a Django User object and a Meeting object
Returns a tuple scheduled_groups, unscheduled groups.
'''
scheduled_groups = []
unscheduled_groups = []
#sessions = Session.objects.filter(meeting=meeting,status__in=('schedw','apprw','appr','sched','notmeet','canceled'))
sessions = Session.objects.filter(meeting=meeting,status__in=('schedw','apprw','appr','sched','canceled'))
groups_with_sessions = [ s.group for s in sessions if s.group.type.slug in ('wg','rg','ag') ]
groups_with_sessions = [ s.group for s in sessions ]
gset = set(groups_with_sessions)
sorted_groups_with_sessions = sorted(gset, key = lambda instance: instance.acronym)
scheduled_sessions = ScheduledSession.objects.filter(schedule=meeting.agenda,session__isnull=False)
groups_with_timeslots = [ x.session.group for x in scheduled_sessions ]
slots = TimeSlot.objects.filter(meeting=meeting,session__isnull=False)
groups_with_timeslots = [ s.session.group for s in slots ]
for group in sorted_groups_with_sessions:
if group in groups_with_timeslots:
scheduled_groups.append(group)
@ -283,9 +238,6 @@ def add(request):
if form.is_valid():
meeting = form.save()
#Create initial Official schedule
get_schedule(request,meeting)
#Create Physical new meeting directory and subdirectories
make_directories(meeting)
@ -420,7 +372,7 @@ def non_session(request, meeting_id):
# if the Break/Registration records don't exist yet (new meeting) create them
if not TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other')):
build_nonsession(request, meeting)
build_nonsession(meeting)
slots = TimeSlot.objects.filter(meeting=meeting,type__in=('break','reg','other','plenary')).order_by('-type__name','time')
@ -437,14 +389,6 @@ def non_session(request, meeting_id):
t = meeting.date + datetime.timedelta(days=int(day))
new_time = datetime.datetime(t.year,t.month,t.day,time.hour,time.minute)
# create TimeSlot object
timeslot = TimeSlot.objects.create(type=form.cleaned_data['type'],
meeting=meeting,
name=name,
time=new_time,
duration=duration,
show_location=form.cleaned_data['show_location'])
# create a dummy Session object to hold materials
# NOTE: we're setting group to none here, but the set_room page will force user
# to pick a legitimate group
@ -458,10 +402,14 @@ def non_session(request, meeting_id):
status_id='sched')
session.save()
# create association
ScheduledSession.objects.create(timeslot=timeslot,
session=session,
schedule=meeting.agenda)
# create TimeSlot object
TimeSlot.objects.create(type=form.cleaned_data['type'],
meeting=meeting,
session=session,
name=name,
time=new_time,
duration=duration,
show_location=form.cleaned_data['show_location'])
messages.success(request, 'Non-Sessions updated successfully')
url = reverse('meetings_non_session', kwargs={'meeting_id':meeting_id})
@ -487,14 +435,13 @@ def non_session_delete(request, meeting_id, slot_id):
'''
slot = get_object_or_404(TimeSlot, id=slot_id)
if slot.type_id in ('other','plenary'):
session = get_session(slot)
if session and session.materials.exclude(states__slug='deleted'):
if slot.session.materials.exclude(states__slug='deleted'):
messages.error(request, 'Materials have already been uploaded for "%s". You must delete those before deleting the timeslot.' % slot.name)
url = reverse('meetings_non_session', kwargs={'meeting_id':meeting_id})
return HttpResponseRedirect(url)
else:
slot.sessions.all().delete()
slot.session.delete()
slot.delete()
messages.success(request, 'Non-Session timeslot deleted successfully')
@ -507,7 +454,6 @@ def non_session_edit(request, meeting_id, slot_id):
'''
meeting = get_object_or_404(Meeting, number=meeting_id)
slot = get_object_or_404(TimeSlot, id=slot_id)
session = get_session(slot)
if request.method == 'POST':
button_text = request.POST.get('submit', '')
@ -515,7 +461,7 @@ def non_session_edit(request, meeting_id, slot_id):
url = reverse('meetings_non_session', kwargs={'meeting_id':meeting_id})
return HttpResponseRedirect(url)
form = NonSessionEditForm(request.POST,meeting=meeting, session=session)
form = NonSessionEditForm(request.POST,meeting=meeting, session=slot.session)
if form.is_valid():
location = form.cleaned_data['location']
group = form.cleaned_data['group']
@ -525,6 +471,7 @@ def non_session_edit(request, meeting_id, slot_id):
slot.name = name
slot.save()
# save group to session object
session = slot.session
session.group = group
session.name = name
session.short = short
@ -538,10 +485,10 @@ def non_session_edit(request, meeting_id, slot_id):
# we need to pass the session to the form in order to disallow changing
# of group after materials have been uploaded
initial = {'location':slot.location,
'group':session.group,
'name':session.name,
'short':session.short}
form = NonSessionEditForm(meeting=meeting,session=session,initial=initial)
'group':slot.session.group,
'name':slot.session.name,
'short':slot.session.short}
form = NonSessionEditForm(meeting=meeting,session=slot.session,initial=initial)
return render_to_response('meetings/non_session_edit.html', {
'meeting': meeting,
@ -562,10 +509,10 @@ def remove_session(request, meeting_id, acronym):
now = datetime.datetime.now()
for session in sessions:
ss = session.official_scheduledsession()
ss.session = None
ss.modified = now
ss.save()
for timeslot in session.timeslot_set.all():
timeslot.session = None
timeslot.modified = now
timeslot.save()
session.status_id = 'canceled'
session.modified = now
session.save()
@ -597,14 +544,14 @@ def rooms(request, meeting_id):
# if we are creating rooms for the first time create full set of timeslots
if first_time:
build_timeslots(request, meeting)
build_timeslots(meeting)
# otherwise if we're modifying rooms
else:
# add timeslots for new rooms, deleting rooms automatically deletes timeslots
for form in formset.forms[formset.initial_form_count():]:
if form.instance.pk:
build_timeslots(request, meeting,room=form.instance)
build_timeslots(meeting,room=form.instance)
messages.success(request, 'Meeting Rooms changed successfully')
url = reverse('meetings_rooms', kwargs={'meeting_id':meeting_id})
@ -634,16 +581,14 @@ def schedule(request, meeting_id, acronym):
for s in sessions:
d = {'session':s.id,
'note':s.agenda_note}
timeslot = get_timeslot(s)
if timeslot:
d['room'] = timeslot.location.id
d['day'] = timeslot.time.isoweekday() % 7 + 1 # adjust to django week_day
d['time'] = timeslot.time.strftime('%H%M')
qs = s.timeslot_set.all()
if qs:
d['room'] = qs[0].location.id
d['day'] = qs[0].time.isoweekday() % 7 + 1 # adjust to django week_day
d['time'] = qs[0].time.strftime('%H%M')
else:
d['day'] = 2 # default
if is_combined(s,meeting):
d['day'] = 2
if is_combined(s):
d['combine'] = True
initial.append(d)
@ -673,39 +618,74 @@ def schedule(request, meeting_id, acronym):
day = form.cleaned_data['day']
combine = form.cleaned_data.get('combine',None)
session = Session.objects.get(id=id)
initial_timeslot = get_timeslot(session)
was_combined = is_combined(session)
initial_timeslots = session.timeslot_set.all()
if initial_timeslots:
initial_timeslot = initial_timeslots[0]
else:
initial_timeslot = None
# find new timeslot
new_day = meeting.date + datetime.timedelta(days=int(day)-1)
hour = datetime.time(int(time[:2]),int(time[2:]))
new_time = datetime.datetime.combine(new_day,hour)
timeslot = TimeSlot.objects.filter(meeting=meeting,time=new_time,location=room)[0]
qs = TimeSlot.objects.filter(meeting=meeting,time=new_time,location=room)
if qs.filter(session=None):
timeslot = qs.filter(session=None)[0]
else:
# we need to create another, identical timeslot
timeslot = TimeSlot.objects.create(meeting=qs[0].meeting,
type=qs[0].type,
name=qs[0].name,
time=qs[0].time,
duration=qs[0].duration,
location=qs[0].location,
show_location=qs[0].show_location,
modified=now)
messages.warning(request, 'WARNING: There are now two sessions scheduled for the timeslot: %s' % timeslot)
# COMBINE SECTION - BEFORE --------------
if 'combine' in form.changed_data and not combine:
next_slot = get_next_slot(initial_timeslot)
for ss in next_slot.scheduledsession_set.filter(schedule=meeting.agenda,session=session):
ss.session = None
ss.save()
next_slot.session = None
next_slot.modified = now
next_slot.save()
# ---------------------------------------
if any(x in form.changed_data for x in ('day','time','room')):
# clear the old association
if initial_timeslot:
# get SS record(s) and unschedule by removing the session reference
for ss in session.scheduledsession_set.filter(schedule=meeting.agenda):
ss.session = None
ss.save()
if any(x in form.changed_data for x in ('day','time','room')):
# clear the old timeslot(s)
for ts in initial_timeslots:
# if the initial timeslot is one of multiple we should delete it
tqs = TimeSlot.objects.filter(meeting=meeting,
type='session',
time=ts.time,
location=ts.location)
if tqs.count() > 1:
ts.delete()
else:
ts.session = None
ts.modified = now
ts.save()
# assign new timeslot(s)
new_slots = []
if timeslot:
assign(session,timeslot,meeting)
if timeslot.sessions.all().count() > 1:
messages.warning(request, 'WARNING: There are now multiple sessions scheduled for the timeslot: %s' % timeslot)
new_slots.append(timeslot)
if was_combined:
new_slots.append(get_next_slot(timeslot))
for ts in new_slots:
timeslot.session = session
timeslot.modified = now
timeslot.save()
if new_slots:
session.status_id = 'sched'
else:
session.status_id = 'schedw'
session.modified = now
session.save()
if 'note' in form.changed_data:
session.agenda_note = note
session.modified = now
@ -714,7 +694,9 @@ def schedule(request, meeting_id, acronym):
# COMBINE SECTION - AFTER ---------------
if 'combine' in form.changed_data and combine:
next_slot = get_next_slot(timeslot)
assign(session,next_slot,meeting)
next_slot.session = session
next_slot.modified = now
next_slot.save()
# ---------------------------------------
# notify. dont send if Tutorial, BOF or indicated on form
@ -722,7 +704,7 @@ def schedule(request, meeting_id, acronym):
if (has_changed
and not extra_form.cleaned_data.get('no_notify',False)
and group.state.slug != 'bof'
and get_timeslot(session)): # and the session is scheduled, else skip
and session.timeslot_set.all()): # and the session is scheduled, else skip
send_notification(request, sessions)
notification_message = "Notification sent."
@ -826,19 +808,19 @@ def times(request, meeting_id):
new_time = datetime.datetime(t.year,t.month,t.day,time.hour,time.minute)
# don't allow creation of timeslots with same start time as existing timeslots
# assert False, (new_time, time_seen)
if new_time in time_seen:
messages.error(request, 'There is already a timeslot for %s. To change you must delete the old one first.' % new_time.strftime('%a %H:%M'))
url = reverse('meetings_times', kwargs={'meeting_id':meeting_id})
return HttpResponseRedirect(url)
for room in meeting.room_set.all():
ts = TimeSlot.objects.create(type_id='session',
meeting=meeting,
name=name,
time=new_time,
location=room,
duration=duration)
ScheduledSession.objects.create(schedule=meeting.agenda,timeslot=ts)
TimeSlot.objects.create(type_id='session',
meeting=meeting,
name=name,
time=new_time,
location=room,
duration=duration)
messages.success(request, 'Timeslots created')
url = reverse('meetings_times', kwargs={'meeting_id':meeting_id})
@ -864,10 +846,7 @@ def times_delete(request, meeting_id, time):
parts = [ int(x) for x in time.split(':') ]
dtime = datetime.datetime(*parts)
qs = meeting.agenda.scheduledsession_set.filter(timeslot__time=dtime,
session__isnull=False)
if qs:
if Session.objects.filter(timeslot__time=dtime,timeslot__meeting=meeting):
messages.error(request, 'ERROR deleting timeslot. There is one or more sessions scheduled for this timeslot.')
url = reverse('meetings_times', kwargs={'meeting_id':meeting_id})
return HttpResponseRedirect(url)

View file

@ -14,7 +14,7 @@ from itertools import chain
from ietf.secr.proceedings.models import Registration
from ietf.secr.utils.document import get_rfc_num
from ietf.secr.utils.group import groups_by_session
from ietf.secr.utils.meeting import get_upload_root, get_proceedings_path, get_material, get_session, get_timeslot
from ietf.secr.utils.meeting import get_upload_root, get_proceedings_path, get_material
from models import InterimMeeting # proxy model
from urllib2 import urlopen
@ -32,7 +32,7 @@ def mycomp(timeslot):
This takes a timeslot object and returns a key to sort by the area acronym or None
'''
try:
group = get_session(timeslot).group
group = timeslot.session.group
key = '%s:%s' % (group.parent.acronym, group.acronym)
except AttributeError:
key = None
@ -349,7 +349,6 @@ def gen_areas(context):
'bof':filter(lambda a: a.parent==area and a.state.slug=='bof' and a.type_id=='wg',gnot),
'ag':filter(lambda a: a.parent==area and a.type_id=='ag',gnot)}
html = render_to_response('proceedings/area.html',{
'area': area,
'meeting': meeting,

View file

@ -216,8 +216,14 @@ def cancel(request, acronym):
session.status_id = 'deleted'
session.save()
# clear schedule assignments if already scheduled
session.scheduledsession_set.all().delete()
# clear timeslot assignment if already scheduled
if session.timeslot_set.all():
timeslot = session.timeslot_set.all()[0]
timeslot.session = None
timeslot.save()
# log activity
#add_session_activity(group,'Session was cancelled',meeting,user)
# send notifitcation
to_email = SESSION_REQUEST_EMAIL

View file

@ -1,5 +1,5 @@
from django.conf import settings
from ietf.meeting.models import Meeting, Session, Schedule, TimeSlot
from ietf.meeting.models import Meeting
import os
@ -28,34 +28,6 @@ def get_proceedings_path(meeting, group):
path = os.path.join(get_upload_root(meeting),'%s.html' % group.acronym)
return path
def get_session(timeslot, schedule=None):
'''
Helper function to get the session given a timeslot, assume Official schedule if one isn't
provided. Replaces "timeslot.session"
'''
# todo, doesn't account for shared timeslot
if not schedule:
schedule = timeslot.meeting.agenda
qs = timeslot.sessions.filter(scheduledsession__schedule=schedule) #.exclude(states__slug='deleted')
if qs:
return qs[0]
else:
return None
def get_timeslot(session, schedule=None):
'''
Helper function to get the timeslot associated with a session. Created for Agenda Tool
db schema changes. Use this function in place of session.timeslot_set.all()[0]. Don't specify
schedule to use the meeting "official" schedule.
'''
if not schedule:
schedule = session.meeting.agenda
ss = session.scheduledsession_set.filter(schedule=schedule)
if ss:
return ss[0].timeslot
else:
return None
def get_upload_root(meeting):
path = ''
if meeting.type.slug == 'ietf':

View file

@ -79,7 +79,7 @@ MEDIA_ROOT = BASE_DIR + "/../static/"
# URL that handles the media served from MEDIA_ROOT.
# Example: "http://media.lawrence.com"
MEDIA_URL = ''
MEDIA_URL = 'http://www.ietf.org'
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
@ -126,6 +126,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.request',
'django.core.context_processors.media',
'django.contrib.messages.context_processors.messages',
'ietf.context_processors.server_mode',
'ietf.context_processors.revision_info',
@ -339,7 +340,7 @@ SECR_BLUE_SHEET_URL = 'https://datatracker.ietf.org/documents/blue_sheet.rtf'
SECR_INTERIM_LISTING_DIR = '/a/www/www6/meeting/interim'
SECR_MAX_UPLOAD_SIZE = 40960000
SECR_PROCEEDINGS_DIR = '/a/www/www6s/proceedings/'
SECR_STATIC_URL = '/secr-static/'
SECR_STATIC_URL = '/secretariat/'
# Put SECRET_KEY in here, or any other sensitive or site-specific
# changes. DO NOT commit settings_local.py to svn.