Skip to content

Commit ecf68db

Browse files
committed
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
1 parent fd01ddd commit ecf68db

53 files changed

Lines changed: 3818 additions & 2036 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ietf/bin/find-submission-confirmation-email-in-postfix-log

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ from django.conf import settings
3131

3232
from ietf.utils.path import path as Path
3333

34-
from ietf.submit.models import IdSubmissionDetail
34+
from ietf.submit.models import Submission
3535
from ietf.doc.models import Document
3636

3737

@@ -56,11 +56,11 @@ from_email = settings.IDSUBMIT_FROM_EMAIL
5656
if "<" in from_email:
5757
from_email = from_email.split("<")[1].split(">")[0]
5858

59-
submission = IdSubmissionDetail.objects.filter(filename=draft).order_by('-pk')[0]
59+
submission = Submission.objects.filter(name=draft).order_by('-pk')[0]
6060
document = Document.objects.get(name=draft)
6161
emails = [ author.address for author in document.authors.all() ]
6262

63-
file = Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.revision))
63+
file = Path(settings.INTERNET_DRAFT_PATH) / ("%s-%s.txt"%(draft, submission.rev))
6464

6565
upload_time = time.localtime(file.mtime)
6666
timestr1 = time.strftime("%b %d %H:%M", upload_time)
@@ -87,4 +87,4 @@ for log in logfiles:
8787
for qi in queue_ids:
8888
if qi in line:
8989
sys.stdout.write(line)
90-
90+

ietf/name/fixtures/names.json

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,101 @@
713713
"desc": ""
714714
}
715715
},
716+
{
717+
"pk": "uploaded",
718+
"model": "name.draftsubmissionstatename",
719+
"fields": {
720+
"order": 1,
721+
"next_states": [
722+
"auth",
723+
"aut-appr",
724+
"grp-appr",
725+
"manual",
726+
"cancel"
727+
],
728+
"used": true,
729+
"name": "Uploaded",
730+
"desc": ""
731+
}
732+
},
733+
{
734+
"pk": "auth",
735+
"model": "name.draftsubmissionstatename",
736+
"fields": {
737+
"order": 2,
738+
"next_states": [
739+
"cancel",
740+
"posted"
741+
],
742+
"used": true,
743+
"name": "Awaiting Submitter Authentication",
744+
"desc": ""
745+
}
746+
},
747+
{
748+
"pk": "aut-appr",
749+
"model": "name.draftsubmissionstatename",
750+
"fields": {
751+
"order": 3,
752+
"next_states": [
753+
"cancel",
754+
"posted"
755+
],
756+
"used": true,
757+
"name": "Awaiting Approval from Previous Version Authors'",
758+
"desc": ""
759+
}
760+
},
761+
{
762+
"pk": "grp-appr",
763+
"model": "name.draftsubmissionstatename",
764+
"fields": {
765+
"order": 4,
766+
"next_states": [
767+
"cancel",
768+
"posted"
769+
],
770+
"used": true,
771+
"name": "Awaiting Initial Version Approval",
772+
"desc": ""
773+
}
774+
},
775+
{
776+
"pk": "manual",
777+
"model": "name.draftsubmissionstatename",
778+
"fields": {
779+
"order": 5,
780+
"next_states": [
781+
"cancel",
782+
"posted"
783+
],
784+
"used": true,
785+
"name": "Awaiting Manual Post",
786+
"desc": ""
787+
}
788+
},
789+
{
790+
"pk": "cancel",
791+
"model": "name.draftsubmissionstatename",
792+
"fields": {
793+
"order": 6,
794+
"next_states": [],
795+
"used": true,
796+
"name": "Cancelled",
797+
"desc": ""
798+
}
799+
},
800+
{
801+
"pk": "posted",
802+
"model": "name.draftsubmissionstatename",
803+
"fields": {
804+
"order": 7,
805+
"next_states": [],
806+
"used": true,
807+
"name": "Posted",
808+
"desc": ""
809+
}
810+
},
716811
{
717812
"pk": "comment",
718813
"model": "name.feedbacktype",
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# encoding: utf-8
2+
import datetime
3+
from south.db import db
4+
from south.v2 import SchemaMigration
5+
from django.db import models
6+
7+
class Migration(SchemaMigration):
8+
9+
def forwards(self, orm):
10+
11+
# Adding model 'DraftSubmissionStateName'
12+
db.create_table('name_draftsubmissionstatename', (
13+
('slug', self.gf('django.db.models.fields.CharField')(max_length=8, primary_key=True)),
14+
('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
15+
('desc', self.gf('django.db.models.fields.TextField')(blank=True)),
16+
('used', self.gf('django.db.models.fields.BooleanField')(default=True)),
17+
('order', self.gf('django.db.models.fields.IntegerField')(default=0)),
18+
))
19+
db.send_create_signal('name', ['DraftSubmissionStateName'])
20+
21+
# Adding M2M table for field next_states on 'DraftSubmissionStateName'
22+
db.create_table('name_draftsubmissionstatename_next_states', (
23+
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
24+
('from_draftsubmissionstatename', models.ForeignKey(orm['name.draftsubmissionstatename'], null=False)),
25+
('to_draftsubmissionstatename', models.ForeignKey(orm['name.draftsubmissionstatename'], null=False))
26+
))
27+
db.create_unique('name_draftsubmissionstatename_next_states', ['from_draftsubmissionstatename_id', 'to_draftsubmissionstatename_id'])
28+
29+
30+
def backwards(self, orm):
31+
32+
# Deleting model 'DraftSubmissionStateName'
33+
db.delete_table('name_draftsubmissionstatename')
34+
35+
# Removing M2M table for field next_states on 'DraftSubmissionStateName'
36+
db.delete_table('name_draftsubmissionstatename_next_states')
37+
38+
39+
models = {
40+
'name.ballotpositionname': {
41+
'Meta': {'ordering': "['order']", 'object_name': 'BallotPositionName'},
42+
'blocking': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
43+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
44+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
45+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
46+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
47+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
48+
},
49+
'name.constraintname': {
50+
'Meta': {'ordering': "['order']", 'object_name': 'ConstraintName'},
51+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
52+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
53+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
54+
'penalty': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
55+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
56+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
57+
},
58+
'name.dbtemplatetypename': {
59+
'Meta': {'ordering': "['order']", 'object_name': 'DBTemplateTypeName'},
60+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
61+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
62+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
63+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
64+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
65+
},
66+
'name.docrelationshipname': {
67+
'Meta': {'ordering': "['order']", 'object_name': 'DocRelationshipName'},
68+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
69+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
70+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
71+
'revname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
72+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
73+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
74+
},
75+
'name.docremindertypename': {
76+
'Meta': {'ordering': "['order']", 'object_name': 'DocReminderTypeName'},
77+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
78+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
79+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
80+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
81+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
82+
},
83+
'name.doctagname': {
84+
'Meta': {'ordering': "['order']", 'object_name': 'DocTagName'},
85+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
86+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
87+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
88+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
89+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
90+
},
91+
'name.doctypename': {
92+
'Meta': {'ordering': "['order']", 'object_name': 'DocTypeName'},
93+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
94+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
95+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
96+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
97+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
98+
},
99+
'name.draftsubmissionstatename': {
100+
'Meta': {'ordering': "['order']", 'object_name': 'DraftSubmissionStateName'},
101+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
102+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
103+
'next_states': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'previous_states'", 'blank': 'True', 'to': "orm['name.DraftSubmissionStateName']"}),
104+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
105+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
106+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
107+
},
108+
'name.feedbacktype': {
109+
'Meta': {'ordering': "['order']", 'object_name': 'FeedbackType'},
110+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
111+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
112+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
113+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
114+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
115+
},
116+
'name.groupmilestonestatename': {
117+
'Meta': {'ordering': "['order']", 'object_name': 'GroupMilestoneStateName'},
118+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
119+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
120+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
121+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
122+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
123+
},
124+
'name.groupstatename': {
125+
'Meta': {'ordering': "['order']", 'object_name': 'GroupStateName'},
126+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
127+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
128+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
129+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
130+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
131+
},
132+
'name.grouptypename': {
133+
'Meta': {'ordering': "['order']", 'object_name': 'GroupTypeName'},
134+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
135+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
136+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
137+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
138+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
139+
},
140+
'name.intendedstdlevelname': {
141+
'Meta': {'ordering': "['order']", 'object_name': 'IntendedStdLevelName'},
142+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
143+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
144+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
145+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
146+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
147+
},
148+
'name.liaisonstatementpurposename': {
149+
'Meta': {'ordering': "['order']", 'object_name': 'LiaisonStatementPurposeName'},
150+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
151+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
152+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
153+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
154+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
155+
},
156+
'name.meetingtypename': {
157+
'Meta': {'ordering': "['order']", 'object_name': 'MeetingTypeName'},
158+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
159+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
160+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
161+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
162+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
163+
},
164+
'name.nomineepositionstate': {
165+
'Meta': {'ordering': "['order']", 'object_name': 'NomineePositionState'},
166+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
167+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
168+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
169+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
170+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
171+
},
172+
'name.rolename': {
173+
'Meta': {'ordering': "['order']", 'object_name': 'RoleName'},
174+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
175+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
176+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
177+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
178+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
179+
},
180+
'name.sessionstatusname': {
181+
'Meta': {'ordering': "['order']", 'object_name': 'SessionStatusName'},
182+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
183+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
184+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
185+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
186+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
187+
},
188+
'name.stdlevelname': {
189+
'Meta': {'ordering': "['order']", 'object_name': 'StdLevelName'},
190+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
191+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
192+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
193+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
194+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
195+
},
196+
'name.streamname': {
197+
'Meta': {'ordering': "['order']", 'object_name': 'StreamName'},
198+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
199+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
200+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
201+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
202+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
203+
},
204+
'name.timeslottypename': {
205+
'Meta': {'ordering': "['order']", 'object_name': 'TimeSlotTypeName'},
206+
'desc': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
207+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
208+
'order': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
209+
'slug': ('django.db.models.fields.CharField', [], {'max_length': '8', 'primary_key': 'True'}),
210+
'used': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
211+
}
212+
}
213+
214+
complete_apps = ['name']

0 commit comments

Comments
 (0)