checkpoint: Allows adding a document to upcoming sessions

- Legacy-Id: 10849
This commit is contained in:
Robert Sparks 2016-02-19 23:13:23 +00:00
parent 859f2ead3d
commit fe17f6d87b
7 changed files with 149 additions and 39 deletions

View file

@ -1002,14 +1002,8 @@ class DocumentMeetingTests(TestCase):
q = PyQuery(response.content)
self.assertEqual(2,len(q('select#id_version option')))
# Simulate the cancel button
response = self.client.post(url,{})
self.assertEqual(response.status_code, 302)
self.assertEqual(doc.sessionpresentation_set.get(pk=sp.pk).rev,None)
self.assertEqual(1,doc.docevent_set.count())
response = self.client.post(url,{'version':'00','save':''})
response = self.client.post(url,{})
self.assertEqual(response.status_code, 302)
self.assertEqual(doc.sessionpresentation_set.get(pk=sp.pk).rev,'00')
self.assertEqual(2,doc.docevent_set.count())
@ -1029,7 +1023,7 @@ class DocumentMeetingTests(TestCase):
q=PyQuery(response.content)
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
def test_remove_document_self(self):
def test_remove_document_session(self):
doc = DocumentFactory.create()
sp = doc.sessionpresentation_set.create(session=self.future,rev=None)
@ -1053,11 +1047,6 @@ class DocumentMeetingTests(TestCase):
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
# Simulate the cancel button
response = self.client.post(url,{})
self.assertEqual(response.status_code, 302)
self.assertTrue(doc.sessionpresentation_set.filter(pk=sp.pk).exists())
self.assertEqual(1,doc.docevent_set.count())
response = self.client.post(url,{'remove_session':''})
self.assertEqual(response.status_code, 302)
@ -1078,3 +1067,26 @@ class DocumentMeetingTests(TestCase):
self.assertEqual(response.status_code, 200)
q=PyQuery(response.content)
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
def test_add_document_session(self):
doc = DocumentFactory.create()
url = urlreverse('ietf.doc.views_doc.add_sessionpresentation',kwargs=dict(name=doc.name))
login_testing_unauthorized(self,self.group_chair.user.username,url)
response = self.client.get(url)
self.assertEqual(response.status_code,200)
response = self.client.post(url,{'session':0,'version':'current'})
self.assertEqual(response.status_code,200)
q=PyQuery(response.content)
self.assertTrue(q('.form-group.has-error'))
response = self.client.post(url,{'session':self.future.pk,'version':'bogus version'})
self.assertEqual(response.status_code,200)
q=PyQuery(response.content)
self.assertTrue(q('.form-group.has-error'))
self.assertEqual(1,doc.docevent_set.count())
response = self.client.post(url,{'session':self.future.pk,'version':'current'})
self.assertEqual(response.status_code,302)
self.assertEqual(2,doc.docevent_set.count())

View file

@ -38,6 +38,7 @@ from ietf.doc import views_status_change
from ietf.doc import views_doc
session_patterns = [
url(r'^add$', views_doc.add_sessionpresentation),
url(r'^(?P<session_id>\d+)/edit$', views_doc.edit_sessionpresentation),
url(r'^(?P<session_id>\d+)/remove$', views_doc.remove_sessionpresentation),
]

View file

@ -60,6 +60,7 @@ from ietf.utils.history import find_history_active_at
from ietf.doc.forms import TelechatForm, NotifyForm
from ietf.doc.mails import email_comment
from ietf.mailtrigger.utils import gather_relevant_expansions
from ietf.meeting.models import Session
def render_document_top(request, doc, tab, name):
tabs = []
@ -1091,14 +1092,15 @@ def email_aliases(request,name=''):
return render(request,'doc/email_aliases.html',{'aliases':aliases,'ietf_domain':settings.IETF_DOMAIN,'doc':doc})
class SessionPresentationForm(forms.Form):
class VersionForm(forms.Form):
version = forms.ChoiceField(required=False,
# TODO is required=False correct here?
version = forms.ChoiceField(required=True,
label='Which version of this document will be discussed at this session?')
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
super(SessionPresentationForm,self).__init__(*args,**kwargs)
super(VersionForm,self).__init__(*args,**kwargs)
self.fields['version'].choices = choices
def edit_sessionpresentation(request,name,session_id):
@ -1116,20 +1118,17 @@ def edit_sessionpresentation(request,name,session_id):
initial = {'version' : sp.rev if sp.rev else 'current'}
if request.method == 'POST':
if 'save' in request.POST:
form = SessionPresentationForm(request.POST,choices=choices)
if form.is_valid():
new_selection = form.cleaned_data['version']
if initial['version'] != new_selection:
doc.sessionpresentation_set.filter(pk=sp.pk).update(rev=None if new_selection=='current' else new_selection)
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
c.desc = "Revision for session %s changed to %s" % (sp.session,new_selection)
c.save()
return redirect('ietf.doc.views_material.all_presentations', name=name)
else:
form = VersionForm(request.POST,choices=choices)
if form.is_valid():
new_selection = form.cleaned_data['version']
if initial['version'] != new_selection:
doc.sessionpresentation_set.filter(pk=sp.pk).update(rev=None if new_selection=='current' else new_selection)
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
c.desc = "Revision for session %s changed to %s" % (sp.session,new_selection)
c.save()
return redirect('ietf.doc.views_material.all_presentations', name=name)
else:
form = SessionPresentationForm(choices=choices,initial=initial)
form = VersionForm(choices=choices,initial=initial)
return render(request,'doc/edit_sessionpresentation.html', {'sp': sp, 'form': form })
@ -1144,12 +1143,88 @@ def remove_sessionpresentation(request,name,session_id):
raise Http404
if request.method == 'POST':
if 'remove_session' in request.POST:
doc.sessionpresentation_set.filter(pk=sp.pk).delete()
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
c.desc = "Removed from session: %s" % (sp.session)
c.save()
doc.sessionpresentation_set.filter(pk=sp.pk).delete()
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
c.desc = "Removed from session: %s" % (sp.session)
c.save()
return redirect('ietf.doc.views_material.all_presentations', name=name)
return render(request,'doc/remove_sessionpresentation.html', {'sp': sp })
def get_upcoming_manageable_sessions(user):
# TODO: Move this into meeting.models or utils, or maybe person.models or utils - it doesn't depend on doc
# Find all the sessions for meetings that haven't ended that the user could affect
# This motif is also in Document.future_presentations - it would be nice to consolodate it somehow
# Consider adding an argument that has some Qs to append to the queryset
candidate_sessions = Session.objects.exclude(status__in=['canceled','disappr','notmeet','deleted']).filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15))
refined_candidates = [ sess for sess in candidate_sessions if sess.meeting.end_date()>=datetime.date.today()]
# Consider keeping this (put acronym=None back in argument list
#if acronym:
# refined_candidates = [ sess for sess in refined_candidates if sess.group.acronym==acronym]
return [ sess for sess in refined_candidates if can_manage_materials(user, sess.group) ]
def sort_sessions(sessions):
# Python sorts are stable since version 2,2, so this series results in a list sorted first
# by the meeting 'number', then by session's group acronym, then by scheduled time
# (or the time of the session request if the session isn't scheduled).
def time_sort_key(session):
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
if official_sessions:
return official_sessions.first().timeslot.time
else:
return session.requested
time_sorted = sorted(sessions,key=time_sort_key)
acronym_sorted = sorted(time_sorted,key=lambda x: x.group.acronym)
meeting_sorted = sorted(acronym_sorted,key=lambda x: x.meeting.number)
return meeting_sorted
class SessionChooserForm(forms.Form):
session = forms.ChoiceField(label="Which session should this document be added to?",required=True)
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
super(SessionChooserForm,self).__init__(*args,**kwargs)
self.fields['session'].choices = choices
@role_required("Secretariat","Area Director","WG Chair","WG Secretary","RG Chair","RG Secretary","IRTF Chair","Team Chair")
def add_sessionpresentation(request,name):
doc = get_object_or_404(Document, name=name)
version_choices = [(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)]
version_choices.insert(0,('current','Current at the time of the session'))
sessions = get_upcoming_manageable_sessions(request.user)
sessions = sort_sessions([s for s in sessions if not s.sessionpresentation_set.filter(document=doc).exists()])
if doc.group:
sessions = sorted(sessions,key=lambda x:0 if x.group==doc.group else 1)
session_choices = [(s.pk,unicode(s)) for s in sessions]
if request.method == 'POST':
version_form = VersionForm(request.POST,choices=version_choices)
session_form = SessionChooserForm(request.POST,choices=session_choices)
if version_form.is_valid() and session_form.is_valid():
session_id = session_form.cleaned_data['session']
version = version_form.cleaned_data['version']
rev = None if version=='current' else version
doc.sessionpresentation_set.create(session_id=session_id,rev=rev)
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
c.desc = "%s to session: %s" % ('Added -%s'%rev if rev else 'Added', Session.objects.get(pk=session_id))
c.save()
return redirect('ietf.doc.views_material.all_presentations', name=name)
else:
version_form = VersionForm(choices=version_choices,initial={'version':'current'})
session_form = SessionChooserForm(choices=session_choices)
return render(request,'doc/add_sessionpresentation.html',{'doc':doc,'version_form':version_form,'session_form':session_form})

View file

@ -0,0 +1,25 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load bootstrap3 %}
{% block title %}Add document to session{% endblock %}
{% block content %}
{% origin %}
<h1>Add document to session<br><small>{{doc.name}}<br>{{doc.title}}</small></h1>
<form method="post">
{% csrf_token %}
{% bootstrap_form session_form %}
{% bootstrap_form version_form %}
{% buttons %}
<button class="btn btn-primary" type="submit" name="save">Save</button>
<a class="btn btn-default" href="{% url 'ietf.doc.views_material.all_presentations' name=doc.name %}">Cancel</a>
{% endbuttons %}
</form>
{% endblock content %}

View file

@ -21,7 +21,7 @@
{% buttons %}
<button class="btn btn-primary" type="submit" name="save">Save</button>
<button class="btn btn-default">Cancel</button>
<a class="btn btn-default" href="{% url 'ietf.doc.views_material.all_presentations' name=sp.document.name %}">Cancel</a>
{% endbuttons %}
</form>

View file

@ -9,11 +9,8 @@
<h1>Sessions linked to {{doc.name}}{% if doc.title %}<br><small>{{doc.title}}</small>{% endif %}</h1>
<div class="buttonlist" >
{% comment TODO %}
<a class="btn btn-default">Add doc to next session for this group</a>
{% endcomment %}
{% if user|has_role:"Secretariat,Area Director,WG Chair,WG Secretary,RG Chair,RG Secretary,IRTF Chair,Team Chair" %}
<a class="btn btn-default" id="addsessionsbutton">Link to more sessions</a>
<a class="btn btn-default" id="addsessionsbutton" href="{% url 'ietf.doc.views_doc.add_sessionpresentation' name=doc.name %}">Link to more sessions</a>
{% else %}
{{user}} failed the has_role check
{% endif %}

View file

@ -24,7 +24,7 @@
{% csrf_token %}
{% buttons %}
<button type="submit" class="btn btn-{% if sp.session.is_material_submission_cutoff %}warning{% else %}primary{% endif %}" name="remove_session">Remove document from session</button>
<button type="submit" class="btn btn-default">Cancel</button>
<a class="btn btn-default href="{% url 'ietf.doc.views_material.all_presentations' name=sp.document.name %}">Cancel</a>
{% endbuttons %}
</form>