Skip to content

Commit 10dceef

Browse files
committed
Refactor IESG agenda pages, put the agenda structure in a helper function in agenda.py, build the agenda up around this structure, and reuse this everywhere instead of duplicating the structure in various templates and the JSON view - this also fixes a couple of minor bugs where the copy-pasted copies were not entirely in sync
- Legacy-Id: 6454
1 parent de2ed52 commit 10dceef

29 files changed

Lines changed: 867 additions & 1700 deletions

ietf/doc/templatetags/ietf_filters.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ def statehelp(state):
476476
url = urlreverse("state_help", kwargs=dict(type=state.type_id)) + "#" + state.slug
477477
return mark_safe('<a class="state-help-icon" href="%s" title="%s">?</a>' % (url, tooltip))
478478

479+
@register.filter
480+
def sectionlevel(section_number):
481+
return section_number.count(".") + 1
482+
479483
def _test():
480484
import doctest
481485
doctest.testmod()

ietf/iesg/agenda.py

Lines changed: 128 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import codecs, re, os, datetime
44

5+
# FIXME: once we're on Python 2.7, replace with: from collections import OrderedDict
6+
from django.utils.datastructures import SortedDict as OrderedDict
7+
58
from django.http import Http404
69
from django.conf import settings
710

@@ -17,7 +20,8 @@ def get_agenda_date(date=None):
1720
return datetime.date.today()
1821
else:
1922
try:
20-
return TelechatDate.objects.active().get(date=datetime.datetime.strptime(date, "%Y-%m-%d").date()).date
23+
# FIXME: .active()
24+
return TelechatDate.objects.all().get(date=datetime.datetime.strptime(date, "%Y-%m-%d").date()).date
2125
except (ValueError, TelechatDate.DoesNotExist):
2226
raise Http404
2327

@@ -30,66 +34,125 @@ def get_doc_section(doc):
3034

3135
g = doc.group_acronym()
3236
if g and str(g) != 'none':
33-
s = s + "1"
34-
elif (s == "3") and doc.stream_id in ("ise","irtf"):
35-
s = s + "3"
37+
s += ".1"
38+
elif s == "3" and doc.stream_id in ("ise","irtf"):
39+
s += ".3"
3640
else:
37-
s = s + "2"
41+
s += ".2"
3842
if doc.get_state_slug() != "rfc" and doc.get_state_slug('draft-iesg') not in ("lc", "writeupw", "goaheadw", "iesg-eva", "defer"):
39-
s = s + "3"
43+
s += ".3"
4044
elif doc.returning_item():
41-
s = s + "2"
45+
s += ".2"
4246
else:
43-
s = s + "1"
47+
s += ".1"
48+
4449
elif doc.type_id == 'charter':
45-
s = get_wg_section(doc.group)
50+
s = "4"
51+
if doc.group.state_id in ('active', 'dormant'):
52+
s += ".2"
53+
else:
54+
s += ".1"
55+
if doc.get_state_slug() in ('extrev', 'iesgrev'):
56+
s += '.2'
57+
else:
58+
s += '.1'
59+
4660
elif doc.type_id == 'statchg':
4761
protocol_action = False
4862
for relation in doc.relateddocument_set.filter(relationship__slug__in=('tops','tois','tohist','toinf','tobcp','toexp')):
4963
if relation.relationship.slug in ('tops','tois') or relation.target.document.std_level.slug in ('std','ds','ps'):
5064
protocol_action = True
5165
if protocol_action:
52-
s="23"
66+
s = "2.3"
5367
else:
54-
s="33"
68+
s = "3.3"
5569
if doc.get_state_slug() not in ("iesgeval", "defer", "appr-pr", "appr-pend", "appr-sent"):
56-
s = s + "3"
70+
s += ".3"
5771
elif doc.returning_item():
58-
s = s + "2"
72+
s += ".2"
5973
else:
60-
s = s + "1"
74+
s += ".1"
6175
elif doc.type_id == 'conflrev':
6276
if doc.get_state('conflrev').slug not in ('adrev','iesgeval','appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent','defer'):
63-
s = "343"
77+
s = "3.4.3"
6478
elif doc.returning_item():
65-
s = "342"
79+
s = "3.4.2"
6680
else:
67-
s = "341"
81+
s = "3.4.1"
6882

6983
return s
7084

71-
def get_wg_section(wg):
72-
s = ""
73-
charter_slug = None
74-
if wg.charter:
75-
charter_slug = wg.charter.get_state_slug()
76-
if wg.state_id in ['active','dormant']:
77-
if charter_slug in ['extrev','iesgrev']:
78-
s = '422'
79-
else:
80-
s = '421'
81-
else:
82-
if charter_slug in ['extrev','iesgrev']:
83-
s = '412'
84-
else:
85-
s = '411'
86-
return s
85+
def agenda_sections():
86+
return OrderedDict([
87+
('1', {'title':"Administrivia"}),
88+
('1.1', {'title':"Roll Call"}),
89+
('1.2', {'title':"Bash the Agenda"}),
90+
('1.3', {'title':"Approval of the Minutes of Past Telechats"}),
91+
('1.4', {'title':"List of Remaining Action Items from Last Telechat"}),
92+
('2', {'title':"Protocol Actions"}),
93+
('2.1', {'title':"WG Submissions"}),
94+
('2.1.1', {'title':"New Items", 'docs': []}),
95+
('2.1.2', {'title':"Returning Items", 'docs':[]}),
96+
('2.1.3', {'title':"For Action", 'docs':[]}),
97+
('2.2', {'title':"Individual Submissions"}),
98+
('2.2.1', {'title':"New Items", 'docs':[]}),
99+
('2.2.2', {'title':"Returning Items", 'docs':[]}),
100+
('2.2.3', {'title':"For Action", 'docs':[]}),
101+
('2.3', {'title':"Status Changes"}),
102+
('2.3.1', {'title':"New Items", 'docs':[]}),
103+
('2.3.2', {'title':"Returning Items", 'docs':[]}),
104+
('2.3.3', {'title':"For Action", 'docs':[]}),
105+
('3', {'title':"Document Actions"}),
106+
('3.1', {'title':"WG Submissions"}),
107+
('3.1.1', {'title':"New Items", 'docs':[]}),
108+
('3.1.2', {'title':"Returning Items", 'docs':[]}),
109+
('3.1.3', {'title':"For Action", 'docs':[]}),
110+
('3.2', {'title':"Individual Submissions Via AD"}),
111+
('3.2.1', {'title':"New Items", 'docs':[]}),
112+
('3.2.2', {'title':"Returning Items", 'docs':[]}),
113+
('3.2.3', {'title':"For Action", 'docs':[]}),
114+
('3.3', {'title':"Status Changes"}),
115+
('3.3.1', {'title':"New Items", 'docs':[]}),
116+
('3.3.2', {'title':"Returning Items", 'docs':[]}),
117+
('3.3.3', {'title':"For Action", 'docs':[]}),
118+
('3.4', {'title':"IRTF and Independent Submission Stream Documents"}),
119+
('3.4.1', {'title':"New Items", 'docs':[]}),
120+
('3.4.2', {'title':"Returning Items", 'docs':[]}),
121+
('3.4.3', {'title':"For Action", 'docs':[]}),
122+
('4', {'title':"Working Group Actions"}),
123+
('4.1', {'title':"WG Creation"}),
124+
('4.1.1', {'title':"Proposed for IETF Review", 'docs':[]}),
125+
('4.1.2', {'title':"Proposed for Approval", 'docs':[]}),
126+
('4.2', {'title':"WG Rechartering"}),
127+
('4.2.1', {'title':"Under Evaluation for IETF Review", 'docs':[]}),
128+
('4.2.2', {'title':"Proposed for Approval", 'docs':[]}),
129+
('5', {'title':"IAB News We Can Use"}),
130+
('6', {'title':"Management Issues"}),
131+
('7', {'title':"Working Group News"}),
132+
])
133+
134+
def fill_in_agenda_administrivia(date, sections):
135+
extra_info_files = (
136+
("1.1", "roll_call", settings.IESG_ROLL_CALL_FILE),
137+
("1.3", "minutes", settings.IESG_MINUTES_FILE),
138+
("1.4", "action_items", settings.IESG_TASK_FILE),
139+
)
140+
141+
for s, key, filename in extra_info_files:
142+
try:
143+
with codecs.open(filename, 'r', 'utf-8', 'replace') as f:
144+
t = f.read().strip()
145+
except IOError:
146+
t = u"(Error reading %s)" % filename
147+
148+
sections[s]["text"] = t
87149

88-
def agenda_docs(date):
89-
matches = Document.objects.filter(docevent__telechatdocevent__telechat_date=date).select_related("stream").distinct()
150+
def fill_in_agenda_docs(date, sections, matches=None):
151+
if not matches:
152+
matches = Document.objects.filter(docevent__telechatdocevent__telechat_date=date)
153+
matches = matches.select_related("stream", "group").distinct()
90154

91-
docmatches = []
92-
155+
docs = []
93156
for doc in matches:
94157
if doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date != date:
95158
continue
@@ -112,59 +175,42 @@ def agenda_docs(date):
112175
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
113176
if e:
114177
doc.consensus = "Yes" if e.consensus else "No"
115-
elif doc.type_id=='conflrev':
178+
elif doc.type_id == "conflrev":
116179
doc.conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document
180+
elif doc.type_id == "charter":
181+
#if doc.group.state_id not in ("proposed", "active"):
182+
# continue
117183

118-
docmatches.append(doc)
184+
doc.group.txt_link = settings.CHARTER_TXT_URL + "%s-%s.txt" % (doc.canonical_name(), doc.rev)
119185

120-
# Be careful to keep this the same as what's used in agenda_documents
121-
docmatches.sort(key=lambda d: d.balloting_started)
122-
123-
res = dict(("s%s%s%s" % (i, j, k), []) for i in range(2, 5) for j in range (1, 4) for k in range(1, 4))
124-
for k in range(1,4):
125-
res['s34%d'%k]=[]
126-
for doc in docmatches:
127-
section_key = "s" + get_doc_section(doc)
128-
if section_key not in res:
129-
res[section_key] = []
130-
res[section_key].append(doc)
131-
return res
132-
133-
def agenda_wg_actions(date):
134-
res = dict(("s%s%s%s" % (i, j, k), []) for i in range(2, 5) for j in range (1, 4) for k in range(1, 4))
135-
charters = Document.objects.filter(type="charter", docevent__telechatdocevent__telechat_date=date).select_related("group").distinct()
136-
charters = charters.filter(group__state__slug__in=["proposed","active"])
137-
for c in charters:
138-
if c.latest_event(TelechatDocEvent, type="scheduled_for_telechat").telechat_date != date:
139-
continue
186+
num = get_doc_section(doc)
187+
if num: # and num in sections
188+
sections[num]["docs"].append(doc)
140189

141-
c.group.txt_link = settings.CHARTER_TXT_URL + "%s-%s.txt" % (c.canonical_name(), c.rev)
190+
# prune empty "For action" sections
191+
empty_for_action = [num for num, section in sections.iteritems()
192+
if section["title"] == "For Action" and not section["docs"]]
193+
for num in empty_for_action:
194+
del sections[num]
142195

143-
section_key = "s" + get_wg_section(c.group)
144-
if section_key not in res:
145-
res[section_key] = []
146-
res[section_key].append(c)
147-
return res
196+
# Be careful to keep this the same as what's used in agenda_documents
197+
for s in sections.itervalues():
198+
if "docs" in s:
199+
s["docs"].sort(key=lambda d: d.balloting_started)
148200

149-
def agenda_management_issues(date):
150-
return TelechatAgendaItem.objects.filter(type=3).order_by('id')
201+
def fill_in_agenda_management_issues(date, sections):
202+
s = "6.%s"
203+
for i, item in enumerate(TelechatAgendaItem.objects.filter(type=3).order_by('id'), start=1):
204+
sections[s % i] = { "title": item.title, "text": item.text }
151205

152206
def agenda_data(request, date=None):
153207
"""Return a dict with the different IESG telechat agenda components."""
154208
date = get_agenda_date(date)
155-
docs = agenda_docs(date)
156-
mgmt = agenda_management_issues(date)
157-
wgs = agenda_wg_actions(date)
158-
data = {'date':str(date), 'docs':docs,'mgmt':mgmt,'wgs':wgs}
159-
for key, filename in {'action_items':settings.IESG_TASK_FILE,
160-
'roll_call':settings.IESG_ROLL_CALL_FILE,
161-
'minutes':settings.IESG_MINUTES_FILE}.items():
162-
try:
163-
f = codecs.open(filename, 'r', 'utf-8', 'replace')
164-
text = f.read().strip()
165-
f.close()
166-
data[key] = text
167-
except IOError:
168-
data[key] = "(Error reading "+key+")"
169-
return data
209+
sections = agenda_sections()
210+
211+
fill_in_agenda_administrivia(date, sections)
212+
fill_in_agenda_docs(date, sections)
213+
fill_in_agenda_management_issues(date, sections)
214+
215+
return { 'date': date.isoformat(), 'sections': sections }
170216

ietf/iesg/tests.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,12 @@ def test_reschedule(self):
229229
r = self.client.post(url, { '%s-telechat_date' % form_id: d.isoformat(),
230230
'%s-clear_returning_item' % form_id: "1" })
231231

232-
self.assertEquals(r.status_code, 200)
232+
self.assertEquals(r.status_code, 302)
233233

234234
# check that it moved below the right header in the DOM on the
235235
# agenda docs page
236+
r = self.client.get(url)
237+
self.assertEquals(r.status_code, 200)
236238
d_header_pos = r.content.find("IESG telechat %s" % d.isoformat())
237239
draft_pos = r.content.find(draft.name)
238240
self.assertTrue(d_header_pos < draft_pos)

0 commit comments

Comments
 (0)