Add IANA expert review tracking. Commit ready for merge.
- Legacy-Id: 16656
This commit is contained in:
parent
38244111e4
commit
e45a32e49f
|
@ -12,7 +12,7 @@ from .models import (StateType, State, RelatedDocument, DocumentAuthor, Document
|
|||
StateDocEvent, ConsensusDocEvent, BallotType, BallotDocEvent, WriteupDocEvent, LastCallDocEvent,
|
||||
TelechatDocEvent, BallotPositionDocEvent, ReviewRequestDocEvent, InitialReviewDocEvent,
|
||||
AddedMessageEvent, SubmissionDocEvent, DeletedEvent, EditedAuthorsDocEvent, DocumentURL,
|
||||
ReviewAssignmentDocEvent )
|
||||
ReviewAssignmentDocEvent, IanaExpertDocEvent )
|
||||
|
||||
|
||||
class StateTypeAdmin(admin.ModelAdmin):
|
||||
|
@ -155,7 +155,7 @@ admin.site.register(InitialReviewDocEvent, DocEventAdmin)
|
|||
admin.site.register(AddedMessageEvent, DocEventAdmin)
|
||||
admin.site.register(SubmissionDocEvent, DocEventAdmin)
|
||||
admin.site.register(EditedAuthorsDocEvent, DocEventAdmin)
|
||||
|
||||
admin.site.register(IanaExpertDocEvent, DocEventAdmin)
|
||||
|
||||
class DeletedEventAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'content_type', 'json', 'by', 'time']
|
||||
|
|
59
ietf/doc/migrations/0024_iana_experts.py
Normal file
59
ietf/doc/migrations/0024_iana_experts.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
# Copyright The IETF Trust 2019, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.23 on 2019-08-07 12:07
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
StateType = apps.get_model('doc','StateType')
|
||||
State = apps.get_model('doc','State')
|
||||
|
||||
StateType.objects.create(slug='draft-iana-experts',label='IANA Experts State')
|
||||
State.objects.create(type_id='draft-iana-experts',
|
||||
slug='need-experts',
|
||||
name='Need IANA Expert(s)',
|
||||
used=True,
|
||||
desc='One or more registries need experts assigned',
|
||||
order=0
|
||||
)
|
||||
State.objects.create(type_id='draft-iana-experts',
|
||||
slug='reviews-assigned',
|
||||
name='Reviews assigned',
|
||||
used=True,
|
||||
desc='One or more expert reviews have been assigned',
|
||||
order=1
|
||||
)
|
||||
State.objects.create(type_id='draft-iana-experts',
|
||||
slug='expert-issues',
|
||||
name='Issues identified',
|
||||
used=True,
|
||||
desc='Some expert reviewers have identified issues',
|
||||
order=2
|
||||
)
|
||||
State.objects.create(type_id='draft-iana-experts',
|
||||
slug='reviewers-ok',
|
||||
name='Expert Reviews OK',
|
||||
used=True,
|
||||
desc='All expert reviews have been completed with no blocking issues',
|
||||
order=2
|
||||
)
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
StateType = apps.get_model('doc','StateType')
|
||||
State = apps.get_model('doc','State')
|
||||
|
||||
State.objects.filter(type_id='draft-iana-experts', slug__in=('need-experts','reviews-assigned','reviews-complete')).delete()
|
||||
StateType.objects.filter(slug='draft-iana-experts').delete()
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('doc', '0023_one_to_many_docalias'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse)
|
||||
]
|
24
ietf/doc/migrations/0025_ianaexpertdocevent.py
Normal file
24
ietf/doc/migrations/0025_ianaexpertdocevent.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Copyright The IETF Trust 2019, All Rights Reserved
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.23 on 2019-08-07 12:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('doc', '0024_iana_experts'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='IanaExpertDocEvent',
|
||||
fields=[
|
||||
('docevent_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='doc.DocEvent')),
|
||||
],
|
||||
bases=('doc.docevent',),
|
||||
),
|
||||
]
|
|
@ -1052,6 +1052,9 @@ class DocEvent(models.Model):
|
|||
class NewRevisionDocEvent(DocEvent):
|
||||
pass
|
||||
|
||||
class IanaExpertDocEvent(DocEvent):
|
||||
pass
|
||||
|
||||
class StateDocEvent(DocEvent):
|
||||
state_type = ForeignKey(StateType)
|
||||
state = ForeignKey(State, blank=True, null=True)
|
||||
|
|
|
@ -16,7 +16,8 @@ from ietf.doc.models import (BallotType, DeletedEvent, StateType, State, Documen
|
|||
TelechatDocEvent, DocReminder, LastCallDocEvent, NewRevisionDocEvent, WriteupDocEvent,
|
||||
InitialReviewDocEvent, DocHistoryAuthor, BallotDocEvent, RelatedDocument,
|
||||
RelatedDocHistory, BallotPositionDocEvent, AddedMessageEvent, SubmissionDocEvent,
|
||||
ReviewRequestDocEvent, ReviewAssignmentDocEvent, EditedAuthorsDocEvent, DocumentURL)
|
||||
ReviewRequestDocEvent, ReviewAssignmentDocEvent, EditedAuthorsDocEvent, DocumentURL,
|
||||
IanaExpertDocEvent )
|
||||
|
||||
from ietf.name.resources import BallotPositionNameResource, DocTypeNameResource
|
||||
class BallotTypeResource(ModelResource):
|
||||
|
@ -713,3 +714,27 @@ class ReviewAssignmentDocEventResource(ModelResource):
|
|||
"state": ALL_WITH_RELATIONS,
|
||||
}
|
||||
api.doc.register(ReviewAssignmentDocEventResource())
|
||||
|
||||
|
||||
from ietf.person.resources import PersonResource
|
||||
class IanaExpertDocEventResource(ModelResource):
|
||||
by = ToOneField(PersonResource, 'by')
|
||||
doc = ToOneField(DocumentResource, 'doc')
|
||||
docevent_ptr = ToOneField(DocEventResource, 'docevent_ptr')
|
||||
class Meta:
|
||||
queryset = IanaExpertDocEvent.objects.all()
|
||||
serializer = api.Serializer()
|
||||
cache = SimpleCache()
|
||||
#resource_name = 'ianaexpertdocevent'
|
||||
ordering = ['docevent_ptr', ]
|
||||
filtering = {
|
||||
"id": ALL,
|
||||
"time": ALL,
|
||||
"type": ALL,
|
||||
"rev": ALL,
|
||||
"desc": ALL,
|
||||
"by": ALL_WITH_RELATIONS,
|
||||
"doc": ALL_WITH_RELATIONS,
|
||||
"docevent_ptr": ALL_WITH_RELATIONS,
|
||||
}
|
||||
api.doc.register(IanaExpertDocEventResource())
|
||||
|
|
|
@ -19,7 +19,7 @@ import debug # pyflakes:ignore
|
|||
from ietf.doc.factories import IndividualDraftFactory, WgDraftFactory, RgDraftFactory, DocEventFactory
|
||||
from ietf.doc.models import ( Document, DocReminder, DocEvent,
|
||||
ConsensusDocEvent, LastCallDocEvent, RelatedDocument, State, TelechatDocEvent,
|
||||
WriteupDocEvent, DocRelationshipName)
|
||||
WriteupDocEvent, DocRelationshipName, IanaExpertDocEvent )
|
||||
from ietf.doc.utils import get_tags_for_stream_id, create_ballot_if_not_open
|
||||
from ietf.name.models import StreamName, DocTagName
|
||||
from ietf.group.factories import GroupFactory, RoleFactory
|
||||
|
@ -200,6 +200,17 @@ class ChangeStateTests(TestCase):
|
|||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEqual(draft.get_state("draft-iana-review"), next_state)
|
||||
|
||||
def test_add_expert_review_comment(self):
|
||||
draft = WgDraftFactory()
|
||||
url = urlreverse('ietf.doc.views_draft.add_iana_experts_comment',kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, 'iana', url)
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
r = self.client.post(url,dict(comment='!2ab3x#1'))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(draft.latest_event(IanaExpertDocEvent,type='comment').desc,'!2ab3x#1')
|
||||
|
||||
|
||||
def test_request_last_call(self):
|
||||
ad = Person.objects.get(user__username="ad")
|
||||
draft = WgDraftFactory(ad=ad,states=[('draft-iesg','ad-eval')])
|
||||
|
|
|
@ -91,7 +91,8 @@ urlpatterns = [
|
|||
url(r'^%(name)s/email-aliases/$' % settings.URL_REGEXPS, RedirectView.as_view(pattern_name='ietf.doc.views_doc.document_email', permanent=False),name='ietf.doc.urls.redirect.document_email'),
|
||||
|
||||
url(r'^%(name)s/edit/state/$' % settings.URL_REGEXPS, views_draft.change_state), # IESG state
|
||||
url(r'^%(name)s/edit/state/(?P<state_type>iana-action|iana-review)/$' % settings.URL_REGEXPS, views_draft.change_iana_state),
|
||||
url(r'^%(name)s/edit/state/(?P<state_type>iana-action|iana-review|iana-experts)/$' % settings.URL_REGEXPS, views_draft.change_iana_state),
|
||||
url(r'^%(name)s/edit/ianaexpertcomment/$' % settings.URL_REGEXPS, views_draft.add_iana_experts_comment),
|
||||
url(r'^%(name)s/edit/info/$' % settings.URL_REGEXPS, views_draft.edit_info),
|
||||
url(r'^%(name)s/edit/requestresurrect/$' % settings.URL_REGEXPS, views_draft.request_resurrect),
|
||||
url(r'^%(name)s/edit/submit-to-iesg/$' % settings.URL_REGEXPS, views_draft.to_iesg),
|
||||
|
|
|
@ -56,7 +56,7 @@ from django import forms
|
|||
import debug # pyflakes:ignore
|
||||
|
||||
from ietf.doc.models import ( Document, DocAlias, DocHistory, DocEvent, BallotDocEvent,
|
||||
ConsensusDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent,
|
||||
ConsensusDocEvent, NewRevisionDocEvent, TelechatDocEvent, WriteupDocEvent, IanaExpertDocEvent,
|
||||
IESG_BALLOT_ACTIVE_STATES, STATUSCHANGE_RELATIONS )
|
||||
from ietf.doc.utils import ( add_links_in_new_revision_events, augment_events_with_revision,
|
||||
can_adopt_draft, can_unadopt_draft, get_chartering_type, get_tags_for_stream_id,
|
||||
|
@ -396,6 +396,9 @@ def document_main(request, name, rev=None):
|
|||
review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.name, [])
|
||||
no_review_from_teams = no_review_from_teams_on_doc(doc, rev or doc.rev)
|
||||
|
||||
exp_comment = doc.latest_event(IanaExpertDocEvent,type="comment")
|
||||
iana_experts_comment = exp_comment and exp_comment.desc
|
||||
|
||||
return render(request, "doc/document_draft.html",
|
||||
dict(doc=doc,
|
||||
group=group,
|
||||
|
@ -452,6 +455,8 @@ def document_main(request, name, rev=None):
|
|||
rfc_editor_state=doc.get_state("draft-rfceditor"),
|
||||
iana_review_state=doc.get_state("draft-iana-review"),
|
||||
iana_action_state=doc.get_state("draft-iana-action"),
|
||||
iana_experts_state=doc.get_state("draft-iana-experts"),
|
||||
iana_experts_comment=iana_experts_comment,
|
||||
started_iesg_process=started_iesg_process,
|
||||
shepherd_writeup=shepherd_writeup,
|
||||
search_archive=search_archive,
|
||||
|
|
|
@ -25,7 +25,7 @@ import debug # pyflakes:ignore
|
|||
|
||||
from ietf.doc.models import ( Document, DocAlias, RelatedDocument, State,
|
||||
StateType, DocEvent, ConsensusDocEvent, TelechatDocEvent, WriteupDocEvent, StateDocEvent,
|
||||
IESG_SUBSTATE_TAGS)
|
||||
IanaExpertDocEvent, IESG_SUBSTATE_TAGS)
|
||||
from ietf.doc.mails import ( email_pulled_from_rfc_queue, email_resurrect_requested,
|
||||
email_resurrection_completed, email_state_changed, email_stream_changed,
|
||||
email_stream_state_changed, email_stream_tags_changed, extra_automation_headers,
|
||||
|
@ -188,6 +188,23 @@ def change_state(request, name):
|
|||
next_states=next_states,
|
||||
to_iesg_eval=to_iesg_eval))
|
||||
|
||||
class AddIanaExpertsCommentForm(forms.Form):
|
||||
comment = forms.CharField(required=True, widget=forms.Textarea, strip=False)
|
||||
|
||||
@role_required('Secretariat', 'IANA')
|
||||
def add_iana_experts_comment(request, name):
|
||||
doc = get_object_or_404(Document, docalias__name = name)
|
||||
if request.method == 'POST':
|
||||
form = AddIanaExpertsCommentForm(request.POST)
|
||||
if form.is_valid():
|
||||
IanaExpertDocEvent.objects.create(doc=doc, rev=doc.rev, by=request.user.person, type="comment", desc=form.cleaned_data['comment'])
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
else:
|
||||
form = AddIanaExpertsCommentForm()
|
||||
|
||||
return render(request, 'doc/draft/add_iana_experts_comment.html', dict(form=form, doc=doc))
|
||||
|
||||
|
||||
class ChangeIanaStateForm(forms.Form):
|
||||
state = forms.ModelChoiceField(State.objects.all(), required=False)
|
||||
|
||||
|
@ -197,6 +214,7 @@ class ChangeIanaStateForm(forms.Form):
|
|||
choices = State.objects.filter(used=True, type=state_type).order_by("order").values_list("pk", "name")
|
||||
self.fields['state'].choices = [("", "-------")] + list(choices)
|
||||
|
||||
|
||||
@role_required('Secretariat', 'IANA')
|
||||
def change_iana_state(request, name, state_type):
|
||||
"""Change IANA review state of Internet Draft. Normally, this is done via
|
||||
|
|
|
@ -514,34 +514,69 @@
|
|||
</tbody>
|
||||
{% endif %}
|
||||
|
||||
{% if iana_review_state %}
|
||||
<tbody class="meta">
|
||||
<tr>
|
||||
<th>IANA</th>
|
||||
<th><a href="{% url "ietf.help.views.state" doc=doc.type.slug type="iana-review" %}">IANA review state</a></th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.change_iana_state' name=doc.name state_type="iana-review" %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_review_state }}
|
||||
</td>
|
||||
</tr>
|
||||
{% if can_edit_iana_state or iana_review_state or iana_experts_state or iana_experts_comment %}
|
||||
<tbody class="meta">
|
||||
{% if iana_review_state or can_edit_iana_state %}
|
||||
<tr>
|
||||
<th>IANA</th>
|
||||
<th><a href="{% url "ietf.help.views.state" doc=doc.type.slug type="iana-review" %}">IANA review state</a></th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.change_iana_state' name=doc.name state_type="iana-review" %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_review_state }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>IANA action state</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.change_iana_state' name=doc.name state_type="iana-action" %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_action_state }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
{% if iana_action_state or can_edit_iana_state %}
|
||||
<tr>
|
||||
<th>{% if not can_edit_iana_state and not iana_review_state %}IANA{% endif %}</th>
|
||||
<th><a href="{% url "ietf.help.views.state" doc=doc.type.slug type="iana-action" %}">IANA action state</a></th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.change_iana_state' name=doc.name state_type="iana-action" %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_action_state }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if iana_experts_state or can_edit_iana_state %}
|
||||
<tr>
|
||||
<th>{% if not can_edit_iana_state and not iana_review_state and not iana_action_state %}IANA{% endif %}</th>
|
||||
<th><a href="{% url "ietf.help.views.state" doc=doc.type.slug type="iana-experts" %}">IANA expert review state</a></th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.change_iana_state' name=doc.name state_type="iana-experts" %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_experts_state }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
{% if iana_experts_comment or can_edit_iana_state %}
|
||||
<tr>
|
||||
<th>{% if not can_edit_iana_state and not iana_review_state and not iana_action_state and not iana_experts_state %}IANA{% endif %}</th>
|
||||
<th>IANA expert review comments</th>
|
||||
<td class="edit">
|
||||
{% if can_edit_iana_state and not snapshot %}
|
||||
<a class="btn btn-default btn-xs" href="{% url 'ietf.doc.views_draft.add_iana_experts_comment' name=doc.name %}">Edit</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ iana_experts_comment }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
</tbody>
|
||||
{% endif %}
|
||||
|
||||
<tbody class="meta">
|
||||
|
|
24
ietf/templates/doc/draft/add_iana_experts_comment.html
Normal file
24
ietf/templates/doc/draft/add_iana_experts_comment.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% extends "base.html" %}
|
||||
{# Copyright The IETF Trust 2019, All Rights Reserved #}
|
||||
{% load origin %}
|
||||
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block title %}Add IANA Experts Review State comment for {{ doc }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% origin %}
|
||||
<h1>Add IANA Experts Review State comment<br><small>{{ doc }}</small></h1>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
<p class="help-block">The comment will be added to the history trail.</p>
|
||||
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<a class="btn btn-default pull-right" href="{% url "ietf.doc.views_doc.document_main" name=doc.name %}">Back</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue