Added editing last call messages, requesting, issuing and tracking IETF LCs to status-change documents

Added a Cancel button to the form that allows editing the relations for status-change documents
Added instructions to the agenda section 3.3

This adds states to status-change- documents and has a migration that must be applied.

This fixes bug #1039
 - Legacy-Id: 5770
This commit is contained in:
Robert Sparks 2013-06-01 21:01:45 +00:00
parent 5bee7ac538
commit a741642717
15 changed files with 846 additions and 55 deletions

View file

@ -0,0 +1,477 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
from ietf.doc.models import State,StateType
class Migration(DataMigration):
def forwards(self, orm):
statchg = StateType.objects.get(slug='statchg')
lc_req = State(
type=statchg,slug="lc-req",
name="Last Call Requested",used=True,order=3,
desc="Last Call has been requested for this proposed status change")
lc_req.save()
in_lc = State(
type=statchg,slug="in-lc",
name="In Last Call",used=True,order=4,
desc="This proposed status change is in IETF Last Call")
in_lc.save()
goahead = State(
type=statchg,slug="goahead",
name="Waiting for AD Go-Ahead",used=True,order=5,
desc="The AD is following up on IETF LC comments")
goahead.save()
adrev=State.objects.get(type=statchg,slug='adrev')
iesgeval=State.objects.get(type=statchg,slug='iesgeval')
defer=State.objects.get(type=statchg,slug='defer')
appr_pr=State.objects.get(type=statchg,slug='appr-pr')
appr_pend=State.objects.get(type=statchg,slug='appr-pend')
appr_sent=State.objects.get(type=statchg,slug='appr-sent')
withdraw=State.objects.get(type=statchg,slug='withdraw')
dead=State.objects.get(type=statchg,slug='dead')
adrev.next_states.add(lc_req)
adrev.save()
lc_req.next_states.add(in_lc)
lc_req.save()
in_lc.next_states.add(goahead)
in_lc.save()
goahead.next_states.add(iesgeval,dead)
goahead.save()
iesgeval.order=6
iesgeval.save()
defer.order=7
defer.save()
appr_pr.next_states.add(appr_pend,appr_sent)
appr_pr.order=8
appr_pr.save()
appr_pend.order=9
appr_pend.save()
appr_sent.order=10
appr_sent.save()
withdraw.delete()
dead.order=11
dead.save()
def backwards(self, orm):
statchg = StateType.objects.get(slug='statchg')
State.objects.filter(type='statchg',slug__in=['lc-req','in-lc','goahead']).delete()
needshep=State.objects.get(type=statchg,slug='needshep')
adrev=State.objects.get(type=statchg,slug='adrev')
iesgeval=State.objects.get(type=statchg,slug='iesgeval')
defer=State.objects.get(type=statchg,slug='defer')
appr_pr=State.objects.get(type=statchg,slug='appr-pr')
appr_pend=State.objects.get(type=statchg,slug='appr-pend')
appr_sent=State.objects.get(type=statchg,slug='appr-sent')
dead=State.objects.get(type=statchg,slug='dead')
withdraw = State(
type=statchg,slug="withdraw",
name="Withdrawn",used=True,order=8,
desc="The request for RFC status changes was withdrawn")
withdraw.save()
needshep.next_states.add(withdraw)
needshep.save()
adrev.next_states.add(withdraw)
adrev.save()
withdraw.next_states.add(needshep)
withdraw.save()
iesgeval.order=3
iesgeval.next_states.add(withdraw)
iesgeval.save()
defer.order=4
defer.next_states.add(withdraw)
defer.save()
appr_pr.next_states.remove(appr_pend,appr_sent)
appr_pr.order=5
appr_pr.save()
appr_pend.order=6
appr_pend.next_states.add(withdraw)
appr_pend.save()
appr_sent.order=7
appr_sent.save()
dead.order=9
dead.save()
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'doc.ballotdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotDocEvent', '_ormbases': ['doc.DocEvent']},
'ballot_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.BallotType']"}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.ballotpositiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'BallotPositionDocEvent', '_ormbases': ['doc.DocEvent']},
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'ballot': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['doc.BallotDocEvent']", 'null': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'comment_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'discuss': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'discuss_time': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'pos': ('django.db.models.fields.related.ForeignKey', [], {'default': "'norecord'", 'to': "orm['name.BallotPositionName']"})
},
'doc.ballottype': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotType'},
'doc_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'positions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.BallotPositionName']", 'symmetrical': 'False', 'blank': 'True'}),
'question': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.consensusdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'ConsensusDocEvent', '_ormbases': ['doc.DocEvent']},
'consensus': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'})
},
'doc.deletedevent': {
'Meta': {'object_name': 'DeletedEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'json': ('django.db.models.fields.TextField', [], {}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'})
},
'doc.docalias': {
'Meta': {'object_name': 'DocAlias'},
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
},
'doc.docevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'DocEvent'},
'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']"}),
'desc': ('django.db.models.fields.TextField', [], {}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'doc.dochistory': {
'Meta': {'object_name': 'DocHistory'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocHistoryAuthor']", 'blank': 'True'}),
'doc': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'history_set'", 'to': "orm['doc.Document']"}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.DocAlias']", 'symmetrical': 'False', 'through': "orm['doc.RelatedDocHistory']", 'blank': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_dochistory_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.dochistoryauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocHistoryAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {})
},
'doc.docreminder': {
'Meta': {'object_name': 'DocReminder'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'due': ('django.db.models.fields.DateTimeField', [], {}),
'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocEvent']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocReminderTypeName']"})
},
'doc.document': {
'Meta': {'object_name': 'Document'},
'abstract': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'ad_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'authors': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['person.Email']", 'symmetrical': 'False', 'through': "orm['doc.DocumentAuthor']", 'blank': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'external_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'intended_std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.IntendedStdLevelName']", 'null': 'True', 'blank': 'True'}),
'internal_comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
'note': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'notify': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1', 'blank': 'True'}),
'pages': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
'related': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'reversely_related_document_set'", 'blank': 'True', 'through': "orm['doc.RelatedDocument']", 'to': "orm['doc.DocAlias']"}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16', 'blank': 'True'}),
'shepherd': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'shepherd_document_set'", 'null': 'True', 'to': "orm['person.Person']"}),
'states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'std_level': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StdLevelName']", 'null': 'True', 'blank': 'True'}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.StreamName']", 'null': 'True', 'blank': 'True'}),
'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['name.DocTagName']", 'null': 'True', 'blank': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocTypeName']", 'null': 'True', 'blank': 'True'})
},
'doc.documentauthor': {
'Meta': {'ordering': "['document', 'order']", 'object_name': 'DocumentAuthor'},
'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Email']"}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '1'})
},
'doc.initialreviewdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'InitialReviewDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.lastcalldocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'LastCallDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'expires': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'})
},
'doc.newrevisiondocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'NewRevisionDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'rev': ('django.db.models.fields.CharField', [], {'max_length': '16'})
},
'doc.relateddochistory': {
'Meta': {'object_name': 'RelatedDocHistory'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocHistory']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'reversely_related_document_history_set'", 'to': "orm['doc.DocAlias']"})
},
'doc.relateddocument': {
'Meta': {'object_name': 'RelatedDocument'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'relationship': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.DocRelationshipName']"}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.Document']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.DocAlias']"})
},
'doc.state': {
'Meta': {'ordering': "['type', 'order']", 'object_name': 'State'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': "orm['doc.State']"}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'doc.statedocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'StateDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.State']", 'null': 'True', 'blank': 'True'}),
'state_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['doc.StateType']"})
},
'doc.statetype': {
'Meta': {'object_name': 'StateType'},
'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '30', 'primary_key': 'True'})
},
'doc.telechatdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'TelechatDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'returning_item': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'telechat_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'})
},
'doc.writeupdocevent': {
'Meta': {'ordering': "['-time', '-id']", 'object_name': 'WriteupDocEvent', '_ormbases': ['doc.DocEvent']},
'docevent_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['doc.DocEvent']", 'unique': 'True', 'primary_key': 'True'}),
'text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'group.group': {
'Meta': {'object_name': 'Group'},
'acronym': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
'ad': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True', 'blank': 'True'}),
'charter': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'chartered_group'", 'unique': 'True', 'null': 'True', 'to': "orm['doc.Document']"}),
'comments': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'list_archive': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'list_email': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'list_subscribe': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['group.Group']", 'null': 'True', 'blank': 'True'}),
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupStateName']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['name.GroupTypeName']", 'null': 'True'}),
'unused_states': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['doc.State']", 'symmetrical': 'False', 'blank': 'True'}),
'unused_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['name.DocTagName']", 'symmetrical': 'False', 'blank': 'True'})
},
'name.ballotpositionname': {
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.docrelationshipname': {
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'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.groupstatename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.grouptypename': {
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.intendedstdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.stdlevelname': {
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'name.streamname': {
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
'person.email': {
'Meta': {'object_name': 'Email'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'address': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'}),
'person': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['person.Person']", 'null': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'})
},
'person.person': {
'Meta': {'object_name': 'Person'},
'address': ('django.db.models.fields.TextField', [], {'max_length': '255', 'blank': 'True'}),
'affiliation': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'ascii': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'ascii_short': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'time': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True', 'null': 'True', 'blank': 'True'})
}
}
complete_apps = ['doc']

View file

@ -16,7 +16,7 @@ from ietf.utils.mail import outbox
from ietf.doc.utils import create_ballot_if_not_open
from ietf.doc.views_status_change import default_approval_text
from ietf.doc.models import Document,DocEvent,NewRevisionDocEvent,BallotPositionDocEvent,TelechatDocEvent,DocAlias,State
from ietf.doc.models import Document,DocEvent,NewRevisionDocEvent,BallotPositionDocEvent,TelechatDocEvent,WriteupDocEvent,DocAlias,State
from ietf.name.models import StreamName
from ietf.group.models import Person
from ietf.iesg.models import TelechatDate
@ -202,6 +202,51 @@ class StatusChangeTestCase(django.test.TestCase):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
self.assertEquals(doc.latest_event(TelechatDocEvent, "scheduled_for_telechat").telechat_date,None)
def test_edit_lc(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('status_change_last_call',kwargs=dict(name=doc.name))
login_testing_unauthorized(self, "ad", url)
# additional setup
doc.relateddocument_set.create(target=DocAlias.objects.get(name='rfc9999'),relationship_id='tois')
doc.relateddocument_set.create(target=DocAlias.objects.get(name='rfc9998'),relationship_id='tohist')
doc.ad = Person.objects.get(name='Ad No2')
doc.save()
# get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertEquals(len(q('form.edit-last-call-text')),1)
self.assertTrue( 'RFC9999 from Proposed Standard to Internet Standard' in ''.join(wrap(r.content,2**16)))
self.assertTrue( 'RFC9998 from Informational to Historic' in ''.join(wrap(r.content,2**16)))
# save
r = self.client.post(url,dict(last_call_text="Bogus last call text",save_last_call_text="1"))
self.assertEquals(r.status_code, 200)
last_call_event = doc.latest_event(WriteupDocEvent, type="changed_last_call_text")
self.assertEquals(last_call_event.text,"Bogus last call text")
# reset
r = self.client.post(url,dict(regenerate_last_call_text="1"))
self.assertEquals(r.status_code,200)
self.assertTrue( 'RFC9999 from Proposed Standard to Internet Standard' in ''.join(wrap(r.content,2**16)))
self.assertTrue( 'RFC9998 from Informational to Historic' in ''.join(wrap(r.content,2**16)))
# request last call
messages_before = len(outbox)
r = self.client.post(url,dict(last_call_text='stuff',send_last_call_request='Save+and+Request+Last+Call'))
self.assertEquals(r.status_code,200)
self.assertTrue( 'Last Call Requested' in ''.join(wrap(r.content,2**16)))
self.assertEquals(len(outbox), messages_before + 1)
self.assertTrue('iesg-secretary' in outbox[-1]['To'])
self.assertTrue('Last Call:' in outbox[-1]['Subject'])
self.assertTrue('Last Call Request has been submitted' in ''.join(wrap(unicode(outbox[-1]),2**16)))
def test_approve(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('status_change_approve',kwargs=dict(name=doc.name))
@ -263,21 +308,24 @@ class StatusChangeTestCase(django.test.TestCase):
# Try to add a relation to an RFC that doesn't exist
r = self.client.post(url,dict(new_relation_row_blah="rfc9997",
statchg_relation_row_blah="tois"))
statchg_relation_row_blah="tois",
Submit="Submit"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
# Try to add a relation leaving the relation type blank
r = self.client.post(url,dict(new_relation_row_blah="rfc9999",
statchg_relation_row_blah=""))
statchg_relation_row_blah="",
Submit="Submit"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
# Try to add a relation with an unknown relationship type
r = self.client.post(url,dict(new_relation_row_blah="rfc9999",
statchg_relation_row_blah="badslug"))
statchg_relation_row_blah="badslug",
Submit="Submit"))
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form ul.errorlist')) > 0)
@ -286,7 +334,8 @@ class StatusChangeTestCase(django.test.TestCase):
r = self.client.post(url,dict(new_relation_row_blah="rfc9999",
statchg_relation_row_blah="toexp",
new_relation_row_foo="rfc9998",
statchg_relation_row_foo="tobcp"))
statchg_relation_row_foo="tobcp",
Submit="Submit"))
self.assertEquals(r.status_code, 302)
doc = Document.objects.get(name='status-change-imaginary-mid-review')
self.assertEquals(doc.relateddocument_set.count(),2)

View file

@ -8,5 +8,6 @@ urlpatterns = patterns('ietf.doc.views_status_change',
url(r'^approve/$', "approve", name='status_change_approve'),
url(r'^telechat/$', "telechat_date", name='status_change_telechat_date'),
url(r'^relations/$', "edit_relations", name='status_change_relations'),
url(r'^last-call/$', "last_call", name='status_change_last_call'),
)

View file

@ -25,6 +25,9 @@ from ietf.name.models import DocRelationshipName, StdLevelName
from ietf.doc.forms import TelechatForm, AdForm, NotifyForm
from ietf.idrfc.views_ballot import LastCallTextForm
from ietf.idrfc.lastcall import request_last_call
class ChangeStateForm(forms.Form):
new_state = forms.ModelChoiceField(State.objects.filter(type="statchg", used=True), label="Status Change Evaluation State", empty_label=None, required=True)
comment = forms.CharField(widget=forms.Textarea, help_text="Optional comment for the review history", required=False)
@ -588,8 +591,8 @@ def edit_relations(request, name):
if request.method == 'POST':
form = EditStatusChangeForm(request.POST)
if form.is_valid():
if 'Submit' in request.POST and form.is_valid():
old_relations={}
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
old_relations[rel.target.document.canonical_name()]=rel.relationship.slug
@ -605,13 +608,14 @@ def edit_relations(request, name):
c.desc += "\nNEW:"
for relname,relslug in (set(new_relations.items())-set(old_relations.items())):
c.desc += "\n "+relname+": "+DocRelationshipName.objects.get(slug=relslug).name
#for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
# c.desc +="\n"+rel.relationship.name+": "+rel.target.document.canonical_name()
c.desc += "\n"
c.save()
return HttpResponseRedirect(status_change.get_absolute_url())
elif 'Cancel' in request.POST:
return HttpResponseRedirect(status_change.get_absolute_url())
else:
relations={}
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
@ -627,3 +631,93 @@ def edit_relations(request, name):
'relation_slugs': relation_slugs,
},
context_instance = RequestContext(request))
def generate_last_call_text(request, doc):
# requester should be set based on doc.group once the group for a status change can be set to something other than the IESG
# and when groups are set, vary the expiration time accordingly
requester = "an individual participant"
expiration_date = datetime.date.today() + datetime.timedelta(days=28)
cc = []
new_text = render_to_string("doc/status_change/last_call_announcement.txt",
dict(doc=doc,
settings=settings,
requester=requester,
expiration_date=expiration_date.strftime("%Y-%m-%d"),
changes=['%s from %s to %s'%(rel.target.name.upper(),rel.target.document.std_level.name,newstatus(rel)) for rel in doc.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS)],
urls=[rel.target.document.get_absolute_url() for rel in doc.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS)],
cc=cc
)
)
e = WriteupDocEvent()
e.type = 'changed_last_call_text'
e.by = request.user.get_profile()
e.doc = doc
e.desc = 'Last call announcement was generated'
e.text = unicode(new_text)
e.save()
return e
@role_required("Area Director", "Secretariat")
def last_call(request, name):
"""Edit the Last Call Text for this status change and possibly request IETF LC"""
status_change = get_object_or_404(Document, type="statchg", name=name)
login = request.user.get_profile()
last_call_event = status_change.latest_event(WriteupDocEvent, type="changed_last_call_text")
if not last_call_event:
last_call_event = generate_last_call_text(request, status_change)
form = LastCallTextForm(initial=dict(last_call_text=last_call_event.text))
if request.method == 'POST':
if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST:
form = LastCallTextForm(request.POST)
if form.is_valid():
t = form.cleaned_data['last_call_text']
if t != last_call_event.text:
e = WriteupDocEvent(doc=status_change, by=login)
e.by = login
e.type = "changed_last_call_text"
e.desc = "Last call announcement was changed"
e.text = t
e.save()
if "send_last_call_request" in request.POST:
save_document_in_history(status_change)
old_description = status_change.friendly_state()
status_change.set_state(State.objects.get(type='statchg', slug='lc-req'))
new_description = status_change.friendly_state()
e = log_state_changed(request, status_change, login, new_description, old_description)
status_change.time = e.time
status_change.save()
request_last_call(request, status_change)
return render_to_response('idrfc/last_call_requested.html',
dict(doc=status_change,
url = status_change.get_absolute_url(),
),
context_instance=RequestContext(request))
if "regenerate_last_call_text" in request.POST:
e = generate_last_call_text(request,status_change)
form = LastCallTextForm(initial=dict(last_call_text=e.text))
return render_to_response('doc/status_change/last_call.html',
dict(doc=status_change,
back_url = status_change.get_absolute_url(),
last_call_event = last_call_event,
last_call_form = form,
),
context_instance = RequestContext(request))

View file

@ -1094,13 +1094,15 @@ class MakeLastCallForm(forms.Form):
def make_last_call(request, name):
"""Make last call for Internet Draft, sending out announcement."""
doc = get_object_or_404(Document, docalias__name=name)
if not doc.get_state("draft-iesg"):
if not (doc.get_state("draft-iesg") or doc.get_state("statchg")):
raise Http404
login = request.user.get_profile()
e = doc.latest_event(WriteupDocEvent, type="changed_last_call_text")
if not e:
if doc.type.slug != 'draft':
raise Http404
e = generate_last_call_announcement(request, doc)
announcement = e.text
@ -1108,8 +1110,9 @@ def make_last_call(request, name):
form = MakeLastCallForm(request.POST)
if form.is_valid():
send_mail_preformatted(request, announcement)
send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
override={ "To": "IANA <drafts-lastcall@icann.org>", "CC": None, "Bcc": None, "Reply-To": None})
if doc.type.slug == 'draft':
send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
override={ "To": "IANA <drafts-lastcall@icann.org>", "CC": None, "Bcc": None, "Reply-To": None})
msg = infer_message(announcement)
msg.by = login
@ -1118,20 +1121,29 @@ def make_last_call(request, name):
save_document_in_history(doc)
prev = doc.get_state("draft-iesg")
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='lc'))
if doc.type.slug == 'draft':
prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
prev = doc.get_state("draft-iesg")
doc.set_state(State.objects.get(used=True, type="draft-iesg", slug='lc'))
e = idrfcutil_log_state_changed(request, doc, login, prev, prev_tag)
prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty'))
prev_tag = prev_tag[0] if prev_tag else None
if prev_tag:
doc.tags.remove(prev_tag)
e = idrfcutil_log_state_changed(request, doc, login, prev, prev_tag)
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, doc.get_state("draft-iesg").name)
elif doc.type.slug == 'statchg':
prev = doc.friendly_state()
doc.set_state(State.objects.get(used=True, type="statchg", slug='in-lc'))
e = docutil_log_state_changed(request, doc, login, doc.friendly_state(), prev)
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, doc.friendly_state())
doc.time = e.time
doc.save()
change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, doc.get_state("draft-iesg").name)
email_state_changed(request, doc, change_description)
email_owner(request, doc, doc.ad, login, change_description)
@ -1146,25 +1158,34 @@ def make_last_call(request, name):
e.save()
# update IANA Review state
prev_state = doc.get_state("draft-iana-review")
if not prev_state:
next_state = State.objects.get(used=True, type="draft-iana-review", slug="need-rev")
doc.set_state(next_state)
add_state_change_event(doc, login, prev_state, next_state)
if doc.type.slug == 'draft':
prev_state = doc.get_state("draft-iana-review")
if not prev_state:
next_state = State.objects.get(used=True, type="draft-iana-review", slug="need-rev")
doc.set_state(next_state)
add_state_change_event(doc, login, prev_state, next_state)
return HttpResponseRedirect(doc.get_absolute_url())
else:
initial = {}
initial["last_call_sent_date"] = date.today()
expire_days = 14
if doc.group.type_id in ("individ", "area"):
expire_days = 28
if doc.type.slug == 'draft':
# This logic is repeated in the code that edits last call text - why?
expire_days = 14
if doc.group.type_id in ("individ", "area"):
expire_days = 28
templ = 'idrfc/make_last_callREDESIGN.html'
else:
expire_days=28
templ = 'doc/status_change/make_last_call.html'
initial["last_call_expiration_date"] = date.today() + timedelta(days=expire_days)
form = MakeLastCallForm(initial=initial)
return render_to_response('idrfc/make_last_callREDESIGN.html',
return render_to_response(templ,
dict(doc=doc,
form=form),
form=form,
announcement=announcement,
),
context_instance=RequestContext(request))

View file

@ -640,6 +640,10 @@ def ad_dashboard_sort_key(doc):
elif doc.get_state_slug('charter') == 'iesgrev':
state = State.objects.get(type__slug='draft-iesg',slug='iesg-eva')
return "1%d%s" % (state.order,seed)
if doc.type.slug=='statchg' and doc.get_state_slug('statchg') == 'adrev':
state = State.objects.get(type__slug='draft-iesg',slug='ad-eval')
return "1%d%s" % (state.order,seed)
if seed.startswith('Needs Shepherd'):
return "100%s" % seed
@ -664,6 +668,7 @@ def ad_dashboard_sort_key(doc):
def by_ad2(request, name):
responsible = Document.objects.values_list('ad', flat=True).distinct()
ad_id = None
for p in Person.objects.filter(Q(role__name__in=("pre-ad", "ad"),
role__group__type="area",
role__group__state="active")
@ -672,6 +677,10 @@ def by_ad2(request, name):
ad_id = p.id
ad_name = p.plain_name()
break
if not ad_id:
raise Http404
docqueryset = Document.objects.filter(ad__id=ad_id)
docs=[]
for doc in docqueryset:

View file

@ -2053,7 +2053,7 @@
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">An RFC status change has been requested, but a shepherding AD has not yet been assigned</field>
<field type="IntegerField" name="order">1</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="122"></object><object pk="128"></object><object pk="129"></object></field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="122"></object><object pk="129"></object></field>
</object>
<object pk="122" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2062,7 +2062,34 @@
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The sponsoring AD is preparing an RFC status change document</field>
<field type="IntegerField" name="order">2</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="123"></object><object pk="128"></object><object pk="129"></object></field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="130"></object><object pk="123"></object><object pk="129"></object></field>
</object>
<object pk="130" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
<field type="SlugField" name="slug">lc-req</field>
<field type="CharField" name="name">Last Call Requested</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">Last Call has been requested for this proposed status change</field>
<field type="IntegerField" name="order">3</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="131"></object></field>
</object>
<object pk="131" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
<field type="SlugField" name="slug">in-lc</field>
<field type="CharField" name="name">In Last Call</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">This proposed status change is in IETF Last Call</field>
<field type="IntegerField" name="order">4</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="132"></object></field>
</object>
<object pk="132" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
<field type="SlugField" name="slug">goahead</field>
<field type="CharField" name="name">Waiting for AD Go-Ahead</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The AD is following up on IETF LC comments</field>
<field type="IntegerField" name="order">5</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="123"></object><object pk="129"></object></field>
</object>
<object pk="123" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2070,8 +2097,8 @@
<field type="CharField" name="name">IESG Evaluation</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The IESG is considering the proposed RFC status changes</field>
<field type="IntegerField" name="order">3</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="124"></object><object pk="125"></object><object pk="126"></object><object pk="128"></object><object pk="129"></object></field>
<field type="IntegerField" name="order">6</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="124"></object><object pk="125"></object><object pk="126"></object><object pk="129"></object></field>
</object>
<object pk="124" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2079,8 +2106,8 @@
<field type="CharField" name="name">IESG Evaluation - Defer</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The evaluation of the proposed RFC status changes have been deferred to the next telechat</field>
<field type="IntegerField" name="order">4</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="123"></object><object pk="125"></object><object pk="126"></object><object pk="128"></object><object pk="129"></object></field>
<field type="IntegerField" name="order">7</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="123"></object><object pk="125"></object><object pk="126"></object><object pk="129"></object></field>
</object>
<object pk="125" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2088,8 +2115,8 @@
<field type="CharField" name="name">Approved - point raised</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The IESG has approved the RFC status changes, but a point has been raised that should be cleared before proceeding to announcement to be sent</field>
<field type="IntegerField" name="order">5</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
<field type="IntegerField" name="order">8</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="126"></object><object pk="127"></object></field>
</object>
<object pk="126" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2097,8 +2124,8 @@
<field type="CharField" name="name">Approved - announcement to be sent</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The IESG has approved the RFC status changes, but the secretariat has not yet sent the announcement</field>
<field type="IntegerField" name="order">6</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="127"></object><object pk="128"></object></field>
<field type="IntegerField" name="order">9</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="127"></object></field>
</object>
<object pk="127" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
@ -2106,25 +2133,16 @@
<field type="CharField" name="name">Approved - announcement sent</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The secretariat has announced the IESG's approved RFC status changes</field>
<field type="IntegerField" name="order">7</field>
<field type="IntegerField" name="order">10</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"></field>
</object>
<object pk="128" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
<field type="SlugField" name="slug">withdraw</field>
<field type="CharField" name="name">Withdrawn</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The request for RFC status changes was withdrawn</field>
<field type="IntegerField" name="order">8</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="121"></object></field>
</object>
<object pk="129" model="doc.state">
<field to="doc.statetype" name="type" rel="ManyToOneRel">statchg</field>
<field type="SlugField" name="slug">dead</field>
<field type="CharField" name="name">Dead</field>
<field type="BooleanField" name="used">True</field>
<field type="TextField" name="desc">The RFC status changes have been abandoned</field>
<field type="IntegerField" name="order">9</field>
<field type="IntegerField" name="order">11</field>
<field to="doc.state" name="next_states" rel="ManyToManyRel"><object pk="121"></object></field>
</object>
<object pk="5" model="doc.ballottype">

View file

@ -65,7 +65,8 @@ form.start-rfc-status-change-review .actions {
</tr>
<tr>
<td colspan="2" class="actions">
<input type="submit" value="Submit"/>
<input type="submit" name="Cancel" value="Cancel"/>
<input type="submit" name="Submit" value="Submit"/>
</td>
</tr>
</table>

View file

@ -1,4 +1,4 @@
Provide a description of what RFCs status are changed and any necessary rational for the change.
Provide a description of what RFCs status are changed and any necessary rationale for the change.
This is a good place to document how the RFC6410 criteria for advancing to Internet Standard are met:

View file

@ -0,0 +1,42 @@
{% extends "base.html" %}
{% block title %}Last Call text for {{ doc }}{% endblock %}
{% block morecss %}
form #id_last_call_text {
width: 700px;
height: 600px;
}
{% endblock %}
{% block content %}
<h1>Last Call text for {{ doc }}</h1>
<form class="edit-last-call-text" action="" method="POST">
{{ last_call_form.last_call_text }}
<p>{{ last_call_form.last_call_text.errors }}</p>
{% comment %}
{% if can_request_last_call and need_intended_status %}
<p>You need to select intended status of {{ need_intended_status }} and regenerate last call text to request last call.</p>
{% endif %}
{% endcomment %}
<div class="actions">
<a href="{{ back_url }}">Back</a>
<input type="submit" name="save_last_call_text" value="Save Last Call Text" />
<input type="submit" name="regenerate_last_call_text" value="Regenerate Last Call Text" />
<input style="margin-left: 8px" type="submit" name="send_last_call_request" value="Save and Request Last Call" />
</div>
</form>
{% load ietf_filters %}
{% if user|in_group:"Secretariat" %}
<p>
<a href="{% url doc_make_last_call name=doc.name %}">Make Last Call</a>
</p>
{% endif %}
{% endblock%}

View file

@ -0,0 +1,25 @@
{% load ietf_filters %}{% load mail_filters %}{% autoescape off %}From: The IESG <iesg-secretary@ietf.org>
To: IETF-Announce <ietf-announce@ietf.org>{% if cc %}
CC: {{ cc }}{% endif %}
Reply-To: ietf@ietf.org
Sender: <iesg-secretary@ietf.org>
Subject: Last Call: {{ doc.title|clean_whitespace }}
{% filter wordwrap:73 %}
The IESG has received a request from {{ requester }} to make the following status changes:
{%for change in changes %}
- {{ change }}
{% endfor %}
The supporting document for this request can be found here:
{{ settings.IDTRACKER_BASE_URL }}{{ doc.get_absolute_url }}
The IESG plans to make a decision in the next few weeks, and solicits final comments on this action. Please send substantive comments to the ietf@ietf.org mailing lists by {{ expiration_date }}. Exceptionally, comments may be sent to iesg@ietf.org instead. In either case, please retain the beginning of the Subject line to allow automated sorting.{% endfilter %}
The affected document{{ urls|pluralize }} can be obtained via
{% for u in urls %}{{ settings.IDTRACKER_BASE_URL}}{{ u }}
{% endfor %}
IESG discussion of this request can be tracked via
{{ settings.IDTRACKER_BASE_URL }}{% url doc_ballot name=doc %}
{% endautoescape %}

View file

@ -0,0 +1,40 @@
{% extends "base.html" %}
{% block title %}Make Last Call for {{ doc.name }}{% endblock %}
{% block morecss %}
form.approve-ballot pre {
margin: 0;
padding: 4px;
border-top: 4px solid #eee;
border-bottom: 4px solid #eee;
}
form.approve-ballot .announcement {
overflow-x: auto;
overflow-y: scroll;
width: 800px;
height: 400px;
border: 1px solid #bbb;
}
{% endblock %}
{% block content %}
<h1>Make Last Call for {{ doc.file_tag }}</h1>
<h2>({{doc.title}})</h2>
<h2>Announcement Text:</h2>
<div style="font-family: monospace; white-space: pre; border-style:solid; border-width:1px; padding:5px;">
{{ announcement }}
</div>
<form style="margin-top:20px" action="" method="POST">
<table>
{{ form.as_table }}
</table>
<div class="actions">
<a href="{{ doc.get_absolute_url }}">Back</a>
<input type="reset" value="Reset">
<input type="submit" value="Make Last Call"/>
</div>
</form>
{% endblock %}

View file

@ -102,11 +102,16 @@
<tr><td>Last updated:</td><td> {{ doc.time|date:"Y-m-d" }}</td></tr>
{% if not snapshot and user|has_role:"Area Director,Secretariat" and doc.get_state_slug not in approved_states %}
<tr><td colspan="2">
<span id="doc_request_resurrect_button" class="yui-button yui-link-button" style="margin-left:2px;">
<span id="doc_edit_affected_rfc_list_button" class="yui-button yui-link-button" style="margin-left:2px;">
<span class="first-child">
<a href="{% url status_change_relations name=doc.name %}">Edit Affected RFC List</a>
</span>
</span>
<span id="doc_edit_last_call_text" class="yui-button yui-link-button" style="margin-left:2px;">
<span class="first-child">
<a href="{% url status_change_last_call name=doc.name %}">Edit Last Call Text</a>
</span>
</span>
</td><tr/>
{% endif %}

View file

@ -53,6 +53,14 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
which it covers? If not, what changes would make it so?"
</blockquote>
{% endif %}
{% if title2|startswith:"3.3" %}
<blockquote>
Reviews should focus on these questions: "Are the proposed
changes to document status appropriate? Have all requirements
for such a change been met? If not, what changes to the proposal
would make it appropriate?"
</blockquote>
{% endif %}
{% endif %}<h4>{{ title3 }}</h4>
{% for doc in section_docs %}

View file

@ -406,7 +406,8 @@ def make_test_data():
crdoc.relateddocument_set.create(target=docalias,relationship_id='conflrev')
# A status change mid review
doc = Document.objects.create(name='status-change-imaginary-mid-review',type_id='statchg', rev='00', notify="fsm@ietf.org")
iesg = Group.objects.get(acronym='iesg')
doc = Document.objects.create(name='status-change-imaginary-mid-review',type_id='statchg', rev='00', notify="fsm@ietf.org",group=iesg)
doc.set_state(State.objects.get(slug='needshep',type__slug='statchg'))
doc.save()
docalias = DocAlias.objects.create(name='status-change-imaginary-mid-review',document=doc)