Merged in [16875] from rjsparks@nostrum.com:
Adds docs with blocking positions to the ADs my-documents page. Fixes #2800. - Legacy-Id: 16906 Note: SVN reference [16875] has been migrated to Git commit f7d4600371b3f2a3c92aa184b517ed4ebee3a118
This commit is contained in:
parent
04e342b3ce
commit
6688d37bb4
|
@ -13,7 +13,7 @@ if six.PY3:
|
|||
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent
|
||||
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, DocAlias, State, DocumentAuthor, StateDocEvent, BallotPositionDocEvent, BallotDocEvent, BallotType
|
||||
from ietf.group.models import Group
|
||||
|
||||
def draft_name_generator(type_id,group,n):
|
||||
|
@ -287,3 +287,34 @@ class StateDocEventFactory(DocEventFactory):
|
|||
else:
|
||||
obj.state = State.objects.get(type_id='draft-iesg',slug='ad-eval')
|
||||
obj.save()
|
||||
|
||||
# All of these Ballot* factories are extremely skeletal. Flesh them out as needed by tests.
|
||||
class BallotTypeFactory(factory.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = BallotType
|
||||
|
||||
doc_type_id = 'draft'
|
||||
slug = 'approve'
|
||||
|
||||
|
||||
class BallotDocEventFactory(DocEventFactory):
|
||||
class Meta:
|
||||
model = BallotDocEvent
|
||||
|
||||
ballot_type = factory.SubFactory(BallotTypeFactory)
|
||||
type = 'created_ballot'
|
||||
|
||||
class BallotPositionDocEventFactory(DocEventFactory):
|
||||
class Meta:
|
||||
model = BallotPositionDocEvent
|
||||
|
||||
type = 'changed_ballot_position'
|
||||
|
||||
# This isn't right - it needs to build a ballot for the same doc as this position
|
||||
# For now, deal with this in test code by building BallotDocEvent and BallotPositionDocEvent
|
||||
# separately and passing the same doc into thier factories.
|
||||
ballot = factory.SubFactory(BallotDocEventFactory)
|
||||
|
||||
ad = factory.SubFactory('ietf.person.factories.PersonFactory')
|
||||
pos_id = 'discuss'
|
||||
|
||||
|
|
|
@ -29,15 +29,18 @@ from tastypie.test import ResourceTestCaseMixin
|
|||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import ( Document, DocAlias, DocRelationshipName, RelatedDocument, State,
|
||||
DocEvent, BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, NewRevisionDocEvent )
|
||||
from ietf.doc.factories import DocumentFactory, DocEventFactory, CharterFactory, ConflictReviewFactory, WgDraftFactory, IndividualDraftFactory, WgRfcFactory, IndividualRfcFactory, StateDocEventFactory
|
||||
DocEvent, BallotPositionDocEvent, LastCallDocEvent, WriteupDocEvent, NewRevisionDocEvent, BallotType )
|
||||
from ietf.doc.factories import ( DocumentFactory, DocEventFactory, CharterFactory,
|
||||
ConflictReviewFactory, WgDraftFactory, IndividualDraftFactory, WgRfcFactory,
|
||||
IndividualRfcFactory, StateDocEventFactory, BallotPositionDocEventFactory,
|
||||
BallotDocEventFactory )
|
||||
from ietf.doc.utils import create_ballot_if_not_open
|
||||
from ietf.group.models import Group
|
||||
from ietf.group.factories import GroupFactory
|
||||
from ietf.group.factories import GroupFactory, RoleFactory
|
||||
from ietf.ipr.factories import HolderIprDisclosureFactory
|
||||
from ietf.meeting.models import Meeting, Session, SessionPresentation
|
||||
from ietf.meeting.factories import MeetingFactory, SessionFactory
|
||||
from ietf.name.models import SessionStatusName
|
||||
from ietf.name.models import SessionStatusName, BallotPositionName
|
||||
from ietf.person.models import Person
|
||||
from ietf.person.factories import PersonFactory
|
||||
from ietf.utils.mail import outbox
|
||||
|
@ -219,7 +222,7 @@ class SearchTests(TestCase):
|
|||
self.assertContains(r, "Document Search")
|
||||
|
||||
def test_docs_for_ad(self):
|
||||
ad = PersonFactory()
|
||||
ad = RoleFactory(name_id='ad',group__type_id='area',group__state_id='active').person
|
||||
draft = IndividualDraftFactory(ad=ad)
|
||||
draft.set_state(State.objects.get(type='draft-iesg', slug='lc'))
|
||||
rfc = IndividualDraftFactory(ad=ad)
|
||||
|
@ -231,7 +234,12 @@ class SearchTests(TestCase):
|
|||
statchg.set_state(State.objects.get(type='statchg', slug='iesgeval'))
|
||||
charter = CharterFactory(ad=ad)
|
||||
charter.set_state(State.objects.get(type='charter', slug='iesgrev'))
|
||||
|
||||
|
||||
ballot_type = BallotType.objects.get(doc_type_id='draft',slug='approve')
|
||||
ballot = BallotDocEventFactory(ballot_type=ballot_type, doc__states=[('draft-iesg','iesg-eva')])
|
||||
discuss_pos = BallotPositionName.objects.get(slug='discuss')
|
||||
discuss_other = BallotPositionDocEventFactory(ballot=ballot, doc=ballot.doc, ad=ad, pos=discuss_pos)
|
||||
|
||||
r = self.client.get(urlreverse('ietf.doc.views_search.docs_for_ad', kwargs=dict(name=ad.full_name_as_key())))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertContains(r, draft.name)
|
||||
|
@ -239,6 +247,8 @@ class SearchTests(TestCase):
|
|||
self.assertContains(r, conflrev.name)
|
||||
self.assertContains(r, statchg.name)
|
||||
self.assertContains(r, charter.name)
|
||||
|
||||
self.assertContains(r, discuss_other.doc.name)
|
||||
|
||||
|
||||
def test_drafts_in_last_call(self):
|
||||
|
|
|
@ -52,9 +52,9 @@ from django.utils.cache import _generate_cache_key # type: ignore (FIXME: remove
|
|||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import ( Document, DocHistory, DocAlias, State,
|
||||
LastCallDocEvent, NewRevisionDocEvent, IESG_SUBSTATE_TAGS )
|
||||
LastCallDocEvent, NewRevisionDocEvent, IESG_SUBSTATE_TAGS, IESG_BALLOT_ACTIVE_STATES )
|
||||
from ietf.doc.fields import select2_id_doc_name_json
|
||||
from ietf.doc.utils import get_search_cache_key
|
||||
from ietf.doc.utils import get_search_cache_key, augment_events_with_revision
|
||||
from ietf.group.models import Group
|
||||
from ietf.idindex.index import active_drafts_index_by_group
|
||||
from ietf.name.models import DocTagName, DocTypeName, StreamName
|
||||
|
@ -415,8 +415,40 @@ def docs_for_ad(request, name):
|
|||
for d in results:
|
||||
d.search_heading = ad_dashboard_group(d)
|
||||
#
|
||||
# Additional content showing docs with blocking positions by this ad
|
||||
blocked_docs = []
|
||||
if ad in get_active_ads():
|
||||
possible_docs = Document.objects.filter(Q(states__type="draft-iesg",
|
||||
states__slug__in=IESG_BALLOT_ACTIVE_STATES) |
|
||||
Q(states__type="charter",
|
||||
states__slug__in=("intrev", "iesgrev")) |
|
||||
Q(states__type__in=("statchg", "conflrev"),
|
||||
states__slug__in=("iesgeval", "defer")),
|
||||
docevent__ballotpositiondocevent__pos__blocking=True,
|
||||
docevent__ballotpositiondocevent__ad=ad)
|
||||
for doc in possible_docs:
|
||||
ballot = doc.active_ballot()
|
||||
if not ballot:
|
||||
continue
|
||||
|
||||
blocking_positions = [p for p in ballot.all_positions() if p.pos.blocking]
|
||||
|
||||
if not blocking_positions or not any( p.ad==ad for p in blocking_positions ):
|
||||
continue
|
||||
|
||||
augment_events_with_revision(doc, blocking_positions)
|
||||
|
||||
doc.blocking_positions = blocking_positions
|
||||
doc.ballot = ballot
|
||||
|
||||
blocked_docs.append(doc)
|
||||
|
||||
# latest first
|
||||
if blocked_docs:
|
||||
blocked_docs.sort(key=lambda d: min(p.time for p in d.blocking_positions if p.ad==ad), reverse=True)
|
||||
|
||||
return render(request, 'doc/drafts_for_ad.html', {
|
||||
'form':form, 'docs':results, 'meta':meta, 'ad_name': ad.plain_name()
|
||||
'form':form, 'docs':results, 'meta':meta, 'ad_name': ad.plain_name(), 'blocked_docs': blocked_docs
|
||||
})
|
||||
|
||||
def drafts_in_last_call(request):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2015, All Rights Reserved #}
|
||||
{% load origin staticfiles %}
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" href="{% static "jquery.tablesorter/css/theme.bootstrap.min.css" %}">
|
||||
|
@ -10,10 +11,49 @@
|
|||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
{% if blocked_docs %}
|
||||
<h1>Blocking positions held by {{ ad_name }}</h1>
|
||||
<table class="table table-condensed table-striped tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Document</th>
|
||||
<th>Status</th>
|
||||
<th>Responsible AD</th>
|
||||
<th>Discusses</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for doc in blocked_docs %}
|
||||
<tr>
|
||||
<td>{{ doc.displayname_with_link }}</td>
|
||||
{% include "doc/search/status_columns.html" %}
|
||||
<td>{{ doc.ad|default:"" }}</td>
|
||||
<td>
|
||||
{% for p in doc.blocking_positions %}
|
||||
{{ p.ad }}
|
||||
({% if p.discuss_time %}{{ p.discuss_time|timesince_days }}{% endif %}
|
||||
days ago{% if doc.get_state_url != "rfc" and p.rev != doc.rev %}
|
||||
for -{{ p.rev }}{% endif %})<br>
|
||||
{% if p.old_ad %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<h1>Documents for {{ ad_name }}</h1>
|
||||
{% include "doc/search/search_results.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
.is-blocking {box-shadow: 0 0 0 0 #000000;}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{% static "jquery.tablesorter/js/jquery.tablesorter.combined.min.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue