Revamp and clean up submit models:
- Rename IdSubmissionDetail to Submission - Rename various submission fields to correspond to the conventions in the new schema - Use a name model for the states instead of IdSubmissionStatus - Drop the TempIdAuthor model which is based on splitting up author names - Add a simple textual SubmissionEvent for tracking events in the lifetime of a submission - Delete a bunch of obsolete fields - Make sure all submission have an access key so we can depend on it - Add state for when approval is needed from previous authors A couple of migrations take care of transforming the IdSubmissionDetail and moving data over/cleaning it up. Also revamp the submit view code: - Make form code do validation/cleaning only so there's a clear separation of concerns - Reduce uses of inheritance that made the code hard to follow - forms now don't inherit from each other, views don't call each other but instead reuse common utilities, templates share CSS/utilities instead of relying on inheritance - Move email rendering/sending to separate file - Drop the in-grown terminology use (auto post vs. manual posts) - Make the status page explain who is emailed for what purpose - Add history table with recorded events - Make the status page handle its post actions by itself instead of duplicating most of the setup logic in a number of simple views - Fix a couple of minor bugs and handle some edge cases better - Expand tests with a couple of more cases Possibly the submit tool could still use more help text added to explain the process, ideally what's explained in the tool instructions page should be inlined or self-evident. - Legacy-Id: 6714
This commit is contained in:
parent
fd01ddd215
commit
ecf68dbb05
|
@ -31,7 +31,7 @@ from django.conf import settings
|
|||
|
||||
from ietf.utils.path import path as Path
|
||||
|
||||
from ietf.submit.models import IdSubmissionDetail
|
||||
from ietf.submit.models import Submission
|
||||
from ietf.doc.models import Document
|
||||
|
||||
|
||||
|
@ -56,11 +56,11 @@ from_email = settings.IDSUBMIT_FROM_EMAIL
|
|||
if "<" in from_email:
|
||||
from_email = from_email.split("<")[1].split(">")[0]
|
||||
|
||||
submission = IdSubmissionDetail.objects.filter(filename=draft).order_by('-pk')[0]
|
||||
submission = Submission.objects.filter(name=draft).order_by('-pk')[0]
|
||||
document = Document.objects.get(name=draft)
|
||||
emails = [ author.address for author in document.authors.all() ]
|
||||
|
||||
file = Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.revision))
|
||||
file = Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.rev))
|
||||
|
||||
upload_time = time.localtime(file.mtime)
|
||||
timestr1 = time.strftime("%b %d %H:%M", upload_time)
|
||||
|
@ -87,4 +87,4 @@ for log in logfiles:
|
|||
for qi in queue_ids:
|
||||
if qi in line:
|
||||
sys.stdout.write(line)
|
||||
|
||||
|
||||
|
|
|
@ -713,6 +713,101 @@
|
|||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "uploaded",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 1,
|
||||
"next_states": [
|
||||
"auth",
|
||||
"aut-appr",
|
||||
"grp-appr",
|
||||
"manual",
|
||||
"cancel"
|
||||
],
|
||||
"used": true,
|
||||
"name": "Uploaded",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "auth",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 2,
|
||||
"next_states": [
|
||||
"cancel",
|
||||
"posted"
|
||||
],
|
||||
"used": true,
|
||||
"name": "Awaiting Submitter Authentication",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "aut-appr",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 3,
|
||||
"next_states": [
|
||||
"cancel",
|
||||
"posted"
|
||||
],
|
||||
"used": true,
|
||||
"name": "Awaiting Approval from Previous Version Authors'",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "grp-appr",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 4,
|
||||
"next_states": [
|
||||
"cancel",
|
||||
"posted"
|
||||
],
|
||||
"used": true,
|
||||
"name": "Awaiting Initial Version Approval",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "manual",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 5,
|
||||
"next_states": [
|
||||
"cancel",
|
||||
"posted"
|
||||
],
|
||||
"used": true,
|
||||
"name": "Awaiting Manual Post",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "cancel",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 6,
|
||||
"next_states": [],
|
||||
"used": true,
|
||||
"name": "Cancelled",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "posted",
|
||||
"model": "name.draftsubmissionstatename",
|
||||
"fields": {
|
||||
"order": 7,
|
||||
"next_states": [],
|
||||
"used": true,
|
||||
"name": "Posted",
|
||||
"desc": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": "comment",
|
||||
"model": "name.feedbacktype",
|
||||
|
|
214
ietf/name/migrations/0016_auto__add_draftsubmissionstatename.py
Normal file
214
ietf/name/migrations/0016_auto__add_draftsubmissionstatename.py
Normal file
|
@ -0,0 +1,214 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'DraftSubmissionStateName'
|
||||
db.create_table('name_draftsubmissionstatename', (
|
||||
('slug', self.gf('django.db.models.fields.CharField')(max_length=8, primary_key=True)),
|
||||
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('desc', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('used', self.gf('django.db.models.fields.BooleanField')(default=True)),
|
||||
('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
|
||||
))
|
||||
db.send_create_signal('name', ['DraftSubmissionStateName'])
|
||||
|
||||
# Adding M2M table for field next_states on 'DraftSubmissionStateName'
|
||||
db.create_table('name_draftsubmissionstatename_next_states', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('from_draftsubmissionstatename', models.ForeignKey(orm['name.draftsubmissionstatename'], null=False)),
|
||||
('to_draftsubmissionstatename', models.ForeignKey(orm['name.draftsubmissionstatename'], null=False))
|
||||
))
|
||||
db.create_unique('name_draftsubmissionstatename_next_states', ['from_draftsubmissionstatename_id', 'to_draftsubmissionstatename_id'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting model 'DraftSubmissionStateName'
|
||||
db.delete_table('name_draftsubmissionstatename')
|
||||
|
||||
# Removing M2M table for field next_states on 'DraftSubmissionStateName'
|
||||
db.delete_table('name_draftsubmissionstatename_next_states')
|
||||
|
||||
|
||||
models = {
|
||||
'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.constraintname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'ConstraintName'},
|
||||
'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'}),
|
||||
'penalty': ('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.dbtemplatetypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DBTemplateTypeName'},
|
||||
'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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'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.draftsubmissionstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': '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['name.DraftSubmissionStateName']"}),
|
||||
'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.feedbacktype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'FeedbackType'},
|
||||
'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.groupmilestonestatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
|
||||
'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.liaisonstatementpurposename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'LiaisonStatementPurposeName'},
|
||||
'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.meetingtypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'MeetingTypeName'},
|
||||
'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.nomineepositionstate': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'NomineePositionState'},
|
||||
'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.rolename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
|
||||
'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.sessionstatusname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'SessionStatusName'},
|
||||
'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'})
|
||||
},
|
||||
'name.timeslottypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'TimeSlotTypeName'},
|
||||
'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'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['name']
|
204
ietf/name/migrations/0017_populate_draftsubmissionstate.py
Normal file
204
ietf/name/migrations/0017_populate_draftsubmissionstate.py
Normal file
|
@ -0,0 +1,204 @@
|
|||
# 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):
|
||||
uploaded, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="uploaded", order=1, name="Uploaded")
|
||||
submitter, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="auth", order=2, name="Awaiting Submitter Authentication")
|
||||
author_approval, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="aut-appr", order=3, name="Awaiting Approval from Previous Version Authors'")
|
||||
group_approval, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="grp-appr", order=4, name="Awaiting Initial Version Approval")
|
||||
manual_post, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="manual", order=5, name="Awaiting Manual Post")
|
||||
cancel, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="cancel", order=6, name="Cancelled")
|
||||
posted, _ = orm.DraftSubmissionStateName.objects.get_or_create(slug="posted", order=7, name="Posted")
|
||||
|
||||
uploaded.next_states = [submitter, author_approval, group_approval, manual_post, cancel]
|
||||
submitter.next_states = [cancel, posted]
|
||||
author_approval.next_states = [cancel, posted]
|
||||
group_approval.next_states = [cancel, posted]
|
||||
manual_post.next_states = [cancel, posted]
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
|
||||
models = {
|
||||
'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.constraintname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'ConstraintName'},
|
||||
'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'}),
|
||||
'penalty': ('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.dbtemplatetypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DBTemplateTypeName'},
|
||||
'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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'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.draftsubmissionstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': '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['name.DraftSubmissionStateName']"}),
|
||||
'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.feedbacktype': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'FeedbackType'},
|
||||
'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.groupmilestonestatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
|
||||
'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.liaisonstatementpurposename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'LiaisonStatementPurposeName'},
|
||||
'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.meetingtypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'MeetingTypeName'},
|
||||
'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.nomineepositionstate': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'NomineePositionState'},
|
||||
'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.rolename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
|
||||
'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.sessionstatusname': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'SessionStatusName'},
|
||||
'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'})
|
||||
},
|
||||
'name.timeslottypename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'TimeSlotTypeName'},
|
||||
'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'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['name']
|
|
@ -66,3 +66,8 @@ class FeedbackType(NameModel):
|
|||
"""Type of feedback: questionnaires, nominations, comments"""
|
||||
class DBTemplateTypeName(NameModel):
|
||||
"""reStructuredText, Plain, Django"""
|
||||
class DraftSubmissionStateName(NameModel):
|
||||
"""Uploaded, Awaiting Submitter Authentication, Awaiting Approval from
|
||||
Previous Version Authors, Awaiting Initial Version Approval, Awaiting
|
||||
Manual Post, Cancelled, Posted"""
|
||||
next_states = models.ManyToManyField('DraftSubmissionStateName', related_name="previous_states", blank=True)
|
||||
|
|
|
@ -17,7 +17,7 @@ from ietf.meeting.models import Meeting
|
|||
from ietf.name.models import StreamName
|
||||
from ietf.doc.models import Document, DocumentAuthor
|
||||
from ietf.doc.utils import augment_with_start_time
|
||||
from ietf.submit.models import IdSubmissionDetail, Preapproval
|
||||
from ietf.submit.models import Submission, Preapproval, DraftSubmissionStateName, SubmissionEvent
|
||||
from ietf.utils.draft import Draft
|
||||
from ietf.secr.proceedings.proc_utils import get_progress_stats
|
||||
from ietf.secr.sreq.views import get_meeting
|
||||
|
@ -107,7 +107,7 @@ def process_files(request,draft):
|
|||
the basename, revision number and a list of file types. Basename and revision
|
||||
are assumed to be the same for all because this is part of the validation process.
|
||||
|
||||
It also creates the IdSubmissionDetail record WITHOUT saving, and places it in the
|
||||
It also creates the Submission record WITHOUT saving, and places it in the
|
||||
session for saving in the final action step.
|
||||
'''
|
||||
files = request.FILES
|
||||
|
@ -124,29 +124,37 @@ def process_files(request,draft):
|
|||
wrapper = Draft(file.read(),file.name)
|
||||
handle_uploaded_file(file)
|
||||
|
||||
# create IdSubmissionDetail record, leaved unsaved
|
||||
idsub = IdSubmissionDetail(
|
||||
id_document_name=draft.title,
|
||||
filename=basename,
|
||||
revision=revision,
|
||||
txt_page_count=draft.pages,
|
||||
filesize=txt_size,
|
||||
creation_date=wrapper.get_creation_date(),
|
||||
# create Submission record, leaved unsaved
|
||||
idsub = Submission(
|
||||
name=basename,
|
||||
title=draft.title,
|
||||
rev=revision,
|
||||
pages=draft.pages,
|
||||
file_size=txt_size,
|
||||
document_date=wrapper.get_creation_date(),
|
||||
submission_date=datetime.date.today(),
|
||||
idnits_message='idnits bypassed by manual posting',
|
||||
temp_id_document_tag=None,
|
||||
group_acronym_id=draft.group.id,
|
||||
group_id=draft.group.id,
|
||||
remote_ip=request.META['REMOTE_ADDR'],
|
||||
first_two_pages=''.join(wrapper.pages[:2]),
|
||||
status_id=-2,
|
||||
state=DraftSubmissionStateName.objects.get(slug="posted"),
|
||||
abstract=draft.abstract,
|
||||
file_type=','.join(file_type_list),
|
||||
man_posted_date=datetime.date.today(),
|
||||
man_posted_by=request.user.get_profile())
|
||||
file_types=','.join(file_type_list),
|
||||
)
|
||||
request.session['idsub'] = idsub
|
||||
|
||||
return (filename,revision,file_type_list)
|
||||
|
||||
def post_submission(request):
|
||||
submission = request.session['idsub']
|
||||
submission.save()
|
||||
|
||||
SubmissionEvent.objects.create(
|
||||
submission=submission,
|
||||
by=request.user.person,
|
||||
desc="Submitted and posted manually")
|
||||
|
||||
|
||||
def promote_files(draft, types):
|
||||
'''
|
||||
This function takes one argument, a draft object. It then moves the draft files from
|
||||
|
@ -308,8 +316,8 @@ def do_revision(draft, request):
|
|||
promote_files(new_draft, request.session['file_type'])
|
||||
|
||||
# save the submission record
|
||||
request.session['idsub'].save()
|
||||
|
||||
post_submission(request)
|
||||
|
||||
# send announcement if we are in IESG process
|
||||
if new_draft.get_state('draft-iesg'):
|
||||
announcement_from_form(request.session['email'],by=request.user.get_profile())
|
||||
|
@ -356,8 +364,8 @@ def do_update(draft,request):
|
|||
promote_files(new_draft, request.session['file_type'])
|
||||
|
||||
# save the submission record
|
||||
request.session['idsub'].save()
|
||||
|
||||
post_submission(request)
|
||||
|
||||
# send announcement
|
||||
announcement_from_form(request.session['email'],by=request.user.get_profile())
|
||||
|
||||
|
@ -581,7 +589,7 @@ def add(request):
|
|||
promote_files(draft, file_type_list)
|
||||
|
||||
# save the submission record
|
||||
request.session['idsub'].save()
|
||||
post_submission(request)
|
||||
|
||||
request.session['action'] = 'add'
|
||||
|
||||
|
|
|
@ -296,12 +296,6 @@ LIAISON_UNIVERSAL_FROM = 'Liaison Statement Management Tool <lsmt@' + IETF_DOMAI
|
|||
LIAISON_ATTACH_PATH = '/a/www/ietf-datatracker/documents/LIAISON/'
|
||||
LIAISON_ATTACH_URL = '/documents/LIAISON/'
|
||||
|
||||
# ID Submission Tool settings
|
||||
IDSUBMIT_FROM_EMAIL = 'IETF I-D Submission Tool <idsubmission@ietf.org>'
|
||||
IDSUBMIT_TO_EMAIL = 'internet-drafts@ietf.org'
|
||||
IDSUBMIT_ANNOUNCE_FROM_EMAIL = 'internet-drafts@ietf.org'
|
||||
IDSUBMIT_ANNOUNCE_LIST_EMAIL = 'i-d-announce@ietf.org'
|
||||
|
||||
# NomCom Tool settings
|
||||
ROLODEX_URL = ""
|
||||
NOMCOM_PUBLIC_KEYS_DIR = '/a/www/nomcom/public_keys/'
|
||||
|
@ -312,8 +306,13 @@ DAYS_TO_EXPIRE_NOMINATION_LINK = ''
|
|||
DEFAULT_FEEDBACK_TYPE = 'offtopic'
|
||||
NOMINEE_FEEDBACK_TYPES = ['comment', 'questio', 'nomina']
|
||||
|
||||
# Days from meeting to cut off dates on submit
|
||||
FIRST_CUTOFF_DAYS = 19
|
||||
# ID Submission Tool settings
|
||||
IDSUBMIT_FROM_EMAIL = 'IETF I-D Submission Tool <idsubmission@ietf.org>'
|
||||
IDSUBMIT_TO_EMAIL = 'internet-drafts@ietf.org'
|
||||
IDSUBMIT_ANNOUNCE_FROM_EMAIL = 'internet-drafts@ietf.org'
|
||||
IDSUBMIT_ANNOUNCE_LIST_EMAIL = 'i-d-announce@ietf.org'
|
||||
|
||||
FIRST_CUTOFF_DAYS = 19 # Days from meeting to cut off dates on submit
|
||||
SECOND_CUTOFF_DAYS = 12
|
||||
CUTOFF_HOUR = 00 # midnight UTC
|
||||
SUBMISSION_START_DAYS = -90
|
||||
|
@ -327,18 +326,16 @@ IDSUBMIT_STAGING_PATH = '/a/www/www6s/staging/'
|
|||
IDSUBMIT_STAGING_URL = 'http://www.ietf.org/staging/'
|
||||
IDSUBMIT_IDNITS_BINARY = '/a/www/ietf-datatracker/scripts/idnits'
|
||||
|
||||
MAX_PLAIN_DRAFT_SIZE = 6291456 # Max size of the txt draft in bytes
|
||||
IDSUBMIT_MAX_PLAIN_DRAFT_SIZE = 6291456 # Max size of the txt draft in bytes
|
||||
|
||||
# DOS THRESHOLDS PER DAY (Sizes are in MB)
|
||||
MAX_SAME_DRAFT_NAME = 20
|
||||
MAX_SAME_DRAFT_NAME_SIZE = 50
|
||||
MAX_SAME_SUBMITTER = 50
|
||||
MAX_SAME_SUBMITTER_SIZE = 150
|
||||
MAX_SAME_WG_DRAFT = 150
|
||||
MAX_SAME_WG_DRAFT_SIZE = 450
|
||||
MAX_DAILY_SUBMISSION = 1000
|
||||
MAX_DAILY_SUBMISSION_SIZE = 2000
|
||||
# End of ID Submission Tool settings
|
||||
IDSUBMIT_MAX_DAILY_SAME_DRAFT_NAME = 20
|
||||
IDSUBMIT_MAX_DAILY_SAME_DRAFT_NAME_SIZE = 50 # in MB
|
||||
IDSUBMIT_MAX_DAILY_SAME_SUBMITTER = 50
|
||||
IDSUBMIT_MAX_DAILY_SAME_SUBMITTER_SIZE = 150 # in MB
|
||||
IDSUBMIT_MAX_DAILY_SAME_GROUP = 150
|
||||
IDSUBMIT_MAX_DAILY_SAME_GROUP_SIZE = 450 # in MB
|
||||
IDSUBMIT_MAX_DAILY_SUBMISSIONS = 1000
|
||||
IDSUBMIT_MAX_DAILY_SUBMISSIONS_SIZE = 2000 # in MB
|
||||
|
||||
# Account settings
|
||||
DAYS_TO_EXPIRE_REGISTRATION_LINK = 3
|
||||
|
|
|
@ -4,37 +4,29 @@ from django.utils.safestring import mark_safe
|
|||
|
||||
from ietf.submit.models import *
|
||||
|
||||
class IdSubmissionStatusAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
admin.site.register(IdSubmissionStatus, IdSubmissionStatusAdmin)
|
||||
|
||||
class IdSubmissionDetailAdmin(admin.ModelAdmin):
|
||||
list_display = ['submission_id', 'draft_link', 'status_link', 'submission_date', 'last_updated_date',]
|
||||
ordering = [ '-submission_date' ]
|
||||
search_fields = ['filename', ]
|
||||
raw_id_fields = ['group_acronym']
|
||||
class SubmissionAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'draft_link', 'status_link', 'submission_date',]
|
||||
ordering = [ '-id' ]
|
||||
search_fields = ['name', ]
|
||||
raw_id_fields = ['group']
|
||||
|
||||
def status_link(self, instance):
|
||||
url = urlreverse('draft_status_by_hash',
|
||||
kwargs=dict(submission_id=instance.submission_id,
|
||||
submission_hash=instance.get_hash()))
|
||||
return '<a href="%s">%s</a>' % (url, instance.status)
|
||||
url = urlreverse('submit_submission_status_by_hash',
|
||||
kwargs=dict(submission_id=instance.pk,
|
||||
access_key=instance.access_key))
|
||||
return '<a href="%s">%s</a>' % (url, instance.state)
|
||||
status_link.allow_tags = True
|
||||
|
||||
def draft_link(self, instance):
|
||||
if instance.status_id in (-1, -2):
|
||||
return '<a href="http://www.ietf.org/id/%s-%s.txt">%s</a>' % (instance.filename, instance.revision, instance.filename)
|
||||
if instance.state_id == "posted":
|
||||
return '<a href="http://www.ietf.org/id/%s-%s.txt">%s</a>' % (instance.name, instance.rev, instance.name)
|
||||
else:
|
||||
return instance.filename
|
||||
return instance.name
|
||||
draft_link.allow_tags = True
|
||||
|
||||
admin.site.register(IdSubmissionDetail, IdSubmissionDetailAdmin)
|
||||
admin.site.register(Submission, SubmissionAdmin)
|
||||
|
||||
class PreapprovalAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
admin.site.register(Preapproval, PreapprovalAdmin)
|
||||
|
||||
class TempIdAuthorsAdmin(admin.ModelAdmin):
|
||||
ordering = ["-id"]
|
||||
admin.site.register(TempIdAuthors, TempIdAuthorsAdmin)
|
||||
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<django-objects version="1.0">
|
||||
<object pk="-4" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Cancelled</field>
|
||||
</object>
|
||||
<object pk="-3" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Dead</field>
|
||||
</object>
|
||||
<object pk="-2" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Posted by the Secretariat</field>
|
||||
</object>
|
||||
<object pk="-1" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Posted</field>
|
||||
</object>
|
||||
<object pk="0" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Ready To Post</field>
|
||||
</object>
|
||||
<object pk="1" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Uploaded</field>
|
||||
</object>
|
||||
<object pk="2" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">ID NITS Passed</field>
|
||||
</object>
|
||||
<object pk="3" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Initial Version Approval Required</field>
|
||||
</object>
|
||||
<object pk="4" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Submitter Authentication Required</field>
|
||||
</object>
|
||||
<object pk="5" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Manual Post Requested</field>
|
||||
</object>
|
||||
<object pk="6" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">External Meta-Data Required</field>
|
||||
</object>
|
||||
<object pk="7" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Internal Database Has Been Updated</field>
|
||||
</object>
|
||||
<object pk="8" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">ID Announcement Scheduled</field>
|
||||
</object>
|
||||
<object pk="9" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">ID Tracker Notification Scheduled</field>
|
||||
</object>
|
||||
<object pk="10" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Initial Version Approval Requested</field>
|
||||
</object>
|
||||
<object pk="101" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Plain text version does not exist</field>
|
||||
</object>
|
||||
<object pk="102" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">File size is larger than 20 MB</field>
|
||||
</object>
|
||||
<object pk="103" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Duplicate Internet-Draft submission is currently in process.</field>
|
||||
</object>
|
||||
<object pk="104" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Simultaneous submission from the same IP address</field>
|
||||
</object>
|
||||
<object pk="105" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Auth key does not match</field>
|
||||
</object>
|
||||
<object pk="106" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - No such Internet-Draft is currently in process</field>
|
||||
</object>
|
||||
<object pk="107" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Draft is not in an appropriate status for the requested page</field>
|
||||
</object>
|
||||
<object pk="108" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Unknown Request</field>
|
||||
</object>
|
||||
<object pk="109" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Invalid Email Address</field>
|
||||
</object>
|
||||
<object pk="110" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Direct Access is prohibited</field>
|
||||
</object>
|
||||
<object pk="201" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Invalid version number</field>
|
||||
</object>
|
||||
<object pk="202" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - Invalid filename</field>
|
||||
</object>
|
||||
<object pk="203" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error - The document failed idnits verification</field>
|
||||
</object>
|
||||
<object pk="204" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Creation Date must be within 3 days of the submission date.</field>
|
||||
</object>
|
||||
<object pk="205" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Error – Not a valid submitter</field>
|
||||
</object>
|
||||
<object pk="206" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Incorrect Meta-Data</field>
|
||||
</object>
|
||||
<object pk="111" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">The document does not contain a legitimate filename that start with draft-*.</field>
|
||||
</object>
|
||||
<object pk="11" model="submit.idsubmissionstatus">
|
||||
<field type="CharField" name="status_value">Initial Version Approved</field>
|
||||
</object>
|
||||
</django-objects>
|
|
@ -1,14 +1,9 @@
|
|||
import hashlib
|
||||
import random
|
||||
import os
|
||||
import subprocess
|
||||
import datetime
|
||||
|
||||
from django import forms
|
||||
from django.core.validators import email_re
|
||||
from django.forms.formsets import formset_factory
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.html import mark_safe
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
|
||||
|
@ -17,44 +12,36 @@ import debug
|
|||
from ietf.group.models import Group, Role
|
||||
from ietf.doc.models import Document
|
||||
from ietf.meeting.models import Meeting
|
||||
from ietf.submit.models import IdSubmissionDetail, TempIdAuthors, Preapproval
|
||||
from ietf.submit.utils import MANUAL_POST_REQUESTED, UPLOADED, AWAITING_AUTHENTICATION, POSTED, POSTED_BY_SECRETARIAT, submission_confirmation_email_list
|
||||
from ietf.submit.models import Submission, Preapproval, DraftSubmissionStateName
|
||||
from ietf.submit.utils import validate_submission_rev, validate_submission_document_date
|
||||
from ietf.submit.parsers.pdf_parser import PDFParser
|
||||
from ietf.submit.parsers.plain_parser import PlainParser
|
||||
from ietf.submit.parsers.ps_parser import PSParser
|
||||
from ietf.submit.parsers.xml_parser import XMLParser
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.utils.draft import Draft
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.log import log
|
||||
|
||||
|
||||
class UploadForm(forms.Form):
|
||||
|
||||
txt = forms.FileField(label=u'.txt format', required=True)
|
||||
xml = forms.FileField(label=u'.xml format', required=False)
|
||||
pdf = forms.FileField(label=u'.pdf format', required=False)
|
||||
ps = forms.FileField(label=u'.ps format', required=False)
|
||||
|
||||
fieldsets = [('Upload a draft', ('txt', 'xml', 'pdf', 'ps'))]
|
||||
|
||||
class Media:
|
||||
css = {'all': ("/css/liaisons.css", )}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request=kwargs.pop('request', None)
|
||||
self.remote_ip=self.request.META.get('REMOTE_ADDR', None)
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UploadForm, self).__init__(*args, **kwargs)
|
||||
self.in_first_cut_off = False
|
||||
self.idnits_message = None
|
||||
self.shutdown = False
|
||||
self.draft = None
|
||||
self.filesize = None
|
||||
self.group = None
|
||||
self.file_type = []
|
||||
self.read_dates()
|
||||
|
||||
def read_dates(self):
|
||||
self.remote_ip = request.META.get('REMOTE_ADDR', None)
|
||||
|
||||
self.in_first_cut_off = False
|
||||
self.cutoff_warning = ""
|
||||
self.shutdown = False
|
||||
self.set_cutoff_warnings()
|
||||
|
||||
self.group = None
|
||||
self.parsed_draft = None
|
||||
|
||||
def set_cutoff_warnings(self):
|
||||
now = datetime.datetime.utcnow()
|
||||
first_cut_off = Meeting.get_first_cut_off()
|
||||
second_cut_off = Meeting.get_second_cut_off()
|
||||
|
@ -74,166 +61,100 @@ class UploadForm(forms.Form):
|
|||
self.cutoff_warning = 'The cut-off time for the I-D submission was %02dh UTC, %s.<br>The I-D submission tool will be reopened at %02dh local time at the IETF meeting location, %s.' % (settings.CUTOFF_HOUR, second_cut_off, settings.CUTOFF_HOUR, ietf_monday)
|
||||
self.shutdown = True
|
||||
|
||||
def __unicode__(self):
|
||||
return self.as_div()
|
||||
def clean_file(self, field_name, parser_class):
|
||||
f = self.cleaned_data[field_name]
|
||||
if not f:
|
||||
return f
|
||||
|
||||
def as_div(self):
|
||||
return render_to_string('submit/submitform.html', {'form': self})
|
||||
parsed_info = parser_class(f).critical_parse()
|
||||
if parsed_info.errors:
|
||||
raise forms.ValidationError(parsed_info.errors)
|
||||
|
||||
return f
|
||||
|
||||
def get_fieldsets(self):
|
||||
if not self.fieldsets:
|
||||
yield dict(name=None, fields=self)
|
||||
else:
|
||||
for fieldset, fields in self.fieldsets:
|
||||
fieldset_dict = dict(name=fieldset, fields=[])
|
||||
for field_name in fields:
|
||||
if field_name in self.fields.keyOrder:
|
||||
fieldset_dict['fields'].append(self[field_name])
|
||||
if not fieldset_dict['fields']:
|
||||
# if there is no fields in this fieldset, we continue to next fieldset
|
||||
continue
|
||||
yield fieldset_dict
|
||||
|
||||
def clean_txt(self):
|
||||
txt_file = self.cleaned_data['txt']
|
||||
if not txt_file:
|
||||
return txt_file
|
||||
parsed_info = PlainParser(txt_file).critical_parse()
|
||||
if parsed_info.errors:
|
||||
raise forms.ValidationError(parsed_info.errors)
|
||||
self.filesize=txt_file.size
|
||||
return txt_file
|
||||
return self.clean_file("txt", PlainParser)
|
||||
|
||||
def clean_pdf(self):
|
||||
pdf_file = self.cleaned_data['pdf']
|
||||
if not pdf_file:
|
||||
return pdf_file
|
||||
parsed_info = PDFParser(pdf_file).critical_parse()
|
||||
if parsed_info.errors:
|
||||
raise forms.ValidationError(parsed_info.errors)
|
||||
return pdf_file
|
||||
return self.clean_file("pdf", PDFParser)
|
||||
|
||||
def clean_ps(self):
|
||||
ps_file = self.cleaned_data['ps']
|
||||
if not ps_file:
|
||||
return ps_file
|
||||
parsed_info = PSParser(ps_file).critical_parse()
|
||||
if parsed_info.errors:
|
||||
raise forms.ValidationError(parsed_info.errors)
|
||||
return ps_file
|
||||
return self.clean_file("ps", PSParser)
|
||||
|
||||
def clean_xml(self):
|
||||
xml_file = self.cleaned_data['xml']
|
||||
if not xml_file:
|
||||
return xml_file
|
||||
parsed_info = XMLParser(xml_file).critical_parse()
|
||||
if parsed_info.errors:
|
||||
raise forms.ValidationError(parsed_info.errors)
|
||||
return xml_file
|
||||
return self.clean_file("xml", XMLParser)
|
||||
|
||||
def clean(self):
|
||||
if self.shutdown:
|
||||
raise forms.ValidationError('The tool is shut down')
|
||||
self.check_paths()
|
||||
if self.cleaned_data.get('txt', None):
|
||||
self.get_draft()
|
||||
self.group=self.get_working_group()
|
||||
self.check_previous_submission()
|
||||
if self.draft.revision == '00' and self.in_first_cut_off:
|
||||
|
||||
# sanity check that paths exist (for development servers)
|
||||
for s in ("IDSUBMIT_STAGING_PATH", "IDSUBMIT_IDNITS_BINARY",
|
||||
"IDSUBMIT_REPOSITORY_PATH", "INTERNET_DRAFT_ARCHIVE_DIR"):
|
||||
if not os.path.exists(getattr(settings, s)):
|
||||
raise forms.ValidationError('%s defined in settings.py does not exist' % s)
|
||||
|
||||
if self.cleaned_data.get('txt'):
|
||||
# try to parse it
|
||||
txt_file = self.cleaned_data['txt']
|
||||
txt_file.seek(0)
|
||||
self.parsed_draft = Draft(txt_file.read(), txt_file.name)
|
||||
txt_file.seek(0)
|
||||
|
||||
if not self.parsed_draft.filename:
|
||||
raise forms.ValidationError("Draft parser could not extract a valid draft name from the .txt file")
|
||||
|
||||
# check group
|
||||
self.group = self.deduce_group()
|
||||
|
||||
# check existing
|
||||
existing = Submission.objects.filter(name=self.parsed_draft.filename, rev=self.parsed_draft.revision).exclude(state__in=("posted", "cancel"))
|
||||
if existing:
|
||||
raise forms.ValidationError(mark_safe('Submission with same name and revision is currently being processed. <a href="%s">Check the status here</a>' % urlreverse("submit_submission_status", kwargs={ 'submission_id': existing[0].pk })))
|
||||
|
||||
# cut-off
|
||||
if self.parsed_draft.revision == '00' and self.in_first_cut_off:
|
||||
raise forms.ValidationError(mark_safe(self.cutoff_warning))
|
||||
self.check_tresholds()
|
||||
|
||||
# check thresholds
|
||||
today = datetime.date.today()
|
||||
|
||||
self.check_submissions_tresholds(
|
||||
"for the draft %s" % self.parsed_draft.filename,
|
||||
dict(name=self.parsed_draft.filename, rev=self.parsed_draft.revision, submission_date=today),
|
||||
settings.IDSUBMIT_MAX_DAILY_SAME_DRAFT_NAME, settings.IDSUBMIT_MAX_DAILY_SAME_DRAFT_NAME_SIZE,
|
||||
)
|
||||
self.check_submissions_tresholds(
|
||||
"for the same submitter",
|
||||
dict(remote_ip=self.remote_ip, submission_date=today),
|
||||
settings.IDSUBMIT_MAX_DAILY_SAME_SUBMITTER, settings.IDSUBMIT_MAX_DAILY_SAME_SUBMITTER_SIZE,
|
||||
)
|
||||
if self.group:
|
||||
self.check_submissions_tresholds(
|
||||
"for the group \"%s\"" % (self.group.acronym),
|
||||
dict(group=self.group, submission_date=today),
|
||||
settings.IDSUBMIT_MAX_DAILY_SAME_GROUP, settings.IDSUBMIT_MAX_DAILY_SAME_GROUP_SIZE,
|
||||
)
|
||||
self.check_submissions_tresholds(
|
||||
"across all submitters",
|
||||
dict(submission_date=today),
|
||||
settings.IDSUBMIT_MAX_DAILY_SUBMISSIONS, settings.IDSUBMIT_MAX_DAILY_SUBMISSIONS_SIZE,
|
||||
)
|
||||
|
||||
return super(UploadForm, self).clean()
|
||||
|
||||
def check_tresholds(self):
|
||||
filename = self.draft.filename
|
||||
revision = self.draft.revision
|
||||
remote_ip = self.remote_ip
|
||||
today = datetime.date.today()
|
||||
def check_submissions_tresholds(self, which, filter_kwargs, max_amount, max_size):
|
||||
submissions = Submission.objects.filter(**filter_kwargs)
|
||||
|
||||
# Same draft by name
|
||||
same_name = IdSubmissionDetail.objects.filter(filename=filename, revision=revision, submission_date=today)
|
||||
if same_name.count() > settings.MAX_SAME_DRAFT_NAME:
|
||||
raise forms.ValidationError('The same I-D cannot be submitted more than %s times a day' % settings.MAX_SAME_DRAFT_NAME)
|
||||
if sum(i.filesize for i in same_name) > settings.MAX_SAME_DRAFT_NAME_SIZE * 1048576:
|
||||
raise forms.ValidationError('The same I-D submission cannot exceed more than %s MByte a day' % settings.MAX_SAME_DRAFT_NAME_SIZE)
|
||||
if len(submissions) > max_amount:
|
||||
raise forms.ValidationError("Max submissions %s has been reached for today (maximum is %s submissions)." % (which, max_amount))
|
||||
if sum(s.file_size for s in submissions) > max_size * 1024 * 1024:
|
||||
raise forms.ValidationError("Max uploaded amount %s has been reached for today (maximum is %s MB)." % (which, max_size))
|
||||
|
||||
# Total from same ip
|
||||
same_ip = IdSubmissionDetail.objects.filter(remote_ip=remote_ip, submission_date=today)
|
||||
if same_ip.count() > settings.MAX_SAME_SUBMITTER:
|
||||
raise forms.ValidationError('The same submitter cannot submit more than %s I-Ds a day' % settings.MAX_SAME_SUBMITTER)
|
||||
if sum(i.filesize for i in same_ip) > settings.MAX_SAME_SUBMITTER_SIZE * 1048576:
|
||||
raise forms.ValidationError('The same submitter cannot exceed more than %s MByte a day' % settings.MAX_SAME_SUBMITTER_SIZE)
|
||||
|
||||
# Total in same group
|
||||
if self.group:
|
||||
same_group = IdSubmissionDetail.objects.filter(group_acronym=self.group, submission_date=today)
|
||||
if same_group.count() > settings.MAX_SAME_WG_DRAFT:
|
||||
raise forms.ValidationError('The same working group I-Ds cannot be submitted more than %s times a day' % settings.MAX_SAME_WG_DRAFT)
|
||||
if sum(i.filesize for i in same_group) > settings.MAX_SAME_WG_DRAFT_SIZE * 1048576:
|
||||
raise forms.ValidationError('Total size of same working group I-Ds cannot exceed %s MByte a day' % settings.MAX_SAME_WG_DRAFT_SIZE)
|
||||
|
||||
|
||||
# Total drafts for today
|
||||
total_today = IdSubmissionDetail.objects.filter(submission_date=today)
|
||||
if total_today.count() > settings.MAX_DAILY_SUBMISSION:
|
||||
raise forms.ValidationError('The total number of today\'s submission has reached the maximum number of submission per day')
|
||||
if sum(i.filesize for i in total_today) > settings.MAX_DAILY_SUBMISSION_SIZE * 1048576:
|
||||
raise forms.ValidationError('The total size of today\'s submission has reached the maximum size of submission per day')
|
||||
|
||||
def check_paths(self):
|
||||
self.staging_path = getattr(settings, 'IDSUBMIT_STAGING_PATH', None)
|
||||
self.idnits = getattr(settings, 'IDSUBMIT_IDNITS_BINARY', None)
|
||||
if not self.staging_path:
|
||||
raise forms.ValidationError('IDSUBMIT_STAGING_PATH not defined in settings.py')
|
||||
if not os.path.exists(self.staging_path):
|
||||
raise forms.ValidationError('IDSUBMIT_STAGING_PATH defined in settings.py does not exist')
|
||||
if not self.idnits:
|
||||
raise forms.ValidationError('IDSUBMIT_IDNITS_BINARY not defined in settings.py')
|
||||
if not os.path.exists(self.idnits):
|
||||
raise forms.ValidationError('IDSUBMIT_IDNITS_BINARY defined in settings.py does not exist')
|
||||
|
||||
def check_previous_submission(self):
|
||||
filename = self.draft.filename
|
||||
revision = self.draft.revision
|
||||
existing = IdSubmissionDetail.objects.filter(filename=filename, revision=revision,
|
||||
status__pk__gte=0, status__pk__lt=100)
|
||||
if existing:
|
||||
raise forms.ValidationError(mark_safe('Duplicate Internet-Draft submission is currently in process. <a href="/submit/status/%s/">Check it here</a>' % existing[0].pk))
|
||||
|
||||
def get_draft(self):
|
||||
if self.draft:
|
||||
return self.draft
|
||||
txt_file = self.cleaned_data['txt']
|
||||
txt_file.seek(0)
|
||||
self.draft = Draft(txt_file.read(), txt_file.name)
|
||||
txt_file.seek(0)
|
||||
return self.draft
|
||||
|
||||
def save(self):
|
||||
for ext in ['txt', 'pdf', 'xml', 'ps']:
|
||||
fd = self.cleaned_data[ext]
|
||||
if not fd:
|
||||
continue
|
||||
self.file_type.append('.%s' % ext)
|
||||
filename = os.path.join(self.staging_path, '%s-%s.%s' % (self.draft.filename, self.draft.revision, ext))
|
||||
destination = open(filename, 'wb+')
|
||||
for chunk in fd.chunks():
|
||||
destination.write(chunk)
|
||||
destination.close()
|
||||
self.check_idnits()
|
||||
return self.save_draft_info(self.draft)
|
||||
|
||||
def check_idnits(self):
|
||||
filepath = os.path.join(self.staging_path, '%s-%s.txt' % (self.draft.filename, self.draft.revision))
|
||||
#p = subprocess.Popen([self.idnits, '--submitcheck', '--nitcount', filepath], stdout=subprocess.PIPE)
|
||||
cmd = "%s --submitcheck --nitcount %s" % (self.idnits, filepath)
|
||||
code, out, err = pipe(cmd)
|
||||
if code != 0:
|
||||
log("idnits error: %s:\n Error %s: %s" %(cmd, code, err))
|
||||
self.idnits_message = out
|
||||
|
||||
def get_working_group(self):
|
||||
name = self.draft.filename
|
||||
def deduce_group(self):
|
||||
"""Figure out group from name or previously submitted draft, returns None if individual."""
|
||||
name = self.parsed_draft.filename
|
||||
existing_draft = Document.objects.filter(name=name, type="draft")
|
||||
if existing_draft:
|
||||
group = existing_draft[0].group
|
||||
|
@ -245,11 +166,11 @@ class UploadForm(forms.Form):
|
|||
if name.startswith('draft-ietf-') or name.startswith("draft-irtf-"):
|
||||
components = name.split("-")
|
||||
if len(components) < 3:
|
||||
raise forms.ValidationError("The draft name \"%s\" is missing a third part, please rename it")
|
||||
raise forms.ValidationError(u"The draft name \"%s\" is missing a third part, please rename it" % name)
|
||||
|
||||
if components[1] == "ietf":
|
||||
group_type = "wg"
|
||||
else:
|
||||
elif components[1] == "irtf":
|
||||
group_type = "rg"
|
||||
|
||||
# first check groups with dashes
|
||||
|
@ -261,109 +182,51 @@ class UploadForm(forms.Form):
|
|||
return Group.objects.get(acronym=components[2], type=group_type)
|
||||
except Group.DoesNotExist:
|
||||
raise forms.ValidationError('There is no active group with acronym \'%s\', please rename your draft' % components[2])
|
||||
|
||||
elif name.startswith("draft-iab-"):
|
||||
return Group.objects.get(acronym="iab")
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def save_draft_info(self, draft):
|
||||
detail = IdSubmissionDetail.objects.create(
|
||||
id_document_name=draft.get_title(),
|
||||
filename=draft.filename,
|
||||
revision=draft.revision,
|
||||
txt_page_count=draft.get_pagecount(),
|
||||
filesize=self.filesize,
|
||||
creation_date=draft.get_creation_date(),
|
||||
submission_date=datetime.date.today(),
|
||||
idnits_message=self.idnits_message,
|
||||
temp_id_document_tag=-1,
|
||||
group_acronym=self.group,
|
||||
remote_ip=self.remote_ip,
|
||||
first_two_pages=''.join(draft.pages[:2]),
|
||||
status_id=UPLOADED,
|
||||
abstract=draft.get_abstract(),
|
||||
file_type=','.join(self.file_type),
|
||||
)
|
||||
for order, author in enumerate(draft.get_author_list(), start=1):
|
||||
full_name, first_name, middle_initial, last_name, name_suffix, email, company = author
|
||||
# save full name
|
||||
TempIdAuthors.objects.create(
|
||||
id_document_tag=-1,
|
||||
first_name=full_name.strip(),
|
||||
email_address=(email or "").strip(),
|
||||
author_order=order,
|
||||
submission=detail)
|
||||
return detail
|
||||
|
||||
|
||||
class AutoPostForm(forms.Form):
|
||||
|
||||
class NameEmailForm(forms.Form):
|
||||
"""For validating supplied submitter and author information."""
|
||||
name = forms.CharField(required=True)
|
||||
email = forms.EmailField(label=u'Email address', required=True)
|
||||
email = forms.EmailField(label=u'Email address')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.draft = kwargs.pop('draft', None)
|
||||
self.validation = kwargs.pop('validation', None)
|
||||
self.replaces = kwargs.pop('replaces', None)
|
||||
super(AutoPostForm, self).__init__(*args, **kwargs)
|
||||
email_required = kwargs.pop("email_required", True)
|
||||
super(NameEmailForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_author_buttons(self):
|
||||
buttons = []
|
||||
for i in self.validation.authors:
|
||||
buttons.append('<input type="button" data-name="%(name)s" data-email="%(email)s" value="%(name)s" />'
|
||||
% dict(name=i.get_full_name(),
|
||||
email=i.email()[1] or ''))
|
||||
return "".join(buttons)
|
||||
self.fields["email"].required = email_required
|
||||
self.fields["name"].widget.attrs["class"] = "name"
|
||||
self.fields["email"].widget.attrs["class"] = "email"
|
||||
|
||||
def save(self, request):
|
||||
self.save_submitter_info()
|
||||
self.save_new_draft_info()
|
||||
self.send_confirmation_mail(request)
|
||||
def clean_name(self):
|
||||
return self.cleaned_data["name"].replace("\n", "").replace("\r", "").replace("<", "").replace(">", "").strip()
|
||||
|
||||
def send_confirmation_mail(self, request):
|
||||
subject = 'Confirmation for Auto-Post of I-D %s' % self.draft.filename
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = submission_confirmation_email_list(self.draft)
|
||||
def clean_email(self):
|
||||
return self.cleaned_data["email"].replace("\n", "").replace("\r", "").replace("<", "").replace(">", "").strip()
|
||||
|
||||
confirm_url = settings.IDTRACKER_BASE_URL + urlreverse('draft_confirm', kwargs=dict(submission_id=self.draft.submission_id, auth_key=self.draft.auth_key))
|
||||
status_url = settings.IDTRACKER_BASE_URL + urlreverse('draft_status_by_hash', kwargs=dict(submission_id=self.draft.submission_id, submission_hash=self.draft.get_hash()))
|
||||
|
||||
send_mail(request, to_email, from_email, subject, 'submit/confirm_autopost.txt',
|
||||
{ 'draft': self.draft, 'confirm_url': confirm_url, 'status_url': status_url })
|
||||
def cleaned_line(self):
|
||||
line = self.cleaned_data["name"]
|
||||
email = self.cleaned_data.get("email")
|
||||
if email:
|
||||
line += u" <%s>" % email
|
||||
return line
|
||||
|
||||
def save_submitter_info(self):
|
||||
return TempIdAuthors.objects.create(
|
||||
id_document_tag=self.draft.temp_id_document_tag,
|
||||
first_name=self.cleaned_data['name'],
|
||||
email_address=self.cleaned_data['email'],
|
||||
author_order=0,
|
||||
submission=self.draft,
|
||||
)
|
||||
class EditSubmissionForm(forms.ModelForm):
|
||||
title = forms.CharField(required=True, max_length=255)
|
||||
rev = forms.CharField(label=u'Revision', max_length=2, required=True)
|
||||
document_date = forms.DateField(required=True)
|
||||
pages = forms.IntegerField(required=True)
|
||||
abstract = forms.CharField(widget=forms.Textarea, required=True)
|
||||
|
||||
def save_new_draft_info(self):
|
||||
salt = hashlib.sha1(str(random.random())).hexdigest()[:5]
|
||||
self.draft.auth_key = hashlib.sha1(salt+self.cleaned_data['email']).hexdigest()
|
||||
self.draft.status_id = AWAITING_AUTHENTICATION
|
||||
self.draft.save()
|
||||
note = forms.CharField(label=mark_safe(u'Comment to<br/> the Secretariat'), widget=forms.Textarea, required=False)
|
||||
|
||||
|
||||
class MetaDataForm(AutoPostForm):
|
||||
|
||||
title = forms.CharField(label=u'Title', required=True)
|
||||
version = forms.CharField(label=u'Version', required=True)
|
||||
creation_date = forms.DateField(label=u'Creation date', required=True)
|
||||
pages = forms.IntegerField(label=u'Pages', required=True)
|
||||
abstract = forms.CharField(label=u'Abstract', widget=forms.Textarea, required=True)
|
||||
name = forms.CharField(required=True)
|
||||
email = forms.EmailField(label=u'Email address', required=True)
|
||||
comments = forms.CharField(label=u'Comments to the secretariat', widget=forms.Textarea, required=False)
|
||||
|
||||
fields = ['title', 'version', 'creation_date', 'pages', 'abstract', 'name', 'email', 'comments']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MetaDataForm, self).__init__(*args, **kwargs)
|
||||
self.set_initials()
|
||||
self.authors = self.get_initial_authors()
|
||||
class Meta:
|
||||
model = Submission
|
||||
fields = ['title', 'rev', 'document_date', 'pages', 'abstract', 'note']
|
||||
|
||||
def get_initial_authors(self):
|
||||
authors=[]
|
||||
|
@ -379,117 +242,33 @@ class MetaDataForm(AutoPostForm):
|
|||
if email and not email_re.search(email):
|
||||
author['errors']['email'] = 'Enter a valid e-mail address'
|
||||
if name or email:
|
||||
author.update({'get_full_name': name,
|
||||
'email': (name, email),
|
||||
author.update({'name': name,
|
||||
'email': email,
|
||||
'index': index,
|
||||
})
|
||||
authors.append(author)
|
||||
authors.sort(key=lambda x: x['index'])
|
||||
return authors
|
||||
|
||||
def set_initials(self):
|
||||
self.fields['pages'].initial=self.draft.txt_page_count
|
||||
self.fields['creation_date'].initial=self.draft.creation_date
|
||||
self.fields['version'].initial=self.draft.revision
|
||||
self.fields['abstract'].initial=self.draft.abstract
|
||||
self.fields['title'].initial=self.draft.id_document_name
|
||||
def clean_rev(self):
|
||||
rev = self.cleaned_data["rev"]
|
||||
|
||||
def clean_creation_date(self):
|
||||
creation_date = self.cleaned_data.get('creation_date', None)
|
||||
if not creation_date:
|
||||
return None
|
||||
submit_date = self.draft.submission_date
|
||||
if (creation_date + datetime.timedelta(days=3) < submit_date or
|
||||
creation_date - datetime.timedelta(days=3) > submit_date):
|
||||
raise forms.ValidationError('Creation Date must be within 3 days of submission date')
|
||||
return creation_date
|
||||
if len(rev) == 1:
|
||||
rev = "0" + rev
|
||||
|
||||
def clean_version(self):
|
||||
version = self.cleaned_data.get('version', None)
|
||||
if not version:
|
||||
return None
|
||||
if len(version) > 2:
|
||||
raise forms.ValidationError('Version field is not in NN format')
|
||||
try:
|
||||
version_int = int(version)
|
||||
except ValueError:
|
||||
raise forms.ValidationError('Version field is not in NN format')
|
||||
if version_int > 99 or version_int < 0:
|
||||
raise forms.ValidationError('Version must be set between 00 and 99')
|
||||
existing_revisions = [int(i.rev) for i in Document.objects.filter(name=self.draft.filename)]
|
||||
expected = 0
|
||||
if existing_revisions:
|
||||
expected = max(existing_revisions) + 1
|
||||
if version_int != expected:
|
||||
raise forms.ValidationError('Invalid Version Number (Version %02d is expected)' % expected)
|
||||
return version
|
||||
error = validate_submission_rev(self.instance.name, rev)
|
||||
if error:
|
||||
raise forms.ValidationError(error)
|
||||
|
||||
def clean(self):
|
||||
if bool([i for i in self.authors if i['errors']]):
|
||||
raise forms.ValidationError('Please fix errors in author list')
|
||||
return super(MetaDataForm, self).clean()
|
||||
return rev
|
||||
|
||||
def get_authors(self):
|
||||
if not self.is_bound:
|
||||
return self.validation.get_authors()
|
||||
else:
|
||||
return self.authors
|
||||
|
||||
def move_docs(self, draft, revision):
|
||||
old_revision = draft.revision
|
||||
for ext in draft.file_type.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (draft.filename, old_revision, ext))
|
||||
dest = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (draft.filename, revision, ext))
|
||||
os.rename(source, dest)
|
||||
|
||||
def save_new_draft_info(self):
|
||||
draft = self.draft
|
||||
draft.id_document_name = self.cleaned_data['title']
|
||||
if draft.revision != self.cleaned_data['version']:
|
||||
self.move_docs(draft, self.cleaned_data['version'])
|
||||
draft.revision = self.cleaned_data['version']
|
||||
draft.creation_date = self.cleaned_data['creation_date']
|
||||
draft.txt_page_count = self.cleaned_data['pages']
|
||||
draft.abstract = self.cleaned_data['abstract']
|
||||
draft.comment_to_sec = self.cleaned_data['comments']
|
||||
draft.status_id = MANUAL_POST_REQUESTED
|
||||
draft.save()
|
||||
|
||||
# sync authors
|
||||
draft.tempidauthors_set.all().delete()
|
||||
|
||||
self.save_submitter_info() # submitter is author 0
|
||||
|
||||
for i, author in enumerate(self.authors):
|
||||
TempIdAuthors.objects.create(
|
||||
id_document_tag=draft.temp_id_document_tag,
|
||||
first_name=author["get_full_name"], # save full name
|
||||
email_address=author["email"][1],
|
||||
author_order=i + 1,
|
||||
submission=draft)
|
||||
|
||||
def save(self, request):
|
||||
self.save_new_draft_info()
|
||||
self.send_mail_to_secretariat(request)
|
||||
|
||||
def send_mail_to_secretariat(self, request):
|
||||
subject = 'Manual Post Requested for %s' % self.draft.filename
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = settings.IDSUBMIT_TO_EMAIL
|
||||
cc = [self.cleaned_data['email']]
|
||||
cc += [i['email'][1] for i in self.authors]
|
||||
if self.draft.group_acronym:
|
||||
cc += [r.email.address for r in Role.objects.filter(group=self.draft.group_acronym, name="chair").select_related("email")]
|
||||
cc = list(set(cc))
|
||||
submitter = self.draft.tempidauthors_set.get(author_order=0)
|
||||
send_mail(request, to_email, from_email, subject, 'submit/manual_post_mail.txt', {
|
||||
'form': self,
|
||||
'draft': self.draft,
|
||||
'url': settings.IDTRACKER_BASE_URL + urlreverse('draft_status', kwargs=dict(submission_id=self.draft.submission_id)),
|
||||
'submitter': submitter
|
||||
},
|
||||
cc=cc)
|
||||
def clean_document_date(self):
|
||||
document_date = self.cleaned_data['document_date']
|
||||
error = validate_submission_document_date(self.instance.submission_date, document_date)
|
||||
if error:
|
||||
raise forms.ValidationError(error)
|
||||
|
||||
return document_date
|
||||
|
||||
class PreapprovalForm(forms.Form):
|
||||
name = forms.CharField(max_length=255, required=True, label="Pre-approved name", initial="draft-ietf-")
|
||||
|
@ -515,7 +294,7 @@ class PreapprovalForm(forms.Form):
|
|||
|
||||
if Preapproval.objects.filter(name=n):
|
||||
raise forms.ValidationError("Pre-approval for this name already exists.")
|
||||
if IdSubmissionDetail.objects.filter(status__in=[POSTED, POSTED_BY_SECRETARIAT ], filename=n):
|
||||
if Submission.objects.filter(state="posted", name=n):
|
||||
raise forms.ValidationError("A draft with this name has already been submitted and accepted. A pre-approval would not make any difference.")
|
||||
|
||||
return n
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# boiler plate
|
||||
import os, sys
|
||||
|
||||
ietf_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../ietf'))
|
||||
|
||||
sys.path.insert(0, ietf_path)
|
||||
|
||||
from django.core.management import setup_environ
|
||||
import settings
|
||||
setup_environ(settings)
|
||||
|
||||
# script
|
||||
from django.core.serializers import serialize
|
||||
from django.db.models import Q
|
||||
|
||||
def output(name, qs):
|
||||
try:
|
||||
f = open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures/%s.xml" % name), 'w')
|
||||
f.write(serialize("xml", qs, indent=4))
|
||||
f.close()
|
||||
except:
|
||||
from django.db import connection
|
||||
from pprint import pprint
|
||||
pprint(connection.queries)
|
||||
raise
|
||||
|
||||
# pick all name models directly out of the module
|
||||
names = []
|
||||
|
||||
from ietf.submit.models import IdSubmissionStatus
|
||||
|
||||
output("idsubmissionstatus", IdSubmissionStatus.objects.all())
|
152
ietf/submit/mail.py
Normal file
152
ietf/submit/mail.py
Normal file
|
@ -0,0 +1,152 @@
|
|||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.contrib.sites.models import Site
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from ietf.utils.mail import send_mail, send_mail_message
|
||||
from ietf.doc.models import Document
|
||||
from ietf.person.models import Person
|
||||
from ietf.group.models import Role
|
||||
from ietf.message.models import Message
|
||||
|
||||
def submission_confirmation_email_list(submission):
|
||||
try:
|
||||
doc = Document.objects.get(name=submission.name)
|
||||
email_list = [i.author.formatted_email() for i in doc.documentauthor_set.all()]
|
||||
except Document.DoesNotExist:
|
||||
email_list = [u"%s <%s>" % (author["name"], author["email"])
|
||||
for author in submission.authors_parsed() if author["email"]]
|
||||
if submission.submitter_parsed()["email"] and submission.submitter not in email_list:
|
||||
email_list.append(submission.submitter)
|
||||
return email_list
|
||||
|
||||
def send_submission_confirmation(request, submission):
|
||||
subject = 'Confirm submission of I-D %s' % submission.name
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = submission_confirmation_email_list(submission)
|
||||
|
||||
confirm_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_confirm_submission', kwargs=dict(submission_id=submission.pk, auth_key=submission.auth_key))
|
||||
status_url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash', kwargs=dict(submission_id=submission.pk, access_key=submission.access_key))
|
||||
|
||||
send_mail(request, to_email, from_email, subject, 'submit/confirm_submission.txt', {
|
||||
'submission': submission,
|
||||
'confirm_url': confirm_url,
|
||||
'status_url': status_url,
|
||||
})
|
||||
|
||||
return to_email
|
||||
|
||||
def send_full_url(request, submission):
|
||||
subject = 'Full URL for managing submission of draft %s' % submission.name
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = submission_confirmation_email_list(submission)
|
||||
url = settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status_by_hash',
|
||||
kwargs=dict(submission_id=submission.pk,
|
||||
access_key=submission.access_key))
|
||||
send_mail(request, to_email, from_email, subject, 'submit/full_url.txt', {
|
||||
'submission': submission,
|
||||
'url': url,
|
||||
})
|
||||
|
||||
return to_email
|
||||
|
||||
def send_approval_request_to_group(request, submission):
|
||||
subject = 'New draft waiting for approval: %s' % submission.name
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = [r.formatted_email() for r in Role.objects.filter(group=submission.group, name="chair").select_related("email", "person")]
|
||||
if not to_email:
|
||||
return to_email
|
||||
|
||||
send_mail(request, to_email, from_email, subject, 'submit/approval_request.txt', {
|
||||
'submission': submission,
|
||||
'domain': Site.objects.get_current().domain,
|
||||
})
|
||||
|
||||
return to_email
|
||||
|
||||
def send_manual_post_request(request, submission, errors):
|
||||
subject = u'Manual Post Requested for %s' % submission.name
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = settings.IDSUBMIT_TO_EMAIL
|
||||
|
||||
cc = [submission.submitter]
|
||||
cc += [u"%s <%s>" % (author["name"], author["email"])
|
||||
for author in submission.authors_parsed() if author["email"]]
|
||||
if submission.group:
|
||||
cc += [r.formatted_email() for r in Role.objects.filter(group=submission.group, name="chair").select_related("email", "person")]
|
||||
cc = list(set(cc))
|
||||
|
||||
send_mail(request, to_email, from_email, subject, 'submit/manual_post_request.txt', {
|
||||
'submission': submission,
|
||||
'url': settings.IDTRACKER_BASE_URL + urlreverse('submit_submission_status', kwargs=dict(submission_id=submission.pk)),
|
||||
'errors': errors,
|
||||
}, cc=cc)
|
||||
|
||||
|
||||
def announce_to_lists(request, submission):
|
||||
m = Message()
|
||||
m.by = Person.objects.get(name="(System)")
|
||||
if request.user.is_authenticated():
|
||||
try:
|
||||
m.by = request.user.get_profile()
|
||||
except Person.DoesNotExist:
|
||||
pass
|
||||
m.subject = 'I-D Action: %s-%s.txt' % (submission.name, submission.rev)
|
||||
m.frm = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
m.to = settings.IDSUBMIT_ANNOUNCE_LIST_EMAIL
|
||||
if submission.group and submission.group.list_email:
|
||||
m.cc = submission.group.list_email
|
||||
m.body = render_to_string('submit/announce_to_lists.txt',
|
||||
dict(submission=submission,
|
||||
settings=settings))
|
||||
m.save()
|
||||
m.related_docs.add(Document.objects.get(name=submission.name))
|
||||
|
||||
send_mail_message(request, m)
|
||||
|
||||
|
||||
def announce_new_version(request, submission, draft, state_change_msg):
|
||||
to_email = []
|
||||
if draft.notify:
|
||||
to_email.append(draft.notify)
|
||||
if draft.ad:
|
||||
to_email.append(draft.ad.role_email("ad").address)
|
||||
|
||||
if draft.stream_id == "iab":
|
||||
to_email.append("IAB Stream <iab-stream@iab.org>")
|
||||
elif draft.stream_id == "ise":
|
||||
to_email.append("Independent Submission Editor <rfc-ise@rfc-editor.org>")
|
||||
elif draft.stream_id == "irtf":
|
||||
to_email.append("IRSG <irsg@irtf.org>")
|
||||
|
||||
# if it has been sent to the RFC Editor, keep them in the loop
|
||||
if draft.get_state_slug("draft-iesg") in ("ann", "rfcqueue"):
|
||||
to_email.append("RFC Editor <rfc-editor@rfc-editor.org>")
|
||||
|
||||
active_ballot = draft.active_ballot()
|
||||
if active_ballot:
|
||||
for ad, pos in active_ballot.active_ad_positions().iteritems():
|
||||
if pos and pos.pos_id == "discuss":
|
||||
to_email.append(ad.role_email("ad").address)
|
||||
|
||||
if to_email:
|
||||
subject = 'New Version Notification - %s-%s.txt' % (submission.name, submission.rev)
|
||||
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
send_mail(request, to_email, from_email, subject, 'submit/announce_new_version.txt',
|
||||
{'submission': submission,
|
||||
'msg': state_change_msg})
|
||||
|
||||
def announce_to_authors(request, submission):
|
||||
authors = [u"%s <%s>" % (author["name"], author["email"]) for author in submission.authors_parsed() if author["email"]]
|
||||
to_email = list(set(submission_confirmation_email_list(submission) + authors))
|
||||
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
subject = 'New Version Notification for %s-%s.txt' % (submission.name, submission.rev)
|
||||
if submission.group:
|
||||
group = submission.group.acronym
|
||||
elif submission.name.startswith('draft-iesg'):
|
||||
group = 'IESG'
|
||||
else:
|
||||
group = 'Individual Submission'
|
||||
send_mail(request, to_email, from_email, subject, 'submit/announce_to_authors.txt',
|
||||
{'submission': submission,
|
||||
'group': group})
|
297
ietf/submit/migrations/0003_turn_nulls_into_empty_strings.py
Normal file
297
ietf/submit/migrations/0003_turn_nulls_into_empty_strings.py
Normal file
|
@ -0,0 +1,297 @@
|
|||
# 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):
|
||||
nullable_string_fields = [
|
||||
"id_document_name",
|
||||
"comment_to_sec",
|
||||
"filename",
|
||||
"revision",
|
||||
"replaces",
|
||||
"file_type",
|
||||
"abstract",
|
||||
"idnits_message",
|
||||
"first_two_pages",
|
||||
"remote_ip",
|
||||
"auth_key",
|
||||
"submission_hash",
|
||||
]
|
||||
|
||||
for f in nullable_string_fields:
|
||||
orm.IdSubmissionDetail.objects.filter(**{ f: None}).update(**{ f: ""})
|
||||
|
||||
def backwards(self, orm):
|
||||
pass
|
||||
|
||||
|
||||
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.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.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.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.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'})
|
||||
},
|
||||
'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'})
|
||||
},
|
||||
'group.ietfwg': {
|
||||
'Meta': {'object_name': 'IETFWG', 'db_table': "'group_group'", '_ormbases': ['group.Group'], 'proxy': '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'}),
|
||||
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'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'})
|
||||
},
|
||||
'submit.idsubmissiondetail': {
|
||||
'Meta': {'object_name': 'IdSubmissionDetail'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'auth_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'comment_to_sec': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'creation_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'error_message': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'file_type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
|
||||
'filename': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'filesize': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'first_two_pages': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'group_acronym': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
|
||||
'id_document_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'idnits_failed': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'idnits_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'invalid_version': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_updated_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_updated_time': ('django.db.models.fields.CharField', [], {'max_length': '25', 'null': 'True', 'blank': 'True'}),
|
||||
'man_posted_by': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'man_posted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'remote_ip': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'replaces': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'revision': ('django.db.models.fields.CharField', [], {'max_length': '3', 'null': 'True', 'blank': 'True'}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.IdSubmissionStatus']", 'null': 'True', 'db_column': "'status_id'", 'blank': 'True'}),
|
||||
'sub_email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'submission_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'submission_hash': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'submission_id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'submitter_tag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'temp_id_document_tag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'txt_page_count': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'warning_message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'wg_submission': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
|
||||
},
|
||||
'submit.idsubmissionstatus': {
|
||||
'Meta': {'object_name': 'IdSubmissionStatus'},
|
||||
'status_id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
|
||||
'status_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'submit.preapproval': {
|
||||
'Meta': {'object_name': 'Preapproval'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'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'})
|
||||
},
|
||||
'submit.tempidauthors': {
|
||||
'Meta': {'object_name': 'TempIdAuthors'},
|
||||
'author_order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'id_document_tag': ('django.db.models.fields.IntegerField', [], {}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_modified_time': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.IdSubmissionDetail']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['submit']
|
327
ietf/submit/migrations/0004_fixup_idsubmissiondetail_fields.py
Normal file
327
ietf/submit/migrations/0004_fixup_idsubmissiondetail_fields.py
Normal file
|
@ -0,0 +1,327 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
depends_on = (
|
||||
("name", "0017_populate_draftsubmissionstate"),
|
||||
)
|
||||
|
||||
def forwards(self, orm):
|
||||
db.rename_table('submit_idsubmissiondetail', 'submit_submission')
|
||||
|
||||
db.rename_column('submit_submission', 'submission_id', "id")
|
||||
|
||||
db.rename_column('submit_submission', 'id_document_name', "title")
|
||||
db.alter_column('submit_submission', 'title', self.gf('django.db.models.fields.CharField')(default='', max_length=255, blank=True))
|
||||
db.rename_column('submit_submission', 'creation_date', "document_date")
|
||||
db.rename_column('submit_submission', 'group_acronym_id', 'group_id')
|
||||
db.rename_column('submit_submission', 'txt_page_count', 'pages')
|
||||
db.rename_column('submit_submission', 'comment_to_sec', 'note')
|
||||
db.alter_column('submit_submission', 'note', self.gf('django.db.models.fields.TextField')(default='', blank=True))
|
||||
db.rename_column('submit_submission', 'filename', 'name')
|
||||
db.alter_column('submit_submission', 'name', self.gf('django.db.models.fields.CharField')(db_index=True, default='', max_length=255, blank=True))
|
||||
db.rename_column('submit_submission', 'filesize', 'file_size')
|
||||
db.rename_column('submit_submission', 'revision', 'rev')
|
||||
db.alter_column('submit_submission', 'rev', self.gf('django.db.models.fields.CharField')(default='', max_length=3, blank=True))
|
||||
|
||||
db.delete_column('submit_submission', 'idnits_failed')
|
||||
db.delete_column('submit_submission', 'invalid_version')
|
||||
db.delete_column('submit_submission', 'temp_id_document_tag')
|
||||
db.delete_column('submit_submission', 'error_message')
|
||||
db.delete_column('submit_submission', 'wg_submission')
|
||||
db.delete_column('submit_submission', 'warning_message')
|
||||
db.delete_column('submit_submission', 'last_updated_date')
|
||||
db.delete_column('submit_submission', 'last_updated_time')
|
||||
|
||||
db.add_column('submit_submission', 'state', self.gf('django.db.models.fields.related.ForeignKey')(default='uploaded', to=orm['name.DraftSubmissionStateName']))
|
||||
db.add_column('submit_submission', 'authors', self.gf('django.db.models.fields.TextField')(default=""))
|
||||
db.add_column('submit_submission', 'submitter', self.gf('django.db.models.fields.CharField')(max_length=255, default=""))
|
||||
|
||||
db.alter_column('submit_submission', 'submission_date', self.gf('django.db.models.fields.DateField')())
|
||||
|
||||
db.alter_column('submit_submission', 'replaces', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
|
||||
|
||||
db.rename_column('submit_submission', 'file_type', 'file_types')
|
||||
db.alter_column('submit_submission', 'file_types', self.gf('django.db.models.fields.CharField')(default='', max_length=50))
|
||||
|
||||
db.alter_column('submit_submission', 'abstract', self.gf('django.db.models.fields.TextField')(default=''))
|
||||
|
||||
db.alter_column('submit_submission', 'idnits_message', self.gf('django.db.models.fields.TextField')(default=''))
|
||||
|
||||
db.alter_column('submit_submission', 'first_two_pages', self.gf('django.db.models.fields.TextField')(default=''))
|
||||
|
||||
db.alter_column('submit_submission', 'remote_ip', self.gf('django.db.models.fields.CharField')(default='', max_length=100))
|
||||
|
||||
db.alter_column('submit_submission', 'auth_key', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
|
||||
|
||||
db.rename_column('submit_submission', 'submission_hash', "access_key")
|
||||
db.alter_column('submit_submission', 'access_key', self.gf('django.db.models.fields.CharField')(default='', max_length=255))
|
||||
|
||||
db.create_table('submit_submissionevent', (
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('submission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['submit.Submission'])),
|
||||
('time', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)),
|
||||
('by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['person.Person'], null=True, blank=True)),
|
||||
('desc', self.gf('django.db.models.fields.TextField')()),
|
||||
))
|
||||
db.send_create_signal('submit', ['SubmissionEvent'])
|
||||
|
||||
def backwards(self, orm):
|
||||
pass
|
||||
|
||||
|
||||
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.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.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.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'})
|
||||
},
|
||||
'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.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.draftsubmissionstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
|
||||
'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'})
|
||||
},
|
||||
'submit.submission': {
|
||||
'Meta': {'object_name': 'Submission'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'auth_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'document_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_types': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'first_two_pages': ('django.db.models.fields.TextField', [], {'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'}),
|
||||
'idnits_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'man_posted_by': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'man_posted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'remote_ip': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'replaces': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'submitter': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'default': "'uploaded'", 'to': "orm['name.DraftSubmissionStateName']"}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.IdSubmissionStatus']", 'null': 'True', 'db_column': "'status_id'", 'blank': 'True'}),
|
||||
'sub_email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'submission_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}),
|
||||
'access_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'submitter_tag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'authors': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'submit.submissionevent': {
|
||||
'Meta': {'ordering': "('-time', '-id')", 'object_name': 'SubmissionEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.Submission']"}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
'submit.idsubmissionstatus': {
|
||||
'Meta': {'object_name': 'IdSubmissionStatus'},
|
||||
'status_id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
|
||||
'status_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'submit.preapproval': {
|
||||
'Meta': {'object_name': 'Preapproval'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'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'})
|
||||
},
|
||||
'submit.tempidauthors': {
|
||||
'Meta': {'object_name': 'TempIdAuthors'},
|
||||
'author_order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'id_document_tag': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_modified_time': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.Submission']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['submit']
|
392
ietf/submit/migrations/0005_fill_in_new_fields.py
Normal file
392
ietf/submit/migrations/0005_fill_in_new_fields.py
Normal file
|
@ -0,0 +1,392 @@
|
|||
# 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):
|
||||
import hashlib, random, time
|
||||
from django.conf import settings
|
||||
|
||||
state_map = dict((n.slug, n) for n in orm["name.DraftSubmissionStateName"].objects.all())
|
||||
status_map = {
|
||||
-4: "cancel",
|
||||
-2: "posted", # Secretariat
|
||||
-1: "posted",
|
||||
1: "uploaded",
|
||||
4: "auth",
|
||||
5: "manual",
|
||||
10: "grp-appr",
|
||||
}
|
||||
|
||||
from django.core.validators import validate_email, ValidationError
|
||||
|
||||
for d in orm.Submission.objects.all().iterator():
|
||||
if not d.name:
|
||||
# get rid of a few mishaps that seem to have been
|
||||
# accepted without a name
|
||||
d.delete()
|
||||
continue
|
||||
|
||||
# map state
|
||||
state = state_map[status_map.get(d.status_id, "cancel")]
|
||||
|
||||
# map authors
|
||||
authors = []
|
||||
submitter = ""
|
||||
submitter_email = ""
|
||||
|
||||
for a in d.tempidauthors_set.order_by("author_order"):
|
||||
parts = (a.first_name or '', a.middle_initial or '', a.last_name or '', a.name_suffix or '')
|
||||
name = u" ".join(x.strip() for x in parts if x.strip())
|
||||
email = a.email_address
|
||||
orig = email
|
||||
|
||||
# clean
|
||||
name = name.replace("\n", "").replace("\r", "").replace("<", "").replace(">", "").strip()
|
||||
email = email.replace("Email:", "").replace("E-mail:", "").replace("mailto:", "").replace(">", "").replace("<", "").replace("\n", "").replace(" ", "").rstrip(",").lstrip(":").strip(".").rstrip(";").rstrip("-").rstrip("\"").lstrip("\"").rstrip("@")
|
||||
|
||||
if email:
|
||||
line = u"%s <%s>" % (name, email)
|
||||
else:
|
||||
line = name
|
||||
|
||||
if a.author_order == 0:
|
||||
submitter = line
|
||||
submitter_email = email
|
||||
else:
|
||||
authors.append(line)
|
||||
|
||||
# make sure we always have a key
|
||||
access_key = d.access_key
|
||||
if not access_key:
|
||||
access_key = hashlib.sha256(settings.SECRET_KEY + ("%.16f" % time.time()) + ("%.16f" % random.random()) + str(d.name.encode("utf-8"))).hexdigest()[:32]
|
||||
|
||||
|
||||
# fill in submission event
|
||||
submitter_person = None
|
||||
if d.submitter_tag:
|
||||
try:
|
||||
submitter_person = orm["person.Person"].objects.get(id=d.submitter_tag)
|
||||
except models.ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
if submitter_email:
|
||||
try:
|
||||
submitter_person = orm["person.Person"].objects.get(email__address=submitter_email)
|
||||
except models.ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
if submitter_person and not submitter:
|
||||
submitter = submitter_person.name
|
||||
|
||||
if submitter_person:
|
||||
orm.SubmissionEvent.objects.get_or_create(
|
||||
submission=d,
|
||||
time=d.submission_date,
|
||||
by=submitter_person,
|
||||
desc="Uploaded submission",
|
||||
)
|
||||
|
||||
|
||||
# fill in manual post events
|
||||
if d.status_id == -2 and d.man_posted_by:
|
||||
if d.man_posted_by == "Amy Vezza":
|
||||
d.man_posted_by = "Amy K. Vezza"
|
||||
|
||||
try:
|
||||
by = orm["person.Person"].objects.get(name=d.man_posted_by)
|
||||
orm.SubmissionEvent.objects.get_or_create(
|
||||
submission=d,
|
||||
time=d.man_posted_date or d.submission_date,
|
||||
by=by,
|
||||
desc="Posted submission manually",
|
||||
)
|
||||
except models.ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
# update the new revision doc events that are set to
|
||||
# "(System)" with our newly discovered submitter
|
||||
if submitter_person and d.state_id == "posted":
|
||||
orm["doc.NewRevisionDocEvent"].objects.filter(doc=d.name, rev=d.rev, type="new_revision", by=0).update(by=submitter_person)
|
||||
|
||||
# update the submission itself
|
||||
orm.Submission.objects.filter(pk=d.pk).update(
|
||||
submitter=submitter,
|
||||
state=state,
|
||||
authors="\n".join(authors),
|
||||
access_key=access_key,
|
||||
)
|
||||
|
||||
|
||||
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.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.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', 'db_index': 'True'}),
|
||||
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'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.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.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'})
|
||||
},
|
||||
'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.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.draftsubmissionstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
|
||||
'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'})
|
||||
},
|
||||
'submit.submission': {
|
||||
'Meta': {'object_name': 'Submission'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'auth_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'document_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_types': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'first_two_pages': ('django.db.models.fields.TextField', [], {'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'}),
|
||||
'idnits_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'man_posted_by': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'man_posted_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'remote_ip': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'replaces': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'submitter': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'default': "'uploaded'", 'to': "orm['name.DraftSubmissionStateName']"}),
|
||||
'status': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.IdSubmissionStatus']", 'null': 'True', 'db_column': "'status_id'", 'blank': 'True'}),
|
||||
'sub_email_priority': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'submission_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}),
|
||||
'access_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'submitter_tag': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'authors': ('django.db.models.fields.TextField', [], {'blank': 'True'})
|
||||
},
|
||||
'submit.submissionevent': {
|
||||
'Meta': {'ordering': "('-time', '-id')", 'object_name': 'SubmissionEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.Submission']"}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
},
|
||||
'submit.idsubmissionstatus': {
|
||||
'Meta': {'object_name': 'IdSubmissionStatus'},
|
||||
'status_id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
|
||||
'status_value': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'submit.preapproval': {
|
||||
'Meta': {'object_name': 'Preapproval'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'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'})
|
||||
},
|
||||
'submit.tempidauthors': {
|
||||
'Meta': {'object_name': 'TempIdAuthors'},
|
||||
'author_order': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'email_address': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'id_document_tag': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
|
||||
'last_modified_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'last_modified_time': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'middle_initial': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'name_suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.Submission']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['submit']
|
|
@ -0,0 +1,301 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Deleting model 'TempIdAuthors'
|
||||
db.delete_table('submit_tempidauthors')
|
||||
|
||||
# Deleting model 'IdSubmissionStatus'
|
||||
db.delete_table('submit_idsubmissionstatus')
|
||||
|
||||
# Deleting field 'Submission.man_posted_date'
|
||||
db.delete_column('submit_submission', 'man_posted_date')
|
||||
|
||||
# Deleting field 'Submission.status'
|
||||
db.delete_column('submit_submission', 'status_id')
|
||||
|
||||
# Deleting field 'Submission.submitter_tag'
|
||||
db.delete_column('submit_submission', 'submitter_tag')
|
||||
|
||||
# Deleting field 'Submission.sub_email_priority'
|
||||
db.delete_column('submit_submission', 'sub_email_priority')
|
||||
|
||||
# Deleting field 'Submission.man_posted_by'
|
||||
db.delete_column('submit_submission', 'man_posted_by')
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Adding model 'TempIdAuthors'
|
||||
db.create_table('submit_tempidauthors', (
|
||||
('last_name', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
|
||||
('last_modified_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True)),
|
||||
('id_document_tag', self.gf('django.db.models.fields.IntegerField')(default=-1)),
|
||||
('last_modified_time', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
|
||||
('email_address', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
|
||||
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('middle_initial', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
|
||||
('first_name', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
|
||||
('submission', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['submit.Submission'])),
|
||||
('name_suffix', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True)),
|
||||
('author_order', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal('submit', ['TempIdAuthors'])
|
||||
|
||||
# Adding model 'IdSubmissionStatus'
|
||||
db.create_table('submit_idsubmissionstatus', (
|
||||
('status_value', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True)),
|
||||
('status_id', self.gf('django.db.models.fields.IntegerField')(primary_key=True)),
|
||||
))
|
||||
db.send_create_signal('submit', ['IdSubmissionStatus'])
|
||||
|
||||
# Adding field 'Submission.man_posted_date'
|
||||
db.add_column('submit_submission', 'man_posted_date', self.gf('django.db.models.fields.DateField')(null=True, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'Submission.status'
|
||||
db.add_column('submit_submission', 'status', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['submit.IdSubmissionStatus'], null=True, db_column='status_id', blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'Submission.submitter_tag'
|
||||
db.add_column('submit_submission', 'submitter_tag', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'Submission.sub_email_priority'
|
||||
db.add_column('submit_submission', 'sub_email_priority', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
|
||||
|
||||
# Adding field 'Submission.man_posted_by'
|
||||
db.add_column('submit_submission', 'man_posted_by', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), keep_default=False)
|
||||
|
||||
|
||||
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.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.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.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'})
|
||||
},
|
||||
'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.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.draftsubmissionstatename': {
|
||||
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
|
||||
'desc': ('django.db.models.fields.TextField', [], {'blank': '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['name.DraftSubmissionStateName']"}),
|
||||
'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'})
|
||||
},
|
||||
'submit.preapproval': {
|
||||
'Meta': {'object_name': 'Preapproval'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
|
||||
'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'})
|
||||
},
|
||||
'submit.submission': {
|
||||
'Meta': {'object_name': 'Submission'},
|
||||
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'access_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'auth_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'authors': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'document_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_size': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'file_types': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
|
||||
'first_two_pages': ('django.db.models.fields.TextField', [], {'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'}),
|
||||
'idnits_message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'remote_ip': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'replaces': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'rev': ('django.db.models.fields.CharField', [], {'max_length': '3', 'blank': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DraftSubmissionStateName']"}),
|
||||
'submission_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.date.today'}),
|
||||
'submitter': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'})
|
||||
},
|
||||
'submit.submissionevent': {
|
||||
'Meta': {'ordering': "('-time', '-id')", 'object_name': 'SubmissionEvent'},
|
||||
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
|
||||
'desc': ('django.db.models.fields.TextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'submission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['submit.Submission']"}),
|
||||
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['submit']
|
|
@ -5,64 +5,73 @@ from django.db import models
|
|||
|
||||
from ietf.person.models import Person
|
||||
from ietf.group.models import Group
|
||||
from ietf.name.models import DraftSubmissionStateName
|
||||
from ietf.utils.uniquekey import generate_unique_key
|
||||
|
||||
|
||||
class IdSubmissionStatus(models.Model):
|
||||
status_id = models.IntegerField(primary_key=True)
|
||||
status_value = models.CharField(blank=True, max_length=255)
|
||||
def parse_email_line(line):
|
||||
"""Split line on the form 'Some Name <email@example.com>'"""
|
||||
m = re.match("([^<]+) <([^>]+)>$", line)
|
||||
if m:
|
||||
return dict(name=m.group(1), email=m.group(2))
|
||||
else:
|
||||
return dict(name=line, email="")
|
||||
|
||||
class Submission(models.Model):
|
||||
state = models.ForeignKey(DraftSubmissionStateName)
|
||||
remote_ip = models.CharField(max_length=100, blank=True)
|
||||
|
||||
access_key = models.CharField(max_length=255, default=generate_unique_key)
|
||||
auth_key = models.CharField(max_length=255, blank=True)
|
||||
|
||||
# draft metadata
|
||||
name = models.CharField(max_length=255, db_index=True)
|
||||
group = models.ForeignKey(Group, null=True, blank=True)
|
||||
title = models.CharField(max_length=255, blank=True)
|
||||
abstract = models.TextField(blank=True)
|
||||
rev = models.CharField(max_length=3, blank=True)
|
||||
pages = models.IntegerField(null=True, blank=True)
|
||||
authors = models.TextField(blank=True, help_text="List of author names and emails, one author per line, e.g. \"John Doe <john@example.org>\"")
|
||||
note = models.TextField(blank=True)
|
||||
replaces = models.CharField(max_length=255, blank=True)
|
||||
|
||||
first_two_pages = models.TextField(blank=True)
|
||||
file_types = models.CharField(max_length=50, blank=True)
|
||||
file_size = models.IntegerField(null=True, blank=True)
|
||||
document_date = models.DateField(null=True, blank=True)
|
||||
submission_date = models.DateField(default=datetime.date.today)
|
||||
|
||||
submitter = models.CharField(max_length=255, blank=True, help_text="Name and email of submitter, e.g. \"John Doe <john@example.org>\"")
|
||||
|
||||
idnits_message = models.TextField(blank=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.status_value
|
||||
return u"%s-%s" % (self.name, self.rev)
|
||||
|
||||
class IdSubmissionDetail(models.Model):
|
||||
submission_id = models.AutoField(primary_key=True)
|
||||
temp_id_document_tag = models.IntegerField(null=True, blank=True)
|
||||
status = models.ForeignKey(IdSubmissionStatus, db_column='status_id', null=True, blank=True)
|
||||
last_updated_date = models.DateField(null=True, blank=True)
|
||||
last_updated_time = models.CharField(null=True, blank=True, max_length=25)
|
||||
id_document_name = models.CharField(null=True, blank=True, max_length=255)
|
||||
group_acronym = models.ForeignKey(Group, null=True, blank=True)
|
||||
filename = models.CharField(null=True, blank=True, max_length=255, db_index=True)
|
||||
creation_date = models.DateField(null=True, blank=True)
|
||||
submission_date = models.DateField(null=True, blank=True)
|
||||
remote_ip = models.CharField(null=True, blank=True, max_length=100)
|
||||
revision = models.CharField(null=True, blank=True, max_length=3)
|
||||
submitter_tag = models.IntegerField(null=True, blank=True)
|
||||
auth_key = models.CharField(null=True, blank=True, max_length=255)
|
||||
idnits_message = models.TextField(null=True, blank=True)
|
||||
file_type = models.CharField(null=True, blank=True, max_length=50)
|
||||
comment_to_sec = models.TextField(null=True, blank=True)
|
||||
abstract = models.TextField(null=True, blank=True)
|
||||
txt_page_count = models.IntegerField(null=True, blank=True)
|
||||
error_message = models.CharField(null=True, blank=True, max_length=255)
|
||||
warning_message = models.TextField(null=True, blank=True)
|
||||
wg_submission = models.IntegerField(null=True, blank=True)
|
||||
filesize = models.IntegerField(null=True, blank=True)
|
||||
man_posted_date = models.DateField(null=True, blank=True)
|
||||
man_posted_by = models.CharField(null=True, blank=True, max_length=255)
|
||||
first_two_pages = models.TextField(null=True, blank=True)
|
||||
sub_email_priority = models.IntegerField(null=True, blank=True)
|
||||
invalid_version = models.IntegerField(null=True, blank=True)
|
||||
idnits_failed = models.IntegerField(null=True, blank=True)
|
||||
submission_hash = models.CharField(null=True, blank=True, max_length=255)
|
||||
replaces = models.CharField(null=True, blank=True, max_length=255)
|
||||
def authors_parsed(self):
|
||||
res = []
|
||||
for line in self.authors.replace("\r", "").split("\n"):
|
||||
line = line.strip()
|
||||
if line:
|
||||
res.append(parse_email_line(line))
|
||||
return res
|
||||
|
||||
def submitter_parsed(self):
|
||||
return parse_email_line(self.submitter)
|
||||
|
||||
|
||||
class SubmissionEvent(models.Model):
|
||||
submission = models.ForeignKey(Submission)
|
||||
time = models.DateTimeField(default=datetime.datetime.now)
|
||||
by = models.ForeignKey(Person, null=True, blank=True)
|
||||
desc = models.TextField()
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s-%s" % (self.filename, self.revision)
|
||||
return u"%s %s by %s at %s" % (self.submission.name, self.desc, self.by.plain_name() if self.by else "(unknown)", self.time)
|
||||
|
||||
def create_hash(self):
|
||||
self.submission_hash = hashlib.md5(settings.SECRET_KEY + self.filename).hexdigest()
|
||||
class Meta:
|
||||
ordering = ("-time", "-id")
|
||||
|
||||
def get_hash(self):
|
||||
if not self.submission_hash:
|
||||
self.create_hash()
|
||||
self.save()
|
||||
return self.submission_hash
|
||||
|
||||
def create_submission_hash(sender, instance, **kwargs):
|
||||
instance.create_hash()
|
||||
|
||||
models.signals.pre_save.connect(create_submission_hash, sender=IdSubmissionDetail)
|
||||
|
||||
class Preapproval(models.Model):
|
||||
"""Pre-approved draft submission name."""
|
||||
|
@ -72,25 +81,3 @@ class Preapproval(models.Model):
|
|||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class TempIdAuthors(models.Model):
|
||||
id_document_tag = models.IntegerField()
|
||||
first_name = models.CharField(blank=True, max_length=255) # with new schema, this contains the full name while the other name fields are empty to avoid loss of information
|
||||
last_name = models.CharField(blank=True, max_length=255)
|
||||
email_address = models.CharField(blank=True, max_length=255)
|
||||
last_modified_date = models.DateField(null=True, blank=True)
|
||||
last_modified_time = models.CharField(blank=True, max_length=100)
|
||||
author_order = models.IntegerField(null=True, blank=True)
|
||||
submission = models.ForeignKey(IdSubmissionDetail)
|
||||
middle_initial = models.CharField(blank=True, max_length=255, null=True)
|
||||
name_suffix = models.CharField(blank=True, max_length=255, null=True)
|
||||
|
||||
def email(self):
|
||||
return (self.get_full_name(), self.email_address)
|
||||
|
||||
def get_full_name(self):
|
||||
parts = (self.first_name or '', self.middle_initial or '', self.last_name or '', self.name_suffix or '')
|
||||
return u" ".join(x.strip() for x in parts if x.strip())
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s <%s>" % self.email()
|
||||
|
|
|
@ -1,26 +1,28 @@
|
|||
import re
|
||||
|
||||
|
||||
CUTOFF_HOUR = 17
|
||||
|
||||
|
||||
class MetaDataDraft(object):
|
||||
revision = None
|
||||
filename = None
|
||||
class MetaData(object):
|
||||
rev = None
|
||||
name = None
|
||||
group = None
|
||||
filesize = None
|
||||
file_size = None
|
||||
first_two_pages = None
|
||||
page_count = None
|
||||
pages = None
|
||||
submission_date = None
|
||||
creation_date = None
|
||||
document_date = None
|
||||
authors = None
|
||||
|
||||
class ParseInfo(object):
|
||||
"""Collect errors from a parse"""
|
||||
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
# warnings are currently unused by the parsers
|
||||
self.warnings = {}
|
||||
self.metadraft = MetaDataDraft()
|
||||
# the metadata fields are currently unused, i.e. the plain
|
||||
# text parser fills in some fields but they are not used
|
||||
# anywhere (instead the draft parser is used for .txt and the
|
||||
# other file types have no actual parsing at the moment)
|
||||
self.metadata = MetaData()
|
||||
|
||||
def add_error(self, error_str):
|
||||
self.errors.append(error_str)
|
||||
|
|
|
@ -17,14 +17,14 @@ class PlainParser(FileParser):
|
|||
super(PlainParser, self).critical_parse()
|
||||
self.parse_max_size()
|
||||
self.parse_file_charset()
|
||||
self.parse_filename()
|
||||
self.parse_name()
|
||||
return self.parsed_info
|
||||
|
||||
def parse_max_size(self):
|
||||
if self.fd.size > settings.MAX_PLAIN_DRAFT_SIZE:
|
||||
self.parsed_info.add_error('File size is larger than %s' % filesizeformat(settings.MAX_PLAIN_DRAFT_SIZE))
|
||||
self.parsed_info.metadraft.filesize = self.fd.size
|
||||
self.parsed_info.metadraft.submission_date = datetime.date.today()
|
||||
if self.fd.size > settings.IDSUBMIT_MAX_PLAIN_DRAFT_SIZE:
|
||||
self.parsed_info.add_error('File size is larger than %s' % filesizeformat(settings.IDSUBMIT_MAX_PLAIN_DRAFT_SIZE))
|
||||
self.parsed_info.metadata.file_size = self.fd.size
|
||||
self.parsed_info.metadata.submission_date = datetime.date.today()
|
||||
|
||||
def parse_file_charset(self):
|
||||
import magic
|
||||
|
@ -40,9 +40,9 @@ class PlainParser(FileParser):
|
|||
magic.magic_load(m.cookie, None)
|
||||
filetype = m.from_buffer(content)
|
||||
if not 'ascii' in filetype:
|
||||
self.parsed_info.add_error('A plain text document must be submitted.')
|
||||
self.parsed_info.add_error('A plain text ASCII document must be submitted.')
|
||||
|
||||
def parse_filename(self):
|
||||
def parse_name(self):
|
||||
self.fd.file.seek(0)
|
||||
draftre = re.compile('(draft-\S+)')
|
||||
revisionre = re.compile('.*-(\d+)$')
|
||||
|
@ -53,24 +53,24 @@ class PlainParser(FileParser):
|
|||
match = draftre.search(line)
|
||||
if not match:
|
||||
continue
|
||||
filename = match.group(1)
|
||||
filename = re.sub('^[^\w]+', '', filename)
|
||||
filename = re.sub('[^\w]+$', '', filename)
|
||||
filename = re.sub('\.txt$', '', filename)
|
||||
extra_chars = re.sub('[0-9a-z\-]', '', filename)
|
||||
name = match.group(1)
|
||||
name = re.sub('^[^\w]+', '', name)
|
||||
name = re.sub('[^\w]+$', '', name)
|
||||
name = re.sub('\.txt$', '', name)
|
||||
extra_chars = re.sub('[0-9a-z\-]', '', name)
|
||||
if extra_chars:
|
||||
if len(extra_chars) == 1:
|
||||
self.parsed_info.add_error((u'The filename contains a disallowed character: %s ' % (', '.join(set(extra_chars))).decode('ascii','replace')) +
|
||||
self.parsed_info.add_error((u'The name contains a disallowed character: %s ' % (', '.join(set(extra_chars))).decode('ascii','replace')) +
|
||||
u'(see http://www.ietf.org/id-info/guidelines.html#naming for details).')
|
||||
else:
|
||||
self.parsed_info.add_error((u'The filename contains disallowed characters: %s ' % (', '.join(set(extra_chars))).decode('ascii','replace')) +
|
||||
self.parsed_info.add_error((u'The name contains disallowed characters: %s ' % (', '.join(set(extra_chars))).decode('ascii','replace')) +
|
||||
u'(see http://www.ietf.org/id-info/guidelines.html#naming for details).')
|
||||
match_revision = revisionre.match(filename)
|
||||
match_revision = revisionre.match(name)
|
||||
if match_revision:
|
||||
self.parsed_info.metadraft.revision = match_revision.group(1)
|
||||
self.parsed_info.metadata.rev = match_revision.group(1)
|
||||
else:
|
||||
self.parsed_info.add_error(u'The filename found on the first page of the document does not contain a revision: "%s"' % (filename,))
|
||||
filename = re.sub('-\d+$', '', filename)
|
||||
self.parsed_info.metadraft.filename = filename
|
||||
self.parsed_info.add_error(u'The name found on the first page of the document does not contain a revision: "%s"' % (name,))
|
||||
name = re.sub('-\d+$', '', name)
|
||||
self.parsed_info.metadata.name = name
|
||||
return
|
||||
self.parsed_info.add_error('The first page of the document does not contain a legitimate filename that start with draft-*')
|
||||
self.parsed_info.add_error('The first page of the document does not contain a legitimate name that start with draft-*')
|
||||
|
|
|
@ -4,40 +4,37 @@ from django import template
|
|||
from django.conf import settings
|
||||
from django.utils.html import mark_safe, escape
|
||||
|
||||
from ietf.submit.utils import POSTED, POSTED_BY_SECRETARIAT
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.inclusion_tag('submit/submission_files.html', takes_context=True)
|
||||
def show_submission_files(context, submission):
|
||||
result = []
|
||||
for ext in submission.file_type.split(','):
|
||||
for ext in submission.file_types.split(','):
|
||||
exists = False
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.filename, submission.revision, ext))
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, submission.rev, ext))
|
||||
if os.path.exists(source):
|
||||
exists = True
|
||||
elif submission.status_id in [POSTED, POSTED_BY_SECRETARIAT]:
|
||||
elif submission.state_id == "posted":
|
||||
continue
|
||||
result.append({'name': '[%s version ]' % ext[1:].capitalize(),
|
||||
result.append({'name': '[%s version]' % ext[1:].upper(),
|
||||
'exists': exists,
|
||||
'url': '%s%s-%s%s' % (settings.IDSUBMIT_STAGING_URL, submission.filename, submission.revision, ext)})
|
||||
'url': '%s%s-%s%s' % (settings.IDSUBMIT_STAGING_URL, submission.name, submission.rev, ext)})
|
||||
return {'files': result}
|
||||
|
||||
|
||||
@register.filter
|
||||
def two_pages_decorated_with_validation(value, validation):
|
||||
pages = value.first_two_pages or ''
|
||||
if not 'revision' in validation.warnings.keys():
|
||||
return mark_safe('<pre class="twopages" style="display: none;">%s</pre>' % escape(pages))
|
||||
result = '<pre class="twopages" style="display: none;">\n'
|
||||
def two_pages_decorated_with_errors(submission, errors):
|
||||
pages = submission.first_two_pages or ''
|
||||
if 'rev' not in errors.keys():
|
||||
return mark_safe('<pre class="twopages">%s</pre>' % escape(pages))
|
||||
result = '<pre class="twopages">\n'
|
||||
for line in pages.split('\n'):
|
||||
if line.find('%s-%s' % (value.filename, value.revision)) > -1:
|
||||
result += '</pre><pre class="twopages" style="display: none; background: red;">'
|
||||
if line.find('%s-%s' % (submission.name, submission.rev)) > -1:
|
||||
result += '</pre><pre class="twopages" style="background: red;">'
|
||||
result += escape(line)
|
||||
result += '\n'
|
||||
result += '</pre><pre class="twopages" style="display: none;">\n'
|
||||
result += '</pre><pre class="twopages">\n'
|
||||
else:
|
||||
result += escape(line)
|
||||
result += '\n'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
Informational Test Name
|
||||
Informational Author Name
|
||||
Internet-Draft Test Center Inc.
|
||||
Intended status: Informational %(date)s
|
||||
Expires: %(expire)s
|
||||
|
||||
|
||||
Testing tests
|
||||
%(filename)s
|
||||
%(name)s
|
||||
|
||||
|
||||
Abstract
|
||||
|
@ -94,12 +94,13 @@ Internet-Draft Testing tests %(month_year)s
|
|||
|
||||
Authors' Addresses
|
||||
|
||||
Test Name
|
||||
Author Name
|
||||
Test Center Inc.
|
||||
Some way 42
|
||||
Some Where, NY
|
||||
42 Some Road
|
||||
Some Where 12345
|
||||
US
|
||||
|
||||
Email: testname@example.com
|
||||
Email: author@example.com
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -17,11 +17,9 @@ from ietf.utils.mail import outbox
|
|||
from ietf.person.models import Person, Email
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.doc.models import *
|
||||
from ietf.submit.models import IdSubmissionDetail, Preapproval
|
||||
from ietf.submit.models import Submission, Preapproval
|
||||
|
||||
class SubmitTests(django.test.TestCase):
|
||||
fixtures = ['idsubmissionstatus']
|
||||
|
||||
def setUp(self):
|
||||
self.staging_dir = os.path.abspath("tmp-submit-staging-dir")
|
||||
os.mkdir(self.staging_dir)
|
||||
|
@ -40,17 +38,7 @@ class SubmitTests(django.test.TestCase):
|
|||
shutil.rmtree(self.repository_dir)
|
||||
shutil.rmtree(self.archive_dir)
|
||||
|
||||
def do_submission(self, name, rev):
|
||||
# break early in case of missing configuration
|
||||
self.assertTrue(os.path.exists(settings.IDSUBMIT_IDNITS_BINARY))
|
||||
|
||||
# get
|
||||
url = urlreverse('submit_index')
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=file][name=txt]')), 1)
|
||||
|
||||
def submission_txt_file(self, name, rev):
|
||||
# construct appropriate text draft
|
||||
f = open(os.path.join(settings.BASE_DIR, "submit", "test_submission.txt"))
|
||||
template = f.read()
|
||||
|
@ -61,58 +49,86 @@ class SubmitTests(django.test.TestCase):
|
|||
expire=(datetime.date.today() + datetime.timedelta(days=100)).strftime("%Y-%m-%d"),
|
||||
year=datetime.date.today().strftime("%Y"),
|
||||
month_year=datetime.date.today().strftime("%B, %Y"),
|
||||
filename="%s-%s" % (name, rev),
|
||||
name="%s-%s" % (name, rev),
|
||||
)
|
||||
|
||||
test_file = StringIO(str(submission_text))
|
||||
test_file.name = "somename.txt"
|
||||
txt_file = StringIO(str(submission_text))
|
||||
txt_file.name = "somename.txt"
|
||||
return txt_file
|
||||
|
||||
def do_submission(self, name, rev):
|
||||
# break early in case of missing configuration
|
||||
self.assertTrue(os.path.exists(settings.IDSUBMIT_IDNITS_BINARY))
|
||||
|
||||
# get
|
||||
url = urlreverse('submit_upload_submission')
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=file][name=txt]')), 1)
|
||||
|
||||
# submit
|
||||
txt_file = self.submission_txt_file(name, rev)
|
||||
|
||||
r = self.client.post(url,
|
||||
dict(txt=test_file))
|
||||
dict(txt=txt_file))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
supply_submitter_url = r["Location"]
|
||||
status_url = r["Location"]
|
||||
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
|
||||
self.assertEquals(IdSubmissionDetail.objects.filter(filename=name).count(), 1)
|
||||
submission = IdSubmissionDetail.objects.get(filename=name)
|
||||
self.assertEquals(submission.tempidauthors_set.count(), 1)
|
||||
self.assertEquals(Submission.objects.filter(name=name).count(), 1)
|
||||
submission = Submission.objects.get(name=name)
|
||||
self.assertTrue(re.search('\s+Summary:\s+0\s+errors|No nits found', submission.idnits_message))
|
||||
author = submission.tempidauthors_set.all()[0]
|
||||
self.assertEquals(author.first_name, "Test Name")
|
||||
self.assertEquals(len(submission.authors_parsed()), 1)
|
||||
author = submission.authors_parsed()[0]
|
||||
self.assertEquals(author["name"], "Author Name")
|
||||
self.assertEquals(author["email"], "author@example.com")
|
||||
|
||||
return supply_submitter_url
|
||||
return status_url
|
||||
|
||||
def supply_submitter(self, name, supply_submitter_url):
|
||||
def supply_submitter(self, name, status_url, submitter_name, submitter_email):
|
||||
# check the page
|
||||
r = self.client.get(supply_submitter_url)
|
||||
r = self.client.get(status_url)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=submit][name=autopost]')), 1)
|
||||
post_button = q('input[type=submit][value*="Post"]')
|
||||
self.assertEquals(len(post_button), 1)
|
||||
action = post_button.parents("form").find('input[type=hidden][name="action"]').val()
|
||||
|
||||
# post submitter info
|
||||
r = self.client.post(supply_submitter_url,
|
||||
dict(autopost="1",
|
||||
name="Test Name",
|
||||
email="testname@example.com",
|
||||
))
|
||||
# submitter is saved as author order 0
|
||||
submission = IdSubmissionDetail.objects.get(filename=name)
|
||||
self.assertEquals(submission.tempidauthors_set.count(), 2)
|
||||
self.assertEquals(submission.tempidauthors_set.get(author_order=0).first_name, "Test Name")
|
||||
r = self.client.post(status_url, {
|
||||
"action": action,
|
||||
"submitter-name": submitter_name,
|
||||
"submitter-email": submitter_email,
|
||||
})
|
||||
|
||||
submission = Submission.objects.get(name=name)
|
||||
self.assertEquals(submission.submitter, u"%s <%s>" % (submitter_name, submitter_email))
|
||||
|
||||
return r
|
||||
|
||||
def test_submit_new(self):
|
||||
def extract_confirm_url(self, confirm_email):
|
||||
# dig out confirm_email link
|
||||
msg = confirm_email.get_payload(decode=True)
|
||||
line_start = "http"
|
||||
confirm_url = None
|
||||
for line in msg.split("\n"):
|
||||
if line.strip().startswith(line_start):
|
||||
confirm_url = line.strip()
|
||||
self.assertTrue(confirm_url)
|
||||
|
||||
return confirm_url
|
||||
|
||||
def test_submit_new_wg(self):
|
||||
# submit new -> supply submitter info -> approve
|
||||
draft = make_test_data()
|
||||
|
||||
name = "draft-ietf-mars-testing-tests"
|
||||
rev = "00"
|
||||
|
||||
supply_submitter_url = self.do_submission(name, rev)
|
||||
status_url = self.do_submission(name, rev)
|
||||
|
||||
# supply submitter info, then draft should be in and ready for approval
|
||||
mailbox_before = len(outbox)
|
||||
r = self.supply_submitter(name, supply_submitter_url)
|
||||
r = self.supply_submitter(name, status_url, "Author Name", "author@example.com")
|
||||
|
||||
self.assertEquals(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
|
@ -126,13 +142,14 @@ class SubmitTests(django.test.TestCase):
|
|||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
approve_submit = q('input[type=submit][value*="Approve"]')
|
||||
self.assertEquals(len(approve_submit), 1)
|
||||
approve_button = q('input[type=submit][value*="Approve"]')
|
||||
self.assertEquals(len(approve_button), 1)
|
||||
|
||||
action = approve_button.parents("form").find('input[type=hidden][name="action"]').val()
|
||||
|
||||
# approve submission
|
||||
mailbox_before = len(outbox)
|
||||
approve_url = approve_submit.parents("form").attr("action")
|
||||
r = self.client.post(approve_url, dict())
|
||||
r = self.client.post(status_url, dict(action=action))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(docalias__name=name)
|
||||
|
@ -140,7 +157,7 @@ class SubmitTests(django.test.TestCase):
|
|||
new_revision = draft.latest_event()
|
||||
self.assertEquals(draft.group.acronym, "mars")
|
||||
self.assertEquals(new_revision.type, "new_revision")
|
||||
self.assertEquals(new_revision.by.name, "Test Name")
|
||||
self.assertEquals(new_revision.by.name, "Author Name")
|
||||
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
|
||||
self.assertTrue(os.path.exists(os.path.join(self.repository_dir, u"%s-%s.txt" % (name, rev))))
|
||||
self.assertEquals(draft.type_id, "draft")
|
||||
|
@ -148,18 +165,19 @@ class SubmitTests(django.test.TestCase):
|
|||
self.assertTrue(draft.expires >= datetime.datetime.now() + datetime.timedelta(days=settings.INTERNET_DRAFT_DAYS_TO_EXPIRE - 1))
|
||||
self.assertEquals(draft.get_state("draft-stream-%s" % draft.stream_id).slug, "wg-doc")
|
||||
self.assertEquals(draft.authors.count(), 1)
|
||||
self.assertEquals(draft.authors.all()[0].get_name(), "Test Name")
|
||||
self.assertEquals(draft.authors.all()[0].address, "testname@example.com")
|
||||
self.assertEquals(draft.authors.all()[0].get_name(), "Author Name")
|
||||
self.assertEquals(draft.authors.all()[0].address, "author@example.com")
|
||||
self.assertEquals(len(outbox), mailbox_before + 2)
|
||||
self.assertTrue((u"I-D Action: %s" % name) in outbox[-2]["Subject"])
|
||||
self.assertTrue("Test Name" in unicode(outbox[-2]))
|
||||
self.assertTrue("Author Name" in unicode(outbox[-2]))
|
||||
self.assertTrue("New Version Notification" in outbox[-1]["Subject"])
|
||||
self.assertTrue(name in unicode(outbox[-1]))
|
||||
self.assertTrue("mars" in unicode(outbox[-1]))
|
||||
|
||||
def test_submit_existing(self):
|
||||
# submit new revision of existing -> supply submitter info -> confirm
|
||||
# submit new revision of existing -> supply submitter info -> prev authors confirm
|
||||
draft = make_test_data()
|
||||
prev_author = draft.documentauthor_set.all()[0]
|
||||
|
||||
# pretend IANA reviewed it
|
||||
draft.set_state(State.objects.get(used=True, type="draft-iana-review", slug="not-ok"))
|
||||
|
@ -188,45 +206,43 @@ class SubmitTests(django.test.TestCase):
|
|||
with open(os.path.join(self.repository_dir, "%s-%s.txt" % (name, old_rev)), 'w') as f:
|
||||
f.write("a" * 2000)
|
||||
|
||||
supply_submitter_url = self.do_submission(name, rev)
|
||||
status_url = self.do_submission(name, rev)
|
||||
|
||||
# supply submitter info, then we get a confirmation email
|
||||
# supply submitter info, then previous authors get a confirmation email
|
||||
mailbox_before = len(outbox)
|
||||
r = self.supply_submitter(name, supply_submitter_url)
|
||||
|
||||
r = self.supply_submitter(name, status_url, "Submitter Name", "submitter@example.com")
|
||||
self.assertEquals(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertTrue("Your submission is pending email authentication" in r.content)
|
||||
self.assertTrue("The submission is pending approval by the authors" in r.content)
|
||||
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
confirmation = outbox[-1]
|
||||
self.assertTrue("Confirmation for" in confirmation["Subject"])
|
||||
self.assertTrue(name in confirmation["Subject"])
|
||||
confirm_email = outbox[-1]
|
||||
self.assertTrue("Confirm submission" in confirm_email["Subject"])
|
||||
self.assertTrue(name in confirm_email["Subject"])
|
||||
self.assertTrue(prev_author.author.address in confirm_email["To"])
|
||||
# submitter and new author can't confirm
|
||||
self.assertTrue("author@example.com" not in confirm_email["To"])
|
||||
self.assertTrue("submitter@example.com" not in confirm_email["To"])
|
||||
|
||||
# dig out confirmation link
|
||||
msg = confirmation.get_payload(decode=True)
|
||||
line_start = "Confirmation URL:"
|
||||
self.assertTrue(line_start in msg)
|
||||
confirm_url = None
|
||||
for line in msg.split("\n"):
|
||||
if line.startswith(line_start):
|
||||
confirm_url = line[len(line_start):].strip()
|
||||
confirm_url = self.extract_confirm_url(confirm_email)
|
||||
|
||||
# go to confirm page
|
||||
r = self.client.get(confirm_url)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=submit][value=Auto-Post]')), 1)
|
||||
self.assertEquals(len(q('input[type=submit][value*="Confirm"]')), 1)
|
||||
|
||||
# confirm
|
||||
mailbox_before = len(outbox)
|
||||
r = self.client.post(confirm_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertTrue('Authorization key accepted' in r.content)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(docalias__name=name)
|
||||
self.assertEquals(draft.rev, rev)
|
||||
self.assertEquals(draft.group.acronym, name.split("-")[2])
|
||||
self.assertEquals(draft.docevent_set.all()[1].type, "new_revision")
|
||||
self.assertEquals(draft.docevent_set.all()[1].by.name, "Test Name")
|
||||
self.assertEquals(draft.docevent_set.all()[1].by.name, "Submitter Name")
|
||||
self.assertTrue(not os.path.exists(os.path.join(self.repository_dir, "%s-%s.txt" % (name, old_rev))))
|
||||
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, "%s-%s.txt" % (name, old_rev))))
|
||||
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
|
||||
|
@ -236,12 +252,12 @@ class SubmitTests(django.test.TestCase):
|
|||
self.assertEquals(draft.get_state_slug("draft-stream-%s" % draft.stream_id), "wg-doc")
|
||||
self.assertEquals(draft.get_state_slug("draft-iana-review"), "changed")
|
||||
self.assertEquals(draft.authors.count(), 1)
|
||||
self.assertEquals(draft.authors.all()[0].get_name(), "Test Name")
|
||||
self.assertEquals(draft.authors.all()[0].address, "testname@example.com")
|
||||
self.assertEquals(draft.authors.all()[0].get_name(), "Author Name")
|
||||
self.assertEquals(draft.authors.all()[0].address, "author@example.com")
|
||||
self.assertEquals(len(outbox), mailbox_before + 3)
|
||||
self.assertTrue((u"I-D Action: %s" % name) in outbox[-3]["Subject"])
|
||||
self.assertTrue((u"I-D Action: %s" % name) in draft.message_set.order_by("-time")[0].subject)
|
||||
self.assertTrue("Test Name" in unicode(outbox[-3]))
|
||||
self.assertTrue("Author Name" in unicode(outbox[-3]))
|
||||
self.assertTrue("New Version Notification" in outbox[-2]["Subject"])
|
||||
self.assertTrue(name in unicode(outbox[-2]))
|
||||
self.assertTrue("mars" in unicode(outbox[-2]))
|
||||
|
@ -251,6 +267,51 @@ class SubmitTests(django.test.TestCase):
|
|||
self.assertTrue(name in unicode(outbox[-1]))
|
||||
self.assertTrue("mars" in unicode(outbox[-1]))
|
||||
|
||||
def test_submit_new_individual(self):
|
||||
# submit new -> supply submitter info -> confirm
|
||||
draft = make_test_data()
|
||||
|
||||
name = "draft-authorname-testing-tests"
|
||||
rev = "00"
|
||||
|
||||
status_url = self.do_submission(name, rev)
|
||||
|
||||
# supply submitter info, then draft should be be ready for email auth
|
||||
mailbox_before = len(outbox)
|
||||
r = self.supply_submitter(name, status_url, "Submitter Name", "submitter@example.com")
|
||||
|
||||
self.assertEquals(r.status_code, 302)
|
||||
status_url = r["Location"]
|
||||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
self.assertTrue("The submission is pending email authentication" in r.content)
|
||||
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
confirm_email = outbox[-1]
|
||||
self.assertTrue("Confirm submission" in confirm_email["Subject"])
|
||||
self.assertTrue(name in confirm_email["Subject"])
|
||||
# both submitter and author get email
|
||||
self.assertTrue("author@example.com" in confirm_email["To"])
|
||||
self.assertTrue("submitter@example.com" in confirm_email["To"])
|
||||
|
||||
confirm_url = self.extract_confirm_url(outbox[-1])
|
||||
|
||||
# go to confirm page
|
||||
r = self.client.get(confirm_url)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=submit][value*="Confirm"]')), 1)
|
||||
|
||||
# confirm
|
||||
mailbox_before = len(outbox)
|
||||
r = self.client.post(confirm_url)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(docalias__name=name)
|
||||
self.assertEquals(draft.rev, rev)
|
||||
new_revision = draft.latest_event()
|
||||
self.assertEquals(new_revision.type, "new_revision")
|
||||
self.assertEquals(new_revision.by.name, "Submitter Name")
|
||||
|
||||
def test_submit_new_wg_with_dash(self):
|
||||
draft = make_test_data()
|
||||
|
||||
|
@ -260,7 +321,7 @@ class SubmitTests(django.test.TestCase):
|
|||
|
||||
self.do_submission(name, "00")
|
||||
|
||||
self.assertEquals(IdSubmissionDetail.objects.get(filename=name).group_acronym.acronym, group.acronym)
|
||||
self.assertEquals(Submission.objects.get(name=name).group.acronym, group.acronym)
|
||||
|
||||
def test_submit_new_irtf(self):
|
||||
draft = make_test_data()
|
||||
|
@ -271,8 +332,8 @@ class SubmitTests(django.test.TestCase):
|
|||
|
||||
self.do_submission(name, "00")
|
||||
|
||||
self.assertEquals(IdSubmissionDetail.objects.get(filename=name).group_acronym.acronym, group.acronym)
|
||||
self.assertEquals(IdSubmissionDetail.objects.get(filename=name).group_acronym.type_id, group.type_id)
|
||||
self.assertEquals(Submission.objects.get(name=name).group.acronym, group.acronym)
|
||||
self.assertEquals(Submission.objects.get(name=name).group.type_id, group.type_id)
|
||||
|
||||
def test_submit_new_iab(self):
|
||||
draft = make_test_data()
|
||||
|
@ -281,7 +342,7 @@ class SubmitTests(django.test.TestCase):
|
|||
|
||||
self.do_submission(name, "00")
|
||||
|
||||
self.assertEquals(IdSubmissionDetail.objects.get(filename=name).group_acronym.acronym, "iab")
|
||||
self.assertEquals(Submission.objects.get(name=name).group.acronym, "iab")
|
||||
|
||||
def test_cancel_submission(self):
|
||||
# submit -> cancel
|
||||
|
@ -290,38 +351,41 @@ class SubmitTests(django.test.TestCase):
|
|||
name = "draft-ietf-mars-testing-tests"
|
||||
rev = "00"
|
||||
|
||||
supply_submitter_url = self.do_submission(name, rev)
|
||||
status_url = self.do_submission(name, rev)
|
||||
|
||||
# check we got cancel button
|
||||
r = self.client.get(supply_submitter_url)
|
||||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
cancel_submission = q('input[type=submit][value*="Cancel"]')
|
||||
self.assertEquals(len(cancel_submission), 1)
|
||||
cancel_button = q('input[type=submit][value*="Cancel"]')
|
||||
self.assertEquals(len(cancel_button), 1)
|
||||
|
||||
cancel_url = cancel_submission.parents("form").attr("action")
|
||||
action = cancel_button.parents("form").find("input[type=hidden][name=\"action\"]").val()
|
||||
|
||||
# cancel
|
||||
r = self.client.post(cancel_url)
|
||||
r = self.client.post(status_url, dict(action=action))
|
||||
self.assertTrue(not os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
|
||||
|
||||
def test_edit_submission(self):
|
||||
def test_edit_submission_and_force_post(self):
|
||||
# submit -> edit
|
||||
draft = make_test_data()
|
||||
|
||||
name = "draft-ietf-mars-testing-tests"
|
||||
rev = "00"
|
||||
|
||||
supply_submitter_url = self.do_submission(name, rev)
|
||||
status_url = self.do_submission(name, rev)
|
||||
|
||||
# check we got edit button
|
||||
r = self.client.get(supply_submitter_url)
|
||||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[type=submit][value*="Adjust"]')), 1)
|
||||
adjust_button = q('input[type=submit][value*="Adjust"]')
|
||||
self.assertEquals(len(adjust_button), 1)
|
||||
|
||||
action = adjust_button.parents("form").find('input[type=hidden][name="action"]').val()
|
||||
|
||||
# go to edit, we do this by posting, slightly weird
|
||||
r = self.client.post(supply_submitter_url)
|
||||
r = self.client.post(status_url, dict(action=action))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
edit_url = r['Location']
|
||||
|
||||
|
@ -329,48 +393,67 @@ class SubmitTests(django.test.TestCase):
|
|||
r = self.client.get(edit_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('input[name=title]')), 1)
|
||||
self.assertEquals(len(q('input[name=edit-title]')), 1)
|
||||
|
||||
# edit
|
||||
mailbox_before = len(outbox)
|
||||
creation_date = datetime.date.today() - datetime.timedelta(days=-3)
|
||||
r = self.client.post(edit_url,
|
||||
dict(title="some title",
|
||||
version="00",
|
||||
creation_date=creation_date.strftime("%Y-%m-%d"),
|
||||
abstract="some abstract",
|
||||
pages="123",
|
||||
name="Some Random Test Person",
|
||||
email="random@example.com",
|
||||
comments="no comments",
|
||||
name_0="Person 1",
|
||||
email_0="person1@example.com",
|
||||
name_1="Person 2",
|
||||
email_1="person2@example.com",
|
||||
))
|
||||
document_date = datetime.date.today() - datetime.timedelta(days=-3)
|
||||
r = self.client.post(edit_url, {
|
||||
"edit-title": "some title",
|
||||
"edit-rev": "00",
|
||||
"edit-document_date": document_date.strftime("%Y-%m-%d"),
|
||||
"edit-abstract": "some abstract",
|
||||
"edit-pages": "123",
|
||||
"submitter-name": "Some Random Test Person",
|
||||
"submitter-email": "random@example.com",
|
||||
"edit-note": "no comments",
|
||||
"authors-0-name": "Person 1",
|
||||
"authors-0-email": "person1@example.com",
|
||||
"authors-1-name": "Person 2",
|
||||
"authors-1-email": "person2@example.com",
|
||||
"authors-prefix": ["authors-", "authors-0", "authors-1"],
|
||||
})
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
submission = IdSubmissionDetail.objects.get(filename=name)
|
||||
self.assertEquals(submission.id_document_name, "some title")
|
||||
self.assertEquals(submission.creation_date, creation_date)
|
||||
submission = Submission.objects.get(name=name)
|
||||
self.assertEquals(submission.title, "some title")
|
||||
self.assertEquals(submission.document_date, document_date)
|
||||
self.assertEquals(submission.abstract, "some abstract")
|
||||
self.assertEquals(submission.txt_page_count, 123)
|
||||
self.assertEquals(submission.comment_to_sec, "no comments")
|
||||
self.assertEquals(submission.pages, 123)
|
||||
self.assertEquals(submission.note, "no comments")
|
||||
self.assertEquals(submission.submitter, "Some Random Test Person <random@example.com>")
|
||||
self.assertEquals(submission.state_id, "manual")
|
||||
|
||||
authors = submission.tempidauthors_set
|
||||
self.assertEquals(authors.count(), 3)
|
||||
# first one is submitter
|
||||
self.assertEquals(authors.get(author_order=0).first_name, "Some Random Test Person")
|
||||
self.assertEquals(authors.get(author_order=0).email_address, "random@example.com")
|
||||
self.assertEquals(authors.get(author_order=1).first_name, "Person 1")
|
||||
self.assertEquals(authors.get(author_order=1).email_address, "person1@example.com")
|
||||
self.assertEquals(authors.get(author_order=2).first_name, "Person 2")
|
||||
self.assertEquals(authors.get(author_order=2).email_address, "person2@example.com")
|
||||
authors = submission.authors_parsed()
|
||||
self.assertEquals(len(authors), 2)
|
||||
self.assertEquals(authors[0]["name"], "Person 1")
|
||||
self.assertEquals(authors[0]["email"], "person1@example.com")
|
||||
self.assertEquals(authors[1]["name"], "Person 2")
|
||||
self.assertEquals(authors[1]["email"], "person2@example.com")
|
||||
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue("Manual Post Requested" in outbox[-1]["Subject"])
|
||||
self.assertTrue(name in outbox[-1]["Subject"])
|
||||
|
||||
# as Secretariat, we should see the force post button
|
||||
self.client.login(remote_user="secretary")
|
||||
|
||||
r = self.client.get(status_url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
post_button = q('input[type=submit][value*="Force"]')
|
||||
self.assertEquals(len(post_button), 1)
|
||||
|
||||
action = post_button.parents("form").find('input[type=hidden][name="action"]').val()
|
||||
|
||||
# force post
|
||||
mailbox_before = len(outbox)
|
||||
r = self.client.post(status_url, dict(action=action))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(docalias__name=name)
|
||||
self.assertEquals(draft.rev, rev)
|
||||
|
||||
def test_request_full_url(self):
|
||||
# submit -> request full URL to be sent
|
||||
draft = make_test_data()
|
||||
|
@ -380,8 +463,8 @@ class SubmitTests(django.test.TestCase):
|
|||
|
||||
self.do_submission(name, rev)
|
||||
|
||||
submission = IdSubmissionDetail.objects.get(filename=name)
|
||||
url = urlreverse('draft_status', kwargs=dict(submission_id=submission.submission_id))
|
||||
submission = Submission.objects.get(name=name)
|
||||
url = urlreverse('submit_submission_status', kwargs=dict(submission_id=submission.pk))
|
||||
|
||||
# check we got request full URL button
|
||||
r = self.client.get(url)
|
||||
|
@ -390,41 +473,79 @@ class SubmitTests(django.test.TestCase):
|
|||
request_button = q('input[type=submit][value*="Request full access"]')
|
||||
self.assertEquals(len(request_button), 1)
|
||||
|
||||
request_url = request_button.parents("form").attr("action")
|
||||
|
||||
# request URL to be sent
|
||||
mailbox_before = len(outbox)
|
||||
r = self.client.post(request_url)
|
||||
|
||||
action = request_button.parents("form").find("input[type=hidden][name=\"action\"]").val()
|
||||
r = self.client.post(url, dict(action=action))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
|
||||
self.assertEquals(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue("Full URL for managing submission" in outbox[-1]["Subject"])
|
||||
self.assertTrue(name in outbox[-1]["Subject"])
|
||||
|
||||
class ApprovalsTests(django.test.TestCase):
|
||||
fixtures = ['idsubmissionstatus']
|
||||
def test_submit_all_file_types(self):
|
||||
draft = make_test_data()
|
||||
|
||||
name = "draft-ietf-mars-testing-tests"
|
||||
rev = "00"
|
||||
|
||||
txt_file = self.submission_txt_file(name, rev)
|
||||
|
||||
# the checks for other file types are currently embarrassingly
|
||||
# dumb, so don't bother constructing proper XML/PS/PDF draft
|
||||
# files
|
||||
xml_file = StringIO('<?xml version="1.0" encoding="utf-8"?>\n<draft>This is XML</draft>')
|
||||
xml_file.name = "somename.xml"
|
||||
|
||||
pdf_file = StringIO('%PDF-1.5\nThis is PDF')
|
||||
pdf_file.name = "somename.pdf"
|
||||
|
||||
ps_file = StringIO('%!PS-Adobe-2.0\nThis is PostScript')
|
||||
ps_file.name = "somename.ps"
|
||||
|
||||
r = self.client.post(urlreverse('submit_upload_submission'), dict(
|
||||
txt=txt_file,
|
||||
xml=xml_file,
|
||||
pdf=pdf_file,
|
||||
ps=ps_file,
|
||||
))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(Submission.objects.filter(name=name).count(), 1)
|
||||
|
||||
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))))
|
||||
self.assertTrue(name in open(os.path.join(self.staging_dir, u"%s-%s.txt" % (name, rev))).read())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.xml" % (name, rev))))
|
||||
self.assertTrue('This is XML' in open(os.path.join(self.staging_dir, u"%s-%s.xml" % (name, rev))).read())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.pdf" % (name, rev))))
|
||||
self.assertTrue('This is PDF' in open(os.path.join(self.staging_dir, u"%s-%s.pdf" % (name, rev))).read())
|
||||
self.assertTrue(os.path.exists(os.path.join(self.staging_dir, u"%s-%s.ps" % (name, rev))))
|
||||
self.assertTrue('This is PostScript' in open(os.path.join(self.staging_dir, u"%s-%s.ps" % (name, rev))).read())
|
||||
|
||||
|
||||
class ApprovalsTests(django.test.TestCase):
|
||||
def test_approvals(self):
|
||||
make_test_data()
|
||||
|
||||
url = urlreverse('submit_approvals')
|
||||
self.client.login(remote_user="marschairman")
|
||||
|
||||
from ietf.submit.views import POSTED, INITIAL_VERSION_APPROVAL_REQUESTED
|
||||
|
||||
Preapproval.objects.create(name="draft-ietf-mars-foo", by=Person.objects.get(user__username="marschairman"))
|
||||
Preapproval.objects.create(name="draft-ietf-mars-baz", by=Person.objects.get(user__username="marschairman"))
|
||||
|
||||
IdSubmissionDetail.objects.create(filename="draft-ietf-mars-foo",
|
||||
group_acronym_id=Group.objects.get(acronym="mars").pk,
|
||||
Submission.objects.create(name="draft-ietf-mars-foo",
|
||||
group_id=Group.objects.get(acronym="mars").pk,
|
||||
submission_date=datetime.date.today(),
|
||||
revision="00",
|
||||
status_id=POSTED)
|
||||
IdSubmissionDetail.objects.create(filename="draft-ietf-mars-bar",
|
||||
group_acronym_id=Group.objects.get(acronym="mars").pk,
|
||||
rev="00",
|
||||
state_id="posted",
|
||||
access_key="abc")
|
||||
Submission.objects.create(name="draft-ietf-mars-bar",
|
||||
group_id=Group.objects.get(acronym="mars").pk,
|
||||
submission_date=datetime.date.today(),
|
||||
revision="00",
|
||||
status_id=INITIAL_VERSION_APPROVAL_REQUESTED)
|
||||
rev="00",
|
||||
state_id="grp-appr",
|
||||
access_key="def")
|
||||
|
||||
# get
|
||||
r = self.client.get(url)
|
||||
|
|
|
@ -2,32 +2,17 @@ from django.conf.urls.defaults import patterns, url
|
|||
|
||||
|
||||
urlpatterns = patterns('ietf.submit.views',
|
||||
url(r'^$', 'submit_index', name='submit_index'),
|
||||
url(r'^status/$', 'submit_status', name='submit_status'),
|
||||
url(r'^status/(?P<submission_id>\d+)/$', 'draft_status', name='draft_status'),
|
||||
url(r'^status/(?P<submission_id>\d+)/edit/$', 'draft_edit', name='draft_edit'),
|
||||
url(r'^status/(?P<submission_id>\d+)/confirm/(?P<auth_key>[a-f\d]+)/$', 'draft_confirm', name='draft_confirm'),
|
||||
url(r'^status/(?P<submission_id>\d+)/cancel/$', 'draft_cancel', name='draft_cancel'),
|
||||
url(r'^status/(?P<submission_id>\d+)/approve/$', 'draft_approve', name='draft_approve'),
|
||||
url(r'^status/(?P<submission_id>\d+)/force/$', 'draft_force', name='draft_force'),
|
||||
url(r'^status/(?P<submission_id>\d+)/request/$', 'full_url_request', name='full_url_request'),
|
||||
url(r'^status/(?P<submission_id>\d+)/(?P<submission_hash>[a-f\d]+)/$', 'draft_status', name='draft_status_by_hash'),
|
||||
url(r'^status/(?P<submission_id>\d+)/(?P<submission_hash>[a-f\d]+)/cancel/$', 'draft_cancel', name='draft_cancel_by_hash'),
|
||||
url(r'^status/(?P<submission_id>\d+)/(?P<submission_hash>[a-f\d]+)/edit/$', 'draft_edit', name='draft_edit_by_hash'),
|
||||
url(r'^$', 'upload_submission', name='submit_upload_submission'),
|
||||
url(r'^status/$', 'search_submission', name='submit_search_submission'),
|
||||
url(r'^status/(?P<submission_id>\d+)/$', 'submission_status', name='submit_submission_status'),
|
||||
url(r'^status/(?P<submission_id>\d+)/edit/$', 'edit_submission', name='submit_edit_submission'),
|
||||
url(r'^status/(?P<submission_id>\d+)/confirm/(?P<auth_key>[a-f\d]+)/$', 'confirm_submission', name='submit_confirm_submission'),
|
||||
url(r'^status/(?P<submission_id>\d+)/(?P<access_key>[a-f\d]*)/$', 'submission_status', name='submit_submission_status_by_hash'),
|
||||
url(r'^status/(?P<submission_id>\d+)/(?P<access_key>[a-f\d]+)/edit/$', 'edit_submission', name='submit_edit_submission_by_hash'),
|
||||
url(r'^note-well/$', 'note_well', name='submit_note_well'),
|
||||
url(r'^tool-instructions/$', 'tool_instructions', name='submit_tool_instructions'),
|
||||
|
||||
url(r'^approvals/$', 'approvals', name='submit_approvals'),
|
||||
url(r'^approvals/addpreapproval/$', 'add_preapproval', name='submit_add_preapproval'),
|
||||
url(r'^approvals/cancelpreapproval/(?P<preapproval_id>[a-f\d]+)/$', 'cancel_preapproval', name='submit_cancel_preapproval'),
|
||||
)
|
||||
|
||||
urlpatterns += patterns('django.views.generic.simple',
|
||||
url(r'^note-well/$', 'direct_to_template',
|
||||
{'template': 'submit/note_well.html',
|
||||
'extra_context': {'selected': 'notewell'}
|
||||
},
|
||||
name='submit_note_well'),
|
||||
url(r'^tool-instructions/$', 'direct_to_template',
|
||||
{'template': 'submit/tool_instructions.html',
|
||||
'extra_context': {'selected': 'instructions'}
|
||||
},
|
||||
name='submit_tool_instructions'),
|
||||
)
|
||||
|
|
|
@ -12,57 +12,129 @@ from ietf.utils.log import log
|
|||
from ietf.utils import unaccent
|
||||
from ietf.ietfauth.utils import has_role
|
||||
|
||||
from ietf.submit.models import TempIdAuthors, IdSubmissionDetail, Preapproval
|
||||
from ietf.submit.models import Submission, SubmissionEvent, Preapproval, DraftSubmissionStateName
|
||||
from ietf.doc.models import *
|
||||
from ietf.person.models import Person, Alias, Email
|
||||
from ietf.doc.utils import add_state_change_event
|
||||
from ietf.message.models import Message
|
||||
from ietf.utils.pipe import pipe
|
||||
from ietf.utils.log import log
|
||||
from ietf.submit.mail import announce_to_lists, announce_new_version, announce_to_authors
|
||||
|
||||
# Some useful states
|
||||
UPLOADED = 1
|
||||
AWAITING_AUTHENTICATION = 4
|
||||
MANUAL_POST_REQUESTED = 5
|
||||
POSTED = -1
|
||||
POSTED_BY_SECRETARIAT = -2
|
||||
CANCELLED = -4
|
||||
INITIAL_VERSION_APPROVAL_REQUESTED = 10
|
||||
def check_idnits(path):
|
||||
#p = subprocess.Popen([self.idnits, '--submitcheck', '--nitcount', path], stdout=subprocess.PIPE)
|
||||
cmd = "%s --submitcheck --nitcount %s" % (settings.IDSUBMIT_IDNITS_BINARY, path)
|
||||
code, out, err = pipe(cmd)
|
||||
if code != 0:
|
||||
log("idnits error: %s:\n Error %s: %s" %( cmd, code, err))
|
||||
return out
|
||||
|
||||
def found_idnits(idnits_message):
|
||||
if not idnits_message:
|
||||
return False
|
||||
success_re = re.compile('\s+Summary:\s+0\s+|No nits found')
|
||||
if success_re.search(idnits_message):
|
||||
return True
|
||||
return False
|
||||
|
||||
def validate_submission(submission):
|
||||
errors = {}
|
||||
|
||||
if submission.state_id not in ("cancel", "posted"):
|
||||
for ext in submission.file_types.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, submission.rev, ext))
|
||||
if not os.path.exists(source):
|
||||
errors['files'] = '"%s" was not found in the staging area.<br />We recommend you that you cancel this submission and upload your files again.' % os.path.basename(source)
|
||||
break
|
||||
|
||||
if not submission.title:
|
||||
errors['title'] = 'Title is empty or was not found'
|
||||
|
||||
if submission.group and submission.group.state_id != "active":
|
||||
errors['group'] = 'Group exists but is not an active group'
|
||||
|
||||
if not submission.abstract:
|
||||
errors['abstract'] = 'Abstract is empty or was not found'
|
||||
|
||||
if not submission.authors_parsed():
|
||||
errors['authors'] = 'No authors found'
|
||||
|
||||
# revision
|
||||
if submission.state_id != "posted":
|
||||
error = validate_submission_rev(submission.name, submission.rev)
|
||||
if error:
|
||||
errors['rev'] = error
|
||||
|
||||
# draft date
|
||||
error = validate_submission_document_date(submission.submission_date, submission.document_date)
|
||||
if error:
|
||||
errors['document_date'] = error
|
||||
|
||||
return errors
|
||||
|
||||
def validate_submission_rev(name, rev):
|
||||
if not rev:
|
||||
return 'Revision not found'
|
||||
|
||||
try:
|
||||
rev = int(rev)
|
||||
except ValueError:
|
||||
return 'Revision must be a number'
|
||||
else:
|
||||
if not (0 <= rev <= 99):
|
||||
return 'Revision must be between 00 and 99'
|
||||
|
||||
expected = 0
|
||||
existing_revs = [int(i.rev) for i in Document.objects.filter(name=name)]
|
||||
if existing_revs:
|
||||
expected = max(existing_revs) + 1
|
||||
|
||||
if rev != expected:
|
||||
return 'Invalid revision (revision %02d is expected)' % expected
|
||||
|
||||
return None
|
||||
|
||||
def validate_submission_document_date(submission_date, document_date):
|
||||
if not document_date:
|
||||
return 'Document date is empty or not in a proper format'
|
||||
elif abs(submission_date - document_date) > datetime.timedelta(days=3):
|
||||
return 'Document date must be within 3 days of submission date'
|
||||
|
||||
return None
|
||||
|
||||
def create_submission_event(request, submission, desc):
|
||||
by = None
|
||||
if request and request.user.is_authenticated():
|
||||
try:
|
||||
by = request.user.person
|
||||
except Person.DoesNotExist:
|
||||
pass
|
||||
|
||||
SubmissionEvent.objects.create(submission=submission, by=by, desc=desc)
|
||||
|
||||
|
||||
|
||||
def request_full_url(request, submission):
|
||||
subject = 'Full URL for managing submission of draft %s' % submission.filename
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = submission_confirmation_email_list(submission)
|
||||
url = settings.IDTRACKER_BASE_URL + urlreverse('draft_status_by_hash',
|
||||
kwargs=dict(submission_id=submission.submission_id,
|
||||
submission_hash=submission.get_hash()))
|
||||
send_mail(request, to_email, from_email, subject, 'submit/request_full_url.txt',
|
||||
{'submission': submission,
|
||||
'url': url})
|
||||
|
||||
|
||||
def perform_post(request, submission):
|
||||
def post_submission(request, submission):
|
||||
system = Person.objects.get(name="(System)")
|
||||
|
||||
try:
|
||||
draft = Document.objects.get(name=submission.filename)
|
||||
draft = Document.objects.get(name=submission.name)
|
||||
save_document_in_history(draft)
|
||||
except Document.DoesNotExist:
|
||||
draft = Document(name=submission.filename)
|
||||
draft = Document(name=submission.name)
|
||||
draft.intended_std_level = None
|
||||
|
||||
prev_rev = draft.rev
|
||||
|
||||
draft.type_id = "draft"
|
||||
draft.time = datetime.datetime.now()
|
||||
draft.title = submission.id_document_name
|
||||
group = submission.group_acronym or Group.objects.get(type="individ")
|
||||
draft.title = submission.title
|
||||
group = submission.group or Group.objects.get(type="individ")
|
||||
if not (group.type_id == "individ" and draft.group and draft.group.type_id == "area"):
|
||||
# don't overwrite an assigned area if it's still an individual
|
||||
# submission
|
||||
draft.group_id = group.pk
|
||||
draft.rev = submission.revision
|
||||
draft.pages = submission.txt_page_count
|
||||
draft.rev = submission.rev
|
||||
draft.pages = submission.pages
|
||||
draft.abstract = submission.abstract
|
||||
was_rfc = draft.get_state_slug() == "rfc"
|
||||
|
||||
|
@ -81,14 +153,14 @@ def perform_post(request, submission):
|
|||
draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
|
||||
draft.save()
|
||||
|
||||
a = submission.tempidauthors_set.filter(author_order=0)
|
||||
if a:
|
||||
submitter = ensure_person_email_info_exists(a[0]).person
|
||||
submitter_parsed = submission.submitter_parsed()
|
||||
if submitter_parsed["name"] and submitter_parsed["email"]:
|
||||
submitter = ensure_person_email_info_exists(submitter_parsed["name"], submitter_parsed["email"]).person
|
||||
else:
|
||||
submitter = system
|
||||
|
||||
draft.set_state(State.objects.get(used=True, type="draft", slug="active"))
|
||||
DocAlias.objects.get_or_create(name=submission.filename, document=draft)
|
||||
DocAlias.objects.get_or_create(name=submission.name, document=draft)
|
||||
|
||||
update_authors(draft, submission)
|
||||
|
||||
|
@ -128,8 +200,8 @@ def perform_post(request, submission):
|
|||
|
||||
state_change_msg = e.desc
|
||||
|
||||
move_docs(submission)
|
||||
submission.status_id = POSTED
|
||||
move_files_to_repository(submission)
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="posted")
|
||||
|
||||
announce_to_lists(request, submission)
|
||||
announce_new_version(request, submission, draft, state_change_msg)
|
||||
|
@ -137,116 +209,33 @@ def perform_post(request, submission):
|
|||
|
||||
submission.save()
|
||||
|
||||
def submission_confirmation_email_list(submission):
|
||||
try:
|
||||
doc = Document.objects.get(name=submission.filename)
|
||||
email_list = [i.author.formatted_email() for i in doc.documentauthor_set.all()]
|
||||
except Document.DoesNotExist:
|
||||
email_list = [u'%s <%s>' % i.email() for i in submission.tempidauthors_set.all()]
|
||||
return email_list
|
||||
|
||||
def announce_to_lists(request, submission):
|
||||
authors = []
|
||||
for i in submission.tempidauthors_set.order_by('author_order'):
|
||||
if not i.author_order:
|
||||
continue
|
||||
authors.append(i.get_full_name())
|
||||
|
||||
m = Message()
|
||||
m.by = Person.objects.get(name="(System)")
|
||||
if request.user.is_authenticated():
|
||||
try:
|
||||
m.by = request.user.get_profile()
|
||||
except Person.DoesNotExist:
|
||||
pass
|
||||
m.subject = 'I-D Action: %s-%s.txt' % (submission.filename, submission.revision)
|
||||
m.frm = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
m.to = settings.IDSUBMIT_ANNOUNCE_LIST_EMAIL
|
||||
if submission.group_acronym and submission.group_acronym.list_email:
|
||||
m.cc = submission.group_acronym.list_email
|
||||
m.body = render_to_string('submit/announce_to_lists.txt', dict(submission=submission,
|
||||
authors=authors,
|
||||
settings=settings,))
|
||||
m.save()
|
||||
m.related_docs.add(Document.objects.get(name=submission.filename))
|
||||
|
||||
send_mail_message(request, m)
|
||||
|
||||
|
||||
def announce_new_version(request, submission, draft, state_change_msg):
|
||||
to_email = []
|
||||
if draft.notify:
|
||||
to_email.append(draft.notify)
|
||||
if draft.ad:
|
||||
to_email.append(draft.ad.role_email("ad").address)
|
||||
|
||||
if draft.stream_id == "iab":
|
||||
to_email.append("IAB Stream <iab-stream@iab.org>")
|
||||
elif draft.stream_id == "ise":
|
||||
to_email.append("Independent Submission Editor <rfc-ise@rfc-editor.org>")
|
||||
elif draft.stream_id == "irtf":
|
||||
to_email.append("IRSG <irsg@irtf.org>")
|
||||
|
||||
# if it has been sent to the RFC Editor, keep them in the loop
|
||||
if draft.get_state_slug("draft-iesg") in ("ann", "rfcqueue"):
|
||||
to_email.append("RFC Editor <rfc-editor@rfc-editor.org>")
|
||||
|
||||
active_ballot = draft.active_ballot()
|
||||
if active_ballot:
|
||||
for ad, pos in active_ballot.active_ad_positions().iteritems():
|
||||
if pos and pos.pos_id == "discuss":
|
||||
to_email.append(ad.role_email("ad").address)
|
||||
|
||||
if to_email:
|
||||
subject = 'New Version Notification - %s-%s.txt' % (submission.filename, submission.revision)
|
||||
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
send_mail(request, to_email, from_email, subject, 'submit/announce_new_version.txt',
|
||||
{'submission': submission,
|
||||
'msg': state_change_msg})
|
||||
|
||||
def announce_to_authors(request, submission):
|
||||
authors = submission.tempidauthors_set.all()
|
||||
to_email = list(set(submission_confirmation_email_list(submission) + [u'%s <%s>' % i.email() for i in authors]))
|
||||
from_email = settings.IDSUBMIT_ANNOUNCE_FROM_EMAIL
|
||||
subject = 'New Version Notification for %s-%s.txt' % (submission.filename, submission.revision)
|
||||
if submission.group_acronym:
|
||||
wg = submission.group_acronym.acronym
|
||||
elif submission.filename.startswith('draft-iesg'):
|
||||
wg = 'IESG'
|
||||
else:
|
||||
wg = 'Individual Submission'
|
||||
send_mail(request, to_email, from_email, subject, 'submit/announce_to_authors.txt',
|
||||
{'submission': submission,
|
||||
'submitter': authors[0].get_full_name(),
|
||||
'wg': wg})
|
||||
|
||||
|
||||
def get_person_from_author(author):
|
||||
persons = None
|
||||
|
||||
def get_person_from_name_email(name, email):
|
||||
# try email
|
||||
if author.email_address:
|
||||
persons = Person.objects.filter(email__address=author.email_address).distinct()
|
||||
if email:
|
||||
persons = Person.objects.filter(email__address=email).distinct()
|
||||
if len(persons) == 1:
|
||||
return persons[0]
|
||||
else:
|
||||
persons = Person.objects.none()
|
||||
|
||||
if not persons:
|
||||
persons = Person.objects.all()
|
||||
|
||||
# try full name
|
||||
p = persons.filter(alias__name=author.get_full_name()).distinct()
|
||||
p = persons.filter(alias__name=name).distinct()
|
||||
if p:
|
||||
return p[0]
|
||||
|
||||
return None
|
||||
|
||||
def ensure_person_email_info_exists(author):
|
||||
person = get_person_from_author(author)
|
||||
def ensure_person_email_info_exists(name, email):
|
||||
person = get_person_from_name_email(name, email)
|
||||
|
||||
# make sure we got a person
|
||||
# make sure we have a person
|
||||
if not person:
|
||||
person = Person()
|
||||
person.name = author.get_full_name()
|
||||
person.name = name
|
||||
person.ascii = unaccent.asciify(person.name)
|
||||
person.save()
|
||||
|
||||
|
@ -254,9 +243,9 @@ def ensure_person_email_info_exists(author):
|
|||
if person.name != person.ascii:
|
||||
Alias.objects.create(name=ascii, person=person)
|
||||
|
||||
# make sure we got an email address
|
||||
if author.email_address:
|
||||
addr = author.email_address.lower()
|
||||
# make sure we have an email address
|
||||
if email:
|
||||
addr = email.lower()
|
||||
else:
|
||||
# we're in trouble, use a fake one
|
||||
addr = u"unknown-email-%s" % person.name.replace(" ", "-")
|
||||
|
@ -277,12 +266,10 @@ def ensure_person_email_info_exists(author):
|
|||
|
||||
return email
|
||||
|
||||
|
||||
def update_authors(draft, submission):
|
||||
# order 0 is submitter
|
||||
authors = []
|
||||
for author in submission.tempidauthors_set.exclude(author_order=0).order_by('author_order'):
|
||||
email = ensure_person_email_info_exists(author)
|
||||
for order, author in enumerate(submission.authors_parsed()):
|
||||
email = ensure_person_email_info_exists(author["name"], author["email"])
|
||||
|
||||
a = DocumentAuthor.objects.filter(document=draft, author=email)
|
||||
if a:
|
||||
|
@ -290,17 +277,29 @@ def update_authors(draft, submission):
|
|||
else:
|
||||
a = DocumentAuthor(document=draft, author=email)
|
||||
|
||||
a.order = author.author_order
|
||||
a.order = order
|
||||
a.save()
|
||||
|
||||
authors.append(email)
|
||||
|
||||
draft.documentauthor_set.exclude(author__in=authors).delete()
|
||||
|
||||
def move_docs(submission):
|
||||
for ext in submission.file_type.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.filename, submission.revision, ext))
|
||||
dest = os.path.join(settings.IDSUBMIT_REPOSITORY_PATH, '%s-%s%s' % (submission.filename, submission.revision, ext))
|
||||
def cancel_submission(submission):
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="cancel")
|
||||
submission.save()
|
||||
|
||||
remove_submission_files(submission)
|
||||
|
||||
def rename_submission_files(submission, prev_rev, new_rev):
|
||||
for ext in submission.file_types.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, prev_rev, ext))
|
||||
dest = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, new_rev, ext))
|
||||
os.rename(source, dest)
|
||||
|
||||
def move_files_to_repository(submission):
|
||||
for ext in submission.file_types.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, submission.rev, ext))
|
||||
dest = os.path.join(settings.IDSUBMIT_REPOSITORY_PATH, '%s-%s%s' % (submission.name, submission.rev, ext))
|
||||
if os.path.exists(source):
|
||||
os.rename(source, dest)
|
||||
else:
|
||||
|
@ -309,28 +308,28 @@ def move_docs(submission):
|
|||
else:
|
||||
raise ValueError("Intended to move '%s' to '%s', but found source and destination missing.")
|
||||
|
||||
def remove_docs(submission):
|
||||
for ext in submission.file_type.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.filename, submission.revision, ext))
|
||||
def remove_submission_files(submission):
|
||||
for ext in submission.file_types.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (submission.name, submission.rev, ext))
|
||||
if os.path.exists(source):
|
||||
os.unlink(source)
|
||||
|
||||
def get_approvable_submissions(user):
|
||||
def approvable_submissions_for_user(user):
|
||||
if not user.is_authenticated():
|
||||
return []
|
||||
|
||||
res = IdSubmissionDetail.objects.filter(status=INITIAL_VERSION_APPROVAL_REQUESTED).order_by('-submission_date')
|
||||
res = Submission.objects.filter(state="grp-appr").order_by('-submission_date')
|
||||
if has_role(user, "Secretariat"):
|
||||
return res
|
||||
|
||||
# those we can reach as chair
|
||||
return res.filter(group_acronym__role__name="chair", group_acronym__role__person__user=user)
|
||||
return res.filter(group__role__name="chair", group__role__person__user=user)
|
||||
|
||||
def get_preapprovals(user):
|
||||
def preapprovals_for_user(user):
|
||||
if not user.is_authenticated():
|
||||
return []
|
||||
|
||||
posted = IdSubmissionDetail.objects.distinct().filter(status__in=[POSTED, POSTED_BY_SECRETARIAT]).values_list('filename', flat=True)
|
||||
posted = Submission.objects.distinct().filter(state="posted").values_list('name', flat=True)
|
||||
res = Preapproval.objects.exclude(name__in=posted).order_by("-time").select_related('by')
|
||||
if has_role(user, "Secretariat"):
|
||||
return res
|
||||
|
@ -341,125 +340,13 @@ def get_preapprovals(user):
|
|||
|
||||
return res
|
||||
|
||||
def get_recently_approved(user, since):
|
||||
def recently_approved_by_user(user, since):
|
||||
if not user.is_authenticated():
|
||||
return []
|
||||
|
||||
res = IdSubmissionDetail.objects.distinct().filter(status__in=[POSTED, POSTED_BY_SECRETARIAT], submission_date__gte=since, revision="00").order_by('-submission_date')
|
||||
res = Submission.objects.distinct().filter(state="posted", submission_date__gte=since, rev="00").order_by('-submission_date')
|
||||
if has_role(user, "Secretariat"):
|
||||
return res
|
||||
|
||||
# those we can reach as chair
|
||||
return res.filter(group_acronym__role__name="chair", group_acronym__role__person__user=user)
|
||||
|
||||
class DraftValidation(object):
|
||||
|
||||
def __init__(self, draft):
|
||||
self.draft = draft
|
||||
self.warnings = {}
|
||||
self.passes_idnits = self.passes_idnits()
|
||||
self.wg = self.get_working_group()
|
||||
self.authors = self.get_authors()
|
||||
self.submitter = self.get_submitter()
|
||||
|
||||
def passes_idnits(self):
|
||||
passes_idnits = self.check_idnits_success(self.draft.idnits_message)
|
||||
return passes_idnits
|
||||
|
||||
def get_working_group(self):
|
||||
if self.draft.group_acronym and self.draft.group_acronym.type_id == "individ":
|
||||
return None
|
||||
return self.draft.group_acronym
|
||||
|
||||
def check_idnits_success(self, idnits_message):
|
||||
if not idnits_message:
|
||||
return False
|
||||
success_re = re.compile('\s+Summary:\s+0\s+|No nits found')
|
||||
if success_re.search(idnits_message):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_valid_attr(self, key):
|
||||
if key in self.warnings.keys():
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_valid(self):
|
||||
self.validate_metadata()
|
||||
return not bool(self.warnings.keys()) and self.passes_idnits
|
||||
|
||||
def validate_metadata(self):
|
||||
self.validate_revision()
|
||||
self.validate_title()
|
||||
self.validate_authors()
|
||||
self.validate_abstract()
|
||||
self.validate_creation_date()
|
||||
self.validate_wg()
|
||||
self.validate_files()
|
||||
|
||||
def validate_files(self):
|
||||
if self.draft.status_id in [POSTED, POSTED_BY_SECRETARIAT]:
|
||||
return
|
||||
for ext in self.draft.file_type.split(','):
|
||||
source = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s%s' % (self.draft.filename, self.draft.revision, ext))
|
||||
if not os.path.exists(source):
|
||||
self.add_warning('document_files', '"%s" were not found in the staging area.<br />We recommend you that you cancel this submission and upload your files again.' % os.path.basename(source))
|
||||
break
|
||||
|
||||
def validate_title(self):
|
||||
if not self.draft.id_document_name:
|
||||
self.add_warning('title', 'Title is empty or was not found')
|
||||
|
||||
def validate_wg(self):
|
||||
if self.wg and self.wg.state_id != "active":
|
||||
self.add_warning('group', 'Group exists but is not an active group')
|
||||
|
||||
def validate_abstract(self):
|
||||
if not self.draft.abstract:
|
||||
self.add_warning('abstract', 'Abstract is empty or was not found')
|
||||
|
||||
def add_warning(self, key, value):
|
||||
self.warnings.update({key: value})
|
||||
|
||||
def validate_revision(self):
|
||||
if self.draft.status_id in [POSTED, POSTED_BY_SECRETARIAT]:
|
||||
return
|
||||
revision = self.draft.revision
|
||||
existing_revisions = [int(i.rev) for i in Document.objects.filter(name=self.draft.filename)]
|
||||
expected = 0
|
||||
if existing_revisions:
|
||||
expected = max(existing_revisions) + 1
|
||||
try:
|
||||
if int(revision) != expected:
|
||||
self.add_warning('revision', 'Invalid Version Number (Version %02d is expected)' % expected)
|
||||
except ValueError:
|
||||
self.add_warning('revision', 'Revision not found')
|
||||
|
||||
def validate_authors(self):
|
||||
if not self.authors:
|
||||
self.add_warning('authors', 'No authors found')
|
||||
return
|
||||
|
||||
def validate_creation_date(self):
|
||||
date = self.draft.creation_date
|
||||
if not date:
|
||||
self.add_warning('creation_date', 'Creation Date field is empty or the creation date is not in a proper format')
|
||||
return
|
||||
submit_date = self.draft.submission_date
|
||||
if (date + datetime.timedelta(days=3) < submit_date or
|
||||
date - datetime.timedelta(days=3) > submit_date):
|
||||
self.add_warning('creation_date', 'Creation Date must be within 3 days of submission date')
|
||||
|
||||
def get_authors(self):
|
||||
return self.draft.tempidauthors_set.exclude(author_order=0).order_by('author_order')
|
||||
|
||||
def get_submitter(self):
|
||||
submitter = self.draft.tempidauthors_set.filter(author_order=0)
|
||||
if submitter:
|
||||
return submitter[0]
|
||||
# elif self.draft.submitter_tag:
|
||||
# try:
|
||||
# return PersonOrOrgInfo.objects.get(pk=self.draft.submitter_tag)
|
||||
# except PersonOrOrgInfo.DoesNotExist:
|
||||
# return False
|
||||
return None
|
||||
return res.filter(group__role__name="chair", group__role__person__user=user)
|
||||
|
|
|
@ -1,32 +1,97 @@
|
|||
# Copyright The IETF Trust 2007, All Rights Reserved
|
||||
import datetime
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse as urlreverse
|
||||
from django.core.validators import validate_email, ValidationError
|
||||
from django.contrib.sites.models import Site
|
||||
from django.http import HttpResponseRedirect, Http404, HttpResponseForbidden, HttpResponseNotAllowed
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
|
||||
from ietf.doc.models import Document
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.utils.mail import send_mail
|
||||
from ietf.ietfauth.utils import has_role, role_required
|
||||
from ietf.submit.models import IdSubmissionDetail, Preapproval
|
||||
from ietf.submit.forms import UploadForm, AutoPostForm, MetaDataForm, PreapprovalForm
|
||||
from ietf.submit.utils import UPLOADED, AWAITING_AUTHENTICATION, MANUAL_POST_REQUESTED, CANCELLED, POSTED, INITIAL_VERSION_APPROVAL_REQUESTED
|
||||
from ietf.submit.utils import get_approvable_submissions, get_preapprovals, get_recently_approved, perform_post, remove_docs, request_full_url
|
||||
from ietf.submit.utils import DraftValidation
|
||||
from ietf.submit.models import Submission, Preapproval, DraftSubmissionStateName
|
||||
from ietf.submit.forms import UploadForm, NameEmailForm, EditSubmissionForm, PreapprovalForm
|
||||
from ietf.submit.utils import approvable_submissions_for_user, preapprovals_for_user, recently_approved_by_user
|
||||
from ietf.submit.utils import check_idnits, found_idnits, validate_submission, create_submission_event
|
||||
from ietf.submit.utils import post_submission, cancel_submission, rename_submission_files
|
||||
from ietf.submit.mail import send_full_url, send_approval_request_to_group, send_submission_confirmation, submission_confirmation_email_list, send_manual_post_request
|
||||
from ietf.utils.uniquekey import generate_unique_key
|
||||
|
||||
def submit_index(request):
|
||||
def upload_submission(request):
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
form = UploadForm(request=request, data=request.POST, files=request.FILES)
|
||||
form = UploadForm(request, data=request.POST, files=request.FILES)
|
||||
if form.is_valid():
|
||||
submit = form.save()
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': submit.submission_id, 'submission_hash': submit.get_hash()}))
|
||||
except IOError, e:
|
||||
if "Client read error" in str(e): # The server got an IOError when trying to read POST data
|
||||
# save files
|
||||
file_types = []
|
||||
for ext in ['txt', 'pdf', 'xml', 'ps']:
|
||||
f = form.cleaned_data[ext]
|
||||
if not f:
|
||||
continue
|
||||
file_types.append('.%s' % ext)
|
||||
|
||||
draft = form.parsed_draft
|
||||
|
||||
name = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.%s' % (draft.filename, draft.revision, ext))
|
||||
with open(name, 'wb+') as destination:
|
||||
for chunk in f.chunks():
|
||||
destination.write(chunk)
|
||||
|
||||
# check idnits
|
||||
text_path = os.path.join(settings.IDSUBMIT_STAGING_PATH, '%s-%s.txt' % (draft.filename, draft.revision))
|
||||
idnits_message = check_idnits(text_path)
|
||||
|
||||
# extract author lines
|
||||
authors = []
|
||||
for author in draft.get_author_list():
|
||||
full_name, first_name, middle_initial, last_name, name_suffix, email, company = author
|
||||
|
||||
line = full_name.replace("\n", "").replace("\r", "").replace("<", "").replace(">", "").strip()
|
||||
email = (email or "").strip()
|
||||
|
||||
if email:
|
||||
try:
|
||||
validate_email(email)
|
||||
except ValidationError:
|
||||
email = ""
|
||||
|
||||
if email:
|
||||
line += u" <%s>" % email
|
||||
|
||||
authors.append(line)
|
||||
|
||||
# save submission
|
||||
submission = Submission.objects.create(
|
||||
state=DraftSubmissionStateName.objects.get(slug="uploaded"),
|
||||
remote_ip=form.remote_ip,
|
||||
name=draft.filename,
|
||||
group=form.group,
|
||||
title=draft.get_title(),
|
||||
abstract=draft.get_abstract(),
|
||||
rev=draft.revision,
|
||||
pages=draft.get_pagecount(),
|
||||
authors="\n".join(authors),
|
||||
note="",
|
||||
first_two_pages=''.join(draft.pages[:2]),
|
||||
file_size=form.cleaned_data['txt'].size,
|
||||
file_types=','.join(file_types),
|
||||
submission_date=datetime.date.today(),
|
||||
document_date=draft.get_creation_date(),
|
||||
replaces="",
|
||||
idnits_message=idnits_message,
|
||||
)
|
||||
|
||||
create_submission_event(request, submission, desc="Uploaded submission")
|
||||
|
||||
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_key=submission.access_key)
|
||||
except IOError as e:
|
||||
if "read error" in str(e): # The server got an IOError when trying to read POST data
|
||||
form = UploadForm(request=request)
|
||||
form._errors = {}
|
||||
form._errors["__all__"] = form.error_class(["There was a failure receiving the complete form data -- please try again."])
|
||||
|
@ -34,241 +99,289 @@ def submit_index(request):
|
|||
raise
|
||||
else:
|
||||
form = UploadForm(request=request)
|
||||
return render_to_response('submit/submit_index.html',
|
||||
|
||||
return render_to_response('submit/upload_submission.html',
|
||||
{'selected': 'index',
|
||||
'form': form},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def note_well(request):
|
||||
return render_to_response('submit/note_well.html', {'selected': 'notewell'},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def submit_status(request):
|
||||
def tool_instructions(request):
|
||||
return render_to_response('submit/tool_instructions.html', {'selected': 'instructions'},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def search_submission(request):
|
||||
error = None
|
||||
filename = None
|
||||
name = None
|
||||
if request.method == 'POST':
|
||||
filename = request.POST.get('filename', '')
|
||||
detail = IdSubmissionDetail.objects.filter(filename=filename).order_by('-pk')
|
||||
if detail:
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': detail[0].submission_id}))
|
||||
error = 'No valid history found for %s' % filename
|
||||
return render_to_response('submit/submit_status.html',
|
||||
name = request.POST.get('name', '')
|
||||
submission = Submission.objects.filter(name=name).order_by('-pk')
|
||||
if submission:
|
||||
return HttpResponseRedirect(urlreverse(submission_status, None, kwargs={'submission_id': submission[0].pk}))
|
||||
error = 'No valid submission found for %s' % name
|
||||
return render_to_response('submit/search_submission.html',
|
||||
{'selected': 'status',
|
||||
'error': error,
|
||||
'filename': filename},
|
||||
'name': name},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def can_edit_submission(request, submission, access_key):
|
||||
key_matched = access_key and submission.access_key == access_key
|
||||
return key_matched or has_role(request.user, "Secretariat")
|
||||
|
||||
def _can_approve(user, detail):
|
||||
if detail.status_id != INITIAL_VERSION_APPROVAL_REQUESTED or not detail.group_acronym:
|
||||
return None
|
||||
if detail.group_acronym.has_role(user, "chair") or has_role(user, "Secretariat"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _can_force_post(user, detail):
|
||||
if detail.status_id not in [MANUAL_POST_REQUESTED,
|
||||
AWAITING_AUTHENTICATION, INITIAL_VERSION_APPROVAL_REQUESTED]:
|
||||
return None
|
||||
if has_role(user, "Secretariat"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _can_cancel(user, detail, submission_hash):
|
||||
if detail.status_id in [CANCELLED, POSTED]:
|
||||
return None
|
||||
if has_role(user, "Secretariat"):
|
||||
return True
|
||||
if submission_hash and detail.get_hash() == submission_hash:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _can_edit(user, detail, submission_hash):
|
||||
if detail.status_id != UPLOADED:
|
||||
return None
|
||||
if has_role(user, "Secretariat"):
|
||||
return True
|
||||
if submission_hash and detail.get_hash() == submission_hash:
|
||||
return True
|
||||
return False
|
||||
|
||||
def draft_status(request, submission_id, submission_hash=None, message=None):
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
if submission_hash and not detail.get_hash() == submission_hash:
|
||||
def submission_status(request, submission_id, access_key=None, message=None):
|
||||
submission = get_object_or_404(Submission, pk=submission_id)
|
||||
if access_key and submission.access_key != access_key:
|
||||
raise Http404
|
||||
validation = DraftValidation(detail)
|
||||
is_valid = validation.is_valid()
|
||||
status = None
|
||||
allow_edit = _can_edit(request.user, detail, submission_hash)
|
||||
can_force_post = _can_force_post(request.user, detail)
|
||||
can_approve = _can_approve(request.user, detail)
|
||||
can_cancel = _can_cancel(request.user, detail, submission_hash)
|
||||
if detail.status_id != UPLOADED:
|
||||
if detail.status_id == CANCELLED:
|
||||
message = ('error', 'This submission has been cancelled, modification is no longer possible')
|
||||
status = detail.status
|
||||
allow_edit = None
|
||||
if detail.group_acronym and detail.revision == '00':
|
||||
replaces = "Replaces draft"
|
||||
else:
|
||||
replaces = None
|
||||
|
||||
if request.method == 'POST' and allow_edit:
|
||||
if request.POST.get('autopost', False):
|
||||
auto_post_form = AutoPostForm(draft=detail, validation=validation, replaces=replaces, data=request.POST)
|
||||
if auto_post_form.is_valid():
|
||||
try:
|
||||
preapproval = Preapproval.objects.get(name=detail.filename)
|
||||
except Preapproval.DoesNotExist:
|
||||
preapproval = None
|
||||
errors = validate_submission(submission)
|
||||
passes_idnits = found_idnits(submission.idnits_message)
|
||||
|
||||
if detail.revision == '00' and detail.group_acronym and detail.group_acronym.type_id == "wg" and not preapproval:
|
||||
detail.status_id = INITIAL_VERSION_APPROVAL_REQUESTED
|
||||
detail.save()
|
||||
key_matched = access_key and submission.access_key == access_key
|
||||
is_secretariat = has_role(request.user, "Secretariat")
|
||||
is_chair = submission.group and submission.group.has_role(request.user, "chair")
|
||||
|
||||
submitter = auto_post_form.save_submitter_info()
|
||||
subject = 'New draft waiting for approval: %s' % detail.filename
|
||||
from_email = settings.IDSUBMIT_FROM_EMAIL
|
||||
to_email = [r.formatted_email() for r in Role.objects.filter(group=detail.group_acronym, name="chair").select_related("email", "person")]
|
||||
if to_email:
|
||||
authors = detail.tempidauthors_set.exclude(author_order=0).order_by('author_order')
|
||||
send_mail(request, to_email, from_email, subject, 'submit/submission_approval.txt',
|
||||
{'submitter': submitter, 'authors': authors,
|
||||
'draft': detail, 'domain': Site.objects.get_current().domain})
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': detail.submission_id}))
|
||||
else:
|
||||
auto_post_form.save(request)
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
validation = DraftValidation(detail)
|
||||
is_valid = validation.is_valid()
|
||||
status = detail.status
|
||||
can_force_post = _can_force_post(request.user, detail)
|
||||
can_approve = _can_approve(request.user, detail)
|
||||
can_cancel = _can_cancel(request.user, detail, submission_hash)
|
||||
allow_edit = None
|
||||
message = ('success', 'Your submission is pending email authentication. An email has been sent you with instructions.')
|
||||
else:
|
||||
submission_hash = detail.get_hash()
|
||||
if submission_hash:
|
||||
return HttpResponseRedirect(urlreverse('draft_edit_by_hash', None, kwargs={'submission_id': detail.submission_id, 'submission_hash': submission_hash}))
|
||||
else:
|
||||
return HttpResponseRedirect(urlreverse(draft_edit, None, kwargs={'submission_id': detail.submission_id }))
|
||||
else:
|
||||
auto_post_form = AutoPostForm(draft=detail, validation=validation, replaces=replaces)
|
||||
can_edit = can_edit_submission(request, submission, access_key) and submission.state_id == "uploaded"
|
||||
can_cancel = (key_matched or is_secretariat) and submission.state.next_states.filter(slug="cancel")
|
||||
can_group_approve = (is_secretariat or is_chair) and submission.state_id == "grp-appr"
|
||||
can_force_post = is_secretariat and submission.state.next_states.filter(slug="posted")
|
||||
show_send_full_url = not key_matched and not is_secretariat and submission.state_id not in ("cancel", "posted")
|
||||
|
||||
show_notify_button = False
|
||||
if allow_edit == False or can_cancel == False:
|
||||
show_notify_button = True
|
||||
if submission_hash is None and has_role(request.user, "Secretariat"):
|
||||
submission_hash = detail.get_hash() # we'll need this when rendering the cancel button in the form
|
||||
return render_to_response('submit/draft_status.html',
|
||||
{'selected': 'status',
|
||||
'detail': detail,
|
||||
'validation': validation,
|
||||
'auto_post_form': auto_post_form,
|
||||
'is_valid': is_valid,
|
||||
'status': status,
|
||||
'message': message,
|
||||
'allow_edit': allow_edit,
|
||||
'can_force_post': can_force_post,
|
||||
'can_approve': can_approve,
|
||||
'can_cancel': can_cancel,
|
||||
'submission_hash': submission_hash,
|
||||
'show_notify_button': show_notify_button,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
confirmation_list = submission_confirmation_email_list(submission)
|
||||
|
||||
try:
|
||||
preapproval = Preapproval.objects.get(name=submission.name)
|
||||
except Preapproval.DoesNotExist:
|
||||
preapproval = None
|
||||
|
||||
requires_group_approval = submission.rev == '00' and submission.group and submission.group.type_id in ("wg", "rg") and not preapproval
|
||||
|
||||
requires_prev_authors_approval = Document.objects.filter(name=submission.name)
|
||||
|
||||
if submission.state_id == "cancel":
|
||||
message = ('error', 'This submission has been cancelled, modification is no longer possible.')
|
||||
elif submission.state_id == "auth":
|
||||
message = ('success', u'The submission is pending email authentication. An email has been sent to: %s' % ",".join(confirmation_list))
|
||||
elif submission.state_id == "grp-appr":
|
||||
message = ('success', 'The submission is pending approval by the group chairs.')
|
||||
elif submission.state_id == "aut-appr":
|
||||
message = ('success', 'The submission is pending approval by the authors of the previous version. An email has been sent to: %s' % ",".join(confirmation_list))
|
||||
|
||||
|
||||
def draft_cancel(request, submission_id, submission_hash=None):
|
||||
if request.method!='POST':
|
||||
return HttpResponseNotAllowed(['POST'])
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
can_cancel = _can_cancel(request.user, detail, submission_hash)
|
||||
if not can_cancel:
|
||||
if can_cancel == None:
|
||||
raise Http404
|
||||
return HttpResponseForbidden('You have no permission to perform this action')
|
||||
detail.status_id = CANCELLED
|
||||
detail.save()
|
||||
remove_docs(detail)
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': submission_id}))
|
||||
submitter_form = NameEmailForm(initial=submission.submitter_parsed(), prefix="submitter")
|
||||
|
||||
|
||||
def draft_edit(request, submission_id, submission_hash=None):
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
can_edit = _can_edit(request.user, detail, submission_hash)
|
||||
if not can_edit:
|
||||
if can_edit == None:
|
||||
raise Http404
|
||||
return HttpResponseForbidden('You have no permission to perform this action')
|
||||
validation = DraftValidation(detail)
|
||||
validation.validate_wg()
|
||||
if request.method == 'POST':
|
||||
form = MetaDataForm(draft=detail, validation=validation, data=request.POST)
|
||||
if form.is_valid():
|
||||
form.save(request)
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': detail.submission_id}))
|
||||
else:
|
||||
form = MetaDataForm(draft=detail, validation=validation)
|
||||
return render_to_response('submit/draft_edit.html',
|
||||
action = request.POST.get('action')
|
||||
if action == "autopost" and submission.state_id == "uploaded":
|
||||
if not can_edit:
|
||||
return HttpResponseForbidden("You do not have permission to perfom this action")
|
||||
|
||||
submitter_form = NameEmailForm(request.POST, prefix="submitter")
|
||||
if submitter_form.is_valid():
|
||||
submission.submitter = submitter_form.cleaned_line()
|
||||
|
||||
if requires_group_approval:
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="grp-appr")
|
||||
submission.save()
|
||||
|
||||
sent_to = send_approval_request_to_group(request, submission)
|
||||
|
||||
desc = "sent approval email to group chairs: %s" % u", ".join(sent_to)
|
||||
|
||||
else:
|
||||
submission.auth_key = generate_unique_key()
|
||||
if requires_prev_authors_approval:
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="aut-appr")
|
||||
else:
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="auth")
|
||||
submission.save()
|
||||
|
||||
sent_to = send_submission_confirmation(request, submission)
|
||||
|
||||
if submission.state_id == "aut-appr":
|
||||
desc = u"sent confirmation email to previous authors: %s" % u", ".join(sent_to)
|
||||
else:
|
||||
desc = u"sent confirmation email to submitter and authors: %s" % u", ".join(sent_to)
|
||||
|
||||
create_submission_event(request, submission, u"Set submitter to \"%s\" and %s" % (submission.submitter, desc))
|
||||
|
||||
return redirect("submit_submission_status_by_hash", submission_id=submission.pk, access_key=access_key)
|
||||
|
||||
elif action == "edit" and submission.state_id == "uploaded":
|
||||
if access_key:
|
||||
return redirect("submit_edit_submission_by_hash", submission_id=submission.pk, access_key=access_key)
|
||||
else:
|
||||
return redirect("submit_edit_submission", submission_id=submission.pk)
|
||||
|
||||
elif action == "sendfullurl" and submission.state_id not in ("cancel", "posted"):
|
||||
sent_to = send_full_url(request, submission)
|
||||
|
||||
message = ('success', u'An email has been sent with the full access URL to: %s' % u",".join(confirmation_list))
|
||||
|
||||
create_submission_event(request, submission, u"Sent full access URL to: %s" % u", ".join(sent_to))
|
||||
|
||||
elif action == "cancel" and submission.state.next_states.filter(slug="cancel"):
|
||||
if not can_cancel:
|
||||
return HttpResponseForbidden('You do not have permission to perform this action')
|
||||
|
||||
cancel_submission(submission)
|
||||
|
||||
create_submission_event(request, submission, "Cancelled submission")
|
||||
|
||||
return redirect("submit_submission_status", submission_id=submission_id)
|
||||
|
||||
|
||||
elif action == "approve" and submission.state_id == "grp-appr":
|
||||
if not can_group_approve:
|
||||
return HttpResponseForbidden('You do not have permission to perform this action')
|
||||
|
||||
post_submission(request, submission)
|
||||
|
||||
create_submission_event(request, submission, "Approved and posted submission")
|
||||
|
||||
return redirect("doc_view", name=submission.name)
|
||||
|
||||
|
||||
elif action == "forcepost" and submission.state.next_states.filter(slug="posted"):
|
||||
if not can_force_post:
|
||||
return HttpResponseForbidden('You do not have permission to perform this action')
|
||||
|
||||
post_submission(request, submission)
|
||||
|
||||
if submission.state_id == "manual":
|
||||
desc = "Posted submission manually"
|
||||
else:
|
||||
desc = "Forced post of submission"
|
||||
|
||||
create_submission_event(request, submission, desc)
|
||||
|
||||
return redirect("doc_view", name=submission.name)
|
||||
|
||||
|
||||
else:
|
||||
# something went wrong, turn this into a GET and let the user deal with it
|
||||
return HttpResponseRedirect("")
|
||||
|
||||
return render_to_response('submit/submission_status.html',
|
||||
{'selected': 'status',
|
||||
'detail': detail,
|
||||
'validation': validation,
|
||||
'form': form,
|
||||
'settings': settings
|
||||
'submission': submission,
|
||||
'errors': errors,
|
||||
'passes_idnits': passes_idnits,
|
||||
'submitter_form': submitter_form,
|
||||
'message': message,
|
||||
'can_edit': can_edit,
|
||||
'can_force_post': can_force_post,
|
||||
'can_group_approve': can_group_approve,
|
||||
'can_cancel': can_cancel,
|
||||
'show_send_full_url': show_send_full_url,
|
||||
'requires_group_approval': requires_group_approval,
|
||||
'requires_prev_authors_approval': requires_prev_authors_approval,
|
||||
'confirmation_list': confirmation_list,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def draft_confirm(request, submission_id, auth_key):
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
message = None
|
||||
if auth_key != detail.auth_key:
|
||||
message = ('error', 'Incorrect authorization key')
|
||||
elif detail.status_id != AWAITING_AUTHENTICATION:
|
||||
message = ('error', 'The submission can not be autoposted because it is in state: %s' % detail.status.status_value)
|
||||
else:
|
||||
if request.method=='POST':
|
||||
message = ('success', 'Authorization key accepted. Auto-Post complete')
|
||||
perform_post(request, detail)
|
||||
def edit_submission(request, submission_id, access_key=None):
|
||||
submission = get_object_or_404(Submission, pk=submission_id, state="uploaded")
|
||||
|
||||
if not can_edit_submission(request.user, submission, access_key):
|
||||
return HttpResponseForbidden('You do not have permission to access this page')
|
||||
|
||||
errors = validate_submission(submission)
|
||||
form_errors = False
|
||||
|
||||
# we split the form handling into multiple forms, one for the
|
||||
# submission itself, one for the submitter, and a list of forms
|
||||
# for the authors
|
||||
|
||||
empty_author_form = NameEmailForm(email_required=False)
|
||||
|
||||
if request.method == 'POST':
|
||||
# get a backup submission now, the model form may change some
|
||||
# fields during validation
|
||||
prev_submission = Submission.objects.get(pk=submission.pk)
|
||||
|
||||
edit_form = EditSubmissionForm(request.POST, instance=submission, prefix="edit")
|
||||
submitter_form = NameEmailForm(request.POST, prefix="submitter")
|
||||
author_forms = [ NameEmailForm(request.POST, email_required=False, prefix=prefix)
|
||||
for prefix in request.POST.getlist("authors-prefix")
|
||||
if prefix != "authors-" ]
|
||||
|
||||
# trigger validation of all forms
|
||||
validations = [edit_form.is_valid(), submitter_form.is_valid()] + [ f.is_valid() for f in author_forms ]
|
||||
if all(validations):
|
||||
submission.submitter = submitter_form.cleaned_line()
|
||||
submission.authors = "\n".join(f.cleaned_line() for f in author_forms)
|
||||
edit_form.save(commit=False) # transfer changes
|
||||
|
||||
if submission.rev != prev_submission.rev:
|
||||
rename_submission_files(submission, prev_submission.rev, submission.rev)
|
||||
|
||||
submission.state = DraftSubmissionStateName.objects.get(slug="manual")
|
||||
submission.save()
|
||||
|
||||
send_manual_post_request(request, submission, errors)
|
||||
|
||||
changed_fields = [
|
||||
submission._meta.get_field(f).verbose_name
|
||||
for f in list(edit_form.fields.keys()) + ["submitter", "authors"]
|
||||
if getattr(submission, f) != getattr(prev_submission, f)
|
||||
]
|
||||
|
||||
if changed_fields:
|
||||
desc = u"Edited %s and sent request for manual post" % u", ".join(changed_fields)
|
||||
else:
|
||||
desc = "Sent request for manual post"
|
||||
|
||||
create_submission_event(request, submission, desc)
|
||||
|
||||
return redirect("submit_submission_status", submission_id=submission.pk)
|
||||
else:
|
||||
return render_to_response('submit/last_confirmation_step.html',
|
||||
{'detail': detail, },
|
||||
context_instance=RequestContext(request))
|
||||
return draft_status(request, submission_id, message=message)
|
||||
form_errors = True
|
||||
else:
|
||||
edit_form = EditSubmissionForm(instance=submission, prefix="edit")
|
||||
submitter_form = NameEmailForm(initial=submission.submitter_parsed(), prefix="submitter")
|
||||
author_forms = [ NameEmailForm(initial=author, email_required=False, prefix="authors-%s" % i)
|
||||
for i, author in enumerate(submission.authors_parsed()) ]
|
||||
|
||||
return render_to_response('submit/edit_submission.html',
|
||||
{'selected': 'status',
|
||||
'submission': submission,
|
||||
'edit_form': edit_form,
|
||||
'submitter_form': submitter_form,
|
||||
'author_forms': author_forms,
|
||||
'empty_author_form': empty_author_form,
|
||||
'errors': errors,
|
||||
'form_errors': form_errors,
|
||||
},
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
|
||||
def draft_approve(request, submission_id, check_function=_can_approve):
|
||||
if request.method!='POST':
|
||||
return HttpResponseNotAllowed(['POST'])
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
can_perform = check_function(request.user, detail)
|
||||
if not can_perform:
|
||||
if can_perform == None:
|
||||
raise Http404
|
||||
return HttpResponseForbidden('You have no permission to perform this action')
|
||||
perform_post(request, detail)
|
||||
return HttpResponseRedirect(urlreverse(draft_status, None, kwargs={'submission_id': submission_id}))
|
||||
def confirm_submission(request, submission_id, auth_key):
|
||||
submission = get_object_or_404(Submission, pk=submission_id)
|
||||
|
||||
if request.method == 'POST' and submission.state_id in ("auth", "aut-appr") and auth_key == submission.auth_key:
|
||||
post_submission(request, submission)
|
||||
|
||||
def draft_force(request, submission_id):
|
||||
if request.method!='POST':
|
||||
return HttpResponseNotAllowed(['POST'])
|
||||
return draft_approve(request, submission_id, check_function=_can_force_post)
|
||||
create_submission_event(request, submission, "Confirmed and posted submission")
|
||||
|
||||
return redirect("doc_view", name=submission.name)
|
||||
|
||||
return render_to_response('submit/confirm_submission.html', {
|
||||
'submission': submission,
|
||||
'auth_key': auth_key,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
def full_url_request(request, submission_id):
|
||||
if request.method!='POST':
|
||||
return HttpResponseNotAllowed(['POST'])
|
||||
detail = get_object_or_404(IdSubmissionDetail, submission_id=submission_id)
|
||||
request_full_url(request, detail)
|
||||
message = ('success', 'An email has been sent to draft authors to inform them of the full access url')
|
||||
return draft_status(request, submission_id, message=message)
|
||||
|
||||
def approvals(request):
|
||||
approvals = get_approvable_submissions(request.user)
|
||||
preapprovals = get_preapprovals(request.user)
|
||||
approvals = approvable_submissions_for_user(request.user)
|
||||
preapprovals = preapprovals_for_user(request.user)
|
||||
|
||||
days = 30
|
||||
recently_approved = get_recently_approved(request.user, datetime.date.today() - datetime.timedelta(days=days))
|
||||
recently_approved = recently_approved_by_user(request.user, datetime.date.today() - datetime.timedelta(days=days))
|
||||
|
||||
return render_to_response('submit/approvals.html',
|
||||
{'selected': 'approvals',
|
||||
|
@ -309,7 +422,7 @@ def add_preapproval(request):
|
|||
def cancel_preapproval(request, preapproval_id):
|
||||
preapproval = get_object_or_404(Preapproval, pk=preapproval_id)
|
||||
|
||||
if preapproval not in get_preapprovals(request.user):
|
||||
if preapproval not in preapprovals_for_user(request.user):
|
||||
raise HttpResponseForbidden("You do not have permission to cancel this preapproval.")
|
||||
|
||||
if request.method == "POST" and request.POST.get("action", "") == "cancel":
|
||||
|
|
|
@ -88,7 +88,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
<a style="padding: 0;" href="{% url ietf.group.views_stream.streams %}irtf/">IRTF</a>
|
||||
<a style="padding: 0;" href="{% url ietf.group.views_stream.streams %}ise/">ISE</a>
|
||||
</li>
|
||||
<li><a href="{% url submit_index %}">Submit a draft</a></li>
|
||||
<li><a href="{% url submit_upload_submission %}">Submit a draft</a></li>
|
||||
{% if user|has_role:"WG Chair" %}
|
||||
<li><a href="{% url submit_approvals %}">Approve a draft</a></li>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{% autoescape off %}
|
||||
A new version (-{{ submission.revision }}) has been submitted for {{ submission.filename }}:
|
||||
http://www.ietf.org/internet-drafts/{{ submission.filename }}-{{ submission.revision }}.txt
|
||||
A new version (-{{ submission.rev }}) has been submitted for {{ submission.name }}:
|
||||
http://www.ietf.org/internet-drafts/{{ submission.name }}-{{ submission.rev }}.txt
|
||||
{% if msg %}
|
||||
{{ msg|striptags }}
|
||||
{% endif %}
|
||||
|
||||
The IETF datatracker page for this Internet-Draft is:
|
||||
https://datatracker.ietf.org/doc/{{ submission.filename }}/
|
||||
https://datatracker.ietf.org/doc/{{ submission.name }}/
|
||||
|
||||
Diff from previous version:
|
||||
http:{{rfcdiff_prefix}}?url2={{ submission.filename }}-{{ submission.revision }}
|
||||
http:{{rfcdiff_prefix}}?url2={{ submission.name }}-{{ submission.rev }}
|
||||
|
||||
Please note that it may take a couple of minutes from the time of submission
|
||||
until the htmlized version and diff are available at tools.ietf.org.
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
{% autoescape off %}
|
||||
A new version of I-D, {{ submission.filename }}-{{ submission.revision }}.txt
|
||||
has been successfully submitted by {{ submitter }} and posted to the
|
||||
A new version of I-D, {{ submission.name }}-{{ submission.rev }}.txt
|
||||
has been successfully submitted by {{ submission.submitter_parsed.name }} and posted to the
|
||||
IETF repository.
|
||||
|
||||
Filename: {{ submission.filename }}
|
||||
Revision: {{ submission.revision }}
|
||||
Title: {{ submission.id_document_name }}
|
||||
Creation date: {{ submission.creation_date|date:"Y-m-d" }}
|
||||
Group: {{ wg }}
|
||||
Number of pages: {{ submission.txt_page_count }}
|
||||
URL: http://www.ietf.org/internet-drafts/{{ submission.filename }}-{{ submission.revision }}.txt
|
||||
Status: http://datatracker.ietf.org/doc/{{ submission.filename }}
|
||||
Htmlized: http://tools.ietf.org/html/{{ submission.filename }}-{{ submission.revision }}
|
||||
{% ifnotequal submission.revision "00" %}Diff: http:{{rfcdiff_prefix}}?url2={{ submission.filename }}-{{ submission.revision }}{% endifnotequal %}
|
||||
Name: {{ submission.name }}
|
||||
Revision: {{ submission.rev }}
|
||||
Title: {{ submission.title }}
|
||||
Document date: {{ submission.document_date|date:"Y-m-d" }}
|
||||
Group: {{ group }}
|
||||
Pages: {{ submission.pages }}
|
||||
URL: http://www.ietf.org/internet-drafts/{{ submission.name }}-{{ submission.rev }}.txt
|
||||
Status: https://datatracker.ietf.org/doc/{{ submission.name }}/
|
||||
Htmlized: http://tools.ietf.org/html/{{ submission.name }}-{{ submission.rev }}
|
||||
{% if submission.rev != "00" %}Diff: http:{{rfcdiff_prefix}}?url2={{ submission.name }}-{{ submission.rev }}{% endif %}
|
||||
|
||||
Abstract:
|
||||
{{ submission.abstract }}
|
||||
|
||||
{{ submission.comment_to_sec|default:"" }}
|
||||
{{ submission.note|default:"" }}
|
||||
|
||||
Please note that it may take a couple of minutes from the time of submission
|
||||
until the htmlized version and diff are available at tools.ietf.org.
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
{% autoescape off %}
|
||||
A New Internet-Draft is available from the on-line Internet-Drafts directories.
|
||||
{% if submission.group_acronym %} This draft is a work item of the {{ submission.group_acronym.name }} Working Group of the IETF.{% endif %}
|
||||
{% if submission.group %} This draft is a work item of the {{ submission.group.name }} Working Group of the IETF.{% endif %}
|
||||
|
||||
Title : {{ submission.id_document_name }}
|
||||
Author(s) : {% for author in authors %}{{ author }}{% if not forloop.last %}
|
||||
Title : {{ submission.title }}
|
||||
Author{{ submission.authors_parsed|pluralize:" ,s" }} : {% for author in submission.authors_parsed %}{{ author.name }}{% if not forloop.last %}
|
||||
{% endif %}{% endfor %}
|
||||
Filename : {{ submission.filename }}-{{ submission.revision }}.txt
|
||||
Pages : {{ submission.txt_page_count }}
|
||||
Filename : {{ submission.name }}-{{ submission.rev }}.txt
|
||||
Pages : {{ submission.pages }}
|
||||
Date : {{ submission.submission_date|date:"Y-m-d" }}
|
||||
|
||||
Abstract:
|
||||
{{ submission.abstract }}
|
||||
|
||||
The IETF datatracker status page for this draft is:
|
||||
https://datatracker.ietf.org/doc/{{ submission.filename }}
|
||||
https://datatracker.ietf.org/doc/{{ submission.name }}/
|
||||
|
||||
There's also a htmlized version available at:
|
||||
http://tools.ietf.org/html/{{ submission.filename }}-{{ submission.revision }}
|
||||
{% if submission.revision != "00" %}
|
||||
http://tools.ietf.org/html/{{ submission.name }}-{{ submission.rev }}
|
||||
{% if submission.rev != "00" %}
|
||||
A diff from the previous version is available at:
|
||||
http:{{settings.RFCDIFF_PREFIX}}?url2={{ submission.filename }}-{{ submission.revision }}
|
||||
http:{{settings.RFCDIFF_PREFIX}}?url2={{ submission.name }}-{{ submission.rev }}
|
||||
{% endif %}
|
||||
|
||||
Please note that it may take a couple of minutes from the time of submission
|
||||
|
|
33
ietf/templates/submit/approval_request.txt
Normal file
33
ietf/templates/submit/approval_request.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
{% autoescape off %}
|
||||
Hi,
|
||||
|
||||
Chair approval is needed for posting of {{ submission.name }}-{{ submission.rev }}.
|
||||
|
||||
To approve the draft, go to this URL (note: you need to login to be able to approve):
|
||||
https://{{ domain }}/submit/status/{{ submission.pk }}/{{ submission.access_key }}/
|
||||
|
||||
File name : {{ submission.name }}
|
||||
Revision : {{ submission.rev }}
|
||||
Submission date : {{ submission.submission_date }}
|
||||
Group : {{ submission.group|default:"Individual Submission" }}
|
||||
|
||||
Title : {{ submission.title }}
|
||||
Document date : {{ submission.document_date }}
|
||||
Pages : {{ submission.pages }}
|
||||
File size : {{ submission.file_size|filesizeformat }}
|
||||
|
||||
Submitter : {{ submission.submitter }}
|
||||
|
||||
Abstract : {{ submission.abstract }}
|
||||
|
||||
|
||||
Authors:
|
||||
{% for author in submission.authors_parsed %} {{ author.name }}{% if author.email %} <{{ author.email }}>{% endif%}
|
||||
{% endfor %}
|
||||
{% endautoescape %}
|
||||
|
||||
|
||||
Best regards,
|
||||
|
||||
The IETF Secretariat
|
||||
through the draft submission service
|
|
@ -22,16 +22,16 @@ table.preapprovals tr:hover td a.cancel { visibility: visible; }
|
|||
<p>You don't have any submissions to approve.</p>
|
||||
{% else %}
|
||||
<table cellspacing="0" class="approvals">
|
||||
<tr>
|
||||
<th>Submission</th>
|
||||
<th>Submitted</th>
|
||||
</tr>
|
||||
{% for d in approvals %}
|
||||
<tr>
|
||||
<td><a href="{% url draft_status d.pk %}">{{ d.filename }}-{{ d.revision }}</a></td>
|
||||
<td>{{ d.submission_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th>Submission</th>
|
||||
<th>Submitted</th>
|
||||
</tr>
|
||||
{% for s in approvals %}
|
||||
<tr>
|
||||
<td><a href="{% url submit_submission_status_by_hash submission_id=s.pk access_key=s.access_key %}">{{ s.name }}-{{ s.rev }}</a></td>
|
||||
<td>{{ s.submission_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
@ -46,19 +46,19 @@ table.preapprovals tr:hover td a.cancel { visibility: visible; }
|
|||
{% else %}
|
||||
|
||||
<table cellspacing="0" class="preapprovals">
|
||||
<tr>
|
||||
<th>Draft name</th>
|
||||
<th>Pre-approved</th>
|
||||
<th>By</th>
|
||||
</tr>
|
||||
{% for p in preapprovals %}
|
||||
<tr>
|
||||
<td>{{ p.name }}</td>
|
||||
<td>{{ p.time|date:"Y-m-d" }}</td>
|
||||
<td>{{ p.by }}</td>
|
||||
<td><a class="cancel" href="{% url submit_cancel_preapproval preapproval_id=p.id %}">cancel pre-approval</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th>Draft name</th>
|
||||
<th>Pre-approved</th>
|
||||
<th>By</th>
|
||||
</tr>
|
||||
{% for p in preapprovals %}
|
||||
<tr>
|
||||
<td>{{ p.name }}</td>
|
||||
<td>{{ p.time|date:"Y-m-d" }}</td>
|
||||
<td>{{ p.by }}</td>
|
||||
<td><a class="cancel" href="{% url submit_cancel_preapproval preapproval_id=p.id %}">cancel pre-approval</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
@ -69,18 +69,19 @@ table.preapprovals tr:hover td a.cancel { visibility: visible; }
|
|||
{% else %}
|
||||
|
||||
<table cellspacing="0" class="recently-approved">
|
||||
<tr>
|
||||
<th>Draft</th>
|
||||
<th>Submitted</th>
|
||||
</tr>
|
||||
{% for d in recently_approved %}
|
||||
<tr>
|
||||
<td><a href="{% url doc_view d.filename %}">{{ d.filename }}</a></td>
|
||||
<td>{{ d.submission_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th>Draft</th>
|
||||
<th>Submitted</th>
|
||||
</tr>
|
||||
{% for d in recently_approved %}
|
||||
<tr>
|
||||
<td><a href="{% url doc_view d.name %}">{{ d.name }}</a></td>
|
||||
<td>{{ d.submission_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<h2>Submission approvals</h2>
|
||||
<p>
|
||||
|
|
56
ietf/templates/submit/confirm_submission.html
Normal file
56
ietf/templates/submit/confirm_submission.html
Normal file
|
@ -0,0 +1,56 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
|
||||
{% block title %}Confirm submission of {{ submission.name }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
{{ block.super }}
|
||||
p.error { color: red; font-weight: bold; font-size: 1.5em; }
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block submit_content %}
|
||||
|
||||
<h2>Confirm submission of {{ submission.name }}</h2>
|
||||
|
||||
{% if submission.state_id != "auth" and submission.state_id != "aut-appr" %}
|
||||
{% if submission.state_id == "posted" %}
|
||||
<p>The submission has already been posted. See the <a href="{% url doc_view name=submission.name %}">draft here</a>.</p>
|
||||
{% else %}
|
||||
<p>The submission is not in a state where it can be confirmed.</p>
|
||||
|
||||
<p>Go to the <a href="{% url submit_submission_status submission_id=submission.pk %}">status page</a>
|
||||
to see what has happened to it.</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
{% if auth_key != submission.auth_key %}
|
||||
<p class="error">Incorrect authorization key.</p>
|
||||
|
||||
<p>Double-check the link you followed. If everything fails, you can go to
|
||||
the <a href="{% url submit_submission_status submission_id=submission.pk %}">status page</a>,
|
||||
cancel the submission and try again.</p>
|
||||
{% else %}
|
||||
<p>Authorization key accepted.</p>
|
||||
|
||||
<p>Please press the button below to finish posting of
|
||||
<strong>{{ submission.name }}-{{ submission.rev }}</strong></p>
|
||||
|
||||
<form method="post">
|
||||
<input type="submit" value="Confirm submission and post draft" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
jQuery(function () {
|
||||
jQuery("form").submit(function() {
|
||||
if (this.submittedAlready)
|
||||
return false;
|
||||
else
|
||||
this.submittedAlready = true;
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
|
@ -2,12 +2,13 @@
|
|||
Hi,
|
||||
|
||||
The IETF datatracker draft submission service has received your draft
|
||||
{{ draft.filename }}-{{ draft.revision }}, and requires a
|
||||
{{ submission.name }}-{{ submission.rev }}, and requires a
|
||||
confirmation step in order to be able to complete the posting of
|
||||
the draft.
|
||||
|
||||
Please follow this link to the page where you can confirm the posting:
|
||||
Confirmation URL: {{ confirm_url|safe }}
|
||||
|
||||
{{ confirm_url }}
|
||||
|
||||
|
||||
Best regards,
|
|
@ -1,169 +0,0 @@
|
|||
{% extends "submit/draft_status.html" %}
|
||||
{% load submit_tags %}
|
||||
{% block title %}Adjust Meta-Data{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
{{ block.super }}
|
||||
table.metadata-table #id_title, table.metadata-table #id_abstract, table.metadata-table #id_comments { width: 500px; }
|
||||
table.metadata-table tr.warning th, table.metadata-table tr.warning td { background-color: #ffeebb; }
|
||||
table.ietf-table tr { vertical-align: top; }
|
||||
table.ietf-table tr.error { background-color: #ffeebb; border-top: 1px dashed red; border-bottom: 1px dashed red;}
|
||||
table.ietf-table span.field-error { display: block; color: red; }
|
||||
{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{{ block.super }}
|
||||
|
||||
<script type="text/javascript" src="/js/draft-submit.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function ($) {
|
||||
|
||||
$.fn.AuthorList = function() {
|
||||
return this.each(function () {
|
||||
var table = $(this);
|
||||
var makeEditable = function() {
|
||||
table.find('tbody tr').each(function(index, value) {
|
||||
var tr = $(this);
|
||||
tr.find('td').each(function() {
|
||||
var td = $(this);
|
||||
var text = td.find('.fieldValue');
|
||||
var name = td.attr('name');
|
||||
if (tr.hasClass('non_editable')) {
|
||||
td.prepend('<input style="display: none;" type="text" name="' + name + '_' + index + '" value="' + text.text() + '" />');
|
||||
} else {
|
||||
td.prepend('<input type="text" name="' + name + '_' + index + '" value="' + text.text() + '" />');
|
||||
text.html('');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var addNewEntry = function() {
|
||||
table.append(table.find('tbody tr').last().clone());
|
||||
var new_tr = table.find('tbody tr').last();
|
||||
new_tr.toggleClass('evenrow').toggleClass('oddrow');
|
||||
new_tr.removeClass('error').find('.field-error').remove();
|
||||
new_tr.find('input').each(function() {
|
||||
var name = $(this).attr('name');
|
||||
var splitted = name.split('_');
|
||||
splitted.reverse();
|
||||
name = name.replace(splitted[0], (parseInt(splitted[0]) + 1).toString(10));
|
||||
$(this).attr('name', name);
|
||||
$(this).val('');
|
||||
});
|
||||
};
|
||||
|
||||
var bindTriggers = function() {
|
||||
$('.new_author').click(addNewEntry);
|
||||
};
|
||||
|
||||
var initialize = function() {
|
||||
makeEditable();
|
||||
bindTriggers();
|
||||
};
|
||||
|
||||
initialize();
|
||||
});
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
$('table.author_list').AuthorList();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
<h2>Adjust External Meta-Data</h2>
|
||||
|
||||
<div id="idnits_results" style="visibility:hidden;">
|
||||
<div class="hd">
|
||||
<span style="display: none;" id="twopages_title">First two pages</span>
|
||||
</div>
|
||||
<div class="bd">
|
||||
<div id="stream_dialog_body" style="padding: 0em 5em; height: 400px; overflow: auto;">
|
||||
<pre class="twopages" style="display: none;">{{ detail.first_two_pages }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="metadata-table">
|
||||
<tr><th>Document</th><td>{{ detail.filename }} <a class="twopages_trigger" href="#">[View first two pages]</a>
|
||||
{% show_submission_files detail %}
|
||||
</td></tr>
|
||||
<tr><th>Submission date</th><td>{{ detail.submission_date }}</td></tr>
|
||||
<tr{% if validation.warnings.group %} class="warning"{% endif %}><th>Group</th><td>{{ validation.wg|default:"Individual Submission" }}
|
||||
{% if validation.warnings.group %}
|
||||
<div class="warn_message">The secretariat will be notified that the working group is not active</div>
|
||||
{% endif %}
|
||||
</td></tr>
|
||||
<tr><th>File size</th><td>{{ detail.filesize|filesizeformat }}</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Adjust data</h3>
|
||||
{% if form.errors %}
|
||||
<div class="metadata-errors">
|
||||
Please fix the following errors.
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="post" action="">
|
||||
<table class="metadata-table">
|
||||
<tr{% if form.errors.title %} class="warning"{% endif %}><th>Title</th><td>{{ form.title }}{{ form.errors.title }}</td></tr>
|
||||
<tr{% if form.errors.version %} class="warning"{% endif %}><th>Version</th><td>{{ form.version }}{{ form.errors.version }}</td></tr>
|
||||
<tr{% if form.errors.creation_date %} class="warning"{% endif %}><th>Creation date</th><td>{{ form.creation_date }}{{ form.errors.creation_date }}</td></tr>
|
||||
<tr{% if form.errors.abstract %} class="warning"{% endif %}><th>Abstract</th><td>{{ form.abstract }}{{ form.errors.abstract }}</td></tr>
|
||||
<tr{% if form.errors.pages %} class="warning"{% endif %}><th>Pages</th><td>{{ form.pages }}{{ form.errors.pages }}</td></tr>
|
||||
<tr><th>Submitter</th>
|
||||
<td>
|
||||
If you are one of the authors, then please click a button by your name to automatically fill in the submitter's information as requested below. Otherwise, Please manually enter your information.<br />
|
||||
{{ form.get_author_buttons|safe }}
|
||||
</td></tr>
|
||||
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
|
||||
<tr{% if form.errors.name %} class="warning"{% endif %}><th class="author">Name</th><td>{{ form.name }}{{ form.errors.name }}</td></tr>
|
||||
{% else %}
|
||||
<tr{% if form.errors.first_name %} class="warning"{% endif %}><th class="author">First name</th><td>{{ form.first_name }}{{ form.errors.first_name }}</td></tr>
|
||||
<tr{% if form.errors.last_name %} class="warning"{% endif %}><th class="author">Last name</th><td>{{ form.last_name }}{{ form.errors.last_name }}</td></tr>
|
||||
{% endif %}
|
||||
<tr{% if form.errors.email %} class="warning"{% endif %}><th class="author">Email address</th><td>{{ form.email }}{{ form.errors.email }}</td></tr>
|
||||
<tr{% if form.errors.comments %} class="warning"{% endif %}><th>Comments to the secretariat</th><td>{{ form.comments }}{{ form.errors.comments }}</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Authors</h3>
|
||||
<table class="author_list ietf-table" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
|
||||
<th>Name</th>
|
||||
{% else %}
|
||||
<th>First name</th>
|
||||
<th>Last name</th>
|
||||
{% endif %}
|
||||
<th>Email address</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for author in form.get_authors %}
|
||||
<tr class="editable {% cycle oddrow,evenrow %}{% if author.errors %} error{% endif %}">
|
||||
{% if settings.USE_DB_REDESIGN_PROXY_CLASSES %}
|
||||
<td name="name"><span class="fieldValue">{{ author.get_full_name|default:"" }}</span><span class="field-error">{{ author.errors.name }}</span></td>
|
||||
{% else %}
|
||||
<td name="first_name"><span class="fieldValue">{{ author.first_name|default:"" }}</span><span class="field-error">{{ author.errors.first_name }}</span></td>
|
||||
<td name="last_name"><span class="fieldValue">{{ author.last_name|default:"" }}</span><span class="field-error">{{ author.errors.last_name }}</span></td>
|
||||
{% endif %}
|
||||
<td name="email"><span class="fieldValue">{{ author.email.1|default:"" }}</span><span class="field-error">{{ author.errors.email }}</span></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align: right; margin-bottom: 1em;">
|
||||
<input type="button" value="Add another author" class="new_author" />
|
||||
</div>
|
||||
<input type="submit" value="Submit for manual posting" />
|
||||
</form>
|
||||
|
||||
<p>
|
||||
The IETF is an organized activity of the <a href="http://www.isoc.org">Internet Society</a>
|
||||
<br>Please send problem reports to <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -1,257 +0,0 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
{% load submit_tags %}
|
||||
{% block title %}Submission status{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
{{ block.super }}
|
||||
div.metadata-errors { border: 1px solid red; background-color: #ffeebb; padding: 5px 10px; margin: 1em 0px; }
|
||||
div.info-message-error { border: 1px solid red; background-color: #ffeebb; padding: 5px 10px; margin: 1em 0px; color: red; }
|
||||
div.info-message-success { border: 1px solid green; background-color: #eeffbb; padding: 5px 10px; margin: 1em 0px; color: green; }
|
||||
table.metadata-table th { white-space: nowrap; font-weight: bold; }
|
||||
table.metadata-table #id_first_name, table.metadata-table #id_last_name { width: 200px; }
|
||||
table.metadata-table #id_email { width: 400px; }
|
||||
table.metadata-table th, table.metadata-table td { text-align: left; background: #ddddff; padding: 5px 10px; }
|
||||
table.metadata-table th.author { text-align: right; }
|
||||
table.metadata-table tr { vertical-align: top; }
|
||||
table.metadata-table tr.warning td, table.metadata-table tr.warning th { background-color: #ffaaaa; }
|
||||
table.metadata-table div.warn_message { color: red; }
|
||||
table.metadata-table ul.errorlist { color: red; padding: 0px; margin: 0px; list-style-type: none; }
|
||||
pre.twopages { margin: 0px; }
|
||||
{% endblock morecss %}
|
||||
|
||||
{% block pagehead %}
|
||||
<script type="text/javascript" src="/js/lib/jquery-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="/js/draft-submit.js"></script>
|
||||
{% if can_cancel %}
|
||||
<script type="text/javascript">
|
||||
function confirmCancelation(){
|
||||
{% if is_valid %}if (!confirm("Cancel this submission?")) return false;{% endif %}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<script type="text/javascript">
|
||||
(function ($) {
|
||||
|
||||
$(document).ready(function () {
|
||||
var handleClose = function() {
|
||||
idnitsDialog.hide();
|
||||
};
|
||||
|
||||
var buttons = [{text:"Close", handler:handleClose, isDefault:true}];
|
||||
var kl = [new YAHOO.util.KeyListener(document, {keys:27}, handleClose)]
|
||||
var idnitsDialog = new YAHOO.widget.Dialog("idnits_results", {
|
||||
visible:false, draggable:false, close:true, modal:true,
|
||||
width:"860px", fixedcenter:true, constraintoviewport:true,
|
||||
buttons: buttons, keylisteners:kl});
|
||||
idnitsDialog.render();
|
||||
|
||||
var showIdnits = function() {
|
||||
$('#idnits_results').show();
|
||||
$('#idnits_title').show();
|
||||
$('#twopages_title').hide();
|
||||
$('pre.idnits_message').show();
|
||||
$('pre.twopages').hide();
|
||||
idnitsDialog.show();
|
||||
return false;
|
||||
}
|
||||
|
||||
var showTwoPages = function() {
|
||||
$('#idnits_results').show();
|
||||
$('#idnits_title').hide();
|
||||
$('#twopages_title').show();
|
||||
$('pre.idnits_message').hide();
|
||||
$('pre.twopages').show();
|
||||
idnitsDialog.show();
|
||||
return false;
|
||||
}
|
||||
|
||||
$('a.idnits_trigger').click(showIdnits);
|
||||
$('a.twopages_trigger').click(showTwoPages);
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
|
||||
{% if status %}
|
||||
<h2>Status of the submission: {{ status.status_value }}</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if message %}
|
||||
<div class="info-message-{{ message.0 }}">{{ message.1 }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if auto_post_form.errors %}
|
||||
<div class="info-message-error">Please fix errors in the form below</div>
|
||||
{% endif %}
|
||||
|
||||
<h2>Check Page</h2>
|
||||
<p>
|
||||
{% if validation.passes_idnits %}
|
||||
Your draft has been verified to meet IDNITS requirements.
|
||||
{% else %}
|
||||
Your draft has NOT been verified to meet IDNITS requirements.
|
||||
{% endif %}
|
||||
<a class="idnits_trigger" href="#">(View IDNITS Results)</a>
|
||||
</p>
|
||||
<div id="idnits_results" style="visibility:hidden; display: none;">
|
||||
<div class="hd">
|
||||
<span style="display: none;" id="idnits_title">Idnits results</span>
|
||||
<span style="display: none;" id="twopages_title">First two pages</span>
|
||||
</div>
|
||||
<div class="bd">
|
||||
<div id="stream_dialog_body" style="padding: 0em 5em; height: 400px; overflow: auto;">
|
||||
<pre class="idnits_message" style="display: none;">{{ detail.idnits_message }}</pre>
|
||||
{{ detail|two_pages_decorated_with_validation:validation }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Meta-Data from the Draft</h2>
|
||||
{% if validation.warnings %}
|
||||
<div class="metadata-errors">
|
||||
<h3>Meta-Data errors found</h3>
|
||||
<p>
|
||||
Please make sure that your Internet-Draft includes all of the required meta-data in the proper format.
|
||||
</p>
|
||||
<p>
|
||||
If your Internet-Draft *does* include all of the required meta-data in the proper format, and if
|
||||
the error(s) identified above are due to the failure of the tool to extract the meta-data correctly,
|
||||
then please use the 'Adjust Meta-Data' button below, which will take you to the 'Adjust Screen' where
|
||||
you can correct the improperly extracted meta-data. You will then be able to submit your Internet-Draft
|
||||
to the Secretariat for manual posting.
|
||||
</p>
|
||||
<p>
|
||||
If your Internet-Draft *does not* include all of the required meta-data in the proper format, then
|
||||
please cancel this submission, update your Internet-Draft, and resubmit it.
|
||||
</p>
|
||||
<p>
|
||||
<strong>NOTE:</strong> The Secretariat will NOT add any meta-data to your Internet-Draft or edit the meta-data. An
|
||||
Internet-Draft that does not include all of the required meta-data in the proper format WILL be
|
||||
returned to the submitter.
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<table class="metadata-table">
|
||||
<tr{% if validation.warnings.document_files %} class="warning"{% endif %}>
|
||||
<th>Document</th>
|
||||
<td>
|
||||
{% ifequal status.status_value "Posted" %}<a href="http://www.ietf.org/id/{{ detail.filename }}-{{detail.revision}}.txt">{{ detail.filename }}</a>{% else %}{{ detail.filename }}{% endifequal %}
|
||||
<br/><a class="twopages_trigger" href="#">[View first two pages]</a>
|
||||
{% show_submission_files detail %}
|
||||
<div class="warn_message">{{ validation.warnings.document_files|safe }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr{% if validation.warnings.revision %} class="warning"{% endif %}><th>Revision</th><td>{{ detail.revision }}<div class="warn_message">{{ validation.warnings.revision }}{% if validation.warnings.revision %}<br /><a class="twopages_trigger" href="#">[View error]</a>{% endif %}</div></td></tr>
|
||||
<tr{% if validation.warnings.group %} class="warning"{% endif %}><th>Group</th><td>{{ validation.wg|default:"Individual Submission" }}<div class="warn_message">{{ validation.warnings.group }}</div></td></tr>
|
||||
<tr{% if validation.warnings.creation_date %} class="warning"{% endif %}><th>Document date</th><td>{{ detail.creation_date }}<div class="warn_message">{{ validation.warnings.creation_date }}</div></td></tr>
|
||||
<tr><th>Submission date</th><td>{{ detail.submission_date }}</td></tr>
|
||||
<tr{% if validation.warnings.title %} class="warning"{% endif %}><th>Title</th><td>{{ detail.id_document_name|default:"" }}<div class="warn_message">{{ validation.warnings.title }}</div></td></tr>
|
||||
<tr{% if validation.warnings.authors %} class="warning"{% endif %}><th colspan="2">Author information</th></tr>
|
||||
{% if validation.warnings.authors %}
|
||||
<tr class="warning"><td colspan="2"><div class="warn_message">{{ validation.warnings.authors|safe }}</div></td></tr>
|
||||
{% endif %}
|
||||
{% if validation.authors %}
|
||||
{% for author in validation.authors %}
|
||||
<tr{% if validation.warnings.authors %} class="warning"{% endif %}><th class="author">Author {{ forloop.counter }}</th><td>{{ author.get_full_name }} {% if author.email.1 %}<{{ author.email.1 }}>{% endif %}</td></tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<tr{% if validation.warnings.abstract %} class="warning"{% endif %}><th>Abstract</th><td>{{ detail.abstract|linebreaksbr }}<div class="warn_message">{{ validation.warnings.abstract }}</div></td></tr>
|
||||
<tr{% if validation.warnings.pages %} class="warning"{% endif %}><th>Pages</th><td>{{ detail.txt_page_count }}<div class="warn_message">{{ validation.warnings.pages }}</div></td></tr>
|
||||
<tr><th>File size</th><td>{{ detail.filesize|filesizeformat }}</td></tr>
|
||||
</table>
|
||||
|
||||
{% if allow_edit %}
|
||||
<form method="post" action="">
|
||||
<input type="submit" value="Adjust Meta-Data" value="adjust" /> (Leads to manual post by the Secretariat)
|
||||
</form>
|
||||
|
||||
{% if is_valid %}
|
||||
<h2>Please edit the following meta-data before proceeding to Auto-Post</h2>
|
||||
<p>
|
||||
If you are one of the authors of this document, then please click the button with your name on it to automatically fill in the submitter information as requested below. Otherwise, please manually enter your information.
|
||||
</p>
|
||||
<form method="post" action="">
|
||||
{{ auto_post_form.get_author_buttons|safe }}
|
||||
<table class="metadata-table">
|
||||
{{ auto_post_form }}
|
||||
</table>
|
||||
<input type="submit" value="Post" name="autopost" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% else %}
|
||||
{% if validation.submitter %}
|
||||
<h3>Submitter information</h3>
|
||||
<table class="metadata-table">
|
||||
<tr><th>Name</th><td>{{ validation.submitter.first_name }}</td></tr>
|
||||
<tr><th>Email address</th><td>{{ validation.submitter.email_address|default:validation.submitter.email.1 }}</td></tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if can_cancel %}
|
||||
<h2>Cancel submission</h2>
|
||||
<p>
|
||||
<form method="post" onsubmit="return confirmCancelation();" action="{% url draft_cancel_by_hash detail.submission_id submission_hash %}">
|
||||
<input type="submit" value="Cancel Submission" /><br>
|
||||
</form>
|
||||
This submission will be canceled, and its uploaded document(s) permanently deleted.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if can_approve %}
|
||||
<p>
|
||||
<form method="post" action="/submit/status/{{ detail.submission_id }}/approve/">
|
||||
<input type="submit" value="Approve this submission" />
|
||||
</form>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if can_force_post %}
|
||||
<p>
|
||||
<form method="post" action="/submit/status/{{ detail.submission_id }}/force/">
|
||||
<input type="submit" value="Force post" />
|
||||
</form>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if show_notify_button %}
|
||||
<div class="metadata-errors">
|
||||
<p>
|
||||
You are not allowed to modify or cancel this submission. You only can modify or cancel this submission from the same URL you were redirected to after the submission.
|
||||
</p>
|
||||
<p>
|
||||
If you are the submitter check your browser history to find this url. You can share it with any person you need.
|
||||
</p>
|
||||
<p>
|
||||
If you are one of the authors you can request the URL from wich you can modify or cancel this submission by clicking the next button. An email will be sent to the draft authors and to the submitter (if the submitter's email is available).
|
||||
</p>
|
||||
<form method="post" action="{% url full_url_request detail.submission_id %}">
|
||||
<input type="submit" value="Request full access URL" />
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p>
|
||||
The IETF is an organized activity of the <a href="http://www.isoc.org">Internet Society</a>
|
||||
<br>Please send problem reports to <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>.
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
jQuery(function () {
|
||||
jQuery("form").submit(function() {
|
||||
if (this.submittedAlready)
|
||||
return false;
|
||||
else
|
||||
this.submittedAlready = true;
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
114
ietf/templates/submit/edit_submission.html
Normal file
114
ietf/templates/submit/edit_submission.html
Normal file
|
@ -0,0 +1,114 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
|
||||
{% load submit_tags %}
|
||||
|
||||
{% block title %}Adjust Meta-Data of Submitted {{ submission.name }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
{{ block.super }}
|
||||
table.metadata-table tr th { padding-right: 2em; }
|
||||
table.metadata-table #id_edit-title, table.metadata-table #id_edit-abstract, table.metadata-table #id_edit-note { width: 40em; }
|
||||
table.authors td { vertical-align: top; }
|
||||
table.authors tr.empty { display: none; }
|
||||
input.add-author { margin-left: 42em; }
|
||||
div.manual-posting { margin-top: 2em; }
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
<h2>Adjust Meta-Data of Submitted {{ submission.name }}</h2>
|
||||
|
||||
<div class="twopages-popup" style="display:none">
|
||||
<div class="content">
|
||||
<pre>{{ submission|two_pages_decorated_with_errors:errors }}</pre>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="" class="button close">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="metadata-table">
|
||||
<tr>
|
||||
<th>Document</th>
|
||||
<td>{{ submission.name }} <a class="twopages-trigger" href="">[View first two pages]</a>
|
||||
{% show_submission_files submission %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><th>Submission date</th><td>{{ submission.submission_date }}</td></tr>
|
||||
|
||||
<tr{% if errors.group %} class="error"{% endif %}>
|
||||
<th>Group</th>
|
||||
<td>{{ submission.group|default:"Individual Submission" }}
|
||||
{% if errors.group %}<div class="error-msg">{{ errors.group }} (note: the Secretariat will be notified of this)</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><th>File size</th><td>{{ submission.file_size|filesizeformat }}</td></tr>
|
||||
</table>
|
||||
|
||||
<h3>Adjust meta-data</h3>
|
||||
|
||||
{% if form_errors %}
|
||||
<div class="metadata-errors">
|
||||
Please fix the following errors.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
|
||||
<table class="metadata-table">
|
||||
{% for field in edit_form %}
|
||||
{% if field.name != "note" %}
|
||||
<tr{% if field.errors %} class="error"{% endif %}><th>{{ field.label_tag }}</th><td>{{ field }}{{ field.errors }}</td></tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% include "submit/submitter_form.html" %}
|
||||
|
||||
{% with edit_form.note as field %}
|
||||
<tr{% if field.errors %} class="error"{% endif %}><th>{{ field.label_tag }}</th><td>{{ field }}{{ field.errors }}</td></tr>
|
||||
{% endwith %}
|
||||
</table>
|
||||
|
||||
|
||||
<h3>Authors</h3>
|
||||
|
||||
<table class="authors metadata-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Email address</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="empty">
|
||||
<td>{{ empty_author_form.name }} <input type="hidden" name="authors-prefix" value="authors-" /></td>
|
||||
<td>{{ empty_author_form.email }}</td>
|
||||
</tr>
|
||||
{% for form in author_forms %}
|
||||
<tr class="{% if form.errors %} error{% endif %}">
|
||||
<td>{{ form.name }} {{ form.name.errors }} <input type="hidden" name="authors-prefix" value="{{ form.prefix }}" /></td>
|
||||
<td>{{ form.email }} {{ form.email.errors }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<input type="button" value="Add another author" class="add-author" />
|
||||
</div>
|
||||
|
||||
<div class="manual-posting">
|
||||
<input type="submit" value="Submit for manual posting" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% include "submit/problem-reports-footer.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ block.super }}
|
||||
<script type="text/javascript" src="/js/utils.js"></script>
|
||||
<script type="text/javascript" src="/js/draft-submit.js"></script>
|
||||
{% endblock %}
|
|
@ -2,7 +2,7 @@
|
|||
Hi,
|
||||
|
||||
The datatracker has received a request to send out the link to the URL where you
|
||||
can confirm the submission of your draft {{ submission.filename }}-{{ submission.revision }}.
|
||||
can confirm the submission of your draft {{ submission.name }}-{{ submission.rev }}.
|
||||
|
||||
Please follow this link to get full access to the submission page:
|
||||
{{ url|safe }}
|
|
@ -1,26 +0,0 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
|
||||
{% block title %}Confirm Auto-Post{% endblock %}
|
||||
|
||||
|
||||
{% block submit_content %}
|
||||
|
||||
<h2>Confirm auto-post</h2>
|
||||
<p>
|
||||
Authorization key accepted. Please press the button below to finish Auto-Post of <strong>{{ detail.filename }}-{{ detail.revision }}</strong>
|
||||
</p>
|
||||
<form action="" method="post">
|
||||
<input type="submit" value="Auto-Post" />
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
jQuery(function () {
|
||||
jQuery("form").submit(function() {
|
||||
if (this.submittedAlready)
|
||||
return false;
|
||||
else
|
||||
this.submittedAlready = true;
|
||||
});
|
||||
});
|
||||
{% endblock %}
|
|
@ -1,31 +0,0 @@
|
|||
{% autoescape off %}
|
||||
Hi,
|
||||
|
||||
Manual posting has been requested for the following Internet-Draft:
|
||||
|
||||
I-D Submission Tool URL:
|
||||
{{ url }}
|
||||
|
||||
File name : {{ draft.filename }}
|
||||
Version : {{ draft.revision }}
|
||||
Submission date : {{ draft.submission_date }}
|
||||
Group : {{ draft.group_acronym|default:"Individual Submission" }} {% if form.validation.warnings.group %}*Please note that this group is not an active one*{% endif %}
|
||||
|
||||
Title : {{ draft.id_document_name }}
|
||||
Document date : {{ draft.creation_date }}
|
||||
Pages : {{ draft.txt_page_count }}
|
||||
File size : {{ draft.filesize|filesizeformat }}
|
||||
|
||||
Submitter : {{ submitter.get_full_name }} <{{ submitter.email.1 }}>
|
||||
|
||||
Abstract : {{ draft.abstract }}
|
||||
|
||||
|
||||
Authors:
|
||||
{% for author in form.get_authors %} {{ author.get_full_name }} <{{ author.email.1 }}>
|
||||
{% endfor %}
|
||||
|
||||
Comments to the secretariat:
|
||||
|
||||
{{ draft.comment_to_sec }}
|
||||
{% endautoescape %}
|
31
ietf/templates/submit/manual_post_request.txt
Normal file
31
ietf/templates/submit/manual_post_request.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% autoescape off %}
|
||||
Hi,
|
||||
|
||||
Manual posting has been requested for the following Internet-Draft:
|
||||
|
||||
I-D Submission Tool URL:
|
||||
{{ url }}
|
||||
|
||||
File name : {{ submission.name }}
|
||||
Revision : {{ submission.rev }}
|
||||
Submission date : {{ submission.submission_date }}
|
||||
Group : {{ submission.group|default:"Individual Submission" }} {% if errors.group %}*Please note: {{ errors.group }}*{% endif %}
|
||||
|
||||
Title : {{ submission.title }}
|
||||
Document date : {{ submission.document_date }}
|
||||
Pages : {{ submission.pages }}
|
||||
File size : {{ submission.file_size|filesizeformat }}
|
||||
|
||||
Submitter : {{ submission.submitter }}
|
||||
|
||||
Abstract : {{ submission.abstract }}
|
||||
|
||||
|
||||
Authors:
|
||||
{% for author in submission.authors_parsed %} {{ author.name }}{% if author.email %} <{{ author.email }}>{% endif%}
|
||||
{% endfor %}
|
||||
|
||||
Comment to the secretariat:
|
||||
|
||||
{{ submission.note }}
|
||||
{% endautoescape %}
|
4
ietf/templates/submit/problem-reports-footer.html
Normal file
4
ietf/templates/submit/problem-reports-footer.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
<p class="problem-reports-footer">
|
||||
The IETF is an organized activity of the <a href="http://www.isoc.org">Internet Society</a><br>
|
||||
Please send problem reports to <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>.
|
||||
</p>
|
18
ietf/templates/submit/search_submission.html
Normal file
18
ietf/templates/submit/search_submission.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
|
||||
{% block title %}Submission status{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
|
||||
<p>Please enter the name of the Internet-Draft you wish to view
|
||||
submission status for:</p>
|
||||
|
||||
<form method="post">
|
||||
{% if error %}<div style="color: red;">{{ error }}</div>{% endif %}
|
||||
<input type="text" name="name" value="{{ name|default:"draft-" }}" />
|
||||
<input type="submit" value="See status" />
|
||||
</form>
|
||||
|
||||
{% include "submit/problem-reports-footer.html" %}
|
||||
|
||||
{% endblock %}
|
|
@ -1,33 +0,0 @@
|
|||
{% autoescape off %}
|
||||
Hi,
|
||||
|
||||
WG chair approval is needed for posting of {{ draft.filename }}-{{ draft.revision }}.
|
||||
|
||||
To approve the draft, go to this URL (note: you need to login to be able to approve):
|
||||
https://{{ domain }}/submit/status/{{ draft.submission_id }}/{{ draft.submission_hash }}/
|
||||
|
||||
File name : {{ draft.filename }}
|
||||
Version : {{ draft.revision }}
|
||||
Submission date : {{ draft.submission_date }}
|
||||
Group : {{ draft.group_acronym|default:"Individual Submission" }}
|
||||
|
||||
Title : {{ draft.id_document_name }}
|
||||
Document date : {{ draft.creation_date }}
|
||||
Pages : {{ draft.txt_page_count }}
|
||||
File size : {{ draft.filesize|filesizeformat }}
|
||||
|
||||
Submitter : {{ submitter.get_full_name }} <{{ submitter.email_address }}>
|
||||
|
||||
Abstract : {{ draft.abstract }}
|
||||
|
||||
|
||||
Authors:
|
||||
{% for author in authors %} {{ author.get_full_name }} <{{ author.email.1 }}>
|
||||
{% endfor %}
|
||||
{% endautoescape %}
|
||||
|
||||
|
||||
Best regards,
|
||||
|
||||
The IETF Secretariat
|
||||
through the draft submission service
|
275
ietf/templates/submit/submission_status.html
Normal file
275
ietf/templates/submit/submission_status.html
Normal file
|
@ -0,0 +1,275 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
|
||||
{% load ietf_filters submit_tags %}
|
||||
|
||||
{% block title %}Status of submission of {{ submission.name }}-{{ submission.rev }}{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
|
||||
{% if submission.state_id != "uploaded" %}
|
||||
<h2>Status of the submission: {{ submission.state.name }}</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if message %}
|
||||
<div class="info-message-{{ message.0 }}">{{ message.1 }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if submitter_form.errors %}
|
||||
<div class="info-message-error">Please fix errors in the form below</div>
|
||||
{% endif %}
|
||||
|
||||
<h2>IDNITS</h2>
|
||||
<p>
|
||||
{% if passes_idnits %}
|
||||
Your draft has been verified to meet IDNITS requirements.
|
||||
{% else %}
|
||||
Your draft has NOT been verified to meet IDNITS requirements.
|
||||
{% endif %}
|
||||
<a class="idnits-trigger" href="">(View IDNITS Results)</a>
|
||||
</p>
|
||||
|
||||
<div class="idnits-popup" style="display:none">
|
||||
<div class="content">
|
||||
<pre>{{ submission.idnits_message }}</pre>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="" class="button close">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="twopages-popup" style="display:none">
|
||||
<div class="content">
|
||||
<pre>{{ submission|two_pages_decorated_with_errors:errors }}</pre>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="" class="button close">Close</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h2>Meta-Data from the Submission</h2>
|
||||
|
||||
{% if errors %}
|
||||
<div class="metadata-errors">
|
||||
<h3>Meta-Data errors found</h3>
|
||||
<p>Please make sure that your Internet-Draft includes all of the required meta-data in the proper format.</p>
|
||||
|
||||
<p>If your Internet-Draft *does* include all of the required meta-data in the proper format, and if
|
||||
the error(s) identified above are due to the failure of the tool to extract the meta-data correctly,
|
||||
then please use the 'Adjust Meta-Data' button below, which will take you to the 'Adjust Screen' where
|
||||
you can correct the improperly extracted meta-data. You will then be able to submit your Internet-Draft
|
||||
to the Secretariat for manual posting.</p>
|
||||
|
||||
<p>If your Internet-Draft *does not* include all of the required meta-data in the proper format, then
|
||||
please cancel this submission, update your Internet-Draft, and resubmit it.</p>
|
||||
|
||||
<p><strong>NOTE:</strong> The Secretariat will NOT add any
|
||||
meta-data to your Internet-Draft or edit the meta-data. An
|
||||
Internet-Draft that does not include all of the required meta-data in
|
||||
the proper format WILL be returned to the submitter.</p>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<table class="metadata-table">
|
||||
<tr{% if errors.files %} class="error"{% endif %}>
|
||||
<th>Document</th>
|
||||
<td>
|
||||
{% if submission.state_id == "posted" %}<a href="http://www.ietf.org/id/{{ submission.name }}-{{submission.rev}}.txt">{{ submission.name }}</a>{% else %}{{ submission.name }}{% endif %}
|
||||
|
||||
<div><a class="twopages-trigger" href="">[View first two pages]</a></div>
|
||||
|
||||
{% show_submission_files submission %}
|
||||
|
||||
{% if errors.files %}<div class="error-msg">{{ errors.files|safe }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.rev %} class="error"{% endif %}>
|
||||
<th>Revision</th>
|
||||
<td>{{ submission.rev }}
|
||||
|
||||
{% if errors.rev %}
|
||||
<div class="error-msg">
|
||||
{{ errors.rev }}
|
||||
<br /><a class="twopages-trigger" href="">[View error]</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.group %} class="error"{% endif %}>
|
||||
<th>Group</th>
|
||||
<td>{{ submission.group|default:"Individual Submission" }}
|
||||
{% if errors.group %}<div class="error-msg">{{ errors.group }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.document_date %} class="error"{% endif %}>
|
||||
<th>Document date</th>
|
||||
<td>{{ submission.document_date }}
|
||||
{% if errors.document_date %}<div class="error-msg">{{ errors.document_date }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Submission date</th>
|
||||
<td>{{ submission.submission_date }}</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.title %} class="error"{% endif %}>
|
||||
<th>Title</th>
|
||||
<td>{{ submission.title|default:"" }}
|
||||
{% if errors.title %}<div class="error-msg">{{ errors.title }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.authors %} class="error"{% endif %}>
|
||||
<th>Authors</th>
|
||||
<td>{% with submission.authors_parsed as authors %}{{ authors|length }} author{{ authors|pluralize }}{% endwith %}
|
||||
{% if errors.authors %}<div class="error-msg">{{ errors.authors|safe }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% for author in submission.authors_parsed %}
|
||||
<tr{% if errors.authors %} class="error"{% endif %}>
|
||||
<th class="author">Author {{ forloop.counter }}</th>
|
||||
<td>{{ author.name }} {% if author.email %}<{{ author.email }}>{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<tr{% if errors.abstract %} class="error"{% endif %}>
|
||||
<th>Abstract</th>
|
||||
<td>{{ submission.abstract|linebreaksbr }}
|
||||
{% if errors.abstract %}<div class="error-msg">{{ errors.abstract }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr{% if errors.pages %} class="error"{% endif %}>
|
||||
<th>Pages</th>
|
||||
<td>{{ submission.pages }}
|
||||
{% if errors.pages %}<div class="error-msg">{{ errors.pages }}</div>{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>File size</th>
|
||||
<td>{{ submission.file_size|filesizeformat }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if can_edit %}
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="edit" />
|
||||
<input type="submit" value="Adjust Meta-Data" value="adjust" /> (Leads to manual post by the Secretariat)
|
||||
</form>
|
||||
|
||||
{% if passes_idnits and not errors %}
|
||||
<h2>Please edit the following meta-data before posting</h2>
|
||||
|
||||
<p></p>
|
||||
|
||||
<form method="post">
|
||||
<table class="metadata-table">
|
||||
{% include "submit/submitter_form.html" %}
|
||||
</table>
|
||||
|
||||
<input type="hidden" name="action" value="autopost" />
|
||||
<input type="submit" value="Post submission" />
|
||||
{% if requires_group_approval %}
|
||||
(Notifies group chairs to get approval)
|
||||
{% else %}
|
||||
{% if requires_prev_authors_approval %}
|
||||
(Notifies authors of previous revision of draft to get approval)
|
||||
{% else %}
|
||||
(Notifies submitter and authors for confirmation)
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
{% if submission.submitter %}
|
||||
<h3>Submitter information</h3>
|
||||
<table class="metadata-table">
|
||||
<tr><th>Name</th><td>{{ submission.submitter_parsed.name }}</td></tr>
|
||||
<tr><th>Email address</th><td>{{ submission.submitter_parsed.email }}</td></tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if can_cancel %}
|
||||
<h2>Cancel submission</h2>
|
||||
<p>
|
||||
Cancel submission and delete the uploaded file{{ submission.file_types|split:","|pluralize }} permanently:
|
||||
|
||||
<form id="cancel-submission" method="post">
|
||||
<input type="hidden" name="action" value="cancel" />
|
||||
<input type="submit" value="Cancel submission" />
|
||||
</form>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if can_group_approve %}
|
||||
<h2>Approve submission</h2>
|
||||
<p>
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="approve" />
|
||||
<input type="submit" value="Approve this submission" />
|
||||
</form>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if can_force_post %}
|
||||
<p>
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="forcepost" />
|
||||
<input type="submit" value="Force post of submission" />
|
||||
</form>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if show_send_full_url %}
|
||||
<div class="metadata-errors">
|
||||
<p>You are not allowed to modify or cancel this submission. You can
|
||||
only modify or cancel this submission from the same URL you were
|
||||
redirected to after the submission.</p>
|
||||
|
||||
<p>If you are the submitter check your browser history to find this
|
||||
URL. You can share it with any person you need.</p>
|
||||
|
||||
<p>If you are one of the authors you can request the URL from wich
|
||||
you can modify or cancel this submission by clicking the next
|
||||
button. An email will then be sent to the authors and submitter
|
||||
(if submitter email was entered): {{ confirmation_list|join:", " }}.</p>
|
||||
|
||||
<form method="post">
|
||||
<input type="hidden" name="action" value="sendfullurl" />
|
||||
<input type="submit" value="Request full access URL" />
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h2>History</h2>
|
||||
|
||||
<table class="ietf-table history">
|
||||
<tr><th>Date</th><th>By</th><th>Text</th></tr>
|
||||
|
||||
{% for e in submission.submissionevent_set.all %}
|
||||
<tr class="{% cycle oddrow,evenrow %}">
|
||||
<td>{{ e.time|date:"Y-m-d" }}</td>
|
||||
<td>{{ e.by|default:"" }}</td>
|
||||
<td>{{ e.desc }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% include "submit/problem-reports-footer.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script type="text/javascript" src="/js/utils.js"></script>
|
||||
<script type="text/javascript" src="/js/draft-submit.js"></script>
|
||||
{% endblock %}
|
|
@ -1,34 +1,22 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block morecss %}
|
||||
.ietf-navset {
|
||||
background:#214197 url(/images/yui/sprite.png) repeat-x left -1400px;
|
||||
color:white;
|
||||
border:1px solid black;
|
||||
padding:4px;
|
||||
}
|
||||
.ietf-navset .selected { font-weight:bold; padding: 0 3px; }
|
||||
.ietf-navset a, .ietf-navset a:visited { color: white; padding:0 3px; }
|
||||
.cutoff-warning { border: 1px dashed red; background-color: #ffeeaa; padding: 1em 2em; margin: 1em 0px; }
|
||||
{% block pagehead %}
|
||||
{{ block.super }}
|
||||
<link rel="stylesheet" type="text/css" href="/css/submit.css"></link>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<h1>IETF Internet-Draft Submission </h1>
|
||||
|
||||
<div class="ietf-navset">
|
||||
{% if selected == "index" %}<span class="selected">Upload</span>{% else %}<a href="{% url submit_index %}">Upload</a>{% endif %} |
|
||||
{% if selected == "status" %}<span class="selected">Status</span>{% else %}<a href="{% url submit_status %}">Status</a>{% endif %} |
|
||||
{% if selected == "index" %}<span class="selected">Upload</span>{% else %}<a href="{% url submit_upload_submission %}">Upload</a>{% endif %} |
|
||||
{% if selected == "status" %}<span class="selected">Status</span>{% else %}<a href="{% url submit_search_submission %}">Status</a>{% endif %} |
|
||||
{% if selected == "instructions" %}<span class="selected">Tool Instructions</span>{% else %}<a href="{% url submit_tool_instructions %}">Tool Instructions</a>{% endif %} |
|
||||
{% if selected == "notewell" %}<span class="selected">NOTE WELL</span>{% else %}<a href="{% url submit_note_well %}">NOTE WELL</a>{% endif %} |
|
||||
{% if selected == "approvals" %}<span class="selected">Approvals</span>{% else %}<a href="{% url submit_approvals %}">Approvals</a>{% endif %}
|
||||
</div>
|
||||
|
||||
{% if form.cutoff_warning %}
|
||||
<div class="cutoff-warning">
|
||||
{{ form.cutoff_warning|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block submit_content %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
{% block title %}Upload{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{{ form.media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
<p>This page is used to submit IETF Internet-Drafts to the Internet-Draft repository. The list of current Internet-Drafts can be accessed at <a href="http://www.ietf.org/ietf/1id-abstracts.txt">http://www.ietf.org/ietf/1id-abstracts.txt</a></p>
|
||||
<p>Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.</p>
|
||||
<p>Internet-Drafts are draft documents, and are valid for a maximum of six months. They may be updated, replaced, or obsoleted by other documents at any time.</p>
|
||||
{% if not form.shutdown %}
|
||||
<p>If you run into problems when submitting an Internet-Draft using this and the following pages, you may alternatively submit your draft by email to <a href="mailto:internet-drafts@ietf.org">internet-drafts@ietf.org</a>. However, be advised that manual processing always takes additional time.</p>
|
||||
|
||||
{{ form }}
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
The IETF is an organized activity of the <a href="http://www.isoc.org">Internet Society</a>
|
||||
<br>Please send problem reports to <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -1,27 +0,0 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
{% block title %}Submission status{% endblock %}
|
||||
|
||||
{% block pagehead %}
|
||||
{{ form.media }}
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
<p>
|
||||
Please enter the filename of the Internet-Draft you wish to view submission status for:
|
||||
</p>
|
||||
|
||||
<form method="post" action="">
|
||||
{% if error %}<div style="color: red;">{{ error }}</div>{% endif %}
|
||||
<input type="text" name="filename" value="{{ filename|default:"draft-" }}" />
|
||||
<input type="submit" value="Find status" />
|
||||
</form>
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Note that the status page only displays the status of an Internet-Draft with a posting still in progress or an Internet-Draft that has been successfully posted.</strong>
|
||||
</p>
|
||||
<p>
|
||||
The IETF is an organized activity of the <a href="http://www.isoc.org">Internet Society</a>
|
||||
<br>Please send problem reports to <a href="mailto:ietf-action@ietf.org">ietf-action@ietf.org</a>.
|
||||
</p>
|
||||
{% endblock %}
|
|
@ -1,53 +0,0 @@
|
|||
{% load i18n %}
|
||||
|
||||
<form class="submitform liaisonform" method="post" action="" enctype="multipart/form-data">
|
||||
|
||||
<div class="formconfig" style="display: none;">
|
||||
{% block formconfig %}
|
||||
<span class="info_update_url">{% url get_info %}</span>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="baseform{% if form.edit %} baseformedit{% endif %}">
|
||||
{% if form.errors %}
|
||||
<div class="formErrors">
|
||||
Please correct the errors below.
|
||||
</div>
|
||||
{{ form.non_field_errors }}
|
||||
{% endif %}
|
||||
{% for fieldset in form.get_fieldsets %}
|
||||
{% if fieldset.name %}
|
||||
<div class="fieldset">
|
||||
<h2>{{ fieldset.name }}</h2>
|
||||
{% endif %}
|
||||
|
||||
{% for field in fieldset.fields %}
|
||||
<div id="baseform-fieldname-{{ field.html_name }}"
|
||||
class="{% if field.errors %}fieldError {% endif %}field BaseFormStringWidget{% if field.field.column_style %} {{ field.field.column_style }}{% endif %}">
|
||||
<label for="id_{{ field.html_name }}">{{ field.label }}
|
||||
{% if field.field.required %}
|
||||
<span class="fieldRequired" title="Required">*</span>
|
||||
{% endif %}
|
||||
</label>
|
||||
<div class="fieldWidget">
|
||||
<div id="{{ field.html_name }}_help" class="formHelp"> {{ field.help_text }}</div>
|
||||
{{ field }}
|
||||
{{ field.errors }}
|
||||
</div>
|
||||
<div class="endfield"></div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if fieldset.name %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if not form.shutdown %}
|
||||
<div class="submitrow">
|
||||
<input type="submit" value="Upload" name="upload" />
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</form>
|
17
ietf/templates/submit/submitter_form.html
Normal file
17
ietf/templates/submit/submitter_form.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<tr>
|
||||
<th>Submitter</th>
|
||||
<td class="author-button-help">
|
||||
If you are one of the authors, please click the button below
|
||||
with your name on it to automatically fill in the
|
||||
submitter information. Otherwise,
|
||||
please manually enter your name and email address.<br /><br />
|
||||
|
||||
{% for author in submission.authors_parsed %}
|
||||
<input type="button" class="author" data-name="{{ author.name }}" data-email="{{ author.email }}" value="{{ author.name }}" />
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{% for field in submitter_form %}
|
||||
<tr{% if field.errors %} class="error"{% endif %}><th>{{ field.label_tag }}</th><td>{{ field }}{{ field.errors }}</td></tr>
|
||||
{% endfor %}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block submit_content %}
|
||||
<h2>I-D Submission Tool Instructions</h2>
|
||||
<h3>Tool URL: <a href="{% url submit_index %}">http://datatracker.ietf.org/{% url submit_index %}</a></h3>
|
||||
<h3>Tool URL: <a href="{% url submit_upload_submission %}">https://datatracker.ietf.org{% url submit_upload_submission %}</a></h3>
|
||||
This page will explain the purpose and content of each screen in the I-D Submission Tool, and the actions that result by clicking the form buttons on each screen.<br>
|
||||
|
||||
The specification for this tool can be found in <a href="http://www.ietf.org/rfc/rfc4228.txt?number=4228">RFC 4228</a>.
|
||||
|
@ -98,7 +98,7 @@ This is the screen where a user can adjust any meta-data that could have been in
|
|||
|
||||
<b>Status Screen</b>
|
||||
<p>
|
||||
The Status screen is the screen where a user can view the current status of a document that has just been submitted by the user, or a document that was submitted previously via the tool. If a link 'Status' is clicked from the tool's first page, then a form field will be provided for a user to look up a document by filename.
|
||||
The Status screen is the screen where a user can view the current status of a document that has just been submitted by the user, or a document that was submitted previously via the tool. If a link 'Status' is clicked from the tool's first page, then a form field will be provided for a user to look up a document by name.
|
||||
</p>
|
||||
<u>Form buttons and resulting actions:</u><br>
|
||||
<table border="0">
|
||||
|
|
63
ietf/templates/submit/upload_submission.html
Normal file
63
ietf/templates/submit/upload_submission.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
{% extends "submit/submit_base.html" %}
|
||||
{% block title %}Upload{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
{{ block.super }}
|
||||
form.upload-form h3 { margin: 0; color: #fff; background-color: #2647a0; padding: 0.3em 0.8em; }
|
||||
form.upload-form table { padding: 0.3em 0.8em; }
|
||||
form.upload-form .required { color: #f00; }
|
||||
form.upload-form td { padding-right: 5em; padding-top: 0.4em; padding-bottom: 0.4em; }
|
||||
form.upload-form .ietf-box { margin-bottom: 1em; }
|
||||
{% endblock %}
|
||||
|
||||
{% block submit_content %}
|
||||
{% if form.cutoff_warning %}
|
||||
<div class="cutoff-warning">
|
||||
{{ form.cutoff_warning|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p>This page is used to submit IETF Internet-Drafts to the
|
||||
Internet-Draft repository. The list of current Internet-Drafts can be
|
||||
accessed at<a href="http://www.ietf.org/ietf/1id-abstracts.txt">http://www.ietf.org/ietf/1id-abstracts.txt</a></p>
|
||||
|
||||
<p>Internet-Drafts are working documents of the Internet Engineering
|
||||
Task Force (IETF), its areas, and its working groups. Note that other
|
||||
groups may also distribute working documents as Internet-Drafts.</p>
|
||||
|
||||
<p>Internet-Drafts are draft documents, and are valid for a maximum of
|
||||
six months. They may be updated, replaced, or obsoleted by other
|
||||
documents at any time.</p>
|
||||
|
||||
{% if not form.shutdown %}
|
||||
<p>If you run into problems when submitting an Internet-Draft
|
||||
using this and the following pages, you may alternatively submit
|
||||
your draft by email to
|
||||
<a href="mailto:internet-drafts@ietf.org">internet-drafts@ietf.org</a>.
|
||||
However, be advised that manual processing always takes additional time.</p>
|
||||
|
||||
<form class="upload-form" method="post" enctype="multipart/form-data">
|
||||
<div class="ietf-box">
|
||||
<h3>Upload a draft</h3>
|
||||
|
||||
{{ form.non_field_errors }}
|
||||
|
||||
<table>
|
||||
{% for field in form %}
|
||||
<tr>
|
||||
<td>{{ field.label_tag }} {% if field.field.required %}<span class="required">*</span>{% endif %}</td>
|
||||
<td>{{ field }} {{ field.errors }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="upload-submit">
|
||||
<input type="submit" value="Upload" name="upload" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% include "submit/problem-reports-footer.html" %}
|
||||
|
||||
{% endblock %}
|
31
static/css/submit.css
Normal file
31
static/css/submit.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
.ietf-navset {
|
||||
background:#214197 url(/images/yui/sprite.png) repeat-x left -1400px;
|
||||
color:white;
|
||||
border:1px solid black;
|
||||
padding:4px;
|
||||
}
|
||||
.ietf-navset .selected { font-weight:bold; padding: 0 3px; }
|
||||
.ietf-navset a, .ietf-navset a:visited { color: white; padding:0 3px; }
|
||||
.cutoff-warning { border: 1px dashed red; background-color: #ffeeaa; padding: 1em 2em; margin: 1em 0px; }
|
||||
.problem-reports-footer { font-style: italic; margin-top: 2em; }
|
||||
|
||||
div.metadata-errors { border: 1px solid red; background-color: #ffeebb; padding: 5px 10px; margin: 1em 0px; max-width: 50em; }
|
||||
div.info-message-error { border: 1px solid red; background-color: #ffeebb; padding: 5px 10px; margin: 1em 0px; color: red; }
|
||||
div.info-message-success { border: 1px solid green; background-color: #eeffbb; padding: 5px 10px; margin: 1em 0px; color: green; }
|
||||
|
||||
table.metadata-table th { white-space: nowrap; font-weight: bold; }
|
||||
table.metadata-table th, table.metadata-table td { text-align: left; background: #ddddff; padding: 5px 10px; }
|
||||
table.metadata-table th.author { text-align: right; }
|
||||
table.metadata-table tr { vertical-align: top; }
|
||||
table.metadata-table tr.error td, table.metadata-table tr.error th { background-color: #ffaaaa; }
|
||||
table.metadata-table div.error-msg { color: red; }
|
||||
table.metadata-table td.author-button-help { max-width: 40em; }
|
||||
table.metadata-table input.name, table.metadata-table input.email { width: 25em; }
|
||||
|
||||
pre.twopages { margin: 0px; }
|
||||
|
||||
.idnits-popup .content,
|
||||
.twopages-popup .content { background-color: #fff; width: 55em; height: 30em; overflow: auto; padding: 1em; }
|
||||
a.idnits-trigger, a.twopages-trigger, a.idnits-trigger:visited, a.twopages-trigger:visited { color: #000; }
|
||||
|
||||
table.history { max-width: 50em; }
|
|
@ -1,12 +1,60 @@
|
|||
$(function (){
|
||||
jQuery(function (){
|
||||
// fill in submitter info when an author button is clicked
|
||||
$("input[type=button]").click(function () {
|
||||
var name = $(this).data("name");
|
||||
if (name == null) // backwards compatibility
|
||||
return;
|
||||
var email = $(this).data("email");
|
||||
jQuery("input[type=button].author").click(function () {
|
||||
var name = jQuery(this).data("name");
|
||||
var email = jQuery(this).data("email");
|
||||
|
||||
$(this).parents("form").find("input[name=name]").val(name || "");
|
||||
$(this).parents("form").find("input[name=email]").val(email || "");
|
||||
jQuery(this).parents("form").find("input[name=submitter-name]").val(name || "");
|
||||
jQuery(this).parents("form").find("input[name=submitter-email]").val(email || "");
|
||||
});
|
||||
|
||||
jQuery("form").submit(function() {
|
||||
if (this.submittedAlready)
|
||||
return false;
|
||||
else {
|
||||
this.submittedAlready = true;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
jQuery("form#cancel-submission").submit(function () {
|
||||
return confirm("Cancel this submission?");
|
||||
});
|
||||
|
||||
jQuery(".idnits-trigger").click(function (e) {
|
||||
e.preventDefault();
|
||||
var popup = jQuery(".idnits-popup").clone().show();
|
||||
showModalBox(popup);
|
||||
});
|
||||
|
||||
jQuery(".twopages-trigger").click(function (e) {
|
||||
e.preventDefault();
|
||||
var popup = jQuery(".twopages-popup").clone().show();
|
||||
showModalBox(popup);
|
||||
});
|
||||
|
||||
jQuery("form .add-author").click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var table = jQuery("table.authors tbody");
|
||||
var row = table.find("tr.empty").clone();
|
||||
|
||||
row.removeClass("empty");
|
||||
var prefixInput = row.find('input[name=authors-prefix]');
|
||||
|
||||
// figure out a prefix
|
||||
var i = 0, prefix;
|
||||
do {
|
||||
++i;
|
||||
prefix = prefixInput.val() + i;
|
||||
}
|
||||
while (table.find('input[name=authors-prefix][value="' + prefix +'"]').length > 0);
|
||||
|
||||
prefixInput.val(prefix);
|
||||
row.find('input').not(prefixInput).each(function () {
|
||||
this.name = prefix + "-" + this.name;
|
||||
});
|
||||
|
||||
table.append(row);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue