Port edit info view with tests to new schema
- Legacy-Id: 2823
This commit is contained in:
parent
4b15644a1e
commit
d56e446833
|
@ -371,6 +371,11 @@
|
|||
<field type="TextField" name="desc"></field>
|
||||
<field type="BooleanField" name="used">1</field>
|
||||
</object>
|
||||
<object pk="ex-ad" model="name.rolename">
|
||||
<field type="CharField" name="name">Ex-Area Director</field>
|
||||
<field type="TextField" name="desc">In-active Area Director</field>
|
||||
<field type="BooleanField" name="used">1</field>
|
||||
</object>
|
||||
<object pk="std" model="name.stdlevelname">
|
||||
<field type="CharField" name="name">Standard</field>
|
||||
<field type="TextField" name="desc"></field>
|
||||
|
|
|
@ -54,7 +54,7 @@ def email_ownerREDESIGN(request, doc, owner, changed_by, text, subject=None):
|
|||
to = owner.formatted_email()
|
||||
send_mail(request, to,
|
||||
"DraftTracker Mail System <iesg-secretary@ietf.org>",
|
||||
"%s updated by %s" % (doc.file_tag(), changed_by),
|
||||
"%s updated by %s" % (doc.file_tag(), changed_by.get_name()),
|
||||
"idrfc/change_notice.txt",
|
||||
dict(text=html_to_text(text),
|
||||
doc=doc,
|
||||
|
|
|
@ -47,6 +47,7 @@ from doc.models import *
|
|||
from name.models import *
|
||||
from group.models import *
|
||||
from person.models import *
|
||||
from ietf.iesg.models import TelechatDates
|
||||
from ietf.utils.test_utils import SimpleUrlTestCase, RealDatabaseTest, login_testing_unauthorized
|
||||
from ietf.utils.test_runner import mail_outbox
|
||||
|
||||
|
@ -105,13 +106,13 @@ def make_test_data():
|
|||
name="Ano Therdir",
|
||||
ascii="Ano Therdir",
|
||||
)
|
||||
ad = Email.objects.create(
|
||||
email = Email.objects.create(
|
||||
address="ano@ietf.org",
|
||||
person=p)
|
||||
Role.objects.create(
|
||||
name_id="ad",
|
||||
group=area,
|
||||
email=ad)
|
||||
email=email)
|
||||
porg = PersonOrOrgInfo.objects.create(
|
||||
first_name="Ano",
|
||||
last_name="Therdir",
|
||||
|
@ -164,6 +165,7 @@ def make_test_data():
|
|||
type_id="draft",
|
||||
title="Optimizing Martian Network Topologies",
|
||||
state_id="active",
|
||||
iesg_state_id="pub-req",
|
||||
stream_id="ietf",
|
||||
group=group,
|
||||
abstract="Techniques for achieving near-optimal Martian networks.",
|
||||
|
@ -171,7 +173,8 @@ def make_test_data():
|
|||
pages=2,
|
||||
intended_std_level_id="ps",
|
||||
ad=ad,
|
||||
notify="aliens@example.mars"
|
||||
notify="aliens@example.mars",
|
||||
note="",
|
||||
)
|
||||
|
||||
DocAlias.objects.create(
|
||||
|
@ -179,12 +182,21 @@ def make_test_data():
|
|||
name=draft.name,
|
||||
)
|
||||
|
||||
# draft has only one event
|
||||
Event.objects.create(
|
||||
type="started_iesg_process",
|
||||
by=ad,
|
||||
doc=draft,
|
||||
desc="Added draft",
|
||||
)
|
||||
|
||||
t = datetime.date.today()
|
||||
dates = TelechatDates(date1=t,
|
||||
date2=t + datetime.timedelta(days=7),
|
||||
date3=t + datetime.timedelta(days=14),
|
||||
date4=t + datetime.timedelta(days=21),
|
||||
)
|
||||
super(dates.__class__, dates).save(force_insert=True)
|
||||
|
||||
return draft
|
||||
|
||||
|
@ -222,7 +234,7 @@ class ChangeStateTestCase(django.test.TestCase):
|
|||
|
||||
|
||||
# change state
|
||||
history_before = draft.event_set.count()
|
||||
events_before = draft.event_set.count()
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
r = self.client.post(url, dict(state="review-e"))
|
||||
|
@ -230,7 +242,7 @@ class ChangeStateTestCase(django.test.TestCase):
|
|||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.iesg_state_id, "review-e")
|
||||
self.assertEquals(draft.event_set.count(), history_before + 1)
|
||||
self.assertEquals(draft.event_set.count(), events_before + 1)
|
||||
self.assertTrue("State changed" in draft.event_set.all()[0].desc)
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 2)
|
||||
self.assertTrue("State Update Notice" in mail_outbox[-2]['Subject'])
|
||||
|
@ -288,149 +300,147 @@ class ChangeStateTestCase(django.test.TestCase):
|
|||
|
||||
|
||||
class EditInfoTestCase(django.test.TestCase):
|
||||
fixtures = ['base', 'draft']
|
||||
fixtures = ['names']
|
||||
|
||||
def test_edit_info(self):
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.filename))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
draft = make_test_data()
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form select[name=intended_status]')), 1)
|
||||
self.assertEquals(len(q('form select[name=intended_std_level]')), 1)
|
||||
self.assertEquals(len(q('form input[name=via_rfc_editor]')), 1)
|
||||
|
||||
prev_job_owner = draft.idinternal.job_owner
|
||||
prev_ad = draft.ad
|
||||
# faulty post
|
||||
r = self.client.post(url, dict(job_owner="123456789"))
|
||||
r = self.client.post(url, dict(ad="123456789"))
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertTrue(len(q('form ul.errorlist')) > 0)
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertEquals(draft.idinternal.job_owner, prev_job_owner)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.ad, prev_ad)
|
||||
|
||||
# edit info
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.event_set.all().count()
|
||||
mailbox_before = len(mail_outbox)
|
||||
draft.group = Acronym.objects.get(acronym_id=Acronym.INDIVIDUAL_SUBMITTER)
|
||||
draft.save()
|
||||
new_job_owner = IESGLogin.objects.exclude(id__in=[IESGLogin.objects.get(login_name="klm").id, draft.idinternal.job_owner_id])[0]
|
||||
new_area = Area.active_areas()[0]
|
||||
|
||||
new_ad = Email.objects.get(address="ano@ietf.org")
|
||||
|
||||
r = self.client.post(url,
|
||||
dict(intended_status=str(draft.intended_status_id),
|
||||
dict(intended_std_level=str(draft.intended_std_level.pk),
|
||||
status_date=str(date.today() + timedelta(2)),
|
||||
area_acronym=str(new_area.area_acronym_id),
|
||||
via_rfc_editor="1",
|
||||
job_owner=new_job_owner.id,
|
||||
state_change_notice_to="test@example.com",
|
||||
note="",
|
||||
ad=str(new_ad.pk),
|
||||
notify="test@example.com",
|
||||
note="New note",
|
||||
telechat_date="",
|
||||
))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertEquals(draft.idinternal.area_acronym, new_area)
|
||||
self.assertTrue(draft.idinternal.via_rfc_editor)
|
||||
self.assertEquals(draft.idinternal.job_owner, new_job_owner)
|
||||
self.assertEquals(draft.idinternal.note, "")
|
||||
self.assertTrue(not draft.idinternal.agenda)
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 3)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(draft.tags.filter(slug="via-rfc"))
|
||||
self.assertEquals(draft.ad, new_ad)
|
||||
self.assertEquals(draft.note, "New note")
|
||||
self.assertTrue(not draft.latest_event(Telechat, type="telechat_date"))
|
||||
self.assertEquals(draft.event_set.count(), events_before + 4)
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
self.assertTrue(draft.filename in mail_outbox[-1]['Subject'])
|
||||
self.assertTrue(draft.name in mail_outbox[-1]['Subject'])
|
||||
|
||||
def test_edit_telechat_date(self):
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
draft.idinternal.agenda = False
|
||||
draft.idinternal.save()
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.filename))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
draft = make_test_data()
|
||||
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
data = dict(intended_status=str(draft.intended_status_id),
|
||||
data = dict(intended_std_level=str(draft.intended_std_level_id),
|
||||
status_date=str(date.today() + timedelta(2)),
|
||||
area_acronym=str(draft.idinternal.area_acronym_id),
|
||||
via_rfc_editor="1",
|
||||
job_owner=str(draft.idinternal.job_owner_id),
|
||||
state_change_notice_to="test@example.com",
|
||||
ad=str(draft.ad_id),
|
||||
notify="test@example.com",
|
||||
note="",
|
||||
)
|
||||
|
||||
from ietf.iesg.models import TelechatDates
|
||||
|
||||
# add to telechat
|
||||
self.assertTrue(not draft.latest_event(Telechat, "scheduled_for_telechat"))
|
||||
data["telechat_date"] = TelechatDates.objects.all()[0].date1.isoformat()
|
||||
r = self.client.post(url, data)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertTrue(draft.idinternal.agenda)
|
||||
self.assertEquals(draft.idinternal.telechat_date, TelechatDates.objects.all()[0].date1)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(draft.latest_event(Telechat, "scheduled_for_telechat"))
|
||||
self.assertEquals(draft.latest_event(Telechat, "scheduled_for_telechat").telechat_date, TelechatDates.objects.all()[0].date1)
|
||||
|
||||
# change telechat
|
||||
data["telechat_date"] = TelechatDates.objects.all()[0].date2.isoformat()
|
||||
r = self.client.post(url, data)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertTrue(draft.idinternal.agenda)
|
||||
self.assertEquals(draft.idinternal.telechat_date, TelechatDates.objects.all()[0].date2)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEquals(draft.latest_event(Telechat, "scheduled_for_telechat").telechat_date, TelechatDates.objects.all()[0].date2)
|
||||
|
||||
# remove from agenda
|
||||
data["telechat_date"] = ""
|
||||
r = self.client.post(url, data)
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertTrue(not draft.idinternal.agenda)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(not draft.latest_event(Telechat, "scheduled_for_telechat").telechat_date)
|
||||
|
||||
for e in draft.event_set.all():
|
||||
print e.desc
|
||||
|
||||
|
||||
def test_add_draft(self):
|
||||
draft = InternetDraft.objects.get(filename="draft-ah-rfc2141bis-urn")
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.filename))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
def test_start_iesg_process_on_draft(self):
|
||||
draft = make_test_data()
|
||||
draft.ad = None
|
||||
draft.iesg_state = None
|
||||
draft.save()
|
||||
draft.event_set.all().delete()
|
||||
|
||||
url = urlreverse('doc_edit_info', kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEquals(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEquals(len(q('form select[name=intended_status]')), 1)
|
||||
self.assertEquals(len(q('form select[name=intended_std_level]')), 1)
|
||||
self.assertEquals(len(q('form input[name=via_rfc_editor]')), 1)
|
||||
self.assertTrue('@' in q('form input[name=state_change_notice_to]')[0].get('value'))
|
||||
self.assertTrue('@' in q('form input[name=notify]')[0].get('value'))
|
||||
|
||||
# add
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
job_owner = IESGLogin.objects.filter(user_level=1)[0]
|
||||
area = Area.active_areas()[0]
|
||||
ad = Email.objects.get(address="aread@ietf.org")
|
||||
|
||||
r = self.client.post(url,
|
||||
dict(intended_status=str(draft.intended_status_id),
|
||||
dict(intended_std_level=str(draft.intended_std_level_id),
|
||||
status_date=str(date.today() + timedelta(2)),
|
||||
area_acronym=str(area.area_acronym_id),
|
||||
via_rfc_editor="1",
|
||||
job_owner=job_owner.id,
|
||||
state_change_notice_to="test@example.com",
|
||||
ad=ad,
|
||||
notify="test@example.com",
|
||||
note="This is a note",
|
||||
telechat_date="",
|
||||
))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ah-rfc2141bis-urn")
|
||||
self.assertEquals(draft.idinternal.area_acronym, area)
|
||||
self.assertTrue(draft.idinternal.via_rfc_editor)
|
||||
self.assertEquals(draft.idinternal.job_owner, job_owner)
|
||||
self.assertEquals(draft.idinternal.note, "This is a note")
|
||||
self.assertTrue(not draft.idinternal.agenda)
|
||||
self.assertEquals(draft.idinternal.comments().count(), 2)
|
||||
self.assertTrue("Draft added" in draft.idinternal.comments()[0].comment_text)
|
||||
self.assertTrue("This is a note" in draft.idinternal.comments()[1].comment_text)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertTrue(draft.tags.filter(slug="via-rfc"))
|
||||
self.assertEquals(draft.ad, ad)
|
||||
self.assertEquals(draft.note, "This is a note")
|
||||
self.assertTrue(not draft.latest_event(Telechat, type="scheduled_for_telechat"))
|
||||
self.assertEquals(draft.event_set.count(), 4)
|
||||
self.assertEquals(draft.event_set.order_by('time', '-id')[0].type, "started_iesg_process")
|
||||
self.assertEquals(len(mail_outbox), mailbox_before)
|
||||
|
||||
|
||||
class ResurrectTestCase(django.test.TestCase):
|
||||
fixtures = ['base', 'draft']
|
||||
fixtures = ['names']
|
||||
|
||||
def test_request_resurrect(self):
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mip6-cn-ipsec")
|
||||
|
@ -450,7 +460,7 @@ class ResurrectTestCase(django.test.TestCase):
|
|||
|
||||
|
||||
# request resurrect
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
r = self.client.post(url, dict())
|
||||
|
@ -458,7 +468,7 @@ class ResurrectTestCase(django.test.TestCase):
|
|||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mip6-cn-ipsec")
|
||||
self.assertEquals(draft.idinternal.resurrect_requested_by, IESGLogin.objects.get(login_name=login_as))
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertTrue("Resurrection" in draft.idinternal.comments()[0].comment_text)
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
self.assertTrue("Resurrection" in mail_outbox[-1]['Subject'])
|
||||
|
@ -471,7 +481,7 @@ class ResurrectTestCase(django.test.TestCase):
|
|||
|
||||
url = urlreverse('doc_resurrect', kwargs=dict(name=draft.filename))
|
||||
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -480,7 +490,7 @@ class ResurrectTestCase(django.test.TestCase):
|
|||
self.assertEquals(len(q('form input[type=submit]')), 1)
|
||||
|
||||
# request resurrect
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
r = self.client.post(url, dict())
|
||||
|
@ -488,18 +498,18 @@ class ResurrectTestCase(django.test.TestCase):
|
|||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mip6-cn-ipsec")
|
||||
self.assertEquals(draft.idinternal.resurrect_requested_by, None)
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertTrue("completed" in draft.idinternal.comments()[0].comment_text)
|
||||
self.assertEquals(draft.status.status, "Active")
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
|
||||
class AddCommentTestCase(django.test.TestCase):
|
||||
fixtures = ['base', 'draft']
|
||||
fixtures = ['names']
|
||||
|
||||
def test_add_comment(self):
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
url = urlreverse('doc_add_comment', kwargs=dict(name=draft.filename))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -508,13 +518,13 @@ class AddCommentTestCase(django.test.TestCase):
|
|||
self.assertEquals(len(q('form textarea[name=comment]')), 1)
|
||||
|
||||
# request resurrect
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
r = self.client.post(url, dict(comment="This is a test."))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertTrue("This is a test." in draft.idinternal.comments()[0].comment_text)
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
self.assertTrue("updated" in mail_outbox[-1]['Subject'])
|
||||
|
@ -536,7 +546,7 @@ class EditPositionTestCase(django.test.TestCase):
|
|||
self.assertEquals(len(q('form textarea[name=comment_text]')), 1)
|
||||
|
||||
# vote
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
self.assertTrue(not Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley"))
|
||||
|
||||
r = self.client.post(url, dict(position="discuss",
|
||||
|
@ -550,11 +560,11 @@ class EditPositionTestCase(django.test.TestCase):
|
|||
self.assertTrue(pos.discuss)
|
||||
self.assertTrue(not (pos.yes or pos.noobj or pos.abstain or pos.recuse))
|
||||
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 3)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 3)
|
||||
self.assertTrue("New position" in draft.idinternal.comments()[2].comment_text)
|
||||
|
||||
# recast vote
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
r = self.client.post(url, dict(position="noobj"))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
|
@ -562,23 +572,23 @@ class EditPositionTestCase(django.test.TestCase):
|
|||
self.assertTrue(pos.noobj)
|
||||
self.assertTrue(not (pos.yes or pos.abstain or pos.recuse))
|
||||
self.assertTrue(pos.discuss == -1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertTrue("Position" in draft.idinternal.comments()[0].comment_text)
|
||||
|
||||
# clear vote
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
r = self.client.post(url, dict(position=""))
|
||||
self.assertEquals(r.status_code, 302)
|
||||
|
||||
pos = Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley")
|
||||
self.assertEquals(len(pos), 0)
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertTrue("Position" in draft.idinternal.comments()[0].comment_text)
|
||||
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"
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -587,7 +597,7 @@ class EditPositionTestCase(django.test.TestCase):
|
|||
self.assertTrue(len(q('form input[name=position]')) > 0)
|
||||
|
||||
# vote for rhousley
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
self.assertTrue(not Position.objects.filter(ballot=draft.idinternal.ballot, ad__login_name="rhousley"))
|
||||
|
||||
r = self.client.post(url, dict(position="discuss"))
|
||||
|
@ -679,7 +689,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))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -716,7 +726,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))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
mailbox_before = len(mail_outbox)
|
||||
|
||||
|
@ -733,7 +743,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))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -788,7 +798,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))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -828,7 +838,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))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -863,7 +873,7 @@ class MakeLastCallTestCase(django.test.TestCase):
|
|||
draft.save()
|
||||
|
||||
url = urlreverse('doc_make_last_call', kwargs=dict(name=draft.filename))
|
||||
login_testing_unauthorized(self, "klm", url)
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
|
@ -1082,13 +1092,13 @@ class ExpireLastCallTestCase(django.test.TestCase):
|
|||
self.assertEquals(len(drafts), 1)
|
||||
|
||||
mailbox_before = len(mail_outbox)
|
||||
history_before = draft.idinternal.comments().count()
|
||||
events_before = draft.idinternal.comments().count()
|
||||
|
||||
expire_last_call(drafts[0])
|
||||
|
||||
draft = InternetDraft.objects.get(filename="draft-ietf-mipshop-pfmipv6")
|
||||
self.assertEquals(draft.idinternal.cur_state.document_state_id, IDState.WAITING_FOR_WRITEUP)
|
||||
self.assertEquals(draft.idinternal.comments().count(), history_before + 1)
|
||||
self.assertEquals(draft.idinternal.comments().count(), events_before + 1)
|
||||
self.assertEquals(len(mail_outbox), mailbox_before + 1)
|
||||
self.assertTrue("Last Call Expired" in mail_outbox[-1]["Subject"])
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from django.conf import settings
|
||||
|
||||
from ietf.idtracker.models import InternetDraft, DocumentComment, BallotInfo, IESGLogin
|
||||
from ietf.idrfc.mails import *
|
||||
|
||||
|
@ -92,3 +94,57 @@ def update_telechat(request, idinternal, new_telechat_date, new_returning_item=N
|
|||
(new_telechat_date,
|
||||
idinternal.telechat_date))
|
||||
idinternal.telechat_date = new_telechat_date
|
||||
|
||||
def update_telechatREDESIGN(request, doc, by, new_telechat_date, new_returning_item=None):
|
||||
on_agenda = bool(new_telechat_date)
|
||||
|
||||
from doc.models import Telechat
|
||||
prev = doc.latest_event(Telechat, type="scheduled_for_telechat")
|
||||
prev_returning = bool(prev and prev.returning_item)
|
||||
prev_telechat = prev.telechat_date if prev else None
|
||||
prev_agenda = bool(prev_telechat)
|
||||
|
||||
returning_item_changed = bool(new_returning_item != None and new_returning_item != prev_returning)
|
||||
|
||||
if new_returning_item == None:
|
||||
returning = prev_returning
|
||||
else:
|
||||
returning = new_returning_item
|
||||
|
||||
if returning == prev_returning and new_telechat_date == prev_telechat:
|
||||
# fully updated, nothing to do
|
||||
return
|
||||
|
||||
# auto-update returning item
|
||||
if (not returning_item_changed and on_agenda and prev_agenda
|
||||
and new_telechat_date != prev_telechat):
|
||||
returning = True
|
||||
|
||||
e = Telechat()
|
||||
e.type = "scheduled_for_telechat"
|
||||
e.by = by
|
||||
e.doc = doc
|
||||
e.returning_item = returning
|
||||
e.telechat_date = new_telechat_date
|
||||
|
||||
if on_agenda != prev_agenda:
|
||||
if on_agenda:
|
||||
e.desc = "Placed on agenda for telechat - %s by %s" % (
|
||||
new_telechat_date, by.get_name())
|
||||
else:
|
||||
e.desc = "Removed from agenda for telechat by %s" % by.get_name()
|
||||
elif on_agenda and new_telechat_date != prev_telechat:
|
||||
e.desc = "Telechat date has been changed to <b>%s</b> from <b>%s</b> by %s" % (
|
||||
new_telechat_date, prev_telechat, by.get_name())
|
||||
else:
|
||||
# we didn't reschedule but flipped returning item bit - let's
|
||||
# just explain that
|
||||
if returning:
|
||||
e.desc = "Added as returning item on telechat by %s" % by.get_name()
|
||||
else:
|
||||
e.desc = "Removed as returning item on telechat by %s" % by.get_name()
|
||||
|
||||
e.save()
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
update_telechat = update_telechatREDESIGN
|
||||
|
|
|
@ -152,7 +152,7 @@ def _get_history(doc, versions):
|
|||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
versions = [] # clear versions
|
||||
event_holder = doc._draft if hasattr(doc, "_draft") else doc._rfcindex
|
||||
for e in event_holder.event_set.all().select_related('by').order_by('-time', '-id'):
|
||||
for e in event_holder.event_set.all().select_related('by').order_by('-time', 'id'):
|
||||
info = {}
|
||||
if e.type == "new_revision":
|
||||
filename = u"%s-%s" % (e.doc.name, e.newrevision.rev)
|
||||
|
|
|
@ -22,8 +22,8 @@ from ietf.idrfc.mails import *
|
|||
from ietf.idrfc.utils import *
|
||||
from ietf.idrfc.lastcall import request_last_call
|
||||
|
||||
from doc.models import Document, Event, save_document_in_history, DocHistory
|
||||
from name.models import IesgDocStateName, get_next_iesg_states
|
||||
from doc.models import Document, Event, Status, Telechat, save_document_in_history, DocHistory
|
||||
from name.models import IesgDocStateName, IntendedStdLevelName, DocInfoTagName, get_next_iesg_states
|
||||
|
||||
class ChangeStateForm(forms.Form):
|
||||
state = forms.ModelChoiceField(IDState.objects.all(), empty_label=None, required=True)
|
||||
|
@ -90,7 +90,7 @@ def change_stateREDESIGN(request, name):
|
|||
"""Change state of Internet Draft, notifying parties as necessary
|
||||
and logging the change as a comment."""
|
||||
doc = get_object_or_404(Document, docalias__name=name)
|
||||
if not doc.latest_event(type="started_iesg_process") or doc.state_id == "expired":
|
||||
if (not doc.latest_event(type="started_iesg_process")) or doc.state_id == "expired":
|
||||
raise Http404()
|
||||
|
||||
login = request.user.get_profile().email()
|
||||
|
@ -379,6 +379,234 @@ def edit_info(request, name):
|
|||
login=login),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
class NameFromEmailModelChoiceField(forms.ModelChoiceField):
|
||||
def label_from_instance(self, obj):
|
||||
return obj.get_name()
|
||||
|
||||
class EditInfoFormREDESIGN(forms.Form):
|
||||
intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.all(), empty_label=None, required=True)
|
||||
status_date = forms.DateField(required=False, help_text="Format is YYYY-MM-DD")
|
||||
via_rfc_editor = forms.BooleanField(required=False, label="Via IRTF or RFC Editor")
|
||||
ad = NameFromEmailModelChoiceField(Email.objects.filter(role__name__in=("ad", "ex-ad")).order_by('role__name', 'person__name'), label="Responsible AD", empty_label=None, required=True)
|
||||
notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False)
|
||||
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False)
|
||||
telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False)
|
||||
returning_item = forms.BooleanField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
old_ads = kwargs.pop('old_ads')
|
||||
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
# fix up ad field
|
||||
choices = self.fields['ad'].choices
|
||||
ex_ads = dict((e.pk, e) for e in Email.objects.filter(role__name="ex-ad"))
|
||||
if old_ads:
|
||||
# separate active ADs from inactive
|
||||
for i, t in enumerate(choices):
|
||||
if t[0] in ex_ads:
|
||||
choices.insert(i, ("", "----------------"))
|
||||
break
|
||||
else:
|
||||
# remove old ones
|
||||
self.fields['ad'].choices = [t for t in choices if t[0] not in ex_ads]
|
||||
|
||||
# telechat choices
|
||||
dates = TelechatDates.objects.all()[0].dates()
|
||||
init = kwargs['initial']['telechat_date']
|
||||
if init and init not in dates:
|
||||
dates.insert(0, init)
|
||||
|
||||
choices = [("", "(not on agenda)")]
|
||||
for d in dates:
|
||||
choices.append((d, d.strftime("%Y-%m-%d")))
|
||||
|
||||
self.fields['telechat_date'].choices = choices
|
||||
|
||||
# returning item is rendered non-standard
|
||||
self.standard_fields = [x for x in self.visible_fields() if x.name not in ('returning_item',)]
|
||||
|
||||
def clean_status_date(self):
|
||||
d = self.cleaned_data['status_date']
|
||||
if d:
|
||||
if d < date.today():
|
||||
raise forms.ValidationError("Date must not be in the past.")
|
||||
if d >= date.today() + timedelta(days=365 * 2):
|
||||
raise forms.ValidationError("Date must be within two years.")
|
||||
|
||||
return d
|
||||
|
||||
def clean_note(self):
|
||||
# note is stored munged in the database
|
||||
return self.cleaned_data['note'].replace('\n', '<br>').replace('\r', '').replace(' ', ' ')
|
||||
|
||||
|
||||
def get_initial_notify(doc):
|
||||
# set change state notice to something sensible
|
||||
receivers = []
|
||||
if doc.group.type_id == "individ":
|
||||
for a in doc.authors.all():
|
||||
receivers.append(e.address)
|
||||
else:
|
||||
receivers.append("%s-chairs@%s" % (doc.group.acronym, settings.TOOLS_SERVER))
|
||||
for editor in Email.objects.filter(role__name="wgeditor", role__group=doc.group):
|
||||
receivers.append(e.address)
|
||||
|
||||
receivers.append("%s@%s" % (doc.name, settings.TOOLS_SERVER))
|
||||
return ", ".join(receivers)
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def edit_infoREDESIGN(request, name):
|
||||
"""Edit various Internet Draft attributes, notifying parties as
|
||||
necessary and logging changes as document events."""
|
||||
doc = get_object_or_404(Document, name=name)
|
||||
if doc.state_id == "expired":
|
||||
raise Http404()
|
||||
|
||||
login = request.user.get_profile().email()
|
||||
|
||||
new_document = False
|
||||
if not doc.iesg_state: # FIXME: should probably get this as argument to view
|
||||
new_document = True
|
||||
doc.iesg_state = IesgDocStateName.objects.get(slug="pub-req")
|
||||
doc.notify = get_initial_notify(doc)
|
||||
|
||||
e = doc.latest_event(Telechat, type="scheduled_for_telechat")
|
||||
initial_telechat_date = e.telechat_date if e else None
|
||||
initial_returning_item = bool(e and e.returning_item)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = EditInfoForm(request.POST,
|
||||
old_ads=False,
|
||||
initial=dict(telechat_date=initial_telechat_date))
|
||||
if form.is_valid():
|
||||
save_document_in_history(doc)
|
||||
|
||||
r = form.cleaned_data
|
||||
if new_document:
|
||||
# fix so Django doesn't barf in the diff below because these
|
||||
# fields can't be NULL
|
||||
doc.ad = r['ad']
|
||||
|
||||
replaces = Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces")
|
||||
if replaces:
|
||||
# this should perhaps be somewhere else, e.g. the
|
||||
# place where the replace relationship is established
|
||||
e = Event()
|
||||
e.type = "added_comment"
|
||||
e.by = Email.objects.get(address="(System)")
|
||||
e.doc = doc
|
||||
e.desc = "Earlier history may be found in the Comment Log for <a href=\"%s\">%s</a>" % (replaces[0], replaces[0].get_absolute_url())
|
||||
e.save()
|
||||
|
||||
e = Event()
|
||||
e.type = "started_iesg_process"
|
||||
e.by = login
|
||||
e.doc = doc
|
||||
e.desc = "IESG process started in state <b>%s</b>" % doc.iesg_state.name
|
||||
e.save()
|
||||
|
||||
orig_ad = doc.ad
|
||||
|
||||
changes = []
|
||||
|
||||
def desc(attr, new, old):
|
||||
entry = "%(attr)s has been changed to <b>%(new)s</b> from <b>%(old)s</b>"
|
||||
if new_document:
|
||||
entry = "%(attr)s has been changed to <b>%(new)s</b>"
|
||||
|
||||
return entry % dict(attr=attr, new=new, old=old)
|
||||
|
||||
def diff(attr, name):
|
||||
v = getattr(doc, attr)
|
||||
if r[attr] != v:
|
||||
changes.append(desc(name, r[attr], v))
|
||||
setattr(doc, attr, r[attr])
|
||||
|
||||
# update the attributes, keeping track of what we're doing
|
||||
diff('intended_std_level', "Intended Status")
|
||||
diff('ad', "Responsible AD")
|
||||
diff('notify', "State Change Notice email list")
|
||||
|
||||
if r['note'] != doc.note:
|
||||
if not r['note']:
|
||||
if doc.note:
|
||||
changes.append("Note field has been cleared")
|
||||
else:
|
||||
if doc.note:
|
||||
changes.append("Note changed to '%s'" % r['note'])
|
||||
else:
|
||||
changes.append("Note added '%s'" % r['note'])
|
||||
|
||||
doc.note = r['note']
|
||||
|
||||
for c in changes:
|
||||
e = Event()
|
||||
e.type = "changed_document"
|
||||
e.by = login
|
||||
e.doc = doc
|
||||
e.desc = c + " by %s" % login.get_name()
|
||||
e.save()
|
||||
|
||||
update_telechat(request, doc, login,
|
||||
r['telechat_date'], r['returning_item'])
|
||||
|
||||
e = doc.latest_event(Status, type="changed_status_date")
|
||||
status_date = e.date if e else None
|
||||
if r["status_date"] != status_date:
|
||||
e = Status()
|
||||
e.type ="changed_status_date"
|
||||
e.by = login
|
||||
e.doc = doc
|
||||
d = desc("Status date", r["status_date"], status_date)
|
||||
changes.append(d)
|
||||
e.desc = d + " by %s" % login.get_name()
|
||||
e.date = r["status_date"]
|
||||
e.save()
|
||||
|
||||
if in_group(request.user, 'Secretariat'):
|
||||
via_rfc = DocInfoTagName.objects.get(slug="via-rfc")
|
||||
if r['via_rfc_editor']:
|
||||
doc.tags.add(via_rfc)
|
||||
else:
|
||||
doc.tags.remove(via_rfc)
|
||||
|
||||
doc.time = datetime.datetime.now()
|
||||
|
||||
if changes and not new_document:
|
||||
email_owner(request, doc, orig_ad, login, "\n".join(changes))
|
||||
|
||||
doc.save()
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
else:
|
||||
e = doc.latest_event(Status)
|
||||
status = e.date if e else None
|
||||
init = dict(intended_std_level=doc.intended_std_level,
|
||||
status_date=status,
|
||||
ad=doc.ad,
|
||||
notify=doc.notify,
|
||||
note=dehtmlify_textarea_text(doc.note),
|
||||
telechat_date=initial_telechat_date,
|
||||
returning_item=initial_returning_item,
|
||||
)
|
||||
|
||||
form = EditInfoForm(old_ads=False, initial=init)
|
||||
|
||||
if not in_group(request.user, 'Secretariat'):
|
||||
# filter out Via RFC Editor
|
||||
form.standard_fields = [x for x in form.standard_fields if x.name != "via_rfc_editor"]
|
||||
|
||||
return render_to_response('idrfc/edit_infoREDESIGN.html',
|
||||
dict(doc=doc,
|
||||
form=form,
|
||||
user=request.user,
|
||||
login=login),
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
|
||||
EditInfoForm = EditInfoFormREDESIGN
|
||||
edit_info = edit_infoREDESIGN
|
||||
|
||||
|
||||
@group_required('Area_Director','Secretariat')
|
||||
def request_resurrect(request, name):
|
||||
|
|
47
ietf/templates/idrfc/edit_infoREDESIGN.html
Normal file
47
ietf/templates/idrfc/edit_infoREDESIGN.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Edit info on {{ doc }}{% endblock %}
|
||||
|
||||
{% block morecss %}
|
||||
form.edit-info #id_state_change_notice_to {
|
||||
width: 600px;
|
||||
}
|
||||
form.edit-info #id_note {
|
||||
width: 600px;
|
||||
height: 150px;
|
||||
}
|
||||
form.edit-info .actions {
|
||||
padding-top: 20px;
|
||||
}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% load ietf_filters %}
|
||||
<h1>Edit info on {{ doc }}</h1>
|
||||
|
||||
<form class="edit-info" action="" method="POST">
|
||||
<table>
|
||||
{% for field in form.standard_fields %}
|
||||
<tr>
|
||||
<th>{{ field.label_tag }}:</th>
|
||||
<td>{{ field }}
|
||||
{% ifequal field.name "telechat_date" %}{{ form.returning_item }} {{ form.returning_item.label_tag }} {{ form.returning_item.errors }}{% endifequal %}
|
||||
{% ifequal field.name "ad" %}
|
||||
{% if user|in_group:"Area_Director" %}
|
||||
<label><input type="checkbox" name="ad" value="{{ login.pk }}" /> Assign to me</label>
|
||||
{% endif %}
|
||||
{% endifequal %}
|
||||
{% if field.help_text %}<div class="help">{{ field.help_text }}</div>{% endif %}
|
||||
{{ field.errors }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="actions">
|
||||
<a href="{{ doc.get_absolute_url }}">Back</a>
|
||||
<input type="submit" value="Save"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -28,6 +28,7 @@ admin.site.register(SendQueue, SendQueueAdmin)
|
|||
# events
|
||||
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
list_display = ["doc", "type", "by", "time"]
|
||||
raw_id_fields = ["doc", "by"]
|
||||
admin.site.register(Event, EventAdmin)
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ class Event(models.Model):
|
|||
return u"%s %s at %s" % (self.by.get_name(), self.get_type_display().lower(), self.time)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-time']
|
||||
ordering = ['-time', 'id']
|
||||
|
||||
class Message(Event):
|
||||
subj = models.CharField(max_length=255)
|
||||
|
|
|
@ -6,7 +6,7 @@ from redesign.person.models import Email
|
|||
|
||||
class Group(models.Model):
|
||||
name = models.CharField(max_length=80)
|
||||
acronym = models.CharField(max_length=16)
|
||||
acronym = models.CharField(max_length=16, db_index=True)
|
||||
state = models.ForeignKey(GroupStateName, null=True)
|
||||
type = models.ForeignKey(GroupTypeName, null=True)
|
||||
charter = models.OneToOneField('doc.Document', related_name='chartered_group', blank=True, null=True)
|
||||
|
@ -49,5 +49,5 @@ class Role(models.Model):
|
|||
email = models.ForeignKey(Email)
|
||||
auth = models.CharField(max_length=255, blank=True)
|
||||
def __unicode__(self):
|
||||
return u"%s is %s in %s" % (self.email.get_name(), self.name.name, self.grop.acronym)
|
||||
return u"%s is %s in %s" % (self.email.get_name(), self.name.name, self.group.acronym)
|
||||
|
||||
|
|
Loading…
Reference in a new issue