Skip to content

Commit 6688d37

Browse files
committed
Merged in [16875] from rjsparks@nostrum.com:
Adds docs with blocking positions to the ADs my-documents page. Fixes ietf-tools#2800. - Legacy-Id: 16906 Note: SVN reference [16875] has been migrated to Git commit f7d4600
1 parent 04e342b commit 6688d37

4 files changed

Lines changed: 123 additions & 10 deletions

File tree

ietf/doc/factories.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from django.conf import settings
1515

16-
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent
16+
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType
1717
from ietf.group.models import Group
1818

1919
def draft_name_generator(type_id,group,n):
@@ -287,3 +287,34 @@ def state(obj, create, extracted, **kwargs):
287287
else:
288288
obj.state = State.objects.get(type_id='draft-iesg',slug='ad-eval')
289289
obj.save()
290+
291+
# All of these Ballot* factories are extremely skeletal. Flesh them out as needed by tests.
292+
class BallotTypeFactory(factory.DjangoModelFactory):
293+
class Meta:
294+
model = BallotType
295+
296+
doc_type_id = 'draft'
297+
slug = 'approve'
298+
299+
300+
class BallotDocEventFactory(DocEventFactory):
301+
class Meta:
302+
model = BallotDocEvent
303+
304+
ballot_type = factory.SubFactory(BallotTypeFactory)
305+
type = 'created_ballot'
306+
307+
class BallotPositionDocEventFactory(DocEventFactory):
308+
class Meta:
309+
model = BallotPositionDocEvent
310+
311+
type = 'changed_ballot_position'
312+
313+
# This isn't right - it needs to build a ballot for the same doc as this position
314+
# For now, deal with this in test code by building BallotDocEvent and BallotPositionDocEvent
315+
# separately and passing the same doc into thier factories.
316+
ballot = factory.SubFactory(BallotDocEventFactory)
317+
318+
ad = factory.SubFactory('ietf.person.factories.PersonFactory')
319+
pos_id = 'discuss'
320+

ietf/doc/tests.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,18 @@
2929
import debug # pyflakes:ignore
3030

3131
from ietf.doc.models import ( Document, DocAlias, DocRelationshipName, RelatedDocument, State,
32-
DocEvent, BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, NewRevisionDocEvent )
33-
from ietf.doc.factories import DocumentFactory, DocEventFactory, CharterFactory, ConflictReviewFactory, WgDraftFactory, IndividualDraftFactory, WgRfcFactory, IndividualRfcFactory, StateDocEventFactory
32+
DocEvent, BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, NewRevisionDocEvent, BallotType )
33+
from ietf.doc.factories import ( DocumentFactory, DocEventFactory, CharterFactory,
34+
ConflictReviewFactory, WgDraftFactory, IndividualDraftFactory, WgRfcFactory,
35+
IndividualRfcFactory, StateDocEventFactory, BallotPositionDocEventFactory,
36+
BallotDocEventFactory )
3437
from ietf.doc.utils import create_ballot_if_not_open
3538
from ietf.group.models import Group
36-
from ietf.group.factories import GroupFactory
39+
from ietf.group.factories import GroupFactory, RoleFactory
3740
from ietf.ipr.factories import HolderIprDisclosureFactory
3841
from ietf.meeting.models import Meeting, Session, SessionPresentation
3942
from ietf.meeting.factories import MeetingFactory, SessionFactory
40-
from ietf.name.models import SessionStatusName
43+
from ietf.name.models import SessionStatusName, BallotPositionName
4144
from ietf.person.models import Person
4245
from ietf.person.factories import PersonFactory
4346
from ietf.utils.mail import outbox
@@ -219,7 +222,7 @@ def test_frontpage(self):
219222
self.assertContains(r, "Document Search")
220223

221224
def test_docs_for_ad(self):
222-
ad = PersonFactory()
225+
ad = RoleFactory(name_id='ad',group__type_id='area',group__state_id='active').person
223226
draft = IndividualDraftFactory(ad=ad)
224227
draft.set_state(State.objects.get(type='draft-iesg', slug='lc'))
225228
rfc = IndividualDraftFactory(ad=ad)
@@ -231,14 +234,21 @@ def test_docs_for_ad(self):
231234
statchg.set_state(State.objects.get(type='statchg', slug='iesgeval'))
232235
charter = CharterFactory(ad=ad)
233236
charter.set_state(State.objects.get(type='charter', slug='iesgrev'))
234-
237+
238+
ballot_type = BallotType.objects.get(doc_type_id='draft',slug='approve')
239+
ballot = BallotDocEventFactory(ballot_type=ballot_type, doc__states=[('draft-iesg','iesg-eva')])
240+
discuss_pos = BallotPositionName.objects.get(slug='discuss')
241+
discuss_other = BallotPositionDocEventFactory(ballot=ballot, doc=ballot.doc, ad=ad, pos=discuss_pos)
242+
235243
r = self.client.get(urlreverse('ietf.doc.views_search.docs_for_ad', kwargs=dict(name=ad.full_name_as_key())))
236244
self.assertEqual(r.status_code, 200)
237245
self.assertContains(r, draft.name)
238246
self.assertContains(r, rfc.canonical_name())
239247
self.assertContains(r, conflrev.name)
240248
self.assertContains(r, statchg.name)
241249
self.assertContains(r, charter.name)
250+
251+
self.assertContains(r, discuss_other.doc.name)
242252

243253

244254
def test_drafts_in_last_call(self):

ietf/doc/views_search.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@
5252
import debug # pyflakes:ignore
5353

5454
from ietf.doc.models import ( Document, DocHistory, DocAlias, State,
55-
LastCallDocEvent, NewRevisionDocEvent, IESG_SUBSTATE_TAGS )
55+
LastCallDocEvent, NewRevisionDocEvent, IESG_SUBSTATE_TAGS, IESG_BALLOT_ACTIVE_STATES )
5656
from ietf.doc.fields import select2_id_doc_name_json
57-
from ietf.doc.utils import get_search_cache_key
57+
from ietf.doc.utils import get_search_cache_key, augment_events_with_revision
5858
from ietf.group.models import Group
5959
from ietf.idindex.index import active_drafts_index_by_group
6060
from ietf.name.models import DocTagName, DocTypeName, StreamName
@@ -415,8 +415,40 @@ def docs_for_ad(request, name):
415415
for d in results:
416416
d.search_heading = ad_dashboard_group(d)
417417
#
418+
# Additional content showing docs with blocking positions by this ad
419+
blocked_docs = []
420+
if ad in get_active_ads():
421+
possible_docs = Document.objects.filter(Q(states__type="draft-iesg",
422+
states__slug__in=IESG_BALLOT_ACTIVE_STATES) |
423+
Q(states__type="charter",
424+
states__slug__in=("intrev", "iesgrev")) |
425+
Q(states__type__in=("statchg", "conflrev"),
426+
states__slug__in=("iesgeval", "defer")),
427+
docevent__ballotpositiondocevent__pos__blocking=True,
428+
docevent__ballotpositiondocevent__ad=ad)
429+
for doc in possible_docs:
430+
ballot = doc.active_ballot()
431+
if not ballot:
432+
continue
433+
434+
blocking_positions = [p for p in ballot.all_positions() if p.pos.blocking]
435+
436+
if not blocking_positions or not any( p.ad==ad for p in blocking_positions ):
437+
continue
438+
439+
augment_events_with_revision(doc, blocking_positions)
440+
441+
doc.blocking_positions = blocking_positions
442+
doc.ballot = ballot
443+
444+
blocked_docs.append(doc)
445+
446+
# latest first
447+
if blocked_docs:
448+
blocked_docs.sort(key=lambda d: min(p.time for p in d.blocking_positions if p.ad==ad), reverse=True)
449+
418450
return render(request, 'doc/drafts_for_ad.html', {
419-
'form':form, 'docs':results, 'meta':meta, 'ad_name': ad.plain_name()
451+
'form':form, 'docs':results, 'meta':meta, 'ad_name': ad.plain_name(), 'blocked_docs': blocked_docs
420452
})
421453

422454
def drafts_in_last_call(request):

ietf/templates/doc/drafts_for_ad.html

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% extends "base.html" %}
22
{# Copyright The IETF Trust 2015, All Rights Reserved #}
33
{% load origin staticfiles %}
4+
{% load ietf_filters %}
45

56
{% block pagehead %}
67
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
@@ -10,10 +11,49 @@
1011

1112
{% block content %}
1213
{% origin %}
14+
{% if blocked_docs %}
15+
<h1>Blocking positions held by {{ ad_name }}</h1>
16+
<table class="table table-condensed table-striped tablesorter">
17+
<thead>
18+
<tr>
19+
<th>Document</th>
20+
<th>Status</th>
21+
<th>Responsible AD</th>
22+
<th>Discusses</th>
23+
</tr>
24+
</thead>
25+
26+
<tbody>
27+
{% for doc in blocked_docs %}
28+
<tr>
29+
<td>{{ doc.displayname_with_link }}</td>
30+
{% include "doc/search/status_columns.html" %}
31+
<td>{{ doc.ad|default:"" }}</td>
32+
<td>
33+
{% for p in doc.blocking_positions %}
34+
{{ p.ad }}
35+
({% if p.discuss_time %}{{ p.discuss_time|timesince_days }}{% endif %}
36+
days ago{% if doc.get_state_url != "rfc" and p.rev != doc.rev %}
37+
for -{{ p.rev }}{% endif %})<br>
38+
{% if p.old_ad %}
39+
</span>
40+
{% endif %}
41+
{% endfor %}
42+
</td>
43+
</tr>
44+
{% endfor %}
45+
</tbody>
46+
</table>
47+
{% endif %}
48+
1349
<h1>Documents for {{ ad_name }}</h1>
1450
{% include "doc/search/search_results.html" %}
1551
{% endblock %}
1652

53+
{% block morecss %}
54+
.is-blocking {box-shadow: 0 0 0 0 #000000;}
55+
{% endblock %}
56+
1757
{% block js %}
1858
<script src="{% static "jquery.tablesorter/js/jquery.tablesorter.combined.min.js" %}"></script>
1959
{% endblock %}

0 commit comments

Comments
 (0)