示例#1
0
def send_status_change_eval_email(request,doc):
    msg = render_to_string("doc/eval_email.txt",
                            dict(doc=doc,
                                 doc_url = settings.IDTRACKER_BASE_URL+doc.get_absolute_url(),
                                 )
                           )
    send_mail_preformatted(request,msg)
示例#2
0
def send_status_change_eval_email(request, doc):
    msg = render_to_string(
        "doc/eval_email.txt",
        dict(
            doc=doc,
            doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
        ))
    send_mail_preformatted(request, msg)
示例#3
0
def approve(request, name):
    """Approve this conflict review, setting the appropriate state and send the announcement to the right parties."""
    review = get_object_or_404(Document, type="conflrev", name=name)

    if review.get_state('conflrev').slug not in ('appr-reqnopub-pend','appr-noprob-pend'):
      raise Http404

    login = request.user.get_profile()

    if request.method == 'POST':

        form = AnnouncementForm(request.POST)

        if form.is_valid():

            new_state_slug = 'appr-reqnopub-sent' if review.get_state('conflrev').slug=='appr-reqnopub-pend' else 'appr-noprob-sent'
            new_review_state = State.objects.get(used=True, type="conflrev", slug=new_state_slug)
            save_document_in_history(review)
            old_description = review.friendly_state()
            review.set_state(new_review_state)
            new_description = review.friendly_state()

            log_state_changed(request, review, login, new_description, old_description)

            close_open_ballots(review, login)

            e = DocEvent(doc=review, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the conflict review response"
            e.save()

            review.time = e.time
            review.save()

            # send announcement
            send_mail_preformatted(request, form.cleaned_data['announcement_text'])

            c = DocEvent(type="added_comment", doc=review, by=login)
            c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
            c.save()

            return HttpResponseRedirect(review.get_absolute_url())

    else:

        init = { "announcement_text" : default_approval_text(review) }
        form = AnnouncementForm(initial=init)
    
    return render_to_response('doc/conflict_review/approve.html',
                              dict(
                                   review = review,
                                   conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document,   
                                   form = form,
                                   ),
                              context_instance=RequestContext(request))
示例#4
0
def approve(request, name):
    """Approve this conflict review, setting the appropriate state and send the announcement to the right parties."""
    review = get_object_or_404(Document, type="conflrev", name=name)

    if review.get_state('conflrev').slug not in ('appr-reqnopub-pend','appr-noprob-pend'):
      raise Http404

    login = request.user.person

    if request.method == 'POST':

        form = AnnouncementForm(request.POST)

        if form.is_valid():
            prev_state = review.get_state()
            events = []

            new_state_slug = 'appr-reqnopub-sent' if prev_state.slug == 'appr-reqnopub-pend' else 'appr-noprob-sent'
            new_state = State.objects.get(used=True, type="conflrev", slug=new_state_slug)

            review.set_state(new_state)
            e = add_state_change_event(review, login, prev_state, new_state)
            events.append(e)

            close_open_ballots(review, login)

            e = DocEvent(doc=review, rev=review.rev, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the conflict review response"
            e.save()
            events.append(e)

            review.save_with_history(events)

            # send announcement
            send_mail_preformatted(request, form.cleaned_data['announcement_text'])

            c = DocEvent(type="added_comment", doc=review, rev=review.rev, by=login)
            c.desc = "The following approval message was sent\n"+form.cleaned_data['announcement_text']
            c.save()

            return HttpResponseRedirect(review.get_absolute_url())

    else:

        init = { "announcement_text" : default_approval_text(review) }
        form = AnnouncementForm(initial=init)
    
    return render(request, 'doc/conflict_review/approve.html',
                              dict(
                                   review = review,
                                   conflictdoc = review.relateddocument_set.get(relationship__slug='conflrev').target.document,   
                                   form = form,
                                   ))
示例#5
0
 def save(self, *args, **kwargs):
     created = not self.pk
     super(Alias, self).save(*args, **kwargs)
     if created:
         if Alias.objects.filter(name=self.name).exclude(person=self.person).count() > 0 :
             msg = render_to_string('person/mail/possible_duplicates.txt',
                                    dict(name=self.name,
                                         persons=Person.objects.filter(alias__name=self.name),
                                         settings=settings
                                         ))
             send_mail_preformatted(None, msg)
示例#6
0
def send_status_change_eval_email(request,doc):
    msg = render_to_string("doc/eval_email.txt",
                            dict(doc=doc,
                                 doc_url = settings.IDTRACKER_BASE_URL+doc.get_absolute_url(),
                                 )
                           )
    addrs = gather_address_lists('ballot_issued',doc=doc)
    override = {'To':addrs.to }
    if addrs.cc:
        override['Cc'] = addrs.cc
    send_mail_preformatted(request,msg,override=override)
示例#7
0
def send_conflict_eval_email(request,review):
    msg = render_to_string("doc/eval_email.txt",
                            dict(doc=review,
                                 doc_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
                                 )
                           )
    send_mail_preformatted(request,msg)
    email_iana(request, 
               review.relateddocument_set.get(relationship__slug='conflrev').target.document,
               settings.IANA_EVAL_EMAIL,
                msg)
示例#8
0
def send_status_change_eval_email(request, doc):
    msg = render_to_string(
        "doc/eval_email.txt",
        dict(
            doc=doc,
            doc_url=settings.IDTRACKER_BASE_URL + doc.get_absolute_url(),
        ))
    addrs = gather_address_lists('ballot_issued', doc=doc)
    override = {'To': addrs.to}
    if addrs.cc:
        override['Cc'] = addrs.cc
    send_mail_preformatted(request, msg, override=override)
示例#9
0
def send_conflict_eval_email(request, review):
    msg = render_to_string(
        "doc/eval_email.txt",
        dict(
            doc=review,
            doc_url=settings.IDTRACKER_BASE_URL + review.get_absolute_url(),
        ))
    send_mail_preformatted(request, msg)
    email_iana(
        request,
        review.relateddocument_set.get(
            relationship__slug='conflrev').target.document,
        '*****@*****.**', msg)
示例#10
0
 def save(self, *args, **kwargs):
     created = not self.pk
     super(Alias, self).save(*args, **kwargs)
     if created:
         if Alias.objects.filter(name=self.name).exclude(
                 person=self.person).count() > 0:
             msg = render_to_string(
                 'person/mail/possible_duplicates.txt',
                 dict(name=self.name,
                      persons=Person.objects.filter(
                          alias__name=self.name).distinct(),
                      settings=settings))
             send_mail_preformatted(None, msg)
示例#11
0
 def save(self, *args, **kwargs):
     created = not self.pk
     super(Person, self).save(*args, **kwargs)
     if created:
         if Person.objects.filter(name=self.name).count() > 1 :
             msg = render_to_string('person/mail/possible_duplicates.txt',
                                    dict(name=self.name,
                                         persons=Person.objects.filter(name=self.name),
                                         settings=settings
                                         ))
             send_mail_preformatted(None, msg)
     self.alias_set.get_or_create(name=self.name)
     if self.ascii and self.name != self.ascii:
         self.alias_set.get_or_create(name=self.ascii)
示例#12
0
def send_conflict_review_started_email(request, review):
    msg = render_to_string("doc/conflict_review/review_started.txt",
                            dict(frm = settings.DEFAULT_FROM_EMAIL,
                                 by = request.user.person,
                                 review = review,
                                 reviewed_doc = review.relateddocument_set.get(relationship__slug='conflrev').target.document,
                                 review_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
                                 )
                           )
    if not has_role(request.user,"Secretariat"):
        send_mail_preformatted(request,msg)
    email_iana(request, 
               review.relateddocument_set.get(relationship__slug='conflrev').target.document,
               settings.IANA_EVAL_EMAIL,
                msg)
示例#13
0
def announcement_text(request, name, ann):
    """Editing of announcement text"""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.person

    if ann in ("action", "review"):
        existing = charter.latest_event(WriteupDocEvent, type="changed_%s_announcement" % ann)
    if not existing:
        if ann == "action":
            existing = default_action_text(group, charter, login)
        elif ann == "review":
            existing = default_review_text(group, charter, login)

    if not existing:
        raise Http404

    form = AnnouncementTextForm(initial=dict(announcement_text=existing.text))

    if request.method == 'POST':
        form = AnnouncementTextForm(request.POST)
        if "save_text" in request.POST and form.is_valid():
            t = form.cleaned_data['announcement_text']
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, by=login)
                e.by = login
                e.type = "changed_%s_announcement" % ann
                e.desc = "%s %s text was changed" % (group.type.name, ann)
                e.text = t
                e.save()
                
                charter.time = e.time
                charter.save()

            if request.GET.get("next", "") == "approve":
                return redirect('charter_approve', name=charter.canonical_name())

            return redirect('doc_writeup', name=charter.canonical_name())

        if "regenerate_text" in request.POST:
            if ann == "action":
                e = default_action_text(group, charter, login)
            elif ann == "review":
                e = default_review_text(group, charter, login)
            # make sure form has the updated text
            form = AnnouncementTextForm(initial=dict(announcement_text=e.text))

        if "send_text" in request.POST and form.is_valid():
            parsed_msg = send_mail_preformatted(request, form.cleaned_data['announcement_text'])
            messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
            return redirect('doc_writeup', name=charter.name)

    return render_to_response('doc/charter/announcement_text.html',
                              dict(charter=charter,
                                   announcement=ann,
                                   back_url=urlreverse("doc_writeup", kwargs=dict(name=charter.name)),
                                   announcement_text_form=form,
                                   ),
                              context_instance=RequestContext(request))
示例#14
0
def send_conflict_eval_email(request,review):
    msg = render_to_string("doc/eval_email.txt",
                            dict(doc=review,
                                 doc_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
                                 )
                           )
    addrs = gather_address_lists('ballot_issued',doc=review).as_strings()
    override = {'To':addrs.to}
    if addrs.cc:
        override['Cc']=addrs.cc
    send_mail_preformatted(request,msg,override=override)
    addrs = gather_address_lists('ballot_issued_iana',doc=review).as_strings()
    email_iana(request, 
               review.relateddocument_set.get(relationship__slug='conflrev').target.document,
               addrs.to,
               msg,
               addrs.cc)
示例#15
0
 def save(self, *args, **kwargs):
     created = not self.pk
     super(Person, self).save(*args, **kwargs)
     if created:
         if Person.objects.filter(name=self.name).count() > 1:
             msg = render_to_string(
                 'person/mail/possible_duplicates.txt',
                 dict(name=self.name,
                      persons=Person.objects.filter(name=self.name),
                      settings=settings))
             send_mail_preformatted(None, msg)
     if not self.name in [
             a.name for a in self.alias_set.filter(name=self.name)
     ]:
         self.alias_set.create(name=self.name)
     if self.ascii and self.name != self.ascii:
         if not self.ascii in [
                 a.name for a in self.alias_set.filter(name=self.ascii)
         ]:
             self.alias_set.create(name=self.ascii)
示例#16
0
def send_conflict_review_started_email(request, review):
    addrs = gather_address_lists('conflrev_requested',doc=review).as_strings(compact=False)
    msg = render_to_string("doc/conflict_review/review_started.txt",
                            dict(frm = settings.DEFAULT_FROM_EMAIL,
                                 to = addrs.to,
                                 cc = addrs.cc,
                                 by = request.user.person,
                                 review = review,
                                 reviewed_doc = review.relateddocument_set.get(relationship__slug='conflrev').target.document,
                                 review_url = settings.IDTRACKER_BASE_URL+review.get_absolute_url(),
                                 )
                           )
    if not has_role(request.user,"Secretariat"):
        send_mail_preformatted(request,msg)

    addrs = gather_address_lists('conflrev_requested_iana',doc=review).as_strings(compact=False)
    email_iana(request, 
               review.relateddocument_set.get(relationship__slug='conflrev').target.document,
               addrs.to,
               msg,
               cc=addrs.cc)
示例#17
0
def approve(request, name):
    """Approve this status change, setting the appropriate state and send the announcements to the right parties."""
    status_change = get_object_or_404(Document, type="statchg", name=name)

    if status_change.get_state('statchg').slug not in ('appr-pend'):
      raise Http404

    login = request.user.get_profile()

    AnnouncementFormSet = formset_factory(AnnouncementForm,extra=0)        

    if request.method == 'POST':

        formset = AnnouncementFormSet(request.POST)

        if formset.is_valid():

            save_document_in_history(status_change)

            old_description = status_change.friendly_state()
            status_change.set_state(State.objects.get(type='statchg', slug='appr-sent'))
            new_description = status_change.friendly_state()
            log_state_changed(request, status_change, login, new_description, old_description)

            close_open_ballots(status_change, login)

            e = DocEvent(doc=status_change, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the status change"
            e.save()

            status_change.time = e.time
            status_change.save()


            for form in formset.forms:

                send_mail_preformatted(request,form.cleaned_data['announcement_text'])

                c = DocEvent(type="added_comment", doc=status_change, by=login)
                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):
                # 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}))
                c.save()

            return HttpResponseRedirect(status_change.get_absolute_url())

    else:

        init = []
        for rel in status_change.relateddocument_set.filter(relationship__slug__in=RELATION_SLUGS):
            init.append({"announcement_text" : default_approval_text(status_change,rel),
                         "label": "Announcement text for %s to %s"%(rel.target.document.canonical_name(),newstatus(rel)),
                       })
        formset = AnnouncementFormSet(initial=init)
        for form in formset.forms:
           form.fields['announcement_text'].label=form.label
    
    return render_to_response('doc/status_change/approve.html',
                              dict(
                                   doc = status_change,
                                   formset = formset,
                                   ),
                              context_instance=RequestContext(request))
示例#18
0
文件: views.py 项目: mcr/ietfdb
def approve(request, name):
    """Approve charter, changing state, fixing revision, copying file to final location."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.get_profile()

    e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
    if not e:
        announcement = default_action_text(group, charter, login).text
    else:
        announcement = e.text

    if request.method == 'POST':
        new_charter_state = State.objects.get(used=True, type="charter", slug="approved")
        prev_charter_state = charter.get_state()

        save_document_in_history(charter)
        charter.set_state(new_charter_state)

        close_open_ballots(charter, login)

        # approve
        e = DocEvent(doc=charter, by=login)
        e.type = "iesg_approved"
        e.desc = "IESG has approved the charter"
        e.save()

        change_description = e.desc

        new_state = GroupStateName.objects.get(slug="active")
        if group.state != new_state:
            save_group_in_history(group)
            prev_state = group.state
            group.state = new_state
            group.time = e.time
            group.save()

            # create an event for the wg state change, too
            e = ChangeStateGroupEvent(group=group, type="changed_state")
            e.time = group.time
            e.by = login
            e.state_id = "active"
            e.desc = "Charter approved, group active"
            e.save()

            change_description += " and %s state has been changed to %s" % (group.type.name, new_state.name)

        e = log_state_changed(request, charter, login, prev_charter_state)

        # according to spec, 00-02 becomes 01, so copy file and record new revision
        try:
            old = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), charter.rev))
            new = os.path.join(charter.get_file_path(), '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev)))
            shutil.copy(old, new)
        except IOError:
            return HttpResponse("There was an error copying %s to %s" %
                                ('%s-%s.txt' % (charter.canonical_name(), charter.rev),
                                 '%s-%s.txt' % (charter.canonical_name(), next_approved_revision(charter.rev))))

        e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision")
        e.rev = next_approved_revision(charter.rev)
        e.desc = "New version available: <b>%s-%s.txt</b>" % (charter.canonical_name(), e.rev)
        e.save()

        charter.rev = e.rev
        charter.time = e.time
        charter.save()

        email_secretariat(request, group, "state-%s" % new_charter_state.slug, change_description)

        # move milestones over
        milestones_to_delete = list(group.groupmilestone_set.filter(state__in=("active", "review")))

        for m in group.groupmilestone_set.filter(state="charter"):
            # see if we got this milestone already (i.e. it was copied
            # verbatim to the charter)
            found = False
            for i, o in enumerate(milestones_to_delete):
                if o.desc == m.desc and o.due == m.due and set(o.docs.all()) == set(m.docs.all()):
                    found = True
                    break

            if found:
                # keep existing, whack charter milestone
                if not o.state_id == "active":
                    save_milestone_in_history(o)
                    o.state_id = "active"
                    o.save()
                    MilestoneGroupEvent.objects.create(
                        group=group, type="changed_milestone", by=login,
                        desc="Changed milestone \"%s\", set state to active from review" % o.desc,
                        milestone=o)

                del milestones_to_delete[i]

                # don't generate a DocEvent for this, it's implicit in the approval event
                save_milestone_in_history(m)
                m.state_id = "deleted"
                m.save()
            else:
                # move charter milestone
                save_milestone_in_history(m)
                m.state_id = "active"
                m.save()

                MilestoneGroupEvent.objects.create(
                    group=group, type="changed_milestone", by=login,
                    desc="Added milestone \"%s\", due %s, from approved charter" % (m.desc, m.due),
                    milestone=m)

        for m in milestones_to_delete:
            save_milestone_in_history(m)
            m.state_id = "deleted"
            m.save()

            MilestoneGroupEvent.objects.create(
                group=group, type="changed_milestone", by=login,
                desc="Deleted milestone \"%s\", not present in approved charter" % m.desc,
                milestone=m)

        # send announcement
        send_mail_preformatted(request, announcement)

        return HttpResponseRedirect(charter.get_absolute_url())
    
    return render_to_response('wgcharter/approve.html',
                              dict(charter=charter,
                                   announcement=announcement),
                              context_instance=RequestContext(request))
示例#19
0
def review_announcement_text(request, name):
    """Editing of review announcement text"""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    by = request.user.person

    existing = charter.latest_event(WriteupDocEvent,
                                    type="changed_review_announcement")
    existing_new_work = charter.latest_event(WriteupDocEvent,
                                             type="changed_new_work_text")

    if not existing:
        (existing, existing_new_work) = default_review_text(group, charter, by)

    if not existing:
        raise Http404

    if not existing_new_work:
        existing_new_work = WriteupDocEvent(doc=charter, rev=charter.rev)
        existing_new_work.by = by
        existing_new_work.type = "changed_new_work_text"
        existing_new_work.desc = "%s review text was changed" % group.type.name
        existing_new_work.text = derive_new_work_text(existing.text, group)
        existing_new_work.time = datetime.datetime.now()

    form = ReviewAnnouncementTextForm(initial=dict(
        announcement_text=existing.text, new_work_text=existing_new_work.text))

    if request.method == 'POST':
        form = ReviewAnnouncementTextForm(request.POST)
        if "save_text" in request.POST and form.is_valid():

            now = datetime.datetime.now()
            events = []

            t = form.cleaned_data['announcement_text']
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, rev=charter.rev)
                e.by = by
                e.type = "changed_review_announcement"
                e.desc = "%s review text was changed" % (group.type.name)
                e.text = t
                e.time = now
                e.save()
                events.append(e)
            elif existing.pk is None:
                existing.save()
                events.append(existing)

            t = form.cleaned_data['new_work_text']
            if t != existing_new_work.text:
                e = WriteupDocEvent(doc=charter, rev=charter.rev)
                e.by = by
                e.type = "changed_new_work_text"
                e.desc = "%s new work message text was changed" % (
                    group.type.name)
                e.text = t
                e.time = now
                e.save()
            elif existing_new_work.pk is None:
                existing_new_work.save()
                events.append(existing_new_work)

            if events:
                charter.save_with_history(events)

            if request.GET.get("next", "") == "approve":
                return redirect('ietf.doc.views_charter.approve',
                                name=charter.canonical_name())

            return redirect('ietf.doc.views_doc.document_writeup',
                            name=charter.canonical_name())

        if "regenerate_text" in request.POST:
            (existing,
             existing_new_work) = default_review_text(group, charter, by)
            existing.save()
            existing_new_work.save()
            form = ReviewAnnouncementTextForm(
                initial=dict(announcement_text=existing.text,
                             new_work_text=existing_new_work.text))

        if any(x in request.POST
               for x in ['send_annc_only', 'send_nw_only', 'send_both'
                         ]) and form.is_valid():
            if any(x in request.POST for x in ['send_annc_only', 'send_both']):
                parsed_msg = send_mail_preformatted(
                    request, form.cleaned_data['announcement_text'])
                messages.success(
                    request,
                    "The email To: '%s' with Subject: '%s' has been sent." % (
                        parsed_msg["To"],
                        parsed_msg["Subject"],
                    ))
            if any(x in request.POST for x in ['send_nw_only', 'send_both']):
                parsed_msg = send_mail_preformatted(
                    request, form.cleaned_data['new_work_text'])
                messages.success(
                    request,
                    "The email To: '%s' with Subject: '%s' has been sent." % (
                        parsed_msg["To"],
                        parsed_msg["Subject"],
                    ))
            return redirect('ietf.doc.views_doc.document_writeup',
                            name=charter.name)

    return render(
        request, 'doc/charter/review_announcement_text.html',
        dict(
            charter=charter,
            back_url=urlreverse('ietf.doc.views_doc.document_writeup',
                                kwargs=dict(name=charter.name)),
            announcement_text_form=form,
        ))
示例#20
0
def approve(request, name):
    """Approve charter, changing state, fixing revision, copying file to final location."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.get_profile()

    e = charter.latest_event(WriteupDocEvent,
                             type="changed_action_announcement")
    if not e:
        announcement = default_action_text(group, charter, login).text
    else:
        announcement = e.text

    if request.method == 'POST':
        new_charter_state = State.objects.get(used=True,
                                              type="charter",
                                              slug="approved")
        prev_charter_state = charter.get_state()

        save_document_in_history(charter)
        charter.set_state(new_charter_state)

        close_open_ballots(charter, login)

        # approve
        e = DocEvent(doc=charter, by=login)
        e.type = "iesg_approved"
        e.desc = "IESG has approved the charter"
        e.save()

        change_description = e.desc

        new_state = GroupStateName.objects.get(slug="active")
        if group.state != new_state:
            save_group_in_history(group)
            prev_state = group.state
            group.state = new_state
            group.time = e.time
            group.save()

            # create an event for the wg state change, too
            e = ChangeStateGroupEvent(group=group, type="changed_state")
            e.time = group.time
            e.by = login
            e.state_id = "active"
            e.desc = "Charter approved, group active"
            e.save()

            change_description += " and %s state has been changed to %s" % (
                group.type.name, new_state.name)

        e = log_state_changed(request, charter, login, prev_charter_state)

        # according to spec, 00-02 becomes 01, so copy file and record new revision
        try:
            old = os.path.join(
                charter.get_file_path(),
                '%s-%s.txt' % (charter.canonical_name(), charter.rev))
            new = os.path.join(
                charter.get_file_path(),
                '%s-%s.txt' % (charter.canonical_name(),
                               next_approved_revision(charter.rev)))
            shutil.copy(old, new)
        except IOError:
            return HttpResponse(
                "There was an error copying %s to %s" %
                ('%s-%s.txt' %
                 (charter.canonical_name(), charter.rev), '%s-%s.txt' %
                 (charter.canonical_name(), next_approved_revision(
                     charter.rev))))

        e = NewRevisionDocEvent(doc=charter, by=login, type="new_revision")
        e.rev = next_approved_revision(charter.rev)
        e.desc = "New version available: <b>%s-%s.txt</b>" % (
            charter.canonical_name(), e.rev)
        e.save()

        charter.rev = e.rev
        charter.time = e.time
        charter.save()

        email_secretariat(request, group, "state-%s" % new_charter_state.slug,
                          change_description)

        # move milestones over
        milestones_to_delete = list(
            group.groupmilestone_set.filter(state__in=("active", "review")))

        for m in group.groupmilestone_set.filter(state="charter"):
            # see if we got this milestone already (i.e. it was copied
            # verbatim to the charter)
            found = False
            for i, o in enumerate(milestones_to_delete):
                if o.desc == m.desc and o.due == m.due and set(
                        o.docs.all()) == set(m.docs.all()):
                    found = True
                    break

            if found:
                # keep existing, whack charter milestone
                if not o.state_id == "active":
                    save_milestone_in_history(o)
                    o.state_id = "active"
                    o.save()
                    MilestoneGroupEvent.objects.create(
                        group=group,
                        type="changed_milestone",
                        by=login,
                        desc=
                        "Changed milestone \"%s\", set state to active from review"
                        % o.desc,
                        milestone=o)

                del milestones_to_delete[i]

                # don't generate a DocEvent for this, it's implicit in the approval event
                save_milestone_in_history(m)
                m.state_id = "deleted"
                m.save()
            else:
                # move charter milestone
                save_milestone_in_history(m)
                m.state_id = "active"
                m.save()

                MilestoneGroupEvent.objects.create(
                    group=group,
                    type="changed_milestone",
                    by=login,
                    desc="Added milestone \"%s\", due %s, from approved charter"
                    % (m.desc, m.due),
                    milestone=m)

        for m in milestones_to_delete:
            save_milestone_in_history(m)
            m.state_id = "deleted"
            m.save()

            MilestoneGroupEvent.objects.create(
                group=group,
                type="changed_milestone",
                by=login,
                desc="Deleted milestone \"%s\", not present in approved charter"
                % m.desc,
                milestone=m)

        # send announcement
        send_mail_preformatted(request, announcement)

        return HttpResponseRedirect(charter.get_absolute_url())

    return render_to_response('wgcharter/approve.html',
                              dict(charter=charter, announcement=announcement),
                              context_instance=RequestContext(request))
示例#21
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    charter = get_object_or_404(Document, type="charter", name=name)

    ballot = charter.latest_event(BallotDocEvent, type="created_ballot")
    if not ballot:
        raise Http404

    login = request.user.person

    approval = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")

    existing = charter.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
    if not existing:
        existing = generate_ballot_writeup(request, charter)

    reissue = charter.latest_event(DocEvent, type="sent_ballot_announcement")

    form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text))

    if request.method == 'POST' and ("save_ballot_writeup" in request.POST or "send_ballot" in request.POST):
        form = BallotWriteupForm(request.POST)
        if form.is_valid():
            t = form.cleaned_data["ballot_writeup"]
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, by=login)
                e.by = login
                e.type = "changed_ballot_writeup_text"
                e.desc = "Ballot writeup was changed"
                e.text = t
                e.save()

                existing = e

            if "send_ballot" in request.POST and approval:
                if has_role(request.user, "Area Director") and not charter.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=login, ballot=ballot):
                    # sending the ballot counts as a yes
                    pos = BallotPositionDocEvent(doc=charter, by=login)
                    pos.type = "changed_ballot_position"
                    pos.ad = login
                    pos.pos_id = "yes"
                    pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
                    pos.save()
                    # Consider mailing this position to 'ballot_saved'

                msg = generate_issue_ballot_mail(request, charter, ballot)
                send_mail_preformatted(request, msg)

                e = DocEvent(doc=charter, by=login)
                e.by = login
                e.type = "sent_ballot_announcement"
                e.desc = "Ballot has been sent"
                e.save()

                return render_to_response('doc/charter/ballot_issued.html',
                                          dict(doc=charter,
                                               ),
                                          context_instance=RequestContext(request))

    return render_to_response('doc/charter/ballot_writeupnotes.html',
                              dict(charter=charter,
                                   ballot_issued=bool(charter.latest_event(type="sent_ballot_announcement")),
                                   ballot_writeup_form=form,
                                   reissue=reissue,
                                   approval=approval,
                                   ),
                              context_instance=RequestContext(request))
示例#22
0
def action_announcement_text(request, name):
    """Editing of action announcement text"""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    by = request.user.person

    existing = charter.latest_event(WriteupDocEvent,
                                    type="changed_action_announcement")
    if not existing:
        existing = default_action_text(group, charter, by)

    if not existing:
        raise Http404

    form = ActionAnnouncementTextForm(initial=dict(
        announcement_text=existing.text))

    if request.method == 'POST':
        form = ActionAnnouncementTextForm(request.POST)
        if "save_text" in request.POST and form.is_valid():
            t = form.cleaned_data['announcement_text']
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, rev=charter.rev)
                e.by = by
                e.type = "changed_action_announcement"
                e.desc = "%s action text was changed" % group.type.name
                e.text = t
                e.save()
            elif existing.pk == None:
                existing.save()

            if request.GET.get("next", "") == "approve":
                return redirect('ietf.doc.views_charter.approve',
                                name=charter.canonical_name())

            return redirect('ietf.doc.views_doc.document_writeup',
                            name=charter.canonical_name())

        if "regenerate_text" in request.POST:
            e = default_action_text(group, charter, by)
            e.save()
            form = ActionAnnouncementTextForm(initial=dict(
                announcement_text=e.text))

        if "send_text" in request.POST and form.is_valid():
            parsed_msg = send_mail_preformatted(
                request, form.cleaned_data['announcement_text'])
            messages.success(
                request,
                "The email To: '%s' with Subject: '%s' has been sent." % (
                    parsed_msg["To"],
                    parsed_msg["Subject"],
                ))
            return redirect('ietf.doc.views_doc.document_writeup',
                            name=charter.name)

    return render(
        request, 'doc/charter/action_announcement_text.html',
        dict(
            charter=charter,
            back_url=urlreverse('ietf.doc.views_doc.document_writeup',
                                kwargs=dict(name=charter.name)),
            announcement_text_form=form,
        ))
示例#23
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    doc = get_object_or_404(Document, docalias__name=name)

    login = request.user.person

    existing = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
    if not existing:
        existing = generate_ballot_writeup(request, doc)
        
    form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text))

    if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST:
        form = BallotWriteupForm(request.POST)
        if form.is_valid():
            t = form.cleaned_data["ballot_writeup"]
            if t != existing.text:
                e = WriteupDocEvent(doc=doc, by=login)
                e.by = login
                e.type = "changed_ballot_writeup_text"
                e.desc = "Ballot writeup was changed"
                e.text = t
                e.save()

            if "issue_ballot" in request.POST:
                create_ballot_if_not_open(doc, login, "approve")
                ballot = doc.latest_event(BallotDocEvent, type="created_ballot")

                if has_role(request.user, "Area Director") and not doc.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot):
                    # sending the ballot counts as a yes
                    pos = BallotPositionDocEvent(doc=doc, by=login)
                    pos.ballot = ballot
                    pos.type = "changed_ballot_position"
                    pos.ad = login
                    pos.pos_id = "yes"
                    pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name())
                    pos.save()

                approval = doc.latest_event(WriteupDocEvent, type="changed_ballot_approval_text")
                if not approval:
                    approval = generate_approval_mail(request, doc)

                msg = generate_issue_ballot_mail(request, doc, ballot)
                send_mail_preformatted(request, msg)
                send_mail_preformatted(request, msg, extra=extra_automation_headers(doc),
                                       override={ "To": "IANA <%s>"%settings.IANA_EVAL_EMAIL, "CC": None, "Bcc": None , "Reply-To": None})

                e = DocEvent(doc=doc, by=login)
                e.by = login
                e.type = "sent_ballot_announcement"
                e.desc = "Ballot has been issued"
                e.save()

                return render_to_response('doc/ballot/ballot_issued.html',
                                          dict(doc=doc,
                                               back_url=doc.get_absolute_url()),
                                          context_instance=RequestContext(request))
                        

    need_intended_status = ""
    if not doc.intended_std_level:
        need_intended_status = doc.file_tag()

    return render_to_response('doc/ballot/writeupnotes.html',
                              dict(doc=doc,
                                   back_url=doc.get_absolute_url(),
                                   ballot_issued=bool(doc.latest_event(type="sent_ballot_announcement")),
                                   ballot_writeup_form=form,
                                   need_intended_status=need_intended_status,
                                   ),
                              context_instance=RequestContext(request))
示例#24
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    doc = get_object_or_404(InternetDraft, filename=name)
    if not doc.idinternal:
        raise Http404()

    login = IESGLogin.objects.get(login_name=request.user.username)

    try:
        ballot = doc.idinternal.ballot
    except BallotInfo.DoesNotExist:
        ballot = generate_ballot(request, doc)

    ballot_writeup_form = BallotWriteupForm(instance=ballot)

    if request.method == 'POST':

        if "save_ballot_writeup" in request.POST:
            ballot_writeup_form = BallotWriteupForm(request.POST, instance=ballot)
            if ballot_writeup_form.is_valid():
                ballot.ballot_writeup = ballot_writeup_form.cleaned_data["ballot_writeup"]
		add_document_comment(request, doc, "Ballot writeup text changed")
                ballot.save()

        if "issue_ballot" in request.POST:
            ballot_writeup_form = BallotWriteupForm(request.POST, instance=ballot)
            approval_text_form = ApprovalTextForm(request.POST, instance=ballot)            
            if ballot_writeup_form.is_valid() and approval_text_form.is_valid():
                ballot.ballot_writeup = ballot_writeup_form.cleaned_data["ballot_writeup"]
                ballot.approval_text = approval_text_form.cleaned_data["approval_text"]
                ballot.active = True
                ballot.ballot_issued = True
                ballot.save()

                if not Position.objects.filter(ballot=ballot, ad=login):
                    pos = Position()
                    pos.ballot = ballot
                    pos.ad = login
                    pos.yes = 1
                    pos.noobj = pos.abstain = pos.approve = pos.discuss = pos.recuse = 0
                    pos.save()

                msg = generate_issue_ballot_mail(request, doc)
                send_mail_preformatted(request, msg)

#                email_iana(request, doc, '*****@*****.**', msg)
                
                doc.b_sent_date = date.today()
                doc.save()

                add_document_comment(request, doc, "Ballot has been issued")
                    
                doc.idinternal.event_date = date.today()
                doc.idinternal.save()
                    
                return render_to_response('idrfc/ballot_issued.html',
                                          dict(doc=doc,
                                               back_url=doc.idinternal.get_absolute_url()),
                                          context_instance=RequestContext(request))
                

        doc.idinternal.event_date = date.today()
        doc.idinternal.save()

    docs_with_invalid_status = [d.document().file_tag() for d in doc.idinternal.ballot_set() if "None" in d.document().intended_status.intended_status or "Request" in d.document().intended_status.intended_status]
    need_intended_status = ", ".join(docs_with_invalid_status)

    return render_to_response('idrfc/ballot_writeupnotes.html',
                              dict(doc=doc,
                                   ballot=ballot,
                                   ballot_writeup_form=ballot_writeup_form,
                                   need_intended_status=need_intended_status,
                                   ),
                              context_instance=RequestContext(request))
示例#25
0
def approve(request, name):
    """Approve charter, changing state, fixing revision, copying file to final location."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    by = request.user.person

    e = charter.latest_event(WriteupDocEvent,
                             type="changed_action_announcement")
    if not e:
        announcement = default_action_text(group, charter, by).text
    else:
        announcement = e.text

    if request.method == 'POST':
        new_charter_state = State.objects.get(used=True,
                                              type="charter",
                                              slug="approved")
        prev_charter_state = charter.get_state()

        charter.set_state(new_charter_state)

        close_open_ballots(charter, by)

        events = []
        # approve
        e = DocEvent(doc=charter, rev=charter.rev, by=by)
        e.type = "iesg_approved"
        e.desc = "IESG has approved the charter"
        e.save()
        events.append(e)

        change_description = e.desc

        group_state_change_event = change_group_state_after_charter_approval(
            group, by)
        if group_state_change_event:
            change_description += " and group state has been changed to %s" % group.state.name

        e = add_state_change_event(charter, by, prev_charter_state,
                                   new_charter_state)
        if e:
            events.append(e)

        fix_charter_revision_after_approval(charter, by)

        charter.save_with_history(events)

        email_admin_re_charter(
            request, group,
            "Charter state changed to \"%s\"" % new_charter_state.name,
            change_description, 'charter_state_edit_admin_needed')

        # move milestones over
        milestones_to_delete = list(
            group.groupmilestone_set.filter(state__in=("active", "review")))

        for m in group.groupmilestone_set.filter(state="charter"):
            # see if we got this milestone already (i.e. it was copied
            # verbatim to the charter)
            found = False
            for i, o in enumerate(milestones_to_delete):
                if o.desc == m.desc and o.due == m.due and set(
                        o.docs.all()) == set(m.docs.all()):
                    found = True
                    break

            if found:
                # keep existing, whack charter milestone
                if not o.state_id == "active":
                    save_milestone_in_history(o)
                    o.state_id = "active"
                    o.save()
                    MilestoneGroupEvent.objects.create(
                        group=group,
                        type="changed_milestone",
                        by=by,
                        desc=
                        "Changed milestone \"%s\", set state to active from review"
                        % o.desc,
                        milestone=o)

                del milestones_to_delete[i]

                # don't generate a DocEvent for this, it's implicit in the approval event
                save_milestone_in_history(m)
                m.state_id = "deleted"
                m.save()
            else:
                # move charter milestone
                save_milestone_in_history(m)
                m.state_id = "active"
                m.save()

                MilestoneGroupEvent.objects.create(
                    group=group,
                    type="changed_milestone",
                    by=by,
                    desc="Added milestone \"%s\", due %s, from approved charter"
                    % (m.desc, m.due),
                    milestone=m)

        for m in milestones_to_delete:
            save_milestone_in_history(m)
            m.state_id = "deleted"
            m.save()

            MilestoneGroupEvent.objects.create(
                group=group,
                type="changed_milestone",
                by=by,
                desc="Deleted milestone \"%s\", not present in approved charter"
                % m.desc,
                milestone=m)

        # send announcement
        send_mail_preformatted(request, announcement)

        return HttpResponseRedirect(charter.get_absolute_url())

    return render(request, 'doc/charter/approve.html',
                  dict(charter=charter, announcement=announcement))
示例#26
0
def approve_ballot(request, name):
    """Approve ballot, sending out announcement, changing state."""
    doc = get_object_or_404(InternetDraft, filename=name)
    if not doc.idinternal:
        raise Http404()

    login = IESGLogin.objects.get(login_name=request.user.username)

    ballot = doc.idinternal.ballot

    if "To: RFC Editor" in ballot.approval_text:
        action = "to_rfc_editor"
    elif "NOT be published" in ballot.approval_text:
        action = "do_not_publish"
    else:
        action = "to_announcement_list"

    announcement = ballot.approval_text + "\n\n" + ballot.ballot_writeup
        
    if request.method == 'POST':
        for i in doc.idinternal.ballot_set():
            if action == "do_not_publish":
                new_state = IDState.DEAD
            else:
                new_state = IDState.APPROVED_ANNOUNCEMENT_SENT

            i.change_state(IDState.objects.get(document_state_id=new_state), None)

            if action == "do_not_publish":
                i.dnp = True
                i.dnp_date = date.today()
                i.noproblem = False

            if action == "to_rfc_editor":
                i.noproblem = True
            
            i.event_date = date.today()
            i.save()

            i.document().b_approve_date = date.today()
            i.document().save()
            
            if action == "do_not_publish":
                comment = "Do Not Publish note has been sent to RFC Editor"
            else:
                comment = "IESG has approved"
                
            comment += " and state has been changed to %s" % i.cur_state.state
            add_document_comment(request, i.document(), comment)
            email_owner(request, i.document(), i.job_owner, login, comment)
            email_state_changed(request, i.document(), strip_tags(comment))

        send_mail_preformatted(request, announcement)

        ballot.an_sent = True
        ballot.an_sent_date = date.today()
        ballot.an_sent_by = login
        ballot.save()

        if action == "to_announcement_list":
            email_iana(request, doc, "*****@*****.**", announcement)

        return HttpResponseRedirect(doc.idinternal.get_absolute_url())
  
    return render_to_response('idrfc/approve_ballot.html',
                              dict(doc=doc,
                                   action=action,
                                   announcement=announcement),
                              context_instance=RequestContext(request))
示例#27
0
def approve_ballot(request, name):
    """Approve ballot, sending out announcement, changing state."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not doc.get_state("draft-iesg"):
        raise Http404

    login = request.user.person

    approval_mail_event = doc.latest_event(WriteupDocEvent,
                                           type="changed_ballot_approval_text")
    if not approval_mail_event:
        approval_mail_event = generate_approval_mail(request, doc)
    approval_text = approval_mail_event.text

    ballot_writeup_event = doc.latest_event(WriteupDocEvent,
                                            type="changed_ballot_writeup_text")
    if not ballot_writeup_event:
        ballot_writeup_event = generate_ballot_writeup(request, doc)
    ballot_writeup = ballot_writeup_event.text

    error_duplicate_rfc_editor_note = False
    e = doc.latest_event(WriteupDocEvent, type="changed_rfc_editor_note_text")
    if e and (e.text != ""):
        if "RFC Editor Note" in ballot_writeup:
            error_duplicate_rfc_editor_note = True
        ballot_writeup += "\n\n" + e.text

    if error_duplicate_rfc_editor_note:
        return render(request, 'doc/draft/rfceditor_note_duplicate_error.html',
                      {'doc': doc})

    if "NOT be published" in approval_text:
        action = "do_not_publish"
    elif "To: RFC Editor" in approval_text:
        action = "to_rfc_editor"
    else:
        action = "to_announcement_list"

    # NOTE: according to Michelle Cotton <*****@*****.**>
    # (as per 2011-10-24) IANA is scraping these messages for
    # information so would like to know beforehand if the format
    # changes
    announcement = approval_text + "\n\n" + ballot_writeup

    if request.method == 'POST':
        if action == "do_not_publish":
            new_state = State.objects.get(used=True,
                                          type="draft-iesg",
                                          slug="dead")
        else:
            new_state = State.objects.get(used=True,
                                          type="draft-iesg",
                                          slug="ann")

        prev_state = doc.get_state("draft-iesg")
        prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
        events = []

        if approval_mail_event.pk == None:
            approval_mail_event.save()
        if ballot_writeup_event.pk == None:
            ballot_writeup_event.save()

        if new_state.slug == "ann" and new_state.slug != prev_state.slug and not request.POST.get(
                "skiprfceditorpost"):
            # start by notifying the RFC Editor
            import ietf.sync.rfceditor
            response, error = ietf.sync.rfceditor.post_approved_draft(
                settings.RFC_EDITOR_SYNC_NOTIFICATION_URL, doc.name)
            if error:
                return render(
                    request,
                    'doc/draft/rfceditor_post_approved_draft_failed.html',
                    dict(name=doc.name, response=response, error=error))

        doc.set_state(new_state)
        doc.tags.remove(*prev_tags)

        # fixup document
        close_open_ballots(doc, login)

        e = DocEvent(doc=doc, rev=doc.rev, by=login)
        if action == "do_not_publish":
            e.type = "iesg_disapproved"
            e.desc = "Do Not Publish note has been sent to the RFC Editor"
        else:
            e.type = "iesg_approved"
            e.desc = "IESG has approved the document"
        e.save()
        events.append(e)

        e = add_state_change_event(doc,
                                   login,
                                   prev_state,
                                   new_state,
                                   prev_tags=prev_tags,
                                   new_tags=[])

        if e:
            events.append(e)

        doc.save_with_history(events)

        # send announcement
        send_mail_preformatted(request, announcement)

        if action == "to_announcement_list":
            addrs = gather_address_lists(
                'ballot_approved_ietf_stream_iana').as_strings(compact=False)
            send_mail_preformatted(request,
                                   announcement,
                                   extra=extra_automation_headers(doc),
                                   override={
                                       "To": addrs.to,
                                       "CC": addrs.cc,
                                       "Bcc": None,
                                       "Reply-To": None
                                   })

        msg = infer_message(announcement)
        msg.by = login
        msg.save()
        msg.related_docs.add(doc)

        return HttpResponseRedirect(doc.get_absolute_url())

    return render(request, 'doc/ballot/approve_ballot.html',
                  dict(doc=doc, action=action, announcement=announcement))
示例#28
0
def review_announcement_text(request, name):
    """Editing of review announcement text"""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.person

    existing = charter.latest_event(WriteupDocEvent, type="changed_review_announcement")
    existing_new_work = charter.latest_event(WriteupDocEvent, type="changed_new_work_text")

    if not existing:
        (existing, existing_new_work) = default_review_text(group, charter, login)

    if not existing:
        raise Http404

    if not existing_new_work:
        existing_new_work = WriteupDocEvent(doc=charter, by=login)
        existing_new_work.by = login 
        existing_new_work.type = "changed_new_work_text"
        existing_new_work.desc = "%s review text was changed" % group.type.name
        existing_new_work.text = derive_new_work_text(existing.text,group)
        existing_new_work.time = datetime.datetime.now()
        existing_new_work.save()

    new_work_text = existing_new_work.text

    form = ReviewAnnouncementTextForm(initial=dict(announcement_text=existing.text,new_work_text=new_work_text))

    if request.method == 'POST':
        form = ReviewAnnouncementTextForm(request.POST)
        if "save_text" in request.POST and form.is_valid():

            now = datetime.datetime.now()
            (e1, e2) = (None, None)

            t = form.cleaned_data['announcement_text']
            if t != existing.text:
                e1 = WriteupDocEvent(doc=charter, by=login)
                e1.by = login
                e1.type = "changed_review_announcement" 
                e1.desc = "%s review text was changed" % (group.type.name)
                e1.text = t
                e1.time = now
                e1.save()

            t = form.cleaned_data['new_work_text']
            if t != new_work_text:
                e2 = WriteupDocEvent(doc=charter, by=login)
                e2.by = login
                e2.type = "changed_new_work_text" 
                e2.desc = "%s new work message text was changed" % (group.type.name)
                e2.text = t
                e2.time = now
                e2.save()

            if e1 or e2:
                charter.time = now
                charter.save()

            if request.GET.get("next", "") == "approve":
                return redirect('charter_approve', name=charter.canonical_name())

            return redirect('doc_writeup', name=charter.canonical_name())

        if "regenerate_text" in request.POST:
            (e1, e2) = default_review_text(group, charter, login)
            form = ReviewAnnouncementTextForm(initial=dict(announcement_text=e1.text,new_work_text=e2.text))

        if any([x in request.POST for x in ['send_annc_only','send_nw_only','send_both']]) and form.is_valid():
            if any([x in request.POST for x in ['send_annc_only','send_both']]):
                parsed_msg = send_mail_preformatted(request, form.cleaned_data['announcement_text'])
                messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
            if any([x in request.POST for x in ['send_nw_only','send_both']]):
                parsed_msg = send_mail_preformatted(request, form.cleaned_data['new_work_text'])
                messages.success(request, "The email To: '%s' with Subject: '%s' has been sent." % (parsed_msg["To"],parsed_msg["Subject"],))
            return redirect('doc_writeup', name=charter.name)

    return render_to_response('doc/charter/review_announcement_text.html',
                              dict(charter=charter,
                                   back_url=urlreverse("doc_writeup", kwargs=dict(name=charter.name)),
                                   announcement_text_form=form,
                                   ),
                              context_instance=RequestContext(request))
示例#29
0
def announcement_text(request, name, ann):
    """Editing of announcement text"""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.get_profile()

    if ann in ("action", "review"):
        existing = charter.latest_event(WriteupDocEvent,
                                        type="changed_%s_announcement" % ann)
    if not existing:
        if ann == "action":
            existing = default_action_text(group, charter, login)
        elif ann == "review":
            existing = default_review_text(group, charter, login)

    if not existing:
        raise Http404

    form = AnnouncementTextForm(initial=dict(announcement_text=existing.text))

    if request.method == 'POST':
        form = AnnouncementTextForm(request.POST)
        if "save_text" in request.POST and form.is_valid():
            t = form.cleaned_data['announcement_text']
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, by=login)
                e.by = login
                e.type = "changed_%s_announcement" % ann
                e.desc = "%s %s text was changed" % (group.type.name, ann)
                e.text = t
                e.save()

                charter.time = e.time
                charter.save()

            if request.GET.get("next", "") == "approve":
                return redirect('charter_approve',
                                name=charter.canonical_name())

            return redirect('doc_writeup', name=charter.canonical_name())

        if "regenerate_text" in request.POST:
            if ann == "action":
                e = default_action_text(group, charter, login)
            elif ann == "review":
                e = default_review_text(group, charter, login)
            # make sure form has the updated text
            form = AnnouncementTextForm(initial=dict(announcement_text=e.text))

        if "send_text" in request.POST and form.is_valid():
            parsed_msg = send_mail_preformatted(
                request, form.cleaned_data['announcement_text'])
            messages.success(
                request,
                "The email To: '%s' with Subjet: '%s' has been sent." % (
                    parsed_msg["To"],
                    parsed_msg["Subject"],
                ))
            return redirect('doc_writeup', name=charter.name)

    return render_to_response('wgcharter/announcement_text.html',
                              dict(
                                  charter=charter,
                                  announcement=ann,
                                  back_url=urlreverse(
                                      "doc_writeup",
                                      kwargs=dict(name=charter.name)),
                                  announcement_text_form=form,
                              ),
                              context_instance=RequestContext(request))
示例#30
0
def approve_ballot(request, name):
    """Approve ballot, sending out announcement, changing state."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not doc.get_state("draft-iesg"):
        raise Http404()

    login = request.user.person

    e = doc.latest_event(WriteupDocEvent, type="changed_ballot_approval_text")
    if not e:
        e = generate_approval_mail(request, doc)
    approval_text = e.text

    e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
    if not e:
        e = generate_ballot_writeup(request, doc)
    ballot_writeup = e.text
    
    if "NOT be published" in approval_text:
        action = "do_not_publish"
    elif "To: RFC Editor" in approval_text:
        action = "to_rfc_editor"
    else:
        action = "to_announcement_list"

    # NOTE: according to Michelle Cotton <*****@*****.**>
    # (as per 2011-10-24) IANA is scraping these messages for
    # information so would like to know beforehand if the format
    # changes
    announcement = approval_text + "\n\n" + ballot_writeup
        
    if request.method == 'POST':
        if action == "do_not_publish":
            new_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
        else:
            new_state = State.objects.get(used=True, type="draft-iesg", slug="ann")

        prev_state = doc.get_state("draft-iesg")
        prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)

        if new_state.slug == "ann" and new_state.slug != prev_state.slug and not request.REQUEST.get("skiprfceditorpost"):
            # start by notifying the RFC Editor
            import ietf.sync.rfceditor
            response, error = ietf.sync.rfceditor.post_approved_draft(settings.RFC_EDITOR_SYNC_NOTIFICATION_URL, doc.name)
            if error:
                return render_to_response('doc/draft/rfceditor_post_approved_draft_failed.html',
                                  dict(name=doc.name,
                                       response=response,
                                       error=error),
                                  context_instance=RequestContext(request))

        save_document_in_history(doc)

        doc.set_state(new_state)
        doc.tags.remove(*prev_tags)
        
        # fixup document
        close_open_ballots(doc, login)

        e = DocEvent(doc=doc, by=login)
        if action == "do_not_publish":
            e.type = "iesg_disapproved"
            e.desc = "Do Not Publish note has been sent to the RFC Editor"
        else:
            e.type = "iesg_approved"
            e.desc = "IESG has approved the document"

        e.save()
        
        change_description = e.desc + " and state has been changed to %s" % doc.get_state("draft-iesg").name
        
        e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=[])

        doc.time = (e and e.time) or datetime.datetime.now()
        doc.save()

        email_state_changed(request, doc, change_description)
        email_ad(request, doc, doc.ad, login, change_description)

        # send announcement

        send_mail_preformatted(request, announcement)

        if action == "to_announcement_list":
            send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
                                   override={ "To": "IANA <%s>"%settings.IANA_APPROVE_EMAIL, "CC": None, "Bcc": None, "Reply-To": None})

        msg = infer_message(announcement)
        msg.by = login
        msg.save()
        msg.related_docs.add(doc)

        return HttpResponseRedirect(doc.get_absolute_url())

    return render_to_response('doc/ballot/approve_ballot.html',
                              dict(doc=doc,
                                   action=action,
                                   announcement=announcement),
                              context_instance=RequestContext(request))
示例#31
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    charter = get_object_or_404(Document, type="charter", name=name)

    ballot = charter.latest_event(BallotDocEvent, type="created_ballot")
    if not ballot:
        raise Http404()

    login = request.user.get_profile()

    approval = charter.latest_event(WriteupDocEvent,
                                    type="changed_action_announcement")

    existing = charter.latest_event(WriteupDocEvent,
                                    type="changed_ballot_writeup_text")
    if not existing:
        existing = generate_ballot_writeup(request, charter)

    reissue = charter.latest_event(DocEvent, type="sent_ballot_announcement")

    form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text))

    if request.method == 'POST' and ("save_ballot_writeup" in request.POST
                                     or "send_ballot" in request.POST):
        form = BallotWriteupForm(request.POST)
        if form.is_valid():
            t = form.cleaned_data["ballot_writeup"]
            if t != existing.text:
                e = WriteupDocEvent(doc=charter, by=login)
                e.by = login
                e.type = "changed_ballot_writeup_text"
                e.desc = "Ballot writeup was changed"
                e.text = t
                e.save()

            if "send_ballot" in request.POST and approval:
                if has_role(request.user,
                            "Area Director") and not charter.latest_event(
                                BallotPositionDocEvent,
                                type="changed_ballot_position",
                                ad=login,
                                ballot=ballot):
                    # sending the ballot counts as a yes
                    pos = BallotPositionDocEvent(doc=charter, by=login)
                    pos.type = "changed_ballot_position"
                    pos.ad = login
                    pos.pos_id = "yes"
                    pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (
                        pos.pos.name, pos.ad.plain_name())
                    pos.save()

                msg = generate_issue_ballot_mail(request, charter, ballot)
                send_mail_preformatted(request, msg)

                e = DocEvent(doc=charter, by=login)
                e.by = login
                e.type = "sent_ballot_announcement"
                e.desc = "Ballot has been sent"
                e.save()

                return render_to_response(
                    'wgcharter/ballot_issued.html',
                    dict(doc=charter, ),
                    context_instance=RequestContext(request))

    return render_to_response(
        'wgcharter/ballot_writeupnotes.html',
        dict(
            charter=charter,
            ballot_issued=bool(
                charter.latest_event(type="sent_ballot_announcement")),
            ballot_writeup_form=form,
            reissue=reissue,
            approval=approval,
        ),
        context_instance=RequestContext(request))
示例#32
0
def make_last_call(request, name):
    """Make last call for Internet Draft, sending out announcement."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not (doc.get_state("draft-iesg") or doc.get_state("statchg")):
        raise Http404

    login = request.user.person

    e = doc.latest_event(WriteupDocEvent, type="changed_last_call_text")
    if not e:
        if doc.type.slug != 'draft':
            raise Http404
        e = generate_last_call_announcement(request, doc)
    announcement = e.text

    if request.method == 'POST':
        form = MakeLastCallForm(request.POST)
        if form.is_valid():
            send_mail_preformatted(request, announcement)
            if doc.type.slug == 'draft':
                send_mail_preformatted(request, announcement, extra=extra_automation_headers(doc),
                                       override={ "To": "IANA <*****@*****.**>", "CC": None, "Bcc": None, "Reply-To": None})

            msg = infer_message(announcement)
            msg.by = login
            msg.save()
            msg.related_docs.add(doc)

            save_document_in_history(doc)

            new_state = doc.get_state()
            prev_tags = new_tags = []

            if doc.type.slug == 'draft':
                new_state = State.objects.get(used=True, type="draft-iesg", slug='lc')
                prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
            elif doc.type.slug == 'statchg':
                new_state = State.objects.get(used=True, type="statchg", slug='in-lc')

            prev_state = doc.get_state(new_state.type_id)

            doc.set_state(new_state)
            doc.tags.remove(*prev_tags)

            e = add_state_change_event(doc, login, prev_state, new_state, prev_tags=prev_tags, new_tags=new_tags)

            doc.time = (e and e.time) or datetime.datetime.now()
            doc.save()

            change_description = "Last call has been made for %s and state has been changed to %s" % (doc.name, new_state.name)

            email_state_changed(request, doc, change_description)
            email_ad(request, doc, doc.ad, login, change_description)
            
            e = LastCallDocEvent(doc=doc, by=login)
            e.type = "sent_last_call"
            e.desc = "The following Last Call announcement was sent out:<br><br>"
            e.desc += announcement

            if form.cleaned_data['last_call_sent_date'] != e.time.date():
                e.time = datetime.datetime.combine(form.cleaned_data['last_call_sent_date'], e.time.time())
            e.expires = form.cleaned_data['last_call_expiration_date']
            e.save()

            # update IANA Review state
            if doc.type.slug == 'draft':
                prev_state = doc.get_state("draft-iana-review")
                if not prev_state:
                    next_state = State.objects.get(used=True, type="draft-iana-review", slug="need-rev")
                    doc.set_state(next_state)
                    add_state_change_event(doc, login, prev_state, next_state)

            return HttpResponseRedirect(doc.get_absolute_url())
    else:
        initial = {}
        initial["last_call_sent_date"] = datetime.date.today()
        if doc.type.slug == 'draft':
            # This logic is repeated in the code that edits last call text - why?
            expire_days = 14
            if doc.group.type_id in ("individ", "area"):
                expire_days = 28
            templ = 'doc/draft/make_last_call.html'
        else:
            expire_days=28
            templ = 'doc/status_change/make_last_call.html'

        initial["last_call_expiration_date"] = datetime.date.today() + datetime.timedelta(days=expire_days)
        
        form = MakeLastCallForm(initial=initial)
  
    return render_to_response(templ,
                              dict(doc=doc,
                                   form=form,
                                   announcement=announcement,
                                  ),
                              context_instance=RequestContext(request))
示例#33
0
def ballot_writeupnotes(request, name):
    """Editing of ballot write-up and notes"""
    doc = get_object_or_404(Document, docalias__name=name)

    login = request.user.person

    existing = doc.latest_event(WriteupDocEvent,
                                type="changed_ballot_writeup_text")
    if not existing:
        existing = generate_ballot_writeup(request, doc)

    form = BallotWriteupForm(initial=dict(ballot_writeup=existing.text))

    if request.method == 'POST' and "save_ballot_writeup" in request.POST or "issue_ballot" in request.POST:
        form = BallotWriteupForm(request.POST)
        if form.is_valid():
            t = form.cleaned_data["ballot_writeup"]
            if t != existing.text:
                e = WriteupDocEvent(doc=doc, rev=doc.rev, by=login)
                e.by = login
                e.type = "changed_ballot_writeup_text"
                e.desc = "Ballot writeup was changed"
                e.text = t
                e.save()
            elif existing.pk == None:
                existing.save()

            if "issue_ballot" in request.POST:
                create_ballot_if_not_open(doc, login, "approve")
                ballot = doc.latest_event(BallotDocEvent,
                                          type="created_ballot")

                if has_role(
                        request.user,
                        "Area Director") and not doc.latest_event(
                            BallotPositionDocEvent, ad=login, ballot=ballot):
                    # sending the ballot counts as a yes
                    pos = BallotPositionDocEvent(doc=doc,
                                                 rev=doc.rev,
                                                 by=login)
                    pos.ballot = ballot
                    pos.type = "changed_ballot_position"
                    pos.ad = login
                    pos.pos_id = "yes"
                    pos.desc = "[Ballot Position Update] New position, %s, has been recorded for %s" % (
                        pos.pos.name, pos.ad.plain_name())
                    pos.save()

                    # Consider mailing this position to 'ballot_saved'

                approval = doc.latest_event(
                    WriteupDocEvent, type="changed_ballot_approval_text")
                if not approval:
                    approval = generate_approval_mail(request, doc)
                    approval.save()

                msg = generate_issue_ballot_mail(request, doc, ballot)

                addrs = gather_address_lists('ballot_issued',
                                             doc=doc).as_strings()
                override = {'To': addrs.to}
                if addrs.cc:
                    override['CC'] = addrs.cc
                send_mail_preformatted(request, msg, override=override)

                addrs = gather_address_lists('ballot_issued_iana',
                                             doc=doc).as_strings()
                override = {
                    "To": "IANA <%s>" % settings.IANA_EVAL_EMAIL,
                    "Bcc": None,
                    "Reply-To": None
                }
                if addrs.cc:
                    override['CC'] = addrs.cc
                send_mail_preformatted(request,
                                       msg,
                                       extra=extra_automation_headers(doc),
                                       override={
                                           "To": "IANA <%s>" %
                                           settings.IANA_EVAL_EMAIL,
                                           "CC": None,
                                           "Bcc": None,
                                           "Reply-To": None
                                       })

                e = DocEvent(doc=doc, rev=doc.rev, by=login)
                e.by = login
                e.type = "sent_ballot_announcement"
                e.desc = "Ballot has been issued"
                e.save()

                return render(request, 'doc/ballot/ballot_issued.html',
                              dict(doc=doc, back_url=doc.get_absolute_url()))

    need_intended_status = ""
    if not doc.intended_std_level:
        need_intended_status = doc.file_tag()

    return render(
        request, 'doc/ballot/writeupnotes.html',
        dict(
            doc=doc,
            back_url=doc.get_absolute_url(),
            ballot_issued=bool(
                doc.latest_event(type="sent_ballot_announcement")),
            ballot_writeup_form=form,
            need_intended_status=need_intended_status,
        ))
示例#34
0
def approve(request, name):
    """Approve charter, changing state, fixing revision, copying file to final location."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group

    login = request.user.person

    e = charter.latest_event(WriteupDocEvent, type="changed_action_announcement")
    if not e:
        announcement = default_action_text(group, charter, login).text
    else:
        announcement = e.text

    if request.method == 'POST':
        new_charter_state = State.objects.get(used=True, type="charter", slug="approved")
        prev_charter_state = charter.get_state()

        save_document_in_history(charter)
        charter.set_state(new_charter_state)

        close_open_ballots(charter, login)

        # approve
        e = DocEvent(doc=charter, by=login)
        e.type = "iesg_approved"
        e.desc = "IESG has approved the charter"
        e.save()

        change_description = e.desc

        group_state_change_event = change_group_state_after_charter_approval(group, login)
        if group_state_change_event:
            change_description += " and group state has been changed to %s" % group.state.name

        add_state_change_event(charter, login, prev_charter_state, new_charter_state)

        fix_charter_revision_after_approval(charter, login)

        email_admin_re_charter(request, group, "Charter state changed to %s" % new_charter_state.name, change_description,'charter_state_edit_admin_needed')

        # move milestones over
        milestones_to_delete = list(group.groupmilestone_set.filter(state__in=("active", "review")))

        for m in group.groupmilestone_set.filter(state="charter"):
            # see if we got this milestone already (i.e. it was copied
            # verbatim to the charter)
            found = False
            for i, o in enumerate(milestones_to_delete):
                if o.desc == m.desc and o.due == m.due and set(o.docs.all()) == set(m.docs.all()):
                    found = True
                    break

            if found:
                # keep existing, whack charter milestone
                if not o.state_id == "active":
                    save_milestone_in_history(o)
                    o.state_id = "active"
                    o.save()
                    MilestoneGroupEvent.objects.create(
                        group=group, type="changed_milestone", by=login,
                        desc="Changed milestone \"%s\", set state to active from review" % o.desc,
                        milestone=o)

                del milestones_to_delete[i]

                # don't generate a DocEvent for this, it's implicit in the approval event
                save_milestone_in_history(m)
                m.state_id = "deleted"
                m.save()
            else:
                # move charter milestone
                save_milestone_in_history(m)
                m.state_id = "active"
                m.save()

                MilestoneGroupEvent.objects.create(
                    group=group, type="changed_milestone", by=login,
                    desc="Added milestone \"%s\", due %s, from approved charter" % (m.desc, m.due),
                    milestone=m)

        for m in milestones_to_delete:
            save_milestone_in_history(m)
            m.state_id = "deleted"
            m.save()

            MilestoneGroupEvent.objects.create(
                group=group, type="changed_milestone", by=login,
                desc="Deleted milestone \"%s\", not present in approved charter" % m.desc,
                milestone=m)

        # send announcement
        send_mail_preformatted(request, announcement)

        return HttpResponseRedirect(charter.get_absolute_url())

    return render_to_response('doc/charter/approve.html',
                              dict(charter=charter,
                                   announcement=announcement),
                              context_instance=RequestContext(request))
示例#35
0
def make_last_call(request, name):
    """Make last call for Internet Draft, sending out announcement."""
    doc = get_object_or_404(Document, docalias__name=name)
    if not (doc.get_state("draft-iesg") or doc.get_state("statchg")):
        raise Http404

    login = request.user.person

    announcement_event = doc.latest_event(WriteupDocEvent,
                                          type="changed_last_call_text")
    if not announcement_event:
        if doc.type_id != 'draft':
            raise Http404
        announcement_event = generate_last_call_announcement(request, doc)
    announcement = announcement_event.text

    if request.method == 'POST':
        form = MakeLastCallForm(request.POST)
        if form.is_valid():
            if announcement_event.pk == None:
                announcement_event.save()

            send_mail_preformatted(request, announcement)
            if doc.type.slug == 'draft':
                addrs = gather_address_lists('last_call_issued_iana',
                                             doc=doc).as_strings(compact=False)
                send_mail_preformatted(request,
                                       announcement,
                                       extra=extra_automation_headers(doc),
                                       override={
                                           "To": addrs.to,
                                           "CC": addrs.cc,
                                           "Bcc": None,
                                           "Reply-To": None
                                       })

            msg = infer_message(announcement)
            msg.by = login
            msg.save()
            msg.related_docs.add(doc)

            new_state = doc.get_state()
            prev_tags = []
            new_tags = []
            events = []

            if doc.type.slug == 'draft':
                new_state = State.objects.get(used=True,
                                              type="draft-iesg",
                                              slug='lc')
                prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
            elif doc.type.slug == 'statchg':
                new_state = State.objects.get(used=True,
                                              type="statchg",
                                              slug='in-lc')

            prev_state = doc.get_state(new_state.type_id)

            doc.set_state(new_state)
            doc.tags.remove(*prev_tags)

            e = add_state_change_event(doc,
                                       login,
                                       prev_state,
                                       new_state,
                                       prev_tags=prev_tags,
                                       new_tags=new_tags)
            if e:
                events.append(e)
            expiration_date = form.cleaned_data['last_call_expiration_date']
            e = LastCallDocEvent(doc=doc, rev=doc.rev, by=login)
            e.type = "sent_last_call"
            e.desc = "The following Last Call announcement was sent out (ends %s):<br><br>" % expiration_date
            e.desc += announcement

            if form.cleaned_data['last_call_sent_date'] != e.time.date():
                e.time = datetime.datetime.combine(
                    form.cleaned_data['last_call_sent_date'], e.time.time())
            e.expires = expiration_date
            e.save()
            events.append(e)

            # update IANA Review state
            if doc.type.slug == 'draft':
                prev_state = doc.get_state("draft-iana-review")
                if not prev_state:
                    next_state = State.objects.get(used=True,
                                                   type="draft-iana-review",
                                                   slug="need-rev")
                    doc.set_state(next_state)
                    e = add_state_change_event(doc, login, prev_state,
                                               next_state)
                    if e:
                        events.append(e)

            doc.save_with_history(events)

            return HttpResponseRedirect(doc.get_absolute_url())
    else:
        initial = {}
        initial["last_call_sent_date"] = datetime.date.today()
        if doc.type.slug == 'draft':
            # This logic is repeated in the code that edits last call text - why?
            expire_days = 14
            if doc.group.type_id in ("individ", "area"):
                expire_days = 28
            templ = 'doc/draft/make_last_call.html'
        else:
            expire_days = 28
            templ = 'doc/status_change/make_last_call.html'

        initial["last_call_expiration_date"] = datetime.date.today(
        ) + datetime.timedelta(days=expire_days)

        form = MakeLastCallForm(initial=initial)

    return render(request, templ,
                  dict(
                      doc=doc,
                      form=form,
                      announcement=announcement,
                  ))
示例#36
0
def approve(request, name):
    """Approve this status change, setting the appropriate state and send the announcements to the right parties."""
    status_change = get_object_or_404(Document, type="statchg", name=name)

    if status_change.get_state('statchg').slug not in ('appr-pend'):
        raise Http404

    login = request.user.person

    AnnouncementFormSet = formset_factory(AnnouncementForm, extra=0)

    if request.method == 'POST':

        formset = AnnouncementFormSet(request.POST)

        if formset.is_valid():

            prev_state = status_change.get_state()
            new_state = State.objects.get(type='statchg', slug='appr-sent')

            status_change.set_state(new_state)

            events = []
            events.append(
                add_state_change_event(status_change, login, prev_state,
                                       new_state))

            close_open_ballots(status_change, login)

            e = DocEvent(doc=status_change, rev=status_change.rev, by=login)
            e.type = "iesg_approved"
            e.desc = "IESG has approved the status change"
            e.save()
            events.append(e)

            status_change.save_with_history(events)

            for form in formset.forms:

                send_mail_preformatted(request,
                                       form.cleaned_data['announcement_text'])

                c = DocEvent(type="added_comment",
                             doc=status_change,
                             rev=status_change.rev,
                             by=login)
                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=STATUSCHANGE_RELATIONS):
                # Add a document event to each target
                c = DocEvent(type="added_comment",
                             doc=rel.target.document,
                             rev=rel.target.document.rev,
                             by=login)
                c.desc = "New status of %s approved by the IESG\n%s%s" % (
                    newstatus(rel), settings.IDTRACKER_BASE_URL,
                    reverse('ietf.doc.views_doc.document_main',
                            kwargs={'name': status_change.name}))
                c.save()

            return HttpResponseRedirect(status_change.get_absolute_url())

    else:

        init = []
        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)),
            })
        formset = AnnouncementFormSet(initial=init)
        for form in formset.forms:
            form.fields['announcement_text'].label = form.label

    return render(request, 'doc/status_change/approve.html',
                  dict(
                      doc=status_change,
                      formset=formset,
                  ))