def add_comment(request, name): """Add comment to history of document.""" doc = get_object_or_404(Document, docalias__name=name) login = request.user.person if request.method == 'POST': form = AddCommentForm(request.POST) if form.is_valid(): c = form.cleaned_data['comment'] e = DocEvent(doc=doc, by=login) e.type = "added_comment" e.desc = c e.save() if doc.type_id == "draft": email_ad(request, doc, doc.ad, login, "A new comment added by %s" % login.name) return redirect("doc_history", name=doc.name) else: form = AddCommentForm() return render_to_response('doc/add_comment.html', dict(doc=doc, form=form), context_instance=RequestContext(request))
def edit_ad(request, name): """Change the responsible Area Director for this charter.""" charter = get_object_or_404(Document, type="charter", name=name) login = request.user.person if request.method == 'POST': form = AdForm(request.POST) if form.is_valid(): new_ad = form.cleaned_data['ad'] if new_ad != charter.ad: save_document_in_history(charter) e = DocEvent(doc=charter, by=login) e.desc = "Responsible AD changed to %s" % new_ad.plain_name() if charter.ad: e.desc += " from %s" % charter.ad.plain_name() e.type = "changed_document" e.save() charter.ad = new_ad charter.time = e.time charter.save() return redirect('doc_view', name=charter.name) else: init = { "ad" : charter.ad_id } form = AdForm(initial=init) return render_to_response('doc/charter/change_ad.html', {'form': form, 'charter': charter, }, context_instance = RequestContext(request))
def edit_notify(request, name): doc = get_object_or_404(Document, type="charter", name=name) login = request.user.person init = {'notify': doc.notify} if request.method == "POST": form = NotifyForm(request.POST, initial=init) if form.is_valid(): n = form.cleaned_data["notify"] if n != doc.notify: save_document_in_history(doc) e = DocEvent(doc=doc, by=login) e.desc = "Notification list changed to %s" % (escape(n) or "none") if doc.notify: e.desc += " from %s" % escape(doc.notify) e.type = "changed_document" e.save() doc.notify = n doc.time = e.time doc.save() return redirect("doc_view", name=doc.name) else: form = NotifyForm(initial=init) return render_to_response('doc/charter/edit_notify.html', dict(doc=doc, form=form, user=request.user, login=login), context_instance=RequestContext(request))
def expire_draft(doc): # clean up files move_draft_files_to_archive(doc, doc.rev) system = Person.objects.get(name="(System)") # change the state save_document_in_history(doc) if doc.latest_event(type='started_iesg_process'): new_state = State.objects.get(used=True, type="draft-iesg", slug="dead") prev_state = doc.get_state(new_state.type_id) prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS) if new_state != prev_state: doc.set_state(new_state) doc.tags.remove(*prev_tags) e = add_state_change_event(doc, system, prev_state, new_state, prev_tags=prev_tags, new_tags=[]) e = DocEvent(doc=doc, by=system) e.type = "expired_document" e.desc = "Document has expired" e.save() doc.set_state(State.objects.get(used=True, type="draft", slug="expired")) doc.time = datetime.datetime.now() doc.save()
def log_state_changed(request, doc, by, prev_state): e = DocEvent(doc=doc, by=by) e.type = "changed_document" e.desc = u"State changed to <b>%s</b> from %s" % ( doc.get_state().name, prev_state.name if prev_state else "None") e.save() return e
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))
def request_last_call(request, doc): if not doc.latest_event(type="changed_ballot_writeup_text"): generate_ballot_writeup(request, doc) if not doc.latest_event(type="changed_ballot_approval_text"): generate_approval_mail(request, doc) if not doc.latest_event(type="changed_last_call_text"): generate_last_call_announcement(request, doc) send_last_call_request(request, doc) e = DocEvent() e.type = "requested_last_call" e.by = request.user.person e.doc = doc e.desc = "Last call was requested" e.save()
def update_rfc_log_from_protocol_page(rfc_names, rfc_must_published_later_than): """Add notices to RFC history log that IANA is now referencing the RFC.""" system = Person.objects.get(name="(System)") updated = [] docs = Document.objects.filter(docalias__name__in=rfc_names).exclude( docevent__type="rfc_in_iana_registry").filter( # only take those that were published after cutoff since we # have a big bunch of old RFCs that we unfortunately don't have data for docevent__type="published_rfc", docevent__time__gte=rfc_must_published_later_than ).distinct() for d in docs: e = DocEvent(doc=d) e.by = system e.type = "rfc_in_iana_registry" e.desc = "IANA registries were updated to include %s" % d.display_name() e.save() updated.append(d) return updated
def edit_position(request, name, ballot_id): """Vote and edit discuss and comment on document as Area Director.""" doc = get_object_or_404(Document, docalias__name=name) ballot = get_object_or_404(BallotDocEvent, type="created_ballot", pk=ballot_id, doc=doc) ad = login = request.user.person if 'ballot_edit_return_point' in request.session: return_to_url = request.session['ballot_edit_return_point'] else: return_to_url = urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc.name, ballot_id=ballot_id)) # if we're in the Secretariat, we can select an AD to act as stand-in for if has_role(request.user, "Secretariat"): ad_id = request.GET.get('ad') if not ad_id: raise Http404 ad = get_object_or_404(Person, pk=ad_id) old_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=ad, ballot=ballot) if request.method == 'POST': if not has_role( request.user, "Secretariat") and not ad.role_set.filter( name="ad", group__type="area", group__state="active"): # prevent pre-ADs from voting return HttpResponseForbidden( "Must be a proper Area Director in an active area to cast ballot" ) form = EditPositionForm(request.POST, ballot_type=ballot.ballot_type) if form.is_valid(): # save the vote clean = form.cleaned_data pos = BallotPositionDocEvent(doc=doc, rev=doc.rev, by=login) pos.type = "changed_ballot_position" pos.ballot = ballot pos.ad = ad pos.pos = clean["position"] pos.comment = clean["comment"].rstrip() pos.comment_time = old_pos.comment_time if old_pos else None pos.discuss = clean["discuss"].rstrip() if not pos.pos.blocking: pos.discuss = "" pos.discuss_time = old_pos.discuss_time if old_pos else None changes = [] added_events = [] # possibly add discuss/comment comments to history trail # so it's easy to see what's happened old_comment = old_pos.comment if old_pos else "" if pos.comment != old_comment: pos.comment_time = pos.time changes.append("comment") if pos.comment: e = DocEvent(doc=doc, rev=doc.rev) e.by = ad # otherwise we can't see who's saying it e.type = "added_comment" e.desc = "[Ballot comment]\n" + pos.comment added_events.append(e) old_discuss = old_pos.discuss if old_pos else "" if pos.discuss != old_discuss: pos.discuss_time = pos.time changes.append("discuss") if pos.pos.blocking: e = DocEvent(doc=doc, rev=doc.rev, by=login) e.by = ad # otherwise we can't see who's saying it e.type = "added_comment" e.desc = "[Ballot %s]\n" % pos.pos.name.lower() e.desc += pos.discuss added_events.append(e) # figure out a description if not old_pos and pos.pos.slug != "norecord": pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % ( pos.pos.name, pos.ad.plain_name()) elif old_pos and pos.pos != old_pos.pos: pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % ( pos.ad.plain_name(), pos.pos.name, old_pos.pos.name) if not pos.desc and changes: pos.desc = u"Ballot %s text updated for %s" % ( u" and ".join(changes), ad.plain_name()) # only add new event if we actually got a change if pos.desc: if login != ad: pos.desc += u" by %s" % login.plain_name() pos.save() for e in added_events: e.save( ) # save them after the position is saved to get later id for sorting order if request.POST.get("send_mail"): qstr = "" if request.GET.get('ad'): qstr += "?ad=%s" % request.GET.get('ad') return HttpResponseRedirect( urlreverse('ietf.doc.views_ballot.send_ballot_comment', kwargs=dict(name=doc.name, ballot_id=ballot_id)) + qstr) elif request.POST.get("Defer"): return redirect('ietf.doc.views_ballot.defer_ballot', name=doc) elif request.POST.get("Undefer"): return redirect('ietf.doc.views_ballot.undefer_ballot', name=doc) else: return HttpResponseRedirect(return_to_url) else: initial = {} if old_pos: initial['position'] = old_pos.pos.slug initial['discuss'] = old_pos.discuss initial['comment'] = old_pos.comment form = EditPositionForm(initial=initial, ballot_type=ballot.ballot_type) blocking_positions = dict((p.pk, p.name) for p in form.fields["position"].queryset.all() if p.blocking) ballot_deferred = doc.active_defer_event() return render( request, 'doc/ballot/edit_position.html', dict( doc=doc, form=form, ad=ad, return_to_url=return_to_url, old_pos=old_pos, ballot_deferred=ballot_deferred, ballot=ballot, show_discuss_text=old_pos and old_pos.pos.blocking, blocking_positions=json.dumps(blocking_positions), ))
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))
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))
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))
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))
def edit_position(request, name, ballot_id): """Vote and edit discuss and comment on document as Area Director.""" doc = get_object_or_404(Document, docalias__name=name) ballot = get_object_or_404(BallotDocEvent, type="created_ballot", pk=ballot_id, doc=doc) ad = login = request.user.person if 'HTTP_REFERER' in request.META: return_to_url = request.META['HTTP_REFERER'] else: return_to_url = urlreverse("doc_ballot", kwargs=dict(name=doc.name, ballot_id=ballot_id)) # if we're in the Secretariat, we can select an AD to act as stand-in for if has_role(request.user, "Secretariat"): ad_id = request.GET.get('ad') if not ad_id: raise Http404() ad = get_object_or_404(Person, pk=ad_id) old_pos = doc.latest_event(BallotPositionDocEvent, type="changed_ballot_position", ad=ad, ballot=ballot) if request.method == 'POST': if not has_role(request.user, "Secretariat") and not ad.role_set.filter(name="ad", group__type="area", group__state="active"): # prevent pre-ADs from voting return HttpResponseForbidden("Must be a proper Area Director in an active area to cast ballot") form = EditPositionForm(request.POST, ballot_type=ballot.ballot_type) if form.is_valid(): # save the vote clean = form.cleaned_data if clean['return_to_url']: return_to_url = clean['return_to_url'] pos = BallotPositionDocEvent(doc=doc, by=login) pos.type = "changed_ballot_position" pos.ballot = ballot pos.ad = ad pos.pos = clean["position"] pos.comment = clean["comment"].rstrip() pos.comment_time = old_pos.comment_time if old_pos else None pos.discuss = clean["discuss"].rstrip() if not pos.pos.blocking: pos.discuss = "" pos.discuss_time = old_pos.discuss_time if old_pos else None changes = [] added_events = [] # possibly add discuss/comment comments to history trail # so it's easy to see what's happened old_comment = old_pos.comment if old_pos else "" if pos.comment != old_comment: pos.comment_time = pos.time changes.append("comment") if pos.comment: e = DocEvent(doc=doc) e.by = ad # otherwise we can't see who's saying it e.type = "added_comment" e.desc = "[Ballot comment]\n" + pos.comment added_events.append(e) old_discuss = old_pos.discuss if old_pos else "" if pos.discuss != old_discuss: pos.discuss_time = pos.time changes.append("discuss") if pos.pos.blocking: e = DocEvent(doc=doc, by=login) e.by = ad # otherwise we can't see who's saying it e.type = "added_comment" e.desc = "[Ballot %s]\n" % pos.pos.name.lower() e.desc += pos.discuss added_events.append(e) # figure out a description if not old_pos and pos.pos.slug != "norecord": pos.desc = u"[Ballot Position Update] New position, %s, has been recorded for %s" % (pos.pos.name, pos.ad.plain_name()) elif old_pos and pos.pos != old_pos.pos: pos.desc = "[Ballot Position Update] Position for %s has been changed to %s from %s" % (pos.ad.plain_name(), pos.pos.name, old_pos.pos.name) if not pos.desc and changes: pos.desc = u"Ballot %s text updated for %s" % (u" and ".join(changes), ad.plain_name()) # only add new event if we actually got a change if pos.desc: if login != ad: pos.desc += u" by %s" % login.plain_name() pos.save() for e in added_events: e.save() # save them after the position is saved to get later id for sorting order if request.POST.get("send_mail"): qstr = "?return_to_url=%s" % return_to_url if request.GET.get('ad'): qstr += "&ad=%s" % request.GET.get('ad') return HttpResponseRedirect(urlreverse("doc_send_ballot_comment", kwargs=dict(name=doc.name, ballot_id=ballot_id)) + qstr) elif request.POST.get("Defer"): return redirect("doc_defer_ballot", name=doc) elif request.POST.get("Undefer"): return redirect("doc_undefer_ballot", name=doc) else: return HttpResponseRedirect(return_to_url) else: initial = {} if old_pos: initial['position'] = old_pos.pos.slug initial['discuss'] = old_pos.discuss initial['comment'] = old_pos.comment if return_to_url: initial['return_to_url'] = return_to_url form = EditPositionForm(initial=initial, ballot_type=ballot.ballot_type) blocking_positions = dict((p.pk, p.name) for p in form.fields["position"].queryset.all() if p.blocking) ballot_deferred = doc.active_defer_event() return render_to_response('doc/ballot/edit_position.html', dict(doc=doc, form=form, ad=ad, return_to_url=return_to_url, old_pos=old_pos, ballot_deferred=ballot_deferred, ballot = ballot, show_discuss_text=old_pos and old_pos.pos.blocking, blocking_positions=json.dumps(blocking_positions), ), context_instance=RequestContext(request))
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))
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))
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, ))