Merged in a lot of shim-layer removals from olau@iola.dk
(-r5194:5465 from branch/iola/shimfree). Copying relevant commit messages here: - Removed .related many to many relationship, it's not really useful since we always have to restrict on the relationship type anyway, instead add two helpers for doing the necessary queries (in both directions) - Added migration for transforming the .desc on the new_revision events into something more akin to what is actually shown in the history page - Added migration for blanking IESG notes that just consist of "RFC XXXX", these have been superfluous for some time - Grant stream chairs access to changing the stream on a draft - Hacked the format_history_text filter to be less weird, using the same formatting for snippets and full text, also link up legacy ballot set events - Moved the decoraters + utilities to new ietfauth/utils.py file - Added simple helper to Email to identify invalid email addresses (from legacy author entries) - Used new new_revision .desc format for when drafts are submitted - Improved the looks of the button class by adding extra contrast and a linear gradient. Currently the gradient is only visible in fairly recent browsers. - Rewrote draft and RFC tabs in terms of the new schema, porting write-up and history tabs as well - Fixed two bugs in RFC Editor syncing: make sure documents we don't know beforehand get a "draft" type and make sure individually submitted drafts get the type="individ" group instead of NULL - Made the CSS-styled button feel a bit nicer to use by flattening the active state, also introduce some temporary styles until browsers catch up with the standard syntax - Added migrations for fixing 1) a dummy RFC entry, 2) three stand-alone RFCs that didn't get their doc.type set, 3) a big bunch of historic stand-alone RFCs that have doc.group=None - set these to the individual submission "none" group for the time being so the view code doesn't have to deal with a special case. In some cases this is wrong since there actually was a WG associated but unfortunately fixing them properly requires detective work (probably parsing the RFCs) and in at least some cases recreating historic WGs. In case someone ends up doing this, the documents to check can still be found with Document.objects.filter(name__startswith="rfc", group__type="individ") since there are almost no new RFCs that didn't went through the I-D process. - Merged the I-D and RFC views by showing I-D information on RFCs too. I-Ds that have been published as RFCs redirect to the RFC URL. Also support alias URLs so e.g. /doc/bcpXXXX redirects to /doc/rfcXXXX. - Fixed revision augmentation so events after RFC publication gets a "RFC" designation - Fixed a bug with tabs not using provided name but rather doc.name - Displaying draft-iesg state rather than doc.friendly_state as IESG state, also show a notice that the IESG state refers to post-RFC processing if it does, like the old separate RFC page did - Fixed the RFC number doc.note migration to catch combined "RFC XXX; BCP XXX" notes too, use the opportunity to remove inserted HTML tags from notes and rely on linebreaksbr filter instead (the other thing was a left-over from the Perl days), update the various uses of the note to reflect that - Refactored slightly to make views_doc.py independent of other idrfc code - Moveed idrfc/views_doc.py to doc/ with associated templates, replace the somewhat fragile simple URL tests for views_doc.py with ordinary unit tests. The new tests are still fairly basic but at least test more than the URL tests did. - Made sure RFC's (and BCP/STD/FYI) are stored as RFC123 instead of RFC0123 in the alias table with a new migration and a change to the RFC Editor sync, this in turn makes /doc/std1/ do the right thing - Now /doc/std1/ works, we can actually do a local link in urlize_ietf_docs rather than linking to the tools.ietf.org server - Fixed history text formatter: sanitize HTML before adding linebreaks and non-breaking spaces, this cuts the time to render a history page with long comments in half - Added a test crawler that walks through the crawlable part of the site, reporting errors and slow pages - Got rid of initial "No record" positions when showing old positions, it's just noise - Added a .select_related() to the document main tab to reduce the number of DB queries, unfortunately it seems it doesn't really help with Django 1.2.x due to a bug (Document inherits from DocumentInfo which makes things a bit more complicated) - Introduced a simple cache in doc.get_state so repeated reads don't cause a DB query - Cleaned up the search code in preparation for removal of the shim-layer; use a static button and don't send extraneous GET parameters - Removed dead code in several places - Legacy-Id: 5830
This commit is contained in:
commit
e678659b56
|
@ -494,6 +494,19 @@ class TransactionTestCase(unittest.TestCase):
|
|||
def assertQuerysetEqual(self, qs, values, transform=repr):
|
||||
return self.assertEqual(map(transform, qs), values)
|
||||
|
||||
# some things from newer (python 2.7) unittests
|
||||
def assertIsNone(self, obj, msg=None):
|
||||
"""Same as self.assertTrue(obj is None), with a nicer default message."""
|
||||
if obj is not None:
|
||||
standardMsg = '%s is not None' % (safe_repr(obj),)
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def assertIsNotNone(self, obj, msg=None):
|
||||
"""Included for symmetry with assertIsNone."""
|
||||
if obj is None:
|
||||
standardMsg = 'unexpectedly None'
|
||||
self.fail(self._formatMessage(msg, standardMsg))
|
||||
|
||||
def connections_support_transactions():
|
||||
"""
|
||||
Returns True if all connections support transactions. This is messy
|
||||
|
|
91
ietf/bin/test-crawl
Executable file
91
ietf/bin/test-crawl
Executable file
|
@ -0,0 +1,91 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os, sys, re, datetime, optparse, traceback
|
||||
import syslog
|
||||
|
||||
# boilerplate
|
||||
basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
|
||||
sys.path = [ basedir ] + sys.path
|
||||
|
||||
from ietf import settings
|
||||
from django.core import management
|
||||
management.setup_environ(settings)
|
||||
|
||||
import django.test
|
||||
from django.conf import settings
|
||||
|
||||
# prevent memory from leaking when settings.DEBUG=True
|
||||
from django.db import connection
|
||||
class DontSaveQueries(object):
|
||||
def append(self, x):
|
||||
pass
|
||||
connection.queries = DontSaveQueries()
|
||||
|
||||
MAX_URL_LENGTH = 500
|
||||
SLOW_THRESHOLD = 1.0
|
||||
|
||||
def strip_url(url):
|
||||
if url.startswith("http://testserver"):
|
||||
url = url[len("http://testserver"):]
|
||||
return url
|
||||
|
||||
def extract_html_urls(content):
|
||||
for m in re.finditer(r'<a.*href="([^"]+)">', content):
|
||||
url = strip_url(m.group(1))
|
||||
if len(url) > MAX_URL_LENGTH:
|
||||
continue # avoid infinite GET parameter appendages
|
||||
|
||||
if not url.startswith("/"):
|
||||
continue
|
||||
|
||||
yield url
|
||||
|
||||
|
||||
visited = set()
|
||||
blacklist = set()
|
||||
urls = set(["/doc/all/"])
|
||||
|
||||
client = django.test.Client()
|
||||
|
||||
while urls:
|
||||
url = urls.pop()
|
||||
|
||||
visited.add(url)
|
||||
|
||||
try:
|
||||
timestamp = datetime.datetime.now()
|
||||
r = client.get(url)
|
||||
elapsed = datetime.datetime.now() - timestamp
|
||||
except KeyboardInterrupt:
|
||||
print "was fetching", url
|
||||
sys.exit(1)
|
||||
except:
|
||||
print "FAIL", url
|
||||
print "============="
|
||||
traceback.print_exc()
|
||||
print "============="
|
||||
else:
|
||||
tags = []
|
||||
|
||||
if r.status_code in (301, 302):
|
||||
u = strip_url(r["Location"])
|
||||
if u not in visited and u not in urls:
|
||||
urls.add(u)
|
||||
|
||||
elif r.status_code == 200:
|
||||
ctype = r["Content-Type"]
|
||||
if ";" in ctype:
|
||||
ctype = ctype[:ctype.index(";")]
|
||||
|
||||
if ctype == "text/html":
|
||||
for u in extract_html_urls(r.content):
|
||||
if u not in visited and u not in urls:
|
||||
urls.add(u)
|
||||
else:
|
||||
tags.append("FAIL")
|
||||
|
||||
if elapsed.total_seconds() > SLOW_THRESHOLD:
|
||||
tags.append("SLOW")
|
||||
|
||||
print r.status_code, "%.3fs" % elapsed.total_seconds(), url, " ".join(tags)
|
||||
|
|
@ -93,7 +93,7 @@ class DocumentAdmin(admin.ModelAdmin):
|
|||
list_display = ['name', 'rev', 'group', 'pages', 'intended_std_level', 'author_list', 'time']
|
||||
search_fields = ['name']
|
||||
list_filter = ['type']
|
||||
raw_id_fields = ['authors', 'related', 'group', 'shepherd', 'ad']
|
||||
raw_id_fields = ['authors', 'group', 'shepherd', 'ad']
|
||||
inlines = [DocAliasInline, DocAuthorInline, RelatedDocumentInline, ]
|
||||
form = DocumentForm
|
||||
|
||||
|
|
351
ietf/doc/migrations/0011_cleanup_new_revision_docevents.py
Normal file
351
ietf/doc/migrations/0011_cleanup_new_revision_docevents.py
Normal file
|
@ -0,0 +1,351 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
for e in orm.NewRevisionDocEvent.objects.filter(type="new_revision").iterator():
|
||||
# fix the format
|
||||
if (e.doc_id.startswith("draft-") or e.doc_id.startswith("charter-")) and e.desc in ("Added new revision", "New revision available"):
|
||||
desc = "New version available: <b>%s-%s.txt</b>" % (e.doc_id, e.rev)
|
||||
orm.DocEvent.objects.filter(id=e.docevent_ptr_id).update(desc=desc)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
|
||||
},
|
||||
'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['doc.Document']"}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
'doc.document': {
|
||||
'Meta': {'object_name': 'Document'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.statetype': {
|
||||
'Meta': {'object_name': 'StateType'},
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docrelationshipname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctagname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.groupstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.grouptypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.intendedstdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.stdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.streamname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'person.email': {
|
||||
'Meta': {'object_name': 'Email'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'person.person': {
|
||||
'Meta': {'object_name': 'Person'},
|
||||
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
363
ietf/doc/migrations/0012_cleanup_doc_notes.py
Normal file
363
ietf/doc/migrations/0012_cleanup_doc_notes.py
Normal file
|
@ -0,0 +1,363 @@
|
|||
# encoding: utf-8
|
||||
import datetime, re
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
for d in orm.Document.objects.filter(type="draft").exclude(note="").iterator():
|
||||
note = d.note
|
||||
|
||||
# get rid of HTML garbage
|
||||
note = note.replace("\r", "")
|
||||
note = note.replace("<br>", "\n")
|
||||
note = note.replace(" ", " ")
|
||||
note = note.strip()
|
||||
|
||||
# whack obsolete RFC/BCP/STD 1234 notes (obsolete now that
|
||||
# we got RFC alias links set up properly),
|
||||
# there are a couple that match without a
|
||||
# corresponding RFC DocAlias, but upon manual
|
||||
# inspection these all turn out to be mistakes in the
|
||||
# note (most are off-by-one in the RFC number)
|
||||
note = re.sub("^((STD|BCP|RFC)\s*#?\d+[\s,;]*)+", "", note).strip()
|
||||
|
||||
if note != d.note:
|
||||
orm.Document.objects.filter(name=d.name).update(note=note)
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
|
||||
},
|
||||
'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['doc.Document']"}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
'doc.document': {
|
||||
'Meta': {'object_name': 'Document'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'previous_states'", 'symmetrical': 'False', 'to': "orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.statetype': {
|
||||
'Meta': {'object_name': 'StateType'},
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docrelationshipname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctagname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.groupstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.grouptypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.intendedstdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.stdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.streamname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'person.email': {
|
||||
'Meta': {'object_name': 'Email'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'person.person': {
|
||||
'Meta': {'object_name': 'Person'},
|
||||
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
379
ietf/doc/migrations/0013_fixup_broken_rfc_docs.py
Normal file
379
ietf/doc/migrations/0013_fixup_broken_rfc_docs.py
Normal file
|
@ -0,0 +1,379 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# first get rid of unconnected redundant RFCs
|
||||
for d in orm.Document.objects.filter(name__startswith="rfc"):
|
||||
if d.docalias_set.count() == 0 and orm.DocAlias.objects.filter(name=d.name):
|
||||
d.delete() # this doc is unreachable
|
||||
|
||||
# fix up some standalone RFCs that didn't get type="draft" set
|
||||
orm.Document.objects.filter(name__startswith="rfc", type=None).update(type="draft")
|
||||
|
||||
# fix RFCs with group=None, set them to the individual
|
||||
# submitter "none" group - this may in some historic cases be
|
||||
# wrong, but in many of those cases we don't have a group to
|
||||
# connect the document to anyway (a later history fixing round
|
||||
# can find these documents as
|
||||
# Document.objects.filter(name__startswith="rfc", group__type="individ"))
|
||||
orm.Document.objects.filter(name__startswith="rfc", group=None).update(group=orm["group.Group"].objects.get(type="individ"))
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
|
||||
},
|
||||
'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.consensusdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.deletedevent': {
|
||||
'Meta': {'object_name': 'DeletedEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'json': ('django.db.models.fields.TextField', [], {}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['doc.Document']"}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
'doc.document': {
|
||||
'Meta': {'object_name': 'Document'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': "orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.statedocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']", 'null': 'True', 'blank': 'True'}),
|
||||
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"})
|
||||
},
|
||||
'doc.statetype': {
|
||||
'Meta': {'object_name': 'StateType'},
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docrelationshipname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctagname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.groupstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.grouptypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.intendedstdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.stdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.streamname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'person.email': {
|
||||
'Meta': {'object_name': 'Email'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'person.person': {
|
||||
'Meta': {'object_name': 'Person'},
|
||||
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
369
ietf/doc/migrations/0014_fix_rfc_aliases.py
Normal file
369
ietf/doc/migrations/0014_fix_rfc_aliases.py
Normal file
|
@ -0,0 +1,369 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
for alias in orm.DocAlias.objects.filter(models.Q(name__startswith="bcp")
|
||||
| models.Q(name__startswith="std")
|
||||
| models.Q(name__startswith="fyi")):
|
||||
# remove left-padded zeros
|
||||
alias.name = alias.name[:3] + str(int(alias.name[3:]))
|
||||
alias.save()
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
|
||||
models = {
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'doc.ballotdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.ballotpositiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['doc.BallotDocEvent']", 'null': 'True'}),
|
||||
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
|
||||
},
|
||||
'doc.ballottype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
|
||||
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.consensusdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.deletedevent': {
|
||||
'Meta': {'object_name': 'DeletedEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'json': ('django.db.models.fields.TextField', [], {}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
'doc.docalias': {
|
||||
'Meta': {'object_name': 'DocAlias'},
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
|
||||
},
|
||||
'doc.docevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'doc.dochistory': {
|
||||
'Meta': {'object_name': 'DocHistory'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
|
||||
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['doc.Document']"}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "orm['doc.RelatedDocHistory']", 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.dochistoryauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {})
|
||||
},
|
||||
'doc.docreminder': {
|
||||
'Meta': {'object_name': 'DocReminder'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'due': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
|
||||
},
|
||||
'doc.document': {
|
||||
'Meta': {'object_name': 'Document'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
|
||||
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
|
||||
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
|
||||
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
|
||||
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
|
||||
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.documentauthor': {
|
||||
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
|
||||
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
|
||||
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
|
||||
},
|
||||
'doc.initialreviewdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.lastcalldocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.newrevisiondocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
|
||||
},
|
||||
'doc.relateddochistory': {
|
||||
'Meta': {'object_name': 'RelatedDocHistory'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.relateddocument': {
|
||||
'Meta': {'object_name': 'RelatedDocument'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
|
||||
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
|
||||
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
|
||||
},
|
||||
'doc.state': {
|
||||
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': "orm['doc.State']"}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'doc.statedocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']", 'null': 'True', 'blank': 'True'}),
|
||||
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"})
|
||||
},
|
||||
'doc.statetype': {
|
||||
'Meta': {'object_name': 'StateType'},
|
||||
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
|
||||
},
|
||||
'doc.telechatdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'doc.writeupdocevent': {
|
||||
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
|
||||
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
|
||||
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'group.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
|
||||
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
|
||||
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
|
||||
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
|
||||
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
|
||||
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'name.ballotpositionname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
|
||||
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docrelationshipname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.docremindertypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctagname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.doctypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.groupstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.grouptypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.intendedstdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.stdlevelname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'name.streamname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
|
||||
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
|
||||
},
|
||||
'person.email': {
|
||||
'Meta': {'object_name': 'Email'},
|
||||
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
|
||||
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
|
||||
},
|
||||
'person.person': {
|
||||
'Meta': {'object_name': 'Person'},
|
||||
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['doc']
|
|
@ -4,6 +4,7 @@ from django.db import models
|
|||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.conf import settings
|
||||
from django.utils.html import mark_safe
|
||||
|
||||
from ietf.group.models import *
|
||||
from ietf.name.models import *
|
||||
|
@ -99,20 +100,26 @@ class DocumentInfo(models.Model):
|
|||
self.states.remove(*others)
|
||||
if state not in already_set:
|
||||
self.states.add(state)
|
||||
self.state_cache = None # invalidate cache
|
||||
|
||||
def unset_state(self, state_type):
|
||||
"""Unset state of type so no state of that type is any longer set."""
|
||||
self.states.remove(*self.states.filter(type=state_type))
|
||||
self.state_cache = None # invalidate cache
|
||||
|
||||
def get_state(self, state_type=None):
|
||||
"""Get state of type, or default state for document type if not specified."""
|
||||
"""Get state of type, or default state for document type if
|
||||
not specified. Uses a local cache to speed multiple state
|
||||
reads up."""
|
||||
if state_type == None:
|
||||
state_type = self.type_id
|
||||
|
||||
try:
|
||||
return self.states.get(type=state_type)
|
||||
except State.DoesNotExist:
|
||||
return None
|
||||
if not hasattr(self, "state_cache") or self.state_cache == None:
|
||||
self.state_cache = {}
|
||||
for s in self.states.all().select_related():
|
||||
self.state_cache[s.type_id] = s
|
||||
|
||||
return self.state_cache.get(state_type, None)
|
||||
|
||||
def get_state_slug(self, state_type=None):
|
||||
"""Get state of type, or default if not specified, returning
|
||||
|
@ -137,8 +144,10 @@ class DocumentInfo(models.Model):
|
|||
def active_ballot(self):
|
||||
"""Returns the most recently created ballot if it isn't closed."""
|
||||
ballot = self.latest_event(BallotDocEvent, type="created_ballot")
|
||||
open = self.ballot_open(ballot.ballot_type.slug) if ballot else False
|
||||
return ballot if open else None
|
||||
if ballot and self.ballot_open(ballot.ballot_type.slug):
|
||||
return ballot
|
||||
else:
|
||||
return None
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -167,7 +176,7 @@ class DocumentAuthor(models.Model):
|
|||
|
||||
class Document(DocumentInfo):
|
||||
name = models.CharField(max_length=255, primary_key=True) # immutable
|
||||
related = models.ManyToManyField('DocAlias', through=RelatedDocument, blank=True, related_name="reversely_related_document_set")
|
||||
#related = models.ManyToManyField('DocAlias', through=RelatedDocument, blank=True, related_name="reversely_related_document_set")
|
||||
authors = models.ManyToManyField(Email, through=DocumentAuthor, blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
|
@ -230,6 +239,14 @@ class Document(DocumentInfo):
|
|||
name = name.upper()
|
||||
return name
|
||||
|
||||
def related_that(self, relationship):
|
||||
"""Return the documents that are source of relationship targeting self."""
|
||||
return Document.objects.filter(relateddocument__target__document=self, relateddocument__relationship=relationship)
|
||||
|
||||
def related_that_doc(self, relationship):
|
||||
"""Return the doc aliases that are target of relationship originating from self."""
|
||||
return DocAlias.objects.filter(relateddocument__source=self, relateddocument__relationship=relationship)
|
||||
|
||||
#TODO can/should this be a function instead of a property? Currently a view uses it as a property
|
||||
@property
|
||||
def telechat_date(self):
|
||||
|
@ -284,9 +301,6 @@ class Document(DocumentInfo):
|
|||
qs = self.docalias_set.filter(name__startswith='rfc')
|
||||
return qs[0].name[3:] if qs else None
|
||||
|
||||
def replaced_by(self):
|
||||
return [ rel.source for alias in self.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='replaces') ]
|
||||
|
||||
def friendly_state(self):
|
||||
""" Return a concise text description of the document's current state """
|
||||
if self.type_id=='draft':
|
||||
|
@ -305,12 +319,12 @@ class Document(DocumentInfo):
|
|||
iesg_state_summary = iesg_state_summary + "::"+"::".join(tag.name for tag in iesg_substate)
|
||||
|
||||
if self.get_state_slug() == "rfc":
|
||||
#return "<a href=\"%s\">RFC %d</a>" % (urlreverse('doc_view', args=['rfc%d' % int(self.rfc_number())]), int(self.rfc_number()))
|
||||
return "RFC %d (%s)" % (int(self.rfc_number()), self.std_level)
|
||||
n = self.rfc_number()
|
||||
return "<a href=\"%s\">RFC %s</a>" % (urlreverse('doc_view', kwargs=dict(name='rfc%s' % n)), n)
|
||||
elif self.get_state_slug() == "repl":
|
||||
rs = self.replaced_by()
|
||||
rs = self.related_that("replaces")
|
||||
if rs:
|
||||
return "Replaced by "+", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', args=[name]),name) for name in rs)
|
||||
return mark_safe("Replaced by " + ", ".join("<a href=\"%s\">%s</a>" % (urlreverse('doc_view', args=[name]), name) for name in rs))
|
||||
else:
|
||||
return "Replaced"
|
||||
elif self.get_state_slug() == "active":
|
||||
|
@ -585,7 +599,13 @@ class BallotDocEvent(DocEvent):
|
|||
|
||||
if e.pos != prev:
|
||||
latest.old_positions.append(e.pos)
|
||||
|
||||
|
||||
# get rid of trailling "No record" positions, some old ballots
|
||||
# have plenty of these
|
||||
for p in positions:
|
||||
while p.old_positions and p.old_positions[-1].slug == "norecord":
|
||||
p.old_positions.pop()
|
||||
|
||||
# add any missing ADs through fake No Record events
|
||||
if self.doc.active_ballot() == self:
|
||||
norecord = BallotPositionName.objects.get(slug="norecord")
|
||||
|
|
|
@ -1,4 +1,144 @@
|
|||
import os, shutil, datetime
|
||||
|
||||
import django.test
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.conf import settings
|
||||
|
||||
from pyquery import PyQuery
|
||||
|
||||
from ietf.utils.mail import outbox
|
||||
from ietf.utils.test_utils import login_testing_unauthorized
|
||||
from ietf.utils.test_data import make_test_data
|
||||
|
||||
from ietf.doc.models import *
|
||||
from ietf.name.models import *
|
||||
from ietf.group.models import *
|
||||
from ietf.person.models import *
|
||||
from ietf.meeting.models import Meeting, MeetingTypeName
|
||||
from ietf.iesg.models import TelechatDate
|
||||
|
||||
# extra tests
|
||||
from ietf.doc.tests_conflict_review import *
|
||||
from ietf.doc.tests_status_change import *
|
||||
|
||||
|
||||
class DocTestCase(django.test.TestCase):
|
||||
fixtures = ['names']
|
||||
|
||||
def test_document_draft(self):
|
||||
draft = make_test_data()
|
||||
|
||||
# these tests aren't testing all attributes yet, feel free to
|
||||
# expand them
|
||||
|
||||
|
||||
# active draft
|
||||
draft.set_state(State.objects.get(type="draft", slug="active"))
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue("Active Internet-Draft" in r.content)
|
||||
|
||||
# expired draft
|
||||
draft.set_state(State.objects.get(type="draft", slug="expired"))
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue("Expired Internet-Draft" in r.content)
|
||||
|
||||
# replaced draft
|
||||
draft.set_state(State.objects.get(type="draft", slug="repl"))
|
||||
|
||||
replacement = Document.objects.create(
|
||||
name="draft-ietf-replacement",
|
||||
time=datetime.datetime.now(),
|
||||
type_id="draft",
|
||||
title="Replacement Draft",
|
||||
stream_id=draft.stream_id, group_id=draft.group_id, abstract=draft.stream, rev=draft.rev,
|
||||
pages=draft.pages, intended_std_level_id=draft.intended_std_level_id,
|
||||
shepherd_id=draft.shepherd_id, ad_id=draft.ad_id, expires=draft.expires,
|
||||
notify=draft.notify, note=draft.note)
|
||||
DocAlias.objects.create(name=replacement.name, document=replacement)
|
||||
rel = RelatedDocument.objects.create(source=replacement,
|
||||
target=draft.docalias_set.get(name__startswith="draft"),
|
||||
relationship_id="replaces")
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue("Replaced Internet-Draft" in r.content)
|
||||
self.assertTrue(replacement.name in r.content)
|
||||
rel.delete()
|
||||
|
||||
# draft published as RFC
|
||||
draft.set_state(State.objects.get(type="draft", slug="rfc"))
|
||||
draft.std_level_id = "bcp"
|
||||
draft.save()
|
||||
|
||||
DocEvent.objects.create(doc=draft, type="published_rfc", by=Person.objects.get(name="(System)"))
|
||||
|
||||
rfc_alias = DocAlias.objects.create(name="rfc123456", document=draft)
|
||||
bcp_alias = DocAlias.objects.create(name="bcp123456", document=draft)
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=draft.name)))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=bcp_alias.name)))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=rfc_alias.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue("RFC 123456" in r.content)
|
||||
self.assertTrue(draft.name in r.content)
|
||||
|
||||
# naked RFC
|
||||
rfc = Document.objects.create(
|
||||
name="rfc1234567",
|
||||
type_id="draft",
|
||||
title="RFC without a Draft",
|
||||
stream_id="ise",
|
||||
group=Group.objects.get(type="individ"),
|
||||
std_level_id="ps")
|
||||
DocAlias.objects.create(name=rfc.name, document=rfc)
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name=rfc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertTrue("RFC 1234567" in r.content)
|
||||
|
||||
# unknown draft
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name="draft-xyz123")))
|
||||
self.assertEqual(r.status_code, 404)
|
||||
|
||||
def test_document_charter(self):
|
||||
make_test_data()
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name="charter-ietf-mars")))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_document_conflict_review(self):
|
||||
make_test_data()
|
||||
|
||||
r = self.client.get(urlreverse("doc_view", kwargs=dict(name='conflict-review-imaginary-irtf-submission')))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_document_ballot(self):
|
||||
doc = make_test_data()
|
||||
ballot = doc.active_ballot()
|
||||
|
||||
BallotPositionDocEvent.objects.create(
|
||||
doc=doc,
|
||||
type="changed_ballot_position",
|
||||
pos_id="yes",
|
||||
comment="Looks fine to me",
|
||||
comment_time=datetime.datetime.now(),
|
||||
ad=Person.objects.get(user__username="ad"),
|
||||
by=Person.objects.get(name="(System)"))
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
# test popup too while we're at it
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.ballot_for_popup", kwargs=dict(name=doc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
||||
def test_document_json(self):
|
||||
doc = make_test_data()
|
||||
|
||||
r = self.client.get(urlreverse("ietf.doc.views_doc.document_json", kwargs=dict(name=doc.name)))
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import os
|
||||
import os, re, urllib
|
||||
import math
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -138,9 +138,12 @@ def augment_events_with_revision(doc, events):
|
|||
|
||||
event_revisions = list(NewRevisionDocEvent.objects.filter(doc=doc).order_by('time', 'id').values('id', 'rev', 'time'))
|
||||
|
||||
cur_rev = doc.rev
|
||||
if doc.get_state_slug() == "rfc":
|
||||
cur_rev = "RFC"
|
||||
if doc.type_id == "draft" and doc.get_state_slug() == "rfc":
|
||||
# add fake "RFC" revision
|
||||
e = doc.latest_event(type="published_rfc")
|
||||
if e:
|
||||
event_revisions.append(dict(id=e.id, time=e.time, rev="RFC"))
|
||||
event_revisions.sort(key=lambda x: (x["time"], x["id"]))
|
||||
|
||||
for e in sorted(events, key=lambda e: (e.time, e.id), reverse=True):
|
||||
while event_revisions and (e.time, e.id) < (event_revisions[-1]["time"], event_revisions[-1]["id"]):
|
||||
|
@ -153,6 +156,37 @@ def augment_events_with_revision(doc, events):
|
|||
|
||||
e.rev = cur_rev
|
||||
|
||||
def add_links_in_new_revision_events(doc, events, diff_revisions):
|
||||
"""Add direct .txt links and diff links to new_revision events."""
|
||||
prev = None
|
||||
|
||||
diff_urls = dict(((name, revision), url) for name, revision, time, url in diff_revisions)
|
||||
|
||||
for e in sorted(events, key=lambda e: (e.time, e.id)):
|
||||
if not e.type == "new_revision":
|
||||
continue
|
||||
|
||||
if not (e.doc.name, e.rev) in diff_urls:
|
||||
continue
|
||||
|
||||
full_url = diff_url = diff_urls[(e.doc.name, e.rev)]
|
||||
|
||||
if doc.type_id in "draft": # work around special diff url for drafts
|
||||
full_url = "http://tools.ietf.org/id/" + diff_url + ".txt"
|
||||
|
||||
# build links
|
||||
links = r'<a href="%s">\1</a>' % full_url
|
||||
if prev:
|
||||
links += ""
|
||||
|
||||
if prev != None:
|
||||
links += ' (<a href="http:%s?url1=%s&url2=%s">diff from previous</a>)' % (settings.RFCDIFF_PREFIX, urllib.quote(diff_url, safe="~"), urllib.quote(prev, safe="~"))
|
||||
|
||||
# replace the bold filename part
|
||||
e.desc = re.sub(r"<b>(.+-[0-9][0-9].txt)</b>", links, e.desc)
|
||||
|
||||
prev = diff_url
|
||||
|
||||
|
||||
def get_document_content(key, filename, split=True, markup=True):
|
||||
f = None
|
||||
|
@ -161,15 +195,12 @@ def get_document_content(key, filename, split=True, markup=True):
|
|||
raw_content = f.read()
|
||||
except IOError:
|
||||
error = "Error; cannot read ("+key+")"
|
||||
if split:
|
||||
return (error, "")
|
||||
else:
|
||||
return error
|
||||
return error
|
||||
finally:
|
||||
if f:
|
||||
f.close()
|
||||
if markup:
|
||||
return markup_txt.markup(raw_content,split)
|
||||
return markup_txt.markup(raw_content, split)
|
||||
else:
|
||||
return raw_content
|
||||
|
||||
|
@ -197,3 +228,16 @@ def add_state_change_event(doc, by, prev_state, new_state, timestamp=None):
|
|||
e.save()
|
||||
return e
|
||||
|
||||
def prettify_std_name(n):
|
||||
if re.match(r"(rfc|bcp|fyi|std)[0-9]+", n):
|
||||
return n[:3].upper() + " " + n[3:]
|
||||
else:
|
||||
return n
|
||||
|
||||
def nice_consensus(consensus):
|
||||
mapping = {
|
||||
None: "Unknown",
|
||||
True: "Yes",
|
||||
False: "No"
|
||||
}
|
||||
return mapping[consensus]
|
||||
|
|
701
ietf/doc/views_doc.py
Normal file
701
ietf/doc/views_doc.py
Normal file
|
@ -0,0 +1,701 @@
|
|||
# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
#
|
||||
# * Neither the name of the Nokia Corporation and/or its
|
||||
# subsidiary(-ies) nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import re, os, datetime, urllib
|
||||
|
||||
from django.http import HttpResponse, Http404
|
||||
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
|
||||
from django.utils import simplejson as json
|
||||
from django.utils.decorators import decorator_from_middleware
|
||||
from django.middleware.gzip import GZipMiddleware
|
||||
from django.core.urlresolvers import reverse as urlreverse, NoReverseMatch
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.doc.models import *
|
||||
from ietf.doc.utils import *
|
||||
from ietf.utils.history import find_history_active_at
|
||||
from ietf.ietfauth.utils import *
|
||||
|
||||
def render_document_top(request, doc, tab, name):
|
||||
tabs = []
|
||||
tabs.append(("Document", "document", urlreverse("doc_view", kwargs=dict(name=name)), True))
|
||||
|
||||
ballot = doc.latest_event(BallotDocEvent, type="created_ballot")
|
||||
if doc.type_id in ("draft","conflrev"):
|
||||
# if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
|
||||
tabs.append(("IESG Evaluation Record", "ballot", urlreverse("doc_ballot", kwargs=dict(name=name)), ballot))
|
||||
elif doc.type_id == "charter":
|
||||
tabs.append(("IESG Review", "ballot", urlreverse("doc_ballot", kwargs=dict(name=name)), ballot))
|
||||
|
||||
# FIXME: if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
|
||||
if doc.type_id != "conflrev":
|
||||
tabs.append(("IESG Writeups", "writeup", urlreverse("doc_writeup", kwargs=dict(name=name)), True))
|
||||
|
||||
tabs.append(("History", "history", urlreverse("doc_history", kwargs=dict(name=name)), True))
|
||||
|
||||
if name.startswith("rfc"):
|
||||
name = "RFC %s" % name[3:]
|
||||
else:
|
||||
name += "-" + doc.rev
|
||||
|
||||
return render_to_string("doc/document_top.html",
|
||||
dict(doc=doc,
|
||||
tabs=tabs,
|
||||
selected=tab,
|
||||
name=name))
|
||||
|
||||
|
||||
@decorator_from_middleware(GZipMiddleware)
|
||||
def document_main(request, name, rev=None):
|
||||
doc = get_object_or_404(Document.objects.select_related(), docalias__name=name)
|
||||
|
||||
# take care of possible redirections
|
||||
aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True)
|
||||
if doc.type_id == "draft" and not name.startswith("rfc"):
|
||||
for a in aliases:
|
||||
if a.startswith("rfc"):
|
||||
return redirect("doc_view", name=a)
|
||||
|
||||
group = doc.group
|
||||
if doc.type_id == 'conflrev':
|
||||
conflictdoc = doc.related_that_doc('conflrev').get().document
|
||||
|
||||
revisions = []
|
||||
for h in doc.history_set.order_by("time", "id"):
|
||||
if h.rev and not h.rev in revisions:
|
||||
revisions.append(h.rev)
|
||||
if not doc.rev in revisions:
|
||||
revisions.append(doc.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)
|
||||
|
||||
if doc.type_id == "charter":
|
||||
# find old group, too
|
||||
gh = find_history_active_at(doc.group, doc.time)
|
||||
if gh:
|
||||
group = gh
|
||||
|
||||
top = render_document_top(request, doc, "document", name)
|
||||
|
||||
|
||||
telechat = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
|
||||
if telechat and (not telechat.telechat_date or telechat.telechat_date < datetime.date.today()):
|
||||
telechat = None
|
||||
|
||||
|
||||
# specific document types
|
||||
if doc.type_id == "draft":
|
||||
split_content = not request.GET.get('include_text')
|
||||
if request.COOKIES.get("full_draft", "") == "on":
|
||||
split = False
|
||||
|
||||
iesg_state = doc.get_state("draft-iesg")
|
||||
|
||||
can_edit = has_role(request.user, ("Area Director", "Secretariat"))
|
||||
stream_slugs = StreamName.objects.values_list("slug", flat=True)
|
||||
can_change_stream = bool(can_edit or (
|
||||
request.user.is_authenticated() and
|
||||
Role.objects.filter(name__in=("chair", "auth"),
|
||||
group__acronym__in=stream_slugs,
|
||||
person__user=request.user)))
|
||||
can_edit_iana_state = has_role(request.user, ("Secretariat", "IANA"))
|
||||
|
||||
rfc_number = name[3:] if name.startswith("") else None
|
||||
draft_name = None
|
||||
for a in aliases:
|
||||
if a.startswith("draft"):
|
||||
draft_name = a
|
||||
|
||||
rfc_aliases = [prettify_std_name(a) for a in aliases
|
||||
if a.startswith("fyi") or a.startswith("std") or a.startswith("bcp")]
|
||||
|
||||
latest_revision = None
|
||||
|
||||
if doc.get_state_slug() == "rfc":
|
||||
# content
|
||||
filename = name + ".txt"
|
||||
|
||||
content = get_document_content(filename, os.path.join(settings.RFC_PATH, filename),
|
||||
split_content, markup=True)
|
||||
|
||||
# file types
|
||||
base_path = os.path.join(settings.RFC_PATH, name + ".")
|
||||
possible_types = ["txt", "pdf", "ps"]
|
||||
found_types = [t for t in possible_types if os.path.exists(base_path + t)]
|
||||
|
||||
base = "http://www.rfc-editor.org/rfc/"
|
||||
|
||||
file_urls = []
|
||||
for t in found_types:
|
||||
label = "plain text" if t == "txt" else t
|
||||
file_urls.append((label, base + name + "." + t))
|
||||
|
||||
if "pdf" not in found_types and "txt" in found_types:
|
||||
file_urls.append(("pdf", base + "pdfrfc/" + name + ".txt.pdf"))
|
||||
|
||||
if "txt" in found_types:
|
||||
file_urls.append(("html", "http://tools.ietf.org/html/" + name))
|
||||
|
||||
if not found_types:
|
||||
content = "This RFC is not currently available online."
|
||||
split_content = False
|
||||
elif "txt" not in found_types:
|
||||
content = "This RFC is not available in plain text format."
|
||||
split_content = False
|
||||
else:
|
||||
filename = "%s-%s.txt" % (draft_name, doc.rev)
|
||||
|
||||
content = get_document_content(filename, os.path.join(settings.INTERNET_DRAFT_PATH, filename),
|
||||
split_content, markup=True)
|
||||
|
||||
# file types
|
||||
base_path = os.path.join(settings.INTERNET_DRAFT_PATH, doc.name + "-" + doc.rev + ".")
|
||||
possible_types = ["pdf", "xml", "ps"]
|
||||
found_types = ["txt"] + [t for t in possible_types if os.path.exists(base_path + t)]
|
||||
|
||||
tools_base = "http://tools.ietf.org/"
|
||||
|
||||
if doc.get_state_slug() == "active":
|
||||
base = "http://www.ietf.org/id/"
|
||||
else:
|
||||
base = tools_base + "id/"
|
||||
|
||||
file_urls = []
|
||||
for t in found_types:
|
||||
label = "plain text" if t == "txt" else t
|
||||
file_urls.append((label, base + doc.name + "-" + doc.rev + "." + t))
|
||||
|
||||
if "pdf" not in found_types:
|
||||
file_urls.append(("pdf", tools_base + "pdf/" + doc.name + "-" + doc.rev + ".pdf"))
|
||||
file_urls.append(("html", tools_base + "html/" + doc.name + "-" + doc.rev))
|
||||
|
||||
# latest revision
|
||||
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
|
||||
|
||||
# ballot
|
||||
ballot_summary = None
|
||||
if iesg_state and iesg_state.slug in ("lc", "writeupw", "goaheadw", "iesg-eva", "defer"):
|
||||
active_ballot = doc.active_ballot()
|
||||
if active_ballot:
|
||||
ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())
|
||||
|
||||
# submission
|
||||
submission = ""
|
||||
if group.type_id == "individ":
|
||||
submission = "individual"
|
||||
elif group.type_id == "area" and doc.stream_id == "ietf":
|
||||
submission = "individual in %s area" % group.acronym
|
||||
elif group.type_id in ("rg", "wg"):
|
||||
submission = "%s %s" % (group.acronym, group.type)
|
||||
if group.type_id == "wg":
|
||||
submission = "<a href=\"%s\">%s</a>" % (urlreverse("wg_docs", kwargs=dict(acronym=doc.group.acronym)), submission)
|
||||
if doc.stream_id and doc.get_state_slug("draft-stream-%s" % doc.stream_id) == "c-adopt":
|
||||
submission = "candidate for %s" % submission
|
||||
|
||||
# resurrection
|
||||
resurrected_by = None
|
||||
if doc.get_state_slug() == "expired":
|
||||
e = doc.latest_event(type__in=("requested_resurrect", "completed_resurrect"))
|
||||
if e and e.type == "requested_resurrect":
|
||||
resurrected_by = e.by
|
||||
|
||||
# stream info
|
||||
stream_state = None
|
||||
if doc.stream:
|
||||
stream_state = doc.get_state("draft-stream-%s" % doc.stream_id)
|
||||
stream_tags = doc.tags.filter(slug__in=get_tags_for_stream_id(doc.stream_id))
|
||||
|
||||
shepherd_writeup = doc.latest_event(WriteupDocEvent, type="changed_protocol_writeup")
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
|
||||
|
||||
consensus = None
|
||||
if doc.stream_id in ("ietf", "irtf", "iab"):
|
||||
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
consensus = nice_consensus(e and e.consensus)
|
||||
|
||||
# mailing list search archive
|
||||
search_archive = "www.ietf.org/mail-archive/web/"
|
||||
if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive:
|
||||
search_archive = group.list_archive
|
||||
|
||||
search_archive = urllib.quote(search_archive, safe="~")
|
||||
|
||||
# conflict reviews
|
||||
conflict_reviews = [d.name for d in doc.related_that("conflrev")]
|
||||
|
||||
# remaining actions
|
||||
actions = []
|
||||
|
||||
if ((not doc.stream_id or doc.stream_id in ("ietf", "irtf")) and group.type_id == "individ" and
|
||||
(request.user.is_authenticated() and
|
||||
Role.objects.filter(person__user=request.user, name__in=("chair", "delegate"),
|
||||
group__type__in=("wg",),
|
||||
group__state="active")
|
||||
or has_role(request.user, "Secretariat"))):
|
||||
actions.append(("Adopt in Group", urlreverse('edit_adopt', kwargs=dict(name=doc.name))))
|
||||
|
||||
if doc.get_state_slug() == "expired" and not resurrected_by and can_edit:
|
||||
actions.append(("Request Resurrect", urlreverse('doc_request_resurrect', kwargs=dict(name=doc.name))))
|
||||
|
||||
if doc.get_state_slug() == "expired" and has_role(request.user, ("Secretariat",)):
|
||||
actions.append(("Resurrect", urlreverse('doc_resurrect', kwargs=dict(name=doc.name))))
|
||||
|
||||
if (doc.get_state_slug() != "expired" and doc.stream_id in ("ise", "irtf")
|
||||
and has_role(request.user, ("Secretariat",)) and not conflict_reviews):
|
||||
label = "Begin IETF Conflict Review"
|
||||
if not doc.intended_std_level:
|
||||
label += " (note that intended status is not set)"
|
||||
actions.append((label, urlreverse('conflict_review_start', kwargs=dict(name=doc.name))))
|
||||
|
||||
if doc.get_state_slug() != "expired" and doc.stream_id in ("ietf",) and can_edit and not iesg_state:
|
||||
actions.append(("Begin IESG Processing", urlreverse('doc_edit_info', kwargs=dict(name=doc.name)) + "?new=1"))
|
||||
|
||||
return render_to_response("doc/document_draft.html",
|
||||
dict(doc=doc,
|
||||
group=group,
|
||||
top=top,
|
||||
name=name,
|
||||
content=content,
|
||||
split_content=split_content,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
latest_revision=latest_revision,
|
||||
|
||||
can_edit=can_edit,
|
||||
can_change_stream=can_change_stream,
|
||||
can_edit_stream_info=can_edit_stream_info,
|
||||
can_edit_shepherd_writeup=can_edit_shepherd_writeup,
|
||||
can_edit_iana_state=can_edit_iana_state,
|
||||
|
||||
rfc_number=rfc_number,
|
||||
draft_name=draft_name,
|
||||
telechat=telechat,
|
||||
ballot_summary=ballot_summary,
|
||||
submission=submission,
|
||||
resurrected_by=resurrected_by,
|
||||
|
||||
replaces=[d.name for d in doc.related_that_doc("replaces")],
|
||||
replaced_by=[d.name for d in doc.related_that("replaces")],
|
||||
updates=[prettify_std_name(d.name) for d in doc.related_that_doc("updates")],
|
||||
updated_by=[prettify_std_name(d.canonical_name()) for d in doc.related_that("updates")],
|
||||
obsoletes=[prettify_std_name(d.name) for d in doc.related_that_doc("obs")],
|
||||
obsoleted_by=[prettify_std_name(d.canonical_name()) for d in doc.related_that("obs")],
|
||||
conflict_reviews=conflict_reviews,
|
||||
rfc_aliases=rfc_aliases,
|
||||
has_errata=doc.tags.filter(slug="errata"),
|
||||
published=doc.latest_event(type="published_rfc"),
|
||||
file_urls=file_urls,
|
||||
stream_state=stream_state,
|
||||
stream_tags=stream_tags,
|
||||
milestones=doc.groupmilestone_set.filter(state="active"),
|
||||
consensus=consensus,
|
||||
iesg_state=iesg_state,
|
||||
rfc_editor_state=doc.get_state("draft-rfceditor"),
|
||||
iana_review_state=doc.get_state("draft-iana-review"),
|
||||
iana_action_state=doc.get_state("draft-iana-action"),
|
||||
started_iesg_process=doc.latest_event(type="started_iesg_process"),
|
||||
shepherd_writeup=shepherd_writeup,
|
||||
search_archive=search_archive,
|
||||
actions=actions,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if doc.type_id == "charter":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
|
||||
content = get_document_content(filename, os.path.join(settings.CHARTER_PATH, filename), split=False, markup=True)
|
||||
|
||||
ballot_summary = None
|
||||
if doc.get_state_slug() in ("intrev", "iesgrev"):
|
||||
active_ballot = doc.active_ballot()
|
||||
if active_ballot:
|
||||
ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())
|
||||
else:
|
||||
ballot_summary = "No active ballot found."
|
||||
|
||||
chartering = get_chartering_type(doc)
|
||||
|
||||
# inject milestones from group
|
||||
milestones = None
|
||||
if chartering and not snapshot:
|
||||
milestones = doc.group.groupmilestone_set.filter(state="charter")
|
||||
|
||||
return render_to_response("doc/document_charter.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
chartering=chartering,
|
||||
content=content,
|
||||
txt_url=settings.CHARTER_TXT_URL + filename,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
telechat=telechat,
|
||||
ballot_summary=ballot_summary,
|
||||
group=group,
|
||||
milestones=milestones,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if doc.type_id == "conflrev":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
pathname = os.path.join(settings.CONFLICT_REVIEW_PATH,filename)
|
||||
|
||||
if doc.rev == "00" and not os.path.isfile(pathname):
|
||||
# This could move to a template
|
||||
content = "A conflict review response has not yet been proposed."
|
||||
else:
|
||||
content = get_document_content(filename, pathname, split=False, markup=True)
|
||||
|
||||
ballot_summary = None
|
||||
if doc.get_state_slug() in ("iesgeval"):
|
||||
ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
|
||||
|
||||
return render_to_response("doc/document_conflict_review.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
content=content,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
telechat=telechat,
|
||||
conflictdoc=conflictdoc,
|
||||
ballot_summary=ballot_summary,
|
||||
approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent')
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
raise Http404
|
||||
|
||||
|
||||
def document_history(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
top = render_document_top(request, doc, "history", name)
|
||||
|
||||
# pick up revisions from events
|
||||
diff_revisions = []
|
||||
|
||||
diffable = name.startswith("draft") or name.startswith("charter") or name.startswith("conflict-review")
|
||||
if diffable:
|
||||
diff_documents = [ doc ]
|
||||
diff_documents.extend(Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces"))
|
||||
|
||||
seen = set()
|
||||
for e in NewRevisionDocEvent.objects.filter(type="new_revision", doc__in=diff_documents).select_related('doc').order_by("-time", "-id"):
|
||||
if (e.doc.name, e.rev) in seen:
|
||||
continue
|
||||
|
||||
seen.add((e.doc.name, e.rev))
|
||||
|
||||
url = ""
|
||||
if name.startswith("charter"):
|
||||
url = request.build_absolute_uri(urlreverse("charter_with_milestones_txt", kwargs=dict(name=e.doc.name, rev=e.rev)))
|
||||
elif name.startswith("conflict-review"):
|
||||
h = find_history_active_at(e.doc, e.time)
|
||||
url = settings.CONFLICT_REVIEW_TXT_URL + ("%s-%s.txt" % ((h or doc).canonical_name(), e.rev))
|
||||
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")
|
||||
|
||||
augment_events_with_revision(doc, events)
|
||||
add_links_in_new_revision_events(doc, events, diff_revisions)
|
||||
|
||||
return render_to_response("doc/document_history.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
diff_revisions=diff_revisions,
|
||||
events=events,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_writeup(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
top = render_document_top(request, doc, "writeup", name)
|
||||
|
||||
def text_from_writeup(event_type):
|
||||
e = doc.latest_event(WriteupDocEvent, type=event_type)
|
||||
if e:
|
||||
return e.text
|
||||
else:
|
||||
return ""
|
||||
|
||||
sections = []
|
||||
if doc.type_id == "draft":
|
||||
writeups = []
|
||||
sections.append(("Approval Announcement",
|
||||
"<em>Draft</em> of message to be sent <em>after</em> approval:",
|
||||
writeups))
|
||||
|
||||
writeups.append(("Announcement",
|
||||
text_from_writeup("changed_ballot_approval_text"),
|
||||
urlreverse("doc_ballot_approvaltext", kwargs=dict(name=doc.name))))
|
||||
|
||||
writeups.append(("Ballot Text",
|
||||
text_from_writeup("changed_ballot_writeup_text"),
|
||||
urlreverse("doc_ballot_writeupnotes", kwargs=dict(name=doc.name))))
|
||||
|
||||
elif doc.type_id == "charter":
|
||||
sections.append(("WG Review Announcement",
|
||||
"",
|
||||
[("WG Review Announcement",
|
||||
text_from_writeup("changed_review_announcement"),
|
||||
urlreverse("ietf.wgcharter.views.announcement_text", kwargs=dict(name=doc.name, ann="review")))]
|
||||
))
|
||||
|
||||
sections.append(("WG Action Announcement",
|
||||
"",
|
||||
[("WG Action Announcement",
|
||||
text_from_writeup("changed_action_announcement"),
|
||||
urlreverse("ietf.wgcharter.views.announcement_text", kwargs=dict(name=doc.name, ann="action")))]
|
||||
))
|
||||
|
||||
if doc.latest_event(BallotDocEvent, type="created_ballot"):
|
||||
sections.append(("Ballot Announcement",
|
||||
"",
|
||||
[("Ballot Announcement",
|
||||
text_from_writeup("changed_ballot_writeup_text"),
|
||||
urlreverse("ietf.wgcharter.views.ballot_writeupnotes", kwargs=dict(name=doc.name)))]
|
||||
))
|
||||
|
||||
if not sections:
|
||||
raise Http404()
|
||||
|
||||
return render_to_response("doc/document_writeup.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
sections=sections,
|
||||
can_edit=has_role(request.user, ("Area Director", "Secretariat")),
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_shepherd_writeup(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
lastwriteup = doc.latest_event(WriteupDocEvent,type="changed_protocol_writeup")
|
||||
if lastwriteup:
|
||||
writeup_text = lastwriteup.text
|
||||
else:
|
||||
writeup_text = "(There is no shepherd's writeup available for this document)"
|
||||
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
|
||||
|
||||
return render_to_response("doc/shepherd_writeup.html",
|
||||
dict(doc=doc,
|
||||
writeup=writeup_text,
|
||||
can_edit=can_edit_shepherd_writeup
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_ballot_content(request, doc, ballot_id, editable=True):
|
||||
"""Render HTML string with content of ballot page."""
|
||||
all_ballots = list(BallotDocEvent.objects.filter(doc=doc, type="created_ballot").order_by("time"))
|
||||
augment_events_with_revision(doc, all_ballots)
|
||||
|
||||
ballot = None
|
||||
if ballot_id != None:
|
||||
ballot_id = int(ballot_id)
|
||||
for b in all_ballots:
|
||||
if b.id == ballot_id:
|
||||
ballot = b
|
||||
break
|
||||
elif all_ballots:
|
||||
ballot = all_ballots[-1]
|
||||
|
||||
if not ballot:
|
||||
raise Http404
|
||||
|
||||
deferred = doc.active_defer_event()
|
||||
|
||||
positions = ballot.all_positions()
|
||||
|
||||
# put into position groups
|
||||
position_groups = []
|
||||
for n in BallotPositionName.objects.filter(slug__in=[p.pos_id for p in positions]).order_by('order'):
|
||||
g = (n, [p for p in positions if p.pos_id == n.slug])
|
||||
g[1].sort(key=lambda p: (p.old_ad, p.ad.plain_name()))
|
||||
if n.blocking:
|
||||
position_groups.insert(0, g)
|
||||
else:
|
||||
position_groups.append(g)
|
||||
|
||||
summary = needed_ballot_positions(doc, [p for p in positions if not p.old_ad])
|
||||
|
||||
text_positions = [p for p in positions if p.discuss or p.comment]
|
||||
text_positions.sort(key=lambda p: (p.old_ad, p.ad.plain_name()))
|
||||
|
||||
ballot_open = not BallotDocEvent.objects.filter(doc=doc,
|
||||
type__in=("closed_ballot", "created_ballot"),
|
||||
time__gt=ballot.time,
|
||||
ballot_type=ballot.ballot_type)
|
||||
if not ballot_open:
|
||||
editable = False
|
||||
|
||||
return render_to_string("doc/document_ballot_content.html",
|
||||
dict(doc=doc,
|
||||
ballot=ballot,
|
||||
position_groups=position_groups,
|
||||
text_positions=text_positions,
|
||||
editable=editable,
|
||||
ballot_open=ballot_open,
|
||||
deferred=deferred,
|
||||
summary=summary,
|
||||
all_ballots=all_ballots,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_ballot(request, name, ballot_id=None):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
top = render_document_top(request, doc, "ballot", name)
|
||||
|
||||
c = document_ballot_content(request, doc, ballot_id, editable=True)
|
||||
|
||||
return render_to_response("doc/document_ballot.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
ballot_content=c,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_json(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
||||
def extract_name(s):
|
||||
return s.name if s else None
|
||||
|
||||
data = {}
|
||||
|
||||
data["name"] = doc.name
|
||||
data["rev"] = doc.rev
|
||||
data["time"] = doc.time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
data["group"] = None
|
||||
if doc.group:
|
||||
data["group"] = dict(
|
||||
name=doc.group.name,
|
||||
type=extract_name(doc.group.type),
|
||||
acronym=doc.group.acronym)
|
||||
data["expires"] = doc.expires.strftime("%Y-%m-%d %H:%M:%S") if doc.expires else None
|
||||
data["title"] = doc.title
|
||||
data["abstract"] = doc.abstract
|
||||
data["aliases"] = list(doc.docalias_set.values_list("name", flat=True))
|
||||
data["state"] = extract_name(doc.get_state())
|
||||
data["intended_std_level"] = extract_name(doc.intended_std_level)
|
||||
data["std_level"] = extract_name(doc.std_level)
|
||||
data["authors"] = [
|
||||
dict(name=e.person.name,
|
||||
email=e.address,
|
||||
affiliation=e.person.affiliation)
|
||||
for e in Email.objects.filter(documentauthor__document=doc).select_related("person").order_by("documentauthor__order")
|
||||
]
|
||||
data["shepherd"] = doc.shepherd.formatted_email() if doc.shepherd else None
|
||||
data["ad"] = doc.ad.role_email("ad").formatted_email() if doc.ad else None
|
||||
|
||||
if doc.type_id == "draft":
|
||||
data["iesg_state"] = extract_name(doc.get_state("draft-iesg"))
|
||||
data["rfceditor_state"] = extract_name(doc.get_state("draft-rfceditor"))
|
||||
data["iana_review_state"] = extract_name(doc.get_state("draft-iana-review"))
|
||||
data["iana_action_state"] = extract_name(doc.get_state("draft-iana-action"))
|
||||
|
||||
if doc.stream_id in ("ietf", "irtf", "iab"):
|
||||
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
data["consensus"] = e.consensus if e else None
|
||||
data["stream"] = extract_name(doc.stream)
|
||||
|
||||
return HttpResponse(json.dumps(data, indent=2), mimetype='text/plain')
|
||||
|
||||
def ballot_for_popup(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
return HttpResponse(document_ballot_content(request, doc, ballot_id=None, editable=False))
|
||||
|
||||
|
||||
def ballot_json(request, name):
|
||||
# REDESIGN: this view needs to be deleted or updated
|
||||
def get_ballot(name):
|
||||
from ietf.doc.models import DocAlias
|
||||
alias = get_object_or_404(DocAlias, name=name)
|
||||
d = alias.document
|
||||
from ietf.idtracker.models import InternetDraft, BallotInfo
|
||||
from ietf.idrfc.idrfc_wrapper import BallotWrapper, IdWrapper, RfcWrapper
|
||||
id = None
|
||||
bw = None
|
||||
dw = None
|
||||
if (d.type_id=='draft'):
|
||||
id = get_object_or_404(InternetDraft, name=d.name)
|
||||
try:
|
||||
if not id.ballot.ballot_issued:
|
||||
raise Http404
|
||||
except BallotInfo.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
bw = BallotWrapper(id) # XXX Fixme: Eliminate this as we go forward
|
||||
# Python caches ~100 regex'es -- explicitly compiling it inside a method
|
||||
# (where you then throw away the compiled version!) doesn't make sense at
|
||||
# all.
|
||||
if re.search("^rfc([1-9][0-9]*)$", name):
|
||||
id.viewing_as_rfc = True
|
||||
dw = RfcWrapper(id)
|
||||
else:
|
||||
dw = IdWrapper(id)
|
||||
# XXX Fixme: Eliminate 'dw' as we go forward
|
||||
|
||||
try:
|
||||
b = d.latest_event(BallotDocEvent, type="created_ballot")
|
||||
except BallotDocEvent.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
return (bw, dw, b, d)
|
||||
|
||||
ballot, doc, b, d = get_ballot(name)
|
||||
response = HttpResponse(mimetype='text/plain')
|
||||
response.write(json.dumps(ballot.dict(), indent=2))
|
||||
return response
|
||||
|
|
@ -395,7 +395,7 @@ class RfcWrapper:
|
|||
|
||||
@models.permalink
|
||||
def get_absolute_url(self):
|
||||
return ('ietf.idrfc.views_doc.document_main', ['rfc%s' % (str(self.rfc_number))])
|
||||
return ('ietf.doc.views_doc.document_main', ['rfc%s' % (str(self.rfc_number))])
|
||||
def displayname_with_link(self):
|
||||
return '<a href="%s">RFC %d</a>' % (self.get_absolute_url(), self.rfc_number)
|
||||
|
||||
|
|
|
@ -66,7 +66,8 @@ def markup(content, split=True):
|
|||
if split:
|
||||
n = content.find("\n", 5000)
|
||||
content1 = "<pre>"+content[:n+1]+"</pre>\n"
|
||||
content2 = "<pre>"+content[n+1:]+"</pre>\n"
|
||||
return (content1, content2)
|
||||
return content1
|
||||
#content2 = "<pre>"+content[n+1:]+"</pre>\n"
|
||||
#return (content1, content2)
|
||||
else:
|
||||
return "<pre>" + content + "</pre>\n"
|
||||
|
|
1725
ietf/idrfc/tests.py
1725
ietf/idrfc/tests.py
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,88 +0,0 @@
|
|||
200 /
|
||||
200 /doc/
|
||||
200,heavy /doc/all/
|
||||
200,heavy /doc/active/
|
||||
|
||||
# draft that's now RFC
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/doc.json
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/ballot.json
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/_ballot.data
|
||||
|
||||
# replaced draft, never went to IESG
|
||||
200 /doc/draft-eronen-mobike-mopo/
|
||||
404 /doc/draft-eronen-mobike-mopo/ballot.json
|
||||
404 /doc/draft-eronen-mobike-mopo/_ballot.data
|
||||
|
||||
# expired draft
|
||||
200 /doc/draft-eronen-eap-sim-aka-80211/
|
||||
|
||||
# Normal RFC
|
||||
200 /doc/rfc4739/
|
||||
200 /doc/rfc4739/doc.json
|
||||
404 /doc/rfc4739/ballot.json
|
||||
404 /doc/rfc4739/_ballot.data
|
||||
|
||||
# RFC that's evaluated in IESG
|
||||
200 /doc/rfc3852/
|
||||
200 /doc/rfc3852/doc.json
|
||||
200 /doc/rfc3852/ballot.json
|
||||
200 /doc/rfc3852/_ballot.data
|
||||
|
||||
# old RFC
|
||||
200 /doc/rfc822/
|
||||
200 /doc/rfc822/doc.json
|
||||
|
||||
# ballot sets
|
||||
200 /doc/rfc3550/ballot.json
|
||||
200 /doc/rfc3550/_ballot.data
|
||||
200 /doc/rfc3551/ballot.json
|
||||
200 /doc/rfc3551/_ballot.data
|
||||
200 /doc/draft-irtf-dtnrg-ltp/ballot.json
|
||||
200 /doc/draft-irtf-dtnrg-ltp/_ballot.data
|
||||
|
||||
# file formats
|
||||
200 /doc/rfc9/ # PDF only
|
||||
200 /doc/rfc2490/ # TXT+PDF+PS
|
||||
200 /doc/rfc500/ # not online
|
||||
|
||||
404 /doc/draft-no-such-draft/
|
||||
404 /doc/rfc4637/
|
||||
|
||||
200 /doc/rfc2444/doc.json # foreignkey problem with Django 1.x
|
||||
|
||||
# current AD -- needs to be updated at some point
|
||||
200 /doc/ad/robert.sparks/
|
||||
# former AD
|
||||
200 /doc/ad/sam.hartman/
|
||||
404 /doc/ad/no.body/
|
||||
|
||||
# ballot exists, but it's not issued
|
||||
404 /doc/draft-ietf-aaa-diameter-api/ballot.json
|
||||
404 /doc/draft-ietf-aaa-diameter-api/_ballot.data
|
||||
# ballot does not exist
|
||||
404 /doc/draft-zeilenga-cldap/ballot.json
|
||||
404 /doc/draft-zeilenga-cldap/_ballot.data
|
||||
# comment with created_by=999
|
||||
200 /doc/draft-ietf-l3vpn-2547bis-mcast-bgp/
|
||||
# comment with created_by=0 (and no idinternal entry)
|
||||
200 /doc/draft-ietf-proto-wgdocument-states/
|
||||
|
||||
200 /doc/search/
|
||||
200 /doc/search/?rfcs=on&name=snmp
|
||||
200 /doc/search/?rfcs=on&name=nfs&by=ad&ad=53
|
||||
200 /doc/search/?activeDrafts=on&name=sipping
|
||||
200 /doc/search/?oldDrafts=on&name=tls
|
||||
200 /doc/search/?activeDrafts=on&oldDrafts=on&ad=53&by=ad
|
||||
200 /doc/search/?activeDrafts=on&state=20&by=state
|
||||
200 /doc/search/?activeDrafts=on&oldDrafts=on&subState=5&by=state
|
||||
200 /doc/search/?activeDrafts=on&oldDrafts=on&rfcs=on&ad=53&name=nfs&by=ad
|
||||
200 /doc/search/?rfcs=on&group=tls&by=group
|
||||
200 /doc/search/?activeDrafts=on&group=tls&by=group
|
||||
200 /doc/search/?activeDrafts=on&oldDrafts=on&rfcs=on&author=eronen&by=author
|
||||
200 /doc/search/?activeDrafts=on&oldDrafts=on&rfcs=on&area=934&name=ldap&by=area
|
||||
200 /doc/search/?activeDrafts=on&name=asdfsadfsdfasdf
|
||||
200 /doc/search/?activeDrafts=on&name=%EF%BD%8C #non-ASCII
|
||||
|
||||
# Test case for missing publication date
|
||||
200 /doc/search/?oldDrafts=on&name=ppvpn
|
|
@ -3,71 +3,12 @@
|
|||
200,heavy /doc/all/
|
||||
200,heavy /doc/active/
|
||||
|
||||
# draft that's now RFC
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/doc.json
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/ballot.json
|
||||
200 /doc/draft-ietf-avt-rtp-atrac-family/ballotpopup/
|
||||
|
||||
# replaced draft, never went to IESG
|
||||
200 /doc/draft-eronen-mobike-mopo/
|
||||
404 /doc/draft-eronen-mobike-mopo/ballot.json
|
||||
404 /doc/draft-eronen-mobike-mopo/ballotpopup/
|
||||
|
||||
# expired draft
|
||||
200 /doc/draft-eronen-eap-sim-aka-80211/
|
||||
|
||||
# Normal RFC
|
||||
200 /doc/rfc4739/
|
||||
200 /doc/rfc4739/doc.json
|
||||
200 /doc/rfc4739/ballot.json # has ballot from I-D
|
||||
200 /doc/rfc4739/ballotpopup/
|
||||
|
||||
# RFC that's evaluated in IESG
|
||||
200 /doc/rfc3852/
|
||||
200 /doc/rfc3852/doc.json
|
||||
200 /doc/rfc3852/ballot.json
|
||||
200 /doc/rfc3852/ballotpopup/
|
||||
|
||||
# old RFC
|
||||
200 /doc/rfc822/
|
||||
200 /doc/rfc822/doc.json
|
||||
|
||||
# ballot sets
|
||||
200 /doc/rfc3550/ballot.json
|
||||
200 /doc/rfc3550/ballotpopup/
|
||||
200 /doc/rfc3551/ballot.json
|
||||
200 /doc/rfc3551/ballotpopup/
|
||||
200 /doc/draft-irtf-dtnrg-ltp/ballot.json
|
||||
200 /doc/draft-irtf-dtnrg-ltp/ballotpopup/
|
||||
|
||||
# file formats
|
||||
200 /doc/rfc9/ # PDF only
|
||||
200 /doc/rfc2490/ # TXT+PDF+PS
|
||||
200 /doc/rfc500/ # not online
|
||||
|
||||
404 /doc/draft-no-such-draft/
|
||||
404 /doc/rfc4637/
|
||||
|
||||
200 /doc/rfc2444/doc.json # foreignkey problem with Django 1.x
|
||||
|
||||
# current AD -- needs to be updated at some point
|
||||
200 /doc/ad/robert.sparks/
|
||||
# former AD
|
||||
200 /doc/ad/sam.hartman/
|
||||
404 /doc/ad/no.body/
|
||||
|
||||
# ballot exists, but it's not issued
|
||||
404 /doc/draft-ietf-aaa-diameter-api/ballot.json
|
||||
404 /doc/draft-ietf-aaa-diameter-api/ballotpopup/
|
||||
# ballot does not exist
|
||||
404 /doc/draft-zeilenga-cldap/ballot.json
|
||||
404 /doc/draft-zeilenga-cldap/ballotpopup/
|
||||
# comment with created_by=999
|
||||
200 /doc/draft-ietf-l3vpn-2547bis-mcast-bgp/
|
||||
# comment with created_by=0 (and no idinternal entry)
|
||||
200 /doc/draft-ietf-proto-wgdocument-states/
|
||||
|
||||
200 /doc/search/
|
||||
200 /doc/search/?rfcs=on&name=snmp
|
||||
200 /doc/search/?rfcs=on&name=nfs&by=ad&ad=112773
|
||||
|
|
|
@ -31,9 +31,10 @@
|
|||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from django.conf.urls.defaults import patterns, url, include
|
||||
from ietf.idrfc import views_doc, views_search, views_edit, views_ballot, views
|
||||
from ietf.idrfc import views_search, views_edit, views_ballot, views
|
||||
from ietf.doc.models import State
|
||||
from ietf.doc import views_status_change
|
||||
from ietf.doc import views_doc
|
||||
|
||||
urlpatterns = patterns('',
|
||||
(r'^/?$', views_search.search_main),
|
||||
|
@ -56,8 +57,7 @@ urlpatterns = patterns('',
|
|||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot/$', views_doc.document_ballot, name="doc_ballot"),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/doc.json$', views_doc.document_json),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballotpopup/$', views_doc.ballot_for_popup),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.tsv$', views_doc.ballot_tsv),
|
||||
(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json),
|
||||
#(r'^(?P<name>[A-Za-z0-9._+-]+)/ballot.json$', views_doc.ballot_json), # legacy view
|
||||
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/$', views_edit.change_state, name='doc_change_state'), # IESG state
|
||||
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/state/(?P<state_type>iana-action|iana-review)/$', views_edit.change_iana_state, name='doc_change_iana_state'),
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.conf import settings
|
|||
|
||||
from ietf.idtracker.models import InternetDraft, DocumentComment, BallotInfo, IESGLogin
|
||||
from ietf.idrfc.mails import *
|
||||
from ietf.ietfauth.decorators import has_role
|
||||
from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream
|
||||
|
||||
def add_document_comment(request, doc, text, ballot=None):
|
||||
if request:
|
||||
|
@ -177,27 +177,3 @@ def update_telechatREDESIGN(request, doc, by, new_telechat_date, new_returning_i
|
|||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
update_telechat = update_telechatREDESIGN
|
||||
|
||||
def can_edit_base(doc, user):
|
||||
return user.is_authenticated() and (
|
||||
has_role(user, ["Secretariat", "Area Director"]) or
|
||||
doc.group.role_set.filter(name__in=("chair", "auth", "delegate"), person__user=user)
|
||||
)
|
||||
|
||||
can_edit_intended_std_level = can_edit_base
|
||||
can_edit_consensus = can_edit_base
|
||||
can_edit_shepherd = can_edit_base
|
||||
|
||||
def can_edit_shepherd_writeup(doc, user):
|
||||
if user.is_authenticated():
|
||||
if Person.objects.filter(user=user).count():
|
||||
return can_edit_base(doc,user) or (doc.shepherd==user.person)
|
||||
return False
|
||||
|
||||
def nice_consensus(consensus):
|
||||
mapping = {
|
||||
None: "Unknown",
|
||||
True: "Yes",
|
||||
False: "No"
|
||||
}
|
||||
return mapping[consensus]
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ from ietf.ipr.search import iprs_from_docs
|
|||
from ietf.idrfc.mails import *
|
||||
from ietf.idrfc.utils import *
|
||||
from ietf.idrfc.lastcall import request_last_call
|
||||
from ietf.idrfc.idrfc_wrapper import BallotWrapper
|
||||
|
||||
from ietf.doc.utils import *
|
||||
from ietf.doc.models import *
|
||||
|
|
|
@ -1,709 +0,0 @@
|
|||
# Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
# All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
#
|
||||
# * Neither the name of the Nokia Corporation and/or its
|
||||
# subsidiary(-ies) nor the names of its contributors may be used
|
||||
# to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import re, os, datetime
|
||||
|
||||
from django.http import HttpResponse, Http404
|
||||
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
|
||||
from django.utils import simplejson as json
|
||||
from django.utils.decorators import decorator_from_middleware
|
||||
from django.middleware.gzip import GZipMiddleware
|
||||
from django.core.urlresolvers import reverse as urlreverse, NoReverseMatch
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.idtracker.models import InternetDraft, IDInternal, BallotInfo, DocumentComment
|
||||
from ietf.idtracker.templatetags.ietf_filters import format_textarea, fill
|
||||
from ietf.idrfc import markup_txt
|
||||
from ietf.idrfc.utils import *
|
||||
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 *
|
||||
from ietf.doc.utils import *
|
||||
from ietf.utils.history import find_history_active_at
|
||||
from ietf.ietfauth.decorators import has_role
|
||||
from ietf.doc.views_status_change import RELATION_SLUGS as status_change_relationships
|
||||
from ietf.wgcharter.utils import historic_milestones_for_charter
|
||||
|
||||
def render_document_top(request, doc, tab, name):
|
||||
tabs = []
|
||||
tabs.append(("Document", "document", urlreverse("ietf.idrfc.views_doc.document_main", kwargs=dict(name=name)), True))
|
||||
|
||||
ballot = doc.latest_event(BallotDocEvent, type="created_ballot")
|
||||
if doc.type_id in ("draft","conflrev","statchg"):
|
||||
# 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=name)), ballot))
|
||||
elif doc.type_id == "charter":
|
||||
tabs.append(("IESG Review", "ballot", urlreverse("ietf.idrfc.views_doc.document_ballot", kwargs=dict(name=name)), ballot))
|
||||
|
||||
# FIXME: if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot:
|
||||
if doc.type_id not in ("conflrev","statchg"):
|
||||
tabs.append(("IESG Writeups", "writeup", urlreverse("ietf.idrfc.views_doc.document_writeup", kwargs=dict(name=doc.name)), True))
|
||||
|
||||
tabs.append(("History", "history", urlreverse("ietf.idrfc.views_doc.document_history", kwargs=dict(name=doc.name)), True))
|
||||
|
||||
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,
|
||||
name=name))
|
||||
|
||||
|
||||
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")
|
||||
|
||||
orig_doc = doc = get_object_or_404(Document, docalias__name=name)
|
||||
group = doc.group
|
||||
if doc.type_id == 'conflrev':
|
||||
conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document
|
||||
|
||||
revisions = []
|
||||
for h in doc.history_set.order_by("time", "id"):
|
||||
if h.rev and not h.rev in revisions:
|
||||
revisions.append(h.rev)
|
||||
if not doc.rev in revisions:
|
||||
revisions.append(doc.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)
|
||||
|
||||
if doc.type_id == "charter":
|
||||
# find old group, too
|
||||
gh = find_history_active_at(doc.group, doc.time)
|
||||
if gh:
|
||||
group = gh
|
||||
|
||||
top = render_document_top(request, doc, "document", name)
|
||||
|
||||
|
||||
|
||||
telechat = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
|
||||
if telechat and not telechat.telechat_date:
|
||||
telechat = None
|
||||
if telechat and telechat.telechat_date < datetime.date.today():
|
||||
telechat = None
|
||||
|
||||
|
||||
if doc.type_id == "charter":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
|
||||
content = _get_html(filename, os.path.join(settings.CHARTER_PATH, filename), split=False)
|
||||
|
||||
ballot_summary = None
|
||||
if doc.get_state_slug() in ("intrev", "iesgrev"):
|
||||
active_ballot = doc.active_ballot()
|
||||
if active_ballot:
|
||||
ballot_summary = needed_ballot_positions(doc, active_ballot.active_ad_positions().values())
|
||||
else:
|
||||
ballot_summary = "No active ballot found."
|
||||
|
||||
chartering = get_chartering_type(doc)
|
||||
|
||||
# inject milestones from group
|
||||
milestones = historic_milestones_for_charter(orig_doc, doc.rev)
|
||||
|
||||
return render_to_response("idrfc/document_charter.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
chartering=chartering,
|
||||
content=content,
|
||||
txt_url=settings.CHARTER_TXT_URL + filename,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
telechat=telechat,
|
||||
ballot_summary=ballot_summary,
|
||||
group=group,
|
||||
milestones=milestones,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if doc.type_id == "conflrev":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
pathname = os.path.join(settings.CONFLICT_REVIEW_PATH,filename)
|
||||
|
||||
if doc.rev == "00" and not os.path.isfile(pathname):
|
||||
# This could move to a template
|
||||
content = "A conflict review response has not yet been proposed."
|
||||
else:
|
||||
content = _get_html(filename, pathname, split=False)
|
||||
|
||||
ballot_summary = None
|
||||
if doc.get_state_slug() in ("iesgeval"):
|
||||
ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
|
||||
|
||||
return render_to_response("idrfc/document_conflict_review.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
content=content,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
telechat=telechat,
|
||||
conflictdoc=conflictdoc,
|
||||
ballot_summary=ballot_summary,
|
||||
approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent')
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if doc.type_id == "statchg":
|
||||
filename = "%s-%s.txt" % (doc.canonical_name(), doc.rev)
|
||||
pathname = os.path.join(settings.STATUS_CHANGE_PATH,filename)
|
||||
|
||||
if doc.rev == "00" and not os.path.isfile(pathname):
|
||||
# This could move to a template
|
||||
content = "Status change text has not yet been proposed."
|
||||
else:
|
||||
content = _get_html(filename, pathname, split=False)
|
||||
|
||||
ballot_summary = None
|
||||
if doc.get_state_slug() in ("iesgeval"):
|
||||
ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
|
||||
|
||||
if isinstance(doc,Document):
|
||||
sorted_relations=doc.relateddocument_set.all().order_by('relationship__name')
|
||||
elif isinstance(doc,DocHistory):
|
||||
sorted_relations=doc.relateddochistory_set.all().order_by('relationship__name')
|
||||
else:
|
||||
sorted_relations=None
|
||||
|
||||
return render_to_response("idrfc/document_status_change.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
content=content,
|
||||
revisions=revisions,
|
||||
snapshot=snapshot,
|
||||
telechat=telechat,
|
||||
ballot_summary=ballot_summary,
|
||||
approved_states=('appr-pend','appr-sent'),
|
||||
sorted_relations=sorted_relations,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
raise Http404()
|
||||
|
||||
|
||||
def document_history(request, name):
|
||||
# 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", name)
|
||||
|
||||
# pick up revisions from events
|
||||
diff_revisions = []
|
||||
|
||||
diffable = name.startswith("draft") or name.startswith("charter") or name.startswith("conflict-review") or name.startswith("status-change")
|
||||
if diffable:
|
||||
diff_documents = [ doc ]
|
||||
diff_documents.extend(Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces"))
|
||||
|
||||
seen = set()
|
||||
for e in NewRevisionDocEvent.objects.filter(type="new_revision", doc__in=diff_documents).select_related('doc').order_by("-time", "-id"):
|
||||
if (e.doc.name, e.rev) in seen:
|
||||
continue
|
||||
|
||||
seen.add((e.doc.name, e.rev))
|
||||
|
||||
url = ""
|
||||
if name.startswith("charter"):
|
||||
h = find_history_active_at(e.doc, e.time)
|
||||
url = settings.CHARTER_TXT_URL + ("%s-%s.txt" % ((h or doc).canonical_name(), e.rev))
|
||||
elif name.startswith("conflict-review"):
|
||||
h = find_history_active_at(e.doc, e.time)
|
||||
url = settings.CONFLICT_REVIEW_TXT_URL + ("%s-%s.txt" % ((h or doc).canonical_name(), e.rev))
|
||||
elif name.startswith("status-change"):
|
||||
h = find_history_active_at(e.doc, e.time)
|
||||
url = settings.STATUS_CHANGE_TXT_URL + ("%s-%s.txt" % ((h or doc).canonical_name(), e.rev))
|
||||
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")
|
||||
|
||||
augment_events_with_revision(doc, events)
|
||||
|
||||
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):
|
||||
if name.lower().startswith("draft") or name.lower().startswith("rfc"):
|
||||
# todo: migrate idrfc to pattern below
|
||||
return document_main_idrfc(request, name, "writeup")
|
||||
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
top = render_document_top(request, doc, "writeup", name)
|
||||
|
||||
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.announcement_text", kwargs=dict(name=doc.name, 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.announcement_text", kwargs=dict(name=doc.name, ann="action"))))
|
||||
|
||||
if doc.latest_event(BallotDocEvent, type="created_ballot"):
|
||||
e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
|
||||
writeups.append(("Ballot Announcement",
|
||||
e.text if e else "",
|
||||
urlreverse("ietf.wgcharter.views.ballot_writeupnotes", kwargs=dict(name=doc.name))))
|
||||
|
||||
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_shepherd_writeup(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
lastwriteup = doc.latest_event(WriteupDocEvent,type="changed_protocol_writeup")
|
||||
if lastwriteup:
|
||||
writeup_text = lastwriteup.text
|
||||
else:
|
||||
writeup_text = "(There is no shepherd's writeup available for this document)"
|
||||
return render_to_response("idrfc/shepherd_writeup.html",
|
||||
dict(doc=doc,
|
||||
writeup=writeup_text,
|
||||
can_edit=can_edit_shepherd_writeup(doc,request.user)
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def document_ballot_content(request, doc, ballot_id, editable=True):
|
||||
"""Render HTML string with content of ballot page."""
|
||||
all_ballots = list(BallotDocEvent.objects.filter(doc=doc, type="created_ballot").order_by("time"))
|
||||
augment_events_with_revision(doc, all_ballots)
|
||||
|
||||
ballot = None
|
||||
if ballot_id != None:
|
||||
ballot_id = int(ballot_id)
|
||||
for b in all_ballots:
|
||||
if b.id == ballot_id:
|
||||
ballot = b
|
||||
break
|
||||
elif all_ballots:
|
||||
ballot = all_ballots[-1]
|
||||
|
||||
if not ballot:
|
||||
raise Http404
|
||||
|
||||
deferred = doc.active_defer_event()
|
||||
|
||||
positions = ballot.all_positions()
|
||||
|
||||
# put into position groups
|
||||
position_groups = []
|
||||
for n in BallotPositionName.objects.filter(slug__in=[p.pos_id for p in positions]).order_by('order'):
|
||||
g = (n, [p for p in positions if p.pos_id == n.slug])
|
||||
g[1].sort(key=lambda p: (p.old_ad, p.ad.plain_name()))
|
||||
if n.blocking:
|
||||
position_groups.insert(0, g)
|
||||
else:
|
||||
position_groups.append(g)
|
||||
|
||||
summary = needed_ballot_positions(doc, [p for p in positions if not p.old_ad])
|
||||
|
||||
text_positions = [p for p in positions if p.discuss or p.comment]
|
||||
text_positions.sort(key=lambda p: (p.old_ad, p.ad.plain_name()))
|
||||
|
||||
ballot_open = not BallotDocEvent.objects.filter(doc=doc,
|
||||
type__in=("closed_ballot", "created_ballot"),
|
||||
time__gt=ballot.time,
|
||||
ballot_type=ballot.ballot_type)
|
||||
if not ballot_open:
|
||||
editable = False
|
||||
|
||||
return render_to_string("idrfc/document_ballot_content.html",
|
||||
dict(doc=doc,
|
||||
ballot=ballot,
|
||||
position_groups=position_groups,
|
||||
text_positions=text_positions,
|
||||
editable=editable,
|
||||
ballot_open=ballot_open,
|
||||
deferred=deferred,
|
||||
summary=summary,
|
||||
all_ballots=all_ballots,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_ballot(request, name, ballot_id=None):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
top = render_document_top(request, doc, "ballot", name)
|
||||
|
||||
c = document_ballot_content(request, doc, ballot_id, editable=True)
|
||||
|
||||
return render_to_response("idrfc/document_ballot.html",
|
||||
dict(doc=doc,
|
||||
top=top,
|
||||
ballot_content=c,
|
||||
),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_json(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
|
||||
def extract_name(s):
|
||||
return s.name if s else None
|
||||
|
||||
data = {}
|
||||
|
||||
data["name"] = doc.name
|
||||
data["rev"] = doc.rev
|
||||
data["time"] = doc.time.strftime("%Y-%m-%d %H:%M:%S")
|
||||
data["group"] = None
|
||||
if doc.group:
|
||||
data["group"] = dict(
|
||||
name=doc.group.name,
|
||||
type=extract_name(doc.group.type),
|
||||
acronym=doc.group.acronym)
|
||||
data["expires"] = doc.expires.strftime("%Y-%m-%d %H:%M:%S") if doc.expires else None
|
||||
data["title"] = doc.title
|
||||
data["abstract"] = doc.abstract
|
||||
data["aliases"] = list(doc.docalias_set.values_list("name", flat=True))
|
||||
data["state"] = extract_name(doc.get_state())
|
||||
data["intended_std_level"] = extract_name(doc.intended_std_level)
|
||||
data["std_level"] = extract_name(doc.std_level)
|
||||
data["authors"] = [
|
||||
dict(name=e.person.name,
|
||||
email=e.address,
|
||||
affiliation=e.person.affiliation)
|
||||
for e in Email.objects.filter(documentauthor__document=doc).select_related("person").order_by("documentauthor__order")
|
||||
]
|
||||
data["shepherd"] = doc.shepherd.formatted_email() if doc.shepherd else None
|
||||
data["ad"] = doc.ad.role_email("ad").formatted_email() if doc.ad else None
|
||||
|
||||
if doc.type_id == "draft":
|
||||
data["iesg_state"] = extract_name(doc.get_state("draft-iesg"))
|
||||
data["rfceditor_state"] = extract_name(doc.get_state("draft-rfceditor"))
|
||||
data["iana_review_state"] = extract_name(doc.get_state("draft-iana-review"))
|
||||
data["iana_action_state"] = extract_name(doc.get_state("draft-iana-action"))
|
||||
|
||||
if doc.stream_id in ("ietf", "irtf", "iab"):
|
||||
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
data["consensus"] = e.consensus if e else None
|
||||
data["stream"] = extract_name(doc.stream)
|
||||
|
||||
return HttpResponse(json.dumps(data, indent=2), mimetype='text/plain')
|
||||
|
||||
def _get_html(key, filename, split=True):
|
||||
return get_document_content(key, filename, split=split, markup=True)
|
||||
|
||||
def include_text(request):
|
||||
include_text = request.GET.get( 'include_text' )
|
||||
if "full_draft" in request.COOKIES:
|
||||
if request.COOKIES["full_draft"] == "on":
|
||||
include_text = 1
|
||||
return include_text
|
||||
|
||||
def document_main_rfc(request, rfc_number, tab):
|
||||
rfci = get_object_or_404(RfcIndex, rfc_number=rfc_number, states__type="draft", states__slug="rfc")
|
||||
rfci.viewing_as_rfc = True
|
||||
doc = RfcWrapper(rfci)
|
||||
|
||||
info = {}
|
||||
info['is_rfc'] = True
|
||||
info['has_pdf'] = (".pdf" in doc.file_types())
|
||||
info['has_txt'] = (".txt" in doc.file_types())
|
||||
info['has_ps'] = (".ps" in doc.file_types())
|
||||
if info['has_txt']:
|
||||
(content1, content2) = _get_html(
|
||||
"rfc"+str(rfc_number)+",html",
|
||||
os.path.join(settings.RFC_PATH, "rfc"+str(rfc_number)+".txt"))
|
||||
else:
|
||||
content1 = ""
|
||||
content2 = ""
|
||||
|
||||
underlying_document = doc.underlying_document()
|
||||
if underlying_document:
|
||||
info['status_changes'] = ', '.join([ rel.source.canonical_name() for rel in RelatedDocument.objects.filter(relationship__in=status_change_relationships,target__document=underlying_document) if rel.source.get_state_slug() in ('appr-sent','appr-pend')])
|
||||
info['proposed_status_changes'] = ', '.join([ rel.source.canonical_name() for rel in RelatedDocument.objects.filter(relationship__in=status_change_relationships,target__document=underlying_document) if rel.source.get_state_slug() in ('needshep','adrev','iesgeval','defer','appr-pr')])
|
||||
|
||||
history = _get_history(doc, None)
|
||||
|
||||
template = "idrfc/doc_tab_%s" % tab
|
||||
if tab == "document":
|
||||
template += "_rfc"
|
||||
return render_to_response(template + ".html",
|
||||
{'content1':content1, 'content2':content2,
|
||||
'doc':doc, 'info':info, 'tab':tab,
|
||||
'include_text':include_text(request),
|
||||
'history':history},
|
||||
context_instance=RequestContext(request));
|
||||
|
||||
@decorator_from_middleware(GZipMiddleware)
|
||||
def document_main_idrfc(request, name, tab):
|
||||
r = re.compile("^rfc([1-9][0-9]*)$")
|
||||
m = r.match(name)
|
||||
if m:
|
||||
return document_main_rfc(request, int(m.group(1)), tab)
|
||||
id = get_object_or_404(InternetDraft, filename=name)
|
||||
doc = IdWrapper(id)
|
||||
|
||||
info = {}
|
||||
info['has_pdf'] = (".pdf" in doc.file_types())
|
||||
info['is_rfc'] = False
|
||||
|
||||
info['conflict_reviews'] = [ rel.source for alias in id.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]
|
||||
info['rfc_editor_state'] = id.get_state("draft-rfceditor")
|
||||
info['iana_review_state'] = id.get_state("draft-iana-review")
|
||||
info['iana_action_state'] = id.get_state("draft-iana-action")
|
||||
info["consensus"] = None
|
||||
if id.stream_id in ("ietf", "irtf", "iab"):
|
||||
e = id.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
info["consensus"] = nice_consensus(e and e.consensus)
|
||||
info["can_edit_consensus"] = can_edit_consensus(id, request.user)
|
||||
info["can_edit_intended_std_level"] = can_edit_intended_std_level(id, request.user)
|
||||
info["can_edit_shepherd"] = can_edit_shepherd(id, request.user)
|
||||
|
||||
(content1, content2) = _get_html(
|
||||
str(name)+","+str(id.revision)+",html",
|
||||
os.path.join(settings.INTERNET_DRAFT_PATH, name+"-"+id.revision+".txt"))
|
||||
|
||||
versions = _get_versions(id)
|
||||
history = _get_history(doc, versions)
|
||||
|
||||
template = "idrfc/doc_tab_%s" % tab
|
||||
if tab == "document":
|
||||
template += "_id"
|
||||
return render_to_response(template + ".html",
|
||||
{'content1':content1, 'content2':content2,
|
||||
'doc':doc, 'info':info, 'tab':tab,
|
||||
'include_text':include_text(request),
|
||||
'stream_info': get_full_info_for_draft(id),
|
||||
'milestones': id.groupmilestone_set.filter(state="active"),
|
||||
'versions':versions, 'history':history},
|
||||
context_instance=RequestContext(request));
|
||||
|
||||
# doc is either IdWrapper or RfcWrapper
|
||||
def _get_history(doc, versions):
|
||||
results = []
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
versions = [] # clear versions
|
||||
event_holder = doc._draft if hasattr(doc, "_draft") else doc._rfcindex
|
||||
for e in event_holder.docevent_set.all().select_related('by').order_by('-time', 'id'):
|
||||
info = {}
|
||||
if e.type == "new_revision":
|
||||
filename = u"%s-%s" % (e.doc.name, e.newrevisiondocevent.rev)
|
||||
e.desc = 'New version available: <a href="http://tools.ietf.org/id/%s.txt">%s</a>' % (filename, filename)
|
||||
if int(e.newrevisiondocevent.rev) != 0:
|
||||
e.desc += ' (<a href="http:%s?url2=%s">diff from -%02d</a>)' % (settings.RFCDIFF_PREFIX, filename, int(e.newrevisiondocevent.rev) - 1)
|
||||
info["dontmolest"] = True
|
||||
|
||||
multiset_ballot_text = "This was part of a ballot set with: "
|
||||
if e.desc.startswith(multiset_ballot_text):
|
||||
names = [ n.strip() for n in e.desc[len(multiset_ballot_text):].split(",") ]
|
||||
e.desc = multiset_ballot_text + ", ".join(u'<a href="%s">%s</a>' % (urlreverse("doc_view", kwargs={'name': n }), n) for n in names)
|
||||
info["dontmolest"] = True
|
||||
|
||||
info['text'] = e.desc
|
||||
info['by'] = e.by.plain_name()
|
||||
info['textSnippet'] = truncatewords_html(info['text'], 25).replace('<br>',' ')
|
||||
info['snipped'] = info['textSnippet'][-3:] == "..." and e.type != "new_revision"
|
||||
results.append({'comment':e, 'info':info, 'date':e.time, 'is_com':True})
|
||||
|
||||
prev_rev = "00"
|
||||
# actually, we're already sorted and this ruins the sort from
|
||||
# the ids which is sometimes needed, so the function should be
|
||||
# rewritten to not rely on a resort
|
||||
results.sort(key=lambda x: x['date'])
|
||||
for o in results:
|
||||
e = o["comment"]
|
||||
if e.type == "new_revision":
|
||||
e.version = e.newrevisiondocevent.rev
|
||||
else:
|
||||
e.version = prev_rev
|
||||
prev_rev = e.version
|
||||
else:
|
||||
if doc.is_id_wrapper:
|
||||
comments = DocumentComment.objects.filter(document=doc.tracker_id).exclude(rfc_flag=1)
|
||||
else:
|
||||
comments = DocumentComment.objects.filter(document=doc.rfc_number,rfc_flag=1)
|
||||
if len(comments) > 0:
|
||||
# also include rfc_flag=NULL, but only if at least one
|
||||
# comment with rfc_flag=1 exists (usually NULL means same as 0)
|
||||
comments = DocumentComment.objects.filter(document=doc.rfc_number).exclude(rfc_flag=0)
|
||||
for comment in comments.order_by('-date','-time','-id').filter(public_flag=1).select_related('created_by'):
|
||||
info = {}
|
||||
info['text'] = comment.comment_text
|
||||
info['by'] = comment.get_fullname()
|
||||
info['textSnippet'] = truncatewords_html(format_textarea(fill(info['text'], 80)), 25)
|
||||
info['snipped'] = info['textSnippet'][-3:] == "..."
|
||||
results.append({'comment':comment, 'info':info, 'date':comment.datetime(), 'is_com':True})
|
||||
|
||||
if doc.is_id_wrapper and versions:
|
||||
for v in versions:
|
||||
if v['draft_name'] == doc.draft_name:
|
||||
v = dict(v) # copy it, since we're modifying datetimes later
|
||||
v['is_rev'] = True
|
||||
results.insert(0, v)
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES and doc.is_id_wrapper and doc.draft_status == "Expired" and doc._draft.expiration_date:
|
||||
results.append({'is_text':True, 'date':doc._draft.expiration_date, 'text':'Draft expired'})
|
||||
if not settings.USE_DB_REDESIGN_PROXY_CLASSES and doc.is_rfc_wrapper:
|
||||
text = 'RFC Published'
|
||||
if doc.draft_name:
|
||||
try:
|
||||
text = 'RFC Published (see <a href="%s">%s</a> for earlier history)' % (urlreverse('doc_view', args=[doc.draft_name]),doc.draft_name)
|
||||
except NoReverseMatch:
|
||||
pass
|
||||
results.append({'is_text':True, 'date':doc.publication_date, 'text':text})
|
||||
|
||||
# convert plain dates to datetimes (required for sorting)
|
||||
for x in results:
|
||||
if not isinstance(x['date'], datetime.datetime):
|
||||
if x['date']:
|
||||
x['date'] = datetime.datetime.combine(x['date'], datetime.time(0,0,0))
|
||||
else:
|
||||
x['date'] = datetime.datetime(1970,1,1)
|
||||
|
||||
results.sort(key=lambda x: x['date'])
|
||||
results.reverse()
|
||||
return results
|
||||
|
||||
# takes InternetDraft instance
|
||||
def _get_versions(draft, include_replaced=True):
|
||||
ov = []
|
||||
ov.append({"draft_name":draft.filename, "revision":draft.revision_display(), "date":draft.revision_date})
|
||||
if include_replaced:
|
||||
draft_list = [draft]+list(draft.replaces_set.all())
|
||||
else:
|
||||
draft_list = [draft]
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.doc.models import NewRevisionDocEvent
|
||||
for e in NewRevisionDocEvent.objects.filter(type="new_revision", doc__in=draft_list).select_related('doc').order_by("-time", "-id"):
|
||||
if not (e.doc.name == draft.name and e.rev == draft.rev):
|
||||
ov.append(dict(draft_name=e.doc.name, revision=e.rev, date=e.time.date()))
|
||||
|
||||
return ov
|
||||
|
||||
for d in draft_list:
|
||||
for v in DraftVersions.objects.filter(filename=d.filename).order_by('-revision'):
|
||||
if (d.filename == draft.filename) and (draft.revision_display() == v.revision):
|
||||
continue
|
||||
ov.append({"draft_name":d.filename, "revision":v.revision, "date":v.revision_date})
|
||||
return ov
|
||||
|
||||
def get_ballot(name):
|
||||
from ietf.doc.models import DocAlias
|
||||
alias = get_object_or_404(DocAlias, name=name)
|
||||
d = alias.document
|
||||
id = None
|
||||
bw = None
|
||||
dw = None
|
||||
if (d.type_id=='draft'):
|
||||
id = get_object_or_404(InternetDraft, name=d.name)
|
||||
try:
|
||||
if not id.ballot.ballot_issued:
|
||||
raise Http404
|
||||
except BallotInfo.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
bw = BallotWrapper(id) # XXX Fixme: Eliminate this as we go forward
|
||||
# Python caches ~100 regex'es -- explicitly compiling it inside a method
|
||||
# (where you then throw away the compiled version!) doesn't make sense at
|
||||
# all.
|
||||
if re.search("^rfc([1-9][0-9]*)$", name):
|
||||
id.viewing_as_rfc = True
|
||||
dw = RfcWrapper(id)
|
||||
else:
|
||||
dw = IdWrapper(id)
|
||||
# XXX Fixme: Eliminate 'dw' as we go forward
|
||||
|
||||
try:
|
||||
b = d.latest_event(BallotDocEvent, type="created_ballot")
|
||||
except BallotDocEvent.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
return (bw, dw, b, d)
|
||||
|
||||
|
||||
def ballot_for_popup(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
return HttpResponse(document_ballot_content(request, doc, ballot_id=None, editable=False))
|
||||
|
||||
def ballot_html(request, name):
|
||||
bw, dw, ballot, doc = get_ballot(name)
|
||||
content = document_ballot_content(request, doc, ballot.pk, editable=True)
|
||||
return HttpResponse(content)
|
||||
|
||||
def ballot_tsv(request, name):
|
||||
ballot, doc, b, d = get_ballot(name)
|
||||
return HttpResponse(render_to_string('idrfc/ballot.tsv', {'ballot':ballot}, RequestContext(request)), content_type="text/plain")
|
||||
|
||||
def ballot_json(request, name):
|
||||
ballot, doc, b, d = get_ballot(name)
|
||||
response = HttpResponse(mimetype='text/plain')
|
||||
response.write(json.dumps(ballot.dict(), indent=2))
|
||||
return response
|
||||
|
|
@ -13,11 +13,12 @@ from django.utils.html import strip_tags
|
|||
from django.db.models import Max
|
||||
from django.conf import settings
|
||||
from django.forms.util import ErrorList
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from ietf.utils.mail import send_mail_text, send_mail_message
|
||||
from ietf.ietfauth.decorators import group_required
|
||||
from ietf.ietfauth.decorators import group_required, has_role, role_required
|
||||
from ietf.ietfauth.utils import user_is_person
|
||||
from ietf.idtracker.templatetags.ietf_filters import in_group
|
||||
from ietf.ietfauth.decorators import has_role, role_required
|
||||
from ietf.idtracker.models import *
|
||||
from ietf.iesg.models import *
|
||||
from ietf.idrfc.mails import *
|
||||
|
@ -225,14 +226,21 @@ class ChangeStreamForm(forms.Form):
|
|||
stream = forms.ModelChoiceField(StreamName.objects.exclude(slug="legacy"), required=False)
|
||||
comment = forms.CharField(widget=forms.Textarea, required=False)
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
@login_required
|
||||
def change_stream(request, name):
|
||||
"""Change the stream of a Document of type 'draft' , notifying parties as necessary
|
||||
"""Change the stream of a Document of type 'draft', notifying parties as necessary
|
||||
and logging the change as a comment."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
if not doc.type_id=='draft':
|
||||
raise Http404()
|
||||
|
||||
if not (has_role(request.user, ("Area Director", "Secretariat")) or
|
||||
(request.user.is_authenticated() and
|
||||
Role.objects.filter(name="chair",
|
||||
group__acronym__in=StreamName.objects.values_list("slug", flat=True),
|
||||
person__user=request.user))):
|
||||
return HttpResponseForbidden("You do not have permission to view this page")
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
||||
if request.method == 'POST':
|
||||
|
@ -248,7 +256,7 @@ def change_stream(request, name):
|
|||
doc.stream = new_stream
|
||||
|
||||
e = DocEvent(doc=doc,by=login,type='changed_document')
|
||||
e.desc = u"Stream changed to <b>%s</b> from %s"% (new_stream,old_stream)
|
||||
e.desc = u"Stream changed to <b>%s</b> from %s"% (new_stream, old_stream or "None")
|
||||
e.save()
|
||||
|
||||
email_desc = e.desc
|
||||
|
@ -287,7 +295,8 @@ def change_intention(request, name):
|
|||
if doc.type_id != 'draft':
|
||||
raise Http404
|
||||
|
||||
if not can_edit_intended_std_level(doc, request.user):
|
||||
if not (has_role(request.user, ("Secretariat", "Area Director"))
|
||||
or is_authorized_in_doc_stream(request.user, doc)):
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
@ -396,8 +405,7 @@ class EditInfoFormREDESIGN(forms.Form):
|
|||
self.standard_fields = [x for x in self.visible_fields() if x.name not in ('returning_item',)]
|
||||
|
||||
def clean_note(self):
|
||||
# note is stored munged in the database
|
||||
return self.cleaned_data['note'].replace('\n', '<br>').replace('\r', '').replace(' ', ' ')
|
||||
return self.cleaned_data['note'].replace('\r', '').strip()
|
||||
|
||||
|
||||
def get_initial_notify(doc):
|
||||
|
@ -532,7 +540,7 @@ def edit_infoREDESIGN(request, name):
|
|||
area=doc.group_id,
|
||||
ad=doc.ad_id,
|
||||
notify=doc.notify,
|
||||
note=dehtmlify_textarea_text(doc.note),
|
||||
note=doc.note,
|
||||
telechat_date=initial_telechat_date,
|
||||
returning_item=initial_returning_item,
|
||||
)
|
||||
|
@ -827,15 +835,16 @@ class IESGNoteForm(forms.Form):
|
|||
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False)
|
||||
|
||||
def clean_note(self):
|
||||
# note is stored munged in the database
|
||||
return self.cleaned_data['note'].replace('\n', '<br>').replace('\r', '').replace(' ', ' ')
|
||||
# not muning the database content to use html line breaks --
|
||||
# that has caused a lot of pain in the past.
|
||||
return self.cleaned_data['note'].replace('\r', '').strip()
|
||||
|
||||
@group_required("Area Director", "Secretariat")
|
||||
def edit_iesg_note(request, name):
|
||||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
login = request.user.get_profile()
|
||||
|
||||
initial = dict(note=dehtmlify_textarea_text(doc.note))
|
||||
initial = dict(note=doc.note)
|
||||
|
||||
if request.method == "POST":
|
||||
form = IESGNoteForm(request.POST, initial=initial)
|
||||
|
@ -883,7 +892,10 @@ def edit_shepherd_writeup(request, name):
|
|||
"""Change this document's shepherd writeup"""
|
||||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
|
||||
if not can_edit_shepherd_writeup(doc, request.user):
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
can_edit_shepherd_writeup = can_edit_stream_info or user_is_person(request.user, doc.shepherd) or has_role(request.user, ["Area Director"])
|
||||
|
||||
if not can_edit_shepherd_writeup:
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
login = request.user.get_profile()
|
||||
|
@ -950,7 +962,9 @@ def edit_shepherd(request, name):
|
|||
# TODO - this shouldn't be type="draft" specific
|
||||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
|
||||
if not can_edit_shepherd(doc, request.user):
|
||||
can_edit_stream_info = is_authorized_in_doc_stream(request.user, doc)
|
||||
|
||||
if not can_edit_stream_info:
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
if request.method == 'POST':
|
||||
|
@ -1036,7 +1050,8 @@ def edit_consensus(request, name):
|
|||
|
||||
doc = get_object_or_404(Document, type="draft", name=name)
|
||||
|
||||
if not can_edit_consensus(doc, request.user):
|
||||
if not (has_role(request.user, ("Secretariat", "Area Director"))
|
||||
or is_authorized_in_doc_stream(request.user, doc)):
|
||||
return HttpResponseForbidden("You do not have the necessary permissions to view this page")
|
||||
|
||||
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
|
||||
|
|
|
@ -44,6 +44,10 @@ from ietf.idrfc.idrfc_wrapper import IdWrapper,RfcWrapper,IdRfcWrapper
|
|||
from ietf.utils import normalize_draftname
|
||||
from django.conf import settings
|
||||
|
||||
from ietf.doc.models import *
|
||||
from ietf.person.models import *
|
||||
from ietf.group.models import *
|
||||
|
||||
class SearchForm(forms.Form):
|
||||
name = forms.CharField(required=False)
|
||||
rfcs = forms.BooleanField(required=False,initial=True)
|
||||
|
@ -54,15 +58,27 @@ class SearchForm(forms.Form):
|
|||
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)
|
||||
group = forms.CharField(required=False)
|
||||
area = forms.ModelChoiceField(Area.active_areas(), empty_label="any area", required=False)
|
||||
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(IDState.objects.all(), empty_label="any state", required=False)
|
||||
state = forms.ModelChoiceField(State.objects.filter(type="draft-iesg"), empty_label="any state", required=False)
|
||||
subState = forms.ChoiceField(choices=(), required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SearchForm, self).__init__(*args, **kwargs)
|
||||
self.fields['ad'].choices = [('', 'any AD')] + [(ad.id, "%s %s" % (ad.first_name, ad.last_name)) for ad in IESGLogin.objects.filter(user_level=1).order_by('last_name')] + [('-99', '------------------')] + [(ad.id, "%s %s" % (ad.first_name, ad.last_name)) for ad in IESGLogin.objects.filter(user_level=2).order_by('last_name')]
|
||||
self.fields['subState'].choices = [('', 'any substate'), ('0', 'no substate')] + [(state.sub_state_id, state.sub_state) for state in IDSubState.objects.all()]
|
||||
responsible = Document.objects.values_list('ad', flat=True).distinct()
|
||||
active_ads = list(Person.objects.filter(role__name="ad",
|
||||
role__group__type="area",
|
||||
role__group__state="active").distinct())
|
||||
inactive_ads = list(((Person.objects.filter(pk__in=responsible) | Person.objects.filter(role__name="pre-ad",
|
||||
role__group__type="area",
|
||||
role__group__state="active")).distinct())
|
||||
.exclude(pk__in=[x.pk for x in active_ads]))
|
||||
extract_last_name = lambda x: x.name_parts()[3]
|
||||
active_ads.sort(key=extract_last_name)
|
||||
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'))]
|
||||
def clean_name(self):
|
||||
value = self.cleaned_data.get('name','')
|
||||
return normalize_draftname(value)
|
||||
|
@ -73,9 +89,9 @@ class SearchForm(forms.Form):
|
|||
q['by'] = None
|
||||
else:
|
||||
for k in ('author','group','area','ad'):
|
||||
if (q['by'] == k) and not q[k]:
|
||||
if (q['by'] == k) and (k not in q or not q[k]):
|
||||
q['by'] = None
|
||||
if (q['by'] == 'state') and not (q['state'] or q['subState']):
|
||||
if (q['by'] == 'state') and (not 'state' in q or not 'subState' in q or not (q['state'] or q['subState'])):
|
||||
q['by'] = None
|
||||
# Reset other fields
|
||||
for k in ('author','group','area','ad'):
|
||||
|
@ -88,7 +104,7 @@ class SearchForm(forms.Form):
|
|||
q['state'] = ""
|
||||
q['subState'] = ""
|
||||
return q
|
||||
|
||||
|
||||
def search_query(query_original, sort_by=None):
|
||||
query = dict(query_original.items())
|
||||
drafts = query['activeDrafts'] or query['oldDrafts']
|
||||
|
@ -97,6 +113,7 @@ def search_query(query_original, sort_by=None):
|
|||
|
||||
# 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, ''))
|
||||
|
@ -107,388 +124,156 @@ def search_query(query_original, sort_by=None):
|
|||
idresults = []
|
||||
rfcresults = []
|
||||
MAX = 500
|
||||
maxReached = False
|
||||
|
||||
prefix = ""
|
||||
q_objs = []
|
||||
if query['by'] in ('ad','state'):
|
||||
prefix = "draft__"
|
||||
if query['name']:
|
||||
q_objs.append(Q(**{prefix+"filename__icontains":query['name']})|Q(**{prefix+"title__icontains":query['name']}))
|
||||
docs = InternetDraft.objects.all()
|
||||
|
||||
if query['by'] == 'author':
|
||||
q_objs.append(Q(**{prefix+"authors__person__last_name__icontains":query['author']}))
|
||||
elif query['by'] == 'group':
|
||||
q_objs.append(Q(**{prefix+"group__acronym":query['group']}))
|
||||
elif query['by'] == 'area':
|
||||
q_objs.append(Q(**{prefix+"group__ietfwg__areagroup__area":query['area']}))
|
||||
elif query['by'] == 'ad':
|
||||
q_objs.append(Q(job_owner=query['ad']))
|
||||
elif query['by'] == 'state':
|
||||
if query['state']:
|
||||
q_objs.append(Q(cur_state=query['state']))
|
||||
if query['subState']:
|
||||
q_objs.append(Q(cur_sub_state=query['subState']))
|
||||
if (not query['rfcs']) and query['activeDrafts'] and (not query['oldDrafts']):
|
||||
q_objs.append(Q(**{prefix+"status":1}))
|
||||
elif query['rfcs'] and query['activeDrafts'] and (not query['oldDrafts']):
|
||||
q_objs.append(Q(**{prefix+"status":1})|Q(**{prefix+"status":3}))
|
||||
elif query['rfcs'] and (not drafts):
|
||||
q_objs.append(Q(**{prefix+"status":3}))
|
||||
if prefix:
|
||||
q_objs.append(Q(rfc_flag=0))
|
||||
matches = IDInternal.objects.filter(*q_objs)
|
||||
else:
|
||||
matches = InternetDraft.objects.filter(*q_objs)
|
||||
if not query['activeDrafts']:
|
||||
matches = matches.exclude(Q(**{prefix+"status":1}))
|
||||
if not query['rfcs']:
|
||||
matches = matches.exclude(Q(**{prefix+"status":3}))
|
||||
if prefix:
|
||||
matches = [id.draft for id in matches[:MAX]]
|
||||
else:
|
||||
matches = matches[:MAX]
|
||||
if len(matches) == MAX:
|
||||
maxReached = True
|
||||
for id in matches:
|
||||
if id.status.status == 'RFC':
|
||||
rfcresults.append([id.rfc_number, id, None, None])
|
||||
# name
|
||||
if query["name"]:
|
||||
docs = docs.filter(Q(docalias__name__icontains=query["name"]) |
|
||||
Q(title__icontains=query["name"])).distinct()
|
||||
|
||||
# rfc/active/old check buttons
|
||||
allowed_states = []
|
||||
if query["rfcs"]:
|
||||
allowed_states.append("rfc")
|
||||
if query["activeDrafts"]:
|
||||
allowed_states.append("active")
|
||||
if query["oldDrafts"]:
|
||||
allowed_states.extend(['repl', 'expired', 'auth-rm', 'ietf-rm'])
|
||||
|
||||
docs = docs.filter(states__type="draft", states__slug__in=allowed_states)
|
||||
|
||||
# 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"])
|
||||
elif by == "area":
|
||||
docs = docs.filter(Q(group__type="wg", group__parent=query["area"]) |
|
||||
Q(group=query["area"])).distinct()
|
||||
elif by == "ad":
|
||||
docs = docs.filter(ad=query["ad"])
|
||||
elif by == "state":
|
||||
if query["state"]:
|
||||
docs = docs.filter(states=query["state"])
|
||||
if query["subState"]:
|
||||
docs = docs.filter(tags=query["subState"])
|
||||
|
||||
# evaluate and fill in values with aggregate queries to avoid
|
||||
# too many individual 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:
|
||||
idresults.append([id])
|
||||
r.canonical_name = (lambda x: lambda: x)(r.name)
|
||||
|
||||
# Next, search RFCs
|
||||
if query['rfcs']:
|
||||
q_objs = []
|
||||
searchRfcIndex = True
|
||||
if query['name']:
|
||||
r = re.compile("^\s*(?:RFC)?\s*(\d+)\s*$", re.IGNORECASE)
|
||||
m = r.match(query['name'])
|
||||
if m:
|
||||
q_objs.append(Q(rfc_number__contains=m.group(1))|Q(title__icontains=query['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:]))
|
||||
|
||||
|
||||
# sort
|
||||
def sort_key(d):
|
||||
res = []
|
||||
|
||||
canonical = d.canonical_name()
|
||||
if canonical.startswith('rfc'):
|
||||
rfc_num = int(canonical[3:])
|
||||
else:
|
||||
rfc_num = None
|
||||
|
||||
if rfc_num != None:
|
||||
res.append(2)
|
||||
elif d.get_state_slug() == "active":
|
||||
res.append(1)
|
||||
else:
|
||||
res.append(3)
|
||||
|
||||
if sort_by == "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":
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
else:
|
||||
q_objs.append(Q(title__icontains=query['name']))
|
||||
if query['by'] == 'author':
|
||||
q_objs.append(Q(authors__icontains=query['author']))
|
||||
elif query['by'] == 'group':
|
||||
# We prefer searching RfcIndex, but it doesn't have group info
|
||||
searchRfcIndex = False
|
||||
q_objs.append(Q(group_acronym=query['group']))
|
||||
elif query['by'] == 'area':
|
||||
# Ditto for area
|
||||
searchRfcIndex = False
|
||||
q_objs.append(Q(area_acronym=query['area']))
|
||||
elif query['by'] == 'ad':
|
||||
numbers = IDInternal.objects.filter(rfc_flag=1,job_owner=query['ad']).values_list('draft_id',flat=True)
|
||||
q_objs.append(Q(rfc_number__in=numbers))
|
||||
elif query['by'] == 'state':
|
||||
numbers_q = [Q(rfc_flag=1)]
|
||||
if query['state']:
|
||||
numbers_q.append(Q(cur_state=query['state']))
|
||||
if query['subState']:
|
||||
numbers_q.append(Q(cur_state=query['subState']))
|
||||
numbers = IDInternal.objects.filter(*numbers_q).values_list('draft_id',flat=True)
|
||||
q_objs.append(Q(rfc_number__in=numbers))
|
||||
|
||||
if searchRfcIndex:
|
||||
matches = RfcIndex.objects.filter(*q_objs)[:MAX]
|
||||
else:
|
||||
matches = Rfc.objects.filter(*q_objs)[:MAX]
|
||||
if len(matches) == MAX:
|
||||
maxReached = True
|
||||
for rfc in matches:
|
||||
found = False
|
||||
for r2 in rfcresults:
|
||||
if r2[0] == rfc.rfc_number:
|
||||
if searchRfcIndex:
|
||||
r2[3] = rfc
|
||||
else:
|
||||
r2[2] = rfc
|
||||
found = True
|
||||
if not found:
|
||||
if searchRfcIndex:
|
||||
rfcresults.append([rfc.rfc_number, None, None, rfc])
|
||||
res.append(d.get_state().order)
|
||||
elif sort_by == "ipr":
|
||||
res.append(d.name)
|
||||
elif sort_by == "ad":
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
elif d.get_state_slug() == "active":
|
||||
if d.get_state("draft-iesg"):
|
||||
res.append(d.get_state("draft-iesg").order)
|
||||
else:
|
||||
rfcresults.append([rfc.rfc_number, None, rfc, None])
|
||||
|
||||
# Find missing InternetDraft objects
|
||||
for r in rfcresults:
|
||||
if not r[1]:
|
||||
ids = InternetDraft.objects.filter(rfc_number=r[0])
|
||||
if len(ids) >= 1:
|
||||
r[1] = ids[0]
|
||||
if not r[1] and r[3] and r[3].draft:
|
||||
ids = InternetDraft.objects.filter(filename=r[3].draft)
|
||||
if len(ids) >= 1:
|
||||
r[1] = ids[0]
|
||||
|
||||
# Finally, find missing RFC objects
|
||||
for r in rfcresults:
|
||||
if not r[2]:
|
||||
rfcs = Rfc.objects.filter(rfc_number=r[0])
|
||||
if len(rfcs) >= 1:
|
||||
r[2] = rfcs[0]
|
||||
if not r[3]:
|
||||
rfcs = RfcIndex.objects.filter(rfc_number=r[0])
|
||||
if len(rfcs) >= 1:
|
||||
r[3] = rfcs[0]
|
||||
|
||||
# TODO: require that RfcIndex is present?
|
||||
|
||||
results = []
|
||||
for res in idresults+rfcresults:
|
||||
if len(res)==1:
|
||||
doc = IdRfcWrapper(IdWrapper(res[0]), None)
|
||||
results.append(doc)
|
||||
res.append(0)
|
||||
else:
|
||||
d = None
|
||||
r = None
|
||||
if res[1]:
|
||||
d = IdWrapper(res[1])
|
||||
if res[3]:
|
||||
r = RfcWrapper(res[3])
|
||||
if d or r:
|
||||
doc = IdRfcWrapper(d, r)
|
||||
results.append(doc)
|
||||
results.sort(key=lambda obj: obj.view_sort_key(sort_by))
|
||||
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
else:
|
||||
res.append(canonical)
|
||||
|
||||
return res
|
||||
|
||||
results.sort(key=sort_key)
|
||||
|
||||
meta = {}
|
||||
if maxReached:
|
||||
if len(docs) == MAX:
|
||||
meta['max'] = MAX
|
||||
if query['by']:
|
||||
meta['advanced'] = True
|
||||
return (results,meta)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
from ietf.doc.models import *
|
||||
from ietf.person.models import *
|
||||
from ietf.group.models import *
|
||||
# finally wrap in old wrappers
|
||||
|
||||
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)
|
||||
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))
|
||||
|
||||
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)
|
||||
group = forms.CharField(required=False)
|
||||
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(used=True, type="draft-iesg"), empty_label="any state", required=False)
|
||||
subState = forms.ChoiceField(choices=(), required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SearchForm, self).__init__(*args, **kwargs)
|
||||
responsible = Document.objects.values_list('ad', flat=True).distinct()
|
||||
active_ads = list(Person.objects.filter(role__name="ad",
|
||||
role__group__type="area",
|
||||
role__group__state="active").distinct())
|
||||
inactive_ads = list(((Person.objects.filter(pk__in=responsible) | Person.objects.filter(role__name="pre-ad",
|
||||
role__group__type="area",
|
||||
role__group__state="active")).distinct())
|
||||
.exclude(pk__in=[x.pk for x in active_ads]))
|
||||
extract_last_name = lambda x: x.name_parts()[3]
|
||||
active_ads.sort(key=extract_last_name)
|
||||
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'))]
|
||||
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]):
|
||||
q['by'] = None
|
||||
if (q['by'] == 'state') and (not 'state' in q or not 'subState' in q or not (q['state'] or q['subState'])):
|
||||
q['by'] = None
|
||||
# Reset other fields
|
||||
for k in ('author','group','area','ad'):
|
||||
if q['by'] != k:
|
||||
self.data[k] = ""
|
||||
q[k] = ""
|
||||
if q['by'] != 'state':
|
||||
self.data['state'] = ""
|
||||
self.data['subState'] = ""
|
||||
q['state'] = ""
|
||||
q['subState'] = ""
|
||||
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']):
|
||||
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()
|
||||
|
||||
# name
|
||||
if query["name"]:
|
||||
docs = docs.filter(Q(docalias__name__icontains=query["name"]) |
|
||||
Q(title__icontains=query["name"])).distinct()
|
||||
|
||||
# rfc/active/old check buttons
|
||||
allowed_states = []
|
||||
if query["rfcs"]:
|
||||
allowed_states.append("rfc")
|
||||
if query["activeDrafts"]:
|
||||
allowed_states.append("active")
|
||||
if query["oldDrafts"]:
|
||||
allowed_states.extend(['repl', 'expired', 'auth-rm', 'ietf-rm'])
|
||||
|
||||
docs = docs.filter(states__type="draft", states__slug__in=allowed_states)
|
||||
|
||||
# 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"])
|
||||
elif by == "area":
|
||||
docs = docs.filter(Q(group__type="wg", group__parent=query["area"]) |
|
||||
Q(group=query["area"])).distinct()
|
||||
elif by == "ad":
|
||||
docs = docs.filter(ad=query["ad"])
|
||||
elif by == "state":
|
||||
if query["state"]:
|
||||
docs = docs.filter(states=query["state"])
|
||||
if query["subState"]:
|
||||
docs = docs.filter(tags=query["subState"])
|
||||
|
||||
# evaluate and fill in values with aggregate queries to avoid
|
||||
# too many individual 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:]))
|
||||
|
||||
|
||||
# sort
|
||||
def sort_key(d):
|
||||
res = []
|
||||
|
||||
canonical = d.canonical_name()
|
||||
if canonical.startswith('rfc'):
|
||||
rfc_num = int(canonical[3:])
|
||||
else:
|
||||
rfc_num = None
|
||||
|
||||
if rfc_num != None:
|
||||
res.append(2)
|
||||
elif d.get_state_slug() == "active":
|
||||
res.append(1)
|
||||
else:
|
||||
res.append(3)
|
||||
|
||||
if sort_by == "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":
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
else:
|
||||
res.append(d.get_state().order)
|
||||
elif sort_by == "ipr":
|
||||
res.append(d.name)
|
||||
elif sort_by == "ad":
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
elif d.get_state_slug() == "active":
|
||||
if d.get_state("draft-iesg"):
|
||||
res.append(d.get_state("draft-iesg").order)
|
||||
else:
|
||||
res.append(0)
|
||||
else:
|
||||
if rfc_num != None:
|
||||
res.append(rfc_num)
|
||||
else:
|
||||
res.append(canonical)
|
||||
|
||||
return res
|
||||
|
||||
results.sort(key=sort_key)
|
||||
|
||||
meta = {}
|
||||
if len(docs) == MAX:
|
||||
meta['max'] = MAX
|
||||
if query['by']:
|
||||
meta['advanced'] = True
|
||||
|
||||
# finally wrap in old wrappers
|
||||
|
||||
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))
|
||||
|
||||
return (wrapped_results, meta)
|
||||
return (wrapped_results, meta)
|
||||
|
||||
|
||||
def generate_query_string(request, ignore_list):
|
||||
|
|
|
@ -4,7 +4,8 @@ import textwrap
|
|||
from django import template
|
||||
from django.conf import settings
|
||||
from django.utils.html import escape, fix_ampersands
|
||||
from django.template.defaultfilters import linebreaksbr, wordwrap, stringfilter, urlize, truncatewords_html
|
||||
from django.utils.text import truncate_html_words
|
||||
from django.template.defaultfilters import linebreaksbr, wordwrap, stringfilter, urlize
|
||||
from django.template import resolve_variable
|
||||
from django.utils.safestring import mark_safe, SafeData
|
||||
from django.utils import simplejson
|
||||
|
@ -221,9 +222,9 @@ def urlize_ietf_docs(string, autoescape=None):
|
|||
if autoescape and not isinstance(string, SafeData):
|
||||
string = escape(string)
|
||||
string = re.sub("(?<!>)(RFC ?)0{0,3}(\d+)", "<a href=\"/doc/rfc\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(BCP ?)0{0,3}(\d+)", "<a href=\"http://tools.ietf.org/html/bcp\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(STD ?)0{0,3}(\d+)", "<a href=\"http://tools.ietf.org/html/std\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(FYI ?)0{0,3}(\d+)", "<a href=\"http://tools.ietf.org/html/fyi\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(BCP ?)0{0,3}(\d+)", "<a href=\"/doc/bcp\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(STD ?)0{0,3}(\d+)", "<a href=\"/doc/std\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(FYI ?)0{0,3}(\d+)", "<a href=\"/doc/fyi\\2/\">\\1\\2</a>", string)
|
||||
string = re.sub("(?<!>)(draft-[-0-9a-zA-Z._+]+)", "<a href=\"/doc/\\1/\">\\1</a>", string)
|
||||
string = re.sub("(?<!>)(conflict-review-[-0-9a-zA-Z._+]+)", "<a href=\"/doc/\\1/\">\\1</a>", string)
|
||||
string = re.sub("(?<!>)(status-change-[-0-9a-zA-Z._+]+)", "<a href=\"/doc/\\1/\">\\1</a>", string)
|
||||
|
@ -461,9 +462,14 @@ def ad_area(user):
|
|||
@register.filter
|
||||
def format_history_text(text):
|
||||
"""Run history text through some cleaning and add ellipsis if it's too long."""
|
||||
full = mark_safe(sanitize_html(keep_spacing(linebreaksbr(urlize(mark_safe(text))))))
|
||||
snippet = truncatewords_html(format_textarea(text), 25)
|
||||
if snippet[-3:] == "...":
|
||||
full = mark_safe(text)
|
||||
|
||||
if text.startswith("This was part of a ballot set with:"):
|
||||
full = urlize_ietf_docs(full)
|
||||
|
||||
full = mark_safe(keep_spacing(linebreaksbr(urlize(sanitize_html(full)))))
|
||||
snippet = truncate_html_words(full, 25)
|
||||
if snippet != full:
|
||||
return mark_safe(u'<div class="snippet">%s<span class="showAll">[show all]</span></div><div style="display:none" class="full">%s</div>' % (snippet, full))
|
||||
return full
|
||||
|
||||
|
|
|
@ -246,9 +246,6 @@ def agenda_docs(date, next_agenda):
|
|||
section_key = "s"+get_doc_section(id)
|
||||
if section_key not in res:
|
||||
res[section_key] = []
|
||||
if id.note:
|
||||
# TODO: Find out why this is _here_
|
||||
id.note = id.note.replace(u"\240",u" ")
|
||||
res[section_key].append({'obj':id})
|
||||
return res
|
||||
|
||||
|
|
|
@ -30,87 +30,6 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from django.utils.http import urlquote
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
|
||||
def passes_test_decorator(test_func, message):
|
||||
"""
|
||||
Decorator creator that creates a decorator for checking that user
|
||||
passes the test, redirecting to login or returning a 403
|
||||
error. The test function should be on the form fn(user) ->
|
||||
true/false.
|
||||
"""
|
||||
def decorate(view_func):
|
||||
def inner(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated():
|
||||
return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL, REDIRECT_FIELD_NAME, urlquote(request.get_full_path())))
|
||||
elif test_func(request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
else:
|
||||
return HttpResponseForbidden(message)
|
||||
return inner
|
||||
return decorate
|
||||
|
||||
def group_required(*group_names):
|
||||
"""Decorator for views that checks that the user is logged in,
|
||||
and belongs to (at least) one of the listed groups."""
|
||||
return passes_test_decorator(lambda u: u.groups.filter(name__in=group_names),
|
||||
"Restricted to group%s %s" % ("s" if len(group_names) != 1 else "", ",".join(group_names)))
|
||||
|
||||
|
||||
def has_role(user, role_names):
|
||||
"""Determines whether user has any of the given standard roles
|
||||
given. Role names must be a list or, in case of a single value, a
|
||||
string."""
|
||||
if isinstance(role_names, str) or isinstance(role_names, unicode):
|
||||
role_names = [ role_names ]
|
||||
|
||||
if not user or not user.is_authenticated():
|
||||
return False
|
||||
|
||||
if not hasattr(user, "roles_check_cache"):
|
||||
user.roles_check_cache = {}
|
||||
|
||||
key = frozenset(role_names)
|
||||
if key not in user.roles_check_cache:
|
||||
|
||||
from ietf.person.models import Person
|
||||
from ietf.group.models import Role
|
||||
|
||||
try:
|
||||
person = user.get_profile()
|
||||
except Person.DoesNotExist:
|
||||
return False
|
||||
|
||||
role_qs = {
|
||||
"Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"),
|
||||
"Secretariat": Q(person=person, name="secr", group__acronym="secretariat"),
|
||||
"IANA": Q(person=person, name="auth", group__acronym="iana"),
|
||||
"RFC Editor": Q(person=person, name="auth", group__acronym="rfceditor"),
|
||||
"IAD": Q(person=person, name="admdir", group__acronym="ietf"),
|
||||
"IETF Chair": Q(person=person, name="chair", group__acronym="ietf"),
|
||||
"IAB Chair": Q(person=person, name="chair", group__acronym="iab"),
|
||||
"WG Chair": Q(person=person,name="chair", group__type="wg", group__state="active"),
|
||||
"WG Secretary": Q(person=person,name="secr", group__type="wg", group__state="active"),
|
||||
}
|
||||
|
||||
filter_expr = Q()
|
||||
for r in role_names:
|
||||
filter_expr |= role_qs[r]
|
||||
|
||||
user.roles_check_cache[key] = bool(Role.objects.filter(filter_expr)[:1])
|
||||
|
||||
return user.roles_check_cache[key]
|
||||
|
||||
def role_required(*role_names):
|
||||
"""View decorator for checking that the user is logged in and
|
||||
has one of the listed roles."""
|
||||
return passes_test_decorator(lambda u: has_role(u, role_names),
|
||||
"Restricted to role%s %s" % ("s" if len(role_names) != 1 else "", ", ".join(role_names)))
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
# overwrite group_required
|
||||
group_required = lambda *group_names: role_required(*[n.replace("Area_Director", "Area Director") for n in group_names])
|
||||
# REDESIGN: backwards compatibility, to be deleted
|
||||
from ietf.ietfauth.utils import role_required, has_role, passes_test_decorator
|
||||
group_required = lambda *group_names: role_required(*[n.replace("Area_Director", "Area Director") for n in group_names])
|
||||
|
|
116
ietf/ietfauth/utils.py
Normal file
116
ietf/ietfauth/utils.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
# various authentication and authorization utilities
|
||||
|
||||
from django.utils.http import urlquote
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponseRedirect, HttpResponseForbidden
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
|
||||
from ietf.doc.models import Document
|
||||
from ietf.person.models import Person
|
||||
from ietf.group.models import Role
|
||||
|
||||
def user_is_person(user, person):
|
||||
"""Test whether user is associated with person."""
|
||||
if not user.is_authenticated() or not person:
|
||||
return False
|
||||
|
||||
if person.user_id == None:
|
||||
return False
|
||||
|
||||
return person.user_id == user.id
|
||||
|
||||
def has_role(user, role_names):
|
||||
"""Determines whether user has any of the given standard roles
|
||||
given. Role names must be a list or, in case of a single value, a
|
||||
string."""
|
||||
if isinstance(role_names, str) or isinstance(role_names, unicode):
|
||||
role_names = [ role_names ]
|
||||
|
||||
if not user or not user.is_authenticated():
|
||||
return False
|
||||
|
||||
# use cache to avoid checking the same permissions again and again
|
||||
if not hasattr(user, "roles_check_cache"):
|
||||
user.roles_check_cache = {}
|
||||
|
||||
key = frozenset(role_names)
|
||||
if key not in user.roles_check_cache:
|
||||
try:
|
||||
person = user.get_profile()
|
||||
except Person.DoesNotExist:
|
||||
return False
|
||||
|
||||
role_qs = {
|
||||
"Area Director": Q(person=person, name__in=("pre-ad", "ad"), group__type="area", group__state="active"),
|
||||
"Secretariat": Q(person=person, name="secr", group__acronym="secretariat"),
|
||||
"IANA": Q(person=person, name="auth", group__acronym="iana"),
|
||||
"RFC Editor": Q(person=person, name="auth", group__acronym="rfceditor"),
|
||||
"IAD": Q(person=person, name="admdir", group__acronym="ietf"),
|
||||
"IETF Chair": Q(person=person, name="chair", group__acronym="ietf"),
|
||||
"IAB Chair": Q(person=person, name="chair", group__acronym="iab"),
|
||||
"WG Chair": Q(person=person,name="chair", group__type="wg", group__state="active"),
|
||||
"WG Secretary": Q(person=person,name="secr", group__type="wg", group__state="active"),
|
||||
}
|
||||
|
||||
filter_expr = Q()
|
||||
for r in role_names:
|
||||
filter_expr |= role_qs[r]
|
||||
|
||||
user.roles_check_cache[key] = bool(Role.objects.filter(filter_expr)[:1])
|
||||
|
||||
return user.roles_check_cache[key]
|
||||
|
||||
|
||||
# convenient decorator
|
||||
|
||||
def passes_test_decorator(test_func, message):
|
||||
"""Decorator creator that creates a decorator for checking that
|
||||
user passes the test, redirecting to login or returning a 403
|
||||
error. The test function should be on the form fn(user) ->
|
||||
true/false."""
|
||||
def decorate(view_func):
|
||||
def inner(request, *args, **kwargs):
|
||||
if not request.user.is_authenticated():
|
||||
return HttpResponseRedirect('%s?%s=%s' % (settings.LOGIN_URL, REDIRECT_FIELD_NAME, urlquote(request.get_full_path())))
|
||||
elif test_func(request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
else:
|
||||
return HttpResponseForbidden(message)
|
||||
return inner
|
||||
return decorate
|
||||
|
||||
def role_required(*role_names):
|
||||
"""View decorator for checking that the user is logged in and
|
||||
has one of the listed roles."""
|
||||
return passes_test_decorator(lambda u: has_role(u, role_names),
|
||||
"Restricted to role%s %s" % ("s" if len(role_names) != 1 else "", ", ".join(role_names)))
|
||||
|
||||
# specific permissions
|
||||
|
||||
def is_authorized_in_doc_stream(user, doc):
|
||||
"""Return whether user is authorized to perform stream duties on
|
||||
document."""
|
||||
if has_role(user, ["Secretariat"]):
|
||||
return True
|
||||
|
||||
if not doc.stream or not user.is_authenticated():
|
||||
return False
|
||||
|
||||
# must be authorized in the stream or group
|
||||
|
||||
group_req = None
|
||||
|
||||
if doc.stream.slug == "ietf":
|
||||
if not doc.group.type == "individ":
|
||||
group_req = Q(group=doc.group)
|
||||
elif doc.stream.slug == "irtf":
|
||||
group_req = Q(group__acronym=doc.stream.slug) | Q(group=doc.group)
|
||||
elif doc.stream.slug in ("iab", "ise"):
|
||||
group_req = Q(group__acronym=doc.stream.slug)
|
||||
|
||||
if not group_req:
|
||||
return False
|
||||
|
||||
return bool(Role.objects.filter(Q(name__in=("chair", "delegate", "auth"), person__user=user) & group_req))
|
||||
|
|
@ -6,6 +6,7 @@ from django.views.generic.simple import redirect_to
|
|||
urlpatterns = patterns('ietf.ietfworkflows.views',
|
||||
url(r'^(?P<name>[^/]+)/history/$', 'stream_history', name='stream_history'),
|
||||
url(r'^(?P<name>[^/]+)/edit/adopt/$', 'edit_adopt', name='edit_adopt'),
|
||||
# FIXME: the name edit_state is far too generic
|
||||
url(r'^(?P<name>[^/]+)/edit/state/$', 'edit_state', name='edit_state'),
|
||||
url(r'^(?P<name>[^/]+)/edit/stream/$', redirect_to, { 'url': '/doc/%(name)s/edit/info/'}) ,
|
||||
url(r'^delegates/(?P<stream_name>[^/]+)/$', 'stream_delegates', name='stream_delegates'),
|
||||
|
|
|
@ -111,4 +111,7 @@ class Email(models.Model):
|
|||
return u'"%s" <%s>' % (self.person.ascii, self.address)
|
||||
else:
|
||||
return self.address
|
||||
|
||||
|
||||
def invalid_address(self):
|
||||
# we have some legacy authors with unknown email addresses
|
||||
return self.address.startswith("unknown-email") and "@" not in self.address
|
||||
|
|
|
@ -148,7 +148,7 @@ def perform_postREDESIGN(request, submission):
|
|||
e = NewRevisionDocEvent(type="new_revision", doc=draft, rev=draft.rev)
|
||||
e.time = draft.time #submission.submission_date
|
||||
e.by = submitter
|
||||
e.desc = "New revision available"
|
||||
e.desc = "New version available: <b>%s-%s.txt</b>" % (draft.name, draft.rev)
|
||||
e.save()
|
||||
|
||||
if draft.stream_id == "ietf" and draft.group.type_id == "wg" and draft.rev == "00":
|
||||
|
|
|
@ -195,11 +195,21 @@ def fetch_index_xml(url):
|
|||
return urllib2.urlopen(url)
|
||||
|
||||
def parse_index(response):
|
||||
def getDocList(parentNode, tagName):
|
||||
def normalize_std_name(std_name):
|
||||
# remove zero padding
|
||||
prefix = std_name[:3]
|
||||
if prefix in ("RFC", "FYI", "BCP", "STD"):
|
||||
try:
|
||||
return prefix + str(int(std_name[3:]))
|
||||
except ValueError:
|
||||
pass
|
||||
return std_name
|
||||
|
||||
def extract_doc_list(parentNode, tagName):
|
||||
l = []
|
||||
for u in parentNode.getElementsByTagName(tagName):
|
||||
for d in u.getElementsByTagName("doc-id"):
|
||||
l.append(d.firstChild.data)
|
||||
l.append(normalize_std_name(d.firstChild.data))
|
||||
return l
|
||||
|
||||
also_list = {}
|
||||
|
@ -209,8 +219,8 @@ def parse_index(response):
|
|||
if event == pulldom.START_ELEMENT and node.tagName in ["bcp-entry", "fyi-entry", "std-entry"]:
|
||||
events.expandNode(node)
|
||||
node.normalize()
|
||||
bcpid = get_child_text(node, "doc-id")
|
||||
doclist = getDocList(node, "is-also")
|
||||
bcpid = normalize_std_name(get_child_text(node, "doc-id"))
|
||||
doclist = extract_doc_list(node, "is-also")
|
||||
for docid in doclist:
|
||||
if docid in also_list:
|
||||
also_list[docid].append(bcpid)
|
||||
|
@ -235,10 +245,10 @@ def parse_index(response):
|
|||
|
||||
current_status = get_child_text(node, "current-status").title()
|
||||
|
||||
updates = getDocList(node, "updates")
|
||||
updated_by = getDocList(node, "updated-by")
|
||||
obsoletes = getDocList(node, "obsoletes")
|
||||
obsoleted_by = getDocList(node, "obsoleted-by")
|
||||
updates = extract_doc_list(node, "updates")
|
||||
updated_by = extract_doc_list(node, "updated-by")
|
||||
obsoletes = extract_doc_list(node, "obsoletes")
|
||||
obsoleted_by = extract_doc_list(node, "obsoleted-by")
|
||||
stream = get_child_text(node, "stream")
|
||||
wg = get_child_text(node, "wg_acronym")
|
||||
if wg and ((wg == "NON WORKING GROUP") or len(wg) > 15):
|
||||
|
@ -329,7 +339,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
|
|||
|
||||
if not doc:
|
||||
results.append("created document %s" % name)
|
||||
doc = Document.objects.get_or_create(name=name)[0]
|
||||
doc = Document.objects.create(name=name, type=DocTypeName.objects.get(slug="draft"))
|
||||
|
||||
# add alias
|
||||
DocAlias.objects.get_or_create(name=name, document=doc)
|
||||
|
@ -360,8 +370,11 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None):
|
|||
if doc.stream != stream_mapping[stream]:
|
||||
changed_attributes["stream"] = stream_mapping[stream]
|
||||
|
||||
if not doc.group and wg:
|
||||
changed_attributes["group"] = Group.objects.get(acronym=wg)
|
||||
if not doc.group: # if we have no group assigned, check if RFC Editor has a suggestion
|
||||
if wg:
|
||||
changed_attributes["group"] = Group.objects.get(acronym=wg)
|
||||
else:
|
||||
changed_attributes["group"] = Group.objects.get(type="individ")
|
||||
|
||||
if not doc.latest_event(type="published_rfc"):
|
||||
e = DocEvent(doc=doc, type="published_rfc")
|
||||
|
|
|
@ -269,7 +269,7 @@ class RFCSyncTestCase(django.test.TestCase):
|
|||
self.assertEqual(rfc_published_date.month, today.month)
|
||||
self.assertEqual(current_status, "Proposed Standard")
|
||||
self.assertEqual(updates, ["RFC123"])
|
||||
self.assertEqual(set(also), set(["BCP0001", "FYI0001", "STD0001"]))
|
||||
self.assertEqual(set(also), set(["BCP1", "FYI1", "STD1"]))
|
||||
self.assertEqual(draft, doc.name)
|
||||
self.assertEqual(wg, doc.group.acronym)
|
||||
self.assertEqual(has_errata, True)
|
||||
|
@ -288,9 +288,9 @@ class RFCSyncTestCase(django.test.TestCase):
|
|||
self.assertEqual(doc.docevent_set.all()[0].time.date(), today)
|
||||
self.assertTrue("errata" in doc.tags.all().values_list("slug", flat=True))
|
||||
self.assertTrue(DocAlias.objects.filter(name="rfc1234", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="bcp0001", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="fyi0001", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="std0001", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="bcp1", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="fyi1", document=doc))
|
||||
self.assertTrue(DocAlias.objects.filter(name="std1", document=doc))
|
||||
self.assertTrue(RelatedDocument.objects.filter(source=doc, target__name="rfc123", relationship="updates"))
|
||||
self.assertEqual(doc.title, "A Testing RFC")
|
||||
self.assertEqual(doc.abstract, "This is some interesting text.")
|
||||
|
@ -443,6 +443,7 @@ class RFCEditorUndoTestCase(django.test.TestCase):
|
|||
self.assertEquals(DeletedEvent.objects.count(), deleted_before + 1)
|
||||
|
||||
# delete e1
|
||||
draft.state_cache = None
|
||||
r = self.client.post(url, dict(event=e1.id))
|
||||
self.assertEquals(draft.get_state("draft-rfceditor"), None)
|
||||
|
||||
|
|
|
@ -10,13 +10,10 @@
|
|||
{% if doc.type_id == "draft" or doc.type_id == "conflrev" %}
|
||||
<div class="action">
|
||||
{% if deferred %}
|
||||
<div><a href="{% url doc_undefer_ballot name=doc.name %}">Undefer ballot</a></div>
|
||||
<a href="{% url doc_undefer_ballot name=doc.name %}">Undefer ballot</a>
|
||||
<div>Ballot deferred by {{ deferred.by }} on {{ deferred.time|date:"Y-m-d" }}.</div>
|
||||
{% else %}
|
||||
<div><a href="{% url doc_defer_ballot name=doc.name %}">Defer ballot</a></div>
|
||||
{% endif %}
|
||||
{% if user|has_role:"Secretariat" %}
|
||||
<div><a href="{% url doc_clear_ballot name=doc.name %}">Clear ballot</a></div>
|
||||
<a href="{% url doc_defer_ballot name=doc.name %}">Defer ballot</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
155
ietf/templates/doc/document_charter.html
Normal file
155
ietf/templates/doc/document_charter.html
Normal file
|
@ -0,0 +1,155 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}{{ doc.canonical_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.last %}{{ 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 "{{ group.name }}"
|
||||
(<a href="{% url ietf.wginfo.views.wg_charter acronym=group.acronym %}">{{ group.acronym }}</a>) {{ group.type.name }}
|
||||
</div>
|
||||
|
||||
<table id="metatable" width="100%">
|
||||
<tr>
|
||||
<td>WG State:</td>
|
||||
<td>{{ group.state.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/doc/help/state/charter/">Charter State</a>:</td>
|
||||
<td>
|
||||
<div>
|
||||
<a title="{{ doc.get_state.desc }}"
|
||||
{% if not snapshot and user|has_role:"Area Director,Secretariat" %}
|
||||
class="editlink" href="{% url charter_change_state name=doc.name %}"
|
||||
{% endif %}>
|
||||
{{ doc.get_state.name }}
|
||||
</a>
|
||||
{% if chartering == "initial" %} - (Initial Chartering){% endif %}
|
||||
{% if chartering == "rechartering" %} - (Rechartering){% endif %}
|
||||
</div>
|
||||
|
||||
{% if not snapshot and chartering %}
|
||||
<div class="telechat">
|
||||
<a
|
||||
{% if user|has_role:"Area Director,Secretariat" %}
|
||||
class="editlink" href="{% url charter_telechat_date name=doc.name %}"
|
||||
{% endif %}>
|
||||
{% if not telechat %}Not on agenda of IESG telechat{% else %}On agenda of {{ telechat.telechat_date|date:"Y-m-d" }} IESG telechat{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if ballot_summary %}
|
||||
<div class="ballot-summary">
|
||||
({{ ballot_summary }})
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if chartering and group.comments %}
|
||||
<tr>
|
||||
{% if chartering == "initial" %}<td>Reason for chartering:</td>{% endif %}
|
||||
{% if chartering == "rechartering" %}<td>Reason for rechartering:</td>{% endif %}
|
||||
<td>{{ group.comments }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td>Responsible AD:</td>
|
||||
<td><a {% if request.user|has_role:"Area Director,Secretariat" %}class="editlink" href="{% url charter_edit_ad name=doc.name %}"{% endif %}>{{ doc.ad|default:"none" }}</a> </td>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr>
|
||||
<td>Send notices to:</td>
|
||||
<td><a {% if user|has_role:"Area Director,Secretariat" %}
|
||||
class="editlink" href="{% url charter_edit_notify name=doc.name %}"
|
||||
{% endif %}>
|
||||
{{ doc.notify|default:"none" }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td>Last updated:</td><td> {{ doc.time|date:"Y-m-d" }}</td></tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
</table>
|
||||
|
||||
<div class="links">
|
||||
<a href="/feed/group-changes/{{ group.acronym }}/">Atom feed</a>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
{% if not snapshot and user|has_role:"Area Director,Secretariat" %}
|
||||
{% if chartering %}
|
||||
{% url charter_startstop_process name=doc.name option='abandon' as abandon_url %}{% if abandon_url %}<a class="button" href="{{ abandon_url }}">Abandon Effort</a>{% endif %}
|
||||
|
||||
{% if request.user|has_role:"Secretariat" %}
|
||||
{% url charter_approve name=doc.name as approve_url %}{% if approve_url %}<a class="button" href="{{ approve_url }}">Approve Charter</a>{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{% if group.state_id == "proposed" or group.state_id == "bof" %}
|
||||
{% url charter_submit name=doc.name option='initcharter' as start_url %}{% if start_url %}<a class="button" href="{{ start_url }}">Start Chartering</a>{% endif %}
|
||||
{% else %}
|
||||
{% url charter_submit name=doc.name option='recharter' as recharter_url %}{% if recharter_url %}<a class="button" href="{{ recharter_url }}">Recharter</a>{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Other versions: <a href="{{ txt_url }}">plain text</a></p>
|
||||
|
||||
<h3>Charter {{ doc.canonical_name }}-{{ doc.rev }}
|
||||
|
||||
{% if not snapshot and user|has_role:"Area Director,Secretariat" and chartering and group.state_id != "conclude" %}
|
||||
<a class="edit" href="{% url charter_submit name=doc.name %}">Change charter text</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
|
||||
{% if doc.rev != "" %}
|
||||
<div class="document-markup">
|
||||
{{ content|safe|keep_spacing|sanitize_html|wordwrap:80|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not snapshot and chartering %}
|
||||
<h3>Proposed Milestones
|
||||
{% if user|has_role:"Area Director,Secretariat" %}
|
||||
<a class="edit" href="{% url wg_edit_charter_milestones acronym=doc.group.acronym %}">Edit charter milestones</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
|
||||
{% if milestones %}
|
||||
{% include "wginfo/milestones.html" %}
|
||||
{% else %}
|
||||
<p>No milestones for charter found.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
{% extends "idrfc/doc_main.html" %}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}{{ doc.name }}-{{ doc.rev }}{% endblock %}
|
||||
{% block title %}{{ doc.canonical_name }}-{{ doc.rev }}{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
|
||||
|
@ -24,7 +24,7 @@
|
|||
<div>
|
||||
{% if snapshot %}Snapshot of{% endif %}
|
||||
{% if doc.get_state_slug not in approved_states %}Proposed{% endif %}
|
||||
IESG Conflict Review for the {{conflictdoc.stream}} document: <a href="{% url doc_view name=conflictdoc.canonical_name %}">{{ conflictdoc.canonical_name }}{% if conflictdoc.get_state_slug != 'rfc' %}-{{ conflictdoc.rev }}{% endif %}</a>
|
||||
IESG Conflict Review for the {{conflictdoc.stream}} document: <a href="{% url doc_view name=conflictdoc.canonical_name %}">{{ conflictdoc.canonical_name }}-{{ conflictdoc.rev }}</a>
|
||||
</div>
|
||||
|
||||
<table id="metatable" width="100%">
|
||||
|
@ -42,26 +42,25 @@
|
|||
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% if not snapshot %}
|
||||
<tr>
|
||||
<td>Telechat Date:</td>
|
||||
<td>
|
||||
|
||||
{% if not snapshot %}
|
||||
<div class="telechat">
|
||||
<a {% if not snapshot and user|has_role:"Area Director,Secretariat" and doc.get_state_slug not in approved_states %}
|
||||
class="editlink" href="{% url conflict_review_telechat_date name=doc.name %}"
|
||||
{%endif%} >
|
||||
{% if not telechat %}Not on agenda of an IESG telechat{% else %}On agenda of {{ telechat.telechat_date|date:"Y-m-d" }} IESG telechat{% if doc.returning_item %} (returning item){% endif %}{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if ballot_summary %}
|
||||
<div class="ballot-summary">
|
||||
({{ ballot_summary }})
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td>Shepherding AD:</td>
|
||||
|
@ -100,7 +99,7 @@
|
|||
|
||||
</div>
|
||||
|
||||
<h3>Conflict Review for {{ conflictdoc.name }}-{{ conflictdoc.rev }}
|
||||
<h3>Conflict Review for {{ conflictdoc.canonical_name }}-{{ conflictdoc.rev }}
|
||||
|
||||
{% if not snapshot and user|has_role:"Area Director,Secretariat" and doc.get_state_slug != 'apprsent' %}
|
||||
<a class="edit" href="{% url conflict_review_submit name=doc.name %}">Change conflict review text</a>
|
||||
|
@ -108,7 +107,7 @@
|
|||
</h3>
|
||||
|
||||
{% if doc.rev %}
|
||||
<div class="markup_draft">
|
||||
<div class="document-markup">
|
||||
{{ content|fill:"80"|safe|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
</div>
|
||||
{% endif %}
|
284
ietf/templates/doc/document_draft.html
Normal file
284
ietf/templates/doc/document_draft.html
Normal file
|
@ -0,0 +1,284 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block title %}{% if doc.get_state_slug == "rfc" %}RFC {{ rfc_number }}{% else %}{{ name }}-{{ doc.rev }}{% endif %}{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
<link rel="stylesheet" type="text/css" href="/css/doc.css"></link>
|
||||
<meta name="description" content="{{ doc.title }} {% if doc.get_state_slug == "rfc" %}(RFC {{ rfc_number }}{% if published %}, {{ published.time|date:"F Y" }}{% endif %}{% if obsoleted_by %}; obsoleted by {{ obsoleted_by|join:", " }}{% endif %}){% else %}(Internet-Draft, {{ doc.time|date:"Y" }}){% endif %}" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ top|safe }}
|
||||
|
||||
<div class="ietf-box metabox">
|
||||
<table id="metatable" width="100%">
|
||||
<tr>
|
||||
<td>Document type:</td>
|
||||
<td>
|
||||
{% if doc.get_state_slug == "rfc" %}
|
||||
RFC - {{ doc.std_level }}
|
||||
({% if published %}{{ published.time|date:"F Y" }}{% else %}publication date unknown{% endif %}{% if has_errata %}; <a href="http://www.rfc-editor.org/errata_search.php?rfc={{ rfc_number }}" rel="nofollow">Errata</a>{% endif %})
|
||||
|
||||
{% if obsoleted_by %}<div>Obsoleted by {{ obsoleted_by|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if updated_by %}<div>Updated by {{ updated_by|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if obsoletes %}<div>Obsoletes {{ obsoletes|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if updates %}<div>Updates {{ updates|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if rfc_aliases %}<div>Also Known As {{ rfc_aliases|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if draft_name %}<div>Was <a href="/doc/{{ draft_name}}/">{{ draft_name }}</a> {% if submission %}({{ submission|safe }}){% endif %}</div>{% endif %}
|
||||
{% else %}
|
||||
{{ doc.get_state }} Internet-Draft {% if submission %}({{ submission|safe }}){% endif %}
|
||||
|
||||
{% if resurrected_by %}- resurrect requested by {{ resurrected_by }}{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if replaces %}<div>Replaces: {{ replaces|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
{% if replaced_by %}<div>Replaced by: {{ replaced_by|join:", "|urlize_ietf_docs }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Document stream:</td>
|
||||
<td>
|
||||
<a {% if can_change_stream %} class="editlink" href="{% url doc_change_stream name=doc.name %}"{% endif %}>
|
||||
{{ doc.stream|default:"No stream defined" }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Last updated:</td>
|
||||
<td>
|
||||
{{ doc.time|date:"Y-m-d" }}
|
||||
{% if latest_revision and latest_revision.time.date != doc.time.date %}
|
||||
(latest revision {{ latest_revision.time|date:"Y-m-d" }})
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if doc.get_state_slug != "rfc" %}
|
||||
<tr>
|
||||
<td>Intended RFC status:</td>
|
||||
<td>
|
||||
<a {% if can_edit or can_edit_stream_info %}class="editlink" href="{% url doc_change_intended_status name=doc.name %}"{% endif %}>
|
||||
{{ doc.intended_std_level|default:"Unknown" }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td>Other versions:</td>
|
||||
<td>
|
||||
{% if doc.get_state_slug != "active" and doc.get_state_slug != "rfc" %}(expired, archived):{% endif %}
|
||||
{% if file_urls %}
|
||||
{% for label, url in file_urls %}<a href="{{ url }}">{{ label}}</a>{% if not forloop.last%}, {% endif %}{% endfor %}
|
||||
{% else %}
|
||||
(not online)
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if conflict_reviews %}
|
||||
<tr>
|
||||
<td>IETF Conflict Review:</td>
|
||||
<td>{{ conflict_reviews|join:", "|urlize_ietf_docs }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
<tr>
|
||||
<td>{{ doc.stream }} State:</td>
|
||||
<td class="stream-state">
|
||||
<a {% if can_edit_stream_info %}class="editlink" href="{% url edit_state name=doc.name %}"{% endif %}>
|
||||
{{ stream_state|default:"(None)" }}
|
||||
</a>
|
||||
|
||||
{% for m in milestones %}
|
||||
<span title="{{ m.desc }} ({{ m.group.acronym }} milestone)" class="milestone">{{ m.due|date:"M Y" }}</span>
|
||||
{% endfor %}
|
||||
|
||||
{% if stream_tags %}
|
||||
<div class="stream-tags">{% for tag in stream_tags %}{{ tag.name }}{% if not forloop.last %}, {% endif %}{% endfor %}</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if consensus %}
|
||||
<tr>
|
||||
<td>Consensus:</td>
|
||||
<td>
|
||||
<a title="Whether the document is the result of a community consensus process as defined in RFC 5741" {% if can_edit or can_edit_stream_info %}class="editlink" href="{% url doc_edit_consensus name=doc.name %}"{% endif %}>
|
||||
{{ consensus }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td>Document shepherd:</td>
|
||||
<td>
|
||||
{# the shepherd edit page only works for WGs at the moment ... #}
|
||||
<a {% if can_edit_stream_info and group.type_id == "wg" %}class="editlink" href="{% url doc_managing_shepherd acronym=group.acronym,name=doc.name %}"{% endif %}>
|
||||
{{ doc.shepherd|default:"No shepherd assigned" }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{# the shepherd write up page only works for WGs at the moment ... #}
|
||||
{% if group.type_id == "wg" %}
|
||||
{% if shepherd_writeup or can_edit_shepherd_writeup %}
|
||||
<tr>
|
||||
<td>Shepherd Write-Up:</td>
|
||||
<td>
|
||||
<a {% if can_edit_shepherd_writeup %}class="editlink"{% endif %} href="{% url doc_managing_writeup acronym=group.acronym,name=doc.name %}">
|
||||
{% if shepherd_writeup %}Last changed {{ shepherd_writeup.time|date:"Y-m-d"}}{% else %}(None){% endif %}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
{% if published and started_iesg_process and published.time < started_iesg_process.time %}
|
||||
<tr>
|
||||
<td colspan='2' style="font-style:italic">This information refers to IESG processing after the RFC was initially published:</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td><a href="/idtracker/help/state/">IESG State</a>:</td>
|
||||
<td>
|
||||
<a {% if iesg_state and can_edit %}class="editlink" href="{% url doc_change_state name=doc.name %}"{% endif %}>
|
||||
{{ iesg_state|default:"I-D Exists" }}</a>
|
||||
|
||||
{% if iana_review_state %}
|
||||
<div>IANA Review State:
|
||||
<a {% if can_edit_iana_state %}class="editlink" href="{% url doc_change_iana_state name=doc.name state_type="iana-review" %}"{% endif %}>{{ iana_review_state }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if iana_review_state %}
|
||||
<div>IANA Action State:
|
||||
<a {% if can_edit_iana_state %}class="editlink" href="{% url doc_change_iana_state name=doc.name state_type="iana-action" %}"{% endif %}>{{ iana_action_state }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if rfc_editor_state %}
|
||||
<div>
|
||||
RFC Editor State:
|
||||
<a href="http://www.rfc-editor.org/queue2.html#{{ doc.name }}">{{ rfc_editor_state }}</a></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="telechat">
|
||||
<a {% if can_edit %}class="editlink" href="{% url doc_change_telechat_date name=doc.name %}"{% endif %}>
|
||||
|
||||
{% if telechat %}
|
||||
On agenda of {{ telechat.telechat_date }} IESG telechat {% if telechat.returning_item %} (returning item){% endif %}
|
||||
{% else %}
|
||||
{% if can_edit %}Not on an upcoming telechat agenda{% endif %}
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if ballot_summary %}<div class="ballot-summary">({{ ballot_summary }})</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Responsible AD:</td>
|
||||
<td>
|
||||
<a {% if can_edit %}class="editlink" href="{% url doc_change_ad name=doc.name %}"{% endif %}>
|
||||
{{ doc.ad|default:"(None)" }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% if iesg_state %}
|
||||
{% if doc.note or can_edit %}
|
||||
<tr>
|
||||
<td>IESG Note:</td>
|
||||
<td>
|
||||
<a {% if can_edit %}class="editlink" href="{% url doc_change_iesg_note name=doc.name %}"{% endif %}>
|
||||
{{ doc.note|default:"(None)"|linebreaksbr }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<td>Send notices to:</td>
|
||||
<td>
|
||||
<a {% if can_edit %}class="editlink" href="{% url doc_change_notify name=doc.name %}"{% endif %}>
|
||||
{{ doc.notify|default:"No addresses provided"}}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
</table>
|
||||
|
||||
<div class="links">
|
||||
<a href="mailto:{{ doc.name }}@tools.ietf.org?subject=Mail%20regarding%20{{ doc.name }}" rel="nofollow">Email Authors</a>
|
||||
| <a href="/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="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>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if can_edit and iesg_state %}
|
||||
<div class="links">
|
||||
<a href="{% url doc_ballot_lastcall name=doc.name %}">Last Call Text</a>
|
||||
| <a href="{% url doc_ballot_writeupnotes name=doc.name %}">Ballot Text</a>
|
||||
| <a href="{% url doc_ballot_approvaltext name=doc.name %}">Announcement Text</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if actions %}
|
||||
<div class="actions">
|
||||
{% for label, url in actions %}<a class="button" href="{{ url }}">{{ label }}</a> {% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if doc.get_state_slug == "active" or doc.get_state_slug == "rfc" %}
|
||||
|
||||
<div class="document-markup">
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
|
||||
{% if split_content %}
|
||||
<p><a style="display:inline-block;margin-left:17em;" href="?include_text=1">[include full document text]</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
|
||||
<p>This Internet-Draft is no longer active. Unofficial copies of old Internet-Drafts can be found here:<br/>
|
||||
<a href="http://tools.ietf.org/id/{{ doc.name }}">http://tools.ietf.org/id/{{ doc.name }}</a></p>
|
||||
|
||||
<h4>Abstract</h4>
|
||||
|
||||
<p>{{ doc.abstract|escape }}</p>
|
||||
|
||||
<h4>Authors</h4>
|
||||
|
||||
<p>
|
||||
{% for author in doc.documentauthor_set.all %}
|
||||
<a {% if not author.author.invalid_address %}href="mailto:{{ author.author.address }}"{% endif %}>{{ author.author.person }} {% if not author.author.invalid_address %}<{{ author.author.address }}>{% endif %}</a>
|
||||
{% if not forloop.last %}<br/>{% endif %}{% endfor %}
|
||||
</p>
|
||||
|
||||
<p>(Note: The e-mail addresses provided for the authors of this Internet-Draft may no longer be valid)</p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -6,13 +6,14 @@
|
|||
|
||||
{% 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 }}/" />
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ top|safe }}
|
||||
|
||||
{% if diff_revisions and diff_revisions|length > 1 %}
|
||||
<div class="ietf-box diffTool">
|
||||
<div class="ietf-box diff-tool">
|
||||
<h2>Diffs</h2>
|
||||
|
||||
<form action="http{% if request.is_secure %}s{% endif %}:{{rfcdiff_prefix}}" method="get" target="_blank">
|
||||
|
@ -55,7 +56,7 @@
|
|||
<h2>Document history</h2>
|
||||
{% if user|has_role:"Area Director,Secretariat,IANA,RFC Editor" %}
|
||||
<div class="history-actions">
|
||||
<a href="{% url doc_add_comment name=doc.name %}">Add comment</a>
|
||||
<a class="button" href="{% url doc_add_comment name=doc.name %}">Add comment</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -9,16 +9,20 @@
|
|||
{% block content %}
|
||||
{{ top|safe }}
|
||||
|
||||
{% for title, text, url in writeups %}
|
||||
<div class="writeup">
|
||||
{% for title, subtitle, writeups in sections %}
|
||||
<h2>{{ title }}</h2>
|
||||
|
||||
{% if can_edit %}<a href="{{ url }}" class="edit">{% if text %}Edit{% else %}Generate{% endif %} {{ title }}</a>{% endif %}
|
||||
{% if subtitle %}<p>{{ subtitle|safe }}</p>{% endif %}
|
||||
|
||||
{% for name, text, url in writeups %}
|
||||
<div class="writeup">
|
||||
{% if can_edit %}<a href="{{ url }}" class="edit button">{% if text %}Edit{% else %}Generate{% endif %} {{ name }}</a>{% endif %}
|
||||
|
||||
<pre {% if can_edit %}class="editable"{% endif %}>
|
||||
{{ text }}
|
||||
</pre>
|
||||
</div>
|
||||
{% endfor%}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
{% endblock content %}
|
25
ietf/templates/doc/shepherd_writeup.html
Normal file
25
ietf/templates/doc/shepherd_writeup.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block morecss %}
|
||||
form #id_content {
|
||||
width: 40em;
|
||||
height: 450px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
Shepherd writeup for {{ doc.canonical_name }}-{{ doc.rev }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Shepherd writeup for {{ doc.canonical_name }}-{{ doc.rev }}</h1>
|
||||
|
||||
<pre style="border:1px solid black;padding:5px;">{{writeup}}</pre>
|
||||
|
||||
<a href="{% url doc_view name=doc.name %}">Back</a>
|
||||
|
||||
{% if can_edit %}
|
||||
<span id="doc_edit_shepherd_writeup" class="yui-button yui-link-button" style="margin-left:2px;">{% url doc_edit_shepherd_writeup name=doc.name as doc_edit_url %}{% if doc_edit_url %}<span class="first-child"><a href="{{doc_edit_url}}">Edit</a></span>{% endif %}</span>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -1,2 +0,0 @@
|
|||
#Discuss Yes No Objection Abstain Recuse No Record
|
||||
{% for p in ballot.get_discuss %}{{p.ad_name}}, {% endfor %} {% for p in ballot.get_yes %}{{p.ad_name}}, {% endfor %} {% for p in ballot.get_no_objection %}{{p.ad_name}}, {% endfor %} {% for p in ballot.get_abstain %}{{p.ad_name}}, {% endfor %} {% for p in ballot.get_recuse %}{{p.ad_name}}, {% endfor %} {% for p in ballot.get_no_record %}{{p.ad_name}}, {% endfor %}
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -1,37 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
{% load ietf_filters %}<td class="date">{% if not doc.rfc %}{{ doc.publication_date }}{% else %}{{ doc.publication_date|date:"Y-m" }}{% endif %}
|
||||
{% if doc.publication_date|timesince_days|new_enough:request %}<br/><span class="ietf-small ietf-highlight-y">{% if not doc.rfc%}<a href="http:{{rfcdiff_prefix}}?url2={{doc.id.draft_name_and_revision}}">new</a>{%else%}new{%endif%}</span>{%endif%}
|
||||
{% if doc.id and doc.id.expected_expiration_date and doc.id.expected_expiration_date|timesince_days|expires_soon:request %}<br/><span class="ietf-small ietf-highlight-y">expires soon</span>{%endif%}
|
||||
</td>
|
|
@ -1,96 +0,0 @@
|
|||
{% comment %}<!--
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->{% endcomment %}
|
||||
{% load ietf_filters %}
|
||||
<table class="ietf-ballot"><tr valign="top"><td class="left">
|
||||
{% if doc_ballot_edit_button and user|in_group:"Area_Director,Secretariat" %}
|
||||
{% if user|in_group:"Area_Director" %}
|
||||
<div style="margin-top:8px; margin-bottom:8px;"><span id="doc_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url idrfc.views_ballot.edit_position name=doc.name,ballot_id=ballot.pk %}">Edit position</a></span></span></div>
|
||||
{% endif %}
|
||||
|
||||
{% if doc.active_defer_event %}
|
||||
<div style="margin-top:8px; margin-bottom:8px;"><span id="doc_undefer_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url doc_undefer_ballot name=doc.name,ballot_id=ballot.pk %}">Undefer ballot</a></span></span></div>
|
||||
<div style="margin-top:8px; margin-bottom:8px;">Ballot deferred by {{ doc.active_defer_event.by }} on {{ doc.active_defer_event.time|date:"Y-m-d" }}.</div>
|
||||
{% else %}
|
||||
<div style="margin-top:8px; margin-bottom:8px;"><span id="doc_defer_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url doc_defer_ballot name=doc.name,ballot_id=ballot.pk %}">Defer ballot</a></span></span></div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if doc_ballot_edit_button and user|in_group:"Secretariat" %}
|
||||
<div style="margin-top:8px; margin-bottom:8px;"><span id="doc_clear_ballot_button" class="yui-button yui-link-button"><span class="first-child"><a href="{% url doc_clear_ballot name=doc.name,ballot_id=ballot.pk %}">Clear ballot</a></span></span></div>
|
||||
{% endif %}
|
||||
|
||||
<p style="margin-top:1em;"><span class="square" style="background:#c00000;"></span><b>Discuss</b><br/>
|
||||
{% with bw.get_discuss as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#80ff80;"></span><b>Yes</b><br/>
|
||||
{% with bw.get_yes as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#80ff80;"></span><b>No Objection</b><br/>
|
||||
{% with bw.get_no_objection as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#ffff00;"></span><b>Abstain</b><br/>
|
||||
{% with bw.get_abstain as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:#c0c0c0;"></span><b>Recuse</b><br/>
|
||||
{% with bw.get_recuse as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
<p><span class="square" style="background:white;"></span><b>No Record</b><br/>
|
||||
{% with bw.get_no_record as positions %}{% include "idrfc/doc_ballot_list.html" %}{% endwith %}</p>
|
||||
|
||||
</td>
|
||||
<td class="right">
|
||||
|
||||
<h2 style="margin-top:12px;">Discusses and other comments</h2>
|
||||
|
||||
{% if bw.is_ballot_set %}<p>Other documents in this ballot set: {% for x in bw.ballot_set_other%}{{x|urlize_ietf_docs}}{% if not forloop.last %}, {% endif %}{% endfor %}</p>{% endif %}
|
||||
|
||||
{% if dw.in_ietf_process and dw.ietf_process.has_active_iesg_ballot %}
|
||||
<p>Summary: <i>{{ dw.ietf_process.iesg_ballot_needed }}</i></p>
|
||||
{% endif %}
|
||||
|
||||
{% for pos in bw.get_texts|dictsort:"is_old_ad" %}
|
||||
<h2 class="ballot_ad"><a name="{{pos.ad_name|slugify}}">{% if pos.is_old_ad %}[{%endif%}{{pos.ad_name|escape}}{% if pos.is_old_ad %}]{%endif%}</a></h2>
|
||||
|
||||
{% ifequal pos.position "Discuss" %}
|
||||
<p><b>Discuss ({{pos.discuss_date}})</b> <img src="/images/comment.png" width="14" height="12" alt=""/></p>
|
||||
<pre>{{pos.discuss_text|wrap_text:80|escape }}</pre>
|
||||
{% endifequal %}
|
||||
|
||||
{% if pos.comment_text %}
|
||||
<p><b>Comment ({{pos.comment_date}})</b> <img src="/images/comment.png" width="14" height="12" alt=""/></p>
|
||||
<pre>{{pos.comment_text|wrap_text:80|escape }}</pre>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td></tr></table>
|
|
@ -1,7 +0,0 @@
|
|||
{% load ietf_filters %}
|
||||
{% for p in positions %}
|
||||
{% if p.is_old_ad %}[{%endif%}<a{% if user|in_group:"Secretariat" %} href="{% url idrfc.views_ballot.edit_position name=doc.name,ballot_id=ballot.pk %}?ad={{ p.ad_username }}" title="Click to edit the position of {{ p.ad_name }}"{% endif %}>{{p.ad_name}}</a>{% if p.is_old_ad %}]{%endif%}{% if p.has_text %} <a href="#{{p.ad_name|slugify}}"><img src="/images/comment.png" width="14" height="12" alt="*" border="0"/></a>{% endif %}<br/>
|
||||
{% if p.old_positions %}<span class="was">(was {{p.old_positions|join:", "}})</span><br/>{%endif%}
|
||||
{% empty %}
|
||||
<i>none</i>
|
||||
{% endfor %}
|
|
@ -1,6 +0,0 @@
|
|||
{{ doc.title }}
|
||||
{% if info.is_rfc %}
|
||||
({{doc.maturity_level}}, {{doc.publication_date|date:"Y"}}){% if doc.obsoleted_by %}; Obsoleted by {{doc.obsoleted_by}}{% endif %}
|
||||
{% else %}
|
||||
({{info.type}}; {{doc.publication_date|date:"Y"}})
|
||||
{% endif %}
|
|
@ -1,68 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
<div class="ietf-box diffTool">
|
||||
<h2 style="margin-top:0;margin-bottom:4px;">Diffs</h2>
|
||||
<form action="http{% if request.is_secure %}s{% endif %}:{{rfcdiff_prefix}}" method="get" target="_blank" style="margin:0;">
|
||||
<table>
|
||||
<tr><td>
|
||||
<label>From:</label> <select name="url1">
|
||||
{% for id in versions %}
|
||||
<option value="{{id.draft_name}}-{{id.revision}}" {% ifequal forloop.counter 2 %} selected="selected" {% endifequal %}>{{id.draft_name}}-{{id.revision}} ({{id.date}})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td rowspan="2" valign="top">
|
||||
Format:
|
||||
<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 id in versions %}
|
||||
<option value="{{id.draft_name}}-{{id.revision}}" {% ifequal forloop.counter 1 %} selected="selected" {% endifequal %}>{{id.draft_name}}-{{id.revision}} ({{id.date}})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
|
@ -1,80 +0,0 @@
|
|||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
<table class="ietf-table">
|
||||
<tr><th class="comment_date">Date</th><th>Version</th><th>By</th><th>Text</th></tr>
|
||||
|
||||
{% for c in history %}
|
||||
<tr class="{% cycle oddrow,evenrow %}"{% if c.is_com %} id="history-{{c.comment.id }}"{% endif %}>
|
||||
<td class="comment_date">{{ c.date|date:"Y-m-d" }}</td>
|
||||
|
||||
{% if c.is_rev %}
|
||||
<td>{{ c.revision }}</td>
|
||||
<td>(System)</td>
|
||||
<td>New version available: <a href="http://tools.ietf.org/id/{{c.draft_name}}-{{c.revision}}.txt">{{c.draft_name}}-{{c.revision}}</a> {% ifnotequal c.revision "00" %}(<a href="http:{{rfcdiff_prefix}}?url2={{c.draft_name}}-{{c.revision}}">diff from -{{c.revision|add:"-1"|stringformat:"02d"}}</a>){% endifnotequal %}</td>
|
||||
{% endif %}
|
||||
|
||||
{% if c.is_text %}
|
||||
<td> </td>
|
||||
<td>(System)</td>
|
||||
<td>{{ c.text|safe }}</td>
|
||||
{% endif %}
|
||||
|
||||
{% if c.is_com %}
|
||||
<td>{{ c.comment.version }}</td>
|
||||
<td>{{ c.info.by|escape }}</td>
|
||||
<td>{% if c.comment.ballot %}
|
||||
[Ballot {{ c.comment.get_ballot_display }}]<br />
|
||||
{% endif %}
|
||||
{% if c.info.snipped %}
|
||||
<div id="commentS{{c.comment.id}}">{{ c.info.textSnippet|safe|sanitize_html|safe }}</div>
|
||||
<span class="comment_toggle" onclick="toggleComment({{c.comment.id}})" id="commentT{{c.comment.id}}">[show all]</span>
|
||||
<div id="commentF{{c.comment.id}}" style="display:none;">
|
||||
{{ c.info.text|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
{% if c.info.dontmolest %}
|
||||
{{ c.info.text|safe }}
|
||||
{% else %}
|
||||
{{ c.info.text|safe|urlize|linebreaksbr|keep_spacing|sanitize_html|safe }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
|
@ -1,126 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
{% block morecss %}
|
||||
.metabox { width: 99%; margin-top:8px; padding:4px; margin-bottom:1em; }
|
||||
#metatable { border: 0; border-spacing: 0; }
|
||||
#metatable tr { vertical-align:top ;}
|
||||
#metatable .post-rfc { font-style: italic; color: #004000; }
|
||||
.comment_toggle { text-decoration: underline; color: blue; }
|
||||
.comment_date { white-space: nowrap; }
|
||||
|
||||
div.diffTool { padding: 8px 4px; margin: 8px 0;}
|
||||
.diffTool label { float:left; width:50px; }
|
||||
|
||||
.markup_draft pre {line-height: 1.2em; margin: 0; }
|
||||
.m_hdr, .m_ftr { color: #808080; }
|
||||
.m_ftr { border-bottom: 1px solid #a0a0a0; }
|
||||
.m_h { font-family: arial; font-weight:bold;}
|
||||
|
||||
a.editlink {
|
||||
background-image: url("/images/pencil.png");
|
||||
background-size:10px;
|
||||
background-position: right top;
|
||||
background-attachment: scroll;
|
||||
background-repeat: no-repeat;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
a.editlink:link {text-decoration:none; color:inherit;}
|
||||
a.editlink:visited {text-decoration:none; color:inherit;}
|
||||
a.editlink:hover {text-decoration:underline;}
|
||||
a.editlink:active {text-decoration:underline;}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{% if doc.in_ietf_process %}
|
||||
<link rel="alternate" type="application/atom+xml" href="/feed/comments/{% if info.is_rfc %}rfc{{doc.rfc_number}}{% else %}{{doc.draft_name}}{% endif %}/" />
|
||||
{% endif %}
|
||||
<meta name="description" content="{% include "idrfc/doc_description.html" %}" />
|
||||
{% comment %}
|
||||
## See ticket #545 -- this is commented out because the versions
|
||||
## that we currently serve is not sufficiently cachable, so the
|
||||
## prefetched version is actually thrown away.
|
||||
## Once the content becomes cacheable, these links should
|
||||
## be reinserted into the document.
|
||||
{% ifequal tab "document" %}
|
||||
{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}
|
||||
<link rel="prefetch" href="ballot/" />
|
||||
<link rel="prefetch" href="writeup/" />
|
||||
{% endif %}
|
||||
<link rel="prefetch" href="history/" />
|
||||
{% endifequal %}
|
||||
{% endcomment %}
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}{% include "idrfc/doc_title.html" %}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ doc.title }}<br/>{% include "idrfc/doc_title.html" %}</h1>
|
||||
|
||||
<div id="mytabs" class="yui-navset">
|
||||
<ul class="yui-nav">
|
||||
<li{% ifequal tab "document" %} class="selected"{% endifequal %}><a href="{{ doc.get_absolute_url }}"><em>Document</em></a></li>
|
||||
<li{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}{% ifequal tab "ballot" %} class="selected"{% endifequal %}{%else%} class="disabled"{%endif%}><a href="{{ doc.get_absolute_url }}ballot/"><em>IESG Evaluation Record</em></a></li>
|
||||
<li{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}{% ifequal tab "writeup" %} class="selected"{% endifequal %}{%else%} class="disabled"{%endif%}><a href="{{ doc.get_absolute_url }}writeup/"><em>IESG Writeups</em></a></li>
|
||||
<li{% ifequal tab "history" %} class="selected"{% endifequal %}><a href="{{ doc.get_absolute_url }}history/"><em>History</em></a></li>
|
||||
</ul>
|
||||
<div class="yui-content">
|
||||
|
||||
{% block tab_content %}{% endblock %}
|
||||
|
||||
</div> <!-- yui-content -->
|
||||
</div> <!-- mytabs -->
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
{% block scripts %}
|
||||
function toggleComment(n) {
|
||||
var el = document.getElementById("commentF"+n);
|
||||
var el2 = document.getElementById("commentS"+n);
|
||||
var el3 = document.getElementById("commentT"+n);
|
||||
if (el.style.display == 'none') {
|
||||
el.style.display = 'block';
|
||||
el2.style.display = 'none';
|
||||
el3.innerHTML = ""; //[hide]";
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
el2.style.display= 'block';
|
||||
el3.innerHTML = "[show all]";
|
||||
}
|
||||
}
|
||||
{% endblock scripts %}
|
|
@ -1,47 +0,0 @@
|
|||
{% extends "idrfc/doc_main.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}
|
||||
{% with 1 as doc_ballot_edit_button %}
|
||||
{% with doc.ietf_process.iesg_ballot as ballot %}
|
||||
{% include "idrfc/doc_ballot.html" %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endblock tab_content %}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
{% extends "idrfc/doc_main.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
<div class="ietf-box metabox">
|
||||
<table id="metatable" width="100%">
|
||||
{% block doc_metatable %}{% endblock %}
|
||||
</table>
|
||||
|
||||
<div style="padding-top:6px;padding-bottom:6px;padding-left:2px;">
|
||||
{% block doc_metalinks %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% block doc_metabuttons %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<div style="padding-bottom:2px;">
|
||||
{% ifequal doc.draft_status "Expired" %}
|
||||
{% if not doc.resurrect_requested_by and user|in_group:"Area_Director" %}
|
||||
<span id="doc_request_resurrect_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url doc_request_resurrect name=doc.draft_name %}">Request resurrect</a></span></span>
|
||||
{% endif %}
|
||||
{% if user|in_group:"Secretariat" %}
|
||||
<span id="doc_resurrect_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url doc_resurrect name=doc.draft_name %}">Resurrect</a></span></span>
|
||||
{% endif %}
|
||||
{% else %} {# not expired #}
|
||||
{% if stream_info.stream.name == 'ISE' or stream_info.stream.name == 'IRTF' %}
|
||||
{% if user|in_group:"Secretariat" and not info.conflict_reviews %}
|
||||
<span id="doc_conflict_review_button" class="yui-button yui-link-button" style="margin-left:2px;">{% url conflict_review_start name=doc.draft_name as start_review_url %}{% if start_review_url %}<span class="first-child"><a href="{{start_review_url}}">Begin IETF Conflict Review {% if not doc.underlying_document.intended_std_level %}(note that intended status is not set){% endif %}</a></span>{% endif %}</span>
|
||||
{% endif %}
|
||||
{% else %} {# Not a candidate for conflict review #}
|
||||
{% if stream_info.stream.name == 'IETF' and not doc.in_ietf_process %}
|
||||
<span id="doc_add_button" class="yui-button yui-link-button" style="margin-left:2px;">{% url doc_edit_info name=doc.draft_name as doc_edit_url %}{% if doc_edit_url %}<span class="first-child"><a href="{{doc_edit_url}}">Begin IESG Processing</a></span>{% endif %}</span>
|
||||
{% else %}
|
||||
{% if doc.underlying_document.get_state_slug == 'rfc' %}
|
||||
<span id="doc_start_status_change" class="yui-button yui-link-button" style="margin-left:2px;">{% url start_rfc_status_change name=doc.underlying_document.canonical_name as start_url %}{% if start_url %}<span class="first-child"><a href="{{start_url}}">Start {% if info.proposed_status_changes %}An Additional {% endif %}Status Change</a></span>{% endif %}</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
</div>
|
||||
{% endif %}{# if user in group #}
|
||||
{% endblock doc_metabuttons %}
|
||||
</div> <!-- metabox -->
|
||||
|
||||
<div id="rfcText1">
|
||||
{% block doc_text1 %}{% endblock %}
|
||||
</div> <!-- rfcText1 -->
|
||||
{% endblock tab_content %}
|
||||
|
||||
{% block content_end %}
|
||||
<div id="rfcText2">
|
||||
{% if include_text %}
|
||||
{% block doc_text2 %}{% endblock %}
|
||||
{% else %}
|
||||
<a href="?include_text=1">[include full document text]</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock content_end %}
|
|
@ -1,238 +0,0 @@
|
|||
{% extends "idrfc/doc_tab_document.html" %}
|
||||
{% comment %}<!--
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->{% endcomment %}
|
||||
|
||||
{% load ietf_filters ietf_streams %}
|
||||
|
||||
{% block doc_metatable %}
|
||||
<tr><td colspan='2'>{{ doc.draft_status }} {% ifnotequal doc.draft_status "RFC" %}Internet-Draft ({{ doc.submission|safe }}){% endifnotequal %}
|
||||
{% ifequal doc.draft_status "Expired" %}
|
||||
{% if doc.resurrect_requested_by %}(resurrect requested by {{ doc.resurrect_requested_by }}){% endif %}
|
||||
{% endifequal %} </td>
|
||||
|
||||
<tr><td>Document Stream:</td><td>
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_stream name=doc.draft_name %}">{% endif %}
|
||||
{% if stream_info.stream %}{{ stream_info.stream.name|default:"No stream defined" }}{% else %}No stream defined{% endif %}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
{% endwith %}
|
||||
</td></tr>
|
||||
|
||||
<tr><td>Last updated:</td><td> {{ doc.publication_date|default:"(data missing)" }}</td></tr>
|
||||
|
||||
{% with doc.replaces as r %}{% if r %}<tr><td>Replaces:</td><td> {% filter urlize_ietf_docs %}{{ r|join:", "}}{% endfilter %}</td></tr>{% endif %}{% endwith %}
|
||||
{% with doc.replaced_by as r %}{% if r %}<tr><td>Replaced by:</td><td> {% filter urlize_ietf_docs %}{{ r|join:", "}}{% endfilter %}</td></tr>{% endif %}{% endwith %}
|
||||
|
||||
{% with info.conflict_reviews as r %}{% if r %}<tr><td>IETF Conflict Review:</td><td> {% filter urlize_ietf_docs %}{{ r|join:","}}{% endfilter %}</td></tr>{% endif %} {% endwith %}
|
||||
|
||||
<tr><td>Intended RFC status:</td><td>
|
||||
<a{% if info.can_edit_intended_std_level %} class="editlink" href="{% url doc_change_intended_status name=doc.draft_name %}"{% endif %}>
|
||||
{{ doc.underlying_document.intended_std_level|default:"(None)" }}
|
||||
</a>
|
||||
</td></tr>
|
||||
|
||||
<tr><td>Other versions:</td>
|
||||
{% ifequal doc.draft_status "Active" %}
|
||||
<td>
|
||||
<a href="http://www.ietf.org/id/{{doc.draft_name_and_revision}}.txt">plain text</a>,
|
||||
{% for ext in doc.file_types %}
|
||||
{% ifnotequal ext ".txt" %}
|
||||
<a href="http://www.ietf.org/id/{{doc.draft_name_and_revision}}{{ext}}">{{ext|cut:"."}}</a>,
|
||||
{% endifnotequal %}
|
||||
{% endfor %}
|
||||
{% if not info.has_pdf %}
|
||||
<a href="http://tools.ietf.org/pdf/{{doc.draft_name_and_revision}}.pdf">pdf</a>,
|
||||
{% endif %}
|
||||
<a href="http://tools.ietf.org/html/{{doc.draft_name_and_revision}}">html</a>
|
||||
</td>
|
||||
{% else %}
|
||||
<td>
|
||||
(expired, archived):
|
||||
<a href="http://tools.ietf.org/id/{{doc.draft_name_and_revision}}.txt">plain text</a>,
|
||||
{% for ext in doc.file_types %}
|
||||
{% ifnotequal ext ".txt" %}
|
||||
<a href="http://tools.ietf.org/id/{{doc.draft_name_and_revision}}{{ext}}">{{ext|cut:"."}}</a>,
|
||||
{% endifnotequal %}
|
||||
{% endfor %}
|
||||
{% if not info.has_pdf %}
|
||||
<a href="http://tools.ietf.org/pdf/{{doc.draft_name_and_revision}}.pdf">pdf</a>,
|
||||
{% endif %}
|
||||
<a href="http://tools.ietf.org/html/{{doc.draft_name_and_revision}}">html</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endifequal %}
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
{% if stream_info.state %}
|
||||
{% ifequal stream_info.stream.name "IETF" %}
|
||||
<tr>
|
||||
<td>IETF State:</td>
|
||||
<td class="stream-state">{{ stream_info.state.name }} ({{ stream_info.streamed.get_group }})
|
||||
{% if stream_info.tags %}<br /><i>{% for tag in stream_info.tags %}{{ tag.name }}{% if not forloop.last %}, {% endif %}{% endfor %}</i>{% endif %}
|
||||
{% if milestones %}{% for m in milestones %}<span title="In {{ m.group.acronym }} milestone: {{ m.desc }}" class="milestone">{{ m.due|date:"M Y" }}</span>{% endfor %}{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
{% if stream_info.stream %}
|
||||
<tr>
|
||||
<td>{{ stream_info.stream.name }} status:</td>
|
||||
<td>
|
||||
{{ stream_info.state.name }} {% if stream_info.streamed.get_group %}({{ stream_info.streamed.get_group }}) {% endif %}
|
||||
{% if stream_info.tags %}<br /><i>{% for tag in stream_info.tags %}{{ tag.name }}{% if not forloop.last %}, {% endif %}{% endfor %}</i>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
{% endif %}
|
||||
<tr><td>Document shepherd:</td><td><a {% if info.can_edit_shepherd %}class="editlink" href="{% url doc_edit_shepherd name=doc.draft_name %}"{% endif %}>{{ doc.underlying_document.shepherd|default:"(None)" }}</a></td></tr>
|
||||
<tr><td></td><td><a href="{% url doc_shepherd_writeup name=doc.draft_name %}">Shepherd writeup</a></td></tr>
|
||||
|
||||
{% if info.consensus %}
|
||||
<tr><td>Consensus:</td><td><a title="Whether the document is the result of a community consensus process as defined in RFC 5741" {% if info.can_edit_consensus %}class="editlink" href="{% url doc_edit_consensus name=doc.draft_name %}"{% endif %}>{{ info.consensus }}</a></td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
|
||||
<tr><td><a href="/idtracker/help/state/">IESG State</>:</td><td>
|
||||
{% if doc.in_ietf_process and user|in_group:"Area_Director,Secretariat" %}
|
||||
<a class="editlink" href="{% url doc_change_state name=doc.draft_name %}"> {{ doc.friendly_state|safe }} </a>
|
||||
{% else %}
|
||||
{{ doc.friendly_state|safe }}
|
||||
{% endif %}
|
||||
{% if info.iana_review_state %}<br />IANA Review State: <a href="/help/state/draft/iana-review/">{{ info.iana_review_state.name|escape }}</a><a class="editlink" {% if user|in_group:"Secretariat,IANA" %}href="{% url doc_change_iana_state name=doc.draft_name state_type="iana-review" %}"{% endif %}> </a>{% endif %}
|
||||
{% if info.iana_action_state %}<br />IANA Action State: <a href="/help/state/draft/iana-action/">{{ info.iana_action_state.name|escape }}</a><a class="editlink" {% if user|in_group:"Secretariat,IANA" %}href="{% url doc_change_iana_state name=doc.draft_name state_type="iana-action" %}"{% endif %}> </a>{% endif %}
|
||||
{% if info.rfc_editor_state %}<br />RFC Editor State: <a href="http://www.rfc-editor.org/queue2.html#{{ doc.draft_name }}">{{ info.rfc_editor_state|escape }}</a>{% endif %}
|
||||
{% ifequal doc.draft_status "Expired" %}
|
||||
{% if doc.resurrect_requested_by %}(resurrect requested by {{ doc.resurrect_requested_by }}){% endif %}
|
||||
{% endifequal %}
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_telechat_date name=doc.draft_name %}">{% endif %}
|
||||
{% if doc.underlying_document.telechat_date %}<br/>On agenda of {{ doc.underlying_document.telechat_date }} IESG telechat {% if doc.underlying_document.returning_item %} (returning item){% endif %}{% else %}{%if add_link %}<br/>Not on an upcoming telechat agenda{% endif %}{% endif %}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
{% if doc.ietf_process.has_active_iesg_ballot %}<br/><i>({{ doc.ietf_process.iesg_ballot_needed }})</i>{%endif%}
|
||||
{% endwith %}
|
||||
</td></tr>
|
||||
{# <tr><td>Submission:</td><td>{{ doc.submission|safe }}</td></tr> #}
|
||||
<tr><td>Responsible AD:</td><td>
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_ad name=doc.draft_name %}">{% endif %}
|
||||
{% if doc.in_ietf_process %}{{ doc.ietf_process.ad_name|default:"(None)"|escape }}{%else%}(None){%endif%}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
{% endwith %}
|
||||
</td></tr>
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if doc.in_ietf_process %}{% if doc.ietf_process.iesg_note or add_link %}<tr><td>
|
||||
IESG Note:</td><td>
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_iesg_note name=doc.draft_name %}">{% endif %}
|
||||
{{ doc.ietf_process.iesg_note|format_textarea|safe }}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
</td></tr>{% endif %}{% endif %}
|
||||
{% endwith %}
|
||||
<tr><td>Send notices to:</td><td>
|
||||
{% with user|in_group:"Area_Director,Secretariat" as add_link %}
|
||||
{% if add_link %}<a class="editlink" href="{% url doc_change_notify name=doc.draft_name %}">{% endif %}
|
||||
{{ doc.underlying_document.notify|default:"No addresses provided"}}
|
||||
{% if add_link %}</a>{% endif %}
|
||||
{% endwith %}
|
||||
</td></tr>
|
||||
|
||||
<tr><td colspan='2'><hr size='1' noshade /></td></tr>
|
||||
|
||||
|
||||
{% endblock doc_metatable %}
|
||||
|
||||
{% block doc_metalinks %}
|
||||
{% edit_actions doc %}
|
||||
<div>
|
||||
<a href="mailto:{{doc.draft_name}}@tools.ietf.org?subject=Mail%20regarding%20{{doc.draft_name}}" rel="nofollow">Email Authors</a>
|
||||
| <a href="/ipr/search/?option=document_search&id_document_tag={{doc.tracker_id}}" rel="nofollow">IPR Disclosures</a>
|
||||
| <a href="http://www.fenron.net/~fenner/ietf/deps/index.cgi?dep={{doc.draft_name}}" rel="nofollow">Dependencies to this draft</a>
|
||||
| <a href="http://tools.ietf.org/idnits?url=http://tools.ietf.org/id/{{doc.draft_name_and_revision}}.txt" rel="nofollow" target="_blank">Check nits</a>
|
||||
{% if doc.in_ietf_process %}| <a href="/feed/comments/{% if info.is_rfc %}rfc{{doc.rfc_number}}{% else %}{{doc.draft_name}}{% endif %}/">Comments feed</a>{% endif %}
|
||||
| <a href="http://www.google.com/search?as_q={{doc.draft_name}}&as_sitesearch={{ doc.search_archive }}" rel="nofollow" target="_blank">Search Mailing Lists</a>
|
||||
{% if user|in_group:"Area_Director" %}
|
||||
| <a href="https://www.iesg.org/bin/c5i?mid=6&rid=77&target={{doc.draft_name}}" rel="nofollow" target="_blank">Search Mailing Lists (ARO)</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<div>
|
||||
{% if doc.in_ietf_process %}
|
||||
<a href="{% url doc_ballot_lastcall name=doc.draft_name %}">Last Call Text</a>
|
||||
| <a href="{% url doc_ballot_writeupnotes name=doc.draft_name %}">Ballot Text</a>
|
||||
| <a href="{% url doc_ballot_approvaltext name=doc.draft_name %}">Announcement Text</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block doc_text1 %}
|
||||
{% ifequal doc.draft_status "Active" %}
|
||||
<div class="markup_draft">
|
||||
{{ content1|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
<p>This Internet-Draft is no longer active. Unofficial copies of old Internet-Drafts can be found here:<br/>
|
||||
<a href="http://tools.ietf.org/id/{{doc.draft_name}}">http://tools.ietf.org/id/{{doc.draft_name}}</a>.</p>
|
||||
|
||||
<p style="max-width: 400px;"><b>Abstract:</b><br/> {{ doc.abstract|escape }}</p>
|
||||
|
||||
<p><b>Authors:</b><br/>
|
||||
{% for author in doc.authors.all %}
|
||||
|
||||
{% if author.email %}
|
||||
<a href="mailto:{{ author.email }}">{{ author.person }} <{{author.email}}></a>
|
||||
{% else %}
|
||||
{% if author.person %}
|
||||
{{ author.person }}
|
||||
{% else %}
|
||||
Missing author info #{{ author.person_id }}
|
||||
{% endif %}
|
||||
{% endif %}<br />
|
||||
|
||||
{% endfor %}</p>
|
||||
|
||||
<p>(Note: The e-mail addresses provided for the authors of this Internet-Draft may no longer be valid)</p>
|
||||
|
||||
{% endifequal %}
|
||||
{% endblock %}{# doc_text1 #}
|
||||
|
||||
{% block doc_text2 %}
|
||||
{% ifequal doc.draft_status "Active" %}
|
||||
<div class="markup_draft">
|
||||
{{ content2|safe }}
|
||||
</div>
|
||||
{% endifequal %}
|
||||
{% endblock %} {# doc_text2 #}
|
|
@ -1,112 +0,0 @@
|
|||
{% extends "idrfc/doc_tab_document.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block doc_metatable %}
|
||||
<tr><td style="width:18ex;">Document type:</td><td>RFC - {{ doc.maturity_level }} {% if doc.stream_name %}({{ doc.stream_name }}){% endif %}
|
||||
{% if doc.obsoleted_by %}<br />Obsoleted by {{ doc.obsoleted_by|urlize_ietf_docs }}{%endif %}
|
||||
{% if doc.updated_by %}<br />Updated by {{ doc.updated_by|urlize_ietf_docs }}{%endif %}
|
||||
{% if doc.obsoletes %}<br />Obsoletes {{ doc.obsoletes|urlize_ietf_docs }}{%endif %}
|
||||
{% if doc.updates %}<br />Updates {{ doc.updates|urlize_ietf_docs }}{%endif %}
|
||||
{% if info.status_changes %}<br />Status changed by {{ info.status_changes|urlize_ietf_docs }}{% endif %}
|
||||
{% if info.proposed_status_changes %}<br />Proposed status changes by {{ info.proposed_status_changes|urlize_ietf_docs }}{% endif %}
|
||||
{% if doc.also %}<br />Also Known As {{ doc.also|urlize_ietf_docs }}{%endif %}
|
||||
{% if doc.draft_name %}<br />Was <a href="/doc/{{ doc.draft_name}}/">{{doc.draft_name}}</a>{% endif %}
|
||||
{% if doc.has_errata %}<br /><a href="http://www.rfc-editor.org/errata_search.php?rfc={{doc.rfc_number}}" rel="nofollow">Errata</a>{% endif %}
|
||||
</td></tr>
|
||||
<tr><td>Published:</td><td> {{ doc.publication_date|date:"Y-m"|default:"(data missing)" }}</td></tr>
|
||||
{% if doc.in_ietf_process %}
|
||||
<tr class="post-rfc"><td colspan="2">* This information refers to IESG processing after the RFC was initially published</td></tr>
|
||||
<tr class="post-rfc"><td><a href="/idtracker/help/state/">State</a>:</td><td>
|
||||
{{ doc.friendly_state|safe }} (IESG: {{ doc.ietf_process.state}})
|
||||
{% if doc.ietf_process.telechat_date %}<br/>On agenda of {{ doc.ietf_process.telechat_date }} IESG telechat {% if doc.ietf_process.telechat_returning_item %} (returning item){%endif%}{%endif%}
|
||||
</td></tr>
|
||||
<tr class="post-rfc"><td>Intended status:</td><td>{% if doc.in_ietf_process %}{{ doc.ietf_process.intended_maturity_level|default:"-" }}{% else %}-{%endif%}</td></tr>
|
||||
<tr class="post-rfc"><td>Responsible AD:</td><td>{{ doc.ietf_process.ad_name|default:"-"|escape }}</td></tr>
|
||||
{% if doc.ietf_process.iesg_note %}<tr class="post-rfc"><td>IESG Note:</td><td>{{ doc.ietf_process.iesg_note|escape }}</td></tr>{% endif %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<tr class="post-rfc"><td>Send notices to:</td><td>{{ doc.ietf_process.state_change_notice_to}}</td></tr>
|
||||
{% endif %}{# if user|in_group:... #}
|
||||
|
||||
{% endif %}
|
||||
<tr><td>Other versions:</td><td>
|
||||
{% if info.has_txt or info.has_ps or info.has_pdf %}
|
||||
{% if info.has_txt %}
|
||||
<a href="http://www.rfc-editor.org/rfc/rfc{{doc.rfc_number}}.txt">plain text</a>,
|
||||
{% endif %}
|
||||
{% if info.has_ps %}
|
||||
<a href="http://www.rfc-editor.org/rfc/rfc{{doc.rfc_number}}.ps">ps</a>,
|
||||
{% endif %}
|
||||
{% if info.has_pdf %}
|
||||
<a href="http://www.rfc-editor.org/rfc/rfc{{doc.rfc_number}}.pdf">pdf</a>,
|
||||
{% else %}
|
||||
{% if info.has_txt %}
|
||||
<a href="http://www.rfc-editor.org/rfc/pdfrfc/rfc{{doc.rfc_number}}.txt.pdf">pdf</a>,
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if info.has_txt %}
|
||||
<a href="http://tools.ietf.org/html/rfc{{doc.rfc_number}}">html</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
(not online)
|
||||
{% endif %}
|
||||
</td></tr>
|
||||
{% endblock doc_metatable %}
|
||||
|
||||
{% block doc_metalinks %}
|
||||
<a href="/ipr/search/?option=rfc_search&rfc_search={{doc.rfc_number}}" rel="nofollow">IPR Disclosures</a>
|
||||
| <a href="http://www.fenron.net/~fenner/ietf/deps/index.cgi?dep=rfc{{doc.rfc_number}}" rel="nofollow">Dependencies to this RFC</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block doc_text1 %}
|
||||
{% if info.has_txt %}
|
||||
<div class="markup_draft">
|
||||
{{ content1|safe }}
|
||||
</div>
|
||||
{% else %}
|
||||
{% if info.has_pdf or info.has_ps %}
|
||||
<p>This RFC is not available in plain text format.</p>
|
||||
{% else %}
|
||||
<p>This RFC is not currently available online.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}{# doc_text1 #}
|
||||
|
||||
{% block doc_text2 %}
|
||||
<div class="markup_draft">
|
||||
{{ content2|safe }}
|
||||
</div>
|
||||
{% endblock %}{# doc_text2 #}
|
|
@ -1,52 +0,0 @@
|
|||
{% extends "idrfc/doc_main.html" %}
|
||||
<!--
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
-->
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
{% if not info.is_rfc %}
|
||||
{% include "idrfc/doc_diffs.html" %}
|
||||
{% endif %}
|
||||
<h2 style="margin-top:1em;">Document history</h2>
|
||||
{% if user|in_group:"Area_Director,Secretariat,IANA,RFC Editor" and doc.in_ietf_process %}
|
||||
<div style="margin-bottom:8px" id="history_actions">
|
||||
<span id="doc_add_comment_button" class="yui-button yui-link-button" style="margin-left:2px;"><span class="first-child"><a href="{% url doc_add_comment name=doc.draft_name %}">Add comment</a></span></span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include "idrfc/doc_history.html" %}
|
||||
{% endblock tab_content %}
|
|
@ -1,73 +0,0 @@
|
|||
{% extends "idrfc/doc_main.html" %}
|
||||
{% comment %}
|
||||
Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
All rights reserved. Contact: Pasi Eronen <pasi.eronen@nokia.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* Neither the name of the Nokia Corporation and/or its
|
||||
subsidiary(-ies) nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
{% load ietf_filters %}
|
||||
|
||||
{% block tab_content %}
|
||||
---- following is a DRAFT of message to be sent AFTER approval ---
|
||||
{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
<div style="background:#E0E0FF">
|
||||
<p align=right>
|
||||
<span id="doc_edit_announce_button" class="yui-button yui-link-button"><span class="first-child">
|
||||
<a href="{% url doc_ballot_approvaltext name=doc.draft_name %}">Edit Announcement Text</a>
|
||||
</span></span>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<pre>
|
||||
{{ doc.ietf_process.iesg_ballot.approval_text|escape|urlize }}
|
||||
</pre>
|
||||
{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
</div>
|
||||
|
||||
<div style="background:#E0E0FF">
|
||||
<p align=right>
|
||||
<span id="doc_ballot_edit_button" class="yui-button yui-link-button"><span class="first-child">
|
||||
<a href="{% url doc_ballot_writeupnotes name=doc.draft_name %}">Edit Ballot Text</a>
|
||||
</span></span>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<pre>
|
||||
{{ doc.ietf_process.iesg_ballot.ballot_writeup|escape|urlize }}
|
||||
</pre>
|
||||
{% if doc.in_ietf_process and doc.ietf_process.has_iesg_ballot %}
|
||||
{% if user|in_group:"Area_Director,Secretariat" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock tab_content %}
|
|
@ -1,5 +0,0 @@
|
|||
{% if info.is_rfc %}
|
||||
RFC {{ doc.rfc_number }}
|
||||
{% else %}
|
||||
{{ doc.draft_name_and_revision }}
|
||||
{% endif %}
|
|
@ -77,11 +77,6 @@ about:
|
|||
{% endif %}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% block scripts %}
|
||||
YAHOO.util.Event.onContentReady("search_submit_button", function () {
|
||||
var oButton = new YAHOO.widget.Button("search_submit_button", {});
|
||||
});
|
||||
{% endblock scripts %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/doc-search.js"></script>
|
||||
|
|
|
@ -32,54 +32,46 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
{% endcomment %}
|
||||
|
||||
<form name="search_form" id="search_form" class="search_form" action="/doc/search/" method="get" {# onsubmit="submitSearch();return false;" #}>
|
||||
<form id="search_form" class="search_form" action="/doc/search/" method="get">
|
||||
|
||||
<div class="search_field">
|
||||
<label>Name/number/title:</label> {{ form.name }}
|
||||
</div>
|
||||
|
||||
<div class="search_field">
|
||||
<label>Types:</label>
|
||||
<table id="search_types">
|
||||
<tr><td>{{ form.rfcs }} RFCs</td></tr>
|
||||
<tr><td>{{ form.activeDrafts }} Internet-Drafts (active)</td></tr>
|
||||
<tr><td>{{ form.oldDrafts }} Internet-Drafts (expired/replaced/withdrawn)</td></tr>
|
||||
</table>
|
||||
<label>Types:</label>
|
||||
<table id="search_types">
|
||||
<tr><td><label>{{ form.rfcs }} RFCs</label></td></tr>
|
||||
<tr><td><label>{{ form.activeDrafts }} Internet-Drafts (active)</label></td></tr>
|
||||
<tr><td><label>{{ form.oldDrafts }} Internet-Drafts (expired/replaced/withdrawn)</label></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<span class="toggle_advanced"><b><img src="/images/{% if meta.advanced %}minus{% else %}plus{% endif %}.png" alt="" id="search_advanced-img" /> Advanced</b></span>
|
||||
<b class="toggle_advanced"><img src="/images/{% if meta.advanced %}minus{% else %}plus{% endif %}.png" alt="" /> Advanced</b>
|
||||
|
||||
<div id="search_advanced" style="{% if not meta.advanced %}display:none;{%endif%}margin-top:1em;">
|
||||
<div id="search_advanced" style="{% if not meta.advanced %}display:none;{%endif%}">
|
||||
Additional search criteria:
|
||||
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="author" {% ifequal meta.by "author" %}checked="checked"{% endifequal %}/> Author (last name):</label> {{ form.author }}
|
||||
<label><input type="radio" class="radio" name="by" value="author" {% if meta.by == "author" %}checked="checked"{% endif %}/> Author (last name):</label> {{ form.author }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="group" {% ifequal meta.by "group" %}checked="checked"{% endifequal %}/> WG:</label> {{ form.group }}
|
||||
<label><input type="radio" class="radio" name="by" value="group" {% if meta.by == "group" %}checked="checked"{% endif %}/> WG:</label> {{ form.group }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="area" {% ifequal meta.by "area" %}checked="checked"{% endifequal %}/> Area:</label> {{ form.area }}
|
||||
<label><input type="radio" class="radio" name="by" value="area" {% if meta.by == "area" %}checked="checked"{% endif %}/> Area:</label> {{ form.area }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="ad" {% ifequal meta.by "ad" %}checked="checked"{% endifequal %}/> Responsible AD:</label> {{ form.ad }}
|
||||
<label><input type="radio" class="radio" name="by" value="ad" {% if meta.by == "ad" %}checked="checked"{% endif %}/> Responsible AD:</label> {{ form.ad }}
|
||||
</div>
|
||||
<div class="search_field">
|
||||
<label><input type="radio" class="radio" name="by" value="state" {% ifequal meta.by "state" %}checked="checked"{% endifequal %}/> IESG State:</label> {{ form.state }} :: {{ form.subState }}
|
||||
<label><input type="radio" class="radio" name="by" value="state" {% if meta.by == "state" %}checked="checked"{% endif %}/> IESG State:</label> {{ form.state }} :: {{ form.subState }}
|
||||
</div>
|
||||
{% comment %}
|
||||
<div class="search_field" style="text-decoration:line-through;color:#808080;">
|
||||
<label>Ballot position:</label> {{ form.positionAd }} has position {{ form.positionValue }}
|
||||
</div>
|
||||
{% endcomment %}
|
||||
|
||||
</div><!-- end of advanced -->
|
||||
|
||||
<div style="padding-top:0.5em;">
|
||||
{# <input type="hidden" name="ajax" value="" /> #}
|
||||
<span class="first-child">
|
||||
<button type="submit" name="search_submit" id="id_search_submit">Search</button>
|
||||
</span>
|
||||
<div class="submit">
|
||||
<input type="submit" class="button" value="Search"/>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
|
|
@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% block content %}
|
||||
<h1>Internet-Drafts and RFCs</h1>
|
||||
|
||||
<div class="ietf-box search_form_box">
|
||||
<div class="ietf-box search-form-box">
|
||||
{% include "idrfc/search_form.html" %}
|
||||
</div>
|
||||
|
||||
|
@ -48,32 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% endif %}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% block scripts %}
|
||||
YAHOO.util.Event.onContentReady("search_submit_button", function () {
|
||||
var oButton = new YAHOO.widget.Button("search_submit_button", {});
|
||||
});
|
||||
{% if meta.searching %}
|
||||
(function ($) {
|
||||
$(document).ready(function () {
|
||||
$('.addtolist a').click(function() {
|
||||
var trigger = $(this);
|
||||
$.ajax({
|
||||
url: trigger.attr('href'),
|
||||
type: 'GET',
|
||||
cache: false,
|
||||
dataType: 'json',
|
||||
success: function(response){
|
||||
if (response.success) {
|
||||
trigger.replaceWith('added');
|
||||
}
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
{% endif %}
|
||||
{% endblock scripts %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/doc-search.js"></script>
|
||||
|
|
|
@ -35,7 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% load ietf_filters %}
|
||||
{% load ballot_icon %}
|
||||
<tr class="{{ forloop.counter|divisibleby:2|yesno:"oddrow,evenrow" }}">
|
||||
{% if user.is_authenticated and show_add_to_list %}
|
||||
{% if show_add_to_list and user.is_authenticated %}
|
||||
<td class="addtolist">
|
||||
{% if doc.id %}
|
||||
<a href="{% url community_add_document doc.id.draft_name %}" title="Add to your personal ID list"><img src="/images/add_to_list.png" alt="Add to your personal ID list" /></a>
|
||||
|
@ -51,7 +51,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% endif %}
|
||||
</td>
|
||||
<td class="title">{{ doc.title }}</td>
|
||||
{% include "idrfc/date_column.html" %}
|
||||
|
||||
<td class="date">{% if not doc.rfc %}{{ doc.publication_date }}{% else %}{{ doc.publication_date|date:"Y-m" }}{% endif %}
|
||||
{% if doc.publication_date|timesince_days|new_enough:request %}<br/><span class="ietf-small ietf-highlight-y">{% if not doc.rfc%}<a href="http:{{rfcdiff_prefix}}?url2={{doc.id.draft_name_and_revision}}">new</a>{%else%}new{%endif%}</span>{%endif%}
|
||||
{% if doc.id and doc.id.expected_expiration_date and doc.id.expected_expiration_date|timesince_days|expires_soon:request %}<br/><span class="ietf-small ietf-highlight-y">expires soon</span>{%endif%}
|
||||
</td>
|
||||
|
||||
{% include "idrfc/status_columns.html" %}
|
||||
{% include "idrfc/ipr_column.html" %}
|
||||
{# <td class="ad">{% if doc.ad_name %}{{ doc.ad_name }}{% else %} {% endif %}</td> #}
|
||||
|
|
|
@ -38,19 +38,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
{% if not docs %}
|
||||
<p><b>No documents match your query.</b></p>
|
||||
{% else %}
|
||||
{% regroup docs by view_sort_group as grouped_docs %}
|
||||
|
||||
<table class="ietf-table ietf-doctable">
|
||||
<tr>{% if user.is_authenticated %}<th></th>{% endif %}
|
||||
{% for hdr in meta.hdrs %}
|
||||
{% include "idrfc/table_header.html" %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
{% if user.is_authenticated %}<th></th>{% endif %}
|
||||
|
||||
{% for hdr in meta.hdrs %}
|
||||
<th class="{{ hdr.htype }}" {% if hdr.colspan %}colspan="{{ hdr.colspan }}"{% endif %}>
|
||||
{{ hdr.htitle }}
|
||||
|
||||
<a href="{{ meta.rqps }}&sortBy={{hdr.htype}}"><img src="/images/sort-header-{% if hdr.selected %}filled{% else %}clear{% endif %}.png"/></a>
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<!-- <tr><th></th><th class="doc">Document</th><th class="title">Title</th><th class="date">Date</th><th class="status" colspan="2">Status</th><th class="ad">Area Director</th></tr> -->
|
||||
{% for doc_group in grouped_docs %}
|
||||
<tr class="header"><td colspan="7">{{doc_group.grouper}}s</td></tr>
|
||||
{% regroup docs by view_sort_group as grouped_docs %}
|
||||
{% for doc_group in grouped_docs %}
|
||||
<tr class="header"><td colspan="7">{{ doc_group.grouper }}s</td></tr>
|
||||
|
||||
{% with 1 as show_add_to_list %}
|
||||
{% for doc in doc_group.list %}
|
||||
{% include "idrfc/search_result_row.html" %}
|
||||
{% include "idrfc/search_result_row.html" %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
{# Copyright The IETF Trust 2011, All Rights Reserved #}
|
||||
|
||||
<th class="{{hdr.htype}}"{% if hdr.colspan %}colspan="{{ hdr.colspan }}" {% endif %}
|
||||
onclick="location=unescape('{{ meta.rqps }}&sortBy={{hdr.htype}}');"
|
||||
style="white-space: nowrap;"
|
||||
>
|
||||
<span>
|
||||
<label>{{hdr.htitle}}</label>
|
||||
{% if hdr.selected %}
|
||||
<img style="border-style: none;vertical-align:top" src="/images/sort-header-filled.png"/>
|
||||
{% else %}
|
||||
<img style="border-style: none;vertical-align:top" src="/images/sort-header-clear.png"/>
|
||||
{% endif %}
|
||||
</span>
|
||||
</th>
|
|
@ -20,6 +20,6 @@
|
|||
{% if doc.primary_flag %}
|
||||
<tr><td></td><td>Token:</td><td><a href="mailto:{{ doc.token_email|urlencode }}">{{ doc.token_name }}</a></td></tr>
|
||||
{% if doc.note %}
|
||||
<tr><td></td><td>Note:</td><td>{{ doc.note|safe|urlize }}</td></tr>
|
||||
<tr><td></td><td>Note:</td><td>{{ doc.note|linebreaksbr|urlize }}</td></tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
@ -83,7 +83,7 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
|
|||
<a href="http://www.ietf.org/id/{{doc.obj.conflictdoc.name}}-{{doc.obj.conflictdoc.rev}}.txt">[txt]</a>
|
||||
<br/>{{ doc.obj.conflictdoc.title|escape }} ({{doc.obj.conflictdoc.stream}}: {{ doc.obj.conflictdoc.intended_std_level }})
|
||||
{% if doc.obj.conflictdoc.note %}
|
||||
<br/>Note: {{ doc.obj.conflictdoc.note|unescape }}
|
||||
<br/>Note: {{ doc.obj.conflictdoc.note|linebreaksbr }}
|
||||
{% endif %}
|
||||
|
||||
{% if doc.obj.conflictdoc.ipr %}
|
||||
|
|
|
@ -85,7 +85,7 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
|
|||
|
||||
|
||||
{% if doc.obj.note %}
|
||||
<br/>Note: {{ doc.obj.note|unescape }}
|
||||
<br/>Note: {{ doc.obj.note|linebreaksbr }}
|
||||
{% endif %}
|
||||
|
||||
{% if doc.obj.ipr %}
|
||||
|
|
|
@ -51,8 +51,8 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
|
|||
{{ doc.obj.conflictdoc.title|escape }} ({{doc.obj.conflictdoc.stream}}: {{ doc.obj.conflictdoc.intended_std_level }})
|
||||
<br><a href="{% url doc_view name=doc.obj.conflictdoc.canonical_name %}">{{doc.obj.conflictdoc.canonical_name}}</a>
|
||||
<a href="http://www.ietf.org/id/{{doc.obj.conflictdoc.canonical_name}}-{{doc.obj.conflictdoc.rev}}.txt">[txt]</a>
|
||||
{% if doc.obj.conflictdoc.note %}{# note: note is not escaped #}
|
||||
<br>Note: {{ doc.obj.conflictdoc.note|safe }}
|
||||
{% if doc.obj.conflictdoc.note %}
|
||||
<br>Note: {{ doc.obj.conflictdoc.note|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% for ipr in doc.obj.conflictdoc.ipr %}
|
||||
{% ifequal ipr.ipr.status 1 %}
|
||||
|
|
|
@ -55,7 +55,7 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
|
|||
{% endwith %}
|
||||
<br>Token: {{ doc.obj.ad.plain_name|escape }} ({{doc.obj.area_acronym}} area)
|
||||
{% if doc.obj.note %}
|
||||
<br>Note: {{ doc.obj.note }}
|
||||
<br>Note: {{ doc.obj.note|linebreaksbr }}
|
||||
{% endif %}
|
||||
{% for ipr in doc.obj.ipr %}
|
||||
{% ifequal ipr.ipr.status 1 %}
|
||||
|
|
|
@ -10,7 +10,7 @@ label { float:left; width: 200px; }
|
|||
|
||||
<h1>IPR Search</h1>
|
||||
<h2>Document Search</h2>
|
||||
<div class="ietf-box search_form_box">
|
||||
<div class="ietf-box search-form-box">
|
||||
<form method="get">
|
||||
<input type="hidden" name="option" value="document_search">
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ is occasionally incorrect.</span>
|
|||
{% else %}
|
||||
none
|
||||
{% if user|has_role:"Area Director,Secretariat" %}
|
||||
- <a href="{% url wginfo.edit.submit_initial_charter acronym=wg.acronym %}">Submit Charter</a>
|
||||
- <a href="{% url ietf.wginfo.edit.submit_initial_charter acronym=wg.acronym %}">Submit Charter</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
|
|
|
@ -411,17 +411,16 @@ def make_test_data():
|
|||
# an independent submission before review
|
||||
doc = Document.objects.create(name='draft-imaginary-independent-submission',type_id='draft')
|
||||
doc.set_state(State.objects.get(used=True, type="draft", slug="active"))
|
||||
DocAlias.objects.create( name='draft-imaginary-independent-submission',document=doc)
|
||||
DocAlias.objects.create(name=doc.name, document=doc)
|
||||
|
||||
# an irtf submission mid review
|
||||
doc = Document.objects.create( name='draft-imaginary-irtf-submission',type_id='draft')
|
||||
docalias = DocAlias.objects.create(name='draft-imaginary-irtf-submission',document=doc)
|
||||
doc = Document.objects.create(name='draft-imaginary-irtf-submission', type_id='draft')
|
||||
docalias = DocAlias.objects.create(name=doc.name, document=doc)
|
||||
doc.stream = StreamName.objects.get(slug='irtf')
|
||||
doc.save()
|
||||
crdoc = Document.objects.create(name='conflict-review-imaginary-irtf-submission',type_id='conflrev',rev='00',notify="fsm@ietf.org")
|
||||
DocAlias.objects.create( name='conflict-review-imaginary-irtf-submission',document=crdoc)
|
||||
crdoc.set_state(State.objects.get(used=True, name='Needs Shepherd',type__slug='conflrev'))
|
||||
crdoc.save()
|
||||
crdoc = Document.objects.create(name='conflict-review-imaginary-irtf-submission', type_id='conflrev', rev='00', notify="fsm@ietf.org")
|
||||
DocAlias.objects.create(name=crdoc.name, document=crdoc)
|
||||
crdoc.set_state(State.objects.get(name='Needs Shepherd', type__slug='conflrev'))
|
||||
crdoc.relateddocument_set.create(target=docalias,relationship_id='conflrev')
|
||||
|
||||
# A status change mid review
|
||||
|
|
|
@ -4,7 +4,6 @@ from django.shortcuts import get_object_or_404, render_to_response
|
|||
from django.template import RequestContext
|
||||
from django.http import HttpResponseForbidden, Http404
|
||||
|
||||
from ietf.idrfc.views_search import SearchForm, search_query
|
||||
from ietf.wgchairs.forms import (RemoveDelegateForm, add_form_factory,
|
||||
workflow_form_factory, TransitionFormSet,
|
||||
WriteUpEditForm, assign_shepherd)
|
||||
|
@ -186,15 +185,7 @@ def wg_shepherd_documents(request, acronym):
|
|||
return HttpResponseForbidden('You have no permission to access this view')
|
||||
current_person = get_person_for_user(user)
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
base_qs = InternetDraft.objects.filter(group=wg, states__type="draft", states__slug="active").select_related("status").order_by('title')
|
||||
else:
|
||||
form = SearchForm({'by': 'group', 'group': str(wg.group_acronym.acronym),
|
||||
'activeDrafts': 'on'})
|
||||
if not form.is_valid():
|
||||
raise ValueError("form did not validate")
|
||||
(docs, meta) = search_query(form.cleaned_data)
|
||||
base_qs = InternetDraft.objects.filter(pk__in=[i.id._draft.pk for i in docs if i.id]).select_related('status')
|
||||
base_qs = InternetDraft.objects.filter(group=wg, states__type="draft", states__slug="active").select_related("status").order_by('title')
|
||||
documents_no_shepherd = base_qs.filter(shepherd=None)
|
||||
documents_my = base_qs.filter(shepherd=current_person)
|
||||
documents_other = base_qs.exclude(shepherd=None).exclude(shepherd__pk__in=[current_person.pk, 0])
|
||||
|
|
|
@ -82,13 +82,16 @@ body { margin: 0; }
|
|||
.ietf-stream .entry-title .entry-date { float: right; }
|
||||
.ietf-stream .entry-comment { background: #eeeeee; margin: 1em 0px; padding: 1em; }
|
||||
|
||||
.search_form_box {width: 99.5%; margin-top:8px; padding:4px; margin-bottom:1em; padding-left:8px;}
|
||||
.search-form-box { width: 99.5%; margin-top:8px; padding:4px; margin-bottom:1em; padding-left:8px; }
|
||||
form#search_form { padding-top: 4px; padding-bottom: 4px; }
|
||||
#search_form .submit { padding-top: 0.5em; }
|
||||
#search_form .submit .button { padding: 0.2em 0.5em; border: 1px solid #999; }
|
||||
#search_form input { padding: 0; padding-left: 2px; border: 1px solid #89d;}
|
||||
#search_form input.radio { padding-left: 0; border: 0; }
|
||||
#search_form input.radio { padding-left: 0; border: 0; }
|
||||
#search_form select { border: 1px solid #89d; }
|
||||
#search_form div.search_field { margin-top:2px; clear:both;}
|
||||
#search_form label { width: 170px; float: left; }
|
||||
#search_form .search_field > label { width: 170px; float: left; }
|
||||
#search_form #search_advanced { margin-top: 1em; }
|
||||
/* checkboxes for document types */
|
||||
#search_form table#search_types { border-collapse:collapse;}
|
||||
#search_form #search_types td { padding:0; }
|
||||
|
@ -106,12 +109,13 @@ table.ietf-table { border-collapse:collapse; border:1px solid #7f7f7f; }
|
|||
.ietf-table tr.evenrow { background-color: #EDF5FF; }
|
||||
.ietf-table tr.oddrow { background-color: white; }
|
||||
.ietf-table td { border-right: 1px solid #cbcbcb; padding:3px 6px; vertical-align: top; }
|
||||
.ietf-table th { color:white; background: #2647A0; text-align:left; padding:3px 6px; border-right: 1px solid #7f7f7f; }
|
||||
.ietf-table th { color: #fff; background: #2647A0; text-align: left; padding:3px 6px; border-right: 1px solid #7f7f7f; }
|
||||
|
||||
.ietf-doctable tr.header { border-top: 1px solid #7f7f7f; border-bottom: 1px solid #7f7f7f; border-left: 1px solid white; border-right:2px solid white;}
|
||||
.ietf-doctable tr.header td {padding: 6px 6px; font-weight: bold; }
|
||||
.ietf-doctable table { max-width: 1200px; }
|
||||
.ietf-doctable th { cursor: pointer }
|
||||
.ietf-doctable th { cursor: pointer; white-space: nowrap; }
|
||||
.ietf-doctable th img { border-style: none; vertical-align: top; }
|
||||
.ietf-doctable th.doc, .ietf-doctable td.doc { min-width:20em; max-width: 35em; }
|
||||
.ietf-doctable th.title, .ietf-doctable td.title { min-width: 20em; max-width: 35em; }
|
||||
.ietf-doctable th.date, .ietf-doctable td.date { white-space:nowrap; min-width: 6em;}
|
||||
|
@ -209,7 +213,13 @@ table.milestones .doc { display: block; padding-left: 1em; }
|
|||
|
||||
.stream-state .milestone { display: inline-block; font-size: smaller; background-color: #d5dde6; padding: 0 0.2em; margin-left: 0.3em; }
|
||||
|
||||
.button { display: inline-block; font-weight: normal; background: #eee; border: 1px solid #bbb; border-radius: 3px; color: #333; padding: 2px 8px; text-align: center; text-decoration: none; outline: none; transition-duration: 0.2s; cursor: pointer }
|
||||
.button:hover { background: #ddd; color: #222; }
|
||||
.button:active { background: #ccc; color: #000; }
|
||||
|
||||
.button, .button:hover:disabled {
|
||||
display: inline-block; padding: 4px 12px; margin-right: 0.3em;
|
||||
color: #222; font-weight: normal; text-align: center; text-decoration: none; outline: none; cursor: pointer;
|
||||
background: #eee; background: linear-gradient(#fff, #e0e0e0); background: -webkit-linear-gradient(#fff, #e0e0e0); background: -moz-linear-gradient(#fff, #e0e0e0);
|
||||
border: 1px solid #666; border-radius: 3px;
|
||||
transition-duration: 0.2s;
|
||||
}
|
||||
.button:hover { color: #111; background: #ddd; background: linear-gradient(#eee, #ccc); background: -webkit-linear-gradient(#eee, #ccc); background: -moz-linear-gradient(#eee, #ccc); }
|
||||
.button:active { color: #000; background: #ccc; }
|
||||
.button:disabled, .button:hover:disabled { color: #999; cursor: default; }
|
||||
|
|
|
@ -3,26 +3,46 @@
|
|||
#metatable tr { vertical-align: top; }
|
||||
#metatable tr:first-child td:first-child { width: 15em; }
|
||||
|
||||
.markup_draft pre { line-height: 1.2em; margin: 0; }
|
||||
.m_hdr, .m_ftr { color: #808080; }
|
||||
.m_ftr { border-bottom: 1px solid #a0a0a0; }
|
||||
.m_h { font-family: arial; font-weight:bold;}
|
||||
.stream-tags { font-style: italic; }
|
||||
|
||||
.document-markup pre { line-height: 1.2em; margin: 0; }
|
||||
.document-markup .m_hdr, .m_ftr { color: #808080; }
|
||||
.document-markup .m_ftr { border-bottom: 1px solid #a0a0a0; }
|
||||
.document-markup .m_h { font-family: arial; font-weight:bold;}
|
||||
|
||||
.snapshots { margin: 0.5em 0; }
|
||||
.snapshots .revisions a:last-child { font-weight: bold; }
|
||||
|
||||
.metabox .actions a { display: inline-block; margin-right: 0.4em; }
|
||||
.metabox .links { margin-bottom: 0.2em; }
|
||||
.metabox .actions { margin-top: 0.5em; }
|
||||
.metabox .ballot-summary { font-style: italic; }
|
||||
.metabox .telechat { margin-top: 0.2em; }
|
||||
|
||||
.diffTool { padding: 8px 4px; margin: 8px 0;}
|
||||
.diffTool h2 { margin-top:0;margin-bottom:4px; }
|
||||
.diffTool label { display: inline-block; width: 3em; padding: 0 0.5em; }
|
||||
.diffTool form { margin: 0; }
|
||||
.diff-tool { padding: 8px 4px; margin: 8px 0;}
|
||||
.diff-tool h2 { margin-top:0;margin-bottom:4px; }
|
||||
.diff-tool label { display: inline-block; width: 3em; padding: 0 0.5em; }
|
||||
.diff-tool form { margin: 0; }
|
||||
|
||||
.history-actions { margin-bottom: 1em; padding-left: 1px; }
|
||||
|
||||
.writeup pre.editable { background-color: #efefff; min-height: 3em; }
|
||||
.writeup a.edit { float: right; }
|
||||
.writeup pre.editable { background-color: #efefff; min-height: 3em; padding: 4px; }
|
||||
.writeup a.edit { float: right; margin: 4px; }
|
||||
|
||||
a.editlink {
|
||||
background-image: url("/images/pencil.png");
|
||||
background-size: 10px;
|
||||
background-position: right top;
|
||||
background-attachment: scroll;
|
||||
background-repeat: no-repeat;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
a.editlink:link {text-decoration:none; color:inherit;}
|
||||
a.editlink:visited {text-decoration:none; color:inherit;}
|
||||
a.editlink:hover {text-decoration:underline;}
|
||||
a.editlink:active {text-decoration:underline;}
|
||||
|
||||
h3 a.edit { font-weight: normal; font-size: 13px; display: inline-block; margin-left: 0.5em;}
|
||||
|
||||
h4 { margin-bottom: 0; }
|
||||
h4 + p { margin-top: 0; max-width: 400px; }
|
||||
|
|
|
@ -1,86 +1,77 @@
|
|||
$(function () {
|
||||
var form = jQuery("#search_form");
|
||||
|
||||
form.find(".search_field input[name=by]").parents("label").click(changeBy);
|
||||
|
||||
form.find(".search_field").find("input,select")
|
||||
.change(toggleSubmit).click(toggleSubmit).keyup(toggleSubmit);
|
||||
|
||||
form.find(".toggle_advanced").click(function () {
|
||||
togglePlusMinus("search_advanced");
|
||||
form.find('.search_field input[type="radio"]').attr("checked", false);
|
||||
changeBy();
|
||||
});
|
||||
|
||||
changeBy();
|
||||
|
||||
// we want to disable our submit button if we have no search text,
|
||||
// we want to disable our submit button if we have no search text,
|
||||
// and we have no advanced options selected
|
||||
function toggleSubmit() {
|
||||
var button = document.getElementById("id_search_submit");
|
||||
var by = findCheckedSearchBy();
|
||||
var value = findSearchByValue(by);
|
||||
var text = document.getElementById("id_name");
|
||||
if ((value == "") && (text.value == "")) {
|
||||
button.disabled = true;
|
||||
} else {
|
||||
button.disabled = false;
|
||||
}
|
||||
var nameSearch = $.trim($("#id_name").val());
|
||||
|
||||
var noAdvanced = true;
|
||||
|
||||
var by = form.find("input[name=by]:checked");
|
||||
if (by.length > 0)
|
||||
by.closest(".search_field").find("input,select").not("input[name=by]").each(function () {
|
||||
if ($.trim(this.value))
|
||||
noAdvanced = false;
|
||||
});
|
||||
|
||||
form.find("input[type=submit]").get(0).disabled = !nameSearch && noAdvanced;
|
||||
}
|
||||
|
||||
function togglePlusMinus(id) {
|
||||
var el = document.getElementById(id);
|
||||
var imgEl = document.getElementById(id+"-img");
|
||||
if (el.style.display == 'none') {
|
||||
el.style.display = 'block';
|
||||
imgEl.src = "/images/minus.png";
|
||||
function togglePlusMinus(toggler, toggled) {
|
||||
var img = toggler.find("img").get(0);
|
||||
if (toggled.is(":hidden")) {
|
||||
toggled.show();
|
||||
img.src = "/images/minus.png";
|
||||
} else {
|
||||
el.style.display = 'none';
|
||||
imgEl.src = "/images/plus.png";
|
||||
toggled.hide();
|
||||
img.src = "/images/plus.png";
|
||||
}
|
||||
}
|
||||
|
||||
function findCheckedSearchBy() {
|
||||
var by='';
|
||||
var f = document.search_form;
|
||||
for (var i = 0; i < f.by.length; i++) {
|
||||
if (f.by[i].checked) {
|
||||
by = f.by[i].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return by;
|
||||
}
|
||||
function updateBy() {
|
||||
form.find("input[name=by]:checked").closest(".search_field").find("input,select").not("input[name=by]").each(function () {
|
||||
this.disabled = false;
|
||||
});
|
||||
|
||||
function findSearchByValue(by) {
|
||||
if (by == 'author') { return document.getElementById("id_author").value; }
|
||||
if (by == 'group') { return document.getElementById("id_group").value; }
|
||||
if (by == 'area') { return document.getElementById("id_area").value; }
|
||||
if (by == 'ad') { return document.getElementById("id_ad").value; }
|
||||
if (by == 'state') {
|
||||
// state might be state...
|
||||
state_value = document.getElementById("id_state").value;
|
||||
if (state_value) { return state_value; }
|
||||
// ...or sub-state
|
||||
return document.getElementById("id_subState").value;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function changeBy() {
|
||||
var by = findCheckedSearchBy();
|
||||
var f = document.search_form;
|
||||
f.author.disabled=true;
|
||||
f.group.disabled=true;
|
||||
f.area.disabled=true;
|
||||
f.ad.disabled=true;
|
||||
f.state.disabled=true; f.subState.disabled=true;
|
||||
if (by=='author') { f.author.disabled=false;}
|
||||
if (by=='group') { f.group.disabled=false;}
|
||||
if (by=='area') { f.area.disabled=false;}
|
||||
if (by=='ad') { f.ad.disabled=false; }
|
||||
if (by=='state') { f.state.disabled=false; f.subState.disabled=false; }
|
||||
form.find("input[name=by]").not(":checked").closest(".search_field").find("input,select").not("input[name=by]").each(function () {
|
||||
this.disabled = true;
|
||||
});
|
||||
|
||||
toggleSubmit();
|
||||
}
|
||||
|
||||
form.find(".search_field input[name=by]").closest("label").click(updateBy);
|
||||
|
||||
form.find(".search_field input,select")
|
||||
.change(toggleSubmit).click(toggleSubmit).keyup(toggleSubmit);
|
||||
|
||||
form.find(".toggle_advanced").click(function () {
|
||||
var advanced = $(this).next();
|
||||
advanced.find('.search_field input[type="radio"]').attr("checked", false);
|
||||
togglePlusMinus($(this), advanced);
|
||||
updateBy();
|
||||
});
|
||||
|
||||
updateBy();
|
||||
|
||||
$("#search_results th").click(function (e) {
|
||||
window.location = $(this).find("a").attr("href");
|
||||
})
|
||||
|
||||
$('#search_results .addtolist a').click(function(e) {
|
||||
e.preventDefault();
|
||||
var trigger = $(this);
|
||||
$.ajax({
|
||||
url: trigger.attr('href'),
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
dataType: 'json',
|
||||
success: function(response){
|
||||
if (response.success) {
|
||||
trigger.replaceWith('added');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue