def change_state(request, name, option=None): """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary and logging the change as a comment.""" review = get_object_or_404(Document, type="conflrev", name=name) login = request.user.get_profile() if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data review_state = clean['review_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=review, by=login) c.desc = comment c.save() if review_state != review.get_state(): save_document_in_history(review) old_description = review.friendly_state() review.set_state(review_state) new_description = review.friendly_state() log_state_changed(request, review, login, new_description, old_description) review.time = datetime.datetime.now() review.save() if review_state.slug == "iesgeval": create_ballot_if_not_open(review, login, "conflrev") ballot = review.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not review.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=review, 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() send_conflict_eval_email(request,review) return redirect('doc_view', name=review.name) else: s = review.get_state() init = dict(review_state=s.pk if s else None) form = ChangeStateForm(initial=init) return render_to_response('doc/change_state.html', dict(form=form, doc=review, login=login, help_url=reverse('help_conflict_review_states'), ), 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 last_call(request, name): """Edit the Last Call Text for this status change and possibly request IETF LC""" status_change = get_object_or_404(Document, type="statchg", name=name) login = request.user.get_profile() last_call_event = status_change.latest_event(WriteupDocEvent, type="changed_last_call_text") if not last_call_event: last_call_event = generate_last_call_text(request, status_change) form = LastCallTextForm(initial=dict(last_call_text=last_call_event.text)) if request.method == 'POST': if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST: form = LastCallTextForm(request.POST) if form.is_valid(): t = form.cleaned_data['last_call_text'] if t != last_call_event.text: e = WriteupDocEvent(doc=status_change, by=login) e.by = login e.type = "changed_last_call_text" e.desc = "Last call announcement was changed" e.text = t e.save() if "send_last_call_request" in request.POST: save_document_in_history(status_change) old_description = status_change.friendly_state() status_change.set_state(State.objects.get(type='statchg', slug='lc-req')) new_description = status_change.friendly_state() e = log_state_changed(request, status_change, login, new_description, old_description) status_change.time = e.time status_change.save() request_last_call(request, status_change) return render_to_response('idrfc/last_call_requested.html', dict(doc=status_change, url = status_change.get_absolute_url(), ), context_instance=RequestContext(request)) if "regenerate_last_call_text" in request.POST: e = generate_last_call_text(request,status_change) form = LastCallTextForm(initial=dict(last_call_text=e.text)) return render_to_response('doc/status_change/last_call.html', dict(doc=status_change, back_url = status_change.get_absolute_url(), last_call_event = last_call_event, last_call_form = form, ), context_instance = RequestContext(request))
def doc_detail(request, date, name): ''' This view displays the ballot information for the document, and lets the user make changes to ballot positions and document state. ''' doc = get_object_or_404(Document, docalias__name=name) # As of Datatracker v4.32, Conflict Review (conflrev) Document Types can # be added to the Telechat agenda. We need to check the document type here # and set the state_type for use later in the view if doc.type_id == 'draft': state_type = 'draft-iesg' elif doc.type_id == 'conflrev': state_type = 'conflrev' elif doc.type_id == 'charter': state_type = 'charter' started_process = doc.latest_event(type="started_iesg_process") login = request.user.get_profile() if doc.active_ballot(): ballots = doc.active_ballot().active_ad_positions() # returns dict of ad:ballotpositiondocevent else: ballots = [] # setup form initials initial_ballot = [] open_positions = 0 for key in sorted(ballots, key = lambda a: a.name_parts()[3]): initial_ballot.append({'name':key.name,'id':key.id,'position':ballots[key].pos.slug if ballots[key] else None}) if ballots[key] and ballots[key].pos.slug == 'norecord': open_positions += 1 elif not ballots[key]: open_positions += 1 tags = doc.tags.filter(slug__in=TELECHAT_TAGS) tag = tags[0].pk if tags else None writeup = get_doc_writeup(doc) initial_state = {'state':doc.get_state(state_type).pk, 'substate':tag} BallotFormset = formset_factory(BallotForm, extra=0) agenda = _agenda_data(request, date=date) header = get_section_header(name,agenda) if name else '' # nav button logic doc_list = get_doc_list(agenda) nav_start = nav_end = False if doc == doc_list[0]: nav_start = True if doc == doc_list[-1]: nav_end = True if request.method == 'POST': button_text = request.POST.get('submit', '') # logic from idrfc/views_ballot.py EditPositionRedesign if button_text == 'update_ballot': formset = BallotFormset(request.POST, initial=initial_ballot) state_form = ChangeStateForm(initial=initial_state) has_changed = False for form in formset.forms: if form.is_valid() and form.changed_data: # create new BallotPositionDocEvent clean = form.cleaned_data ad = Person.objects.get(id=clean['id']) pos = BallotPositionDocEvent(doc=doc,by=login) pos.type = "changed_ballot_position" pos.ad = ad pos.ballot = doc.latest_event(BallotDocEvent, type="created_ballot") pos.pos = clean['position'] if form.initial['position'] == None: pos.desc = '[Ballot Position Update] New position, %s, has been recorded for %s by %s' % (pos.pos.name, ad.name, login.name) else: pos.desc = '[Ballot Position Update] Position for %s has been changed to %s by %s' % (ad.name, pos.pos.name, login.name) pos.save() has_changed = True if has_changed: messages.success(request,'Ballot position changed.') url = reverse('telechat_doc_detail', kwargs={'date':date,'name':name}) return HttpResponseRedirect(url) # logic from idrfc/views_edit.py change_stateREDESIGN elif button_text == 'update_state': formset = BallotFormset(initial=initial_ballot) state_form = ChangeStateForm(request.POST, initial=initial_state) if state_form.is_valid(): state = state_form.cleaned_data['state'] tag = state_form.cleaned_data['substate'] prev = doc.get_state(state_type) # tag handling is a bit awkward since the UI still works # as if IESG tags are a substate prev_tag = doc.tags.filter(slug__in=(TELECHAT_TAGS)) prev_tag = prev_tag[0] if prev_tag else None #if state != prev or tag != prev_tag: if state_form.changed_data: save_document_in_history(doc) old_description = doc.friendly_state() if 'state' in state_form.changed_data: doc.set_state(state) if 'substate' in state_form.changed_data: if prev_tag: doc.tags.remove(prev_tag) if tag: doc.tags.add(tag) new_description = doc.friendly_state() e = log_state_changed(request, doc, login, new_description, old_description) doc.time = e.time doc.save() email_state_changed(request, doc, e.desc) email_owner(request, doc, doc.ad, login, e.desc) if state.slug == "lc-req": request_last_call(request, doc) messages.success(request,'Document state updated') url = reverse('telechat_doc_detail', kwargs={'date':date,'name':name}) return HttpResponseRedirect(url) else: formset = BallotFormset(initial=initial_ballot) state_form = ChangeStateForm(initial=initial_state) # if this is a conflict review document add referenced document if doc.type_id == 'conflrev': conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document else: conflictdoc = None return render_to_response('telechat/doc.html', { 'date': date, 'document': doc, 'conflictdoc': conflictdoc, 'agenda': agenda, 'formset': formset, 'header': header, 'open_positions': open_positions, 'state_form': state_form, 'writeup': writeup, 'nav_start': nav_start, 'nav_end': nav_end}, 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.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 change_state(request, name, option=None): """Change state of an IESG review for IETF conflicts in other stream's documents, notifying parties as necessary and logging the change as a comment.""" review = get_object_or_404(Document, type="conflrev", name=name) login = request.user.get_profile() if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): clean = form.cleaned_data review_state = clean['review_state'] comment = clean['comment'].rstrip() if comment: c = DocEvent(type="added_comment", doc=review, by=login) c.desc = comment c.save() if review_state != review.get_state(): save_document_in_history(review) old_description = review.friendly_state() review.set_state(review_state) new_description = review.friendly_state() log_state_changed(request, review, login, new_description, old_description) review.time = datetime.datetime.now() review.save() if review_state.slug == "iesgeval": create_ballot_if_not_open(review, login, "conflrev") ballot = review.latest_event(BallotDocEvent, type="created_ballot") if has_role(request.user, "Area Director") and not review.latest_event( BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"): # The AD putting a conflict review into iesgeval who doesn't already have a position is saying "yes" pos = BallotPositionDocEvent(doc=review, 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() send_conflict_eval_email(request, review) return redirect('doc_view', name=review.name) else: s = review.get_state() init = dict(review_state=s.pk if s else None) form = ChangeStateForm(initial=init) return render_to_response( 'doc/change_state.html', dict( form=form, doc=review, login=login, help_url=reverse('help_conflict_review_states'), ), 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 doc_detail(request, date, name): ''' This view displays the ballot information for the document, and lets the user make changes to ballot positions and document state. ''' doc = get_object_or_404(Document, docalias__name=name) # As of Datatracker v4.32, Conflict Review (conflrev) Document Types can # be added to the Telechat agenda. We need to check the document type here # and set the state_type for use later in the view if doc.type_id == 'draft': state_type = 'draft-iesg' elif doc.type_id == 'conflrev': state_type = 'conflrev' elif doc.type_id == 'charter': state_type = 'charter' started_process = doc.latest_event(type="started_iesg_process") login = request.user.get_profile() if doc.active_ballot(): ballots = doc.active_ballot().active_ad_positions( ) # returns dict of ad:ballotpositiondocevent else: ballots = [] # setup form initials initial_ballot = [] open_positions = 0 for key in sorted(ballots, key=lambda a: a.name_parts()[3]): initial_ballot.append({ 'name': key.name, 'id': key.id, 'position': ballots[key].pos.slug if ballots[key] else None }) if ballots[key] and ballots[key].pos.slug == 'norecord': open_positions += 1 elif not ballots[key]: open_positions += 1 tags = doc.tags.filter(slug__in=TELECHAT_TAGS) tag = tags[0].pk if tags else None writeup = get_doc_writeup(doc) initial_state = {'state': doc.get_state(state_type).pk, 'substate': tag} BallotFormset = formset_factory(BallotForm, extra=0) agenda = _agenda_data(request, date=date) header = get_section_header(name, agenda) if name else '' # nav button logic doc_list = get_doc_list(agenda) nav_start = nav_end = False if doc == doc_list[0]: nav_start = True if doc == doc_list[-1]: nav_end = True if request.method == 'POST': button_text = request.POST.get('submit', '') # logic from idrfc/views_ballot.py EditPositionRedesign if button_text == 'update_ballot': formset = BallotFormset(request.POST, initial=initial_ballot) state_form = ChangeStateForm(initial=initial_state) has_changed = False for form in formset.forms: if form.is_valid() and form.changed_data: # create new BallotPositionDocEvent clean = form.cleaned_data ad = Person.objects.get(id=clean['id']) pos = BallotPositionDocEvent(doc=doc, by=login) pos.type = "changed_ballot_position" pos.ad = ad pos.ballot = doc.latest_event(BallotDocEvent, type="created_ballot") pos.pos = clean['position'] if form.initial['position'] == None: pos.desc = '[Ballot Position Update] New position, %s, has been recorded for %s by %s' % ( pos.pos.name, ad.name, login.name) else: pos.desc = '[Ballot Position Update] Position for %s has been changed to %s by %s' % ( ad.name, pos.pos.name, login.name) pos.save() has_changed = True if has_changed: messages.success(request, 'Ballot position changed.') url = reverse('telechat_doc_detail', kwargs={ 'date': date, 'name': name }) return HttpResponseRedirect(url) # logic from idrfc/views_edit.py change_stateREDESIGN elif button_text == 'update_state': formset = BallotFormset(initial=initial_ballot) state_form = ChangeStateForm(request.POST, initial=initial_state) if state_form.is_valid(): state = state_form.cleaned_data['state'] tag = state_form.cleaned_data['substate'] prev = doc.get_state(state_type) # tag handling is a bit awkward since the UI still works # as if IESG tags are a substate prev_tag = doc.tags.filter(slug__in=(TELECHAT_TAGS)) prev_tag = prev_tag[0] if prev_tag else None #if state != prev or tag != prev_tag: if state_form.changed_data: save_document_in_history(doc) old_description = doc.friendly_state() if 'state' in state_form.changed_data: doc.set_state(state) if 'substate' in state_form.changed_data: if prev_tag: doc.tags.remove(prev_tag) if tag: doc.tags.add(tag) new_description = doc.friendly_state() e = log_state_changed(request, doc, login, new_description, old_description) doc.time = e.time doc.save() email_state_changed(request, doc, e.desc) email_owner(request, doc, doc.ad, login, e.desc) if state.slug == "lc-req": request_last_call(request, doc) messages.success(request, 'Document state updated') url = reverse('telechat_doc_detail', kwargs={ 'date': date, 'name': name }) return HttpResponseRedirect(url) else: formset = BallotFormset(initial=initial_ballot) state_form = ChangeStateForm(initial=initial_state) # if this is a conflict review document add referenced document if doc.type_id == 'conflrev': conflictdoc = doc.relateddocument_set.get( relationship__slug='conflrev').target.document else: conflictdoc = None return render_to_response( 'telechat/doc.html', { 'date': date, 'document': doc, 'conflictdoc': conflictdoc, 'agenda': agenda, 'formset': formset, 'header': header, 'open_positions': open_positions, 'state_form': state_form, 'writeup': writeup, 'nav_start': nav_start, 'nav_end': nav_end }, RequestContext(request, {}), )
def last_call(request, name): """Edit the Last Call Text for this status change and possibly request IETF LC""" status_change = get_object_or_404(Document, type="statchg", name=name) login = request.user.get_profile() last_call_event = status_change.latest_event(WriteupDocEvent, type="changed_last_call_text") if not last_call_event: last_call_event = generate_last_call_text(request, status_change) form = LastCallTextForm(initial=dict(last_call_text=last_call_event.text)) if request.method == 'POST': if "save_last_call_text" in request.POST or "send_last_call_request" in request.POST: form = LastCallTextForm(request.POST) if form.is_valid(): t = form.cleaned_data['last_call_text'] if t != last_call_event.text: e = WriteupDocEvent(doc=status_change, by=login) e.by = login e.type = "changed_last_call_text" e.desc = "Last call announcement was changed" e.text = t e.save() if "send_last_call_request" in request.POST: save_document_in_history(status_change) old_description = status_change.friendly_state() status_change.set_state( State.objects.get(type='statchg', slug='lc-req')) new_description = status_change.friendly_state() e = log_state_changed(request, status_change, login, new_description, old_description) status_change.time = e.time status_change.save() request_last_call(request, status_change) return render_to_response( 'idrfc/last_call_requested.html', dict( doc=status_change, url=status_change.get_absolute_url(), ), context_instance=RequestContext(request)) if "regenerate_last_call_text" in request.POST: e = generate_last_call_text(request, status_change) form = LastCallTextForm(initial=dict(last_call_text=e.text)) return render_to_response('doc/status_change/last_call.html', dict( doc=status_change, back_url=status_change.get_absolute_url(), last_call_event=last_call_event, last_call_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.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))