Port idtracker feeds to new schema, move them to doc/, clean up
idtracker/ - only templatetags/ietf_filters and proxy code is left - Legacy-Id: 5643
This commit is contained in:
parent
564a97d2ee
commit
7892e29036
86
ietf/doc/feeds.py
Normal file
86
ietf/doc/feeds.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
|
||||
import datetime, re
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.syndication.feeds import Feed, FeedDoesNotExist
|
||||
from django.utils.feedgenerator import Atom1Feed
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.template.defaultfilters import truncatewords_html, date as datefilter, linebreaks
|
||||
from django.utils.html import strip_tags
|
||||
from django.utils.text import truncate_words
|
||||
|
||||
from ietf.doc.models import *
|
||||
from ietf.doc.utils import augment_events_with_revision
|
||||
from ietf.idtracker.templatetags.ietf_filters import format_textarea
|
||||
|
||||
class DocumentChanges(Feed):
|
||||
feed_type = Atom1Feed
|
||||
|
||||
def get_object(self, bits):
|
||||
if len(bits) != 1:
|
||||
raise Document.DoesNotExist
|
||||
|
||||
return Document.objects.get(docalias__name=bits[0])
|
||||
|
||||
def title(self, obj):
|
||||
return "Changes for %s" % obj.display_name()
|
||||
|
||||
def link(self, obj):
|
||||
if obj is None:
|
||||
raise FeedDoesNotExist
|
||||
if not hasattr(self, "cached_link"):
|
||||
self.cached_link = urlreverse("doc_history", kwargs=dict(name=obj.canonical_name()))
|
||||
return self.cached_link
|
||||
|
||||
def subtitle(self, obj):
|
||||
return "History of change entries for %s." % obj.display_name()
|
||||
|
||||
def items(self, obj):
|
||||
events = obj.docevent_set.all().order_by("-time","-id")
|
||||
augment_events_with_revision(obj, events)
|
||||
return events
|
||||
|
||||
def item_title(self, item):
|
||||
return u"[%s] %s [rev. %s]" % (item.by, truncate_words(strip_tags(item.desc), 15), item.rev)
|
||||
|
||||
def item_description(self, item):
|
||||
return truncatewords_html(format_textarea(item.desc), 20)
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.time
|
||||
|
||||
def item_author_name(self, item):
|
||||
return unicode(item.by)
|
||||
|
||||
def item_link(self, item):
|
||||
return self.cached_link + "#history-%s" % item.pk
|
||||
|
||||
class InLastCall(Feed):
|
||||
title = "Documents in Last Call"
|
||||
subtitle = "Announcements for documents in last call."
|
||||
feed_type = Atom1Feed
|
||||
author_name = 'IESG Secretary'
|
||||
link = "/doc/iesg/last-call/"
|
||||
|
||||
def items(self):
|
||||
docs = list(Document.objects.filter(type="draft", states=State.objects.get(type="draft-iesg", slug="lc")))
|
||||
for d in docs:
|
||||
d.lc_event = d.latest_event(LastCallDocEvent, type="sent_last_call")
|
||||
|
||||
docs = [d for d in docs if d.lc_event]
|
||||
docs.sort(key=lambda d: d.lc_event.expires)
|
||||
|
||||
return docs
|
||||
|
||||
def item_title(self, item):
|
||||
return u"%s (%s - %s)" % (item.name,
|
||||
datefilter(item.lc_event.time, "F j"),
|
||||
datefilter(item.lc_event.expires, "F j, Y"))
|
||||
|
||||
def item_description(self, item):
|
||||
return linebreaks(item.lc_event.desc)
|
||||
|
||||
def item_pubdate(self, item):
|
||||
return item.lc_event.time
|
||||
|
|
@ -403,8 +403,6 @@ def drafts_in_iesg_process(request, last_call_only=None):
|
|||
|
||||
grouped_docs.append((s, docs))
|
||||
|
||||
#drafts.sort(key=lambda d: (d.cur_state_id, d.status_date or datetime.date.min, d.b_sent_date or datetime.date.min))
|
||||
|
||||
return render_to_response('doc/drafts_in_iesg_process.html', {
|
||||
"grouped_docs": grouped_docs,
|
||||
"title": title,
|
||||
|
|
|
@ -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))
|
||||
|
|
@ -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"
|
||||
|
|
|
@ -1,88 +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 = list(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.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))
|
||||
|
|
@ -227,7 +227,7 @@
|
|||
| <a href="{% url ipr_search %}?option=document_search&id={{ doc.name }}" rel="nofollow">IPR Disclosures</a>
|
||||
| <a href="http://www.fenron.net/~fenner/ietf/deps/index.cgi?dep={{ name }}" rel="nofollow">Dependencies to this document</a>
|
||||
| <a href="http://tools.ietf.org/idnits?url=http://tools.ietf.org/id/{{ doc.filename_with_rev }}" rel="nofollow" target="_blank">Check nits</a>
|
||||
| <a href="/feed/comments/{{ name }}/">History feed</a>
|
||||
| <a href="/feed/document-changes/{{ name }}/">History feed</a>
|
||||
| <a href="http://www.google.com/search?as_q={{ doc.name }}&as_sitesearch={{ search_archive }}" rel="nofollow" target="_blank">Search Mailing Lists</a>
|
||||
{% if user|has_role:"Area Director" %}
|
||||
| <a href="https://www.iesg.org/bin/c5i?mid=6&rid=77&target={{ doc.name }}" rel="nofollow" target="_blank">Search Mailing Lists (ARO)</a>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed/comments/{{ doc.canonical_name }}/" />
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed/document-changes/{{ doc.canonical_name }}/" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{# Copyright The IETF Trust 2007, All Rights Reserved #}
|
||||
{% load ietf_filters %}
|
||||
{{ obj.comment_text|format_textarea|safe|truncatewords_html:"20" }}
|
|
@ -1,5 +0,0 @@
|
|||
{# Copyright The IETF Trust 2007, All Rights Reserved #}
|
||||
{% load ietf_filters %}
|
||||
[{{ obj.get_username }}] {{ obj.comment_text|removetags:"b"|truncatewords:"15"|safe }}
|
||||
{% if obj.ballot %}[[ IESG {{ obj.get_ballot_display.upper }} ]]{% endif %}
|
||||
{% if not obj.document.rfc_flag %}[ version {{ obj.version }} ]{% endif %}
|
|
@ -1,3 +0,0 @@
|
|||
{# Copyright The IETF Trust 2007, All Rights Reserved #}
|
||||
{% load ietf_filters %}
|
||||
{{ obj.ballot.last_call_text|escape|linebreaks }}
|
|
@ -1,2 +0,0 @@
|
|||
{# Copyright The IETF Trust 2007, All Rights Reserved #}
|
||||
{{ obj }} ({{ obj.document.lc_sent_date|date:"F j" }}-{{ obj.document.lc_expiration_date|date:"F j, Y" }})
|
|
@ -5,7 +5,7 @@ from django.conf.urls.defaults import patterns, include, handler404, handler500
|
|||
from django.contrib import admin
|
||||
|
||||
from ietf.iesg.feeds import IESGAgenda
|
||||
from ietf.idtracker.feeds import DocumentComments, InLastCall
|
||||
from ietf.doc.feeds import DocumentChanges, InLastCall
|
||||
from ietf.ipr.feeds import LatestIprDisclosures
|
||||
from ietf.proceedings.feeds import LatestWgProceedingsActivity
|
||||
from ietf.liaisons.feeds import Liaisons
|
||||
|
@ -23,7 +23,7 @@ admin.site.disable_action('delete_selected')
|
|||
feeds = {
|
||||
'iesg-agenda': IESGAgenda,
|
||||
'last-call': InLastCall,
|
||||
'comments': DocumentComments,
|
||||
'document-changes': DocumentChanges,
|
||||
'group-changes': GroupChanges,
|
||||
'ipr': LatestIprDisclosures,
|
||||
'liaison': Liaisons,
|
||||
|
@ -46,6 +46,7 @@ urlpatterns = patterns('',
|
|||
(r'^cookies/', include('ietf.cookies.urls')),
|
||||
(r'^doc/', include('ietf.idrfc.urls')),
|
||||
(r'^drafts/', include('ietf.doc.redirect_drafts_urls')),
|
||||
(r'^feed/comments/(?P<remainder>.*)/$', 'django.views.generic.simple.redirect_to', { 'url': '/feed/document-changes/%(remainder)s/'}),
|
||||
(r'^feed/(?P<url>.*)/$', 'django.contrib.syndication.views.feed', { 'feed_dict': feeds}),
|
||||
(r'^idtracker/', include('ietf.doc.redirect_idtracker_urls')),
|
||||
(r'^iesg/', include('ietf.iesg.urls')),
|
||||
|
|
Loading…
Reference in a new issue