示例#1
0
文件: lastcall.py 项目: algby/ietfdb
def expire_last_call(doc):
    if doc.type_id == 'draft':
        new_state = State.objects.get(used=True, type="draft-iesg", slug="writeupw")
        e = doc.latest_event(WriteupDocEvent, type="changed_ballot_writeup_text")
        if e and "Relevant content can frequently be found in the abstract" not in e.text:
            # if boiler-plate text has been removed, we assume the
            # write-up has been written
            new_state = State.objects.get(used=True, type="draft-iesg", slug="goaheadw")
    elif doc.type_id == 'statchg':
        new_state = State.objects.get(used=True, type="statchg", slug="goahead")
    else:
        raise ValueError("Unexpected document type to expire_last_call(): %s" % doc.type)

    save_document_in_history(doc)

    prev_state = doc.get_state(new_state.type_id)
    doc.set_state(new_state)

    prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
    doc.tags.remove(*prev_tags)

    system = Person.objects.get(name="(System)")
    e = add_state_change_event(doc, system, prev_state, new_state, prev_tags=prev_tags, new_tags=[])
                    
    doc.time = (e and e.time) or datetime.datetime.now()
    doc.save()

    email_last_call_expired(doc)
示例#2
0
def do_replace(draft, request):
    'Perform document replace'
    
    save_document_in_history(draft)

    replaced = request.session['data']['replaced']          # a DocAlias
    replaced_by = request.session['data']['replaced_by']    # a Document

    # change state and update last modified
    draft.set_state(State.objects.get(type="draft", slug="repl"))
    draft.time = datetime.datetime.now()
    draft.save()

    # create relationship
    RelatedDocument.objects.create(source=replaced_by,
                                   target=replaced,
                                   relationship=DocRelationshipName.objects.get(slug='replaces'))

    # create DocEvent
    # no replace DocEvent at this time, Jan 2012
    
    # move replaced document to archive
    archive_draft_files(replaced.document.name + '-' + replaced.document.rev)

    # send announcement
    announcement_from_form(request.session['email'],by=request.user.person)

    return
示例#3
0
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))
示例#4
0
    def test_document_primary_and_history_views(self):
        make_test_data()

        # Ensure primary views of both current and historic versions of documents works
        for docname in ["draft-imaginary-independent-submission",
                        "conflict-review-imaginary-irtf-submission",
                        "status-change-imaginary-mid-review",
                        "charter-ietf-mars",
                        "agenda-42-mars",
                        "minutes-42-mars",
                        "slides-42-mars-1",
                       ]:
            doc = Document.objects.get(name=docname)
            # give it some history
            save_document_in_history(doc)
            doc.rev="01"
            doc.save()

            r = self.client.get(urlreverse("doc_view", kwargs=dict(name=doc.name)))
            self.assertEqual(r.status_code, 200)
            self.assertTrue("%s-01"%docname in unicontent(r))
    
            r = self.client.get(urlreverse("doc_view", kwargs=dict(name=doc.name,rev="01")))
            self.assertEqual(r.status_code, 302)
     
            r = self.client.get(urlreverse("doc_view", kwargs=dict(name=doc.name,rev="00")))
            self.assertEqual(r.status_code, 200)
            self.assertTrue("%s-00"%docname in unicontent(r))
示例#5
0
def expire_draft(doc):
    # clean up files
    move_draft_files_to_archive(doc, doc.rev)

    # change the state
    system = Person.objects.get(name="(System)")

    save_document_in_history(doc)
    if doc.latest_event(type='started_iesg_process'):
        dead_state = State.objects.get(used=True, type="draft-iesg", slug="dead")
        prev = doc.get_state("draft-iesg")
        prev_tag = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
        prev_tag = prev_tag[0] if prev_tag else None
        if prev != dead_state:
            doc.set_state(dead_state)
            if prev_tag:
                doc.tags.remove(prev_tag)
            log_state_changed(None, doc, system, prev, prev_tag)

        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()
示例#6
0
def assign_shepherd(user, internetdraft, shepherd):
    if internetdraft.shepherd == shepherd:
        return

    from ietf.doc.models import save_document_in_history, DocEvent, Document

    # saving the proxy object is a bit of a mess, so convert it to a
    # proper document
    doc = Document.objects.get(name=internetdraft.name)

    save_document_in_history(doc)

    doc.time = datetime.datetime.now()
    doc.shepherd = shepherd
    doc.save()

    e = DocEvent(type="changed_document")
    e.time = doc.time
    e.doc = doc
    e.by = user.get_profile()
    if not shepherd:
        e.desc = u"Unassigned shepherd"
    else:
        e.desc = u"Changed shepherd to %s" % shepherd.plain_name()
    e.save()

    # update proxy too
    internetdraft.shepherd = shepherd
示例#7
0
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))
示例#8
0
def do_undefer_ballot(request, doc):
    '''
    Helper function to perform undefer of ballot.  Takes the Request object, for use in 
    logging, and the Document object.
    '''
    login = request.user.person
    telechat_date = TelechatDate.objects.active().order_by("date")[0].date
    save_document_in_history(doc)

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

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

    prev_state = doc.get_state(new_state.type_id if new_state else None)

    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()

    update_telechat(request, doc, login, telechat_date)
    email_state_changed(request, doc, e.desc)
    email_ballot_undeferred(request, doc, login.plain_name(), telechat_date)
示例#9
0
文件: expire.py 项目: algby/ietfdb
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()
示例#10
0
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))
示例#11
0
文件: forms.py 项目: mcr/ietfdb
def assign_shepherd(user, internetdraft, shepherd):
    if internetdraft.shepherd == shepherd:
        return
    
    from ietf.doc.models import save_document_in_history, DocEvent, Document

    # saving the proxy object is a bit of a mess, so convert it to a
    # proper document
    doc = Document.objects.get(name=internetdraft.name)
    
    save_document_in_history(doc)

    doc.time = datetime.datetime.now()
    doc.shepherd = shepherd
    doc.save()

    e = DocEvent(type="changed_document")
    e.time = doc.time
    e.doc = doc
    e.by = user.get_profile()
    if not shepherd:
        e.desc = u"Unassigned shepherd"
    else:
        e.desc = u"Changed shepherd to %s" % shepherd.plain_name()
    e.save()

    # update proxy too
    internetdraft.shepherd = shepherd
示例#12
0
def do_revision(draft, request):
    '''
    This function handles adding a new revision of an existing Internet-Draft.  
    Prerequisites: draft must be active
    Input: title, revision_date, pages, abstract, file input fields to upload new 
    draft document(s)
    Actions
    - move current doc(s) to archive directory
    - upload new docs to live dir
    - save doc in history
    - increment revision 
    - reset expires
    - create DocEvent
    - handle sub-state
    - schedule notification
    '''
    
    # TODO this behavior may change with archive strategy
    archive_draft_files(draft.name + '-' + draft.rev)
    
    save_document_in_history(draft)

    # save form data
    form = BaseRevisionModelForm(request.session['data'],instance=draft)
    if form.is_valid():
        new_draft = form.save()
    else:
        raise Exception(form.errors)
        raise Exception('Problem with input data %s' % form.data)

    # set revision and expires
    new_draft.rev = request.session['filename'][-2:]
    new_draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
    new_draft.time = datetime.datetime.now()
    new_draft.save()
    
    # create DocEvent
    NewRevisionDocEvent.objects.create(type='new_revision',
                                       by=request.user.person,
                                       doc=draft,
                                       rev=new_draft.rev,
                                       desc='New revision available',
                                       time=draft.time)

    handle_substate(new_draft)
    
    # move uploaded files to production directory
    promote_files(new_draft, request.session['file_type'])
    
    # save the submission record
    post_submission(request)

    # send announcement if we are in IESG process
    if new_draft.get_state('draft-iesg'):
        announcement_from_form(request.session['email'],by=request.user.person)

    return
示例#13
0
def update_tags(request, obj, comment, person, set_tags=[], reset_tags=[], extra_notify=[]):
    if settings.USE_DB_REDESIGN_PROXY_CLASSES:
        doc = Document.objects.get(pk=obj.pk)
        save_document_in_history(doc)

        obj.tags.remove(*reset_tags)
        obj.tags.add(*set_tags)

        doc.time = datetime.datetime.now()

        e = DocEvent(type="changed_document", time=doc.time, by=person, doc=doc)
        l = []
        if set_tags:
            l.append(u"Annotation tag%s %s set." % (pluralize(set_tags), ", ".join(x.name for x in set_tags)))
        if reset_tags:
            l.append(u"Annotation tag%s %s cleared." % (pluralize(reset_tags), ", ".join(x.name for x in reset_tags)))
        e.desc = " ".join(l)
        e.save()

        receivers = get_notification_receivers(doc, extra_notify)
        send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                  u"Annotations tags changed for draft %s" % doc.name,
                  'ietfworkflows/annotation_tags_updated_mail.txt',
                  dict(doc=doc,
                       entry=dict(setted=", ".join(x.name for x in set_tags),
                                  unsetted=", ".join(x.name for x in reset_tags),
                                  change_date=doc.time,
                                  person=person,
                                  comment=comment)))
        return

    ctype = ContentType.objects.get_for_model(obj)
    setted = []
    resetted = []
    for tag in set_tags:
        if isinstance(tag, basestring):
            if set_tag_by_name(obj, tag):
                setted.append(tag)
        else:
            if set_tag(obj, tag):
                setted.append(tag.name)
    for tag in reset_tags:
        if isinstance(tag, basestring):
            if reset_tag_by_name(obj, tag):
                resetted.append(tag)
        else:
            if reset_tag(obj, tag):
                resetted.append(tag.name)
    entry = ObjectAnnotationTagHistoryEntry.objects.create(
        content_type=ctype,
        content_id=obj.pk,
        setted=','.join(setted),
        unsetted=','.join(resetted),
        date=datetime.datetime.now(),
        comment=comment,
        person=person)
    notify_tag_entry(entry, extra_notify)
示例#14
0
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))
示例#15
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))
示例#16
0
文件: views.py 项目: algby/ietfdb
def edit(request, id):
    '''
    Since there's a lot going on in this function we are summarizing in the docstring.
    Also serves as a record of requirements.

    if revision number increases add document_comments and send notify-revision
    if revision date changed and not the number return error
    check if using restricted words (?)
    send notification based on check box
    revision date = now if a new status box checked add_id5.cfm 
    (notify_[resurrection,revision,updated,extended])
    if rfcnum="" rfcnum=0
    if status != 2, expired_tombstone="0"
    if new revision move current txt and ps files to archive directory (add_id5.cfm)
    if status > 3 create tombstone, else send revision notification (EmailIDRevision.cfm)
    '''
    draft = get_object_or_404(Document, name=id)
    
    if request.method == 'POST':
        button_text = request.POST.get('submit', '')
        if button_text == 'Cancel':
            return redirect('drafts_view', id=id)

        form = EditModelForm(request.POST, instance=draft)
        if form.is_valid():
            if form.changed_data:
                save_document_in_history(draft)
                DocEvent.objects.create(type='changed_document',
                                        by=request.user.person,
                                        doc=draft,
                                        desc='Changed field(s): %s' % ','.join(form.changed_data))
                # see EditModelForm.save() for detailed logic
                form.save()
                
                messages.success(request, 'Draft modified successfully!')
            
            return redirect('drafts_view', id=id)
        else:
            #assert False, form.errors
            pass
    else:
        form = EditModelForm(instance=draft)
    
    return render_to_response('drafts/edit.html', {
        'form': form,
        'draft': draft},
        RequestContext(request, {}),
    )
示例#17
0
def defer_ballot(request, name):
    """Signal post-pone of ballot, notifying relevant parties."""
    doc = get_object_or_404(Document, docalias__name=name)
    if doc.type_id not in ('draft','conflrev','statchg'):
        raise Http404()
    interesting_state = dict(draft='draft-iesg',conflrev='conflrev',statchg='statchg')
    state = doc.get_state(interesting_state[doc.type_id])
    if not state or state.slug=='defer' or not doc.telechat_date():
        raise Http404()

    login = request.user.person
    telechat_date = TelechatDate.objects.active().order_by("date")[1].date

    if request.method == 'POST':
        save_document_in_history(doc)

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

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

        prev_state = doc.get_state(new_state.type_id if new_state else None)

        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()

        email_state_changed(request, doc, e.desc)

        update_telechat(request, doc, login, telechat_date)
        email_ballot_deferred(request, doc, login.plain_name(), telechat_date)

        return HttpResponseRedirect(doc.get_absolute_url())
  
    return render_to_response('doc/ballot/defer_ballot.html',
                              dict(doc=doc,
                                   telechat_date=telechat_date,
                                   back_url=doc.get_absolute_url()),
                              context_instance=RequestContext(request))
示例#18
0
def do_update(draft,request):
    '''
     Actions
    - increment revision #
    - reset expires
    - create DocEvent
    - do substate check
    - change state to Active
    '''
    save_document_in_history(draft)
    
    # save form data
    form = BaseRevisionModelForm(request.session['data'],instance=draft)
    if form.is_valid():
        new_draft = form.save()
    else:
        raise Exception('Problem with input data %s' % form.data)

    handle_substate(new_draft)
    
    # update draft record
    new_draft.rev = os.path.splitext(request.session['data']['filename'])[0][-2:]
    new_draft.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE)
    new_draft.time = datetime.datetime.now()
    new_draft.save()
    
    new_draft.set_state(State.objects.get(type="draft", slug="active"))
    
    # create DocEvent
    NewRevisionDocEvent.objects.create(type='new_revision',
                                       by=request.user.person,
                                       doc=new_draft,
                                       rev=new_draft.rev,
                                       desc='New revision available',
                                       time=new_draft.time)
    
    # move uploaded files to production directory
    promote_files(new_draft, request.session['file_type'])
    
    # save the submission record
    post_submission(request)

    # send announcement
    announcement_from_form(request.session['email'],by=request.user.person)
    
    return
示例#19
0
def change_title(request, name, option=None):
    """Change title of charter, notifying parties as necessary and
    logging the title as a comment."""
    charter = get_object_or_404(Document, type="charter", name=name)
    group = charter.group
    if not can_manage_group_type(request.user, group.type_id):
        return HttpResponseForbidden("You don't have permission to access this view")
    login = request.user.person
    if request.method == 'POST':
        form = ChangeTitleForm(request.POST, charter=charter)
        if form.is_valid():
            clean = form.cleaned_data
            charter_rev = charter.rev
            new_title = clean['charter_title']
            comment = clean['comment'].rstrip()
            message = clean['message']
            prev_title = charter.title
            if new_title != prev_title:
                # Charter title changed
                save_document_in_history(charter)
                charter.title=new_title
                charter.rev = charter_rev
                if not comment:
                    comment = "Changed charter title from '%s' to '%s'." % (prev_title, new_title)
                event = DocEvent(type="added_comment", doc=charter, by=login)
                event.desc = comment
                event.save()
                charter.time = datetime.datetime.now()
                charter.save()
                if message:
                    email_admin_re_charter(request, group, "Charter title changed to %s" % new_title, message,'charter_state_edit_admin_needed')
                email_state_changed(request, charter, "Title changed to %s." % new_title,'doc_state_edited')
            return redirect('doc_view', name=charter.name)
    else:
        form = ChangeTitleForm(charter=charter)
    title = "Change charter title of %s %s" % (group.acronym, group.type.name)
    return render_to_response('doc/charter/change_title.html',
                              dict(form=form,
                                   doc=group.charter,
                                   login=login,
                                   title=title,
                                   ),
                              context_instance=RequestContext(request))
示例#20
0
def update_stream(request, doc, comment, person, to_stream, extra_notify=[]):
    if settings.USE_DB_REDESIGN_PROXY_CLASSES:
        doc = Document.objects.get(pk=doc.pk)
        save_document_in_history(doc)

        doc.time = datetime.datetime.now()
        from_stream = doc.stream
        doc.stream = to_stream
        doc.save()

        e = DocEvent(type="changed_stream", time=doc.time, by=person, doc=doc)
        e.desc = u"Stream changed to <b>%s</b>" % to_stream.name
        if from_stream:
            e.desc += u"from %s" % from_stream.name
        e.save()

        receivers = get_notification_receivers(doc, extra_notify)
        send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                  u"Stream changed for draft %s" % doc.name,
                  'ietfworkflows/stream_updated_mail.txt',
                  dict(doc=doc,
                       entry=dict(from_stream=from_stream,
                                  to_stream=to_stream,
                                  transition_date=doc.time,
                                  person=person,
                                  comment=comment)))
        return

    ctype = ContentType.objects.get_for_model(doc)
    from_stream = get_stream_from_draft(doc)
    to_stream = set_stream_for_draft(doc, to_stream)
    entry = ObjectStreamHistoryEntry.objects.create(
        content_type=ctype,
        content_id=doc.pk,
        from_stream=from_stream and from_stream.name or '',
        to_stream=to_stream and to_stream.name or '',
        date=datetime.datetime.now(),
        comment=comment,
        person=person)
    notify_stream_entry(entry, extra_notify)
示例#21
0
def do_extend(draft, request):
    '''
    Actions:
    - update revision_date
    - set extension_date
    '''
    save_document_in_history(draft)

    draft.expires = request.session['data']['expiration_date']
    draft.time = datetime.datetime.now()
    draft.save()
    
    DocEvent.objects.create(type='changed_document',
                            by=request.user.person,
                            doc=draft,
                            time=draft.time,
                            desc='extend_expiry')
                            
    # save scheduled announcement
    announcement_from_form(request.session['email'],by=request.user.person)
    
    return
示例#22
0
def make_notify_changed_event(request, doc, by, new_notify, time=None):

    # FOR REVIEW: This preserves the behavior from when
    # drafts and charters had separate edit_notify
    # functions. If it should be unified, there should
    # also be a migration function cause historic
    # events to match
    if doc.type.slug=='charter':
        event_type = 'changed_document'
        save_document_in_history(doc)
    else:
        event_type = 'added_comment'

    e = DocEvent(type=event_type, doc=doc, by=by)
    e.desc = "Notification list changed to %s" % (escape(new_notify) or "none")
    if doc.notify:
        e.desc += " from %s" % escape(doc.notify)
    if time:
        e.time = time
    e.save()

    return e
示例#23
0
    def test_document_ballot(self):
        doc = make_test_data()
        ballot = doc.active_ballot()

        save_document_in_history(doc)

        pos = BallotPositionDocEvent.objects.create(
            doc=doc,
            ballot=ballot,
            type="changed_ballot_position",
            pos_id="yes",
            comment="Looks fine to me",
            comment_time=datetime.datetime.now(),
            ad=Person.objects.get(user__username="******"),
            by=Person.objects.get(name="(System)"))

        r = self.client.get(urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc.name)))
        self.assertEqual(r.status_code, 200)
        self.assertTrue(pos.comment in unicontent(r))

        # test with ballot_id
        r = self.client.get(urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc.name, ballot_id=ballot.pk)))
        self.assertEqual(r.status_code, 200)
        self.assertTrue(pos.comment in unicontent(r))

        # test popup too while we're at it
        r = self.client.get(urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)))
        self.assertEqual(r.status_code, 200)

        # Now simulate a new revision and make sure positions on older revisions are marked as such
        oldrev = doc.rev
        e = NewRevisionDocEvent.objects.create(doc=doc,rev='%02d'%(int(doc.rev)+1),type='new_revision',by=Person.objects.get(name="(System)"))
        save_document_in_history(doc)
        doc.rev = e.rev
        doc.save()
        r = self.client.get(urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc.name)))
        self.assertEqual(r.status_code, 200)
        self.assertTrue( '(%s for -%s)' % (pos.comment_time.strftime('%Y-%m-%d'), oldrev) in unicontent(r))
示例#24
0
def submit(request, name):
    doc = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.get_profile()

    path = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev))
    not_uploaded_yet = doc.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the status change text document doesn't actually exist yet
        next_rev = doc.rev
    else:
        next_rev = "%02d" % (int(doc.rev)+1) 

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                save_document_in_history(doc)

                doc.rev = next_rev

                e = NewRevisionDocEvent(doc=doc, by=login, type="new_revision")
                e.desc = "New version available: <b>%s-%s.txt</b>" % (doc.canonical_name(), doc.rev)
                e.rev = doc.rev
                e.save()
            
                # Save file on disk
                form.save(doc)

                doc.time = datetime.datetime.now()
                doc.save()

                return HttpResponseRedirect(reverse('doc_view', kwargs={'name': doc.name}))

        elif "reset_text" in request.POST:

            init = { "content": render_to_string("doc/status_change/initial_template.txt",dict())}
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = { "content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string("doc/status_change/initial_template.txt",
                                                dict(),
                                              )
        else:
            filename = os.path.join(settings.STATUS_CHANGE_PATH, '%s-%s.txt' % (doc.canonical_name(), doc.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render_to_response('doc/status_change/submit.html',
                              {'form': form,
                               'next_rev': next_rev,
                               'doc' : doc,
                              },
                              context_instance=RequestContext(request))
示例#25
0
def change_state(request, name, option=None):
    """Change state of an status-change document, notifying parties as necessary
       and logging the change as a comment."""
    status_change = get_object_or_404(Document, type="statchg", name=name)

    login = request.user.person

    if request.method == 'POST':
        form = ChangeStateForm(request.POST)
        if form.is_valid():
            clean = form.cleaned_data
            new_state = clean['new_state']
            comment = clean['comment'].rstrip()

            if comment:
                c = DocEvent(type="added_comment", doc=status_change, by=login)
                c.desc = comment
                c.save()

            prev_state = status_change.get_state()
            if new_state != prev_state:
                save_document_in_history(status_change)

                status_change.set_state(new_state)
                e = add_state_change_event(status_change, login, prev_state, new_state)

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

                if new_state.slug == "iesgeval":
                    create_ballot_if_not_open(status_change, login, "statchg", e.time)
                    ballot = status_change.latest_event(BallotDocEvent, type="created_ballot")
                    if has_role(request.user, "Area Director") and not status_change.latest_event(BallotPositionDocEvent, ad=login, ballot=ballot, type="changed_ballot_position"):

                        # The AD putting a status change into iesgeval who doesn't already have a position is saying "yes"
                        pos = BallotPositionDocEvent(doc=status_change, 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_status_change_eval_email(request,status_change)


                if new_state.slug == "lc-req":
                    request_last_call(request, status_change)
                    return render_to_response('doc/draft/last_call_requested.html',
                                              dict(doc=status_change,
                                                   url = status_change.get_absolute_url(),
                                                  ),
                                              context_instance=RequestContext(request))

            return redirect('doc_view', name=status_change.name)
    else:
        s = status_change.get_state()
        init = dict(new_state=s.pk if s else None,
                    type='statchg',
                    label='Status Change Evaluation State',
                   )
        form = ChangeStateForm(initial=init)

    return render_to_response('doc/change_state.html',
                              dict(form=form,
                                   doc=status_change,
                                   login=login,
                                   help_url=reverse('state_help', kwargs=dict(type="status-change")),
                                   ),
                              context_instance=RequestContext(request))
示例#26
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))
示例#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

    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))
示例#28
0
def lastcalltext(request, name):
    """Editing of the last call text"""
    doc = get_object_or_404(Document, docalias__name=name)
    if not doc.get_state("draft-iesg"):
        raise Http404()

    login = request.user.person

    existing = doc.latest_event(WriteupDocEvent, type="changed_last_call_text")
    if not existing:
        existing = generate_last_call_announcement(request, doc)
        
    form = LastCallTextForm(initial=dict(last_call_text=existing.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 != existing.text:
                    e = WriteupDocEvent(doc=doc, 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(doc)

                    prev_state = doc.get_state("draft-iesg")
                    new_state = State.objects.get(used=True, type="draft-iesg", slug='lc-req')

                    prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)

                    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=[])

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

                    email_state_changed(request, doc, e.desc)
                    email_ad(request, doc, doc.ad, login, e.desc)

                    request_last_call(request, doc)
                    
                    return render_to_response('doc/draft/last_call_requested.html',
                                              dict(doc=doc),
                                              context_instance=RequestContext(request))
        
        if "regenerate_last_call_text" in request.POST:
            e = generate_last_call_announcement(request, doc)
            
            # make sure form has the updated text
            form = LastCallTextForm(initial=dict(last_call_text=e.text))


    s = doc.get_state("draft-iesg")
    can_request_last_call = s.order < 27
    can_make_last_call = s.order < 20
    
    need_intended_status = ""
    if not doc.intended_std_level:
        need_intended_status = doc.file_tag()

    return render_to_response('doc/ballot/lastcalltext.html',
                              dict(doc=doc,
                                   back_url=doc.get_absolute_url(),
                                   last_call_form=form,
                                   can_request_last_call=can_request_last_call,
                                   can_make_last_call=can_make_last_call,
                                   need_intended_status=need_intended_status,
                                   ),
                              context_instance=RequestContext(request))
示例#29
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))
示例#30
0
文件: rfceditor.py 项目: algby/ietfdb
def update_docs_from_rfc_index(data, skip_older_than_date=None):
    std_level_mapping = {
        "Standard": StdLevelName.objects.get(slug="std"),
        "Internet Standard": StdLevelName.objects.get(slug="std"),
        "Draft Standard": StdLevelName.objects.get(slug="ds"),
        "Proposed Standard": StdLevelName.objects.get(slug="ps"),
        "Informational": StdLevelName.objects.get(slug="inf"),
        "Experimental": StdLevelName.objects.get(slug="exp"),
        "Best Current Practice": StdLevelName.objects.get(slug="bcp"),
        "Historic": StdLevelName.objects.get(slug="hist"),
        "Unknown": StdLevelName.objects.get(slug="unkn"),
        }

    stream_mapping = {
        "IETF": StreamName.objects.get(slug="ietf"),
        "INDEPENDENT": StreamName.objects.get(slug="ise"),
        "IRTF": StreamName.objects.get(slug="irtf"),
        "IAB": StreamName.objects.get(slug="iab"),
        "Legacy": StreamName.objects.get(slug="legacy"),
    }

    tag_has_errata = DocTagName.objects.get(slug='errata')
    relationship_obsoletes = DocRelationshipName.objects.get(slug="obs")
    relationship_updates = DocRelationshipName.objects.get(slug="updates")

    system = Person.objects.get(name="(System)")

    results = []
    new_rfcs = []

    for rfc_number, title, authors, rfc_published_date, current_status, updates, updated_by, obsoletes, obsoleted_by, also, draft, has_errata, stream, wg, file_formats, pages, abstract in data:

        if skip_older_than_date and rfc_published_date < skip_older_than_date:
            # speed up the process by skipping old entries
            continue

        # we assume two things can happen: we get a new RFC, or an
        # attribute has been updated at the RFC Editor (RFC Editor
        # attributes take precedence over our local attributes)

        # make sure we got the document and alias
        doc = None
        name = "rfc%s" % rfc_number
        a = DocAlias.objects.filter(name=name).select_related("document")
        if a:
            doc = a[0].document
        else:
            if draft:
                try:
                    doc = Document.objects.get(name=draft)
                except Document.DoesNotExist:
                    pass

            if not doc:
                results.append("created document %s" % name)
                doc = Document.objects.create(name=name, type=DocTypeName.objects.get(slug="draft"))

            # add alias
            DocAlias.objects.get_or_create(name=name, document=doc)
            results.append("created alias %s to %s" % (name, doc.name))

        # check attributes
        changed_attributes = {}
        changed_states = []
        created_relations = []
        other_changes = False
        if title != doc.title:
            changed_attributes["title"] = title

        if abstract and abstract != doc.abstract:
            changed_attributes["abstract"] = abstract

        if pages and int(pages) != doc.pages:
            changed_attributes["pages"] = int(pages)

        if std_level_mapping[current_status] != doc.std_level:
            changed_attributes["std_level"] = std_level_mapping[current_status]

        if doc.get_state_slug() != "rfc":
            changed_states.append(State.objects.get(used=True, type="draft", slug="rfc"))
            move_draft_files_to_archive(doc, doc.rev)

        if doc.stream != stream_mapping[stream]:
            changed_attributes["stream"] = stream_mapping[stream]

        if not doc.group: # if we have no group assigned, check if RFC Editor has a suggestion
            if wg:
                changed_attributes["group"] = Group.objects.get(acronym=wg)
            else:
                changed_attributes["group"] = Group.objects.get(type="individ")

        if not doc.latest_event(type="published_rfc"):
            e = DocEvent(doc=doc, type="published_rfc")
            # unfortunately, rfc_published_date doesn't include the correct day
            # at the moment because the data only has month/year, so
            # try to deduce it
            d = datetime.datetime.combine(rfc_published_date, datetime.time())
            synthesized = datetime.datetime.now()
            if abs(d - synthesized) > datetime.timedelta(days=60):
                synthesized = d
            else:
                direction = -1 if (d - synthesized).total_seconds() < 0 else +1
                while synthesized.month != d.month or synthesized.year != d.year:
                    synthesized += datetime.timedelta(days=direction)
            e.time = synthesized
            e.by = system
            e.desc = "RFC published"
            e.save()
            other_changes = True

            results.append("Added RFC published event: %s" % e.time.strftime("%Y-%m-%d"))
            new_rfcs.append(doc)

        for t in ("draft-iesg", "draft-stream-iab", "draft-stream-irtf", "draft-stream-ise"):
            slug = doc.get_state_slug(t)
            if slug and slug != "pub":
                changed_states.append(State.objects.get(used=True, type=t, slug="pub"))

        def parse_relation_list(l):
            res = []
            for x in l:
                if x[:3] in ("NIC", "IEN", "STD", "RTR"):
                    # try translating this to RFCs that we can handle
                    # sensibly; otherwise we'll have to ignore them
                    l = DocAlias.objects.filter(name__startswith="rfc", document__docalias__name=x.lower())
                else:
                    l = DocAlias.objects.filter(name=x.lower())

                for a in l:
                    if a not in res:
                        res.append(a)
            return res

        for x in parse_relation_list(obsoletes):
            if not RelatedDocument.objects.filter(source=doc, target=x, relationship=relationship_obsoletes):
                created_relations.append(RelatedDocument(source=doc, target=x, relationship=relationship_obsoletes))

        for x in parse_relation_list(updates):
            if not RelatedDocument.objects.filter(source=doc, target=x, relationship=relationship_updates):
                created_relations.append(RelatedDocument(source=doc, target=x, relationship=relationship_updates))

        if also:
            for a in also:
                a = a.lower()
                if not DocAlias.objects.filter(name=a):
                    DocAlias.objects.create(name=a, document=doc)
                    other_changes = True
                    results.append("Created alias %s to %s" % (a, doc.name))

        if has_errata:
            if not doc.tags.filter(pk=tag_has_errata.pk):
                changed_attributes["tags"] = list(doc.tags.all()) + [tag_has_errata]
        else:
            if doc.tags.filter(pk=tag_has_errata.pk):
                changed_attributes["tags"] = set(doc.tags.all()) - set([tag_has_errata])

        if changed_attributes or changed_states or created_relations or other_changes:
            # apply changes
            save_document_in_history(doc)
            for k, v in changed_attributes.iteritems():
                setattr(doc, k, v)
                results.append("Changed %s to %s on %s" % (k, v, doc.name))

            for s in changed_states:
                doc.set_state(s)
                results.append("Set state %s on %s" % (s, doc.name))

            for o in created_relations:
                o.save()
                results.append("Created %s" % o)

            doc.time = datetime.datetime.now()
            doc.save()

    return results, new_rfcs
示例#31
0
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))
示例#32
0
def submit(request, name):
    review = get_object_or_404(Document, type="conflrev", name=name)

    login = request.user.get_profile()

    path = os.path.join(settings.CONFLICT_REVIEW_PATH,
                        '%s-%s.txt' % (review.canonical_name(), review.rev))
    not_uploaded_yet = review.rev == "00" and not os.path.exists(path)

    if not_uploaded_yet:
        # this case is special - the conflict review text document doesn't actually exist yet
        next_rev = review.rev
    else:
        next_rev = "%02d" % (int(review.rev) + 1)

    if request.method == 'POST':
        if "submit_response" in request.POST:
            form = UploadForm(request.POST, request.FILES)
            if form.is_valid():
                save_document_in_history(review)

                review.rev = next_rev

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

                # Save file on disk
                form.save(review)

                review.time = datetime.datetime.now()
                review.save()

                return HttpResponseRedirect(
                    reverse('doc_view', kwargs={'name': review.name}))

        elif "reset_text" in request.POST:

            init = {
                "content":
                render_to_string("doc/conflict_review/review_choices.txt",
                                 dict())
            }
            form = UploadForm(initial=init)

        # Protect against handcrufted malicious posts
        else:
            form = None

    else:
        form = None

    if not form:
        init = {"content": ""}

        if not_uploaded_yet:
            init["content"] = render_to_string(
                "doc/conflict_review/review_choices.txt",
                dict(),
            )
        else:
            filename = os.path.join(
                settings.CONFLICT_REVIEW_PATH,
                '%s-%s.txt' % (review.canonical_name(), review.rev))
            try:
                with open(filename, 'r') as f:
                    init["content"] = f.read()
            except IOError:
                pass

        form = UploadForm(initial=init)

    return render_to_response('doc/conflict_review/submit.html', {
        'form':
        form,
        'next_rev':
        next_rev,
        'review':
        review,
        'conflictdoc':
        review.relateddocument_set.get(
            relationship__slug='conflrev').target.document,
    },
                              context_instance=RequestContext(request))
示例#33
0
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, {}),
    )
示例#34
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))
示例#35
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))
示例#36
0
    def save(self):
        comment = self.cleaned_data.get('comment').strip()
        weeks = self.cleaned_data.get('weeks')
        group = IETFWG.objects.get(pk=self.cleaned_data.get('group'))
        estimated_date = None
        if weeks:
            now = datetime.date.today()
            estimated_date = now + datetime.timedelta(weeks=weeks)
        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            # do changes on real Document object instead of proxy to avoid trouble
            doc = Document.objects.get(pk=self.draft.pk)
            save_document_in_history(doc)

            doc.time = datetime.datetime.now()

            if group.type.slug == "rg":
                new_stream = StreamName.objects.get(slug="irtf")
            else:
                new_stream = StreamName.objects.get(slug="ietf")

            if doc.stream != new_stream:
                e = DocEvent(type="changed_stream")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed to <b>%s</b>" % new_stream.name
                if doc.stream:
                    e.desc += u" from %s" % doc.stream.name
                e.save()
                doc.stream = new_stream

            if doc.group.pk != group.pk:
                e = DocEvent(type="changed_group")
                e.time = doc.time
                e.by = self.user.get_profile()
                e.doc = doc
                e.desc = u"Changed group to <b>%s (%s)</b>" % (
                    group.name, group.acronym.upper())
                if doc.group.type_id != "individ":
                    e.desc += " from %s (%s)" % (doc.group.name,
                                                 doc.group.acronym)
                e.save()
                doc.group_id = group.pk

            doc.save()
            self.draft = InternetDraft.objects.get(
                pk=doc.pk)  # make sure proxy object is updated
        else:
            workflow = get_workflow_for_wg(wg)
            set_workflow_for_object(self.draft, workflow)
            stream = get_stream_by_name(IETF_STREAM)
            streamed = get_streamed_draft(self.draft)
            if not streamed:
                set_stream_for_draft(self.draft, stream)
                streamed = get_streamed_draft(self.draft)
            streamed.stream = stream
            streamed.group = wg
            streamed.save()

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            from ietf.doc.models import State
            if self.draft.stream_id == "irtf":
                to_state = State.objects.get(used=True,
                                             slug="active",
                                             type="draft-stream-irtf")
            else:
                to_state = State.objects.get(used=True,
                                             slug="c-adopt",
                                             type="draft-stream-%s" %
                                             self.draft.stream_id)
        else:
            to_state = get_state_by_name(CALL_FOR_ADOPTION)
        update_state(self.request,
                     self.draft,
                     comment=comment,
                     person=self.person,
                     to_state=to_state,
                     estimated_date=estimated_date)

        if settings.USE_DB_REDESIGN_PROXY_CLASSES:
            if comment:
                e = DocEvent(type="added_comment")
                e.time = self.draft.time
                e.by = self.person
                e.doc_id = self.draft.pk
                e.desc = comment
                e.save()
示例#37
0
def edit_material(request, name=None, acronym=None, action=None, doc_type=None):
    # the materials process is not very developed, so at the moment we
    # handle everything through the same view/form

    if action == "new":
        group = get_object_or_404(Group, acronym=acronym)
        if not group.features.has_materials:
            raise Http404

        doc = None
        document_type = get_object_or_404(DocTypeName, slug=doc_type)
    else:
        doc = get_object_or_404(Document, name=name)
        group = doc.group
        document_type = doc.type

    if not can_manage_materials(request.user, group):
        return HttpResponseForbidden("You don't have permission to access this view")

    if request.method == 'POST':
        form = UploadMaterialForm(document_type, action, group, doc, request.POST, request.FILES)

        if form.is_valid():
            if action == "new":
                doc = Document()
                doc.type = document_type
                doc.group = group
                doc.rev = "00"
                doc.name = form.cleaned_data["name"]
                prev_rev = None
            else:
                save_document_in_history(doc)
                prev_rev = doc.rev

            prev_title = doc.title
            prev_state = doc.get_state()

            if "title" in form.cleaned_data:
                doc.title = form.cleaned_data["title"]

            if "abstract" in form.cleaned_data:
                doc.abstract = form.cleaned_data["abstract"]

            doc.time = datetime.datetime.now()

            if "material" in form.fields:
                if action != "new":
                    doc.rev = "%02d" % (int(doc.rev) + 1)

                f = form.cleaned_data["material"]
                file_ext = os.path.splitext(f.name)[1]

                with open(os.path.join(doc.get_file_path(), doc.name + "-" + doc.rev + file_ext), 'wb+') as dest:
                    for chunk in f.chunks():
                        dest.write(chunk)

            doc.save()

            if action == "new":
                DocAlias.objects.get_or_create(name=doc.name, document=doc)

            if prev_rev != doc.rev:
                e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev)
                e.time = doc.time
                e.by = request.user.person
                e.desc = "New version available: <b>%s-%s</b>" % (doc.name, doc.rev)
                e.save()
                
            if prev_title != doc.title:
                e = DocEvent(doc=doc, by=request.user.person, type='changed_document')
                e.desc = u"Changed title to <b>%s</b>" % doc.title
                if prev_title:
                    e.desc += u" from %s" % prev_title
                e.time = doc.time
                e.save()

            if "state" in form.cleaned_data and form.cleaned_data["state"] != prev_state:
                doc.set_state(form.cleaned_data["state"])
                add_state_change_event(doc, request.user.person, prev_state, form.cleaned_data["state"])

            return redirect("doc_view", name=doc.name)
    else:
        form = UploadMaterialForm(document_type, action, group, doc)

    return render(request, 'doc/material/edit_material.html', {
        'group': group,
        'form': form,
        'action': action,
        'document_type': document_type,
        'doc_name': doc.name if doc else "",
    })
示例#38
0
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))
示例#39
0
文件: views.py 项目: mcr/ietfdb
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, {}),
    )
示例#40
0
def update_state(request, doc, comment, person, to_state, estimated_date=None, extra_notify=[]):
    if settings.USE_DB_REDESIGN_PROXY_CLASSES:
        doc = Document.objects.get(pk=doc.pk)
        save_document_in_history(doc)

        doc.time = datetime.datetime.now()
        from_state = doc.get_state("draft-stream-%s" % doc.stream_id)
        doc.set_state(to_state)

        e = DocEvent(type="changed_document", time=doc.time, by=person, doc=doc)
        e.desc = u"%s changed to <b>%s</b> from %s" % (to_state.type.label, to_state, from_state)
        e.save()

        # reminder
        reminder_type = DocReminderTypeName.objects.get(slug="stream-s")
        try:
            reminder = DocReminder.objects.get(event__doc=doc, type=reminder_type,
                                               active=True)
        except DocReminder.DoesNotExist:
            reminder = None

        if estimated_date:
            if not reminder:
                reminder = DocReminder(type=reminder_type)

            reminder.event = e
            reminder.due = estimated_date
            reminder.active = True
            reminder.save()
        elif reminder:
            reminder.active = False
            reminder.save()

        receivers = get_notification_receivers(doc, extra_notify)
        send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                  u"State changed for draft %s" % doc.name,
                  'ietfworkflows/state_updated_mail.txt',
                  dict(doc=doc,
                       entry=dict(from_state=from_state,
                                  to_state=to_state,
                                  transition_date=doc.time,
                                  person=person,
                                  comment=comment)))

        if (to_state.slug=='sub-pub'):
            receivers = get_pubreq_receivers(doc, extra_notify)
            cc_receivers = get_pubreq_cc_receivers(doc)

            send_mail(request, receivers, settings.DEFAULT_FROM_EMAIL,
                      u"Publication has been requested for draft %s" % doc.name,
                      'ietfworkflows/state_updated_mail.txt',
                      dict(doc=doc,
                           entry=dict(from_state=from_state,
                                      to_state=to_state,
                                      transition_date=doc.time,
                                      person=person,
                                      comment=comment)), cc=cc_receivers)

        return

    ctype = ContentType.objects.get_for_model(doc)
    from_state = get_state_for_draft(doc)
    to_state = set_state_for_draft(doc, to_state, estimated_date)
    if not to_state:
        return False
    entry = ObjectWorkflowHistoryEntry.objects.create(
        content_type=ctype,
        content_id=doc.pk,
        from_state=from_state and from_state.name or '',
        to_state=to_state and to_state.name or '',
        date=datetime.datetime.now(),
        comment=comment,
        person=person)
    notify_state_entry(entry, extra_notify)