Skip to content

Commit fe17f6d

Browse files
committed
checkpoint: Allows adding a document to upcoming sessions
- Legacy-Id: 10849
1 parent 859f2ea commit fe17f6d

7 files changed

Lines changed: 148 additions & 38 deletions

File tree

ietf/doc/tests.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,14 +1002,8 @@ def test_edit_document_session(self):
10021002
q = PyQuery(response.content)
10031003
self.assertEqual(2,len(q('select#id_version option')))
10041004

1005-
# Simulate the cancel button
1006-
response = self.client.post(url,{})
1007-
self.assertEqual(response.status_code, 302)
1008-
self.assertEqual(doc.sessionpresentation_set.get(pk=sp.pk).rev,None)
1009-
10101005
self.assertEqual(1,doc.docevent_set.count())
10111006
response = self.client.post(url,{'version':'00','save':''})
1012-
response = self.client.post(url,{})
10131007
self.assertEqual(response.status_code, 302)
10141008
self.assertEqual(doc.sessionpresentation_set.get(pk=sp.pk).rev,'00')
10151009
self.assertEqual(2,doc.docevent_set.count())
@@ -1029,7 +1023,7 @@ def test_edit_document_session_after_proceedings_closed(self):
10291023
q=PyQuery(response.content)
10301024
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
10311025

1032-
def test_remove_document_self(self):
1026+
def test_remove_document_session(self):
10331027
doc = DocumentFactory.create()
10341028
sp = doc.sessionpresentation_set.create(session=self.future,rev=None)
10351029

@@ -1053,11 +1047,6 @@ def test_remove_document_self(self):
10531047
response = self.client.get(url)
10541048
self.assertEqual(response.status_code, 200)
10551049

1056-
# Simulate the cancel button
1057-
response = self.client.post(url,{})
1058-
self.assertEqual(response.status_code, 302)
1059-
self.assertTrue(doc.sessionpresentation_set.filter(pk=sp.pk).exists())
1060-
10611050
self.assertEqual(1,doc.docevent_set.count())
10621051
response = self.client.post(url,{'remove_session':''})
10631052
self.assertEqual(response.status_code, 302)
@@ -1078,3 +1067,26 @@ def test_remove_document_session_after_proceedings_closed(self):
10781067
self.assertEqual(response.status_code, 200)
10791068
q=PyQuery(response.content)
10801069
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
1070+
1071+
def test_add_document_session(self):
1072+
doc = DocumentFactory.create()
1073+
1074+
url = urlreverse('ietf.doc.views_doc.add_sessionpresentation',kwargs=dict(name=doc.name))
1075+
login_testing_unauthorized(self,self.group_chair.user.username,url)
1076+
response = self.client.get(url)
1077+
self.assertEqual(response.status_code,200)
1078+
1079+
response = self.client.post(url,{'session':0,'version':'current'})
1080+
self.assertEqual(response.status_code,200)
1081+
q=PyQuery(response.content)
1082+
self.assertTrue(q('.form-group.has-error'))
1083+
1084+
response = self.client.post(url,{'session':self.future.pk,'version':'bogus version'})
1085+
self.assertEqual(response.status_code,200)
1086+
q=PyQuery(response.content)
1087+
self.assertTrue(q('.form-group.has-error'))
1088+
1089+
self.assertEqual(1,doc.docevent_set.count())
1090+
response = self.client.post(url,{'session':self.future.pk,'version':'current'})
1091+
self.assertEqual(response.status_code,302)
1092+
self.assertEqual(2,doc.docevent_set.count())

ietf/doc/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from ietf.doc import views_doc
3939

4040
session_patterns = [
41+
url(r'^add$', views_doc.add_sessionpresentation),
4142
url(r'^(?P<session_id>\d+)/edit$', views_doc.edit_sessionpresentation),
4243
url(r'^(?P<session_id>\d+)/remove$', views_doc.remove_sessionpresentation),
4344
]

ietf/doc/views_doc.py

Lines changed: 95 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
from ietf.doc.forms import TelechatForm, NotifyForm
6161
from ietf.doc.mails import email_comment
6262
from ietf.mailtrigger.utils import gather_relevant_expansions
63+
from ietf.meeting.models import Session
6364

6465
def render_document_top(request, doc, tab, name):
6566
tabs = []
@@ -1091,14 +1092,15 @@ def email_aliases(request,name=''):
10911092

10921093
return render(request,'doc/email_aliases.html',{'aliases':aliases,'ietf_domain':settings.IETF_DOMAIN,'doc':doc})
10931094

1094-
class SessionPresentationForm(forms.Form):
1095+
class VersionForm(forms.Form):
10951096

1096-
version = forms.ChoiceField(required=False,
1097+
# TODO is required=False correct here?
1098+
version = forms.ChoiceField(required=True,
10971099
label='Which version of this document will be discussed at this session?')
10981100

10991101
def __init__(self, *args, **kwargs):
11001102
choices = kwargs.pop('choices')
1101-
super(SessionPresentationForm,self).__init__(*args,**kwargs)
1103+
super(VersionForm,self).__init__(*args,**kwargs)
11021104
self.fields['version'].choices = choices
11031105

11041106
def edit_sessionpresentation(request,name,session_id):
@@ -1116,20 +1118,17 @@ def edit_sessionpresentation(request,name,session_id):
11161118
initial = {'version' : sp.rev if sp.rev else 'current'}
11171119

11181120
if request.method == 'POST':
1119-
if 'save' in request.POST:
1120-
form = SessionPresentationForm(request.POST,choices=choices)
1121-
if form.is_valid():
1122-
new_selection = form.cleaned_data['version']
1123-
if initial['version'] != new_selection:
1124-
doc.sessionpresentation_set.filter(pk=sp.pk).update(rev=None if new_selection=='current' else new_selection)
1125-
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
1126-
c.desc = "Revision for session %s changed to %s" % (sp.session,new_selection)
1127-
c.save()
1128-
return redirect('ietf.doc.views_material.all_presentations', name=name)
1129-
else:
1121+
form = VersionForm(request.POST,choices=choices)
1122+
if form.is_valid():
1123+
new_selection = form.cleaned_data['version']
1124+
if initial['version'] != new_selection:
1125+
doc.sessionpresentation_set.filter(pk=sp.pk).update(rev=None if new_selection=='current' else new_selection)
1126+
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
1127+
c.desc = "Revision for session %s changed to %s" % (sp.session,new_selection)
1128+
c.save()
11301129
return redirect('ietf.doc.views_material.all_presentations', name=name)
11311130
else:
1132-
form = SessionPresentationForm(choices=choices,initial=initial)
1131+
form = VersionForm(choices=choices,initial=initial)
11331132

11341133
return render(request,'doc/edit_sessionpresentation.html', {'sp': sp, 'form': form })
11351134

@@ -1144,12 +1143,88 @@ def remove_sessionpresentation(request,name,session_id):
11441143
raise Http404
11451144

11461145
if request.method == 'POST':
1147-
if 'remove_session' in request.POST:
1148-
doc.sessionpresentation_set.filter(pk=sp.pk).delete()
1146+
doc.sessionpresentation_set.filter(pk=sp.pk).delete()
1147+
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
1148+
c.desc = "Removed from session: %s" % (sp.session)
1149+
c.save()
1150+
return redirect('ietf.doc.views_material.all_presentations', name=name)
1151+
1152+
return render(request,'doc/remove_sessionpresentation.html', {'sp': sp })
1153+
1154+
1155+
def get_upcoming_manageable_sessions(user):
1156+
1157+
# TODO: Move this into meeting.models or utils, or maybe person.models or utils - it doesn't depend on doc
1158+
# Find all the sessions for meetings that haven't ended that the user could affect
1159+
# This motif is also in Document.future_presentations - it would be nice to consolodate it somehow
1160+
1161+
# Consider adding an argument that has some Qs to append to the queryset
1162+
1163+
candidate_sessions = Session.objects.exclude(status__in=['canceled','disappr','notmeet','deleted']).filter(meeting__date__gte=datetime.date.today()-datetime.timedelta(days=15))
1164+
refined_candidates = [ sess for sess in candidate_sessions if sess.meeting.end_date()>=datetime.date.today()]
1165+
1166+
# Consider keeping this (put acronym=None back in argument list
1167+
#if acronym:
1168+
# refined_candidates = [ sess for sess in refined_candidates if sess.group.acronym==acronym]
1169+
1170+
return [ sess for sess in refined_candidates if can_manage_materials(user, sess.group) ]
1171+
1172+
def sort_sessions(sessions):
1173+
1174+
# Python sorts are stable since version 2,2, so this series results in a list sorted first
1175+
# by the meeting 'number', then by session's group acronym, then by scheduled time
1176+
# (or the time of the session request if the session isn't scheduled).
1177+
1178+
def time_sort_key(session):
1179+
official_sessions = session.timeslotassignments.filter(schedule=session.meeting.agenda)
1180+
if official_sessions:
1181+
return official_sessions.first().timeslot.time
1182+
else:
1183+
return session.requested
1184+
1185+
time_sorted = sorted(sessions,key=time_sort_key)
1186+
acronym_sorted = sorted(time_sorted,key=lambda x: x.group.acronym)
1187+
meeting_sorted = sorted(acronym_sorted,key=lambda x: x.meeting.number)
1188+
1189+
return meeting_sorted
1190+
1191+
class SessionChooserForm(forms.Form):
1192+
session = forms.ChoiceField(label="Which session should this document be added to?",required=True)
1193+
1194+
def __init__(self, *args, **kwargs):
1195+
choices = kwargs.pop('choices')
1196+
super(SessionChooserForm,self).__init__(*args,**kwargs)
1197+
self.fields['session'].choices = choices
1198+
1199+
@role_required("Secretariat","Area Director","WG Chair","WG Secretary","RG Chair","RG Secretary","IRTF Chair","Team Chair")
1200+
def add_sessionpresentation(request,name):
1201+
doc = get_object_or_404(Document, name=name)
1202+
1203+
version_choices = [(x,x) for x in doc.docevent_set.filter(type='new_revision').values_list('newrevisiondocevent__rev',flat=True)]
1204+
version_choices.insert(0,('current','Current at the time of the session'))
1205+
1206+
sessions = get_upcoming_manageable_sessions(request.user)
1207+
sessions = sort_sessions([s for s in sessions if not s.sessionpresentation_set.filter(document=doc).exists()])
1208+
if doc.group:
1209+
sessions = sorted(sessions,key=lambda x:0 if x.group==doc.group else 1)
1210+
1211+
session_choices = [(s.pk,unicode(s)) for s in sessions]
1212+
1213+
if request.method == 'POST':
1214+
version_form = VersionForm(request.POST,choices=version_choices)
1215+
session_form = SessionChooserForm(request.POST,choices=session_choices)
1216+
if version_form.is_valid() and session_form.is_valid():
1217+
session_id = session_form.cleaned_data['session']
1218+
version = version_form.cleaned_data['version']
1219+
rev = None if version=='current' else version
1220+
doc.sessionpresentation_set.create(session_id=session_id,rev=rev)
11491221
c = DocEvent(type="added_comment", doc=doc, by=request.user.person)
1150-
c.desc = "Removed from session: %s" % (sp.session)
1222+
c.desc = "%s to session: %s" % ('Added -%s'%rev if rev else 'Added', Session.objects.get(pk=session_id))
11511223
c.save()
1224+
return redirect('ietf.doc.views_material.all_presentations', name=name)
11521225

1153-
return redirect('ietf.doc.views_material.all_presentations', name=name)
1226+
else:
1227+
version_form = VersionForm(choices=version_choices,initial={'version':'current'})
1228+
session_form = SessionChooserForm(choices=session_choices)
11541229

1155-
return render(request,'doc/remove_sessionpresentation.html', {'sp': sp })
1230+
return render(request,'doc/add_sessionpresentation.html',{'doc':doc,'version_form':version_form,'session_form':session_form})
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{% extends "base.html" %}
2+
{# Copyright The IETF Trust 2015, All Rights Reserved #}
3+
{% load origin %}
4+
5+
{% load bootstrap3 %}
6+
7+
{% block title %}Add document to session{% endblock %}
8+
9+
{% block content %}
10+
{% origin %}
11+
<h1>Add document to session<br><small>{{doc.name}}<br>{{doc.title}}</small></h1>
12+
13+
<form method="post">
14+
{% csrf_token %}
15+
16+
{% bootstrap_form session_form %}
17+
{% bootstrap_form version_form %}
18+
19+
{% buttons %}
20+
<button class="btn btn-primary" type="submit" name="save">Save</button>
21+
<a class="btn btn-default" href="{% url 'ietf.doc.views_material.all_presentations' name=doc.name %}">Cancel</a>
22+
{% endbuttons %}
23+
24+
</form>
25+
{% endblock content %}

ietf/templates/doc/edit_sessionpresentation.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ <h1>Change document revision for session<br><small>{{sp.document.name}}<br>{{sp.
2121

2222
{% buttons %}
2323
<button class="btn btn-primary" type="submit" name="save">Save</button>
24-
<button class="btn btn-default">Cancel</button>
24+
<a class="btn btn-default" href="{% url 'ietf.doc.views_material.all_presentations' name=sp.document.name %}">Cancel</a>
2525
{% endbuttons %}
2626

2727
</form>

ietf/templates/doc/material/all_presentations.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,8 @@
99
<h1>Sessions linked to {{doc.name}}{% if doc.title %}<br><small>{{doc.title}}</small>{% endif %}</h1>
1010

1111
<div class="buttonlist" >
12-
{% comment TODO %}
13-
<a class="btn btn-default">Add doc to next session for this group</a>
14-
{% endcomment %}
1512
{% if user|has_role:"Secretariat,Area Director,WG Chair,WG Secretary,RG Chair,RG Secretary,IRTF Chair,Team Chair" %}
16-
<a class="btn btn-default" id="addsessionsbutton">Link to more sessions</a>
13+
<a class="btn btn-default" id="addsessionsbutton" href="{% url 'ietf.doc.views_doc.add_sessionpresentation' name=doc.name %}">Link to more sessions</a>
1714
{% else %}
1815
{{user}} failed the has_role check
1916
{% endif %}

ietf/templates/doc/remove_sessionpresentation.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ <h2>Session</h2>
2424
{% csrf_token %}
2525
{% buttons %}
2626
<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>
27-
<button type="submit" class="btn btn-default">Cancel</button>
27+
<a class="btn btn-default href="{% url 'ietf.doc.views_material.all_presentations' name=sp.document.name %}">Cancel</a>
2828
{% endbuttons %}
2929
</form>
3030

0 commit comments

Comments
 (0)