diff --git a/ietf/doc/expire.py b/ietf/doc/expire.py index 1650b4ddf5..681ca963a3 100644 --- a/ietf/doc/expire.py +++ b/ietf/doc/expire.py @@ -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"))) diff --git a/ietf/doc/migrations/0024_remove_ad_is_watching_states.py b/ietf/doc/migrations/0024_remove_ad_is_watching_states.py new file mode 100644 index 0000000000..0c0fb0ad25 --- /dev/null +++ b/ietf/doc/migrations/0024_remove_ad_is_watching_states.py @@ -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 {idexists_state.name} 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)] diff --git a/ietf/doc/templatetags/ballot_icon.py b/ietf/doc/templatetags/ballot_icon.py index 5f59822c7b..a94c145007 100644 --- a/ietf/doc/templatetags/ballot_icon.py +++ b/ietf/doc/templatetags/ballot_icon.py @@ -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 = ( diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py index 0c99ed281a..f95ba8812b 100644 --- a/ietf/doc/tests_ballot.py +++ b/ietf/doc/tests_ballot.py @@ -559,7 +559,7 @@ def test_issue_ballot_warn_if_early(self): 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) diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index dcb71bdf69..09a7b38999 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -26,7 +26,7 @@ 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 @@ def test_edit_telechat_date(self): 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 @@ def test_expire_drafts(self): 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) diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py index 2b7faac92b..4ff40d2268 100644 --- a/ietf/doc/views_ballot.py +++ b/ietf/doc/views_ballot.py @@ -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, )) diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index 02d59f0df3..915dcebde5 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -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"): diff --git a/ietf/doc/views_draft.py b/ietf/doc/views_draft.py index 30175491da..d709aedd42 100644 --- a/ietf/doc/views_draft.py +++ b/ietf/doc/views_draft.py @@ -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 doc_event(type, by, doc, desc): 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 %s" % (replaces[0], replaces[0].get_absolute_url()) + e.desc = ( + 'Earlier history may be found in the Comment Log for %s' + % (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 %s" % doc.get_state("draft-iesg").name + e.desc = ( + "Document is now in IESG state %s" + % doc.get_state("draft-iesg").name + ) e.save() events.append(e) @@ -691,9 +739,9 @@ def desc(attr, new, old): entry = "%(attr)s changed to %(new)s from %(old)s" if new_document: entry = "%(attr)s changed to %(new)s" - + 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 diff(attr, 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 diff(attr, 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 diff(attr, 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): diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py index 528fb05a22..4fa3b2560c 100644 --- a/ietf/doc/views_search.py +++ b/ietf/doc/views_search.py @@ -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 = [] diff --git a/ietf/group/views.py b/ietf/group/views.py index e3fd7e80d9..71986384e0 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -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 "", diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py index 11c4521485..4f021c0dc7 100644 --- a/ietf/idindex/index.py +++ b/ietf/idindex/index.py @@ -51,7 +51,7 @@ def add_line(f1, f2, f3, f4): 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)) diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index 401767657d..8f1262b4cf 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -312,7 +312,7 @@ "order": 42, "slug": "watching", "type": "draft-iesg", - "used": true + "used": false }, "model": "doc.state", "pk": 11 diff --git a/ietf/templates/doc/draft/change_state.html b/ietf/templates/doc/draft/change_state.html index 3515c290e1..1cae8358a4 100644 --- a/ietf/templates/doc/draft/change_state.html +++ b/ietf/templates/doc/draft/change_state.html @@ -12,9 +12,9 @@

{% if state.slug == "dead" %}

- 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.

{% endif %}