Skip to content

Commit a1b5671

Browse files
committed
Preliminary generalization of /doc/ tabs with top factored out, main
page being specific, writeup page generic with some specific code to setup writeups (only charter ported), history page being generic (I-D/RFC not ported, needs two event hack fixes), and ballot page not done, pending on multi-ballot solution. - Legacy-Id: 4091
1 parent 43bef39 commit a1b5671

6 files changed

Lines changed: 432 additions & 36 deletions

File tree

ietf/idrfc/urls.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@
4141
(r'^in-last-call/$', views_search.in_last_call),
4242
url(r'^ad/(?P<name>[A-Za-z0-9.-]+)/$', views_search.by_ad, name="doc_search_by_ad"),
4343

44-
url(r'^(?P<name>[A-Za-z0-9.-]+)/$', views_doc.document_main, name="doc_view"),
44+
url(r'^(?P<name>[A-Za-z0-9.-]+)/((?P<rev>[0-9-]+)/)?$', views_doc.document_main, name="doc_view"),
4545
url(r'^(?P<name>[A-Za-z0-9.-]+)/history/$', views_doc.document_history),
4646
url(r'^(?P<name>[A-Za-z0-9.-]+)/writeup/$', views_doc.document_writeup),
47-
url(r'^(?P<name>[A-Za-z0-9.-]+)/ballot/$', views_doc.document_ballot),
47+
url(r'^(?P<name>[A-Za-z0-9.-]+)/ballot/((?P<ballot>[A-Za-z0-9.-]+)/)?$', views_doc.document_ballot),
4848
(r'^(?P<name>[A-Za-z0-9.-]+)/doc.json$', views_doc.document_debug),
4949
(r'^(?P<name>[A-Za-z0-9.-]+)/_ballot.data$', views_doc.ballot_html), # why is this url so weird instead of just ballot.html?
5050
(r'^(?P<name>[A-Za-z0-9.-]+)/ballot.tsv$', views_doc.ballot_tsv),

ietf/idrfc/views_doc.py

Lines changed: 200 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from datetime import datetime, time
3535

3636
from django.http import HttpResponse, Http404
37-
from django.shortcuts import render_to_response, get_object_or_404
37+
from django.shortcuts import render_to_response, get_object_or_404, redirect
3838
from django.template import RequestContext
3939
from django.template.loader import render_to_string
4040
from django.template.defaultfilters import truncatewords_html
@@ -50,52 +50,219 @@
5050
from ietf.idrfc.models import RfcIndex, DraftVersions
5151
from ietf.idrfc.idrfc_wrapper import BallotWrapper, IdWrapper, RfcWrapper
5252
from ietf.ietfworkflows.utils import get_full_info_for_draft
53+
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, WriteupDocEvent
54+
from ietf.utils.history import find_history_active_at
55+
from ietf.ietfauth.decorators import has_role
56+
5357

5458
def render_document_top(request, doc, tab):
5559
tabs = []
56-
tabs.append(("Document", "document", urlreverse("idrfc.views_doc.document_main", kwargs=dict(name=doc.name))))
60+
tabs.append(("Document", "document", urlreverse("ietf.idrfc.views_doc.document_main", kwargs=dict(name=doc.name))))
61+
62+
if doc.type_id == "draft":
63+
# if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
64+
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("ietf.idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
65+
elif doc.type_id == "charter":
66+
tabs.append(("IESG Review", "ballot", urlreverse("ietf.idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
5767

58-
if doc_type == "draft":
59-
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
60-
elif doc_type == "charter":
61-
tabs.append(("IESG Review", "ballot", urlreverse("idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
68+
# FIXME: if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
69+
tabs.append(("IESG Writeups", "writeup", urlreverse("ietf.idrfc.views_doc.document_writeup", kwargs=dict(name=doc.name))))
70+
tabs.append(("History", "history", urlreverse("ietf.idrfc.views_doc.document_history", kwargs=dict(name=doc.name))))
6271

63-
tabs.append(("IESG Writeups", "writeup", urlreverse("idrfc.views_doc.document_writeup", kwargs=dict(name=doc.name))))
64-
tabs.append(("History", "history", urlreverse("idrfc.views_doc.document_history", kwargs=dict(name=doc.name))))
72+
name = doc.canonical_name()
73+
if name.startswith("rfc"):
74+
name = "RFC %s" % name[3:]
75+
else:
76+
name += "-" + doc.rev
6577

6678
return render_to_string("idrfc/document_top.html",
6779
dict(doc=doc,
6880
tabs=tabs,
69-
selected=tab))
70-
71-
72-
def document_main(request, name):
73-
if name.startswith("ietf-charter-"):
74-
# FIXME: render top
75-
# render content
76-
# refactor history similarly? or use directly
77-
# refactor writeup, generalize on names and links to edit
78-
# refactor ballot to have multiple ballot typesiet
79-
80-
return render_to_response("idrfc/doc_tab_document.html",
81-
{'content1':content1,
82-
'content2':content2,
83-
'doc': doc,
84-
'tab': "document",
85-
'include_text':include_text(request)},
86-
context_instance=RequestContext(request));
81+
selected=tab,
82+
name=name))
83+
84+
85+
def document_main(request, name, rev=None):
86+
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
87+
if rev != None: # no support for old revisions at the moment
88+
raise Http404()
89+
return document_main_idrfc(request, name, tab="document")
90+
91+
doc = get_object_or_404(Document, docalias__name=name)
92+
93+
revisions = [ doc.rev ]
94+
for h in doc.history_set.order_by("-time"):
95+
if not h.rev in revisions:
96+
revisions.append(h.rev)
97+
98+
snapshot = False
99+
100+
if rev != None:
101+
if rev == doc.rev:
102+
return redirect('doc_view', name=name)
103+
104+
# find the entry in the history
105+
for h in doc.history_set.order_by("-time"):
106+
if rev == h.rev:
107+
snapshot = True
108+
doc = h
109+
break
110+
111+
if not snapshot:
112+
return redirect('doc_view', name=name)
87113

114+
# find old group, too
115+
gh = find_history_active_at(doc.group, doc.time)
116+
if gh:
117+
doc.group = gh
118+
119+
top = render_document_top(request, doc, "document")
120+
121+
122+
if doc.type_id == "charter":
123+
# FIXME: add editing of charters/telechat date
124+
# FIXME: check sanity of edit buttons "Recharter"
125+
# FIXME: clean up wgcharter code redundant with this
126+
127+
filename = doc.name + "-" + doc.rev + ".txt"
128+
129+
content = _get_html(filename, os.path.join(settings.CHARTER_PATH, filename), split=False)
130+
131+
telechat = None
132+
if not snapshot:
133+
telechat = doc.latest_event(type="scheduled_for_telechat")
134+
135+
return render_to_response("idrfc/document_charter.html",
136+
dict(doc=doc,
137+
top=top,
138+
chartering=get_chartering_type(doc),
139+
content=content,
140+
txt_url=settings.CHARTER_TXT_URL + filename,
141+
revisions=revisions,
142+
snapshot=snapshot,
143+
telechat=telechat,
144+
),
145+
context_instance=RequestContext(request))
146+
147+
raise Http404()
88148

89-
return document_main_idrfc(request, name, "document")
90149

91150
def document_history(request, name):
92-
return document_main_idrfc(request, name, "history")
151+
# todo: remove need for specific handling of drafts by porting the
152+
# two event text hacks
153+
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
154+
return document_main_idrfc(request, name, "history")
155+
156+
157+
doc = get_object_or_404(Document, docalias__name=name)
158+
top = render_document_top(request, doc, "history")
159+
160+
diff_documents = [ doc ]
161+
diff_documents.extend(Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces"))
162+
163+
# pick up revisions from events
164+
diff_revisions = []
165+
seen = set()
166+
167+
diffable = name.startswith("draft") or name.startswith("charter")
168+
169+
if diffable:
170+
for e in NewRevisionDocEvent.objects.filter(type="new_revision", doc__in=diff_documents).select_related('doc').order_by("-time", "-id"):
171+
if not (e.doc.name, e.rev) in seen:
172+
seen.add((e.doc.name, e.rev))
173+
174+
url = ""
175+
if name.startswith("charter"):
176+
url = settings.CHARTER_TXT_URL + e.doc.name + e.rev + ".txt"
177+
elif name.startswith("draft"):
178+
# rfcdiff tool has special support for IDs
179+
url = e.doc.name + "-" + e.rev
180+
181+
diff_revisions.append((e.doc.name, e.rev, e.time, url))
182+
183+
# grab event history
184+
events = doc.docevent_set.all().order_by("-time", "-id").select_related("by")
185+
186+
# fill in revision numbers
187+
event_revisions = list(NewRevisionDocEvent.objects.filter(doc=doc).order_by('time', 'id').values('rev', 'time'))
188+
189+
cur_rev = doc.rev
190+
if doc.get_state_slug() == "rfc":
191+
cur_rev = "RFC"
192+
193+
for e in events:
194+
while event_revisions and e.time < event_revisions[-1]["time"]:
195+
event_revisions.pop()
196+
197+
if event_revisions:
198+
cur_rev = event_revisions[-1]["rev"]
199+
else:
200+
cur_rev = "00"
201+
202+
e.rev = cur_rev
203+
204+
# add snippets
205+
for e in events:
206+
e.desc_snippet = truncatewords_html(format_textarea(fill(e.desc, 80)), 3)
207+
if not e.desc_snippet.endswith("..."):
208+
e.desc_snippet = None
209+
210+
return render_to_response("idrfc/document_history.html",
211+
dict(doc=doc,
212+
top=top,
213+
diff_revisions=diff_revisions,
214+
events=events,
215+
),
216+
context_instance=RequestContext(request))
93217

94218
def document_writeup(request, name):
95-
return document_main_idrfc(request, name, "writeup")
219+
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
220+
# todo: migrate idrfc to pattern below
221+
return document_main_idrfc(request, name, "writeup")
222+
223+
doc = get_object_or_404(Document, docalias__name=name)
224+
top = render_document_top(request, doc, "writeup")
225+
226+
writeups = []
227+
if doc.type_id == "charter":
228+
e = doc.latest_event(WriteupDocEvent, type="changed_review_announcement")
229+
writeups.append(("WG Review Announcement",
230+
e.text if e else "",
231+
urlreverse("ietf.wgcharter.views_ballot.announcement_text", kwargs=dict(name=doc.group.acronym, ann="review"))))
232+
233+
e = doc.latest_event(WriteupDocEvent, type="changed_action_announcement")
234+
writeups.append(("WG Action Announcement",
235+
e.text if e else "",
236+
urlreverse("ietf.wgcharter.views_ballot.announcement_text", kwargs=dict(name=doc.group.acronym, ann="action"))))
237+
238+
e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
239+
writeups.append(("Ballot Announcement",
240+
e.text if e else "",
241+
urlreverse("ietf.wgcharter.views_ballot.ballot_writeupnotes", kwargs=dict(name=doc.group.acronym))))
242+
243+
if not writeups:
244+
raise Http404()
245+
246+
return render_to_response("idrfc/document_writeup.html",
247+
dict(doc=doc,
248+
top=top,
249+
writeups=writeups,
250+
can_edit=has_role(request.user, ("Area Director", "Secretariat")),
251+
),
252+
context_instance=RequestContext(request))
253+
254+
255+
256+
def document_ballot(request, name, ballot=None):
257+
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
258+
return document_main_idrfc(request, name, "ballot")
259+
260+
doc = get_object_or_404(Document, docalias__name=name)
261+
top = render_document_top(request, doc, "ballot")
262+
263+
# FIXME: port implementation from wgcharter
96264

97-
def document_ballot(request, name):
98-
return document_main_idrfc(request, name, "ballot")
265+
raise Http404()
99266

100267
def document_debug(request, name):
101268
r = re.compile("^rfc([1-9][0-9]*)$")
@@ -109,7 +276,7 @@ def document_debug(request, name):
109276
doc = IdWrapper(draft=id)
110277
return HttpResponse(doc.to_json(), mimetype='text/plain')
111278

112-
def _get_html(key, filename):
279+
def _get_html(key, filename, split=True):
113280
f = None
114281
try:
115282
f = open(filename, 'rb')
@@ -119,8 +286,7 @@ def _get_html(key, filename):
119286
finally:
120287
if f:
121288
f.close()
122-
(c1,c2) = markup_txt.markup(raw_content)
123-
return (c1,c2)
289+
return markup_txt.markup(raw_content, split)
124290

125291
def include_text(request):
126292
include_text = request.GET.get( 'include_text' )

0 commit comments

Comments
 (0)