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
This commit is contained in:
Ole Laursen 2012-03-15 16:38:56 +00:00
parent 43bef3929f
commit a1b5671ead
6 changed files with 429 additions and 33 deletions

View file

@ -41,10 +41,10 @@ urlpatterns = patterns('',
(r'^in-last-call/$', views_search.in_last_call),
url(r'^ad/(?P<name>[A-Za-z0-9.-]+)/$', views_search.by_ad, name="doc_search_by_ad"),
url(r'^(?P<name>[A-Za-z0-9.-]+)/$', views_doc.document_main, name="doc_view"),
url(r'^(?P<name>[A-Za-z0-9.-]+)/((?P<rev>[0-9-]+)/)?$', views_doc.document_main, name="doc_view"),
url(r'^(?P<name>[A-Za-z0-9.-]+)/history/$', views_doc.document_history),
url(r'^(?P<name>[A-Za-z0-9.-]+)/writeup/$', views_doc.document_writeup),
url(r'^(?P<name>[A-Za-z0-9.-]+)/ballot/$', views_doc.document_ballot),
url(r'^(?P<name>[A-Za-z0-9.-]+)/ballot/((?P<ballot>[A-Za-z0-9.-]+)/)?$', views_doc.document_ballot),
(r'^(?P<name>[A-Za-z0-9.-]+)/doc.json$', views_doc.document_debug),
(r'^(?P<name>[A-Za-z0-9.-]+)/_ballot.data$', views_doc.ballot_html), # why is this url so weird instead of just ballot.html?
(r'^(?P<name>[A-Za-z0-9.-]+)/ballot.tsv$', views_doc.ballot_tsv),

View file

@ -34,7 +34,7 @@ import re, os
from datetime import datetime, time
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import RequestContext
from django.template.loader import render_to_string
from django.template.defaultfilters import truncatewords_html
@ -50,52 +50,219 @@ from ietf.idrfc import markup_txt
from ietf.idrfc.models import RfcIndex, DraftVersions
from ietf.idrfc.idrfc_wrapper import BallotWrapper, IdWrapper, RfcWrapper
from ietf.ietfworkflows.utils import get_full_info_for_draft
from ietf.doc.models import Document, DocEvent, NewRevisionDocEvent, WriteupDocEvent
from ietf.utils.history import find_history_active_at
from ietf.ietfauth.decorators import has_role
def render_document_top(request, doc, tab):
tabs = []
tabs.append(("Document", "document", urlreverse("idrfc.views_doc.document_main", kwargs=dict(name=doc.name))))
tabs.append(("Document", "document", urlreverse("ietf.idrfc.views_doc.document_main", kwargs=dict(name=doc.name))))
if doc_type == "draft":
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
elif doc_type == "charter":
tabs.append(("IESG Review", "ballot", urlreverse("idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
if doc.type_id == "draft":
# if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("ietf.idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
elif doc.type_id == "charter":
tabs.append(("IESG Review", "ballot", urlreverse("ietf.idrfc.views_doc.document_ballot", kwargs=dict(name=doc.name))))
tabs.append(("IESG Writeups", "writeup", urlreverse("idrfc.views_doc.document_writeup", kwargs=dict(name=doc.name))))
tabs.append(("History", "history", urlreverse("idrfc.views_doc.document_history", kwargs=dict(name=doc.name))))
# FIXME: if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
tabs.append(("IESG Writeups", "writeup", urlreverse("ietf.idrfc.views_doc.document_writeup", kwargs=dict(name=doc.name))))
tabs.append(("History", "history", urlreverse("ietf.idrfc.views_doc.document_history", kwargs=dict(name=doc.name))))
name = doc.canonical_name()
if name.startswith("rfc"):
name = "RFC %s" % name[3:]
else:
name += "-" + doc.rev
return render_to_string("idrfc/document_top.html",
dict(doc=doc,
tabs=tabs,
selected=tab))
selected=tab,
name=name))
def document_main(request, name):
if name.startswith("ietf-charter-"):
# FIXME: render top
# render content
# refactor history similarly? or use directly
# refactor writeup, generalize on names and links to edit
# refactor ballot to have multiple ballot typesiet
def document_main(request, name, rev=None):
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
if rev != None: # no support for old revisions at the moment
raise Http404()
return document_main_idrfc(request, name, tab="document")
return render_to_response("idrfc/doc_tab_document.html",
{'content1':content1,
'content2':content2,
'doc': doc,
'tab': "document",
'include_text':include_text(request)},
context_instance=RequestContext(request));
doc = get_object_or_404(Document, docalias__name=name)
revisions = [ doc.rev ]
for h in doc.history_set.order_by("-time"):
if not h.rev in revisions:
revisions.append(h.rev)
snapshot = False
if rev != None:
if rev == doc.rev:
return redirect('doc_view', name=name)
# find the entry in the history
for h in doc.history_set.order_by("-time"):
if rev == h.rev:
snapshot = True
doc = h
break
if not snapshot:
return redirect('doc_view', name=name)
# find old group, too
gh = find_history_active_at(doc.group, doc.time)
if gh:
doc.group = gh
top = render_document_top(request, doc, "document")
return document_main_idrfc(request, name, "document")
if doc.type_id == "charter":
# FIXME: add editing of charters/telechat date
# FIXME: check sanity of edit buttons "Recharter"
# FIXME: clean up wgcharter code redundant with this
filename = doc.name + "-" + doc.rev + ".txt"
content = _get_html(filename, os.path.join(settings.CHARTER_PATH, filename), split=False)
telechat = None
if not snapshot:
telechat = doc.latest_event(type="scheduled_for_telechat")
return render_to_response("idrfc/document_charter.html",
dict(doc=doc,
top=top,
chartering=get_chartering_type(doc),
content=content,
txt_url=settings.CHARTER_TXT_URL + filename,
revisions=revisions,
snapshot=snapshot,
telechat=telechat,
),
context_instance=RequestContext(request))
raise Http404()
def document_history(request, name):
return document_main_idrfc(request, name, "history")
# todo: remove need for specific handling of drafts by porting the
# two event text hacks
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
return document_main_idrfc(request, name, "history")
doc = get_object_or_404(Document, docalias__name=name)
top = render_document_top(request, doc, "history")
diff_documents = [ doc ]
diff_documents.extend(Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces"))
# pick up revisions from events
diff_revisions = []
seen = set()
diffable = name.startswith("draft") or name.startswith("charter")
if diffable:
for e in NewRevisionDocEvent.objects.filter(type="new_revision", doc__in=diff_documents).select_related('doc').order_by("-time", "-id"):
if not (e.doc.name, e.rev) in seen:
seen.add((e.doc.name, e.rev))
url = ""
if name.startswith("charter"):
url = settings.CHARTER_TXT_URL + e.doc.name + e.rev + ".txt"
elif name.startswith("draft"):
# rfcdiff tool has special support for IDs
url = e.doc.name + "-" + e.rev
diff_revisions.append((e.doc.name, e.rev, e.time, url))
# grab event history
events = doc.docevent_set.all().order_by("-time", "-id").select_related("by")
# fill in revision numbers
event_revisions = list(NewRevisionDocEvent.objects.filter(doc=doc).order_by('time', 'id').values('rev', 'time'))
cur_rev = doc.rev
if doc.get_state_slug() == "rfc":
cur_rev = "RFC"
for e in events:
while event_revisions and e.time < event_revisions[-1]["time"]:
event_revisions.pop()
if event_revisions:
cur_rev = event_revisions[-1]["rev"]
else:
cur_rev = "00"
e.rev = cur_rev
# add snippets
for e in events:
e.desc_snippet = truncatewords_html(format_textarea(fill(e.desc, 80)), 3)
if not e.desc_snippet.endswith("..."):
e.desc_snippet = None
return render_to_response("idrfc/document_history.html",
dict(doc=doc,
top=top,
diff_revisions=diff_revisions,
events=events,
),
context_instance=RequestContext(request))
def document_writeup(request, name):
return document_main_idrfc(request, name, "writeup")
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
# todo: migrate idrfc to pattern below
return document_main_idrfc(request, name, "writeup")
def document_ballot(request, name):
return document_main_idrfc(request, name, "ballot")
doc = get_object_or_404(Document, docalias__name=name)
top = render_document_top(request, doc, "writeup")
writeups = []
if doc.type_id == "charter":
e = doc.latest_event(WriteupDocEvent, type="changed_review_announcement")
writeups.append(("WG Review Announcement",
e.text if e else "",
urlreverse("ietf.wgcharter.views_ballot.announcement_text", kwargs=dict(name=doc.group.acronym, ann="review"))))
e = doc.latest_event(WriteupDocEvent, type="changed_action_announcement")
writeups.append(("WG Action Announcement",
e.text if e else "",
urlreverse("ietf.wgcharter.views_ballot.announcement_text", kwargs=dict(name=doc.group.acronym, ann="action"))))
e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
writeups.append(("Ballot Announcement",
e.text if e else "",
urlreverse("ietf.wgcharter.views_ballot.ballot_writeupnotes", kwargs=dict(name=doc.group.acronym))))
if not writeups:
raise Http404()
return render_to_response("idrfc/document_writeup.html",
dict(doc=doc,
top=top,
writeups=writeups,
can_edit=has_role(request.user, ("Area Director", "Secretariat")),
),
context_instance=RequestContext(request))
def document_ballot(request, name, ballot=None):
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
return document_main_idrfc(request, name, "ballot")
doc = get_object_or_404(Document, docalias__name=name)
top = render_document_top(request, doc, "ballot")
# FIXME: port implementation from wgcharter
raise Http404()
def document_debug(request, name):
r = re.compile("^rfc([1-9][0-9]*)$")
@ -109,7 +276,7 @@ def document_debug(request, name):
doc = IdWrapper(draft=id)
return HttpResponse(doc.to_json(), mimetype='text/plain')
def _get_html(key, filename):
def _get_html(key, filename, split=True):
f = None
try:
f = open(filename, 'rb')
@ -119,8 +286,7 @@ def _get_html(key, filename):
finally:
if f:
f.close()
(c1,c2) = markup_txt.markup(raw_content)
return (c1,c2)
return markup_txt.markup(raw_content, split)
def include_text(request):
include_text = request.GET.get( 'include_text' )

View file

@ -0,0 +1,109 @@
{% extends "base.html" %}
{% load ietf_filters %}
{% block title %}{{ doc.name }}-{{ doc.rev }}{% endblock %}
{% block pagehead %}
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
{% endblock %}
{% block content %}
{{ top|safe }}
<div class="snapshots">
Snapshots:
<span class="revisions">
{% for rev in revisions %}
<a {% if rev != doc.rev %}href="{% url doc_view name=doc.name %}{% if not forloop.first %}{{ rev }}/{% endif %}"{% endif %}>{{ rev }}</a>
{% endfor %}
</span>
</div>
<div class="ietf-box metabox">
<div>
{% if snapshot %}Snapshot of{% endif %}
{% if doc.get_state_slug != "approved" %}Proposed{% endif %}
Charter for {{ doc.group.name }}
(<a href="{% url wginfo.views.wg_charter acronym=doc.group.acronym %}">{{ doc.group.acronym }} {{ doc.group.type.name }}</a>)
</div>
<table id="metatable" width="100%">
<tr>
<td>WG State:</td>
<td>{{ doc.group.state.name }}</td>
</tr>
<tr>
<td><a href="/wgcharter/help/state/">Charter State</a>:</td>
<td>
<span title="{{ doc.get_state.desc }}">{{ doc.get_state.name }}</span>
{% if chartering == "initial" %}(Initial Chartering){% endif %}
{% if chartering == "rechartering" %}(Rechartering){% endif %}
{% if not snapshot and user|has_role:"Area Director,Secretariat" %}
- <a href="{% url wg_change_state name=doc.group.acronym %}">Change state</a>
{% endif %}
</td>
</tr>
{% if chartering %}
{% if doc.group.comments %}
<tr>
{% if chartering == "initial" %}<td>Reason for chartering:</td>{% endif %}
{% if chartering == "rechartering" %}<td>Reason for rechartering:</td>{% endif %}
<td>{{ doc.group.comments }}</td>
</tr>
{% endif %}
{% if not snapshot %}
<tr>
<td>Telechat:</td>
<td>
{% if not doc.telechat %}Not on agenda{% else %}{{ doc.telechat.date|date:"Y-m-d" }}{% endif %}
{% if user|has_role:"Area Director,Secretariat" %}
- <a href="FIXME">Change</a>
{% endif %}
</td>
</tr>
{% endif %}
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
<tr><td>Last updated:</td><td> {{ doc.time|date:"Y-m-d" }}</td></tr>
{% endif %}
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
</table>
{% if not snapshot and user|has_role:"Area Director,Secretariat" %}
{% if chartering %}
{% if doc.group.state_id != "conclude" %}
<a href="{% url wg_submit name=doc.group.acronym %}">Edit charter</a>
{% endif %}
<a href="{% url wg_startstop_process name=doc.group.acronym option='abandon' %}">Abandon effort</a>
{% else %}
<a href="{% url wg_startstop_process name=doc.group.acronym option='recharter' %}">Recharter</a>
{% endif %}
{% endif %}
<div><a href="/feed/wgcomments/{{ doc.group.acronym }}/">Atom feed</a></div>
</div>
<p>Other versions: <a href="{{ txt_url }}">plain text</a></p>
<h3>Charter {{ doc.name }}-{{ doc.rev }}</h3>
<div class="markup_draft">
{{ content|fill:"80"|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
</div>
{% endblock %}

View file

@ -0,0 +1,88 @@
{% extends "base.html" %}
{% load ietf_filters %}
{% block title %}History for {{ doc.name }}-{{ doc.rev }}{% endblock %}
{% block pagehead %}
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
{% endblock %}
{% block content %}
{{ top|safe }}
{% if diff_revisions %}
<div class="ietf-box diffTool">
<h2>Diffs</h2>
<form action="http{% if request.is_secure %}s{% endif %}://tools.ietf.org/rfcdiff" method="get" target="_blank">
<table>
<tr>
<td>
<label>From:</label>
<select name="url1">
{% for name, rev, time, url in diff_revisions %}
<option value="{{ url }}" {% if forloop.counter == 2 %} selected="selected" {% endif %}>{{ name }}-{{ rev }} ({{ time|date:"Y-m-d" }})</option>
{% endfor %}
</select>
</td>
<td rowspan="2" valign="top">
<label>Format:</label>
<select name="difftype">
<option value="--html" selected="selected">Side-by-side</option>
<option value="--abdiff">Before-after</option>
<option value="--chbars">Change bars</option>
<option value="--hwdiff">Wdiff</option>
</select>
<input name="submit" value="Go!" type="submit" />
</td>
</tr>
<tr>
<td>
<label>To:</label>
<select name="url2">
{% for name, rev, time, url in diff_revisions %}
<option value="{{ url }}" {% if forloop.counter == 1 %} selected="selected" {% endif %}>{{ name }}-{{ rev }} ({{ time|date:"Y-m-d" }})</option>
{% endfor %}
</select>
</td>
</tr>
</table>
</form>
</div>
{% endif %}
<h2>Document history</h2>
{% if user|has_role:"Area Director,Secretariat,IANA" %}
<div class="history-actions">
<a href="{% url doc_add_comment name=doc.name %}">Add comment</a>
</div>
{% endif %}
<table class="ietf-table history">
<tr><th>Date</th><th>Version</th><th>By</th><th>Text</th></tr>
{% for e in events %}
<tr class="{% cycle oddrow,evenrow %}" id="history-{{ e.pk }}">
<td>{{ e.time|date:"Y-m-d" }}</td>
<td>{{ e.rev }}</td>
<td>{{ e.by|escape }}</td>
<td>{% if e.desc_snippet %}
<div class="snippet">{{ e.desc_snippet|safe }} <span class="showAll">[show all]</span></div>
<div class="full" style="display:none;">
{{ e.desc|fill:"80"|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
</div>
{% else %}
{{ e.desc|fill:"80"|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
{% block content_end %}
<script type="text/javascript" src="/js/doc-history.js"></script>
{% endblock content_end %}

View file

@ -0,0 +1,9 @@
<h1>{{ doc.title }}<br/>{{ name }}</h1>
<div id="mytabs" class="yui-navset">
<ul class="yui-nav">
{% for name, t, url in tabs %}
<li {% if t == selected %}class="selected"{% endif %}><a href="{{ url }}"><em>{{ name }}</em></a></li>
{% endfor %}
</ul>
</div>

View file

@ -0,0 +1,24 @@
{% extends "base.html" %}
{% block title %}Writeups for {{ doc.name }}-{{ doc.rev }}{% endblock %}
{% block pagehead %}
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
{% endblock %}
{% block content %}
{{ top|safe }}
{% for title, text, url in writeups %}
<div class="writeup">
<h2>{{ title }}</h2>
{% if can_edit %}<a href="{{ url }}" class="edit">Edit {{ title }}</a>{% endif %}
<pre {% if can_edit %}class="editable"{% endif %}>
{{ text }}
</pre>
</div>
{% endfor%}
{% endblock content %}