Skip to content

Commit 7238fd9

Browse files
committed
Add support for series request. Javascript tweaks
- Legacy-Id: 11028
1 parent b85df63 commit 7238fd9

7 files changed

Lines changed: 164 additions & 22 deletions

File tree

ietf/meeting/forms.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from django import forms
55
from django.core.validators import ValidationError
6+
from django.forms import BaseFormSet
67
from django.forms.fields import Field
78
from django.utils.encoding import force_text
89
from django.utils import six
@@ -110,6 +111,27 @@ class GroupModelChoiceField(forms.ModelChoiceField):
110111
def label_from_instance(self, obj):
111112
return obj.acronym
112113

114+
'''
115+
class BaseSessionFormSet(BaseFormSet):
116+
def save_new_objects(self, commit=True):
117+
self.new_objects = []
118+
for form in self.extra_forms:
119+
if not form.has_changed():
120+
continue
121+
# If someone has marked an add form for deletion, don't save the
122+
# object.
123+
if self.can_delete and self._should_delete_form(form):
124+
continue
125+
self.new_objects.append(self.save_new(form, commit=commit))
126+
if not commit:
127+
self.saved_forms.append(form)
128+
return self.new_objects
129+
130+
def save(self,commit=True):
131+
#return self.save_existing_objects(commit) + self.save_new_objects(commit)
132+
return self.save_new_objects(commit)
133+
'''
134+
113135
# -------------------------------------------------
114136
# Forms
115137
# -------------------------------------------------
@@ -140,10 +162,16 @@ def set_group_options(self):
140162

141163
self.fields['group'].queryset = queryset
142164

165+
# if there's only one possibility make it the default
166+
if len(queryset) == 1:
167+
self.fields['group'].initial = queryset[0]
168+
143169
class InterimSessionForm(forms.Form):
144170
date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='Date', required=True)
145171
time = forms.TimeField()
172+
utc_time = forms.TimeField()
146173
duration = DurationField()
174+
end_time = forms.TimeField()
147175
remote_instructions = forms.CharField(max_length=1024,required=False)
148176
agenda = forms.CharField(required=False,widget=forms.Textarea)
149177
agenda_note = forms.CharField(max_length=255,required=False)

ietf/meeting/helpers.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from ietf.group.models import Group
1919
from ietf.ietfauth.utils import has_role, user_is_person
2020
from ietf.person.models import Person
21-
from ietf.meeting.models import Meeting
21+
from ietf.meeting.models import Meeting, Schedule
2222
from ietf.utils.history import find_history_active_at, find_history_replacements_active_at
2323
from ietf.utils.pipe import pipe
2424

@@ -285,6 +285,35 @@ def session_constraint_expire(request,session):
285285
if key is not None and cache.has_key(key):
286286
cache.delete(key)
287287

288+
def get_earliest_session(session_formset):
289+
'''Return earliest InterimSessionForm from formset'''
290+
earliest = session_formset[0]
291+
if len(session_formset) == 1:
292+
return earliest
293+
for form in session_formset[1:]:
294+
date = form.cleaned_data.get('date')
295+
if date and date < earliest.cleaned_data.get('date'):
296+
earliest = form
297+
return earliest
298+
288299
def get_next_interim_number(group,date):
289300
sequence = Meeting.objects.filter(number__startswith='interim-%s-%s' % (date.year,group.acronym)).count() + 1
290301
return 'interim-%s-%s-%s' % (date.year,group.acronym,sequence)
302+
303+
def create_interim_meeting(request_form,session_form):
304+
'''Create an Interim meeting, given an InterimRequestForm and InterimSessionForm'''
305+
group = request_form.cleaned_data.get('group')
306+
date = session_form.cleaned_data.get('date')
307+
number = get_next_interim_number(group,date)
308+
city = session_form.cleaned_data.get('city')
309+
country = session_form.cleaned_data.get('country')
310+
timezone = session_form.cleaned_data.get('timezone')
311+
if not request_form.cleaned_data.get('face_to_face'):
312+
timezone = 'UTC'
313+
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
314+
country=country,time_zone=timezone)
315+
schedule = Schedule.objects.create(meeting=meeting, owner=request_form.person, visible=True, public=True)
316+
meeting.agenda = schedule
317+
meeting.save()
318+
return meeting
319+

ietf/meeting/tests_views.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,48 @@ def test_interim_request_options(self):
381381
len(q("#id_group option")) -1 ) # -1 for options placeholder
382382

383383
def test_interim_request_single(self):
384+
make_meeting_test_data()
385+
group = Group.objects.get(acronym='mars')
386+
date = datetime.date.today() + datetime.timedelta(days=30)
387+
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
388+
dt = datetime.datetime.combine(date, time)
389+
duration = datetime.timedelta(hours=3)
390+
remote_instructions = 'Use webex'
391+
agenda = 'Intro. Slides. Discuss.'
392+
agenda_note = 'On second level'
393+
self.client.login(username="secretary", password="secretary+password")
394+
data = {'group':group.pk,
395+
'meeting_type':'single',
396+
'form-0-date':date.strftime("%Y-%m-%d"),
397+
'form-0-time':time.strftime('%H:%M'),
398+
'form-0-duration':'03:00:00',
399+
'form-0-city':'',
400+
'form-0-country':'',
401+
'form-0-timezone':'',
402+
'form-0-remote_instructions':remote_instructions,
403+
'form-0-agenda':agenda,
404+
'form-0-agenda_note':agenda_note,
405+
'form-TOTAL_FORMS':1,
406+
'form-INITIAL_FORMS':0}
407+
408+
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
409+
410+
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
411+
meeting = Meeting.objects.order_by('id').last()
412+
self.assertEqual(meeting.type_id,'interim')
413+
self.assertEqual(meeting.date,date)
414+
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year,group.acronym,1))
415+
self.assertEqual(meeting.city,'')
416+
self.assertEqual(meeting.country,'')
417+
self.assertEqual(meeting.time_zone,'UTC')
418+
self.assertEqual(meeting.agenda_note,agenda_note)
419+
session = meeting.session_set.first()
420+
self.assertEqual(session.remote_instructions,remote_instructions)
421+
timeslot = session.official_timeslotassignment().timeslot
422+
self.assertEqual(timeslot.time,dt)
423+
self.assertEqual(timeslot.duration,duration)
424+
425+
def test_interim_request_single_f2f(self):
384426
make_meeting_test_data()
385427
group = Group.objects.get(acronym='mars')
386428
date = datetime.date.today() + datetime.timedelta(days=30)

ietf/meeting/views.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting
3636
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_meetings
3737
from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file
38-
from ietf.meeting.helpers import convert_draft_to_pdf, get_next_interim_number
38+
from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session
39+
from ietf.meeting.helpers import create_interim_meeting
3940
from ietf.utils.pipe import pipe
4041
from ietf.utils.pdf import pdf_pages
4142

@@ -897,22 +898,20 @@ def interim_request(request):
897898
if request.method == 'POST':
898899
form = InterimRequestForm(request, data=request.POST)
899900
formset = SessionFormset(data=request.POST)
901+
person = request.user.person
900902
if form.is_valid() and formset.is_valid():
901903
group = form.cleaned_data.get('group')
902904
meeting_type = form.cleaned_data.get('meeting_type')
905+
906+
# pre create meeting
903907
if meeting_type in ('single','multi-day'):
904-
date = sorted([ f.cleaned_data.get('date') for f in formset.forms])[0]
905-
number = get_next_interim_number(group,date)
906-
city = formset.forms[0].cleaned_data.get('city')
907-
country = formset.forms[0].cleaned_data.get('country')
908-
timezone = formset.forms[0].cleaned_data.get('timezone')
909-
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
910-
country=country,time_zone=timezone)
911-
schedule = Schedule.objects.create(meeting=meeting, owner=person, visible=True, public=True)
912-
meeting.agenda = schedule
913-
meeting.save()
908+
meeting = create_interim_meeting(request_form=form,session_form=get_earliest_session(formset))
909+
914910
for f in formset.forms:
915-
# TODO: create meetings if type == series
911+
if not f.has_changed():
912+
continue
913+
if meeting_type == 'series':
914+
meeting = create_interim_meeting(form,f)
916915
f.save(request,group,meeting)
917916
return redirect(upcoming)
918917
else:
@@ -935,7 +934,7 @@ def ical_upcoming(request):
935934
def upcoming(request):
936935
'''List of upcoming meetings'''
937936
today = datetime.datetime.today()
938-
meetings = Meeting.objects.filter(date__gt=today)
937+
meetings = Meeting.objects.filter(date__gte=today).order_by('date')
939938

940939
# extract groups hierarchy
941940
seen = set()

ietf/static/ietf/css/ietf.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,3 +466,7 @@ form.navbar-form input.form-control.input-sm { width: 141px; }
466466
#interim-request-form .fieldset.template {
467467
display: none;
468468
}
469+
470+
#interim-request-form .time-field {
471+
width: 100px;
472+
}

ietf/static/ietf/js/meeting-interim-request.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
var interimRequest = {
33
// functions for Interim Meeting Request
44
init : function() {
5+
// get elements
56
interimRequest.form = $(this);
6-
//interimRequest.sessionTemplate = interimRequest.form.find('.fieldset.template');
7+
interimRequest.addButton = $('#add_session');
8+
interimRequest.faceToFace = $('#id_face_to_face');
9+
// bind functions
710
$('.select2-field').select2();
811
$('#add_session').click(interimRequest.addSession);
912
$('#id_face_to_face').change(interimRequest.toggleLocation);
10-
$('#id_face_to_face').each(interimRequest.toggleLocation);
13+
$('input[name="meeting_type"]').change(interimRequest.checkAddButton);
14+
// init
15+
interimRequest.faceToFace.each(interimRequest.toggleLocation);
16+
interimRequest.checkAddButton();
1117
},
1218

1319
addSession : function() {
@@ -16,6 +22,7 @@ var interimRequest = {
1622
var el = template.clone(true);
1723
var totalField = $('#id_form-TOTAL_FORMS');
1824
var total = +totalField.val();
25+
var meeting_type = $('input[name="meeting_type"]:checked').val();
1926

2027
el.find(':input').each(function() {
2128
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
@@ -38,6 +45,27 @@ var interimRequest = {
3845
el.find(".select2-field").each(function () {
3946
setupSelect2Field($(this));
4047
});
48+
49+
if(interimRequest.faceToFace.prop('checked')){
50+
var first_session = $(".fieldset:first");
51+
el.find("input[name$='city']").val(first_session.find("input[name$='city']").val());
52+
el.find("select[name$='country']").val(first_session.find("select[name$='country']").val());
53+
el.find("select[name$='timezone']").val(first_session.find("select[name$='timezone']").val());
54+
}
55+
56+
if(meeting_type == 'multi-day'){
57+
el.find(".location").prop('disabled', true);
58+
}
59+
60+
},
61+
62+
checkAddButton : function() {
63+
var meeting_type = $('input[name="meeting_type"]:checked').val();
64+
if(meeting_type == 'single'){
65+
interimRequest.addButton.hide();
66+
} else {
67+
interimRequest.addButton.show();
68+
}
4169
},
4270

4371
toggleLocation : function() {

ietf/templates/meeting/interim_request.html

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,16 @@ <h1>Interim Meeting Request</h1>
6363
<label for="session" class="col-md-2 control-label">Session</label>
6464
<div class="">
6565
<div class="form-inline">
66-
<div class="col-md-3">{% render_field form.date class="form-control" %}</div>
67-
<div class="col-md-3">{% render_field form.time class="form-control" placeholder="time" %}</div>
68-
<div class="col-md-3">{% render_field form.duration class="form-control" placeholder="duration" %}</div>
66+
<div class="col-md-9">
67+
{% render_field form.date class="form-control" %}
68+
<div>
69+
{% render_field form.time class="form-control time-field" placeholder="time" %}
70+
<p class="help-block">Time</p>
71+
</div>
72+
{% render_field form.utc_time class="form-control time-field computed" disabled="disabled" placeholder="UTC time" %}
73+
{% render_field form.duration class="form-control time-field" placeholder="duration" %}
74+
{% render_field form.end_time class="form-control time-field computed" placeholder="end time" disabled="disabled" %}
75+
</div>
6976
</div>
7077
</div>
7178
</div>
@@ -87,14 +94,19 @@ <h1>Interim Meeting Request</h1>
8794
</div> <!-- fieldset -->
8895
{% endfor %}
8996

90-
<div class="row">
91-
<button id="add_session" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true">Add Session</button>
92-
</div>
97+
<div class="form-group">
98+
<div class="col-md-10">
99+
<button id="add_session" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>Add Session</button>
100+
</div>
101+
</div>
93102

103+
<div class="form-group"
94104
{% buttons %}
95105
<button type="submit" class="btn btn-primary">Submit</button>
96106
<a class="btn btn-default pull-right" href="{% url "ietf.meeting.views.upcoming" %}">Back</a>
97107
{% endbuttons %}
108+
</div>
109+
98110
</form>
99111

100112
{% endblock %}

0 commit comments

Comments
 (0)