Merged in [8293] from rjsparks@nostrum.com:\n XXX: Should what is now captured in the list of STATUSCHANGE_RELATIONS instead be captured in the database in name_docrelationshipname?

Refactored editing the notify field to remove redundant code.
Changed the default notification list to include .all for documents, and the wg list for wg documents.
Allowed recalculating the notification list for all document types.
Improved the calculated notification list value for charters, conflict-reviews, and status-changes.
Adds shepherds to the notification list when they are assigned to a document.
Adds the working group email list to the notification list when a document is adopted.
Fixes #1438
 - Legacy-Id: 8385
Note: SVN reference [8293] has been migrated to Git commit 640c5eb52ace8bb6d2c1b3ca6c14ef10ad0f324f
This commit is contained in:
Henrik Levkowetz 2014-10-12 17:32:11 +00:00
parent 6f7a2cceb6
commit d4e5f070af
20 changed files with 216 additions and 283 deletions

View file

@ -34,4 +34,8 @@ class AdForm(forms.Form):
self.fields['ad'].choices = list(choices) + [("", "-------"), (ad_pk, Person.objects.get(pk=ad_pk).plain_name())]
class NotifyForm(forms.Form):
notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False)
notify = forms.CharField(max_length=255, help_text="List of email addresses to receive state notifications, separated by comma", label="Notification list", required=False)
def clean_notify(self):
addrspecs = [x.strip() for x in self.cleaned_data["notify"].split(',')]
return ', '.join(addrspecs)

View file

@ -178,6 +178,8 @@ class DocumentInfo(models.Model):
class Meta:
abstract = True
STATUSCHANGE_RELATIONS = ('tops','tois','tohist','toinf','tobcp','toexp')
class RelatedDocument(models.Model):
source = models.ForeignKey('Document')
target = models.ForeignKey('DocAlias')

View file

@ -181,11 +181,23 @@ class EditCharterTests(TestCase):
# post
self.assertTrue(not charter.notify)
r = self.client.post(url, dict(notify="someone@example.com, someoneelse@example.com"))
newlist = "someone@example.com, someoneelse@example.com"
r = self.client.post(url, dict(notify=newlist,save_addresses="1"))
self.assertEqual(r.status_code, 302)
charter = Document.objects.get(name=charter.name)
self.assertEqual(charter.notify, "someone@example.com, someoneelse@example.com")
self.assertEqual(charter.notify, newlist)
# Ask the form to regenerate the list
r = self.client.post(url,dict(regenerate_addresses="1"))
self.assertEqual(r.status_code,200)
charter= Document.objects.get(name=charter.name)
# Regenerate does not save!
self.assertEqual(charter.notify,newlist)
q = PyQuery(r.content)
formlist = q('form input[name=notify]')[0].value
self.assertTrue('marschairman@ietf.org' in formlist)
self.assertFalse('someone@example.com' in formlist)
def test_edit_ad(self):
make_test_data()

View file

@ -176,12 +176,22 @@ class ConflictReviewTests(TestCase):
# change notice list
newlist = '"Foo Bar" <foo@bar.baz.com>'
r = self.client.post(url,dict(notify=newlist))
r = self.client.post(url,dict(notify=newlist,save_addresses="1"))
self.assertEqual(r.status_code,302)
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
self.assertEqual(doc.notify,newlist)
self.assertTrue(doc.latest_event(DocEvent,type="added_comment").desc.startswith('Notification list changed'))
# Ask the form to regenerate the list
r = self.client.post(url,dict(regenerate_addresses="1"))
self.assertEqual(r.status_code,200)
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')
# Regenerate does not save!
self.assertEqual(doc.notify,newlist)
q = PyQuery(r.content)
self.assertTrue('draft-imaginary-irtf-submission@tools.ietf.org' in q('form input[name=notify]')[0].value)
self.assertTrue('irtf-chair@ietf.org' in q('form input[name=notify]')[0].value)
self.assertTrue('foo@bar.baz.com' not in q('form input[name=notify]')[0].value)
def test_edit_ad(self):
doc = Document.objects.get(name='conflict-review-imaginary-irtf-submission')

View file

@ -841,7 +841,9 @@ class IndividualInfoFormsTests(TestCase):
self.assertEqual(r.status_code,302)
self.doc = Document.objects.get(name=self.docname)
self.assertEqual(self.doc.shepherd,plain)
self.assertTrue(self.doc.latest_event(DocEvent,type="added_comment").desc.startswith('Document shepherd changed to Plain Man'))
comments = '::'.join([x.desc for x in self.doc.docevent_set.filter(time=self.doc.time,type="added_comment")])
self.assertTrue('Document shepherd changed to Plain Man' in comments)
self.assertTrue('Notification list changed' in comments)
ad = Person.objects.get(name='Aread Irector')
two_answers = "%s,%s" % (plain_email, ad.email_set.all()[0])
@ -1021,16 +1023,19 @@ class AdoptDraftTests(TestCase):
# adopt in mars WG
mailbox_before = len(outbox)
events_before = draft.docevent_set.count()
mars = Group.objects.get(acronym="mars")
r = self.client.post(url,
dict(comment="some comment",
group=Group.objects.get(acronym="mars").pk,
group=mars.pk,
weeks="10"))
self.assertEqual(r.status_code, 302)
draft = Document.objects.get(pk=draft.pk)
self.assertEqual(draft.group.acronym, "mars")
self.assertEqual(draft.stream_id, "ietf")
self.assertEqual(draft.docevent_set.count() - events_before, 4)
self.assertEqual(draft.docevent_set.count() - events_before, 5)
self.assertTrue(mars.list_email in draft.notify)
self.assertTrue('draft-ietf-mars-test.all@tools.ietf.org' in draft.notify)
self.assertEqual(len(outbox), mailbox_before + 1)
self.assertTrue("state changed" in outbox[-1]["Subject"].lower())
self.assertTrue("marschairman@ietf.org" in unicode(outbox[-1]))

View file

@ -139,12 +139,28 @@ class StatusChangeTests(TestCase):
# change notice list
newlist = '"Foo Bar" <foo@bar.baz.com>'
r = self.client.post(url,dict(notify=newlist))
r = self.client.post(url,dict(notify=newlist,save_addresses="1"))
self.assertEqual(r.status_code,302)
doc = Document.objects.get(name='status-change-imaginary-mid-review')
self.assertEqual(doc.notify,newlist)
self.assertTrue(doc.latest_event(DocEvent,type="added_comment").desc.startswith('Notification list changed'))
# Some additional setup so there's something to put in a generated notify list
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')
# Ask the form to regenerate the list
r = self.client.post(url,dict(regenerate_addresses="1"))
self.assertEqual(r.status_code,200)
doc = Document.objects.get(name='status-change-imaginary-mid-review')
# Regenerate does not save!
self.assertEqual(doc.notify,newlist)
q = PyQuery(r.content)
formlist = q('form input[name=notify]')[0].value
self.assertTrue('draft-ietf-random-thing@ietf.org' in formlist)
self.assertTrue('draft-ietf-random-otherthing@ietf.org' in formlist)
self.assertFalse('foo@bar.baz.com' in formlist)
def test_edit_title(self):
doc = Document.objects.get(name='status-change-imaginary-mid-review')
url = urlreverse('status_change_title',kwargs=dict(name=doc.name))

View file

@ -74,7 +74,7 @@ urlpatterns = patterns('',
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/stream/$', views_draft.change_stream, name='doc_change_stream'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/replaces/$', views_draft.replaces, name='doc_change_replaces'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/notify/$', views_draft.edit_notices, name='doc_change_notify'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/notify/$', views_doc.edit_notify, name='doc_change_notify'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/status/$', views_draft.change_intention, name='doc_change_intended_status'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/telechat/$', views_doc.telechat_date, name='doc_change_telechat_date'),
url(r'^(?P<name>[A-Za-z0-9._+-]+)/edit/iesgnote/$', views_draft.edit_iesg_note, name='doc_change_iesg_note'),

View file

@ -6,7 +6,7 @@ urlpatterns = patterns('',
url(r'^state/$', "ietf.doc.views_charter.change_state", name='charter_change_state'),
url(r'^(?P<option>initcharter|recharter|abandon)/$', "ietf.doc.views_charter.change_state", name='charter_startstop_process'),
url(r'^telechat/$', "ietf.doc.views_doc.telechat_date", name='charter_telechat_date'),
url(r'^notify/$', "ietf.doc.views_charter.edit_notify", name='charter_edit_notify'),
url(r'^notify/$', "ietf.doc.views_doc.edit_notify", name='charter_edit_notify'),
url(r'^ad/$', "ietf.doc.views_charter.edit_ad", name='charter_edit_ad'),
url(r'^(?P<ann>action|review)/$', "ietf.doc.views_charter.announcement_text", name="charter_edit_announcement"),
url(r'^ballotwriteupnotes/$', "ietf.doc.views_charter.ballot_writeupnotes"),

View file

@ -3,7 +3,6 @@ from django.conf.urls import patterns, url
urlpatterns = patterns('ietf.doc.views_conflict_review',
url(r'^state/$', "change_state", name='conflict_review_change_state'),
url(r'^submit/$', "submit", name='conflict_review_submit'),
url(r'^notices/$', "edit_notices", name='conflict_review_notices'),
url(r'^ad/$', "edit_ad", name='conflict_review_ad'),
url(r'^approve/$', "approve", name='conflict_review_approve'),
url(r'^start_conflict_review/$', "start_review", name='conflict_review_start'),
@ -11,6 +10,7 @@ urlpatterns = patterns('ietf.doc.views_conflict_review',
urlpatterns += patterns('ietf.doc.views_doc',
url(r'^telechat/$', "telechat_date", name='conflict_review_telechat_date'),
url(r'^notices/$', "edit_notify", name='conflict_review_notices'),
)

View file

@ -3,7 +3,6 @@ from django.conf.urls import patterns, url
urlpatterns = patterns('ietf.doc.views_status_change',
url(r'^state/$', "change_state", name='status_change_change_state'),
url(r'^submit/$', "submit", name='status_change_submit'),
url(r'^notices/$', "edit_notices", name='status_change_notices'),
url(r'^ad/$', "edit_ad", name='status_change_ad'),
url(r'^title/$', "edit_title", name='status_change_title'),
url(r'^approve/$', "approve", name='status_change_approve'),
@ -13,6 +12,7 @@ urlpatterns = patterns('ietf.doc.views_status_change',
urlpatterns += patterns('ietf.doc.views_doc',
url(r'^telechat/$', "telechat_date", name='status_change_telechat_date'),
url(r'^notices/$', "edit_notify", name='status_change_notices'),
)

View file

@ -5,16 +5,19 @@ import math
import datetime
from django.conf import settings
from django.db.models import Q
from django.db.models.query import EmptyQuerySet
from django.forms import ValidationError
from django.utils.html import strip_tags
from django.utils.html import strip_tags, escape
from ietf.utils import markup_txt
from ietf.doc.models import Document, DocHistory
from ietf.doc.models import DocAlias, RelatedDocument, BallotType, DocReminder
from ietf.doc.models import DocEvent, BallotDocEvent, NewRevisionDocEvent, StateDocEvent
from ietf.doc.models import save_document_in_history, STATUSCHANGE_RELATIONS
from ietf.name.models import DocReminderTypeName, DocRelationshipName
from ietf.group.models import Role
from ietf.person.models import Email
from ietf.ietfauth.utils import has_role
from ietf.utils import draft
from ietf.utils.mail import send_mail
@ -333,6 +336,29 @@ def has_same_ballot(doc, date1, date2=datetime.date.today()):
ballot2 = doc.latest_event(BallotDocEvent,type='created_ballot',time__lt=date2+datetime.timedelta(days=1))
return ballot1==ballot2
def make_notify_changed_event(request, doc, by, new_notify, time=None):
# FOR REVIEW: This preserves the behavior from when
# drafts and charters had separate edit_notify
# functions. If it should be unified, there should
# also be a migration function cause historic
# events to match
if doc.type.slug=='charter':
event_type = 'changed_document'
save_document_in_history(doc)
else:
event_type = 'added_comment'
e = DocEvent(type=event_type, doc=doc, by=by)
e.desc = "Notification list changed to %s" % (escape(new_notify) or "none")
if doc.notify:
e.desc += " from %s" % escape(doc.notify)
if time:
e.time = time
e.save()
return e
def update_telechat(request, doc, by, new_telechat_date, new_returning_item=None):
from ietf.doc.models import TelechatDocEvent
@ -447,3 +473,47 @@ def check_common_doc_name_rules(name):
if errors:
raise ValidationError(errors)
def get_initial_notify(doc,extra=None):
# set change state notice to something sensible
receivers = []
if doc.type.slug=='draft':
if doc.group.type_id in ("individ", "area"):
for a in doc.authors.all():
receivers.append(a.address)
else:
receivers.append("%s-chairs@%s" % (doc.group.acronym, settings.TOOLS_SERVER))
for editor in Email.objects.filter(role__name="editor", role__group=doc.group):
receivers.append(editor.address)
if doc.group.list_email:
receivers.append(doc.group.list_email)
receivers.append("%s.all@%s" % (doc.name, settings.TOOLS_SERVER))
elif doc.type.slug=='charter':
receivers.extend([role.person.formatted_email() for role in doc.group.role_set.filter(name__slug__in=['ad','chair','secr','techadv'])])
else:
pass
for relation in doc.relateddocument_set.filter(Q(relationship='conflrev')|Q(relationship__in=STATUSCHANGE_RELATIONS)):
if relation.relationship.slug=='conflrev':
doc_to_review = relation.target.document
receivers.extend([x.person.formatted_email() for x in Role.objects.filter(group__acronym=doc_to_review.stream.slug,name='chair')])
receivers.append("%s@%s" % (doc_to_review.name, settings.TOOLS_SERVER))
elif relation.relationship.slug in STATUSCHANGE_RELATIONS:
affected_doc = relation.target.document
if affected_doc.notify:
receivers.extend(affected_doc.notify.split(','))
if doc.shepherd:
receivers.append(doc.shepherd.email_address())
if extra:
if isinstance(extra,basestring):
extra = extra.split(', ')
receivers.extend(extra)
return ", ".join(set([x.strip() for x in receivers]))

View file

@ -5,7 +5,6 @@ from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.core.urlresolvers import reverse as urlreverse
from django.template import RequestContext
from django import forms
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.conf import settings
from django.contrib import messages
@ -225,48 +224,6 @@ def change_state(request, name, option=None):
),
context_instance=RequestContext(request))
class NotifyForm(forms.Form):
notify = forms.CharField(max_length=255, help_text="List of email addresses to receive state notifications, separated by comma", label="Notification list", required=False)
def clean_notify(self):
return self.cleaned_data["notify"].strip()
@role_required("Area Director", "Secretariat")
def edit_notify(request, name):
doc = get_object_or_404(Document, type="charter", name=name)
login = request.user.person
init = {'notify': doc.notify}
if request.method == "POST":
form = NotifyForm(request.POST, initial=init)
if form.is_valid():
n = form.cleaned_data["notify"]
if n != doc.notify:
save_document_in_history(doc)
e = DocEvent(doc=doc, by=login)
e.desc = "Notification list changed to %s" % (escape(n) or "none")
if doc.notify:
e.desc += " from %s" % escape(doc.notify)
e.type = "changed_document"
e.save()
doc.notify = n
doc.time = e.time
doc.save()
return redirect("doc_view", name=doc.name)
else:
form = NotifyForm(initial=init)
return render_to_response('doc/charter/edit_notify.html',
dict(doc=doc,
form=form,
user=request.user,
login=login),
context_instance=RequestContext(request))
class AdForm(forms.Form):
ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'),
label="Responsible AD", empty_label="(None)", required=True)

View file

@ -13,7 +13,7 @@ from ietf.doc.models import ( BallotDocEvent, BallotPositionDocEvent, DocAlias,
from ietf.doc.utils import ( add_state_change_event, close_open_ballots,
create_ballot_if_not_open, get_document_content, update_telechat )
from ietf.doc.mails import email_iana
from ietf.doc.forms import AdForm, NotifyForm
from ietf.doc.forms import AdForm
from ietf.group.models import Role, Group
from ietf.iesg.models import TelechatDate
from ietf.ietfauth.utils import has_role, role_required, is_authorized_in_doc_stream
@ -205,41 +205,6 @@ def submit(request, name):
},
context_instance=RequestContext(request))
@role_required("Area Director", "Secretariat")
def edit_notices(request, name):
"""Change the set of email addresses document change notificaitions go to."""
review = get_object_or_404(Document, type="conflrev", name=name)
if request.method == 'POST':
form = NotifyForm(request.POST)
if form.is_valid():
review.notify = form.cleaned_data['notify']
review.save()
login = request.user.person
c = DocEvent(type="added_comment", doc=review, by=login)
c.desc = "Notification list changed to : "+review.notify
c.save()
return redirect('doc_view', name=review.name)
else:
init = { "notify" : review.notify }
form = NotifyForm(initial=init)
conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document
titletext = 'the conflict review of %s-%s' % (conflictdoc.canonical_name(),conflictdoc.rev)
return render_to_response('doc/notify.html',
{'form': form,
'doc': review,
'titletext' : titletext
},
context_instance = RequestContext(request))
@role_required("Area Director", "Secretariat")
def edit_ad(request, name):
"""Change the shepherding Area Director for this review."""

View file

@ -43,20 +43,20 @@ from django import forms
from ietf.doc.models import ( Document, DocAlias, DocHistory, DocEvent, BallotDocEvent,
ConsensusDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent,
IESG_BALLOT_ACTIVE_STATES)
IESG_BALLOT_ACTIVE_STATES, STATUSCHANGE_RELATIONS )
from ietf.doc.utils import ( add_links_in_new_revision_events, augment_events_with_revision,
can_adopt_draft, get_chartering_type, get_document_content, get_tags_for_stream_id,
needed_ballot_positions, nice_consensus, prettify_std_name, update_telechat, has_same_ballot)
needed_ballot_positions, nice_consensus, prettify_std_name, update_telechat, has_same_ballot,
get_initial_notify, make_notify_changed_event )
from ietf.community.models import CommunityList
from ietf.doc.mails import email_ad
from ietf.doc.views_status_change import RELATION_SLUGS as status_change_relationships
from ietf.group.models import Role
from ietf.group.utils import can_manage_group_type, can_manage_materials
from ietf.ietfauth.utils import has_role, is_authorized_in_doc_stream, user_is_person, role_required
from ietf.name.models import StreamName, BallotPositionName
from ietf.person.models import Email
from ietf.utils.history import find_history_active_at
from ietf.doc.forms import TelechatForm
from ietf.doc.forms import TelechatForm, NotifyForm
def render_document_top(request, doc, tab, name):
tabs = []
@ -289,7 +289,7 @@ def document_main(request, name, rev=None):
# conflict reviews
conflict_reviews = [d.document.name for d in doc.related_that("conflrev")]
status_change_docs = doc.related_that(status_change_relationships)
status_change_docs = doc.related_that(STATUSCHANGE_RELATIONS)
status_changes = [ rel.document for rel in status_change_docs if rel.document.get_state_slug() in ('appr-sent','appr-pend')]
proposed_status_changes = [ rel.document for rel in status_change_docs if rel.document.get_state_slug() in ('needshep','adrev','iesgeval','defer','appr-pr')]
@ -897,3 +897,49 @@ def telechat_date(request, name):
prompts=prompts,
login=login),
context_instance=RequestContext(request))
@role_required('Area Director', 'Secretariat')
def edit_notify(request, name):
"""Change the set of email addresses document change notificaitions go to."""
login = request.user.person
doc = get_object_or_404(Document, name=name)
init = { "notify" : doc.notify }
if request.method == 'POST':
if "save_addresses" in request.POST:
form = NotifyForm(request.POST)
if form.is_valid():
new_notify = form.cleaned_data['notify']
if set(new_notify.split(',')) != set(doc.notify.split(',')):
e = make_notify_changed_event(request, doc, login, new_notify)
doc.notify = new_notify
doc.time = e.time
doc.save()
return redirect('doc_view', name=doc.name)
elif "regenerate_addresses" in request.POST:
init = { "notify" : get_initial_notify(doc) }
form = NotifyForm(initial=init)
# Protect from handcrufted POST
else:
form = NotifyForm(initial=init)
else:
init = { "notify" : doc.notify }
form = NotifyForm(initial=init)
if doc.type.slug=='conflrev':
conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document
titletext = 'the conflict review of %s' % conflictdoc.canonical_name()
else:
titletext = '%s' % doc.canonical_name()
return render_to_response('doc/edit_notify.html',
{'form': form,
'doc': doc,
'titletext': titletext,
},
context_instance = RequestContext(request))

View file

@ -21,7 +21,7 @@ from ietf.doc.mails import ( email_ad, email_pulled_from_rfc_queue, email_resurr
generate_publication_request, html_to_text )
from ietf.doc.utils import ( add_state_change_event, can_adopt_draft,
get_tags_for_stream_id, nice_consensus,
update_reminder, update_telechat )
update_reminder, update_telechat, make_notify_changed_event, get_initial_notify )
from ietf.doc.lastcall import request_last_call
from ietf.group.models import Group, Role
from ietf.iesg.models import TelechatDate
@ -30,7 +30,7 @@ from ietf.ietfauth.utils import role_required
from ietf.message.models import Message
from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName
from ietf.person.forms import EmailsField
from ietf.person.models import Person, Email
from ietf.person.models import Person
from ietf.secr.lib.template import jsonapi
from ietf.utils.mail import send_mail, send_mail_message
from ietf.utils.textupload import get_cleaned_text_file_content
@ -501,21 +501,6 @@ class EditInfoForm(forms.Form):
def clean_note(self):
return self.cleaned_data['note'].replace('\r', '').strip()
def get_initial_notify(doc):
# set change state notice to something sensible
receivers = []
if doc.group.type_id in ("individ", "area"):
for a in doc.authors.all():
receivers.append(a.address)
else:
receivers.append("%s-chairs@%s" % (doc.group.acronym, settings.TOOLS_SERVER))
for editor in Email.objects.filter(role__name="editor", role__group=doc.group):
receivers.append(editor.address)
receivers.append("%s@%s" % (doc.name, settings.TOOLS_SERVER))
return ", ".join(receivers)
def to_iesg(request,name):
""" Submit an IETF stream document to the IESG for publication """
doc = get_object_or_404(Document, docalias__name=name, stream='ietf')
@ -831,52 +816,6 @@ def resurrect(request, name):
back_url=doc.get_absolute_url()),
context_instance=RequestContext(request))
class NotifyForm(forms.Form):
notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False)
@role_required('Area Director', 'Secretariat')
def edit_notices(request, name):
"""Change the set of email addresses document change notificaitions go to."""
doc = get_object_or_404(Document, type="draft", name=name)
if request.method == 'POST':
if "save_addresses" in request.POST:
form = NotifyForm(request.POST)
if form.is_valid():
doc.notify = form.cleaned_data['notify']
doc.save()
login = request.user.person
c = DocEvent(type="added_comment", doc=doc, by=login)
c.desc = "Notification list changed to : "+doc.notify
c.save()
return redirect('doc_view', name=doc.name)
elif "regenerate_addresses" in request.POST:
init = { "notify" : get_initial_notify(doc) }
form = NotifyForm(initial=init)
# Protect from handcrufted POST
else:
init = { "notify" : doc.notify }
form = NotifyForm(initial=init)
else:
init = { "notify" : doc.notify }
form = NotifyForm(initial=init)
return render_to_response('doc/draft/change_notify.html',
{'form': form,
'doc': doc,
},
context_instance = RequestContext(request))
class IESGNoteForm(forms.Form):
note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False)
@ -1028,13 +967,23 @@ def edit_shepherd(request, name):
doc.shepherd = form.cleaned_data['shepherd'][0].person
else:
doc.shepherd = None
doc.save()
login = request.user.person
c = DocEvent(type="added_comment", doc=doc, by=login)
c.desc = "Document shepherd changed to "+ (doc.shepherd.name if doc.shepherd else "(None)")
c.save()
if doc.shepherd.formatted_email() not in doc.notify:
addrs = doc.notify
if addrs:
addrs += ', '
addrs += doc.shepherd.formatted_email()
e = make_notify_changed_event(request, doc, login, addrs, c.time)
doc.notify = addrs
doc.time = c.time
doc.save()
return redirect('doc_view', name=doc.name)
else:
@ -1291,6 +1240,10 @@ def adopt_draft(request, name):
e.save()
doc.group = group
new_notify = get_initial_notify(doc,extra=doc.notify)
make_notify_changed_event(request, doc, by, new_notify, doc.time)
doc.notify = new_notify
doc.save()
comment = form.cleaned_data["comment"].strip()

View file

@ -10,8 +10,8 @@ from django.conf import settings
from ietf.doc.models import ( Document, DocAlias, State, DocEvent, BallotDocEvent,
BallotPositionDocEvent, NewRevisionDocEvent, WriteupDocEvent,
save_document_in_history )
from ietf.doc.forms import AdForm, NotifyForm
save_document_in_history, STATUSCHANGE_RELATIONS )
from ietf.doc.forms import AdForm
from ietf.doc.lastcall import request_last_call
from ietf.doc.utils import get_document_content, add_state_change_event, update_telechat, close_open_ballots, create_ballot_if_not_open
from ietf.doc.views_ballot import LastCallTextForm
@ -199,38 +199,6 @@ def submit(request, name):
},
context_instance=RequestContext(request))
@role_required("Area Director", "Secretariat")
def edit_notices(request, name):
"""Change the set of email addresses document change notificaitions go to."""
status_change = get_object_or_404(Document, type="statchg", name=name)
if request.method == 'POST':
form = NotifyForm(request.POST)
if form.is_valid():
status_change.notify = form.cleaned_data['notify']
status_change.save()
login = request.user.person
c = DocEvent(type="added_comment", doc=status_change, by=login)
c.desc = "Notification list changed to : "+status_change.notify
c.save()
return redirect('doc_view', name=status_change.name)
else:
init = { "notify" : status_change.notify }
form = NotifyForm(initial=init)
return render_to_response('doc/notify.html',
{'form': form,
'doc': status_change,
'titletext' : '%s-%s.txt' % (status_change.canonical_name(),status_change.rev)
},
context_instance = RequestContext(request))
class ChangeTitleForm(forms.Form):
title = forms.CharField(max_length=255, label="Title", required=True)
@ -390,7 +358,7 @@ def approve(request, name):
c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
c.save()
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
for rel in status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS):
# Add a document event to each target
c = DocEvent(type="added_comment", doc=rel.target.document, by=login)
c.desc = "New status of %s approved by the IESG\n%s%s" % (newstatus(rel), settings.IDTRACKER_BASE_URL,reverse('doc_view', kwargs={'name': status_change.name}))
@ -401,7 +369,7 @@ def approve(request, name):
else:
init = []
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
for rel in status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS):
init.append({"announcement_text" : default_approval_text(status_change,rel),
"label": "Announcement text for %s to %s"%(rel.target.document.canonical_name(),newstatus(rel)),
})
@ -416,8 +384,6 @@ def approve(request, name):
),
context_instance=RequestContext(request))
RELATION_SLUGS = ('tops','tois','tohist','toinf','tobcp','toexp')
def clean_helper(form, formtype):
cleaned_data = super(formtype, form).clean()
@ -449,7 +415,7 @@ def clean_helper(form, formtype):
elif not DocAlias.objects.filter(name=key):
errors.append(key+" does not exist\n")
if new_relations[key] not in RELATION_SLUGS:
if new_relations[key] not in STATUSCHANGE_RELATIONS:
errors.append("Please choose a new status level for "+key+"\n")
if errors:
@ -542,7 +508,7 @@ def start_rfc_status_change(request,name):
login = request.user.person
relation_slugs = DocRelationshipName.objects.filter(slug__in=RELATION_SLUGS)
relation_slugs = DocRelationshipName.objects.filter(slug__in=STATUSCHANGE_RELATIONS)
if request.method == 'POST':
form = StartStatusChangeForm(request.POST)
@ -598,17 +564,17 @@ def edit_relations(request, name):
login = request.user.person
relation_slugs = DocRelationshipName.objects.filter(slug__in=RELATION_SLUGS)
relation_slugs = DocRelationshipName.objects.filter(slug__in=STATUSCHANGE_RELATIONS)
if request.method == 'POST':
form = EditStatusChangeForm(request.POST)
if 'Submit' in request.POST and form.is_valid():
old_relations={}
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
for rel in status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS):
old_relations[rel.target.document.canonical_name()]=rel.relationship.slug
new_relations=form.cleaned_data['relations']
status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS).delete()
status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS).delete()
for key in new_relations:
status_change.relateddocument_set.create(target=DocAlias.objects.get(name=key),
relationship_id=new_relations[key])
@ -629,7 +595,7 @@ def edit_relations(request, name):
else:
relations={}
for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
for rel in status_change.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS):
relations[rel.target.document.canonical_name()]=rel.relationship.slug
init = { "relations":relations,
}
@ -657,8 +623,8 @@ def generate_last_call_text(request, doc):
settings=settings,
requester=requester,
expiration_date=expiration_date.strftime("%Y-%m-%d"),
changes=['%s from %s to %s\n (%s)'%(rel.target.name.upper(),rel.target.document.std_level.name,newstatus(rel),rel.target.document.title) 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)],
changes=['%s from %s to %s\n (%s)'%(rel.target.name.upper(),rel.target.document.std_level.name,newstatus(rel),rel.target.document.title) for rel in doc.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS)],
urls=[rel.target.document.get_absolute_url() for rel in doc.relateddocument_set.filter(relationship__slug__in=STATUSCHANGE_RELATIONS)],
cc=cc
)
)

View file

@ -1,32 +0,0 @@
{% extends "base.html" %}
{% block title %}Set notification list for {{ doc.name }}{% endblock %}
{% block morecss %}
form.edit-notify td input#id_notify { width: 40em; }
form.edit-notify td.actions { padding-top: 1em; }
{% endblock %}
{% block content %}
{% load ietf_filters %}
<h1>Set notification list for {{ doc.name }}</h1>
<form class="edit-notify" action="" method="post">{% csrf_token %}
<table>
<tr>
<th>{{ form.notify.label_tag }}</th>
<td>{{ form.notify }}
<div class="help">{{ form.notify.help_text }}</div>
{{ form.notify.errors }}
</td>
</tr>
<tr>
<td></td>
<td class="actions">
<a href="{% url "doc_view" name=doc.name %}">Back</a>
<input type="submit" value="Save"/>
</td>
</tr>
</table>
</form>
{% endblock %}

View file

@ -11,11 +11,11 @@ form.edit-info #id_notify {
{% endblock %}
{% block title %}
Edit notification addresses for {{ doc.canonical_name }}-{{ doc.rev }}
Edit notification addresses for {{titletext}}
{% endblock %}
{% block content %}
<h1>Edit notification addresses for {{ doc.canonical_name }}-{{ doc.rev }}</h1>
<h1>Edit notification addresses for {{titletext}}</h1>
<form class="edit-info" action="" enctype="multipart/form-data" method="post">{% csrf_token %}
<table>

View file

@ -1,42 +0,0 @@
{% extends "base.html" %}
{% block morecss %}
form.edit-info #id_notify {
width: 600px;
}
.warning {
font-weight: bold;
color: #a00;
}
{% endblock %}
{% block title %}
Edit notification addresses for {{titletext}}
{% endblock %}
{% block content %}
<h1>Edit notification addresses for {{titletext}}</h1>
<form class="edit-info" action="" enctype="multipart/form-data" method="post">{% csrf_token %}
<table>
{% for field in form.visible_fields %}
<tr>
<th>{{ field.label_tag }}</th>
<td>
{{ field }}
{% 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="{% url "doc_view" name=doc.canonical_name %}">Back</a>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form>
{% endblock %}

View file

@ -299,6 +299,7 @@ def make_test_data():
def rfc_for_status_change_test_factory(name,rfc_num,std_level_id):
target_rfc = Document.objects.create(name=name, type_id='draft', std_level_id=std_level_id)
target_rfc.set_state(State.objects.get(slug='rfc',type__slug='draft'))
target_rfc.notify = "%s@ietf.org"%name
target_rfc.save()
docalias = DocAlias.objects.create(name=name,document=target_rfc)
docalias = DocAlias.objects.create(name='rfc%d'%rfc_num,document=target_rfc) # pyflakes:ignore