Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pages left to ballot on #7516

Merged
merged 13 commits into from
Aug 9, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ datatracker.sublime-workspace
/docker/docker-compose.extend-custom.yml
/env
/ghostdriver.log
/geckodriver.log
/htmlcov
/ietf/static/dist-neue
/latest-coverage.json
Expand Down
68 changes: 64 additions & 4 deletions ietf/iesg/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from ietf.doc.models import DocEvent, BallotPositionDocEvent, TelechatDocEvent
from ietf.doc.models import Document, State, RelatedDocument
from ietf.doc.factories import WgDraftFactory, IndividualDraftFactory, ConflictReviewFactory, BaseDocumentFactory, CharterFactory, WgRfcFactory, IndividualRfcFactory
from ietf.doc.factories import BallotDocEventFactory, BallotPositionDocEventFactory, TelechatDocEventFactory, WgDraftFactory, IndividualDraftFactory, ConflictReviewFactory, BaseDocumentFactory, CharterFactory, WgRfcFactory, IndividualRfcFactory
from ietf.doc.utils import create_ballot_if_not_open
from ietf.group.factories import RoleFactory, GroupFactory, DatedGroupMilestoneFactory, DatelessGroupMilestoneFactory
from ietf.group.models import Group, GroupMilestone, Role
Expand All @@ -30,7 +30,6 @@
from ietf.iesg.factories import IESGMgmtItemFactory, TelechatAgendaContentFactory
from ietf.utils.timezone import date_today, DEADLINE_TZINFO


class IESGTests(TestCase):
def test_feed(self):
draft = WgDraftFactory(states=[('draft','active'),('draft-iesg','iesg-eva')],ad=Person.objects.get(user__username='ad'))
Expand Down Expand Up @@ -500,12 +499,13 @@ def test_agenda_documents_txt(self):
def test_agenda_documents(self):
url = urlreverse("ietf.iesg.views.agenda_documents")
r = self.client.get(url)

self.assertEqual(r.status_code, 200)

for k, d in self.telechat_docs.items():
self.assertContains(r, d.name, msg_prefix="%s '%s' not in response" % (k, d.name, ))
self.assertContains(r, d.title, msg_prefix="%s '%s' title not in response" % (k, d.title, ))

self.assertContains(r, d.title, msg_prefix="%s '%s' not in response" % (k, d.title, ))
def test_past_documents(self):
url = urlreverse("ietf.iesg.views.past_documents")
# We haven't put any documents on past telechats, so this should be empty
Expand Down Expand Up @@ -580,6 +580,66 @@ def test_admin_change(self):
draft = Document.objects.get(name="draft-ietf-mars-test")
self.assertEqual(draft.telechat_date(),today)

class IESGAgendaTelechatPagesTests(TestCase):
def setUp(self):
super().setUp()
# make_immutable_test_data made a set of future telechats - only need one
# We'll take the "next" one
self.telechat_date = get_agenda_date()
# make_immutable_test_data made and area with only one ad - give it another
ad = Person.objects.get(user__username="ad")
adrole = Role.objects.get(person=ad, name="ad")
ad2 = RoleFactory(group=adrole.group, name_id="ad").person
self.ads=[ad,ad2]

# Make some drafts
docs = [
WgDraftFactory(pages=2, states=[('draft-iesg','iesg-eva'),]),
IndividualDraftFactory(pages=20, states=[('draft-iesg','iesg-eva'),]),
WgDraftFactory(pages=200, states=[('draft-iesg','iesg-eva'),]),
]
# Put them on the telechat
for doc in docs:
TelechatDocEventFactory(doc=doc, telechat_date=self.telechat_date)
# Give them ballots
ballots = [BallotDocEventFactory(doc=doc) for doc in docs]

# Give the "ad" Area-Director a discuss on one
BallotPositionDocEventFactory(balloter=ad, doc=docs[0], pos_id="discuss", ballot=ballots[0])
# and a "norecord" position on another
BallotPositionDocEventFactory(balloter=ad, doc=docs[1], pos_id="norecord", ballot=ballots[1])
# Now "ad" should have 220 pages left to ballot on.
# Every other ad should have 222 pages left to ballot on.

def test_ad_pages_left_to_ballot_on(self):
url = urlreverse("ietf.iesg.views.agenda_documents")

# A non-AD user won't get "pages left"
response = self.client.get(url)
telechat = response.context["telechats"][0]
self.assertEqual(telechat["date"], self.telechat_date)
self.assertEqual(telechat["ad_pages_left_to_ballot_on"],0)
self.assertNotContains(response,"pages left to ballot on")

username=self.ads[0].user.username
self.assertTrue(self.client.login(username=username, password=f"{username}+password"))

response = self.client.get(url)
telechat = response.context["telechats"][0]
self.assertEqual(telechat["ad_pages_left_to_ballot_on"],220)
self.assertContains(response,"220 pages left to ballot on")

self.client.logout()
username=self.ads[1].user.username
self.assertTrue(self.client.login(username=username, password=f"{username}+password"))

response = self.client.get(url)
telechat = response.context["telechats"][0]
self.assertEqual(telechat["ad_pages_left_to_ballot_on"],222)




class RescheduleOnAgendaTests(TestCase):
def test_reschedule(self):
draft = WgDraftFactory()
Expand Down
22 changes: 17 additions & 5 deletions ietf/iesg/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from ietf.iesg.agenda import get_doc_section


TelechatPageCount = namedtuple('TelechatPageCount',['for_approval','for_action','related'])
TelechatPageCount = namedtuple('TelechatPageCount',['for_approval','for_action','related','ad_pages_left_to_ballot_on'])

def telechat_page_count(date=None, docs=None):
def telechat_page_count(date=None, docs=None, ad=None):
if not date and not docs:
return TelechatPageCount(0, 0, 0)
return TelechatPageCount(0, 0, 0, 0)

if not docs:
candidates = Document.objects.filter(docevent__telechatdocevent__telechat_date=date).distinct()
Expand All @@ -24,7 +24,18 @@ def telechat_page_count(date=None, docs=None):

drafts = [d for d in for_approval if d.type_id == 'draft']

pages_for_approval = sum([d.pages or 0 for d in drafts])
ad_pages_left_to_ballot_on = 0
pages_for_approval = 0

for draft in drafts:
pages_for_approval += draft.pages or 0
if ad:
ballot = draft.active_ballot()
if ballot:
positions = ballot.active_balloter_positions()
ad_position = positions[ad]
if ad_position is None or ad_position.pos_id == "norecord":
ad_pages_left_to_ballot_on += draft.pages or 0

pages_for_action = 0
for d in for_action:
Expand Down Expand Up @@ -53,4 +64,5 @@ def telechat_page_count(date=None, docs=None):

return TelechatPageCount(for_approval=pages_for_approval,
for_action=pages_for_action,
related=related_pages)
related=related_pages,
ad_pages_left_to_ballot_on=ad_pages_left_to_ballot_on)
8 changes: 6 additions & 2 deletions ietf/iesg/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ def handle_reschedule_form(request, doc, dates, status):
return form

def agenda_documents(request):
ad = request.user.person if has_role(request.user, "Area Director") else None

dates = list(TelechatDate.objects.active().order_by('date').values_list("date", flat=True)[:4])

docs_by_date = dict((d, []) for d in dates)
Expand Down Expand Up @@ -390,11 +392,13 @@ def agenda_documents(request):
# the search_result_row view to display them (which expects them)
fill_in_document_table_attributes(docs_by_date[date], have_telechat_date=True)
fill_in_agenda_docs(date, sections, docs_by_date[date])
pages = telechat_page_count(docs=docs_by_date[date]).for_approval

page_count = telechat_page_count(docs=docs_by_date[date], ad=ad)
pages = page_count.for_approval

telechats.append({
"date": date,
"pages": pages,
"ad_pages_left_to_ballot_on": page_count.ad_pages_left_to_ballot_on,
"sections": sorted((num, section) for num, section in sections.items()
if "2" <= num < "5")
})
Expand Down
7 changes: 6 additions & 1 deletion ietf/templates/iesg/agenda_documents.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ <h1>Documents on future IESG telechat agendas</h1>
<h2>
IESG telechat {{ t.date }}
<br>
<small class="text-body-secondary">{{ t.pages }} page{{ t.pages|pluralize }}</small>
<small class="text-body-secondary">
{{ t.pages }} page{{ t.pages|pluralize }}
{% if t.ad_pages_left_to_ballot_on %}
({{ t.ad_pages_left_to_ballot_on }} pages left to ballot on)
{% endif %}
</small>
</h2>
<div class="buttonlist">
<a class="btn btn-primary" role="button" href="{% url 'ietf.iesg.views.agenda' %}">
Expand Down
Loading