add time and duration to interim request form
- Legacy-Id: 10884
This commit is contained in:
parent
3a1af7dc83
commit
269547a757
|
@ -1,6 +1,11 @@
|
|||
import datetime
|
||||
import re
|
||||
|
||||
from django import forms
|
||||
from django.forms.fields import Field
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils import six
|
||||
|
||||
from ietf.group.models import Group
|
||||
from ietf.ietfauth.utils import has_role
|
||||
from ietf.meeting.models import Meeting, Schedule, TimeSlot, Session, SchedTimeSessAssignment, countries, timezones
|
||||
|
@ -9,6 +14,93 @@ from ietf.meeting.models import Meeting, Schedule, TimeSlot, Session, SchedTimeS
|
|||
countries.insert(0, ('', '-'*9 ))
|
||||
timezones.insert(0, ('', '-'*9 ))
|
||||
|
||||
# -------------------------------------------------
|
||||
# DurationField from Django 1.8
|
||||
# -------------------------------------------------
|
||||
def duration_string(duration):
|
||||
days = duration.days
|
||||
seconds = duration.seconds
|
||||
microseconds = duration.microseconds
|
||||
|
||||
minutes = seconds // 60
|
||||
seconds = seconds % 60
|
||||
|
||||
hours = minutes // 60
|
||||
minutes = minutes % 60
|
||||
|
||||
string = '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
|
||||
if days:
|
||||
string = '{} '.format(days) + string
|
||||
if microseconds:
|
||||
string += '.{:06d}'.format(microseconds)
|
||||
|
||||
return string
|
||||
|
||||
standard_duration_re = re.compile(
|
||||
r'^'
|
||||
r'(?:(?P<days>-?\d+) (days?, )?)?'
|
||||
r'((?:(?P<hours>\d+):)(?=\d+:\d+))?'
|
||||
r'(?:(?P<minutes>\d+):)?'
|
||||
r'(?P<seconds>\d+)'
|
||||
r'(?:\.(?P<microseconds>\d{1,6})\d{0,6})?'
|
||||
r'$'
|
||||
)
|
||||
|
||||
# Support the sections of ISO 8601 date representation that are accepted by
|
||||
# timedelta
|
||||
iso8601_duration_re = re.compile(
|
||||
r'^P'
|
||||
r'(?:(?P<days>\d+(.\d+)?)D)?'
|
||||
r'(?:T'
|
||||
r'(?:(?P<hours>\d+(.\d+)?)H)?'
|
||||
r'(?:(?P<minutes>\d+(.\d+)?)M)?'
|
||||
r'(?:(?P<seconds>\d+(.\d+)?)S)?'
|
||||
r')?'
|
||||
r'$'
|
||||
)
|
||||
|
||||
def parse_duration(value):
|
||||
"""Parses a duration string and returns a datetime.timedelta.
|
||||
|
||||
The preferred format for durations in Django is '%d %H:%M:%S.%f'.
|
||||
|
||||
Also supports ISO 8601 representation.
|
||||
"""
|
||||
match = standard_duration_re.match(value)
|
||||
if not match:
|
||||
match = iso8601_duration_re.match(value)
|
||||
if match:
|
||||
kw = match.groupdict()
|
||||
if kw.get('microseconds'):
|
||||
kw['microseconds'] = kw['microseconds'].ljust(6, '0')
|
||||
kw = {k: float(v) for k, v in six.iteritems(kw) if v is not None}
|
||||
return datetime.timedelta(**kw)
|
||||
|
||||
class DurationField(Field):
|
||||
default_error_messages = {
|
||||
'invalid': 'Enter a valid duration.',
|
||||
}
|
||||
|
||||
def prepare_value(self, value):
|
||||
if isinstance(value, datetime.timedelta):
|
||||
return duration_string(value)
|
||||
return value
|
||||
|
||||
def to_python(self, value):
|
||||
if value in self.empty_values:
|
||||
return None
|
||||
if isinstance(value, datetime.timedelta):
|
||||
return value
|
||||
value = parse_duration(force_text(value))
|
||||
if value is None:
|
||||
raise ValidationError(self.error_messages['invalid'], code='invalid')
|
||||
return value
|
||||
|
||||
|
||||
# -------------------------------------------------
|
||||
# Helpers
|
||||
# -------------------------------------------------
|
||||
|
||||
class GroupModelChoiceField(forms.ModelChoiceField):
|
||||
'''
|
||||
Custom ModelChoiceField, changes the label to a more readable format
|
||||
|
@ -16,9 +108,15 @@ class GroupModelChoiceField(forms.ModelChoiceField):
|
|||
def label_from_instance(self, obj):
|
||||
return obj.acronym
|
||||
|
||||
# -------------------------------------------------
|
||||
# Forms
|
||||
# -------------------------------------------------
|
||||
|
||||
class InterimRequestForm(forms.Form):
|
||||
group = GroupModelChoiceField(queryset = Group.objects.filter(type__in=('wg','rg'),state='active').order_by('acronym'))
|
||||
date = forms.DateField()
|
||||
time = forms.TimeField()
|
||||
duration = DurationField()
|
||||
face_to_face = forms.BooleanField(required=False)
|
||||
city = forms.CharField(max_length=255,required=False)
|
||||
country = forms.ChoiceField(choices=countries,required=False)
|
||||
|
@ -41,6 +139,8 @@ class InterimRequestForm(forms.Form):
|
|||
agenda = self.cleaned_data.get('agenda')
|
||||
agenda_note = self.cleaned_data.get('agenda_note')
|
||||
date = self.cleaned_data.get('date')
|
||||
time = self.cleaned_data.get('time')
|
||||
duration = self.cleaned_data.get('duration')
|
||||
group = self.cleaned_data.get('group')
|
||||
city = self.cleaned_data.get('city')
|
||||
country = self.cleaned_data.get('country')
|
||||
|
@ -51,8 +151,10 @@ class InterimRequestForm(forms.Form):
|
|||
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
|
||||
country=country,agenda_note=agenda_note,time_zone=timezone)
|
||||
schedule = Schedule.objects.create(meeting=meeting, owner=self.person, visible=True, public=True)
|
||||
slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=30 * 60,
|
||||
time=datetime.datetime.combine(datetime.date.today(), datetime.time(9, 30)))
|
||||
meeting.agenda = schedule
|
||||
meeting.save()
|
||||
slot = TimeSlot.objects.create(meeting=meeting, type_id="session", duration=duration,
|
||||
time=datetime.datetime.combine(date, time))
|
||||
session = Session.objects.create(meeting=meeting,
|
||||
group=group,
|
||||
requested_by=self.person,
|
||||
|
|
|
@ -389,6 +389,9 @@ class InterimTests(TestCase):
|
|||
def test_interim_request_submit(self):
|
||||
make_meeting_test_data()
|
||||
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)
|
||||
group = Group.objects.get(acronym='mars')
|
||||
city = 'San Francisco'
|
||||
country = 'US'
|
||||
|
@ -399,6 +402,8 @@ class InterimTests(TestCase):
|
|||
self.client.login(username="secretary", password="secretary+password")
|
||||
data = {'group':group.pk,
|
||||
'date':date.strftime("%Y-%m-%d"),
|
||||
'time':time.strftime('%H:%M'),
|
||||
'duration':'03:00:00',
|
||||
'city':city,
|
||||
'country':country,
|
||||
'timezone':timezone,
|
||||
|
@ -421,6 +426,9 @@ class InterimTests(TestCase):
|
|||
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)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue