feat: remove "AD is watching" state (#7960)
* feat: remove "AD is watching" state * chore: update names.json * refactor: use idexists state, not dead * fix: remove guidance to use watching state * chore: remove references to 'watching' state * feat: remove create_in_state from edit_info view * test: update test * style: Black + move class closer to use * refactor: remove lint * fix: restore missing admonition --------- Co-authored-by: Robert Sparks <rjsparks@nostrum.com>
This commit is contained in:
parent
5ea4cc13bb
commit
fbcfa19add
|
@ -34,8 +34,8 @@ def expirable_drafts(queryset=None):
|
|||
|
||||
# Populate this first time through (but after django has been set up)
|
||||
if nonexpirable_states is None:
|
||||
# all IESG states except I-D Exists, AD Watching, and Dead block expiry
|
||||
nonexpirable_states = list(State.objects.filter(used=True, type="draft-iesg").exclude(slug__in=("idexists","watching", "dead")))
|
||||
# all IESG states except I-D Exists and Dead block expiry
|
||||
nonexpirable_states = list(State.objects.filter(used=True, type="draft-iesg").exclude(slug__in=("idexists", "dead")))
|
||||
# sent to RFC Editor and RFC Published block expiry (the latter
|
||||
# shouldn't be possible for an active draft, though)
|
||||
nonexpirable_states += list(State.objects.filter(used=True, type__in=("draft-stream-iab", "draft-stream-irtf", "draft-stream-ise"), slug__in=("rfc-edit", "pub")))
|
||||
|
|
121
ietf/doc/migrations/0024_remove_ad_is_watching_states.py
Normal file
121
ietf/doc/migrations/0024_remove_ad_is_watching_states.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
# Copyright The IETF Trust 2024, All Rights Reserved
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def get_helper(DocHistory, RelatedDocument, RelatedDocHistory, DocumentAuthor, DocHistoryAuthor):
|
||||
"""Dependency injection wrapper"""
|
||||
|
||||
def save_document_in_history(doc):
|
||||
"""Save a snapshot of document and related objects in the database.
|
||||
|
||||
Local copy of ietf.doc.utils.save_document_in_history() to avoid depending on the
|
||||
code base in a migration.
|
||||
"""
|
||||
|
||||
def get_model_fields_as_dict(obj):
|
||||
return dict((field.name, getattr(obj, field.name))
|
||||
for field in obj._meta.fields
|
||||
if field is not obj._meta.pk)
|
||||
|
||||
# copy fields
|
||||
fields = get_model_fields_as_dict(doc)
|
||||
fields["doc"] = doc
|
||||
fields["name"] = doc.name
|
||||
|
||||
dochist = DocHistory(**fields)
|
||||
dochist.save()
|
||||
|
||||
# copy many to many
|
||||
for field in doc._meta.many_to_many:
|
||||
if field.remote_field.through and field.remote_field.through._meta.auto_created:
|
||||
hist_field = getattr(dochist, field.name)
|
||||
hist_field.clear()
|
||||
hist_field.set(getattr(doc, field.name).all())
|
||||
|
||||
# copy remaining tricky many to many
|
||||
def transfer_fields(obj, HistModel):
|
||||
mfields = get_model_fields_as_dict(item)
|
||||
# map doc -> dochist
|
||||
for k, v in mfields.items():
|
||||
if v == doc:
|
||||
mfields[k] = dochist
|
||||
HistModel.objects.create(**mfields)
|
||||
|
||||
for item in RelatedDocument.objects.filter(source=doc):
|
||||
transfer_fields(item, RelatedDocHistory)
|
||||
|
||||
for item in DocumentAuthor.objects.filter(document=doc):
|
||||
transfer_fields(item, DocHistoryAuthor)
|
||||
|
||||
return dochist
|
||||
|
||||
return save_document_in_history
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
"""Mark watching draft-iesg state unused after removing it from Documents"""
|
||||
StateDocEvent = apps.get_model("doc", "StateDocEvent")
|
||||
Document = apps.get_model("doc", "Document")
|
||||
State = apps.get_model("doc", "State")
|
||||
StateType = apps.get_model("doc", "StateType")
|
||||
Person = apps.get_model("person", "Person")
|
||||
|
||||
save_document_in_history = get_helper(
|
||||
DocHistory=apps.get_model("doc", "DocHistory"),
|
||||
RelatedDocument=apps.get_model("doc", "RelatedDocument"),
|
||||
RelatedDocHistory=apps.get_model("doc", "RelatedDocHistory"),
|
||||
DocumentAuthor=apps.get_model("doc", "DocumentAuthor"),
|
||||
DocHistoryAuthor=apps.get_model("doc", "DocHistoryAuthor"),
|
||||
)
|
||||
|
||||
draft_iesg_state_type = StateType.objects.get(slug="draft-iesg")
|
||||
idexists_state = State.objects.get(type=draft_iesg_state_type, slug="idexists")
|
||||
watching_state = State.objects.get(type=draft_iesg_state_type, slug="watching")
|
||||
system_person = Person.objects.get(name="(System)")
|
||||
|
||||
# Remove state from documents that currently have it
|
||||
for doc in Document.objects.filter(states=watching_state):
|
||||
assert doc.type_id == "draft"
|
||||
doc.states.remove(watching_state)
|
||||
doc.states.add(idexists_state)
|
||||
e = StateDocEvent.objects.create(
|
||||
type="changed_state",
|
||||
by=system_person,
|
||||
doc=doc,
|
||||
rev=doc.rev,
|
||||
desc=f"{draft_iesg_state_type.label} changed to <b>{idexists_state.name}</b> from {watching_state.name}",
|
||||
state_type=draft_iesg_state_type,
|
||||
state=idexists_state,
|
||||
)
|
||||
doc.time = e.time
|
||||
doc.save()
|
||||
save_document_in_history(doc)
|
||||
assert not Document.objects.filter(states=watching_state).exists()
|
||||
|
||||
# Mark state as unused
|
||||
watching_state.used = False
|
||||
watching_state.save()
|
||||
|
||||
|
||||
def reverse(apps, schema_editor):
|
||||
"""Mark watching draft-iesg state as used
|
||||
|
||||
Does not try to re-apply the state to Documents modified by the forward migration. This
|
||||
could be done in theory, but would either require dangerous history rewriting or add a
|
||||
lot of history junk.
|
||||
"""
|
||||
State = apps.get_model("doc", "State")
|
||||
StateType = apps.get_model("doc", "StateType")
|
||||
State.objects.filter(
|
||||
type=StateType.objects.get(slug="draft-iesg"), slug="watching"
|
||||
).update(used=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("doc", "0023_bofreqspamstate"),
|
||||
]
|
||||
|
||||
operations = [migrations.RunPython(forward, reverse)]
|
|
@ -184,7 +184,7 @@ def state_age_colored(doc):
|
|||
if not iesg_state:
|
||||
return ""
|
||||
|
||||
if iesg_state in ["dead", "watching", "pub", "idexists"]:
|
||||
if iesg_state in ["dead", "pub", "idexists"]:
|
||||
return ""
|
||||
try:
|
||||
state_datetime = (
|
||||
|
|
|
@ -559,7 +559,7 @@ class BallotWriteupsTests(TestCase):
|
|||
q = PyQuery(r.content)
|
||||
self.assertFalse(q('[class=text-danger]:contains("not completed IETF Last Call")'))
|
||||
|
||||
for state_slug in ["lc", "watching", "ad-eval"]:
|
||||
for state_slug in ["lc", "ad-eval"]:
|
||||
draft.set_state(State.objects.get(type="draft-iesg",slug=state_slug))
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
|
|
|
@ -26,7 +26,7 @@ from ietf.doc.models import ( Document, DocReminder, DocEvent,
|
|||
WriteupDocEvent, DocRelationshipName, IanaExpertDocEvent )
|
||||
from ietf.doc.utils import get_tags_for_stream_id, create_ballot_if_not_open
|
||||
from ietf.doc.views_draft import AdoptDraftForm
|
||||
from ietf.name.models import StreamName, DocTagName, RoleName
|
||||
from ietf.name.models import DocTagName, RoleName
|
||||
from ietf.group.factories import GroupFactory, RoleFactory
|
||||
from ietf.group.models import Group, Role
|
||||
from ietf.person.factories import PersonFactory, EmailFactory
|
||||
|
@ -471,69 +471,61 @@ class EditInfoTests(TestCase):
|
|||
self.assertIn("may not leave enough time", get_payload_text(outbox[-1]))
|
||||
|
||||
def test_start_iesg_process_on_draft(self):
|
||||
|
||||
draft = WgDraftFactory(
|
||||
name="draft-ietf-mars-test2",
|
||||
group__acronym='mars',
|
||||
group__acronym="mars",
|
||||
intended_std_level_id="ps",
|
||||
authors=[Person.objects.get(user__username='ad')],
|
||||
)
|
||||
|
||||
url = urlreverse('ietf.doc.views_draft.edit_info', kwargs=dict(name=draft.name))
|
||||
authors=[Person.objects.get(user__username="ad")],
|
||||
)
|
||||
|
||||
url = urlreverse("ietf.doc.views_draft.edit_info", kwargs=dict(name=draft.name))
|
||||
login_testing_unauthorized(self, "secretary", url)
|
||||
|
||||
# normal get
|
||||
r = self.client.get(url)
|
||||
self.assertEqual(r.status_code, 200)
|
||||
q = PyQuery(r.content)
|
||||
self.assertEqual(len(q('form select[name=intended_std_level]')), 1)
|
||||
self.assertEqual("", q('form textarea[name=notify]')[0].value.strip())
|
||||
self.assertEqual(len(q("form select[name=intended_std_level]")), 1)
|
||||
self.assertEqual("", q("form textarea[name=notify]")[0].value.strip())
|
||||
|
||||
# add
|
||||
events_before = draft.docevent_set.count()
|
||||
events_before = list(draft.docevent_set.values_list("id", flat=True))
|
||||
mailbox_before = len(outbox)
|
||||
|
||||
ad = Person.objects.get(name="Areað Irector")
|
||||
|
||||
r = self.client.post(url,
|
||||
dict(intended_std_level=str(draft.intended_std_level_id),
|
||||
ad=ad.pk,
|
||||
create_in_state=State.objects.get(used=True, type="draft-iesg", slug="watching").pk,
|
||||
notify="test@example.com",
|
||||
telechat_date="",
|
||||
))
|
||||
r = self.client.post(
|
||||
url,
|
||||
dict(
|
||||
intended_std_level=str(draft.intended_std_level_id),
|
||||
ad=ad.pk,
|
||||
notify="test@example.com",
|
||||
telechat_date="",
|
||||
),
|
||||
)
|
||||
self.assertEqual(r.status_code, 302)
|
||||
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEqual(draft.get_state_slug("draft-iesg"), "watching")
|
||||
self.assertEqual(draft.get_state_slug("draft-iesg"), "pub-req")
|
||||
self.assertEqual(draft.get_state_slug("draft-stream-ietf"), "sub-pub")
|
||||
self.assertEqual(draft.ad, ad)
|
||||
self.assertTrue(not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat"))
|
||||
self.assertEqual(draft.docevent_set.count(), events_before + 4)
|
||||
self.assertCountEqual(draft.action_holders.all(), [draft.ad])
|
||||
events = list(draft.docevent_set.order_by('time', 'id'))
|
||||
self.assertEqual(events[-4].type, "started_iesg_process")
|
||||
self.assertEqual(len(outbox), mailbox_before+1)
|
||||
self.assertTrue('IESG processing' in outbox[-1]['Subject'])
|
||||
self.assertTrue('draft-ietf-mars-test2@' in outbox[-1]['To'])
|
||||
|
||||
# Redo, starting in publication requested to make sure WG state is also set
|
||||
draft.set_state(State.objects.get(type_id='draft-iesg', slug='idexists'))
|
||||
draft.set_state(State.objects.get(type='draft-stream-ietf',slug='writeupw'))
|
||||
draft.stream = StreamName.objects.get(slug='ietf')
|
||||
draft.action_holders.clear()
|
||||
draft.save_with_history([DocEvent.objects.create(doc=draft, rev=draft.rev, type="changed_stream", by=Person.objects.get(user__username="secretary"), desc="Test")])
|
||||
r = self.client.post(url,
|
||||
dict(intended_std_level=str(draft.intended_std_level_id),
|
||||
ad=ad.pk,
|
||||
create_in_state=State.objects.get(used=True, type="draft-iesg", slug="pub-req").pk,
|
||||
notify="test@example.com",
|
||||
telechat_date="",
|
||||
))
|
||||
self.assertEqual(r.status_code, 302)
|
||||
draft = Document.objects.get(name=draft.name)
|
||||
self.assertEqual(draft.get_state_slug('draft-iesg'),'pub-req')
|
||||
self.assertEqual(draft.get_state_slug('draft-stream-ietf'),'sub-pub')
|
||||
self.assertTrue(
|
||||
not draft.latest_event(TelechatDocEvent, type="scheduled_for_telechat")
|
||||
)
|
||||
# check that the expected events were created (don't insist on ordering)
|
||||
self.assertCountEqual(
|
||||
draft.docevent_set.exclude(id__in=events_before).values_list("type", flat=True),
|
||||
[
|
||||
"changed_action_holders", # action holders set to AD
|
||||
"changed_document", # WG state set to sub-pub
|
||||
"changed_document", # AD set
|
||||
"changed_document", # state change notice email set
|
||||
"started_iesg_process", # IESG state is now pub-req
|
||||
],
|
||||
)
|
||||
self.assertCountEqual(draft.action_holders.all(), [draft.ad])
|
||||
self.assertEqual(len(outbox), mailbox_before + 1)
|
||||
self.assertTrue("IESG processing" in outbox[-1]["Subject"])
|
||||
self.assertTrue("draft-ietf-mars-test2@" in outbox[-1]["To"])
|
||||
|
||||
def test_edit_consensus(self):
|
||||
draft = WgDraftFactory()
|
||||
|
@ -750,10 +742,6 @@ class ExpireIDsTests(DraftFileMixin, TestCase):
|
|||
|
||||
self.assertEqual(len(list(get_expired_drafts())), 1)
|
||||
|
||||
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="watching"))
|
||||
|
||||
self.assertEqual(len(list(get_expired_drafts())), 1)
|
||||
|
||||
draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="iesg-eva"))
|
||||
|
||||
self.assertEqual(len(list(get_expired_drafts())), 0)
|
||||
|
|
|
@ -641,7 +641,7 @@ def ballot_writeupnotes(request, name):
|
|||
existing.save()
|
||||
|
||||
if "issue_ballot" in request.POST and not ballot_already_approved:
|
||||
if prev_state.slug in ['watching', 'writeupw', 'goaheadw']:
|
||||
if prev_state.slug in ['writeupw', 'goaheadw']:
|
||||
new_state = State.objects.get(used=True, type="draft-iesg", slug='iesg-eva')
|
||||
prev_tags = doc.tags.filter(slug__in=IESG_SUBSTATE_TAGS)
|
||||
doc.set_state(new_state)
|
||||
|
@ -708,7 +708,7 @@ def ballot_writeupnotes(request, name):
|
|||
back_url=doc.get_absolute_url(),
|
||||
ballot_issued=bool(doc.latest_event(type="sent_ballot_announcement")),
|
||||
warn_lc = not doc.docevent_set.filter(lastcalldocevent__expires__date__lt=date_today(DEADLINE_TZINFO)).exists(),
|
||||
warn_unexpected_state= prev_state if bool(prev_state.slug in ['watching', 'ad-eval', 'lc']) else None,
|
||||
warn_unexpected_state= prev_state if bool(prev_state.slug in ['ad-eval', 'lc']) else None,
|
||||
ballot_writeup_form=form,
|
||||
need_intended_status=need_intended_status,
|
||||
))
|
||||
|
|
|
@ -587,7 +587,7 @@ def document_main(request, name, rev=None, document_html=False):
|
|||
if doc.get_state_slug() not in ["rfc", "expired"] and doc.stream_id in ("ietf",) and not snapshot:
|
||||
if iesg_state_slug == 'idexists' and can_edit:
|
||||
actions.append(("Begin IESG Processing", urlreverse('ietf.doc.views_draft.edit_info', kwargs=dict(name=doc.name)) + "?new=1"))
|
||||
elif can_edit_stream_info and (iesg_state_slug in ('idexists','watching')):
|
||||
elif can_edit_stream_info and (iesg_state_slug == 'idexists'):
|
||||
actions.append(("Submit to IESG for Publication", urlreverse('ietf.doc.views_draft.to_iesg', kwargs=dict(name=doc.name))))
|
||||
|
||||
if request.user.is_authenticated and hasattr(request.user, "person"):
|
||||
|
|
|
@ -487,40 +487,6 @@ def change_intention(request, name):
|
|||
doc=doc,
|
||||
))
|
||||
|
||||
class EditInfoForm(forms.Form):
|
||||
intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.filter(used=True), empty_label="(None)", required=True, label="Intended RFC status")
|
||||
area = forms.ModelChoiceField(Group.objects.filter(type="area", state="active"), empty_label="(None - individual submission)", required=False, label="Assigned to area")
|
||||
ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active",role__group__type='area').order_by('name'), label="Responsible AD", empty_label="(None)", required=True)
|
||||
create_in_state = forms.ModelChoiceField(State.objects.filter(used=True, type="draft-iesg", slug__in=("pub-req", "watching")), empty_label=None, required=False)
|
||||
notify = forms.CharField(
|
||||
widget=forms.Textarea,
|
||||
max_length=1023,
|
||||
label="Notice emails",
|
||||
help_text="Separate email addresses with commas.",
|
||||
required=False,
|
||||
)
|
||||
telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False, widget=forms.Select(attrs={'onchange':'make_bold()'}))
|
||||
returning_item = forms.BooleanField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
# if previous AD is now ex-AD, append that person to the list
|
||||
ad_pk = self.initial.get('ad')
|
||||
choices = self.fields['ad'].choices
|
||||
if ad_pk and ad_pk not in [pk for pk, name in choices]:
|
||||
self.fields['ad'].choices = list(choices) + [("", "-------"), (ad_pk, Person.objects.get(pk=ad_pk).plain_name())]
|
||||
|
||||
# telechat choices
|
||||
dates = [d.date for d in TelechatDate.objects.active().order_by('date')]
|
||||
init = kwargs['initial']['telechat_date']
|
||||
if init and init not in dates:
|
||||
dates.insert(0, init)
|
||||
|
||||
self.fields['telechat_date'].choices = [("", "(not on agenda)")] + [(d, d.strftime("%Y-%m-%d")) for d in dates]
|
||||
|
||||
# returning item is rendered non-standard
|
||||
self.standard_fields = [x for x in self.visible_fields() if x.name not in ('returning_item',)]
|
||||
|
||||
def to_iesg(request,name):
|
||||
""" Submit an IETF stream document to the IESG for publication """
|
||||
|
@ -619,7 +585,71 @@ def to_iesg(request,name):
|
|||
notify=notify,
|
||||
))
|
||||
|
||||
@role_required('Area Director','Secretariat')
|
||||
class EditInfoForm(forms.Form):
|
||||
intended_std_level = forms.ModelChoiceField(
|
||||
IntendedStdLevelName.objects.filter(used=True),
|
||||
empty_label="(None)",
|
||||
required=True,
|
||||
label="Intended RFC status",
|
||||
)
|
||||
area = forms.ModelChoiceField(
|
||||
Group.objects.filter(type="area", state="active"),
|
||||
empty_label="(None - individual submission)",
|
||||
required=False,
|
||||
label="Assigned to area",
|
||||
)
|
||||
ad = forms.ModelChoiceField(
|
||||
Person.objects.filter(
|
||||
role__name="ad", role__group__state="active", role__group__type="area"
|
||||
).order_by("name"),
|
||||
label="Responsible AD",
|
||||
empty_label="(None)",
|
||||
required=True,
|
||||
)
|
||||
notify = forms.CharField(
|
||||
widget=forms.Textarea,
|
||||
max_length=1023,
|
||||
label="Notice emails",
|
||||
help_text="Separate email addresses with commas.",
|
||||
required=False,
|
||||
)
|
||||
telechat_date = forms.TypedChoiceField(
|
||||
coerce=lambda x: datetime.datetime.strptime(x, "%Y-%m-%d").date(),
|
||||
empty_value=None,
|
||||
required=False,
|
||||
widget=forms.Select(attrs={"onchange": "make_bold()"}),
|
||||
)
|
||||
returning_item = forms.BooleanField(required=False)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(self.__class__, self).__init__(*args, **kwargs)
|
||||
|
||||
# if previous AD is now ex-AD, append that person to the list
|
||||
ad_pk = self.initial.get("ad")
|
||||
choices = self.fields["ad"].choices
|
||||
if ad_pk and ad_pk not in [pk for pk, name in choices]:
|
||||
self.fields["ad"].choices = list(choices) + [
|
||||
("", "-------"),
|
||||
(ad_pk, Person.objects.get(pk=ad_pk).plain_name()),
|
||||
]
|
||||
|
||||
# telechat choices
|
||||
dates = [d.date for d in TelechatDate.objects.active().order_by("date")]
|
||||
init = kwargs["initial"]["telechat_date"]
|
||||
if init and init not in dates:
|
||||
dates.insert(0, init)
|
||||
|
||||
self.fields["telechat_date"].choices = [("", "(not on agenda)")] + [
|
||||
(d, d.strftime("%Y-%m-%d")) for d in dates
|
||||
]
|
||||
|
||||
# returning item is rendered non-standard
|
||||
self.standard_fields = [
|
||||
x for x in self.visible_fields() if x.name not in ("returning_item",)
|
||||
]
|
||||
|
||||
|
||||
@role_required("Area Director", "Secretariat")
|
||||
def edit_info(request, name):
|
||||
"""Edit various Internet-Draft attributes, notifying parties as
|
||||
necessary and logging changes as document events."""
|
||||
|
@ -628,7 +658,8 @@ def edit_info(request, name):
|
|||
raise Http404
|
||||
|
||||
new_document = False
|
||||
if doc.get_state_slug("draft-iesg") == "idexists": # FIXME: should probably receive "new document" as argument to view instead of this
|
||||
# FIXME: should probably receive "new document" as argument to view instead of this
|
||||
if doc.get_state_slug("draft-iesg") == "idexists":
|
||||
new_document = True
|
||||
doc.notify = get_initial_notify(doc)
|
||||
|
||||
|
@ -636,34 +667,45 @@ def edit_info(request, name):
|
|||
initial_telechat_date = e.telechat_date if e else None
|
||||
initial_returning_item = bool(e and e.returning_item)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = EditInfoForm(request.POST,
|
||||
initial=dict(ad=doc.ad_id,
|
||||
telechat_date=initial_telechat_date))
|
||||
if request.method == "POST":
|
||||
form = EditInfoForm(
|
||||
request.POST,
|
||||
initial=dict(ad=doc.ad_id, telechat_date=initial_telechat_date),
|
||||
)
|
||||
if form.is_valid():
|
||||
by = request.user.person
|
||||
pubreq_state = State.objects.get(type="draft-iesg", slug="pub-req")
|
||||
|
||||
r = form.cleaned_data
|
||||
events = []
|
||||
|
||||
if new_document:
|
||||
doc.set_state(r['create_in_state'])
|
||||
doc.set_state(pubreq_state)
|
||||
|
||||
# Is setting the WG state here too much of a hidden side-effect?
|
||||
if r['create_in_state'].slug=='pub-req':
|
||||
if doc.stream and doc.stream.slug=='ietf' and doc.group and doc.group.type_id == 'wg':
|
||||
submitted_state = State.objects.get(type='draft-stream-ietf',slug='sub-pub')
|
||||
doc.set_state(submitted_state)
|
||||
e = DocEvent()
|
||||
e.type = "changed_document"
|
||||
e.by = by
|
||||
e.doc = doc
|
||||
e.rev = doc.rev
|
||||
e.desc = "Working group state set to %s" % submitted_state.name
|
||||
e.save()
|
||||
events.append(e)
|
||||
if (
|
||||
doc.stream
|
||||
and doc.stream.slug == "ietf"
|
||||
and doc.group
|
||||
and doc.group.type_id == "wg"
|
||||
):
|
||||
submitted_state = State.objects.get(
|
||||
type="draft-stream-ietf", slug="sub-pub"
|
||||
)
|
||||
doc.set_state(submitted_state)
|
||||
e = DocEvent()
|
||||
e.type = "changed_document"
|
||||
e.by = by
|
||||
e.doc = doc
|
||||
e.rev = doc.rev
|
||||
e.desc = "Working group state set to %s" % submitted_state.name
|
||||
e.save()
|
||||
events.append(e)
|
||||
|
||||
replaces = Document.objects.filter(targets_related__source=doc, targets_related__relationship="replaces")
|
||||
replaces = Document.objects.filter(
|
||||
targets_related__source=doc,
|
||||
targets_related__relationship="replaces",
|
||||
)
|
||||
if replaces:
|
||||
# this should perhaps be somewhere else, e.g. the
|
||||
# place where the replace relationship is established?
|
||||
|
@ -672,7 +714,10 @@ def edit_info(request, name):
|
|||
e.by = Person.objects.get(name="(System)")
|
||||
e.doc = doc
|
||||
e.rev = doc.rev
|
||||
e.desc = "Earlier history may be found in the Comment Log for <a href=\"%s\">%s</a>" % (replaces[0], replaces[0].get_absolute_url())
|
||||
e.desc = (
|
||||
'Earlier history may be found in the Comment Log for <a href="%s">%s</a>'
|
||||
% (replaces[0], replaces[0].get_absolute_url())
|
||||
)
|
||||
e.save()
|
||||
events.append(e)
|
||||
|
||||
|
@ -681,7 +726,10 @@ def edit_info(request, name):
|
|||
e.by = by
|
||||
e.doc = doc
|
||||
e.rev = doc.rev
|
||||
e.desc = "Document is now in IESG state <b>%s</b>" % doc.get_state("draft-iesg").name
|
||||
e.desc = (
|
||||
"Document is now in IESG state <b>%s</b>"
|
||||
% doc.get_state("draft-iesg").name
|
||||
)
|
||||
e.save()
|
||||
events.append(e)
|
||||
|
||||
|
@ -691,9 +739,9 @@ def edit_info(request, name):
|
|||
entry = "%(attr)s changed to <b>%(new)s</b> from <b>%(old)s</b>"
|
||||
if new_document:
|
||||
entry = "%(attr)s changed to <b>%(new)s</b>"
|
||||
|
||||
|
||||
return entry % dict(attr=attr, new=new, old=old)
|
||||
|
||||
|
||||
def diff(attr, name):
|
||||
v = getattr(doc, attr)
|
||||
if r[attr] != v:
|
||||
|
@ -701,9 +749,9 @@ def edit_info(request, name):
|
|||
setattr(doc, attr, r[attr])
|
||||
|
||||
# update the attributes, keeping track of what we're doing
|
||||
diff('intended_std_level', "Intended Status")
|
||||
diff('ad', "Responsible AD")
|
||||
diff('notify', "State Change Notice email list")
|
||||
diff("intended_std_level", "Intended Status")
|
||||
diff("ad", "Responsible AD")
|
||||
diff("notify", "State Change Notice email list")
|
||||
|
||||
if doc.group.type_id in ("individ", "area"):
|
||||
if not r["area"]:
|
||||
|
@ -717,12 +765,16 @@ def edit_info(request, name):
|
|||
doc.group = r["area"]
|
||||
|
||||
for c in changes:
|
||||
events.append(DocEvent.objects.create(doc=doc, rev=doc.rev, by=by, desc=c, type="changed_document"))
|
||||
events.append(
|
||||
DocEvent.objects.create(
|
||||
doc=doc, rev=doc.rev, by=by, desc=c, type="changed_document"
|
||||
)
|
||||
)
|
||||
|
||||
# Todo - chase this
|
||||
e = update_telechat(request, doc, by,
|
||||
r['telechat_date'], r['returning_item'])
|
||||
|
||||
e = update_telechat(
|
||||
request, doc, by, r["telechat_date"], r["returning_item"]
|
||||
)
|
||||
if e:
|
||||
events.append(e)
|
||||
|
||||
|
@ -730,40 +782,44 @@ def edit_info(request, name):
|
|||
|
||||
if new_document:
|
||||
# If we created a new doc, update the action holders as though it
|
||||
# started in idexists and moved to its create_in_state. Do this
|
||||
# started in idexists and moved to pub-req. Do this
|
||||
# after the doc has been updated so, e.g., doc.ad is set.
|
||||
update_action_holders(
|
||||
doc,
|
||||
State.objects.get(type='draft-iesg', slug='idexists'),
|
||||
r['create_in_state']
|
||||
State.objects.get(type="draft-iesg", slug="idexists"),
|
||||
pubreq_state,
|
||||
)
|
||||
|
||||
if changes:
|
||||
email_iesg_processing_document(request, doc, changes)
|
||||
|
||||
|
||||
return HttpResponseRedirect(doc.get_absolute_url())
|
||||
else:
|
||||
init = dict(intended_std_level=doc.intended_std_level_id,
|
||||
area=doc.group_id,
|
||||
ad=doc.ad_id,
|
||||
notify=doc.notify,
|
||||
telechat_date=initial_telechat_date,
|
||||
returning_item=initial_returning_item,
|
||||
)
|
||||
init = dict(
|
||||
intended_std_level=doc.intended_std_level_id,
|
||||
area=doc.group_id,
|
||||
ad=doc.ad_id,
|
||||
notify=doc.notify,
|
||||
telechat_date=initial_telechat_date,
|
||||
returning_item=initial_returning_item,
|
||||
)
|
||||
|
||||
form = EditInfoForm(initial=init)
|
||||
|
||||
# optionally filter out some fields
|
||||
if not new_document:
|
||||
form.standard_fields = [x for x in form.standard_fields if x.name != "create_in_state"]
|
||||
if doc.group.type_id not in ("individ", "area"):
|
||||
form.standard_fields = [x for x in form.standard_fields if x.name != "area"]
|
||||
|
||||
return render(request, 'doc/draft/edit_info.html',
|
||||
dict(doc=doc,
|
||||
form=form,
|
||||
user=request.user,
|
||||
ballot_issued=doc.latest_event(type="sent_ballot_announcement")))
|
||||
return render(
|
||||
request,
|
||||
"doc/draft/edit_info.html",
|
||||
dict(
|
||||
doc=doc,
|
||||
form=form,
|
||||
user=request.user,
|
||||
ballot_issued=doc.latest_event(type="sent_ballot_announcement"),
|
||||
),
|
||||
)
|
||||
|
||||
@role_required('Area Director','Secretariat')
|
||||
def request_resurrect(request, name):
|
||||
|
|
|
@ -757,7 +757,7 @@ def drafts_in_last_call(request):
|
|||
})
|
||||
|
||||
def drafts_in_iesg_process(request):
|
||||
states = State.objects.filter(type="draft-iesg").exclude(slug__in=('idexists', 'pub', 'dead', 'watching', 'rfcqueue'))
|
||||
states = State.objects.filter(type="draft-iesg").exclude(slug__in=('idexists', 'pub', 'dead', 'rfcqueue'))
|
||||
title = "Documents in IESG process"
|
||||
|
||||
grouped_docs = []
|
||||
|
|
|
@ -731,7 +731,7 @@ def dependencies(request, acronym, group_type=None):
|
|||
{
|
||||
"id": x.became_rfc().name if x.became_rfc() else x.name,
|
||||
"rfc": x.type_id == "rfc" or x.became_rfc() is not None,
|
||||
"post-wg": x.get_state_slug("draft-iesg") not in ["idexists", "watching", "dead"],
|
||||
"post-wg": x.get_state_slug("draft-iesg") not in ["idexists", "dead"],
|
||||
"expired": x.get_state_slug("draft") == "expired",
|
||||
"replaced": x.get_state_slug("draft") == "repl",
|
||||
"group": x.group.acronym if x.group and x.group.acronym != "none" else "",
|
||||
|
|
|
@ -51,7 +51,7 @@ def all_id_txt():
|
|||
res.append(f1 + "\t" + f2 + "\t" + f3 + "\t" + f4)
|
||||
|
||||
|
||||
inactive_states = ["idexists", "pub", "watching", "dead"]
|
||||
inactive_states = ["idexists", "pub", "dead"]
|
||||
|
||||
excludes = list(State.objects.filter(type="draft", slug__in=["rfc","repl"]))
|
||||
includes = list(State.objects.filter(type="draft-iesg").exclude(slug__in=inactive_states))
|
||||
|
|
|
@ -312,7 +312,7 @@
|
|||
"order": 42,
|
||||
"slug": "watching",
|
||||
"type": "draft-iesg",
|
||||
"used": true
|
||||
"used": false
|
||||
},
|
||||
"model": "doc.state",
|
||||
"pk": 11
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
</h1>
|
||||
{% if state.slug == "dead" %}
|
||||
<p class="alert alert-warning my-3">
|
||||
This document is in IESG state "Dead". It is unusual to change
|
||||
this to anything other than "AD is watching", and this should
|
||||
never be used as a replacement for Begin IESG Processing.
|
||||
This document is in IESG state "Dead". It is unusual to change this to
|
||||
anything other than "I-D Exists" and this should never be used as a
|
||||
replacement for Begin IESG Processing.
|
||||
</p>
|
||||
{% endif %}
|
||||
<a class="btn btn-info my-3"
|
||||
|
|
Loading…
Reference in a new issue