diff --git a/ietf/secr/meetings/forms.py b/ietf/secr/meetings/forms.py
index 9f6a5d589..5d15e9893 100644
--- a/ietf/secr/meetings/forms.py
+++ b/ietf/secr/meetings/forms.py
@@ -166,36 +166,17 @@ class NewSessionForm(forms.Form):
return cleaned_data
-class NonSessionEditForm(forms.Form):
- name = forms.CharField(help_text='Name that appears on the agenda')
- short = forms.CharField(max_length=32,label='Short Name',help_text='Enter an abbreviated session name (used for material file names)')
- location = forms.ModelChoiceField(queryset=Room.objects)
- group = forms.ModelChoiceField(
- queryset=Group.objects.filter(type__in=['ietf','team'],state='active'),
- help_text='''Select a group to associate with this session. For example:
- Tutorials = Education,
- Code Sprint = Tools Team,
- Technical Plenary = IAB,
- Administrative Plenary = IAOC or IESG''',empty_label=None)
-
- def __init__(self,*args,**kwargs):
- meeting = kwargs.pop('meeting')
- self.session = kwargs.pop('session')
- super(NonSessionEditForm, self).__init__(*args,**kwargs)
- self.fields['location'].queryset = Room.objects.filter(meeting=meeting)
-
- def clean_group(self):
- group = self.cleaned_data['group']
- if self.session.group != group and self.session.materials.all():
- raise forms.ValidationError("ERROR: can't change group after materials have been uploaded")
- return group
-
class TimeSlotForm(forms.Form):
day = forms.ChoiceField(choices=DAYS_CHOICES)
time = forms.TimeField()
duration = ietf.utils.fields.DurationField()
name = forms.CharField(help_text='Name that appears on the agenda')
+ def __init__(self,*args,**kwargs):
+ super(TimeSlotForm, self).__init__(*args,**kwargs)
+ self.fields["time"].widget.attrs["placeholder"] = "HH:MM"
+ self.fields["duration"].widget.attrs["placeholder"] = "HH:MM"
+
def clean_duration(self):
'''Limit to HH:MM format'''
duration = self.data['duration']
@@ -208,14 +189,21 @@ class NonSessionForm(TimeSlotForm):
type = forms.ModelChoiceField(queryset=TimeSlotTypeName.objects.filter(used=True).exclude(slug__in=('session',)),empty_label=None)
group = forms.ModelChoiceField(
queryset=Group.objects.filter(type__in=['ietf','team'],state='active'),
- help_text='Required for Session types: other, plenary',
+ help_text='''Select a group to associate with this session. For example:
+ Tutorials = Education,
+ Code Sprint = Tools Team,
+ Plenary = IETF''',
required=False)
+ location = forms.ModelChoiceField(queryset=Room.objects, required=False)
show_location = forms.BooleanField(required=False)
def __init__(self,*args,**kwargs):
+ if 'meeting' in kwargs:
+ self.meeting = kwargs.pop('meeting')
+ if 'session' in kwargs:
+ self.session = kwargs.pop('session')
super(NonSessionForm, self).__init__(*args,**kwargs)
- self.fields["time"].widget.attrs["placeholder"] = "HH:MM"
- self.fields["duration"].widget.attrs["placeholder"] = "HH:MM"
+ self.fields['location'].queryset = Room.objects.filter(meeting=self.meeting)
def clean(self):
super(NonSessionForm, self).clean()
@@ -225,13 +213,19 @@ class NonSessionForm(TimeSlotForm):
group = cleaned_data['group']
type = cleaned_data['type']
short = cleaned_data['short']
- if type.slug in ('other','plenary') and not group:
+ if type.slug in ('other','plenary','lead') and not group:
raise forms.ValidationError('ERROR: a group selection is required')
- if type.slug in ('other','plenary') and not short:
+ if type.slug in ('other','plenary','lead') and not short:
raise forms.ValidationError('ERROR: a short name is required')
return cleaned_data
-
+
+ def clean_group(self):
+ group = self.cleaned_data['group']
+ if hasattr(self, 'session') and self.session.group != group and self.session.materials.all():
+ raise forms.ValidationError("ERROR: can't change group after materials have been uploaded")
+ return group
+
class UploadBlueSheetForm(forms.Form):
file = forms.FileField(help_text='example: bluesheets-84-ancp-01.pdf')
diff --git a/ietf/secr/meetings/tests.py b/ietf/secr/meetings/tests.py
index 46eb53a96..8fc6bb6df 100644
--- a/ietf/secr/meetings/tests.py
+++ b/ietf/secr/meetings/tests.py
@@ -207,7 +207,15 @@ class SecrMeetingTestCase(TestCase):
self.client.login(username="secretary", password="secretary+password")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
-
+ response = self.client.post(url, {
+ 'day': 0,
+ 'time':'08:00',
+ 'duration':'01:00',
+ 'name':'Test Morning Session'
+ }, follow=True)
+ self.assertRedirects(response, url)
+ self.assertTrue('Test Morning Session' in response.content)
+
def test_meetings_times_delete(self):
meeting = make_meeting_test_data()
qs = TimeSlot.objects.filter(meeting=meeting,type='session')
@@ -266,6 +274,30 @@ class SecrMeetingTestCase(TestCase):
self.assertEqual(response.status_code, 200)
self.assertTrue('invalid format' in response.content)
+ def test_meetings_nonsession_edit(self):
+ meeting = make_meeting_test_data()
+ session = meeting.session_set.exclude(name='').first() # get first non-session session
+ timeslot = session.official_timeslotassignment().timeslot
+ url = reverse('ietf.secr.meetings.views.non_session_edit',kwargs={'meeting_id':42,'schedule_name':meeting.agenda.name,'slot_id':timeslot.pk})
+ redirect_url = reverse('ietf.secr.meetings.views.non_session',kwargs={'meeting_id':42,'schedule_name':'test-agenda'})
+ new_time = timeslot.time + datetime.timedelta(days=1)
+ self.client.login(username="secretary", password="secretary+password")
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 200)
+ response = self.client.post(url, {
+ 'name':'IETF Hackathon',
+ 'short':'hackathon',
+ 'location':timeslot.location.id,
+ 'group':session.group.id,
+ 'time':new_time.strftime('%H:%M'),
+ 'duration':'01:00',
+ 'day':'2',
+ 'type':'other',
+ })
+ self.assertRedirects(response, redirect_url)
+ timeslot = session.official_timeslotassignment().timeslot
+ self.assertEqual(timeslot.time,new_time)
+
def test_meetings_select_group(self):
make_meeting_test_data()
url = reverse('ietf.secr.meetings.views.select_group',kwargs={'meeting_id':42,'schedule_name':'test-agenda'})
diff --git a/ietf/secr/meetings/views.py b/ietf/secr/meetings/views.py
index 8b0675481..e20f4ea60 100644
--- a/ietf/secr/meetings/views.py
+++ b/ietf/secr/meetings/views.py
@@ -15,13 +15,14 @@ from django.utils.functional import curry
from ietf.ietfauth.utils import role_required
from ietf.utils.mail import send_mail
+from ietf.meeting.forms import duration_string
from ietf.meeting.helpers import get_meeting, make_materials_directories
from ietf.meeting.models import Meeting, Session, Room, TimeSlot, SchedTimeSessAssignment, Schedule
from ietf.group.models import Group, GroupEvent
from ietf.person.models import Person
from ietf.secr.meetings.blue_sheets import create_blue_sheets
from ietf.secr.meetings.forms import ( BaseMeetingRoomFormSet, MeetingModelForm, MeetingSelectForm,
- MeetingRoomForm, NewSessionForm, NonSessionEditForm, NonSessionForm, TimeSlotForm,
+ MeetingRoomForm, NewSessionForm, NonSessionForm, TimeSlotForm,
UploadBlueSheetForm, get_next_slot )
from ietf.secr.proceedings.views import build_choices
from ietf.secr.proceedings.utils import handle_upload_file
@@ -459,23 +460,20 @@ def non_session(request, meeting_id, schedule_name):
slots = slots.order_by('-type__name','time')
if request.method == 'POST':
- form = NonSessionForm(request.POST)
+ form = NonSessionForm(request.POST, meeting=meeting)
if form.is_valid():
- day = form.cleaned_data['day']
- time = form.cleaned_data['time']
+ time = get_timeslot_time(form, meeting)
name = form.cleaned_data['name']
short = form.cleaned_data['short']
type = form.cleaned_data['type']
group = form.cleaned_data['group']
duration = form.cleaned_data['duration']
- 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=type,
meeting=meeting,
name=name,
- time=new_time,
+ time=time,
duration=duration,
show_location=form.cleaned_data['show_location'])
@@ -501,7 +499,7 @@ def non_session(request, meeting_id, schedule_name):
messages.success(request, 'Non-Sessions updated successfully')
return redirect('ietf.secr.meetings.views.non_session', meeting_id=meeting_id, schedule_name=schedule_name)
else:
- form = NonSessionForm(initial={'show_location':True})
+ form = NonSessionForm(initial={'show_location':True}, meeting=meeting)
if TimeSlot.objects.filter(meeting=meeting,type='other',location__isnull=True):
messages.warning(request, 'There are non-session items which do not have a room assigned')
@@ -552,14 +550,22 @@ def non_session_edit(request, meeting_id, schedule_name, slot_id):
if button_text == 'Cancel':
return redirect('ietf.secr.meetings.views.non_session', meeting_id=meeting_id, schedule_name=schedule_name)
- form = NonSessionEditForm(request.POST,meeting=meeting, session=session)
+ form = NonSessionForm(request.POST,meeting=meeting,session=session)
if form.is_valid():
location = form.cleaned_data['location']
group = form.cleaned_data['group']
name = form.cleaned_data['name']
short = form.cleaned_data['short']
+ duration = form.cleaned_data['duration']
+ slot_type = form.cleaned_data['type']
+ show_location = form.cleaned_data['show_location']
+ time = get_timeslot_time(form, meeting)
slot.location = location
slot.name = name
+ slot.time = time
+ slot.duration = duration
+ slot.type = slot_type
+ slot.show_location = show_location
slot.save()
# save group to session object
session.group = group
@@ -573,11 +579,17 @@ def non_session_edit(request, meeting_id, schedule_name, slot_id):
else:
# we need to pass the session to the form in order to disallow changing
# of group after materials have been uploaded
+ delta = slot.time.date() - meeting.date
initial = {'location':slot.location,
'group':session.group,
'name':session.name,
- 'short':session.short}
- form = NonSessionEditForm(meeting=meeting,session=session,initial=initial)
+ 'short':session.short,
+ 'day':delta.days,
+ 'time':slot.time.strftime('%H:%M'),
+ 'duration':duration_string(slot.duration),
+ 'show_location':slot.show_location,
+ 'type':slot.type}
+ form = NonSessionForm(initial=initial, meeting=meeting, session=session)
return render(request, 'meetings/non_session_edit.html', {
'meeting': meeting,
@@ -889,25 +901,21 @@ def times(request, meeting_id, schedule_name):
if request.method == 'POST':
form = TimeSlotForm(request.POST)
if form.is_valid():
- day = form.cleaned_data['day']
- time = form.cleaned_data['time']
+ time = get_timeslot_time(form, meeting)
duration = form.cleaned_data['duration']
name = form.cleaned_data['name']
- t = meeting.date + datetime.timedelta(days=int(day))
- 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'))
+ if time in time_seen:
+ messages.error(request, 'There is already a timeslot for %s. To change you must delete the old one first.' % time.strftime('%a %H:%M'))
return redirect('ietf.secr.meetings.views.times', meeting_id=meeting_id,schedule_name=schedule_name)
for room in meeting.room_set.all():
TimeSlot.objects.create(type_id='session',
meeting=meeting,
name=name,
- time=new_time,
+ time=time,
location=room,
duration=duration)
@@ -924,6 +932,14 @@ def times(request, meeting_id, schedule_name):
'times': times},
)
+def get_timeslot_time(form, meeting):
+ '''Returns datetime calculated from day and time form fields'''
+ time = form.cleaned_data['time']
+ day = form.cleaned_data['day']
+
+ date = meeting.date + datetime.timedelta(days=int(day))
+ return datetime.datetime(date.year,date.month,date.day,time.hour,time.minute)
+
@role_required('Secretariat')
def times_edit(request, meeting_id, schedule_name, time):
'''
@@ -944,15 +960,12 @@ def times_edit(request, meeting_id, schedule_name, time):
form = TimeSlotForm(request.POST)
if form.is_valid():
day = form.cleaned_data['day']
- time = form.cleaned_data['time']
+ time = get_timeslot_time(form, meeting)
duration = form.cleaned_data['duration']
name = form.cleaned_data['name']
- t = meeting.date + datetime.timedelta(days=int(day))
- new_time = datetime.datetime(t.year,t.month,t.day,time.hour,time.minute)
-
for timeslot in timeslots:
- timeslot.time = new_time
+ timeslot.time = time
timeslot.duration = duration
timeslot.name = name
timeslot.save()
diff --git a/ietf/secr/templates/meetings/non_session.html b/ietf/secr/templates/meetings/non_session.html
index cae8c1979..69b499226 100644
--- a/ietf/secr/templates/meetings/non_session.html
+++ b/ietf/secr/templates/meetings/non_session.html
@@ -18,6 +18,7 @@