Skip to content

Commit e8d40c8

Browse files
committed
Show all sessions associated with a document.
Remove the day/seq urls from the materials tree. Allow sessionpresentation.rev to be None, meaning "current version". Streamlined workflows to focus on current versions of a draft as a default. Allow adding and editing sessionpresentations when looking at a specific document. Allow adding drafts when looking at a specific session. Add the meeting tab to 'team' groups. Refactored several utility classes and expanded on factories. Fixes ietf-tools#1908 and ietf-tools#1910. Commit ready for merge. - Legacy-Id: 10856
2 parents 8919f22 + a39f207 commit e8d40c8

27 files changed

Lines changed: 870 additions & 334 deletions

ietf/doc/factories.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import factory
2+
3+
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent
4+
from ietf.person.factories import PersonFactory
5+
6+
class DocumentFactory(factory.DjangoModelFactory):
7+
class Meta:
8+
model = Document
9+
10+
type_id = 'draft'
11+
title = factory.Faker('sentence',nb_words=6)
12+
rev = '00'
13+
group = None
14+
15+
@factory.lazy_attribute_sequence
16+
def name(self, n):
17+
return '%s-%s-%s-%s%d'%(
18+
self.type_id,
19+
'bogusperson',
20+
self.group.acronym if self.group else 'netherwhere',
21+
'musings',
22+
n,
23+
)
24+
25+
newrevisiondocevent = factory.RelatedFactory('ietf.doc.factories.NewRevisionDocEventFactory','doc')
26+
27+
class DocEventFactory(factory.DjangoModelFactory):
28+
class Meta:
29+
model = DocEvent
30+
31+
type = 'added_comment'
32+
by = factory.SubFactory(PersonFactory)
33+
doc = factory.SubFactory(DocumentFactory)
34+
desc = factory.Faker('sentence',nb_words=6)
35+
36+
class NewRevisionDocEventFactory(DocEventFactory):
37+
class Meta:
38+
model = NewRevisionDocEvent
39+
40+
type = 'new_revision'
41+
rev = '00'
42+
43+
@factory.lazy_attribute
44+
def desc(self):
45+
return 'New version available %s-%s'%(self.doc.name,self.rev)

ietf/doc/tests.py

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020
from ietf.doc.models import ( Document, DocAlias, DocRelationshipName, RelatedDocument, State,
2121
DocEvent, BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, NewRevisionDocEvent,
2222
save_document_in_history )
23+
from ietf.doc.factories import DocumentFactory
2324
from ietf.group.models import Group
25+
from ietf.group.factories import GroupFactory
2426
from ietf.meeting.models import Meeting, Session, SessionPresentation
27+
from ietf.meeting.factories import SessionFactory
2528
from ietf.name.models import SessionStatusName
2629
from ietf.person.models import Person
30+
from ietf.person.factories import PersonFactory
2731
from ietf.utils.mail import outbox
2832
from ietf.utils.test_data import make_test_data
2933
from ietf.utils.test_utils import login_testing_unauthorized, unicontent
@@ -904,3 +908,185 @@ def testExpansions(self):
904908
self.assertEqual(r.status_code, 200)
905909
self.assertTrue('draft-ietf-mars-test.all@ietf.org' in unicontent(r))
906910
self.assertTrue('ballot_saved' in unicontent(r))
911+
912+
class DocumentMeetingTests(TestCase):
913+
914+
def setUp(self):
915+
self.group = GroupFactory(type_id='wg',state_id='active')
916+
self.group_chair = PersonFactory()
917+
self.group.role_set.create(name_id='chair',person=self.group_chair,email=self.group_chair.email())
918+
919+
self.other_group = GroupFactory(type_id='wg',state_id='active')
920+
self.other_chair = PersonFactory()
921+
self.other_group.role_set.create(name_id='chair',person=self.other_chair,email=self.other_chair.email())
922+
923+
today = datetime.date.today()
924+
cut_days = settings.MEETING_MATERIALS_SUBMISSION_CORRECTION_DAYS
925+
self.past_cutoff = SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today-datetime.timedelta(days=1+cut_days))
926+
self.past = SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today-datetime.timedelta(days=cut_days/2))
927+
self.inprog = SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today-datetime.timedelta(days=1))
928+
self.future = SessionFactory.create(meeting__type_id='ietf',group=self.group,meeting__date=today+datetime.timedelta(days=90))
929+
self.interim = SessionFactory.create(meeting__type_id='interim',group=self.group,meeting__date=today+datetime.timedelta(days=45))
930+
931+
def test_view_document_meetings(self):
932+
doc = DocumentFactory.create()
933+
doc.sessionpresentation_set.create(session=self.inprog,rev=None)
934+
doc.sessionpresentation_set.create(session=self.interim,rev=None)
935+
936+
url = urlreverse('ietf.doc.views_doc.all_presentations', kwargs=dict(name=doc.name))
937+
response = self.client.get(url)
938+
self.assertEqual(response.status_code, 200)
939+
q = PyQuery(response.content)
940+
self.assertTrue(all([q(id) for id in ['#inprogressmeets','#futuremeets']]))
941+
self.assertFalse(any([q(id) for id in ['#pastmeets',]]))
942+
self.assertFalse(q('#addsessionsbutton'))
943+
self.assertFalse(q("a.btn:contains('Remove document')"))
944+
945+
doc.sessionpresentation_set.create(session=self.past_cutoff,rev=None)
946+
doc.sessionpresentation_set.create(session=self.past,rev=None)
947+
948+
self.client.login(username="secretary", password="secretary+password")
949+
response = self.client.get(url)
950+
self.assertEqual(response.status_code, 200)
951+
q = PyQuery(response.content)
952+
self.assertTrue(q('#addsessionsbutton'))
953+
self.assertEqual(1,len(q("#inprogressmeets a.btn-default:contains('Remove document')")))
954+
self.assertEqual(1,len(q("#futuremeets a.btn-default:contains('Remove document')")))
955+
self.assertEqual(1,len(q("#pastmeets a.btn-default:contains('Remove document')")))
956+
self.assertEqual(1,len(q("#pastmeets a.btn-warning:contains('Remove document')")))
957+
958+
self.client.login(username=self.group_chair.user.username,password='%s+password'%self.group_chair.user.username)
959+
response = self.client.get(url)
960+
self.assertEqual(response.status_code, 200)
961+
q = PyQuery(response.content)
962+
self.assertTrue(q('#addsessionsbutton'))
963+
self.assertEqual(1,len(q("#inprogressmeets a.btn-default:contains('Remove document')")))
964+
self.assertEqual(1,len(q("#futuremeets a.btn-default:contains('Remove document')")))
965+
self.assertEqual(1,len(q("#pastmeets a.btn-default:contains('Remove document')")))
966+
self.assertTrue(q('#pastmeets'))
967+
self.assertFalse(q("#pastmeets a.btn-warning:contains('Remove document')"))
968+
969+
self.client.login(username=self.other_chair.user.username,password='%s+password'%self.other_chair.user.username)
970+
response = self.client.get(url)
971+
self.assertEqual(response.status_code, 200)
972+
q = PyQuery(response.content)
973+
self.assertTrue(q('#addsessionsbutton'))
974+
self.assertTrue(all([q(id) for id in ['#futuremeets','#pastmeets','#inprogressmeets']]))
975+
self.assertFalse(q("#inprogressmeets a.btn:contains('Remove document')"))
976+
self.assertFalse(q("#futuremeets a.btn:contains('Remove document')"))
977+
self.assertFalse(q("#pastmeets a.btn:contains('Remove document')"))
978+
979+
def test_edit_document_session(self):
980+
doc = DocumentFactory.create()
981+
sp = doc.sessionpresentation_set.create(session=self.future,rev=None)
982+
983+
url = urlreverse('ietf.doc.views_doc.edit_sessionpresentation',kwargs=dict(name='no-such-doc',session_id=sp.session_id))
984+
response = self.client.get(url)
985+
self.assertEqual(response.status_code, 404)
986+
987+
url = urlreverse('ietf.doc.views_doc.edit_sessionpresentation',kwargs=dict(name=doc.name,session_id=0))
988+
response = self.client.get(url)
989+
self.assertEqual(response.status_code, 404)
990+
991+
url = urlreverse('ietf.doc.views_doc.edit_sessionpresentation',kwargs=dict(name=doc.name,session_id=sp.session_id))
992+
response = self.client.get(url)
993+
self.assertEqual(response.status_code, 404)
994+
995+
self.client.login(username=self.other_chair.user.username,password='%s+password'%self.other_chair.user.username)
996+
response = self.client.get(url)
997+
self.assertEqual(response.status_code, 404)
998+
999+
self.client.login(username=self.group_chair.user.username,password='%s+password'%self.group_chair.user.username)
1000+
response = self.client.get(url)
1001+
self.assertEqual(response.status_code, 200)
1002+
q = PyQuery(response.content)
1003+
self.assertEqual(2,len(q('select#id_version option')))
1004+
1005+
self.assertEqual(1,doc.docevent_set.count())
1006+
response = self.client.post(url,{'version':'00','save':''})
1007+
self.assertEqual(response.status_code, 302)
1008+
self.assertEqual(doc.sessionpresentation_set.get(pk=sp.pk).rev,'00')
1009+
self.assertEqual(2,doc.docevent_set.count())
1010+
1011+
def test_edit_document_session_after_proceedings_closed(self):
1012+
doc = DocumentFactory.create()
1013+
sp = doc.sessionpresentation_set.create(session=self.past_cutoff,rev=None)
1014+
1015+
url = urlreverse('ietf.doc.views_doc.edit_sessionpresentation',kwargs=dict(name=doc.name,session_id=sp.session_id))
1016+
self.client.login(username=self.group_chair.user.username,password='%s+password'%self.group_chair.user.username)
1017+
response = self.client.get(url)
1018+
self.assertEqual(response.status_code, 404)
1019+
1020+
self.client.login(username='secretary',password='secretary+password')
1021+
response = self.client.get(url)
1022+
self.assertEqual(response.status_code, 200)
1023+
q=PyQuery(response.content)
1024+
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
1025+
1026+
def test_remove_document_session(self):
1027+
doc = DocumentFactory.create()
1028+
sp = doc.sessionpresentation_set.create(session=self.future,rev=None)
1029+
1030+
url = urlreverse('ietf.doc.views_doc.remove_sessionpresentation',kwargs=dict(name='no-such-doc',session_id=sp.session_id))
1031+
response = self.client.get(url)
1032+
self.assertEqual(response.status_code, 404)
1033+
1034+
url = urlreverse('ietf.doc.views_doc.remove_sessionpresentation',kwargs=dict(name=doc.name,session_id=0))
1035+
response = self.client.get(url)
1036+
self.assertEqual(response.status_code, 404)
1037+
1038+
url = urlreverse('ietf.doc.views_doc.remove_sessionpresentation',kwargs=dict(name=doc.name,session_id=sp.session_id))
1039+
response = self.client.get(url)
1040+
self.assertEqual(response.status_code, 404)
1041+
1042+
self.client.login(username=self.other_chair.user.username,password='%s+password'%self.other_chair.user.username)
1043+
response = self.client.get(url)
1044+
self.assertEqual(response.status_code, 404)
1045+
1046+
self.client.login(username=self.group_chair.user.username,password='%s+password'%self.group_chair.user.username)
1047+
response = self.client.get(url)
1048+
self.assertEqual(response.status_code, 200)
1049+
1050+
self.assertEqual(1,doc.docevent_set.count())
1051+
response = self.client.post(url,{'remove_session':''})
1052+
self.assertEqual(response.status_code, 302)
1053+
self.assertFalse(doc.sessionpresentation_set.filter(pk=sp.pk).exists())
1054+
self.assertEqual(2,doc.docevent_set.count())
1055+
1056+
def test_remove_document_session_after_proceedings_closed(self):
1057+
doc = DocumentFactory.create()
1058+
sp = doc.sessionpresentation_set.create(session=self.past_cutoff,rev=None)
1059+
1060+
url = urlreverse('ietf.doc.views_doc.remove_sessionpresentation',kwargs=dict(name=doc.name,session_id=sp.session_id))
1061+
self.client.login(username=self.group_chair.user.username,password='%s+password'%self.group_chair.user.username)
1062+
response = self.client.get(url)
1063+
self.assertEqual(response.status_code, 404)
1064+
1065+
self.client.login(username='secretary',password='secretary+password')
1066+
response = self.client.get(url)
1067+
self.assertEqual(response.status_code, 200)
1068+
q=PyQuery(response.content)
1069+
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/tests_material.py

Lines changed: 2 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
from StringIO import StringIO
77
from pyquery import PyQuery
88

9+
import debug # pyflakes:ignore
10+
911
from django.conf import settings
1012
from django.core.urlresolvers import reverse as urlreverse
1113

1214
from ietf.doc.models import Document, State, DocAlias, NewRevisionDocEvent
13-
from ietf.doc.views_material import material_presentations, edit_material_presentations
1415
from ietf.group.models import Group
1516
from ietf.meeting.models import Meeting, Session, SessionPresentation
1617
from ietf.name.models import SessionStatusName
1718
from ietf.person.models import Person
1819
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent
1920
from ietf.utils.test_data import make_test_data
2021

21-
from ietf.meeting.test_data import make_meeting_test_data
2222

2323
class GroupMaterialTests(TestCase):
2424
def setUp(self):
@@ -173,67 +173,3 @@ def test_revise(self):
173173
with open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + ".txt")) as f:
174174
self.assertEqual(f.read(), content)
175175

176-
def test_material_presentations(self):
177-
doc = self.create_slides()
178-
meeting = make_meeting_test_data()
179-
meeting.session_set.filter(group__acronym='mars').update(group=doc.group)
180-
181-
url = urlreverse(material_presentations,kwargs=dict(name=doc.name))
182-
login_testing_unauthorized(self, "secretary", url)
183-
184-
r = self.client.get(url)
185-
self.assertEqual(r.status_code, 200)
186-
187-
url = urlreverse(material_presentations,kwargs=dict(name=doc.name,seq=1))
188-
r = self.client.get(url)
189-
self.assertEqual(r.status_code, 200)
190-
191-
when = meeting.agenda.assignments.filter(session__group__acronym='testteam').first().timeslot.time
192-
mdw = when.date().isoformat()
193-
dow = ['mon','tue','wed','thu','fri','sat','sun'][when.weekday()]
194-
195-
for kw in [ dict(),
196-
dict(seq=1),
197-
dict(week_day=dow),
198-
dict(week_day=dow,seq=1),
199-
dict(date=mdw),
200-
dict(date=mdw,seq=1),
201-
dict(date=mdw+'-0930'),
202-
dict(date=mdw+'-0930',seq=1),
203-
]:
204-
kw['name'] = doc.name
205-
kw['acronym'] = 'testteam'
206-
url = urlreverse(material_presentations,kwargs=kw)
207-
r = self.client.get(url)
208-
self.assertEqual(r.status_code, 200)
209-
210-
def test_edit_material_presentations(self):
211-
doc = self.create_slides()
212-
meeting = make_meeting_test_data()
213-
meeting.session_set.filter(group__acronym='mars').update(group=doc.group)
214-
215-
session = meeting.agenda.assignments.filter(session__group__acronym='testteam').first().session
216-
217-
url = urlreverse(edit_material_presentations,kwargs=dict(name=doc.name,acronym='testteam',seq=1))
218-
login_testing_unauthorized(self, "secretary", url)
219-
r = self.client.get(url)
220-
self.assertEqual(r.status_code, 200)
221-
222-
self.assertEqual(doc.sessionpresentation_set.count(),0)
223-
224-
# add the materials to a session
225-
r = self.client.post(url, dict(action="Save",version="00"))
226-
self.assertEqual(r.status_code, 302)
227-
self.assertEqual(doc.sessionpresentation_set.first().session , session)
228-
229-
# change the version
230-
r = self.client.post(url, dict(action="Save",version="01"))
231-
self.assertEqual(r.status_code, 302)
232-
self.assertEqual(doc.sessionpresentation_set.first().session , session)
233-
234-
# take the slides back off that meeting
235-
r = self.client.post(url, dict(action="Save",version="notpresented"))
236-
self.assertEqual(r.status_code, 302)
237-
self.assertEqual(doc.sessionpresentation_set.count(),0)
238-
239-

ietf/doc/urls.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
from ietf.doc import views_status_change
3838
from ietf.doc import views_doc
3939

40+
session_patterns = [
41+
url(r'^add$', views_doc.add_sessionpresentation),
42+
url(r'^(?P<session_id>\d+)/edit$', views_doc.edit_sessionpresentation),
43+
url(r'^(?P<session_id>\d+)/remove$', views_doc.remove_sessionpresentation),
44+
]
45+
4046
urlpatterns = patterns('',
4147
(r'^/?$', views_search.search),
4248
url(r'^(?P<name>[A-Za-z0-9\._\+\-]+)$', views_search.search_for_name, name="doc_search_for_name"),
@@ -112,5 +118,7 @@
112118
(r'^(?P<name>charter-[A-Za-z0-9._+-]+)/', include('ietf.doc.urls_charter')),
113119
(r'^(?P<name>[A-Za-z0-9._+-]+)/conflict-review/', include('ietf.doc.urls_conflict_review')),
114120
(r'^(?P<name>[A-Za-z0-9._+-]+)/status-change/', include('ietf.doc.urls_status_change')),
121+
url(r'^(?P<name>[A-Za-z0-9._+-]+)/meetings$', 'ietf.doc.views_doc.all_presentations', name="all_presentations"),
115122
(r'^(?P<name>[A-Za-z0-9._+-]+)/material/', include('ietf.doc.urls_material')),
123+
url(r'^(?P<name>[A-Za-z0-9._+-]+)/session/', include(session_patterns)),
116124
)

ietf/doc/urls_material.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,5 @@
22

33
urlpatterns = patterns('ietf.doc.views_material',
44
url(r'^(?P<action>state|title|abstract|revise)/$', "edit_material", name="material_edit"),
5-
url(r'^sessions/$', "material_presentations", name="material_presentations"),
6-
(r'^sessions/(?P<seq>\d+)/edit/$', "edit_material_presentations"),
7-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/edit/$', "edit_material_presentations"),
8-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/edit/$', "edit_material_presentations"),
9-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/edit/$', "edit_material_presentations"),
10-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/(?P<seq>\d+)/edit/$', "edit_material_presentations"),
11-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/edit/$', "edit_material_presentations"),
12-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/edit/$', "edit_material_presentations"),
13-
(r'^sessions/(?P<seq>\d+)/$', "material_presentations"),
14-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/$', "material_presentations"),
15-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<seq>\d+)/$', "material_presentations"),
16-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/$', "material_presentations"),
17-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<week_day>[a-zA-Z]+)/(?P<seq>\d+)/$', "material_presentations"),
18-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/$', "material_presentations"),
19-
(r'^sessions/(?P<acronym>[A-Za-z0-9_\-\+]+)/(?P<date>\d{4}-\d{2}-\d{2}(-\d{4})?)/(?P<seq>\d+)/$', "material_presentations"),
205
)
216

0 commit comments

Comments
 (0)