Skip to content

Commit 114ba0a

Browse files
committed
winding up: added ability to add drafts to a session while looking at the session.
- Legacy-Id: 10853
1 parent 4a12225 commit 114ba0a

5 files changed

Lines changed: 160 additions & 5 deletions

File tree

ietf/meeting/tests_views.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import datetime
44
import urlparse
55

6+
import debug # pyflakes:ignore
7+
68
from django.core.urlresolvers import reverse as urlreverse
79
from django.conf import settings
810

@@ -13,8 +15,10 @@
1315
from ietf.meeting.test_data import make_meeting_test_data
1416
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent
1517

18+
from ietf.person.factories import PersonFactory
1619
from ietf.group.factories import GroupFactory
1720
from ietf.meeting.factories import SessionFactory, SessionPresentationFactory
21+
from ietf.doc.factories import DocumentFactory
1822

1923
class MeetingTests(TestCase):
2024
def setUp(self):
@@ -338,8 +342,51 @@ def test_session_details(self):
338342
SessionPresentationFactory.create(session=session,document__type_id='slides')
339343
SessionPresentationFactory.create(session=session,document__type_id='agenda')
340344

341-
url = urlreverse("ietf.meeting.views.session_details", kwargs=dict(num=session.meeting.number, acronym=group.acronym))
345+
url = urlreverse('ietf.meeting.views.session_details', kwargs=dict(num=session.meeting.number, acronym=group.acronym))
342346
r = self.client.get(url)
343347
self.assertTrue(all([x in unicontent(r) for x in ('slides','agenda','minutes','draft')]))
344348
self.assertFalse('deleted' in unicontent(r))
345349

350+
def test_add_session_drafts(self):
351+
group = GroupFactory.create(type_id='wg',state_id='active')
352+
group_chair = PersonFactory.create()
353+
group.role_set.create(name_id='chair',person = group_chair, email = group_chair.email())
354+
session = SessionFactory.create(meeting__type_id='ietf',group=group, meeting__date=datetime.date.today()+datetime.timedelta(days=90))
355+
SessionPresentationFactory.create(session=session,document__type_id='draft',rev=None)
356+
old_draft = session.sessionpresentation_set.filter(document__type='draft').first().document
357+
new_draft = DocumentFactory(type_id='draft')
358+
359+
url = urlreverse('ietf.meeting.views.add_session_drafts', kwargs=dict(num=session.meeting.number, session_id=session.pk))
360+
361+
r = self.client.get(url)
362+
self.assertEqual(r.status_code, 404)
363+
364+
self.client.login(username="plain",password="plain+password")
365+
r = self.client.get(url)
366+
self.assertEqual(r.status_code, 404)
367+
368+
self.client.login(username=group_chair.user.username, password='%s+password'%group_chair.user.username)
369+
r = self.client.get(url)
370+
self.assertEqual(r.status_code, 200)
371+
self.assertTrue(old_draft.name in unicontent(r))
372+
373+
r = self.client.post(url,dict(drafts=[new_draft.name,old_draft.name]))
374+
self.assertTrue(r.status_code, 200)
375+
q=PyQuery(r.content)
376+
self.assertTrue(q('form .alert-danger:contains("Already linked:")'))
377+
378+
self.assertEqual(1,session.sessionpresentation_set.count())
379+
r = self.client.post(url,dict(drafts=[new_draft.name,]))
380+
self.assertTrue(r.status_code, 302)
381+
self.assertEqual(2,session.sessionpresentation_set.count())
382+
383+
session.meeting.date -= datetime.timedelta(days=180)
384+
session.meeting.save()
385+
r = self.client.get(url)
386+
self.assertEqual(r.status_code,404)
387+
self.client.login(username='secretary',password='secretary+password')
388+
r = self.client.get(url)
389+
self.assertEqual(r.status_code,200)
390+
q = PyQuery(r.content)
391+
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
392+

ietf/meeting/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
safe_for_all_meeting_types = [
1010
url(r'^session/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', views.session_details),
11+
url(r'^session/(?P<session_id>\d+)/drafts$', views.add_session_drafts),
1112
]
1213

1314
type_ietf_only_patterns = [

ietf/meeting/views.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import debug # pyflakes:ignore
1414

1515
from django import forms
16-
from django.shortcuts import render, redirect
16+
from django.shortcuts import render, redirect, get_object_or_404
1717
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
1818
from django.contrib import messages
1919
from django.core.urlresolvers import reverse
@@ -23,7 +23,7 @@
2323
from django.forms import ModelForm
2424
from django.views.decorators.csrf import ensure_csrf_cookie
2525

26-
from ietf.doc.models import Document, State
26+
from ietf.doc.models import Document, State, DocEvent
2727
from ietf.group.models import Group
2828
from ietf.group.utils import can_manage_materials
2929
from ietf.ietfauth.utils import role_required, has_role
@@ -39,6 +39,8 @@
3939
from ietf.utils.pipe import pipe
4040
from ietf.utils.pdf import pdf_pages
4141

42+
from ietf.doc.fields import SearchableDocumentsField
43+
4244
def materials(request, meeting_num=None):
4345
meeting = get_meeting(meeting_num)
4446

@@ -874,3 +876,45 @@ def sort_key(session):
874876
'can_manage_materials' : can_manage,
875877
'type_counter': type_counter,
876878
})
879+
880+
class SessionDraftsForm(forms.Form):
881+
drafts = SearchableDocumentsField(required=False)
882+
883+
def __init__(self, *args, **kwargs):
884+
self.already_linked = kwargs.pop('already_linked')
885+
super(self.__class__, self).__init__(*args, **kwargs)
886+
887+
def clean(self):
888+
selected = self.cleaned_data['drafts']
889+
problems = set(selected).intersection(set(self.already_linked))
890+
if problems:
891+
raise forms.ValidationError("Already linked: %s" % ', '.join([d.name for d in problems]))
892+
return self.cleaned_data
893+
894+
def add_session_drafts(request, session_id, num):
895+
# num is redundant, but we're dragging it along an artifact of where we are in the current URL structure
896+
session = get_object_or_404(Session,pk=session_id)
897+
if not session.can_manage_materials(request.user):
898+
raise Http404
899+
if session.is_material_submission_cutoff() and not has_role(request.user, "Secretariat"):
900+
raise Http404
901+
902+
already_linked = [sp.document for sp in session.sessionpresentation_set.filter(document__type_id='draft')]
903+
904+
if request.method == 'POST':
905+
form = SessionDraftsForm(request.POST,already_linked=already_linked)
906+
if form.is_valid():
907+
for draft in form.cleaned_data['drafts']:
908+
session.sessionpresentation_set.create(document=draft,rev=None)
909+
c = DocEvent(type="added_comment", doc=draft, by=request.user.person)
910+
c.desc = "Added to session: %s" % session
911+
c.save()
912+
return redirect('ietf.meeting.views.session_details', num=session.meeting.number, acronym=session.group.acronym)
913+
else:
914+
form = SessionDraftsForm(already_linked=already_linked)
915+
916+
return render(request, "meeting/add_session_drafts.html",
917+
{ 'session': session,
918+
'already_linked': session.sessionpresentation_set.filter(document__type_id='draft'),
919+
'form': form,
920+
})
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{% extends "base.html" %}
2+
{# Copyright The IETF Trust 2015, All Rights Reserved #}
3+
{% load origin staticfiles bootstrap3 %}
4+
5+
{% block title %}Add drafts to {{ session.meeting }} : {{ session.group.acronym }}{% endblock %}
6+
7+
{% block pagehead %}
8+
<link rel="stylesheet" href="{% static 'select2/select2.css' %}">
9+
<link rel="stylesheet" href="{% static 'select2-bootstrap-css/select2-bootstrap.min.css' %}">
10+
{% endblock %}
11+
12+
{% block content %}
13+
{% origin %}
14+
15+
<h1>Add drafts to {{ session.meeting }} : {{ session.group.acronym }}</h1>
16+
{% comment %} TODO: put the session name here or calculate the number at the meeting {% endcomment %}
17+
18+
{% if session.is_material_submission_cutoff %}
19+
<div class="alert alert-warning">The deadline for submission corrections has passed. This may affect published proceedings.</div>
20+
{% endif %}
21+
22+
<div class="alert alert-info">This form will link additional drafts to this session with a revision of "Current at time of presentation". For more fine grained control of versions, or to remove a draft from a session, adjust the sessions associated with a draft from the draft's main page.</div>
23+
<div class="panel panel-default">
24+
<div class="panel-heading">Drafts already linked to this sesssion</div>
25+
<div class="panel-body">
26+
<table class="table table-contensed table-striped">
27+
<tr>
28+
<th class="col-md-1">Revision</th>
29+
<th>Document</th>
30+
</tr>
31+
{% for sp in already_linked %}
32+
<tr>
33+
<td>{% if sp.rev %}-{{sp.rev}}{% else %}(current){% endif %}</td>
34+
<td>{{sp.document.title}} ({{sp.document.name}})</td>
35+
</tr>
36+
{% endfor %}
37+
</table>
38+
</div>
39+
</div>
40+
41+
<div class="panel panel-default">
42+
<div class="panel-heading">Additional drafts to link to this session</div>
43+
<div class="panel-body">
44+
<form method="post">
45+
{% csrf_token %}
46+
{% bootstrap_form form %}
47+
{% buttons %}
48+
<button class="btn btn-{% if session.is_material_submission_cutoff %}warning{% else %}primary{% endif %}" type="submit">Save</button>
49+
<a class="btn btn-default" href="{% url 'ietf.meeting.views.session_details' num=session.meeting.number acronym=session.group.acronym %}">Cancel</a>
50+
{% endbuttons %}
51+
</form>
52+
</div>
53+
</div>
54+
55+
{% endblock %}
56+
57+
{% block js %}
58+
<script src="{% static 'select2/select2.min.js' %}"></script>
59+
<script src="{% static 'ietf/js/select2-field.js' %}"></script>
60+
{% endblock %}

ietf/templates/meeting/session_details.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ <h2>{% if sessions|length > 1 %}Session {{ forloop.counter }} : {% endif %}{{ se
1515
{% if session.status.slug == 'sched' or session.status.slug == 'schedw' %}
1616
<div class="buttonlist">
1717
<a class="btn btn-default" href="{% url 'ietf.secr.proceedings.views.upload_unified' meeting_num=session.meeting.number acronym=session.group.acronym %}">
18-
Upload/Edit Materials
18+
Upload/Edit materials
19+
</a>
20+
<a class="btn btn-default" href="{% url 'ietf.meeting.views.add_session_drafts' session_id=session.pk num=session.meeting.number %}">
21+
Link additional drafts to session
1922
</a>
2023
{% if not type_counter.agenda %}
2124
<span class="label label-warning">This session does not yet have an agenda</span>
@@ -38,7 +41,7 @@ <h2>{% if sessions|length > 1 %}Session {{ forloop.counter }} : {% endif %}{{ se
3841
{% else %}
3942
{% url 'doc_view' name=pres.document.name as url %}
4043
{% endif %}
41-
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}-{{ pres.rev }})
44+
<a href="{{url}}">{{pres.document.title}} ({{ pres.document.name }}{% if pres.rev %}-{{ pres.rev }}{% endif %})
4245
</a>
4346
</td>
4447
</tr>

0 commit comments

Comments
 (0)