")
@@ -110,13 +104,13 @@ def render_ballot_icon(user, doc):
c = "position-%s" % (pos.pos.slug if pos else "norecord")
- if hasattr(user, "get_profile") and ad == user.get_profile():
+ if user_is_person(user, ad):
c += " my"
res.append('
' % c)
res.append("
")
- res.append("
")
+ res.append("
")
return "".join(res)
@@ -125,48 +119,51 @@ class BallotIconNode(template.Node):
self.doc_var = doc_var
def render(self, context):
doc = template.resolve_variable(self.doc_var, context)
- #if hasattr(doc, "_idinternal"):
- # # hack for old schema
- # doc = doc._idinternal
return render_ballot_icon(context.get("user"), doc)
def do_ballot_icon(parser, token):
try:
- tagName, docName = token.split_contents()
+ tag_name, doc_name = token.split_contents()
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
- return BallotIconNode(docName)
+ return BallotIconNode(doc_name)
register.tag('ballot_icon', do_ballot_icon)
+
@register.filter
def my_position(doc, user):
- user_name = get_user_name({'user':user})
- if not user_name:
- return None
- if not in_group(user, "Area_Director"):
+ if not has_role(user, "Area Director"):
return None
+ # FIXME: temporary backwards-compatibility hack
+ from ietf.doc.models import Document
+ if not isinstance(doc, Document):
+ doc = doc._draft
+
ballot = doc.active_ballot()
pos = "No Record"
if ballot:
- changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad__name=user_name, ballot=ballot)
- if changed_pos:
- pos = changed_pos.pos.name;
+ changed_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad__user=user, ballot=ballot)
+ if changed_pos:
+ pos = changed_pos.pos.name;
return pos
-@register.filter
+@register.filter()
def state_age_colored(doc):
- if doc.type.slug == 'draft':
- if not doc.latest_event(type='started_iesg_process'):
- return ""
+ # FIXME: temporary backwards-compatibility hack
+ from ietf.doc.models import Document
+ if not isinstance(doc, Document):
+ doc = doc._draft
+
+ if doc.type_id == 'draft':
if not doc.get_state_slug() in ["active", "rfc"]:
# Don't show anything for expired/withdrawn/replaced drafts
return ""
- main_state = doc.get_state('draft-iesg')
- IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
- sub_states = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
+ main_state = doc.get_state_slug('draft-iesg')
+ if not main_state:
+ return ""
- if main_state.slug in ["dead","watching","pub"]:
+ if main_state in ["dead", "watching", "pub"]:
return ""
try:
state_date = doc.docevent_set.filter(
@@ -181,26 +178,26 @@ def state_age_colored(doc):
Q(desc__istartswith="IESG process started in state")
).order_by('-time')[0].time.date()
except IndexError:
- state_date = date(1990,1,1)
- days = timesince_days(state_date)
+ state_date = datetime.date(1990,1,1)
+ days = (datetime.date.today() - state_date).days
# loosely based on
# http://trac.tools.ietf.org/group/iesg/trac/wiki/PublishPath
- if main_state.slug == "lc":
+ if main_state == "lc":
goal1 = 30
goal2 = 30
- elif main_state.slug == "rfcqueue":
+ elif main_state == "rfcqueue":
goal1 = 60
goal2 = 120
- elif main_state.slug in ["lc-req", "ann"]:
+ elif main_state in ["lc-req", "ann"]:
goal1 = 4
goal2 = 7
- elif 'need-rev' in [x.slug for x in sub_states]:
+ elif 'need-rev' in [x.slug for x in doc.tags.all()]:
goal1 = 14
goal2 = 28
- elif main_state.slug == "pub-req":
+ elif main_state == "pub-req":
goal1 = 7
goal2 = 14
- elif main_state.slug == "ad-eval":
+ elif main_state == "ad-eval":
goal1 = 14
goal2 = 28
else:
@@ -216,6 +213,7 @@ def state_age_colored(doc):
title = ' title="Goal is <%d days"' % (goal1,)
else:
title = ''
- return '(for %d day%s)' % (class_name,title,days,('','s')[days != 1])
+ return mark_safe('(for %d day%s)' % (
+ class_name, title, days, 's' if days != 1 else ''))
else:
return ""
diff --git a/ietf/idrfc/tests.py b/ietf/idrfc/tests.py
index 9903aa59c..5ec9ddc5b 100644
--- a/ietf/idrfc/tests.py
+++ b/ietf/idrfc/tests.py
@@ -1013,13 +1013,13 @@ class ExpireIDsTestCase(django.test.TestCase):
shutil.rmtree(self.id_dir)
shutil.rmtree(self.archive_dir)
- def write_id_file(self, name, size):
+ def write_draft_file(self, name, size):
f = open(os.path.join(self.id_dir, name), 'w')
f.write("a" * size)
f.close()
- def test_in_id_expire_freeze(self):
- from ietf.idrfc.expire import in_id_expire_freeze
+ def test_in_draft_expire_freeze(self):
+ from ietf.idrfc.expire import in_draft_expire_freeze
Meeting.objects.create(number="123",
type=MeetingTypeName.objects.get(slug="ietf"),
@@ -1027,70 +1027,70 @@ class ExpireIDsTestCase(django.test.TestCase):
second_cut_off = Meeting.get_second_cut_off()
ietf_monday = Meeting.get_ietf_monday()
- self.assertTrue(not in_id_expire_freeze(datetime.datetime.combine(second_cut_off - datetime.timedelta(days=7), time(0, 0, 0))))
- self.assertTrue(not in_id_expire_freeze(datetime.datetime.combine(second_cut_off, time(0, 0, 0))))
- self.assertTrue(in_id_expire_freeze(datetime.datetime.combine(second_cut_off + datetime.timedelta(days=7), time(0, 0, 0))))
- self.assertTrue(in_id_expire_freeze(datetime.datetime.combine(ietf_monday - datetime.timedelta(days=1), time(0, 0, 0))))
- self.assertTrue(not in_id_expire_freeze(datetime.datetime.combine(ietf_monday, time(0, 0, 0))))
+ self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off - datetime.timedelta(days=7), time(0, 0, 0))))
+ self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(second_cut_off, time(0, 0, 0))))
+ self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(second_cut_off + datetime.timedelta(days=7), time(0, 0, 0))))
+ self.assertTrue(in_draft_expire_freeze(datetime.datetime.combine(ietf_monday - datetime.timedelta(days=1), time(0, 0, 0))))
+ self.assertTrue(not in_draft_expire_freeze(datetime.datetime.combine(ietf_monday, time(0, 0, 0))))
- def test_warn_expirable_ids(self):
- from ietf.idrfc.expire import get_soon_to_expire_ids, send_expire_warning_for_id
+ def test_warn_expirable_drafts(self):
+ from ietf.idrfc.expire import get_soon_to_expire_drafts, send_expire_warning_for_draft
draft = make_test_data()
- self.assertEquals(len(list(get_soon_to_expire_ids(14))), 0)
+ self.assertEquals(len(list(get_soon_to_expire_drafts(14))), 0)
# hack into expirable state
draft.unset_state("draft-iesg")
draft.expires = datetime.datetime.now() + datetime.timedelta(days=10)
draft.save()
- self.assertEquals(len(list(get_soon_to_expire_ids(14))), 1)
+ self.assertEquals(len(list(get_soon_to_expire_drafts(14))), 1)
# test send warning
mailbox_before = len(outbox)
- send_expire_warning_for_id(draft)
+ send_expire_warning_for_draft(draft)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("aread@ietf.org" in str(outbox[-1])) # author
self.assertTrue("wgchairman@ietf.org" in str(outbox[-1]))
- def test_expire_ids(self):
- from ietf.idrfc.expire import get_expired_ids, send_expire_notice_for_id, expire_id
+ def test_expire_drafts(self):
+ from ietf.idrfc.expire import get_expired_drafts, send_expire_notice_for_draft, expire_draft
draft = make_test_data()
- self.assertEquals(len(list(get_expired_ids())), 0)
+ self.assertEquals(len(list(get_expired_drafts())), 0)
# hack into expirable state
draft.unset_state("draft-iesg")
draft.expires = datetime.datetime.now()
draft.save()
- self.assertEquals(len(list(get_expired_ids())), 1)
+ self.assertEquals(len(list(get_expired_drafts())), 1)
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="watching"))
- self.assertEquals(len(list(get_expired_ids())), 1)
+ self.assertEquals(len(list(get_expired_drafts())), 1)
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva"))
- self.assertEquals(len(list(get_expired_ids())), 0)
+ self.assertEquals(len(list(get_expired_drafts())), 0)
# test notice
mailbox_before = len(outbox)
- send_expire_notice_for_id(draft)
+ send_expire_notice_for_draft(draft)
self.assertEquals(len(outbox), mailbox_before + 1)
self.assertTrue("expired" in outbox[-1]["Subject"])
# test expiry
txt = "%s-%s.txt" % (draft.name, draft.rev)
- self.write_id_file(txt, 5000)
+ self.write_draft_file(txt, 5000)
- expire_id(draft)
+ expire_draft(draft)
draft = Document.objects.get(name=draft.name)
self.assertEquals(draft.get_state_slug(), "expired")
@@ -1099,16 +1099,16 @@ class ExpireIDsTestCase(django.test.TestCase):
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, txt)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, txt)))
- def test_clean_up_id_files(self):
+ def test_clean_up_draft_files(self):
draft = make_test_data()
- from ietf.idrfc.expire import clean_up_id_files
+ from ietf.idrfc.expire import clean_up_draft_files
# put unknown file
unknown = "draft-i-am-unknown-01.txt"
- self.write_id_file(unknown, 5000)
+ self.write_draft_file(unknown, 5000)
- clean_up_id_files()
+ clean_up_draft_files()
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, unknown)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "unknown_ids", unknown)))
@@ -1116,9 +1116,9 @@ class ExpireIDsTestCase(django.test.TestCase):
# put file with malformed name (no revision)
malformed = draft.name + ".txt"
- self.write_id_file(malformed, 5000)
+ self.write_draft_file(malformed, 5000)
- clean_up_id_files()
+ clean_up_draft_files()
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, malformed)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "unknown_ids", malformed)))
@@ -1129,11 +1129,11 @@ class ExpireIDsTestCase(django.test.TestCase):
draft.save()
txt = "%s-%s.txt" % (draft.name, draft.rev)
- self.write_id_file(txt, 5000)
+ self.write_draft_file(txt, 5000)
pdf = "%s-%s.pdf" % (draft.name, draft.rev)
- self.write_id_file(pdf, 5000)
+ self.write_draft_file(pdf, 5000)
- clean_up_id_files()
+ clean_up_draft_files()
# txt files shouldn't be moved (for some reason)
self.assertTrue(os.path.exists(os.path.join(self.id_dir, txt)))
@@ -1157,9 +1157,9 @@ class ExpireIDsTestCase(django.test.TestCase):
# expired without tombstone
txt = "%s-%s.txt" % (draft.name, draft.rev)
- self.write_id_file(txt, 5000)
+ self.write_draft_file(txt, 5000)
- clean_up_id_files()
+ clean_up_draft_files()
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, txt)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "expired_without_tombstone", txt)))
@@ -1169,9 +1169,9 @@ class ExpireIDsTestCase(django.test.TestCase):
revision_before = draft.rev
txt = "%s-%s.txt" % (draft.name, draft.rev)
- self.write_id_file(txt, 1000) # < 1500 means tombstone
+ self.write_draft_file(txt, 1000) # < 1500 means tombstone
- clean_up_id_files()
+ clean_up_draft_files()
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, txt)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "deleted_tombstones", txt)))
diff --git a/ietf/idrfc/urls.py b/ietf/idrfc/urls.py
index 71cabcb9a..32e5415b5 100644
--- a/ietf/idrfc/urls.py
+++ b/ietf/idrfc/urls.py
@@ -37,15 +37,20 @@ from ietf.doc import views_status_change
from ietf.doc import views_doc
urlpatterns = patterns('',
- (r'^/?$', views_search.search_main),
- (r'^search/$', views_search.search_results),
- (r'^all/$', views_search.all),
- (r'^active/$', views_search.active),
- (r'^in-last-call/$', views_search.in_last_call),
- url(r'^rfc-status-changes/$', views_status_change.rfc_status_changes, name='rfc_status_changes'),
- url(r'^start-rfc-status-change/(?P[A-Za-z0-9._+-]*)$', views_status_change.start_rfc_status_change, name='start_rfc_status_change'),
- url(r'^ad/(?P[A-Za-z0-9.-]+)/$', views_search.by_ad, name="doc_search_by_ad"),
- url(r'^ad2/(?P[A-Za-z0-9.-]+)/$', views_search.by_ad2, name="doc_search_by_ad2"),
+ (r'^/?$', views_search.search),
+ url(r'^search/$', views_search.search, name="doc_search"),
+ url(r'^in-last-call/$', views_search.drafts_in_last_call, name="drafts_in_last_call"),
+ url(r'^ad/(?P[A-Za-z0-9.-]+)/$', views_search.drafts_for_ad, name="drafts_for_ad"),
+# (r'^all/$', views_search.all), # XXX CHECK MERGE
+# (r'^active/$', views_search.active), # XXX CHECK MERGE
+ url(r'^rfc-status-changes/$', views_status_change.rfc_status_changes, name='rfc_status_changes'),
+ url(r'^start-rfc-status-change/(?P[A-Za-z0-9._+-]*)$', views_status_change.start_rfc_status_change, name='start_rfc_status_change'),
+ url(r'^iesg/(?P[A-Za-z0-9.-]+/)?$', views_search.drafts_in_iesg_process, name="drafts_in_iesg_process"),
+
+# url(r'^ad2/(?P[A-Za-z0-9.-]+)/$', views_search.by_ad2, name="doc_search_by_ad2"),
+
+ url(r'^all/$', views_search.index_all_drafts, name="index_all_drafts"),
+ url(r'^active/$', views_search.index_active_drafts, name="index_active_drafts"),
url(r'^(?P[A-Za-z0-9._+-]+)/((?P[0-9-]+)/)?$', views_doc.document_main, name="doc_view"),
url(r'^(?P[A-Za-z0-9._+-]+)/history/$', views_doc.document_history, name="doc_history"),
@@ -56,7 +61,7 @@ urlpatterns = patterns('',
url(r'^(?P[A-Za-z0-9._+-]+)/ballot/(?P[0-9]+)/$', views_doc.document_ballot, name="doc_ballot"),
url(r'^(?P[A-Za-z0-9._+-]+)/ballot/$', views_doc.document_ballot, name="doc_ballot"),
(r'^(?P[A-Za-z0-9._+-]+)/doc.json$', views_doc.document_json),
- (r'^(?P[A-Za-z0-9._+-]+)/ballotpopup/$', views_doc.ballot_for_popup),
+ (r'^(?P[A-Za-z0-9._+-]+)/ballotpopup/(?P[0-9]+)/$', views_doc.ballot_popup),
#(r'^(?P[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json), # legacy view
url(r'^(?P[A-Za-z0-9._+-]+)/edit/state/$', views_edit.change_state, name='doc_change_state'), # IESG state
@@ -86,6 +91,8 @@ urlpatterns = patterns('',
url(r'^(?P[A-Za-z0-9._+-]+)/edit/approveballot/$', views_ballot.approve_ballot, name='doc_approve_ballot'),
url(r'^(?P[A-Za-z0-9._+-]+)/edit/makelastcall/$', views_ballot.make_last_call, name='doc_make_last_call'),
+ url(r'^help/state/(?P[\w-]+)/$', 'ietf.doc.views_help.state_help', name="state_help"),
+
(r'^(?Pcharter-[A-Za-z0-9._+-]+)/', include('ietf.wgcharter.urls')),
(r'^(?P[A-Za-z0-9._+-]+)/conflict-review/', include('ietf.doc.urls_conflict_review')),
(r'^(?P[A-Za-z0-9._+-]+)/status-change/', include('ietf.doc.urls_status_change')),
@@ -97,4 +104,3 @@ urlpatterns += patterns('django.views.generic.simple',
url(r'^help/state/status-change/$', 'direct_to_template', { 'template': 'doc/states.html', 'extra_context': { 'states': State.objects.filter(type="statchg").order_by("order"),'title':"RFC Status Change" } }, name='help_status_change_states'),
)
-
diff --git a/ietf/idrfc/utils.py b/ietf/idrfc/utils.py
index e0fababef..4cc8df32b 100644
--- a/ietf/idrfc/utils.py
+++ b/ietf/idrfc/utils.py
@@ -64,12 +64,12 @@ def log_state_changed(request, doc, by, email_watch_list=True, note=''):
return change
def log_state_changedREDESIGN(request, doc, by, prev_iesg_state, prev_iesg_tag):
- from ietf.doc.models import DocEvent
+ from ietf.doc.models import DocEvent, IESG_SUBSTATE_TAGS
state = doc.get_state("draft-iesg")
state_name = state.name
- tags = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
if tags:
state_name += "::" + tags[0].name
diff --git a/ietf/idrfc/views_ballot.py b/ietf/idrfc/views_ballot.py
index fce68359f..3dfefe5b8 100644
--- a/ietf/idrfc/views_ballot.py
+++ b/ietf/idrfc/views_ballot.py
@@ -453,7 +453,7 @@ def defer_ballotREDESIGN(request, name):
prev_state = doc.friendly_state()
if doc.type_id == 'draft':
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='defer'))
- prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
@@ -641,7 +641,7 @@ def lastcalltextREDESIGN(request, name):
prev = doc.get_state("draft-iesg")
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='lc-req'))
- prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
@@ -1035,7 +1035,7 @@ def approve_ballotREDESIGN(request, name):
prev = doc.get_state("draft-iesg")
doc.set_state(new_state)
- prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
diff --git a/ietf/idrfc/views_edit.py b/ietf/idrfc/views_edit.py
index e6e781c83..a663f916d 100644
--- a/ietf/idrfc/views_edit.py
+++ b/ietf/idrfc/views_edit.py
@@ -47,8 +47,6 @@ class ChangeStateForm(forms.Form):
def change_state(request, name):
pass
-IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty')
-
class ChangeStateFormREDESIGN(forms.Form):
state = forms.ModelChoiceField(State.objects.filter(used=True, type="draft-iesg"), empty_label=None, required=True)
substate = forms.ModelChoiceField(DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS), required=False)
@@ -93,7 +91,7 @@ def change_stateREDESIGN(request, name):
# tag handling is a bit awkward since the UI still works
# as if IESG tags are a substate
- prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
prev_tag = prev_tag[0] if prev_tag else None
if next_state != prev_state or tag != prev_tag:
@@ -144,7 +142,7 @@ def change_stateREDESIGN(request, name):
else:
state = doc.get_state("draft-iesg")
- t = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
+ t = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
form = ChangeStateForm(initial=dict(state=state.pk if state else None,
substate=t[0].pk if t else None))
form.docname=name
diff --git a/ietf/idrfc/views_search.py b/ietf/idrfc/views_search.py
index 8863545ab..9c5b47857 100644
--- a/ietf/idrfc/views_search.py
+++ b/ietf/idrfc/views_search.py
@@ -31,29 +31,26 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import re, datetime
+
from django import forms
from django.shortcuts import render_to_response
from django.db.models import Q
from django.template import RequestContext
-from django.views.decorators.cache import cache_page
-from ietf.idtracker.models import IDState, IESGLogin, IDSubState, Area, InternetDraft, Rfc, IDInternal, IETFWG
-from ietf.idrfc.models import RfcIndex
-from ietf.ipr.models import IprDraft
-from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponsePermanentRedirect
-from ietf.idrfc.idrfc_wrapper import IdWrapper,RfcWrapper,IdRfcWrapper
-from ietf.utils import normalize_draftname
-from django.conf import settings
+from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
+from ietf.idrfc.expire import expirable_draft
+from ietf.utils import normalize_draftname
from ietf.doc.models import *
from ietf.person.models import *
from ietf.group.models import *
+from ietf.ipr.models import IprDocAlias
+from ietf.idindex.index import active_drafts_index_by_group
class SearchForm(forms.Form):
name = forms.CharField(required=False)
- rfcs = forms.BooleanField(required=False,initial=True)
- activeDrafts = forms.BooleanField(required=False,initial=True)
- oldDrafts = forms.BooleanField(required=False,initial=False)
- lucky = forms.BooleanField(required=False,initial=False)
+ rfcs = forms.BooleanField(required=False, initial=True)
+ activedrafts = forms.BooleanField(required=False, initial=True)
+ olddrafts = forms.BooleanField(required=False, initial=False)
by = forms.ChoiceField(choices=[(x,x) for x in ('author','group','area','ad','state')], required=False, initial='wg', label='Foobar')
author = forms.CharField(required=False)
@@ -61,7 +58,9 @@ class SearchForm(forms.Form):
area = forms.ModelChoiceField(Group.objects.filter(type="area", state="active").order_by('name'), empty_label="any area", required=False)
ad = forms.ChoiceField(choices=(), required=False)
state = forms.ModelChoiceField(State.objects.filter(type="draft-iesg"), empty_label="any state", required=False)
- subState = forms.ChoiceField(choices=(), required=False)
+ substate = forms.ChoiceField(choices=(), required=False)
+
+ sort = forms.ChoiceField(choices=(("document", "Document"), ("title", "Title"), ("date", "Date"), ("status", "Status"), ("ipr", "Ipr"), ("ad", "AD")), required=False, widget=forms.HiddenInput)
def __init__(self, *args, **kwargs):
super(SearchForm, self).__init__(*args, **kwargs)
@@ -78,54 +77,138 @@ class SearchForm(forms.Form):
inactive_ads.sort(key=extract_last_name)
self.fields['ad'].choices = c = [('', 'any AD')] + [(ad.pk, ad.plain_name()) for ad in active_ads] + [('', '------------------')] + [(ad.pk, ad.name) for ad in inactive_ads]
- self.fields['subState'].choices = [('', 'any substate'), ('0', 'no substate')] + [(n.slug, n.name) for n in DocTagName.objects.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))]
+ self.fields['substate'].choices = [('', 'any substate'), ('0', 'no substate')] + [(n.slug, n.name) for n in DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS)]
+
def clean_name(self):
value = self.cleaned_data.get('name','')
return normalize_draftname(value)
+
def clean(self):
q = self.cleaned_data
# Reset query['by'] if needed
- if 'by' not in q:
- q['by'] = None
- else:
- for k in ('author','group','area','ad'):
- if (q['by'] == k) and (k not in q or not q[k]):
+ if 'by' in q:
+ for k in ('author', 'group', 'area', 'ad'):
+ if q['by'] == k and not q.get(k):
q['by'] = None
- if (q['by'] == 'state') and (not 'state' in q or not 'subState' in q or not (q['state'] or q['subState'])):
+ if q['by'] == 'state' and not (q.get("state") or q.get('substate')):
q['by'] = None
# Reset other fields
- for k in ('author','group','area','ad'):
- if q['by'] != k:
- self.data[k] = ""
+ for k in ('author','group', 'area', 'ad'):
+ if k != q['by']:
q[k] = ""
if q['by'] != 'state':
- self.data['state'] = ""
- self.data['subState'] = ""
- q['state'] = ""
- q['subState'] = ""
+ q['state'] = q['substate'] = None
return q
-def search_query(query_original, sort_by=None):
- query = dict(query_original.items())
- drafts = query['activeDrafts'] or query['oldDrafts']
- if (not drafts) and (not query['rfcs']):
+def wrap_value(v):
+ return lambda: v
+
+def fill_in_search_attributes(docs):
+ # fill in some attributes for the search results to save some
+ # hairy template code and avoid repeated SQL queries - remaining
+ # queries we don't handle here are mostly implicit many-to-many
+ # relations for which there is poor support in Django 1.2
+
+ docs_dict = dict((d.pk, d) for d in docs)
+ doc_ids = docs_dict.keys()
+
+ rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__in=doc_ids).values_list("document_id", "name"))
+
+ # latest event cache
+ event_types = ("published_rfc",
+ "changed_ballot_position",
+ "started_iesg_process",
+ "new_revision")
+ for d in docs:
+ d.latest_event_cache = dict()
+ for e in event_types:
+ d.latest_event_cache[e] = None
+
+ for e in DocEvent.objects.filter(doc__in=doc_ids, type__in=event_types).order_by('time'):
+ docs_dict[e.doc_id].latest_event_cache[e.type] = e
+
+ # IPR
+ for d in docs:
+ d.iprs = []
+
+ ipr_docaliases = IprDocAlias.objects.filter(doc_alias__document__in=doc_ids).select_related('doc_alias')
+ for a in ipr_docaliases:
+ docs_dict[a.doc_alias.document_id].iprs.append(a)
+
+ # telechat date, can't do this with above query as we need to get TelechatDocEvents out
+ seen = set()
+ for e in TelechatDocEvent.objects.filter(doc__in=doc_ids, type="scheduled_for_telechat").order_by('-time'):
+ if e.doc_id not in seen:
+ d = docs_dict[e.doc_id]
+ d.telechat_date = wrap_value(d.telechat_date(e))
+ seen.add(e.doc_id)
+
+ # misc
+ for d in docs:
+ # emulate canonical name which is used by a lot of the utils
+ d.canonical_name = wrap_value(rfc_aliases[d.pk] if d.pk in rfc_aliases else d.name)
+
+ if d.rfc_number() != None and d.latest_event_cache["published_rfc"]:
+ d.latest_revision_date = d.latest_event_cache["published_rfc"].time
+ elif d.latest_event_cache["new_revision"]:
+ d.latest_revision_date = d.latest_event_cache["new_revision"].time
+ else:
+ d.latest_revision_date = d.time
+
+ if d.get_state_slug() == "rfc":
+ d.search_heading = "RFCs"
+ elif d.get_state_slug() == "active":
+ d.search_heading = "Active Internet-Drafts"
+ else:
+ d.search_heading = "Old Internet-Drafts"
+
+ d.expirable = expirable_draft(d)
+
+ if d.get_state_slug() != "rfc":
+ d.milestones = d.groupmilestone_set.filter(state="active").order_by("time").select_related("group")
+
+
+
+ # RFCs
+
+ # errata
+ erratas = set(Document.objects.filter(tags="errata", name__in=rfc_aliases.keys()).distinct().values_list("name", flat=True))
+ for d in docs:
+ d.has_errata = d.name in erratas
+
+ # obsoleted/updated by
+ for a in rfc_aliases:
+ d = docs_dict[a]
+ d.obsoleted_by_list = []
+ d.updated_by_list = []
+
+ xed_by = RelatedDocument.objects.filter(target__name__in=rfc_aliases.values(),
+ relationship__in=("obs", "updates")).select_related('target__document_id')
+ rel_rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc",
+ document__in=[rel.source_id for rel in xed_by]).values_list('document_id', 'name'))
+ for rel in xed_by:
+ d = docs_dict[rel.target.document_id]
+ if rel.relationship_id == "obs":
+ l = d.obsoleted_by_list
+ elif rel.relationship_id == "updates":
+ l = d.updated_by_list
+ l.append(rel_rfc_aliases[rel.source_id].upper())
+ l.sort()
+
+
+def retrieve_search_results(form):
+ """Takes a validated SearchForm and return the results."""
+ if not form.is_valid():
+ raise ValueError("SearchForm doesn't validate: %s" % form.errors)
+
+ query = form.cleaned_data
+
+ if not (query['activedrafts'] or query['olddrafts'] or query['rfcs']):
return ([], {})
- # Non-ASCII strings don't match anything; this check
- # is currently needed to avoid complaints from MySQL.
- # FIXME: this should be fixed with MySQL if it's still a problem?
- for k in ['name','author','group']:
- try:
- tmp = str(query.get(k, ''))
- except:
- query[k] = '*NOSUCH*'
-
- # Start by search InternetDrafts
- idresults = []
- rfcresults = []
MAX = 500
- docs = InternetDraft.objects.all()
+ docs = Document.objects.filter(type="draft")
# name
if query["name"]:
@@ -136,9 +219,9 @@ def search_query(query_original, sort_by=None):
allowed_states = []
if query["rfcs"]:
allowed_states.append("rfc")
- if query["activeDrafts"]:
+ if query["activedrafts"]:
allowed_states.append("active")
- if query["oldDrafts"]:
+ if query["olddrafts"]:
allowed_states.extend(['repl', 'expired', 'auth-rm', 'ietf-rm'])
docs = docs.filter(states__type="draft", states__slug__in=allowed_states)
@@ -146,7 +229,6 @@ def search_query(query_original, sort_by=None):
# radio choices
by = query["by"]
if by == "author":
- # FIXME: this is full name, not last name as hinted in the HTML
docs = docs.filter(authors__person__name__icontains=query["author"])
elif by == "group":
docs = docs.filter(group__acronym=query["group"])
@@ -158,66 +240,20 @@ def search_query(query_original, sort_by=None):
elif by == "state":
if query["state"]:
docs = docs.filter(states=query["state"])
- if query["subState"]:
- docs = docs.filter(tags=query["subState"])
+ if query["substate"]:
+ docs = docs.filter(tags=query["substate"])
- # evaluate and fill in values with aggregate queries to avoid
- # too many individual queries
+ # evaluate and fill in attribute results immediately to cut down
+ # the number of queries
results = list(docs.select_related("states", "ad", "ad__person", "std_level", "intended_std_level", "group", "stream")[:MAX])
- rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__in=[r.pk for r in results]).values_list("document_id", "name"))
- # canonical name
- for r in results:
- if r.pk in rfc_aliases:
- # lambda weirdness works around lambda binding in local for loop scope
- r.canonical_name = (lambda x: lambda: x)(rfc_aliases[r.pk])
- else:
- r.canonical_name = (lambda x: lambda: x)(r.name)
-
- result_map = dict((r.pk, r) for r in results)
-
- # events
- event_types = ("published_rfc",
- "changed_ballot_position",
- "started_iesg_process",
- "new_revision")
- for d in rfc_aliases.keys():
- for e in event_types:
- setattr(result_map[d], e, None)
-
- for e in DocEvent.objects.filter(doc__in=rfc_aliases.keys(), type__in=event_types).order_by('-time'):
- r = result_map[e.doc_id]
- if not getattr(r, e.type):
- # sets e.g. r.published_date = e for use in proxy wrapper
- setattr(r, e.type, e)
-
- # obsoleted/updated by
- for d in rfc_aliases:
- r = result_map[d]
- r.obsoleted_by_list = []
- r.updated_by_list = []
-
- xed_by = RelatedDocument.objects.filter(target__name__in=rfc_aliases.values(), relationship__in=("obs", "updates")).select_related('target__document_id')
- rel_rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__in=[rel.source_id for rel in xed_by]).values_list('document_id', 'name'))
- for rel in xed_by:
- r = result_map[rel.target.document_id]
- if rel.relationship_id == "obs":
- attr = "obsoleted_by_list"
- else:
- attr = "updated_by_list"
-
- getattr(r, attr).append(int(rel_rfc_aliases[rel.source_id][3:]))
-
+ fill_in_search_attributes(results)
# sort
def sort_key(d):
res = []
- canonical = d.canonical_name()
- if canonical.startswith('rfc'):
- rfc_num = int(canonical[3:])
- else:
- rfc_num = None
+ rfc_num = d.rfc_number()
if rfc_num != None:
res.append(2)
@@ -226,20 +262,20 @@ def search_query(query_original, sort_by=None):
else:
res.append(3)
- if sort_by == "title":
+ if query["sort"] == "title":
res.append(d.title)
- elif sort_by == "date":
- res.append(str(d.revision_date or datetime.date(1990, 1, 1)))
- elif sort_by == "status":
+ elif query["sort"] == "date":
+ res.append(str(d.latest_revision_date))
+ elif query["sort"] == "status":
if rfc_num != None:
- res.append(rfc_num)
+ res.append(int(rfc_num))
else:
- res.append(d.get_state().order)
- elif sort_by == "ipr":
- res.append(d.name)
- elif sort_by == "ad":
+ res.append(d.get_state().order if d.get_state() else None)
+ elif query["sort"] == "ipr":
+ res.append(len(d.iprs))
+ elif query["sort"] == "ad":
if rfc_num != None:
- res.append(rfc_num)
+ res.append(int(rfc_num))
elif d.get_state_slug() == "active":
if d.get_state("draft-iesg"):
res.append(d.get_state("draft-iesg").order)
@@ -247,286 +283,177 @@ def search_query(query_original, sort_by=None):
res.append(0)
else:
if rfc_num != None:
- res.append(rfc_num)
+ res.append(int(rfc_num))
else:
- res.append(canonical)
+ res.append(d.canonical_name())
return res
results.sort(key=sort_key)
+ # fill in a meta dict with some information for rendering the result table
meta = {}
- if len(docs) == MAX:
+ if len(results) == MAX:
meta['max'] = MAX
- if query['by']:
- meta['advanced'] = True
+ meta['by'] = query['by']
+ meta['advanced'] = bool(query['by'])
- # finally wrap in old wrappers
+ meta['headers'] = [{'title': 'Document', 'key':'document'},
+ {'title': 'Title', 'key':'title'},
+ {'title': 'Date', 'key':'date'},
+ {'title': 'Status', 'key':'status', 'colspan':'2'},
+ {'title': 'IPR', 'key':'ipr'},
+ {'title': 'Area Director', 'key':'ad'}]
- wrapped_results = []
- for r in results:
- draft = None
- rfc = None
- if not r.name.startswith('rfc'):
- draft = IdWrapper(r)
- if r.name.startswith('rfc') or r.pk in rfc_aliases:
- rfc = RfcWrapper(r)
- wrapped_results.append(IdRfcWrapper(draft, rfc))
+ if hasattr(form.data, "urlencode"): # form was fed a Django QueryDict, not local plain dict
+ d = form.data.copy()
+ for h in meta['headers']:
+ d["sort"] = h["key"]
+ h["sort_url"] = "?" + d.urlencode()
+ if h['key'] == query.get('sort'):
+ h['sorted'] = True
- return (wrapped_results, meta)
-
+ return (results, meta)
-def generate_query_string(request, ignore_list):
- """Recreates the parameter string from the given request, and
- returns it as a string.
- Any parameter names present in ignore_list shall not be put
- in the result string.
- """
- params = []
- for i in request.GET:
- if not i in ignore_list:
- params.append(i + "=" + request.GET[i])
- return "?" + "&".join(params)
-def search_results(request):
- if len(request.REQUEST.items()) == 0:
- return search_main(request)
- form = SearchForm(dict(request.REQUEST.items()))
- if not form.is_valid():
- return HttpResponseBadRequest("form not valid?", mimetype="text/plain")
+def search(request):
+ if request.GET:
+ # backwards compatibility
+ get_params = request.GET.copy()
+ if 'activeDrafts' in request.GET:
+ get_params['activedrafts'] = request.GET['activeDrafts']
+ if 'oldDrafts' in request.GET:
+ get_params['olddrafts'] = request.GET['oldDrafts']
+ if 'subState' in request.GET:
+ get_params['substate'] = request.GET['subState']
- sort_by = None
- if "sortBy" in request.GET:
- sort_by = request.GET["sortBy"]
+ form = SearchForm(get_params)
+ if not form.is_valid():
+ return HttpResponseBadRequest("form not valid: %s" % form.errors)
- (results,meta) = search_query(form.cleaned_data, sort_by)
-
- meta['searching'] = True
- meta['by'] = form.cleaned_data['by']
- meta['rqps'] = generate_query_string(request, ['sortBy'])
- # With a later Django we can do this from the template (incude with tag)
- # Pass the headers and their sort key names
- meta['hdrs'] = [{'htitle': 'Document', 'htype':'doc'},
- {'htitle': 'Title', 'htype':'title'},
- {'htitle': 'Date', 'htype':'date'},
- {'htitle': 'Status', 'htype':'status', 'colspan':'2'},
- {'htitle': 'IPR', 'htype':'ipr'},
- {'htitle': 'Ad/Shepherd', 'htype':'ad'}]
-
- # Make sure we know which one is selected (for visibility later)
- if sort_by:
- for hdr in meta['hdrs']:
- if hdr['htype'] == sort_by:
- hdr['selected'] = True
-
- if 'ajax' in request.REQUEST and request.REQUEST['ajax']:
- return render_to_response('idrfc/search_results.html', {'docs':results, 'meta':meta}, context_instance=RequestContext(request))
- elif form.cleaned_data['lucky'] and len(results)==1:
- doc = results[0]
- if doc.id:
- return HttpResponsePermanentRedirect(doc.id.get_absolute_url())
- else:
- return HttpResponsePermanentRedirect(doc.rfc.get_absolute_url())
+ results, meta = retrieve_search_results(form)
+ meta['searching'] = True
else:
- return render_to_response('idrfc/search_main.html', {'form':form, 'docs':results,'meta':meta}, context_instance=RequestContext(request))
-
+ form = SearchForm()
+ results = []
+ meta = { 'by': None, 'advanced': False, 'searching': False }
-def search_main(request):
- form = SearchForm()
- return render_to_response('idrfc/search_main.html', {'form':form}, context_instance=RequestContext(request))
+ return render_to_response('doc/search.html',
+ {'form':form, 'docs':results, 'meta':meta, 'show_add_to_list': True },
+ context_instance=RequestContext(request))
-def by_ad(request, name):
- ad_id = None
- ad_name = None
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- responsible = Document.objects.values_list('ad', flat=True).distinct()
- for p in Person.objects.filter(Q(role__name__in=("pre-ad", "ad"),
- role__group__type="area",
- role__group__state="active")
- | Q(pk__in=responsible)).distinct():
- if name == p.full_name_as_key():
- ad_id = p.id
- ad_name = p.plain_name()
- break
- else:
- for i in IESGLogin.objects.filter(user_level__in=[1,2]):
- iname = str(i).lower().replace(' ','.')
- if name == iname:
- ad_id = i.id
- ad_name = str(i)
- break
- if not ad_id:
- raise Http404
- form = SearchForm({'by':'ad','ad':ad_id,
- 'rfcs':'on', 'activeDrafts':'on', 'oldDrafts':'on'})
- if not form.is_valid():
- raise ValueError("form did not validate")
- (results,meta) = search_query(form.cleaned_data)
- results.sort(key=lambda obj: obj.view_sort_key_byad())
- return render_to_response('idrfc/by_ad.html', {'form':form, 'docs':results,'meta':meta, 'ad_name':ad_name}, context_instance=RequestContext(request))
-
-def ad_dashboard_group(doc):
-
- if doc.type.slug=='draft':
- if doc.get_state_slug('draft') == 'rfc':
- return 'RFC'
- elif doc.get_state_slug('draft') == 'active' and doc.get_state_slug('draft-iesg'):
- return '%s Internet-Draft' % doc.get_state('draft-iesg').name
- else:
- return '%s Internet-Draft' % doc.get_state('draft').name
- elif doc.type.slug=='conflrev':
- if doc.get_state_slug('conflrev') in ('appr-reqnopub-sent','appr-noprob-sent'):
- return 'Approved Conflict Review'
- elif doc.get_state_slug('conflrev') in ('appr-reqnopub-pend','appr-noprob-pend','appr-reqnopub-pr','appr-noprob-pr'):
- return "%s Conflict Review" % State.objects.get(type__slug='draft-iesg',slug='approved')
- else:
- return '%s Conflict Review' % doc.get_state('conflrev')
- elif doc.type.slug=='statchg':
- if doc.get_state_slug('statchg') in ('appr-sent',):
- return 'Approved Status Change'
- if doc.get_state_slug('statchg') in ('appr-pend','appr-pr'):
- return '%s Status Change' % State.objects.get(type__slug='draft-iesg',slug='approved')
- else:
- return '%s Status Change' % doc.get_state('statchg')
- elif doc.type.slug=='charter':
- if doc.get_state_slug('charter') == 'approved':
- return "Approved Charter"
- else:
- return '%s Charter' % doc.get_state('charter')
- else:
- return "Document"
-
-def ad_dashboard_sort_key(doc):
-
- if doc.type.slug=='draft' and doc.get_state_slug('draft') == 'rfc':
- return "21%04d" % int(doc.rfc_number())
- if doc.type.slug=='statchg' and doc.get_state_slug('statchg') == 'appr-sent':
- return "22%d" % 0 # TODO - get the date of the transition into this state here
- if doc.type.slug=='conflrev' and doc.get_state_slug('conflrev') in ('appr-reqnopub-sent','appr-noprob-sent'):
- return "23%d" % 0 # TODO - get the date of the transition into this state here
- if doc.type.slug=='charter' and doc.get_state_slug('charter') == 'approved':
- return "24%d" % 0 # TODO - get the date of the transition into this state here
-
- seed = ad_dashboard_group(doc)
-
- if doc.type.slug=='conflrev' and doc.get_state_slug('conflrev') == 'adrev':
- state = State.objects.get(type__slug='draft-iesg',slug='ad-eval')
- return "1%d%s" % (state.order,seed)
-
- if doc.type.slug=='charter':
- if doc.get_state_slug('charter') in ('notrev','infrev'):
- return "100%s" % seed
- elif doc.get_state_slug('charter') == 'intrev':
- state = State.objects.get(type__slug='draft-iesg',slug='ad-eval')
- return "1%d%s" % (state.order,seed)
- elif doc.get_state_slug('charter') == 'extrev':
- state = State.objects.get(type__slug='draft-iesg',slug='lc')
- return "1%d%s" % (state.order,seed)
- elif doc.get_state_slug('charter') == 'iesgrev':
- state = State.objects.get(type__slug='draft-iesg',slug='iesg-eva')
- return "1%d%s" % (state.order,seed)
-
- if doc.type.slug=='statchg' and doc.get_state_slug('statchg') == 'adrev':
- state = State.objects.get(type__slug='draft-iesg',slug='ad-eval')
- return "1%d%s" % (state.order,seed)
-
- if seed.startswith('Needs Shepherd'):
- return "100%s" % seed
- if seed.endswith(' Document'):
- seed = seed[:-9]
- elif seed.endswith(' Internet-Draft'):
- seed = seed[:-15]
- elif seed.endswith(' Conflict Review'):
- seed = seed[:-16]
- elif seed.endswith(' Status Change'):
- seed = seed[:-14]
- state = State.objects.filter(type__slug='draft-iesg',name=seed)
- if state:
- ageseconds = 0
- changetime= doc.latest_event(type='changed_document')
- if changetime:
- ad = (datetime.datetime.now()-doc.latest_event(type='changed_document').time)
- ageseconds = (ad.microseconds + (ad.seconds + ad.days * 24 * 3600) * 10**6) / 10**6
- return "1%d%s%s%010d" % (state[0].order,seed,doc.type.slug,ageseconds)
-
- return "3%s" % seed
-
-def by_ad2(request, name):
+def drafts_for_ad(request, name):
+ ad = None
responsible = Document.objects.values_list('ad', flat=True).distinct()
- ad_id = None
for p in Person.objects.filter(Q(role__name__in=("pre-ad", "ad"),
role__group__type="area",
role__group__state="active")
| Q(pk__in=responsible)).distinct():
if name == p.full_name_as_key():
- ad_id = p.id
- ad_name = p.plain_name()
+ ad = p
break
-
- if not ad_id:
+ if not ad:
raise Http404
+ form = SearchForm({'by':'ad','ad': ad.id,
+ 'rfcs':'on', 'activedrafts':'on', 'olddrafts':'on',
+ 'sort': 'status'})
+ results, meta = retrieve_search_results(form)
- docqueryset = Document.objects.filter(ad__id=ad_id)
- docs=[]
- for doc in docqueryset:
- doc.ad_dashboard_sort_key = ad_dashboard_sort_key(doc)
- doc.ad_dashboard_group = ad_dashboard_group(doc)
- if doc.get_state_slug() == 'rfc':
- doc.display_date = doc.latest_event(type='published_rfc').time
- else:
- revision = doc.latest_event(type='new_revision')
- if revision:
- doc.display_date = revision.time
- # This might be better handled as something Documents know about themselves
- now = datetime.datetime.now()
- doc.can_expire = (doc.type.slug=='draft' and doc.get_state_slug('draft')=='active' and ( not doc.get_state('draft-iesg') or doc.get_state('draft-iesg').order >= 42) and doc.expires>now)
- if doc.get_state_slug('draft') == 'rfc':
- doc.obsoleted_by = ", ".join([ 'RFC %04d' % int(rel.source.rfc_number()) for alias in doc.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='obsoletes') ] )
- doc.updated_by = ", ".join([ 'RFC %04d' % int(rel.source.rfc_number()) for alias in doc.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='updates') ] )
- doc.has_errata = bool(doc.tags.filter(slug="errata"))
- else:
- s = doc.get_state("draft-rfceditor")
- if s:
- # extract possible extra annotations
- tags = doc.tags.filter(slug__in=("iana", "ref"))
- doc.rfc_editor_state = "*".join([s.name] + [t.slug.upper() for t in tags])
- if doc.type.slug == 'draft':
- doc.iprCount = IprDraft.objects.filter(document=doc, ipr__status__in=[1,3]).count()
- doc.iprUrl = "/ipr/search?option=document_search&id_document_tag=%s" % doc.name
- docs.append(doc)
- docs.sort(key=ad_dashboard_sort_key)
- return render_to_response('idrfc/by_ad2.html',{'docs':docs,'ad_name':ad_name}, context_instance=RequestContext(request))
+ for d in results:
+ if d.get_state_slug() == "active":
+ iesg_state = d.get_state("draft-iesg")
+ if iesg_state:
+ if iesg_state.slug == "dead":
+ d.search_heading = "IESG Dead Internet-Drafts"
+ else:
+ d.search_heading = "%s Internet-Drafts" % iesg_state.name
+ return render_to_response('doc/drafts_for_ad.html',
+ { 'form':form, 'docs':results, 'meta':meta, 'ad_name': ad.plain_name() },
+ context_instance=RequestContext(request))
-@cache_page(15*60) # 15 minutes
-def all(request):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- active = (dict(filename=n) for n in InternetDraft.objects.filter(states__type="draft", states__slug="active").order_by("name").values_list('name', flat=True))
- rfc1 = (dict(filename=d, rfc_number=int(n[3:])) for d, n in DocAlias.objects.filter(document__states__type="draft", document__states__slug="rfc", name__startswith="rfc").exclude(document__name__startswith="rfc").order_by("document__name").values_list('document__name','name').distinct())
- rfc2 = (dict(rfc_number=r, draft=None) for r in sorted(int(n[3:]) for n in Document.objects.filter(type="draft", name__startswith="rfc").values_list('name', flat=True)))
- dead = InternetDraft.objects.exclude(states__type="draft", states__slug__in=("active", "rfc")).select_related("states").order_by("name")
+def drafts_in_last_call(request):
+ lc_state = State.objects.get(type="draft-iesg", slug="lc").pk
+ form = SearchForm({'by':'state','state': lc_state, 'rfcs':'on', 'activedrafts':'on'})
+ results, meta = retrieve_search_results(form)
+
+ return render_to_response('doc/drafts_in_last_call.html',
+ { 'form':form, 'docs':results, 'meta':meta },
+ context_instance=RequestContext(request))
+
+def drafts_in_iesg_process(request, last_call_only=None):
+ if last_call_only:
+ states = State.objects.filter(type="draft-iesg", slug__in=("lc", "writeupw", "goaheadw"))
+ title = "Documents in Last Call"
else:
- active = InternetDraft.objects.all().filter(status=1).order_by("filename").values('filename')
- rfc1 = InternetDraft.objects.all().filter(status=3).order_by("filename").values('filename','rfc_number')
- rfc_numbers1 = InternetDraft.objects.all().filter(status=3).values_list('rfc_number', flat=True)
- rfc2 = RfcIndex.objects.all().exclude(rfc_number__in=rfc_numbers1).order_by('rfc_number').values('rfc_number','draft')
- dead = InternetDraft.objects.all().exclude(status__in=[1,3]).order_by("filename").select_related('status__status')
- return render_to_response('idrfc/all.html', {'active':active, 'rfc1':rfc1, 'rfc2':rfc2, 'dead':dead}, context_instance=RequestContext(request))
+ states = State.objects.filter(type="draft-iesg").exclude(slug__in=('pub', 'dead', 'watching', 'rfcqueue'))
+ title = "Documents in IESG process"
-@cache_page(15*60) # 15 minutes
-def active(request):
- groups = IETFWG.objects.exclude(group_acronym=1027)
- individual = IETFWG.objects.get(group_acronym=1027)
- return render_to_response("idrfc/active.html", {'groups':groups,'individual':individual}, context_instance=RequestContext(request))
+ grouped_docs = []
-def in_last_call(request):
-
- lcdocs = []
+ for s in states.order_by("order"):
+ docs = Document.objects.filter(type="draft", states=s).distinct().order_by("time").select_related("ad", "group", "group__parent")
+ if docs:
+ if s.slug == "lc":
+ for d in docs:
+ e = d.latest_event(LastCallDocEvent, type="sent_last_call")
+ d.lc_expires = e.expires if e else datetime.datetime.min
+ docs = list(docs)
+ docs.sort(key=lambda d: d.lc_expires)
- for p in InternetDraft.objects.all().filter(idinternal__primary_flag=1).filter(idinternal__cur_state__state='In Last Call'):
- if (p.idinternal.rfc_flag):
- lcdocs.append(IdRfcWrapper(None,RfcWrapper(p)))
- else:
- lcdocs.append(IdRfcWrapper(IdWrapper(p),None))
+ grouped_docs.append((s, docs))
- return render_to_response("idrfc/in_last_call.html", {'lcdocs':lcdocs}, context_instance=RequestContext(request))
+ return render_to_response('doc/drafts_in_iesg_process.html', {
+ "grouped_docs": grouped_docs,
+ "title": title,
+ "last_call_only": last_call_only,
+ }, context_instance=RequestContext(request))
+
+def index_all_drafts(request):
+ # try to be efficient since this view returns a lot of data
+ categories = []
+
+ for s in ("active", "rfc", "expired", "repl", "auth-rm", "ietf-rm"):
+ state = State.objects.get(type="draft", slug=s)
+
+ if state.slug == "rfc":
+ heading = "RFCs"
+ elif state.slug in ("ietf-rm", "auth-rm"):
+ heading = "Internet-Drafts %s" % state.name
+ else:
+ heading = "%s Internet-Drafts" % state.name
+
+ draft_names = DocAlias.objects.filter(document__states=state).values_list("name", "document")
+
+ names = []
+ names_to_skip = set()
+ for name, doc in draft_names:
+ sort_key = name
+ if name != doc:
+ if not name.startswith("rfc"):
+ name, doc = doc, name
+ names_to_skip.add(doc)
+
+ if name.startswith("rfc"):
+ name = name.upper()
+ sort_key = -int(name[3:])
+
+ names.append((name, sort_key))
+
+ names.sort(key=lambda t: t[1])
+
+ names = ['' + name +''
+ for name, _ in names if name not in names_to_skip]
+
+ categories.append((state,
+ heading,
+ len(names),
+ " ".join(names)
+ ))
+ return render_to_response('doc/index_all_drafts.html', { "categories": categories },
+ context_instance=RequestContext(request))
+
+def index_active_drafts(request):
+ groups = active_drafts_index_by_group()
+
+ return render_to_response("doc/index_active_drafts.html", { 'groups': groups }, context_instance=RequestContext(request))
diff --git a/ietf/idtracker/README b/ietf/idtracker/README
deleted file mode 100644
index 815328d30..000000000
--- a/ietf/idtracker/README
+++ /dev/null
@@ -1,56 +0,0 @@
-form_for_model(IDInternal) will autogenerate form elemnts to edit the model
-
-class ImageAddForm(BaseForm):
-
- def __init__(self, *args, name=None, **kwargs):
- super(ImageAddForm, self).__init__(*args, **kwargs)
- self.fields['category'].choices=(('a','a'),)
- # create filter based on name=
-
-ImageForm = form_for_model(Image, form=ImageAddForm)
-foo = ImageForm(name='foo')
-
-
-
-To get from draft to author list:
-
->>> d = a[5]
->>> print d
-draft-fenner-zinin-rtg-standard-reqts
->>> print d.authors.all()
-[, ]
->>> l=d.authors.all()
->>> print l[0].person
-Bill Fenner
->>> print l[0].person.emailaddresses_set.filter(priority=d.id_document_tag)
-[]
->>> print l[0].person.emailaddresses_set.filter(priority=d.id_document_tag)[0].ail_address
-fenner@research.att.com
-
-IDAuthors should have an auxilliary function for this.
-It's the one that has the person linkage and knows the document.
-
-
---
-we should use a variant of django-registration.
-http://www.stonemind.net/blog/2007/04/13/django-registration-for-newbies/
-
-1. verify email address with round trip
-2. if there's a row in iesg_login, use that username
- (? liaison tool logins ?)
- otherwise, force the email address
-3. get a password and create the user
- (this is almost the same as resetting the password)
-4. find the person_or_org_info row, associate that with
- the user row
-
---
-
- Both the regular and date-base object_detail can take either an
-+object_id, or a slug/slug_field combo.
- So use the username as the "slug" and specify 'username' as the
-+'slug_field' argument.
-
-http://www.b-list.org/weblog/2006/11/16/django-tips-get-most-out-generic-views
-
-newly learned: 'slug_field' just gets passed so can be otherdb__username
diff --git a/ietf/idtracker/feeds.py b/ietf/idtracker/feeds.py
deleted file mode 100644
index 4b4a5f678..000000000
--- a/ietf/idtracker/feeds.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright The IETF Trust 2007, All Rights Reserved
-
-from django.conf import settings
-from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
-from django.utils.feedgenerator import Atom1Feed
-from ietf.idtracker.models import IDInternal
-import datetime
-import re
-
-class DocumentComments(Feed):
- feed_type = Atom1Feed
- def get_object(self, bits):
- if len(bits) != 1:
- raise IDInternal.DoesNotExist
- rfc = re.match('rfc(\d+)', bits[0])
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- return IDInternal.objects.get(docalias__name=bits[0])
-
- if rfc:
- return IDInternal.objects.get(draft=int(rfc.group(1)), rfc_flag=1)
- else:
- return IDInternal.objects.get(draft__filename=bits[0], rfc_flag=0)
-
- def title(self, obj):
- # filename is a function for RFCs and an attribute for I-Ds.
- # This works transparently for templates but is not transparent
- # for python.
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- return "I-D Tracker comments for %s" % obj.filename
-
- if obj.rfc_flag:
- filename = obj.document().filename()
- else:
- filename = obj.document().filename
- return "I-D Tracker comments for %s" % filename
-
- def link(self, obj):
- if obj is None:
- raise FeedDoesNotExist
- return obj.get_absolute_url()
-
- def description(self, obj):
- return self.title(obj)
-
- def items(self, obj):
- return obj.public_comments().order_by("-date","-id")
-
- def item_pubdate(self, item):
- return item.datetime()
-
- def item_author_name(self, item):
- return item.get_author()
-
-class InLastCall(Feed):
- title = "Documents in Last Call"
- feed_type = Atom1Feed
- author_name = 'IESG Secretary'
- link = "/idtracker/status/last-call/"
-
- def items(self):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- ret = list(IDInternal.objects.filter(states__type="draft-iesg", states__slug="lc"))
- else:
- ret = list(IDInternal.objects.filter(primary_flag=1).filter(cur_state__state='In Last Call'))
- ret.sort(key=lambda item: (item.document().lc_expiration_date or datetime.date.today()))
- return ret
-
- def item_pubdate(self, item):
- # this method needs to return a datetime instance, even
- # though the database has only date, not time
- return datetime.datetime.combine((item.document().lc_sent_date or datetime.datetime.now().date()), datetime.time(0,0,0))
-
diff --git a/ietf/idtracker/fixtures/.gitignore b/ietf/idtracker/fixtures/.gitignore
deleted file mode 100644
index a74b07aee..000000000
--- a/ietf/idtracker/fixtures/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/*.pyc
diff --git a/ietf/idtracker/fixtures/wgtest.xml b/ietf/idtracker/fixtures/wgtest.xml
deleted file mode 100644
index 5c7bd6174..000000000
--- a/ietf/idtracker/fixtures/wgtest.xml
+++ /dev/null
@@ -1,151 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ietf/idtracker/sitemaps.py b/ietf/idtracker/sitemaps.py
deleted file mode 100644
index 650a4a94a..000000000
--- a/ietf/idtracker/sitemaps.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright The IETF Trust 2007, All Rights Reserved
-#
-from django.contrib.sitemaps import Sitemap
-from django.conf import settings
-from ietf.idtracker.models import IDInternal, InternetDraft
-
-class IDTrackerMap(Sitemap):
- changefreq = "always"
- def items(self):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- return IDInternal.objects.all()
- else:
- return IDInternal.objects.exclude(draft=999999)
-
-class DraftMap(Sitemap):
- changefreq = "always"
- def items(self):
- return InternetDraft.objects.all()
- def location(self, obj):
- return "/drafts/%s/" % obj.filename
- def lastmod(self, obj):
- return obj.last_modified_date
diff --git a/ietf/idtracker/templatetags/ietf_filters.py b/ietf/idtracker/templatetags/ietf_filters.py
index 77ea5f946..3afffac2a 100644
--- a/ietf/idtracker/templatetags/ietf_filters.py
+++ b/ietf/idtracker/templatetags/ietf_filters.py
@@ -31,9 +31,18 @@ def expand_comma(value):
def format_charter(value):
return value.replace("\n\n", "
").replace("\n"," \n")
-@register.filter(name='indent')
-def indent(value,numspaces=2):
- return value.replace("\n", "\n"+" "*int(numspaces));
+@register.filter
+def indent(value, numspaces=2):
+ replacement = "\n" + " " * int(numspaces)
+ res = value.replace("\n", replacement)
+ if res.endswith(replacement):
+ res = res[:-int(numspaces)] # fix up superfluous spaces
+ return res
+
+@register.filter
+def unindent(value):
+ """Remove indentation from string."""
+ return re.sub("\n +", "\n", value)
@register.filter(name='parse_email_list')
def parse_email_list(value):
@@ -241,6 +250,11 @@ def dashify(string):
"""
return re.sub('.', '-', string)
+@register.filter
+def underline(string):
+ """Return string with an extra line underneath of dashes, for plain text underlining."""
+ return string + "\n" + ("-" * len(string))
+
@register.filter(name='lstrip')
def lstripw(string, chars):
"""Strip matching leading characters from words in string"""
@@ -320,23 +334,6 @@ def wrap_text(text, width=72):
prev_indent = indent
return "\n".join(filled)
-@register.filter(name="id_index_file_types")
-def id_index_file_types(text):
- r = ".txt"
- if text.find("txt") < 0:
- return r
- if text.find("ps") >= 0:
- r = r + ",.ps"
- if text.find("pdf") >= 0:
- r = r + ",.pdf"
- return r
-
-@register.filter(name="id_index_wrap")
-def id_index_wrap(text):
- x = wordwrap(text, 72)
- x = x.replace("\n", "\n ")
- return " "+x.strip()
-
@register.filter(name="compress_empty_lines")
def compress_empty_lines(text):
text = re.sub("( *\n){3,}", "\n\n", text)
@@ -408,14 +405,6 @@ def expires_soon(x,request):
days = 14
return x > -days
-@register.filter(name='greater_than')
-def greater_than(x, y):
- return x > int(y)
-
-@register.filter(name='less_than')
-def less_than(x, y):
- return x < int(y)
-
@register.filter(name='equal')
def equal(x, y):
return str(x)==str(y)
@@ -470,32 +459,22 @@ def format_history_text(text):
full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(full)))))
snippet = truncate_html_words(full, 25)
if snippet != full:
- return mark_safe(u'
%s[show all]
%s
' % (snippet, full))
+ return mark_safe(u'
%s[show all]
%s
' % (snippet, full))
return full
-@register.filter
-def user_roles_json(user):
- roles = {}
- if not isinstance(user, basestring) and user.is_authenticated():
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- from ietf.group.models import Role
- for r in Role.objects.filter(person__user=user).select_related(depth=1):
- if r.name_id == "secr" and r.group.acronym == "secretariat":
- roles["Secretariat"] = True
- elif r.name_id == "ad" and r.group.type_id == "area" and r.group.state_id == "active":
- roles["Area Director"] = roles["Area_Director"] = True
- else:
- for g in user.groups.all():
- roles[g.name] = True
- return mark_safe(simplejson.dumps(roles))
-
@register.filter
def textify(text):
text = re.sub("?b>", "*", text)
text = re.sub("?i>", "/", text)
# There are probably additional conversions we should apply here
return text
-
+
+@register.filter
+def state(doc, slug):
+ if slug == "stream": # convenient shorthand
+ slug = "%s-stream-%s" % (doc.type_id, doc.stream_id)
+ return doc.get_state(slug)
+
def _test():
import doctest
doctest.testmod()
diff --git a/ietf/idtracker/templatetags/versiontags.py b/ietf/idtracker/templatetags/versiontags.py
deleted file mode 100644
index 893e4b407..000000000
--- a/ietf/idtracker/templatetags/versiontags.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright The IETF Trust 2007, All Rights Reserved
-
-from django import template
-from ietf import __date__, __rev__, __version__, __id__
-
-
-register = template.Library()
-
-
-@register.simple_tag
-def revision_time():
- return __date__[7:32]
-
-@register.simple_tag
-def revision_date():
- return __date__[34:-3]
-
-@register.simple_tag
-def revision_num():
- return __rev__[6:-2]
-
-@register.simple_tag
-def revision_id():
- return __id__[5:-2]
-
-@register.simple_tag
-def version_num():
- return __version__
-
diff --git a/ietf/idtracker/tests.py b/ietf/idtracker/tests.py
index d9b63ba7a..7c2c3aaa7 100644
--- a/ietf/idtracker/tests.py
+++ b/ietf/idtracker/tests.py
@@ -1,42 +1,10 @@
# Copyright The IETF Trust 2007, All Rights Reserved
#
-import doctest
+import doctest, unittest
+
from ietf.idtracker.templatetags import ietf_filters
-import unittest
-from ietf.utils.test_utils import SimpleUrlTestCase, canonicalize_feed, canonicalize_sitemap
-import django.test
class TemplateTagTest(unittest.TestCase):
- def testTemplateTags(self):
- print " Testing ietf_filters"
- #doctest.testmod(ietf_filters,verbose=True)
- (failures, tests) = doctest.testmod(ietf_filters)
+ def test_template_tags(self):
+ failures, tests = doctest.testmod(ietf_filters)
self.assertEqual(failures, 0)
- print "OK (ietf_filters)"
-
-class IdTrackerUrlTestCase(SimpleUrlTestCase):
- def testUrls(self):
- self.doTestUrls(__file__)
- def doCanonicalize(self, url, content):
- if url.startswith("/feed/"):
- return canonicalize_feed(content)
- elif url.startswith("/sitemap"):
- return canonicalize_sitemap(content)
- else:
- return content
-
-# class WGRoleTest(django.test.TestCase):
-# fixtures = ['wgtest']
-#
-# def setUp(self):
-# from ietf.idtracker.models import IETFWG
-# self.xmas = IETFWG.objects.get(group_acronym__acronym='xmas')
-# self.snow = IETFWG.objects.get(group_acronym__acronym='snow')
-#
-# def test_roles(self):
-# print " Testing WG roles"
-# self.assertEquals(self.xmas.wgchair_set.all()[0].role(), 'xmas WG Chair')
-# self.assertEquals(self.snow.wgchair_set.all()[0].role(), 'snow BOF Chair')
-# self.assertEquals(self.xmas.wgsecretary_set.all()[0].role(), 'xmas WG Secretary')
-# self.assertEquals(self.xmas.wgtechadvisor_set.all()[0].role(), 'xmas Technical Advisor')
-# print "OK"
diff --git a/ietf/idtracker/testurl.list b/ietf/idtracker/testurl.list
deleted file mode 100644
index 0b28acb1f..000000000
--- a/ietf/idtracker/testurl.list
+++ /dev/null
@@ -1,25 +0,0 @@
-200 /idtracker/help/state/
-200 /idtracker/help/state/12/
-200 /idtracker/help/substate/1/
-301 /idtracker/help/evaluation/
-200 /idtracker/status/
-200 /idtracker/status/last-call/
-
-301 /idtracker/rfc3847/
-301 /idtracker/draft-ietf-isis-link-attr/
-301 /idtracker/draft-eronen-tls-psk/ # no IESG information
-301 /idtracker/
-200 /feed/comments/draft-ietf-isis-link-attr/
-200 /feed/comments/rfc3373/
-200 /feed/last-call/
-
-# An RFC with no matching value in InternetDrafts. This tests
-# subtle cases of using the draft relation when it's not appropriate.
-# See ticket #218.
-301 /idtracker/rfc2444/
-200 /feed/comments/rfc2444/
-
-# Test case for missing comment time (bug fixed in changeset 1733)
-200 /feed/comments/draft-ietf-msec-newtype-keyid/
-
-#200,heavy /sitemap-idtracker.xml
diff --git a/ietf/idtracker/urls.py b/ietf/idtracker/urls.py
deleted file mode 100644
index 300c43614..000000000
--- a/ietf/idtracker/urls.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright The IETF Trust 2007, All Rights Reserved
-
-from django.conf.urls.defaults import patterns, url
-from ietf.idtracker.models import IDState, IDSubState
-from ietf.idtracker import views
-from django.views.generic.simple import redirect_to
-
-urlpatterns = patterns('django.views.generic.simple',
- url(r'^help/state/$', 'direct_to_template', { 'template': 'idtracker/states.html', 'extra_context': { 'states': IDState.objects.all(), 'substates': IDSubState.objects.all() } }, name="help_states"),
- (r'^help/evaluation/$', redirect_to, {'url':'http://www.ietf.org/iesg/voting-procedures.html' }),
-)
-urlpatterns += patterns('',
- (r'^status/$', views.status),
- (r'^status/last-call/$', views.last_call),
-)
-urlpatterns += patterns('',
- (r'^rfc0*(?P\d+)/$', views.redirect_rfc),
- (r'^(?P\d+)/$', views.redirect_id),
- (r'^(?P[^/]+)/$', views.redirect_filename),
- (r'^comment/(?P\d+)/$', views.redirect_comment),
- (r'^ballot/(?P\d+)/$', views.redirect_ballot),
- (r'^([^/]+)/comment/(?P\d+)/$', views.redirect_comment),
- (r'^help/state/(?P\d+)/$', views.state_desc),
- (r'^help/substate/(?P\d+)/$', views.state_desc, { 'is_substate': 1 }),
- (r'^$', redirect_to, { 'url': '/doc/'}),
-)
diff --git a/ietf/idtracker/views.py b/ietf/idtracker/views.py
deleted file mode 100644
index a61411f05..000000000
--- a/ietf/idtracker/views.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright The IETF Trust 2007, All Rights Reserved
-
-# Create your views here.
-from django.http import HttpResponsePermanentRedirect, Http404
-from django.conf import settings
-from django.template import RequestContext
-from django.shortcuts import get_object_or_404, render_to_response
-from django.views.generic.list_detail import object_detail, object_list
-from ietf.idtracker.models import InternetDraft, IDInternal, IDState, IDSubState, BallotInfo, DocumentComment
-import re, datetime
-
-def state_desc(request, state, is_substate=0):
- if int(state) == 100:
- object = {
- 'state': 'I-D Exists',
- 'description': """
-Initial (default) state for all internet drafts. Such documents are
-not being tracked by the IESG as no request has been made of the
-IESG to do anything with the document.
-"""
- }
- elif is_substate:
- sub = get_object_or_404(IDSubState, pk=state)
- object = { 'state': sub.sub_state, 'description': sub.description }
- else:
- object = get_object_or_404(IDState, pk=state)
- return render_to_response('idtracker/state_desc.html', {'state': object},
- context_instance=RequestContext(request))
-
-def status(request):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- drafts = IDInternal.objects.filter(states__type="draft-iesg").exclude(states__type="draft-iesg", states__slug__in=('pub', 'dead', 'watching', 'rfcqueue')).distinct().order_by('states__order')
- drafts = [ d for d in drafts if not d.replaced_by ]
- drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
- # sadly we can't use the generic view because it only works with a queryset...
- return render_to_response('idtracker/status_of_items.html', dict(object_list=drafts, title="IESG Status of Items"), context_instance=RequestContext(request))
-
- queryset = IDInternal.objects.filter(primary_flag=1).exclude(cur_state__state__in=('RFC Ed Queue', 'RFC Published', 'AD is watching', 'Dead')).order_by('cur_state', 'status_date', 'ballot')
- return object_list(request, template_name="idtracker/status_of_items.html", queryset=queryset, extra_context={'title': 'IESG Status of Items'})
-
-def last_call(request):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- drafts = list(IDInternal.objects.filter(states__type="draft-iesg", states__slug__in=('lc', 'writeupw', 'goaheadw')).distinct().order_by('states__order'))
- drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
- # sadly we can't use the generic view because it only works with a queryset...
- return render_to_response('idtracker/status_of_items.html', dict(object_list=drafts, title="Documents in Last Call", lastcall=1), context_instance=RequestContext(request))
-
- queryset = IDInternal.objects.filter(primary_flag=1).filter(cur_state__state__in=('In Last Call', 'Waiting for Writeup', 'Waiting for AD Go-Ahead')).order_by('cur_state', 'status_date', 'ballot')
- return object_list(request, template_name="idtracker/status_of_items.html", queryset=queryset, extra_context={'title': 'Documents in Last Call', 'lastcall': 1})
-
-def redirect_id(request, object_id):
- '''Redirect from historical document ID to preferred filename url.'''
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- raise Http404() # we don't store the numbers anymore
-
- doc = get_object_or_404(InternetDraft, id_document_tag=object_id)
- return HttpResponsePermanentRedirect("/doc/"+doc.filename+"/")
-
-def redirect_rfc(request, rfc_number):
- return HttpResponsePermanentRedirect("/doc/rfc"+rfc_number+"/")
-
-def redirect_filename(request, filename):
- return HttpResponsePermanentRedirect("/doc/"+filename+"/")
-
-def redirect_ballot(request, object_id):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- raise Http404() # we don't store the numbers anymore
-
- ballot = get_object_or_404(BallotInfo, pk=object_id)
- ids = ballot.drafts.filter(primary_flag=1)
- if len(ids) == 0:
- raise Http404("Ballot does not correspond to any document")
- id = ids[0]
- if id.rfc_flag:
- return HttpResponsePermanentRedirect("/doc/rfc"+str(id.draft_id)+"/#ballot")
- else:
- return HttpResponsePermanentRedirect("/doc/"+id.draft.filename+"/#ballot")
-
-def redirect_comment(request, object_id):
- if settings.USE_DB_REDESIGN_PROXY_CLASSES:
- raise Http404() # we don't store the numbers anymore
-
- comment = get_object_or_404(DocumentComment, pk=object_id)
- id = comment.document
- if id.rfc_flag:
- return HttpResponsePermanentRedirect("/doc/rfc"+str(id.draft_id)+"/#history-"+str(object_id))
- else:
- return HttpResponsePermanentRedirect("/doc/"+id.draft.filename+"/#history-"+str(object_id))
-
diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py
index 83a55151d..406bdb234 100644
--- a/ietf/iesg/tests.py
+++ b/ietf/iesg/tests.py
@@ -505,11 +505,11 @@ class DeferUndeferTestCase(django.test.TestCase):
self.assertEquals(len(q('form.defer')),1)
# defer
- self.assertEquals(doc.telechat_date,first_date)
+ self.assertEquals(doc.telechat_date(), first_date)
r = self.client.post(url,dict())
self.assertEquals(r.status_code, 302)
doc = Document.objects.get(name=name)
- self.assertEquals(doc.telechat_date,second_date)
+ self.assertEquals(doc.telechat_date(), second_date)
self.assertTrue(doc.returning_item())
defer_states = dict(draft=['draft-iesg','defer'],conflrev=['conflrev','defer'])
if doc.type_id in defer_states:
@@ -547,11 +547,11 @@ class DeferUndeferTestCase(django.test.TestCase):
self.assertEquals(len(q('form.undefer')),1)
# undefer
- self.assertEquals(doc.telechat_date,second_date)
+ self.assertEquals(doc.telechat_date(), second_date)
r = self.client.post(url,dict())
self.assertEquals(r.status_code, 302)
doc = Document.objects.get(name=name)
- self.assertEquals(doc.telechat_date,first_date)
+ self.assertEquals(doc.telechat_date(), first_date)
self.assertTrue(doc.returning_item())
undefer_states = dict(draft=['draft-iesg','iesg-eva'],conflrev=['conflrev','iesgeval'])
if doc.type_id in undefer_states:
diff --git a/ietf/iesg/views.py b/ietf/iesg/views.py
index bd995abfb..024221151 100644
--- a/ietf/iesg/views.py
+++ b/ietf/iesg/views.py
@@ -515,8 +515,7 @@ class RescheduleForm(forms.Form):
self.fields['telechat_date'].choices = choices
def handle_reschedule_form(request, doc, dates):
- initial = dict(
- telechat_date=doc.telechat_date if doc.on_upcoming_agenda() else None)
+ initial = dict(telechat_date=doc.telechat_date())
formargs = dict(telechat_dates=dates,
prefix="%s" % doc.name,
@@ -551,11 +550,11 @@ def agenda_documents(request):
i.reschedule_form = handle_reschedule_form(request, i, dates)
# some may have been taken off the schedule by the reschedule form
- docs = filter(lambda x: x.on_upcoming_agenda(), docs)
-
+ docs = [d for d in docs if d.telechat_date()]
+
telechats = []
for date in dates:
- matches = filter(lambda x: x.telechat_date == date, docs)
+ matches = filter(lambda x: x.telechat_date() == date, docs)
res = {}
for i in matches:
section_key = "s" + get_doc_section(i)
diff --git a/ietf/ipr/models.py b/ietf/ipr/models.py
index 65ec0d41d..9b84a3a24 100644
--- a/ietf/ipr/models.py
+++ b/ietf/ipr/models.py
@@ -2,9 +2,6 @@
from django.db import models
from django.conf import settings
-#from django import newforms as forms
-from ietf.idtracker.views import InternetDraft
-from ietf.idtracker.models import Rfc
from ietf.utils.lazy import reverse_lazy
# ------------------------------------------------------------------------
@@ -139,9 +136,6 @@ class IprDetail(models.Model):
return None
except IprContact.MultipleObjectsReturned:
return self.contact.filter(contact_type=3)[0]
- class Meta:
- if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
- db_table = 'ipr_detail'
class IprContact(models.Model):
TYPE_CHOICES = (
@@ -162,20 +156,8 @@ class IprContact(models.Model):
email = models.EmailField(max_length=255)
def __str__(self):
return self.name or ''
- class Meta:
- if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
- db_table = 'ipr_contacts'
-class IprDraft(models.Model):
- ipr = models.ForeignKey(IprDetail, related_name='drafts_old' if settings.USE_DB_REDESIGN_PROXY_CLASSES else 'drafts')
- document = models.ForeignKey(InternetDraft, db_column='id_document_tag', related_name="ipr_draft_old" if settings.USE_DB_REDESIGN_PROXY_CLASSES else "ipr")
- revision = models.CharField(max_length=2)
- def __str__(self):
- return "%s which applies to %s-%s" % ( self.ipr, self.document, self.revision )
- class Meta:
- db_table = 'ipr_ids'
-
class IprNotification(models.Model):
ipr = models.ForeignKey(IprDetail)
notification = models.TextField(blank=True)
@@ -183,94 +165,70 @@ class IprNotification(models.Model):
time_sent = models.CharField(blank=True, max_length=25)
def __str__(self):
return "IPR notification for %s sent %s %s" % (self.ipr, self.date_sent, self.time_sent)
- class Meta:
- if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
- db_table = 'ipr_notifications'
-
-class IprRfc(models.Model):
- ipr = models.ForeignKey(IprDetail, related_name='rfcs_old' if settings.USE_DB_REDESIGN_PROXY_CLASSES else 'rfcs')
- document = models.ForeignKey(Rfc, db_column='rfc_number', related_name="ipr_rfc_old" if settings.USE_DB_REDESIGN_PROXY_CLASSES else "ipr")
- def __str__(self):
- return "%s applies to RFC%04d" % ( self.ipr, self.document_id )
- class Meta:
- db_table = 'ipr_rfcs'
class IprUpdate(models.Model):
ipr = models.ForeignKey(IprDetail, related_name='updates')
updated = models.ForeignKey(IprDetail, db_column='updated', related_name='updated_by')
status_to_be = models.IntegerField(null=True, blank=True)
processed = models.IntegerField(null=True, blank=True)
+
+
+from ietf.doc.models import DocAlias
+
+class IprDocAlias(models.Model):
+ ipr = models.ForeignKey(IprDetail, related_name='documents')
+ doc_alias = models.ForeignKey(DocAlias)
+ rev = models.CharField(max_length=2, blank=True)
+ def __unicode__(self):
+ if self.rev:
+ return u"%s which applies to %s-%s" % (self.ipr, self.doc_alias.name, self.rev)
+ else:
+ return u"%s which applies to %s" % (self.ipr, self.doc_alias.name)
+
class Meta:
- if not settings.USE_DB_REDESIGN_PROXY_CLASSES:
- db_table = 'ipr_updates'
+ verbose_name = "IPR document alias"
+ verbose_name_plural = "IPR document aliases"
+# proxy stuff
-if settings.USE_DB_REDESIGN_PROXY_CLASSES or hasattr(settings, "IMPORTING_IPR"):
- from ietf.doc.models import DocAlias
-
- class IprDocAlias(models.Model):
- ipr = models.ForeignKey(IprDetail, related_name='documents')
- doc_alias = models.ForeignKey(DocAlias)
- rev = models.CharField(max_length=2, blank=True)
- def __unicode__(self):
- if self.rev:
- return u"%s which applies to %s-%s" % (self.ipr, self.doc_alias.name, self.rev)
- else:
- return u"%s which applies to %s" % (self.ipr, self.doc_alias.name)
+from ietf.utils.proxy import TranslatingManager
- class Meta:
- verbose_name = "IPR document alias"
- verbose_name_plural = "IPR document aliases"
+class IprDraftProxy(IprDocAlias):
+ objects = TranslatingManager(dict(document="doc_alias__name"))
- # proxy stuff
- IprDraftOld = IprDraft
- IprRfcOld = IprRfc
+ # document = models.ForeignKey(InternetDraft, db_column='id_document_tag', "ipr")
+ # document = models.ForeignKey(Rfc, db_column='rfc_number', related_name="ipr")
+ @property
+ def document(self):
+ from ietf.doc.proxy import DraftLikeDocAlias
+ return DraftLikeDocAlias.objects.get(pk=self.doc_alias_id)
- from ietf.utils.proxy import TranslatingManager
-
- class IprDraftProxy(IprDocAlias):
- objects = TranslatingManager(dict(document="doc_alias__name"))
-
- # document = models.ForeignKey(InternetDraft, db_column='id_document_tag', "ipr")
- # document = models.ForeignKey(Rfc, db_column='rfc_number', related_name="ipr")
- @property
- def document(self):
- from ietf.doc.proxy import DraftLikeDocAlias
- return DraftLikeDocAlias.objects.get(pk=self.doc_alias_id)
-
- #revision = models.CharField(max_length=2)
- @property
- def revision(self):
- return self.rev
-
- class Meta:
- proxy = True
+ #revision = models.CharField(max_length=2)
+ @property
+ def revision(self):
+ return self.rev
- IprDraft = IprDraftProxy
+ class Meta:
+ proxy = True
- class IprRfcProxy(IprDocAlias):
- objects = TranslatingManager(dict(document=lambda v: ("doc_alias__name", "rfc%s" % v)))
-
- # document = models.ForeignKey(InternetDraft, db_column='id_document_tag', "ipr")
- # document = models.ForeignKey(Rfc, db_column='rfc_number', related_name="ipr")
- @property
- def document(self):
- from ietf.doc.proxy import DraftLikeDocAlias
- return DraftLikeDocAlias.objects.get(pk=self.doc_alias_id)
-
- #revision = models.CharField(max_length=2)
- @property
- def revision(self):
- return self.rev
-
- class Meta:
- proxy = True
+IprDraft = IprDraftProxy
- IprRfc = IprRfcProxy
-
+class IprRfcProxy(IprDocAlias):
+ objects = TranslatingManager(dict(document=lambda v: ("doc_alias__name", "rfc%s" % v)))
+ # document = models.ForeignKey(InternetDraft, db_column='id_document_tag', "ipr")
+ # document = models.ForeignKey(Rfc, db_column='rfc_number', related_name="ipr")
+ @property
+ def document(self):
+ from ietf.doc.proxy import DraftLikeDocAlias
+ return DraftLikeDocAlias.objects.get(pk=self.doc_alias_id)
-# changes done by convert-096.py:changed maxlength to max_length
-# removed core
-# removed edit_inline
-# removed raw_id_admin
+ #revision = models.CharField(max_length=2)
+ @property
+ def revision(self):
+ return self.rev
+
+ class Meta:
+ proxy = True
+
+IprRfc = IprRfcProxy
diff --git a/ietf/ipr/urls.py b/ietf/ipr/urls.py
index 77a00f9a1..43ad3749f 100644
--- a/ietf/ipr/urls.py
+++ b/ietf/ipr/urls.py
@@ -15,7 +15,7 @@ urlpatterns = patterns('',
(r'^new-(?Pspecific)/$', new.new),
(r'^new-(?Pgeneric)/$', new.new),
(r'^new-(?Pthird-party)/$', new.new),
- (r'^search/$', search.search),
+ url(r'^search/$', search.search, name="ipr_search"),
)
diff --git a/ietf/templates/base.html b/ietf/templates/base.html
index 0ed8ba14b..9ec643469 100644
--- a/ietf/templates/base.html
+++ b/ietf/templates/base.html
@@ -45,10 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{% block morecss %}{% endblock %}
{% block pagehead %}{% endblock %}
-
{% ifnotequal server_mode "production" %}
{% else %}
@@ -107,7 +103,6 @@ YAHOO.util.Event.onContentReady("wgs", function () {
{% endblock %}
//]]>
-
{% block js %}{% endblock %}
{% block content_end %}
diff --git a/ietf/templates/base_leftmenu.html b/ietf/templates/base_leftmenu.html
index d4b0462ce..7c08aecaf 100644
--- a/ietf/templates/base_leftmenu.html
+++ b/ietf/templates/base_leftmenu.html
@@ -38,17 +38,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.