Add support for series request. Javascript tweaks
- Legacy-Id: 11028
This commit is contained in:
parent
b85df63a4f
commit
7238fd9148
|
@ -3,6 +3,7 @@ import re
|
|||
|
||||
from django import forms
|
||||
from django.core.validators import ValidationError
|
||||
from django.forms import BaseFormSet
|
||||
from django.forms.fields import Field
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils import six
|
||||
|
@ -110,6 +111,27 @@ class GroupModelChoiceField(forms.ModelChoiceField):
|
|||
def label_from_instance(self, obj):
|
||||
return obj.acronym
|
||||
|
||||
'''
|
||||
class BaseSessionFormSet(BaseFormSet):
|
||||
def save_new_objects(self, commit=True):
|
||||
self.new_objects = []
|
||||
for form in self.extra_forms:
|
||||
if not form.has_changed():
|
||||
continue
|
||||
# If someone has marked an add form for deletion, don't save the
|
||||
# object.
|
||||
if self.can_delete and self._should_delete_form(form):
|
||||
continue
|
||||
self.new_objects.append(self.save_new(form, commit=commit))
|
||||
if not commit:
|
||||
self.saved_forms.append(form)
|
||||
return self.new_objects
|
||||
|
||||
def save(self,commit=True):
|
||||
#return self.save_existing_objects(commit) + self.save_new_objects(commit)
|
||||
return self.save_new_objects(commit)
|
||||
'''
|
||||
|
||||
# -------------------------------------------------
|
||||
# Forms
|
||||
# -------------------------------------------------
|
||||
|
@ -140,10 +162,16 @@ class InterimRequestForm(forms.Form):
|
|||
|
||||
self.fields['group'].queryset = queryset
|
||||
|
||||
# if there's only one possibility make it the default
|
||||
if len(queryset) == 1:
|
||||
self.fields['group'].initial = queryset[0]
|
||||
|
||||
class InterimSessionForm(forms.Form):
|
||||
date = DatepickerDateField(date_format="yyyy-mm-dd", picker_settings={"autoclose": "1" }, label='Date', required=True)
|
||||
time = forms.TimeField()
|
||||
utc_time = forms.TimeField()
|
||||
duration = DurationField()
|
||||
end_time = forms.TimeField()
|
||||
remote_instructions = forms.CharField(max_length=1024,required=False)
|
||||
agenda = forms.CharField(required=False,widget=forms.Textarea)
|
||||
agenda_note = forms.CharField(max_length=255,required=False)
|
||||
|
|
|
@ -18,7 +18,7 @@ from ietf.doc.models import Document
|
|||
from ietf.group.models import Group
|
||||
from ietf.ietfauth.utils import has_role, user_is_person
|
||||
from ietf.person.models import Person
|
||||
from ietf.meeting.models import Meeting
|
||||
from ietf.meeting.models import Meeting, Schedule
|
||||
from ietf.utils.history import find_history_active_at, find_history_replacements_active_at
|
||||
from ietf.utils.pipe import pipe
|
||||
|
||||
|
@ -285,6 +285,35 @@ def session_constraint_expire(request,session):
|
|||
if key is not None and cache.has_key(key):
|
||||
cache.delete(key)
|
||||
|
||||
def get_earliest_session(session_formset):
|
||||
'''Return earliest InterimSessionForm from formset'''
|
||||
earliest = session_formset[0]
|
||||
if len(session_formset) == 1:
|
||||
return earliest
|
||||
for form in session_formset[1:]:
|
||||
date = form.cleaned_data.get('date')
|
||||
if date and date < earliest.cleaned_data.get('date'):
|
||||
earliest = form
|
||||
return earliest
|
||||
|
||||
def get_next_interim_number(group,date):
|
||||
sequence = Meeting.objects.filter(number__startswith='interim-%s-%s' % (date.year,group.acronym)).count() + 1
|
||||
return 'interim-%s-%s-%s' % (date.year,group.acronym,sequence)
|
||||
|
||||
def create_interim_meeting(request_form,session_form):
|
||||
'''Create an Interim meeting, given an InterimRequestForm and InterimSessionForm'''
|
||||
group = request_form.cleaned_data.get('group')
|
||||
date = session_form.cleaned_data.get('date')
|
||||
number = get_next_interim_number(group,date)
|
||||
city = session_form.cleaned_data.get('city')
|
||||
country = session_form.cleaned_data.get('country')
|
||||
timezone = session_form.cleaned_data.get('timezone')
|
||||
if not request_form.cleaned_data.get('face_to_face'):
|
||||
timezone = 'UTC'
|
||||
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
|
||||
country=country,time_zone=timezone)
|
||||
schedule = Schedule.objects.create(meeting=meeting, owner=request_form.person, visible=True, public=True)
|
||||
meeting.agenda = schedule
|
||||
meeting.save()
|
||||
return meeting
|
||||
|
||||
|
|
|
@ -381,6 +381,48 @@ class InterimTests(TestCase):
|
|||
len(q("#id_group option")) -1 ) # -1 for options placeholder
|
||||
|
||||
def test_interim_request_single(self):
|
||||
make_meeting_test_data()
|
||||
group = Group.objects.get(acronym='mars')
|
||||
date = datetime.date.today() + datetime.timedelta(days=30)
|
||||
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
||||
dt = datetime.datetime.combine(date, time)
|
||||
duration = datetime.timedelta(hours=3)
|
||||
remote_instructions = 'Use webex'
|
||||
agenda = 'Intro. Slides. Discuss.'
|
||||
agenda_note = 'On second level'
|
||||
self.client.login(username="secretary", password="secretary+password")
|
||||
data = {'group':group.pk,
|
||||
'meeting_type':'single',
|
||||
'form-0-date':date.strftime("%Y-%m-%d"),
|
||||
'form-0-time':time.strftime('%H:%M'),
|
||||
'form-0-duration':'03:00:00',
|
||||
'form-0-city':'',
|
||||
'form-0-country':'',
|
||||
'form-0-timezone':'',
|
||||
'form-0-remote_instructions':remote_instructions,
|
||||
'form-0-agenda':agenda,
|
||||
'form-0-agenda_note':agenda_note,
|
||||
'form-TOTAL_FORMS':1,
|
||||
'form-INITIAL_FORMS':0}
|
||||
|
||||
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
||||
|
||||
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
|
||||
meeting = Meeting.objects.order_by('id').last()
|
||||
self.assertEqual(meeting.type_id,'interim')
|
||||
self.assertEqual(meeting.date,date)
|
||||
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year,group.acronym,1))
|
||||
self.assertEqual(meeting.city,'')
|
||||
self.assertEqual(meeting.country,'')
|
||||
self.assertEqual(meeting.time_zone,'UTC')
|
||||
self.assertEqual(meeting.agenda_note,agenda_note)
|
||||
session = meeting.session_set.first()
|
||||
self.assertEqual(session.remote_instructions,remote_instructions)
|
||||
timeslot = session.official_timeslotassignment().timeslot
|
||||
self.assertEqual(timeslot.time,dt)
|
||||
self.assertEqual(timeslot.duration,duration)
|
||||
|
||||
def test_interim_request_single_f2f(self):
|
||||
make_meeting_test_data()
|
||||
group = Group.objects.get(acronym='mars')
|
||||
date = datetime.date.today() + datetime.timedelta(days=30)
|
||||
|
|
|
@ -35,7 +35,8 @@ from ietf.meeting.helpers import get_modified_from_assignments
|
|||
from ietf.meeting.helpers import get_wg_list, find_ads_for_meeting
|
||||
from ietf.meeting.helpers import get_meeting, get_schedule, agenda_permissions, get_meetings
|
||||
from ietf.meeting.helpers import preprocess_assignments_for_agenda, read_agenda_file
|
||||
from ietf.meeting.helpers import convert_draft_to_pdf, get_next_interim_number
|
||||
from ietf.meeting.helpers import convert_draft_to_pdf, get_earliest_session
|
||||
from ietf.meeting.helpers import create_interim_meeting
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.pdf import pdf_pages
|
||||
|
||||
|
@ -897,22 +898,20 @@ def interim_request(request):
|
|||
if request.method == 'POST':
|
||||
form = InterimRequestForm(request, data=request.POST)
|
||||
formset = SessionFormset(data=request.POST)
|
||||
person = request.user.person
|
||||
if form.is_valid() and formset.is_valid():
|
||||
group = form.cleaned_data.get('group')
|
||||
meeting_type = form.cleaned_data.get('meeting_type')
|
||||
|
||||
# pre create meeting
|
||||
if meeting_type in ('single','multi-day'):
|
||||
date = sorted([ f.cleaned_data.get('date') for f in formset.forms])[0]
|
||||
number = get_next_interim_number(group,date)
|
||||
city = formset.forms[0].cleaned_data.get('city')
|
||||
country = formset.forms[0].cleaned_data.get('country')
|
||||
timezone = formset.forms[0].cleaned_data.get('timezone')
|
||||
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
|
||||
country=country,time_zone=timezone)
|
||||
schedule = Schedule.objects.create(meeting=meeting, owner=person, visible=True, public=True)
|
||||
meeting.agenda = schedule
|
||||
meeting.save()
|
||||
meeting = create_interim_meeting(request_form=form,session_form=get_earliest_session(formset))
|
||||
|
||||
for f in formset.forms:
|
||||
# TODO: create meetings if type == series
|
||||
if not f.has_changed():
|
||||
continue
|
||||
if meeting_type == 'series':
|
||||
meeting = create_interim_meeting(form,f)
|
||||
f.save(request,group,meeting)
|
||||
return redirect(upcoming)
|
||||
else:
|
||||
|
@ -935,7 +934,7 @@ def ical_upcoming(request):
|
|||
def upcoming(request):
|
||||
'''List of upcoming meetings'''
|
||||
today = datetime.datetime.today()
|
||||
meetings = Meeting.objects.filter(date__gt=today)
|
||||
meetings = Meeting.objects.filter(date__gte=today).order_by('date')
|
||||
|
||||
# extract groups hierarchy
|
||||
seen = set()
|
||||
|
|
|
@ -466,3 +466,7 @@ form.navbar-form input.form-control.input-sm { width: 141px; }
|
|||
#interim-request-form .fieldset.template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#interim-request-form .time-field {
|
||||
width: 100px;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
var interimRequest = {
|
||||
// functions for Interim Meeting Request
|
||||
init : function() {
|
||||
// get elements
|
||||
interimRequest.form = $(this);
|
||||
//interimRequest.sessionTemplate = interimRequest.form.find('.fieldset.template');
|
||||
interimRequest.addButton = $('#add_session');
|
||||
interimRequest.faceToFace = $('#id_face_to_face');
|
||||
// bind functions
|
||||
$('.select2-field').select2();
|
||||
$('#add_session').click(interimRequest.addSession);
|
||||
$('#id_face_to_face').change(interimRequest.toggleLocation);
|
||||
$('#id_face_to_face').each(interimRequest.toggleLocation);
|
||||
$('input[name="meeting_type"]').change(interimRequest.checkAddButton);
|
||||
// init
|
||||
interimRequest.faceToFace.each(interimRequest.toggleLocation);
|
||||
interimRequest.checkAddButton();
|
||||
},
|
||||
|
||||
addSession : function() {
|
||||
|
@ -16,6 +22,7 @@ var interimRequest = {
|
|||
var el = template.clone(true);
|
||||
var totalField = $('#id_form-TOTAL_FORMS');
|
||||
var total = +totalField.val();
|
||||
var meeting_type = $('input[name="meeting_type"]:checked').val();
|
||||
|
||||
el.find(':input').each(function() {
|
||||
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
|
||||
|
@ -38,6 +45,27 @@ var interimRequest = {
|
|||
el.find(".select2-field").each(function () {
|
||||
setupSelect2Field($(this));
|
||||
});
|
||||
|
||||
if(interimRequest.faceToFace.prop('checked')){
|
||||
var first_session = $(".fieldset:first");
|
||||
el.find("input[name$='city']").val(first_session.find("input[name$='city']").val());
|
||||
el.find("select[name$='country']").val(first_session.find("select[name$='country']").val());
|
||||
el.find("select[name$='timezone']").val(first_session.find("select[name$='timezone']").val());
|
||||
}
|
||||
|
||||
if(meeting_type == 'multi-day'){
|
||||
el.find(".location").prop('disabled', true);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
checkAddButton : function() {
|
||||
var meeting_type = $('input[name="meeting_type"]:checked').val();
|
||||
if(meeting_type == 'single'){
|
||||
interimRequest.addButton.hide();
|
||||
} else {
|
||||
interimRequest.addButton.show();
|
||||
}
|
||||
},
|
||||
|
||||
toggleLocation : function() {
|
||||
|
|
|
@ -63,9 +63,16 @@
|
|||
<label for="session" class="col-md-2 control-label">Session</label>
|
||||
<div class="">
|
||||
<div class="form-inline">
|
||||
<div class="col-md-3">{% render_field form.date class="form-control" %}</div>
|
||||
<div class="col-md-3">{% render_field form.time class="form-control" placeholder="time" %}</div>
|
||||
<div class="col-md-3">{% render_field form.duration class="form-control" placeholder="duration" %}</div>
|
||||
<div class="col-md-9">
|
||||
{% render_field form.date class="form-control" %}
|
||||
<div>
|
||||
{% render_field form.time class="form-control time-field" placeholder="time" %}
|
||||
<p class="help-block">Time</p>
|
||||
</div>
|
||||
{% render_field form.utc_time class="form-control time-field computed" disabled="disabled" placeholder="UTC time" %}
|
||||
{% render_field form.duration class="form-control time-field" placeholder="duration" %}
|
||||
{% render_field form.end_time class="form-control time-field computed" placeholder="end time" disabled="disabled" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -87,14 +94,19 @@
|
|||
</div> <!-- fieldset -->
|
||||
{% endfor %}
|
||||
|
||||
<div class="row">
|
||||
<button id="add_session" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true">Add Session</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-10">
|
||||
<button id="add_session" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span>Add Session</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group"
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<a class="btn btn-default pull-right" href="{% url "ietf.meeting.views.upcoming" %}">Back</a>
|
||||
{% endbuttons %}
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue