Skip to content

Commit e94d1df

Browse files
committed
Clean up search views and remove dead code, port them to the new DB
schema, hack related views in iesg/ and wginfo/ to use the new search interfaces, avoid camelCase in search GET parameters (with backwards-compat fallback), add some simple search unit tests, remove caching from views_search.py index pages as they're now pretty fast to generate, rewrite ballot popup JS, regularize some CSS classes to use hyphen-notation rather than camelCase, move some of the search templates to doc/. idrfc/ now mostly contains some wrapper code still in use by other subdirs, some ported code not yet moved, and dead code. - Legacy-Id: 5611
1 parent bb7d037 commit e94d1df

40 files changed

Lines changed: 952 additions & 601 deletions

ietf/doc/models.py

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ def __unicode__(self):
3636
class Meta:
3737
ordering = ["type", "order"]
3838

39+
IESG_BALLOT_ACTIVE_STATES = ("lc", "writeupw", "goaheadw", "iesg-eva", "defer")
40+
IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
41+
3942
class DocumentInfo(models.Model):
4043
"""Any kind of document. Draft, RFC, Charter, IPR Statement, Liaison Statement"""
4144
time = models.DateTimeField(default=datetime.datetime.now) # should probably have auto_now=True
@@ -186,9 +189,7 @@ def __unicode__(self):
186189
def get_absolute_url(self):
187190
name = self.name
188191
if self.type_id == "draft" and self.get_state_slug() == "rfc":
189-
aliases = self.docalias_set.filter(name__startswith="rfc")
190-
if aliases:
191-
name = aliases[0].name
192+
name = self.canonical_name()
192193
elif self.type_id in ('slides','agenda','minutes'):
193194
session = self.session_set.all()[0]
194195
meeting = session.meeting
@@ -248,11 +249,10 @@ def related_that_doc(self, relationship):
248249
"""Return the doc aliases that are target of relationship originating from self."""
249250
return DocAlias.objects.filter(relateddocument__source=self, relateddocument__relationship=relationship)
250251

251-
#TODO can/should this be a function instead of a property? Currently a view uses it as a property
252-
@property
253-
def telechat_date(self):
254-
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
255-
return e.telechat_date if e else None
252+
def telechat_date(self, e=None):
253+
if not e:
254+
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
255+
return e.telechat_date if e and e.telechat_date and e.telechat_date >= datetime.date.today() else None
256256

257257
def area_acronym(self):
258258
g = self.group
@@ -271,10 +271,6 @@ def group_acronym(self):
271271
else:
272272
return "none"
273273

274-
def on_upcoming_agenda(self):
275-
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
276-
return bool(e and e.telechat_date and e.telechat_date >= datetime.date.today())
277-
278274
def returning_item(self):
279275
e = self.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
280276
return e.returning_item if e else None
@@ -299,56 +295,56 @@ def displayname_with_link(self):
299295
return '<a href="%s">%s-%s</a>' % (self.get_absolute_url(), self.name , self.rev)
300296

301297
def rfc_number(self):
302-
qs = self.docalias_set.filter(name__startswith='rfc')
303-
return qs[0].name[3:] if qs else None
298+
n = self.canonical_name()
299+
return n[3:] if n.startswith("rfc") else None
304300

305301
def friendly_state(self):
306-
""" Return a concise text description of the document's current state """
307-
if self.type_id=='draft':
308-
# started_iesg_process is is how the redesigned database schema (as of May2012) captured what
309-
# used to be "has an IDInternal", aka *Wrapper.in_ietf_process()=True
310-
in_iesg_process = self.latest_event(type='started_iesg_process')
311-
iesg_state_summary=None
312-
if in_iesg_process:
313-
iesg_state = self.states.get(type='draft-iesg')
302+
""" Return a concise text description of the document's current state."""
303+
state = self.get_state()
304+
if not state:
305+
return "Unknown state"
306+
307+
if self.type_id == 'draft':
308+
iesg_state = self.get_state("draft-iesg")
309+
iesg_state_summary = None
310+
if iesg_state:
314311
# This knowledge about which tags are reportable IESG substate tags is duplicated in idrfc
315-
IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
316312
iesg_substate = self.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
317313
# There really shouldn't be more than one tag in iesg_substate, but this will do something sort-of-sensible if there is
318314
iesg_state_summary = iesg_state.name
319315
if iesg_substate:
320316
iesg_state_summary = iesg_state_summary + "::"+"::".join(tag.name for tag in iesg_substate)
321317

322-
if self.get_state_slug() == "rfc":
323-
n = self.rfc_number()
324-
return "<a href=\"%s\">RFC %s</a>" % (urlreverse('doc_view', kwargs=dict(name='rfc%s' % n)), n)
325-
elif self.get_state_slug() == "repl":
318+
if state.slug == "rfc":
319+
return "RFC %s (%s)" % (self.rfc_number(), self.std_level)
320+
elif state.slug == "repl":
326321
rs = self.related_that("replaces")
327322
if rs:
328-
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', args=[name]), name) for name in rs))
323+
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', kwargs=dict(name=name)), name) for name in rs))
329324
else:
330325
return "Replaced"
331-
elif self.get_state_slug() == "active":
332-
if in_iesg_process:
326+
elif state.slug == "active":
327+
if iesg_state:
333328
if iesg_state.slug == "dead":
334329
# Many drafts in the draft-iesg "Dead" state are not dead
335330
# in other state machines; they're just not currently under
336331
# IESG processing. Show them as "I-D Exists (IESG: Dead)" instead...
337-
return "I-D Exists (IESG: "+iesg_state_summary+")"
332+
return "I-D Exists (IESG: %s)" % iesg_state_summary
338333
elif iesg_state.slug == "lc":
339-
expiration_date = str(self.latest_event(LastCallDocEvent,type="sent_last_call").expires.date())
340-
return iesg_state_summary + " (ends "+expiration_date+")"
341-
else:
342-
return iesg_state_summary
334+
e = self.latest_event(LastCallDocEvent, type="sent_last_call")
335+
if e:
336+
return iesg_state_summary + " (ends %s)" % e.expires.date().isoformat()
337+
338+
return iesg_state_summary
343339
else:
344340
return "I-D Exists"
345341
else:
346-
if in_iesg_process and iesg_state.slug == "dead":
347-
return self.get_state().name +" (IESG: "+iesg_state_summary+")"
342+
if iesg_state and iesg_state.slug == "dead":
343+
return state.name + " (IESG: %s)" % iesg_state_summary
348344
# Expired/Withdrawn by Submitter/IETF
349-
return self.get_state().name
345+
return state.name
350346
else:
351-
return self.get_state().name
347+
return state.name
352348

353349
def ipr(self):
354350
"""Returns the IPR disclosures against this document (as a queryset over IprDocAlias)."""

ietf/doc/tests.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,108 @@
2121
from ietf.doc.tests_conflict_review import *
2222

2323

24+
class SearchTestCase(django.test.TestCase):
25+
fixtures = ['names']
26+
27+
def test_search(self):
28+
draft = make_test_data()
29+
30+
base_url = urlreverse("doc_search")
31+
32+
# only show form, no search yet
33+
r = self.client.get(base_url)
34+
self.assertEqual(r.status_code, 200)
35+
36+
# no match
37+
r = self.client.get(base_url + "?activedrafts=on&name=thisisnotadocumentname")
38+
self.assertEqual(r.status_code, 200)
39+
self.assertTrue("no documents match" in r.content.lower())
40+
41+
r = self.client.get(base_url + "?rfcs=on&name=")
42+
self.assertEqual(r.status_code, 200)
43+
self.assertTrue("no documents match" in r.content.lower())
44+
45+
r = self.client.get(base_url + "?olddrafts=on&name=")
46+
self.assertEqual(r.status_code, 200)
47+
self.assertTrue("no documents match" in r.content.lower())
48+
49+
# find by rfc/active/inactive
50+
draft.set_state(State.objects.get(type="draft", slug="rfc"))
51+
r = self.client.get(base_url + "?rfcs=on&name=%s" % draft.name)
52+
self.assertEqual(r.status_code, 200)
53+
self.assertTrue(draft.title in r.content)
54+
55+
draft.set_state(State.objects.get(type="draft", slug="active"))
56+
r = self.client.get(base_url + "?activedrafts=on&name=%s" % draft.name)
57+
self.assertEqual(r.status_code, 200)
58+
self.assertTrue(draft.title in r.content)
59+
60+
draft.set_state(State.objects.get(type="draft", slug="expired"))
61+
r = self.client.get(base_url + "?olddrafts=on&name=%s" % draft.name)
62+
self.assertEqual(r.status_code, 200)
63+
self.assertTrue(draft.title in r.content)
64+
65+
draft.set_state(State.objects.get(type="draft", slug="active"))
66+
67+
# find by title
68+
r = self.client.get(base_url + "?activedrafts=on&name=%s" % draft.title.split()[0])
69+
self.assertEqual(r.status_code, 200)
70+
self.assertTrue(draft.title in r.content)
71+
72+
# find by author
73+
r = self.client.get(base_url + "?activedrafts=on&by=author&author=%s" % draft.authors.all()[0].person.name_parts()[1])
74+
self.assertEqual(r.status_code, 200)
75+
self.assertTrue(draft.title in r.content)
76+
77+
# find by group
78+
r = self.client.get(base_url + "?activedrafts=on&by=group&group=%s" % draft.group.acronym)
79+
self.assertEqual(r.status_code, 200)
80+
self.assertTrue(draft.title in r.content)
81+
82+
# find by area
83+
r = self.client.get(base_url + "?activedrafts=on&by=area&area=%s" % draft.group.parent_id)
84+
self.assertEqual(r.status_code, 200)
85+
self.assertTrue(draft.title in r.content)
86+
87+
# find by area
88+
r = self.client.get(base_url + "?activedrafts=on&by=area&area=%s" % draft.group.parent_id)
89+
self.assertEqual(r.status_code, 200)
90+
self.assertTrue(draft.title in r.content)
91+
92+
# find by AD
93+
r = self.client.get(base_url + "?activedrafts=on&by=ad&ad=%s" % draft.ad_id)
94+
self.assertEqual(r.status_code, 200)
95+
self.assertTrue(draft.title in r.content)
96+
97+
# find by IESG state
98+
r = self.client.get(base_url + "?activedrafts=on&by=state&state=%s&substate=" % draft.get_state("draft-iesg").pk)
99+
self.assertEqual(r.status_code, 200)
100+
self.assertTrue(draft.title in r.content)
101+
102+
def test_drafts_pages(self):
103+
draft = make_test_data()
104+
105+
r = self.client.get(urlreverse("drafts_for_ad", kwargs=dict(name=draft.ad.full_name_as_key())))
106+
self.assertEqual(r.status_code, 200)
107+
self.assertTrue(draft.title in r.content)
108+
109+
draft.set_state(State.objects.get(type="draft-iesg", slug="lc"))
110+
r = self.client.get(urlreverse("drafts_in_last_call"))
111+
self.assertEqual(r.status_code, 200)
112+
self.assertTrue(draft.title in r.content)
113+
114+
def test_indexes(self):
115+
draft = make_test_data()
116+
117+
r = self.client.get(urlreverse("index_all_drafts"))
118+
self.assertEqual(r.status_code, 200)
119+
self.assertTrue(draft.name in r.content)
120+
121+
r = self.client.get(urlreverse("index_active_drafts"))
122+
self.assertEqual(r.status_code, 200)
123+
self.assertTrue(draft.title in r.content)
124+
125+
24126
class DocTestCase(django.test.TestCase):
25127
fixtures = ['names']
26128

ietf/idrfc/lastcall.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from ietf.idrfc.mails import *
99
from ietf.idrfc.utils import *
1010

11-
from ietf.doc.models import Document, DocEvent, LastCallDocEvent, WriteupDocEvent, save_document_in_history, State
11+
from ietf.doc.models import *
1212
from ietf.person.models import Person
1313

1414
def request_last_call(request, doc):
@@ -83,7 +83,7 @@ def expire_last_callREDESIGN(doc):
8383
prev = doc.get_state("draft-iesg")
8484
doc.set_state(state)
8585

86-
prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
86+
prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
8787
prev_tag = prev_tag[0] if prev_tag else None
8888
if prev_tag:
8989
doc.tags.remove(prev_tag)

0 commit comments

Comments
 (0)