Skip to content

Commit 3f3e6f0

Browse files
committed
add edit view. refactor to use modelforms
- Legacy-Id: 11176
1 parent facead5 commit 3f3e6f0

12 files changed

Lines changed: 849 additions & 305 deletions

File tree

ietf/doc/templatetags/ietf_filters.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,3 +610,9 @@ def session_end_time(session):
610610
timeslot = session.official_timeslotassignment().timeslot
611611
return timeslot.time + timeslot.duration
612612

613+
@register.filter
614+
def format_timedelta(timedelta):
615+
s = timedelta.seconds
616+
hours, remainder = divmod(s, 3600)
617+
minutes, seconds = divmod(remainder, 60)
618+
return '{hours:02d}:{minutes:02d}'.format(hours=hours,minutes=minutes)

ietf/meeting/forms.py

Lines changed: 172 additions & 66 deletions
Large diffs are not rendered by default.

ietf/meeting/helpers.py

Lines changed: 159 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import debug # pyflakes:ignore
1717

1818
from ietf.doc.models import Document
19+
from ietf.doc.utils import get_document_content
1920
from ietf.group.models import Group
2021
from ietf.ietfauth.utils import has_role, user_is_person
2122
from ietf.liaisons.utils import get_person_for_user
@@ -290,67 +291,31 @@ def session_constraint_expire(request,session):
290291
# -------------------------------------------------
291292
# Interim Meeting Helpers
292293
# -------------------------------------------------
293-
def get_announcement_initial(meeting):
294-
'''Returns a dictionary suitable to initialize an InterimAnnouncementForm (Message ModelForm)'''
295-
group = meeting.session_set.first().group
296-
in_person = bool(meeting.city)
297-
initial = {}
298-
initial['to'] = settings.INTERIM_ANNOUNCE_TO_EMAIL
299-
initial['cc'] = group.list_email
300-
initial['frm'] = settings.INTERIM_ANNOUNCE_FROM_EMAIL
301-
if in_person:
302-
desc = 'Interim'
303-
else:
304-
desc = 'Virtual'
305-
initial['subject'] = '%s (%s) WG %s Meeting: %s' % (group.name,group.acronym,desc,meeting.date)
306-
body = render_to_string('meeting/interim_announcement.txt', locals())
307-
initial['body'] = body
308-
return initial
309294

310-
def get_earliest_session(session_formset):
311-
'''Return earliest InterimSessionForm from formset'''
312-
earliest = session_formset[0]
313-
if len(session_formset) == 1:
314-
return earliest
315-
for form in session_formset[1:]:
316-
date = form.cleaned_data.get('date')
317-
if date and date < earliest.cleaned_data.get('date'):
318-
earliest = form
319-
return earliest
320-
321-
def get_next_interim_number(group,date):
322-
sequence = Meeting.objects.filter(number__startswith='interim-%s-%s' % (date.year,group.acronym)).count() + 1
323-
return 'interim-%s-%s-%s' % (date.year,group.acronym,sequence)
324-
325-
def create_interim_meeting(group,date,city='',country='',timezone='UTC',person=None):
326-
'''Helper function to create interim meeting and associated schedule'''
327-
if not person:
328-
person = Person.objects.get(name="(System)")
329-
number = get_next_interim_number(group,date)
330-
meeting = Meeting.objects.create(number=number,type_id='interim',date=date,city=city,
331-
country=country,time_zone=timezone)
332-
schedule = Schedule.objects.create(meeting=meeting, owner=person, visible=True, public=True)
333-
meeting.agenda = schedule
334-
meeting.save()
335-
return meeting
336295

337-
def create_interim_meeting_from_forms(request_form,session_form):
338-
'''Create an Interim meeting, given an InterimRequestForm and InterimSessionForm'''
339-
group = request_form.cleaned_data.get('group')
340-
date = session_form.cleaned_data.get('date')
341-
city = session_form.cleaned_data.get('city')
342-
country = session_form.cleaned_data.get('country')
343-
timezone = session_form.cleaned_data.get('timezone')
344-
person = request_form.person
345-
return create_interim_meeting(group=group,date=date,city=city,country=country,timezone=timezone,person=person)
346-
347-
def assign_interim_session(session,time):
348-
'''Helper function to create a timeslot and assign the interim session'''
349-
slot = TimeSlot.objects.create(meeting=session.meeting, type_id="session",
350-
duration=session.requested_duration, time=time)
351-
SchedTimeSessAssignment.objects.create(timeslot=slot, session=session, schedule=session.meeting.agenda)
352-
353-
def can_approve_interim_request(meeting,user):
296+
def assign_interim_session(form):
297+
"""Helper function to create a timeslot and assign the interim session"""
298+
time = datetime.datetime.combine(
299+
form.cleaned_data['date'],
300+
form.cleaned_data['time'])
301+
session = form.instance
302+
if session.official_timeslotassignment():
303+
slot = session.official_timeslotassignment().timeslot
304+
slot.time = time
305+
slot.save()
306+
else:
307+
slot = TimeSlot.objects.create(
308+
meeting=session.meeting,
309+
type_id="session",
310+
duration=session.requested_duration,
311+
time=time)
312+
SchedTimeSessAssignment.objects.create(
313+
timeslot=slot,
314+
session=session,
315+
schedule=session.meeting.agenda)
316+
317+
318+
def can_approve_interim_request(meeting, user):
354319
'''Returns True if the user has permissions to approve an interim meeting request'''
355320
if meeting.type.slug != 'interim':
356321
return False
@@ -361,26 +326,29 @@ def can_approve_interim_request(meeting,user):
361326
if not session:
362327
return False
363328
group = session.group
364-
if group.type.slug == 'wg' and group.parent.role_set.filter(name='ad',person=person):
329+
if group.type.slug == 'wg' and group.parent.role_set.filter(name='ad', person=person):
365330
return True
366-
if group.type.slug == 'rg' and group.parent.role_set.filter(name='chair',person=person):
331+
if group.type.slug == 'rg' and group.parent.role_set.filter(name='chair', person=person):
367332
return True
368333
return False
369334

370-
def can_edit_interim_request(meeting,user):
335+
336+
def can_edit_interim_request(meeting, user):
371337
'''Returns True if the user can edit the interim meeting request'''
372-
373-
if can_approve_interim_request(meeting,user):
338+
339+
if can_approve_interim_request(meeting, user):
374340
return True
375-
341+
376342
return False
377343

344+
378345
def can_request_interim_meeting(user):
379-
if has_role(user, ('Secretariat','Area Director','WG Chair','IRTF Chair', 'RG Chair')):
346+
if has_role(user, ('Secretariat', 'Area Director', 'WG Chair', 'IRTF Chair', 'RG Chair')):
380347
return True
381348
return False
382349

383-
def can_view_interim_request(meeting,user):
350+
351+
def can_view_interim_request(meeting, user):
384352
'''Returns True if the user can see the pending interim request in the pending interim view'''
385353
if meeting.type.slug != 'interim':
386354
return False
@@ -395,6 +363,129 @@ def can_view_interim_request(meeting,user):
395363
return True
396364
if has_role(user, 'IRTF Chair') and group.type.slug == 'rg':
397365
return True
398-
if group.role_set.filter(name='chair',person=person):
366+
if group.role_set.filter(name='chair', person=person):
399367
return True
400368
return False
369+
370+
371+
def create_interim_meeting(group, date, city='', country='', timezone='UTC',
372+
person=None):
373+
"""Helper function to create interim meeting and associated schedule"""
374+
if not person:
375+
person = Person.objects.get(name='(System)')
376+
number = get_next_interim_number(group, date)
377+
meeting = Meeting.objects.create(
378+
number=number,
379+
type_id='interim',
380+
date=date,
381+
city=city,
382+
country=country,
383+
time_zone=timezone)
384+
schedule = Schedule.objects.create(
385+
meeting=meeting,
386+
owner=person,
387+
visible=True,
388+
public=True)
389+
meeting.agenda = schedule
390+
meeting.save()
391+
return meeting
392+
393+
394+
def get_announcement_initial(meeting):
395+
'''Returns a dictionary suitable to initialize an InterimAnnouncementForm (Message ModelForm)'''
396+
group = meeting.session_set.first().group
397+
in_person = bool(meeting.city)
398+
initial = {}
399+
initial['to'] = settings.INTERIM_ANNOUNCE_TO_EMAIL
400+
initial['cc'] = group.list_email
401+
initial['frm'] = settings.INTERIM_ANNOUNCE_FROM_EMAIL
402+
if in_person:
403+
desc = 'Interim'
404+
else:
405+
desc = 'Virtual'
406+
initial['subject'] = '%s (%s) WG %s Meeting: %s' % (group.name, group.acronym, desc, meeting.date)
407+
body = render_to_string('meeting/interim_announcement.txt', locals())
408+
initial['body'] = body
409+
return initial
410+
411+
412+
def get_earliest_session_date(formset):
413+
'''Return earliest date from InterimSession Formset'''
414+
return sorted([f.cleaned_data['date'] for f in formset.forms if f.cleaned_data.get('date')])[0]
415+
416+
417+
def get_interim_initial(meeting):
418+
'''Returns a dictionary suitable to initialize a InterimRequestForm'''
419+
initial = {}
420+
initial['group'] = meeting.session_set.first().group
421+
if meeting.city:
422+
initial['in_person'] = True
423+
else:
424+
initial['in_person'] = False
425+
if meeting.session_set.count() > 1:
426+
initial['meeting_type'] = 'multi-day'
427+
else:
428+
initial['meeting_type'] = 'single'
429+
if meeting.session_set.first().status.slug == 'apprw':
430+
initial['approved'] = False
431+
else:
432+
initial['approved'] = True
433+
return initial
434+
435+
436+
def get_interim_session_initial(meeting):
437+
'''Returns a list of dictionaries suitable to initialize a InterimSessionForm'''
438+
initials = []
439+
for session in meeting.session_set.all():
440+
initial = {}
441+
initial['date'] = session.official_timeslotassignment().timeslot.time
442+
initial['time'] = session.official_timeslotassignment().timeslot.time
443+
initial['duration'] = session.requested_duration
444+
initial['remote_instructions'] = session.remote_instructions
445+
initial['agenda_note'] = session.agenda_note
446+
doc = session.agenda()
447+
if doc:
448+
path = os.path.join(doc.get_file_path(), doc.filename_with_rev())
449+
initial['agenda'] = get_document_content(os.path.basename(path), path, markup=False)
450+
initials.append(initial)
451+
452+
return initials
453+
454+
455+
def is_meeting_approved(meeting):
456+
"""Returns True if the meeting is approved"""
457+
if meeting.session_set.first().status.slug == 'apprw':
458+
return False
459+
else:
460+
return True
461+
462+
463+
def get_next_interim_number(group, date):
464+
"""Returns a unique number to use for the next interim meeting for
465+
*group*"""
466+
meetings = Meeting.objects.filter(
467+
number__startswith='interim-{year}-{group}'.format(
468+
year=date.year,
469+
group=group.acronym))
470+
if meetings:
471+
sequences = [int(m.number.split('-')[-1]) for m in meetings]
472+
last_sequence = sorted(sequences)[-1]
473+
else:
474+
last_sequence = 0
475+
return 'interim-{year}-{group}-{sequence}'.format(
476+
year=date.year,
477+
group=group.acronym,
478+
sequence=last_sequence + 1)
479+
480+
481+
def sessions_post_save(forms):
482+
"""Helper function to perform various post save operations on each form of a
483+
InterimSessionModelForm formset"""
484+
485+
for form in forms:
486+
if not form.has_changed():
487+
continue
488+
if ('date' in form.changed_data) or ('time' in form.changed_data):
489+
assign_interim_session(form)
490+
if 'agenda' in form.changed_data:
491+
form.save_agenda()

ietf/meeting/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ def reverse_constraints(self):
995995
return Constraint.objects.filter(target=self.group, meeting=self.meeting).order_by('name__name')
996996

997997
def timeslotassignment_for_agenda(self, schedule):
998-
return self.timeslotassignments.filter(schedule=schedule)[0]
998+
return self.timeslotassignments.filter(schedule=schedule).first()
999999

10001000
def official_timeslotassignment(self):
10011001
return self.timeslotassignment_for_agenda(self.meeting.agenda)

ietf/meeting/test_data.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ def make_interim_meeting(group,date,status='sched'):
1616
attendees=10, requested_by=system_person,
1717
requested_duration=20, status_id=status,
1818
scheduled=datetime.datetime.now(),type_id="session")
19-
assign_interim_session(session,time)
19+
#assign_interim_session(session,time)
20+
slot = TimeSlot.objects.create(
21+
meeting=meeting,
22+
type_id="session",
23+
duration=session.requested_duration,
24+
time=time)
25+
SchedTimeSessAssignment.objects.create(
26+
timeslot=slot,
27+
session=session,
28+
schedule=session.meeting.agenda)
2029
return meeting
2130

2231
def make_meeting_test_data():

0 commit comments

Comments
 (0)