Port edit position and send ballot comment views with tests to new schema

- Legacy-Id: 2852
This commit is contained in:
Ole Laursen 2011-02-11 17:29:25 +00:00
parent 996b060749
commit 0e932ffd6f
8 changed files with 406 additions and 68 deletions

View file

@ -642,7 +642,7 @@ class BallotWrapper:
for pos in BallotPosition.objects.filter(doc=self.ballot, type="changed_ballot_position", time__gte=self.ballot.process_start, time__lte=self.ballot.process_end).select_related('ad').order_by("-time", '-id'):
if pos.ad not in seen:
p = dict(ad_name=pos.ad.get_name(),
ad_username="", # FIXME: don't seem to have username at the moment
ad_username=pos.ad.pk, # ought to rename this in doc_ballot_list
position=pos.pos.name,
is_old_ad=pos.ad not in active_ads,
old_positions=[])
@ -676,7 +676,7 @@ class BallotWrapper:
for ad in active_ads:
if ad not in seen:
d = dict(ad_name=ad.get_name(),
ad_username="", # FIXME: don't seem to have username at the moment
ad_username=pos.ad.pk,
position="No Record",
)
positions.append(d)

View file

@ -534,63 +534,74 @@ class AddCommentTestCase(django.test.TestCase):
self.assertTrue(draft.name in mail_outbox[-1]['Subject'])
class EditPositionTestCase(django.test.TestCase):
fixtures = ['base', 'draft', 'ballot']
fixtures = ['names']
def test_edit_position(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_edit_position', kwargs=dict(name=draft.filename))
login_testing_unauthorized(self, "rhousley", url)
draft = make_test_data()
url = urlreverse('doc_edit_position', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "ad", url)
ad = Email.objects.get(address="aread@ietf.org")
# normal get
r = self.client.get(url)
self.assertEquals(r.status_code, 200)
q = PyQuery(r.content)
self.assertTrue(len(q('form input[name=position]')) > 0)
self.assertEquals(len(q('form textarea[name=comment_text]')), 1)
self.assertEquals(len(q('form textarea[name=comment]')), 1)
# vote
events_before = draft.event_set.count()
self.assertTrue(not Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley"))
r = self.client.post(url, dict(position="discuss",
discuss_text="This is a discussion test.",
comment_text="This is a test."))
discuss="This is a discussion test.",
comment="This is a test."))
self.assertEquals(r.status_code, 302)
pos = Position.objects.get(ballot=draft.idinternal.ballot, ad__login_name="rhousley")
self.assertTrue("This is a discussion test." in IESGDiscuss.objects.get(ballot=draft.idinternal.ballot, ad__login_name="rhousley").text)
self.assertTrue("This is a test." in IESGComment.objects.get(ballot=draft.idinternal.ballot, ad__login_name="rhousley").text)
self.assertTrue(pos.discuss)
self.assertTrue(not (pos.yes or pos.noobj or pos.abstain or pos.recuse))
pos = draft.latest_event(BallotPosition, ad=ad)
self.assertEquals(pos.pos.slug, "discuss")
self.assertTrue("This is a discussion test." in pos.discuss)
self.assertTrue(pos.discuss_time != None)
self.assertTrue("This is a test." in pos.comment)
self.assertTrue(pos.comment_time != None)
self.assertTrue("New position" in pos.desc)
self.assertEquals(draft.event_set.count(), events_before + 3)
self.assertTrue("New position" in draft.idinternal.comments()[2].comment_text)
# recast vote
events_before = draft.event_set.count()
r = self.client.post(url, dict(position="noobj"))
self.assertEquals(r.status_code, 302)
pos = Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley")[0]
self.assertTrue(pos.noobj)
self.assertTrue(not (pos.yes or pos.abstain or pos.recuse))
self.assertTrue(pos.discuss == -1)
pos = draft.latest_event(BallotPosition, ad=ad)
self.assertEquals(pos.pos.slug, "noobj")
self.assertEquals(draft.event_set.count(), events_before + 1)
self.assertTrue("Position" in draft.idinternal.comments()[0].comment_text)
self.assertTrue("Position for" in pos.desc)
# clear vote
events_before = draft.event_set.count()
r = self.client.post(url, dict(position=""))
r = self.client.post(url, dict(position="norecord"))
self.assertEquals(r.status_code, 302)
pos = Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley")
self.assertEquals(len(pos), 0)
pos = draft.latest_event(BallotPosition, ad=ad)
self.assertEquals(pos.pos.slug, "norecord")
self.assertEquals(draft.event_set.count(), events_before + 1)
self.assertTrue("Position" in draft.idinternal.comments()[0].comment_text)
self.assertTrue("Position for" in pos.desc)
# change comment
events_before = draft.event_set.count()
r = self.client.post(url, dict(position="norecord", comment="New comment."))
self.assertEquals(r.status_code, 302)
pos = draft.latest_event(BallotPosition, ad=ad)
self.assertEquals(pos.pos.slug, "norecord")
self.assertEquals(draft.event_set.count(), events_before + 2)
self.assertTrue("Ballot comment text updated" in pos.desc)
def test_edit_position_as_secretary(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_edit_position', kwargs=dict(name=draft.filename))
url += "?ad=rhousley"
draft = make_test_data()
url = urlreverse('doc_edit_position', kwargs=dict(name=draft.name))
ad = Email.objects.get(address="aread@ietf.org")
url += "?ad=%s" % ad.pk
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -599,23 +610,30 @@ class EditPositionTestCase(django.test.TestCase):
q = PyQuery(r.content)
self.assertTrue(len(q('form input[name=position]')) > 0)
# vote for rhousley
# vote on behalf of AD
events_before = draft.event_set.count()
self.assertTrue(not Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley"))
r = self.client.post(url, dict(position="discuss"))
self.assertEquals(r.status_code, 302)
pos = Position.objects.get(ballot=draft.idinternal.ballot, ad__login_name="rhousley")
self.assertTrue(pos.discuss)
self.assertTrue(not (pos.yes or pos.noobj or pos.abstain or pos.recuse))
pos = draft.latest_event(BallotPosition, ad=ad)
self.assertEquals(pos.pos.slug, "discuss")
self.assertTrue("New position" in pos.desc)
self.assertTrue("by Sec" in pos.desc)
def test_send_ballot_comment(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_send_ballot_comment', kwargs=dict(name=draft.filename))
login_as = "rhousley"
login_testing_unauthorized(self, login_as, url)
draft = make_test_data()
draft.notify = "somebody@example.com"
draft.save()
ad = Email.objects.get(address="aread@ietf.org")
BallotPosition.objects.create(doc=draft, type="changed_ballot_position",
by=ad, ad=ad, pos=BallotPositionName.objects.get(slug="yes"),
comment="Test!",
comment_time=datetime.datetime.now())
url = urlreverse('doc_send_ballot_comment', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "ad", url)
# normal get
r = self.client.get(url)
@ -625,16 +643,15 @@ class EditPositionTestCase(django.test.TestCase):
# send
mailbox_before = len(mail_outbox)
IESGComment.objects.create(ballot=draft.idinternal.ballot,
ad=IESGLogin.objects.get(login_name=login_as),
text="Test!", date=date.today(),
revision=draft.revision_display(), active=1)
r = self.client.post(url, dict(cc="test@example.com", cc_state_change="1"))
self.assertEquals(r.status_code, 302)
self.assertEquals(len(mail_outbox), mailbox_before + 1)
self.assertTrue("COMMENT" in mail_outbox[-1]['Subject'])
m = mail_outbox[-1]
self.assertTrue("COMMENT" in m['Subject'])
self.assertTrue(draft.name in m['Subject'])
self.assertTrue("Test!" in str(m))
class DeferBallotTestCase(django.test.TestCase):
@ -642,7 +659,7 @@ class DeferBallotTestCase(django.test.TestCase):
def test_defer_ballot(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_defer_ballot', kwargs=dict(name=draft.filename))
url = urlreverse('doc_defer_ballot', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "rhousley", url)
# normal get
@ -666,7 +683,7 @@ class DeferBallotTestCase(django.test.TestCase):
def test_undefer_ballot(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_undefer_ballot', kwargs=dict(name=draft.filename))
url = urlreverse('doc_undefer_ballot', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "rhousley", url)
draft.idinternal.ballot.defer = True
@ -691,7 +708,7 @@ class BallotWriteupsTestCase(django.test.TestCase):
def test_edit_last_call_text(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.filename))
url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -728,7 +745,7 @@ class BallotWriteupsTestCase(django.test.TestCase):
def test_request_last_call(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.filename))
url = urlreverse('doc_ballot_lastcall', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
mailbox_before = len(mail_outbox)
@ -745,7 +762,7 @@ class BallotWriteupsTestCase(django.test.TestCase):
def test_edit_ballot_writeup(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.filename))
url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -765,7 +782,7 @@ class BallotWriteupsTestCase(django.test.TestCase):
def test_issue_ballot(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.filename))
url = urlreverse('doc_ballot_writeupnotes', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "rhousley", url)
draft.idinternal.ballot.ballot_issued = False
@ -800,7 +817,7 @@ class BallotWriteupsTestCase(django.test.TestCase):
def test_edit_approval_text(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_ballot_approvaltext', kwargs=dict(name=draft.filename))
url = urlreverse('doc_ballot_approvaltext', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -840,7 +857,7 @@ class ApproveBallotTestCase(django.test.TestCase):
def test_approve_ballot(self):
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.filename))
url = urlreverse('doc_approve_ballot', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -875,7 +892,7 @@ class MakeLastCallTestCase(django.test.TestCase):
draft.lc_expiration_date = None
draft.save()
url = urlreverse('doc_make_last_call', kwargs=dict(name=draft.filename))
url = urlreverse('doc_make_last_call', kwargs=dict(name=draft.name))
login_testing_unauthorized(self, "secretary", url)
# normal get
@ -984,7 +1001,7 @@ class ExpireIDsTestCase(django.test.TestCase):
self.assertEquals(int(draft.revision), int(revision_before) + 1)
self.assertTrue(not os.path.exists(os.path.join(self.id_dir, txt)))
self.assertTrue(os.path.exists(os.path.join(self.archive_dir, txt)))
new_txt = "%s-%s.txt" % (draft.filename, draft.revision)
new_txt = "%s-%s.txt" % (draft.name, draft.revision)
self.assertTrue(os.path.exists(os.path.join(self.id_dir, new_txt)))
def test_clean_up_id_files(self):
@ -1015,9 +1032,9 @@ class ExpireIDsTestCase(django.test.TestCase):
draft.status_id = 3
draft.save()
txt = "%s-%s.txt" % (draft.filename, draft.revision)
txt = "%s-%s.txt" % (draft.name, draft.revision)
self.write_id_file(txt, 5000)
pdf = "%s-%s.pdf" % (draft.filename, draft.revision)
pdf = "%s-%s.pdf" % (draft.name, draft.revision)
self.write_id_file(pdf, 5000)
clean_up_id_files()
@ -1035,7 +1052,7 @@ class ExpireIDsTestCase(django.test.TestCase):
draft.expiration_date = datetime.date.today() - datetime.timedelta(days=InternetDraft.DAYS_TO_EXPIRE + 1)
draft.save()
txt = "%s-%s.txt" % (draft.filename, draft.revision)
txt = "%s-%s.txt" % (draft.name, draft.revision)
self.write_id_file(txt, 5000)
clean_up_id_files()
@ -1053,7 +1070,7 @@ class ExpireIDsTestCase(django.test.TestCase):
revision_before = draft.revision
txt = "%s-%s.txt" % (draft.filename, draft.revision)
txt = "%s-%s.txt" % (draft.name, draft.revision)
self.write_id_file(txt, 1000)
clean_up_id_files()

View file

@ -22,6 +22,9 @@ from ietf.idrfc.mails import *
from ietf.idrfc.utils import *
from ietf.idrfc.lastcall import request_last_call
from doc.models import Document, Event, BallotPosition, save_document_in_history
from name.models import BallotPositionName
BALLOT_CHOICES = (("yes", "Yes"),
("noobj", "No Objection"),
("discuss", "Discuss"),
@ -78,14 +81,13 @@ def edit_position(request, name):
if not ad_username:
raise Http404()
ad = get_object_or_404(IESGLogin, login_name=ad_username)
pos, discuss, comment = get_ballot_info(doc.idinternal.ballot, ad)
doc.latest_event(BallotPosition, type='changed_ballot_position', ad=ad)
if request.method == 'POST':
form = EditPositionForm(request.POST)
if form.is_valid():
# save the vote
# save the vote
clean = form.cleaned_data
if clean['return_to_url']:
@ -189,6 +191,139 @@ def edit_position(request, name):
),
context_instance=RequestContext(request))
class EditPositionFormREDESIGN(forms.Form):
position = forms.ModelChoiceField(queryset=BallotPositionName.objects.all(), widget=forms.RadioSelect, initial="norecord", required=True)
discuss = forms.CharField(required=False, widget=forms.Textarea)
comment = forms.CharField(required=False, widget=forms.Textarea)
return_to_url = forms.CharField(required=False, widget=forms.HiddenInput)
@group_required('Area_Director','Secretariat')
def edit_positionREDESIGN(request, name):
"""Vote and edit discuss and comment on Internet Draft as Area Director."""
doc = get_object_or_404(Document, docalias__name=name)
if not doc.iesg_state:
raise Http404()
ad = login = request.user.get_profile().email()
if 'HTTP_REFERER' in request.META:
return_to_url = request.META['HTTP_REFERER']
else:
return_to_url = doc.get_absolute_url()
# if we're in the Secretariat, we can select an AD to act as stand-in for
if not in_group(request.user, "Area_Director"):
ad_id = request.GET.get('ad')
if not ad_id:
raise Http404()
ad = get_object_or_404(Email, pk=ad_id)
old_pos = doc.latest_event(BallotPosition, type="changed_ballot_position", ad=ad)
if request.method == 'POST':
form = EditPositionForm(request.POST)
if form.is_valid():
# save the vote
clean = form.cleaned_data
if clean['return_to_url']:
return_to_url = clean['return_to_url']
pos = BallotPosition(doc=doc, by=login)
pos.type = "changed_ballot_position"
pos.ad = ad
pos.pos = clean["position"]
pos.comment = clean["comment"].strip()
pos.comment_time = old_pos.comment_time if old_pos else None
pos.discuss = clean["discuss"].strip()
pos.discuss_time = old_pos.discuss_time if old_pos else None
changes = []
added_events = []
# possibly add discuss/comment comments to history trail
# so it's easy to see
old_comment = old_pos.comment if old_pos else ""
if pos.comment != old_comment:
pos.comment_time = pos.time
changes.append("comment")
if pos.comment:
e = Event(doc=doc)
e.by = ad # otherwise we can't see who's saying it
e.type = "added_comment"
e.desc = "[Ballot comment]\n" + pos.comment
added_events.append(e)
old_discuss = old_pos.discuss if old_pos else ""
if pos.discuss != old_discuss:
pos.discuss_time = pos.time
changes.append("discuss")
if pos.discuss:
e = Event(doc=doc, by=login)
e.by = ad # otherwise we can't see who's saying it
e.type = "added_comment"
e.desc = "[Ballot discuss]\n" + pos.discuss
added_events.append(e)
# figure out a description
if not old_pos and pos.pos.slug != "norecord":
pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.get_name())
elif old_pos and pos.pos != old_pos.pos:
pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos.ad.get_name(), pos.pos.name, old_pos.pos.name)
if not pos.desc and changes:
pos.desc = u"Ballot %s text updated for %s" % (u" and ".join(changes), ad.get_name())
# only add new event if we actually got a change
if pos.desc:
if login != ad:
pos.desc += u" by %s" % login.get_name()
pos.save()
for e in added_events:
e.save() # save them after the position is saved to get later id
doc.time = pos.time
doc.save()
# FIXME: test
if request.POST.get("send_mail"):
qstr = "?return_to_url=%s" % return_to_url
if request.GET.get('ad'):
qstr += "&ad=%s" % request.GET.get('ad')
return HttpResponseRedirect(urlreverse("doc_send_ballot_comment", kwargs=dict(name=doc.name)) + qstr)
else:
return HttpResponseRedirect(return_to_url)
else:
initial = {}
if old_pos:
initial['position'] = old_pos.pos.slug
initial['discuss'] = old_pos.discuss
initial['comment'] = old_pos.comment
if return_to_url:
initial['return_to_url'] = return_to_url
form = EditPositionForm(initial=initial)
return render_to_response('idrfc/edit_positionREDESIGN.html',
dict(doc=doc,
form=form,
ad=ad,
return_to_url=return_to_url,
old_pos=old_pos,
),
context_instance=RequestContext(request))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
edit_position = edit_positionREDESIGN
EditPositionForm = EditPositionFormREDESIGN
@group_required('Area_Director','Secretariat')
def send_ballot_comment(request, name):
"""Email Internet Draft ballot discuss/comment for area director."""
@ -255,6 +390,73 @@ def send_ballot_comment(request, name):
),
context_instance=RequestContext(request))
@group_required('Area_Director','Secretariat')
def send_ballot_commentREDESIGN(request, name):
"""Email Internet Draft ballot discuss/comment for area director."""
doc = get_object_or_404(Document, docalias__name=name)
ad = login = request.user.get_profile().email()
return_to_url = request.GET.get('return_to_url')
if not return_to_url:
return_to_url = doc.get_absolute_url()
if 'HTTP_REFERER' in request.META:
back_url = request.META['HTTP_REFERER']
else:
back_url = doc.get_absolute_url()
# if we're in the Secretariat, we can select an AD to act as stand-in for
if not in_group(request.user, "Area_Director"):
ad_id = request.GET.get('ad')
if not ad_id:
raise Http404()
ad = get_object_or_404(Email, pk=ad_id)
pos = doc.latest_event(BallotPosition, type="changed_ballot_position", ad=ad)
if not pos:
raise Http404()
subj = []
d = ""
if pos.pos == "discuss" and pos.discuss:
d = pos.discuss
subj.append("DISCUSS")
c = ""
if pos.comment:
c = pos.comment
subj.append("COMMENT")
subject = "%s: %s" % (" and ".join(subj), doc.file_tag())
body = render_to_string("idrfc/ballot_comment_mail.txt",
dict(discuss=d, comment=c))
frm = ad.formatted_email()
to = "iesg@ietf.org"
if request.method == 'POST':
cc = [x.strip() for x in request.POST.get("cc", "").split(',') if x.strip()]
if request.POST.get("cc_state_change") and doc.notify:
cc.extend(doc.notify.split(','))
send_mail_text(request, to, frm, subject, body, cc=", ".join(cc))
return HttpResponseRedirect(return_to_url)
return render_to_response('idrfc/send_ballot_commentREDESIGN.html',
dict(doc=doc,
subject=subject,
body=body,
frm=frm,
to=to,
ad=ad,
can_send=d or c,
back_url=back_url,
),
context_instance=RequestContext(request))
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
send_ballot_comment = send_ballot_commentREDESIGN
@group_required('Area_Director','Secretariat')
def defer_ballot(request, name):

View file

@ -1,6 +1,6 @@
{% if discuss %}Discuss:
{{ discuss|safe }}
{{ discuss|safe|wordwrap:73 }}
{% endif %}{% if comment %}Comment:
{{ comment|safe }}
{{ comment|safe|wordwrap:73 }}
{% endif %}

View file

@ -0,0 +1,66 @@
{% extends "base.html" %}
{% block title %}Change position for {{ ad.get_name }}{% endblock %}
{% block morecss %}
form.position-form .position ul {
padding: 0;
margin: 0;
}
form.position-form .position li {
list-style-type: none;
float: left;
padding-right: 10px;
}
form.position-form .last-edited {
font-style: italic;
}
form.position-form .discuss-text {
padding-top: 20px
}
form.position-form #id_discuss_text,
form.position-form #id_comment_text {
width: 700px;
height: 250px;
}
form.position-form .comment-text {
margin-top: 20px;
}
{% endblock %}
{% block content %}
<h1>Change position for {{ ad.get_name }}</h1>
<form class="position-form" action="" method="POST">
<div class="position">{{ form.position }}</div>
<div style="clear:left"></div>
<div class="discuss-widgets" {% ifnotequal form.position.initial "discuss" %}style="display:none"{% endifnotequal %}>
<div class="discuss-text">
{{ form.discuss.label_tag }}:
{% if old_pos and old_pos.discuss_time %}<span class="last-edited">(last edited {{ old_pos.discuss_time }})</span>{% endif %}
</div>
{{ form.discuss }}
</div>
<div class="comment-text">
{{ form.comment.label_tag }}:
{% if old_pos and old_pos.comment_time %}<span class="last-edited">(last edited {{ old_pos.comment_time }}){% endif %}</span>
</div>
{{ form.comment }}
<div class="actions">
<a href="{{ return_to_url }}">Back</a>
<input type="submit" name="send_mail" value="Save and send email"/>
<input type="submit" value="Save"/>
</div>
{{ form.return_to_url }}
</form>
{% endblock %}
{% block content_end %}
<script type="text/javascript" src="/js/doc-edit-position.js"></script>
{% endblock %}

View file

@ -0,0 +1,47 @@
{% extends "base.html" %}
{% block title %}Email Discuss and Comment text for {{ ad.get_name }} to IESG list{% endblock %}
{% block morecss %}
form.send-ballot pre {
margin: 0;
padding: 4px;
border-top: 4px solid #eee;
border-bottom: 4px solid #eee;
}
{% endblock %}
{% block content %}
<h1>Email Discuss and Comment text for {{ ad.get_name }} to IESG list</h1>
<form class="send-ballot" action="" method="POST">
<table>
<tr><th>From:</th> <td>{{ frm }}</td></tr>
<tr><th>To:</th> <td>{{ to }}</td></tr>
<tr>
<th>Cc:<br/>
<span class="help">separated<br/> by comma</span></th>
<td><input type="text" name="cc" value="" size="75" /><br/>
{% if doc.notify %}
<label>
<input type="checkbox" name="cc_state_change" value="1" />
{{ doc.notify }}
</label>
{% endif %}
</td>
</tr>
<tr><th>Subject:</th> <td>{{ subject }}</td></tr>
<tr>
<th>Body:</th>
<td><pre>{{ body }}</pre></td>
</tr>
<tr>
<td></td>
<td class="actions">
<a href="{{ back_url }}">Back</a>
<input type="submit" value="Send"/>
</td>
</tr>
</table>
</form>
{% endblock %}

View file

@ -18,6 +18,7 @@ admin.site.register(DocHistory, DocHistoryAdmin)
class DocAliasAdmin(admin.ModelAdmin):
list_display = [ 'name', 'document_link', ]
search_fields = [ 'name', 'document__name', ]
raw_id_fields = ['document']
admin.site.register(DocAlias, DocAliasAdmin)
class SendQueueAdmin(admin.ModelAdmin):
@ -33,14 +34,19 @@ class EventAdmin(admin.ModelAdmin):
def by_raw(self, instance):
return instance.by_id
by_raw.short_description = "By"
admin.site.register(Event, EventAdmin)
admin.site.register(Message, EventAdmin)
admin.site.register(Text, EventAdmin)
admin.site.register(NewRevision, EventAdmin)
admin.site.register(BallotPosition, EventAdmin)
admin.site.register(Status, EventAdmin)
admin.site.register(Expiration, EventAdmin)
admin.site.register(Telechat, EventAdmin)
class BallotPositionAdmin(EventAdmin):
raw_id_fields = ["doc", "by", "ad"]
admin.site.register(BallotPosition, BallotPositionAdmin)

View file

@ -257,7 +257,7 @@ class NewRevision(Event):
# IESG events
class BallotPosition(Event):
ad = models.ForeignKey(Email)
pos = models.ForeignKey(BallotPositionName, verbose_name="position", default="norec")
pos = models.ForeignKey(BallotPositionName, verbose_name="position", default="norecord")
discuss = models.TextField(help_text="Discuss text if position is discuss", blank=True)
discuss_time = models.DateTimeField(help_text="Time discuss text was written", blank=True, null=True)
comment = models.TextField(help_text="Optional comment", blank=True)