Merge pull request from rjsparks/rfc_htmlized

fix: migration, main view, htmlized view repair
This commit is contained in:
Jennifer Richards 2023-09-13 18:53:35 -03:00 committed by GitHub
commit 00bcc11247
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 238 additions and 313 deletions

View file

@ -328,7 +328,7 @@ def rfcdiff_latest_json(request, name, rev=None):
response = dict()
condition, document, history, found_rev = find_doc_for_rfcdiff(name, rev)
if document.type_id == "rfc":
draft = next(iter(document.related_that('became_rfc')), None)
draft = document.came_from_draft()
if condition == 'no such document':
raise Http404
elif condition in ('historic version', 'current version'):

View file

@ -51,7 +51,11 @@ class BaseDocumentFactory(factory.django.DjangoModelFactory):
def name(self, n):
return draft_name_generator(self.type_id,self.group,n)
newrevisiondocevent = factory.RelatedFactory('ietf.doc.factories.NewRevisionDocEventFactory','doc')
@factory.post_generation
def newrevisiondocevent(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
if create:
if obj.type_id != "rfc":
NewRevisionDocEventFactory(doc=obj)
@factory.post_generation
def states(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument
@ -106,6 +110,7 @@ class DocumentFactory(BaseDocumentFactory):
class RfcFactory(BaseDocumentFactory):
type_id = "rfc"
rev = ""
rfc_number = factory.Sequence(lambda n: n + 1000)
name = factory.LazyAttribute(lambda o: f"rfc{o.rfc_number:d}")
expires = None

View file

@ -130,7 +130,7 @@ class Command(BaseCommand):
for draft in interesting_drafts.distinct().iterator():
# Omit drafts that became RFCs, unless they were published in the last DEFAULT_YEARS
if draft.get_state_slug()=="rfc":
rfc = next(iter(draft.related_that_doc("became_rfc")), None)
rfc = draft.became_rfc()
log.assertion("rfc is not None")
if rfc.latest_event(type='published_rfc').time < show_since:
continue

View file

@ -0,0 +1,34 @@
# Generated by Django 4.2.5 on 2023-09-11 17:52
from django.db import migrations
from django.db.models import Subquery, OuterRef, F
def forward(apps, schema_editor):
DocHistory = apps.get_model("doc", "DocHistory")
RelatedDocument = apps.get_model("doc", "RelatedDocument")
DocHistory.objects.filter(type_id="draft", doc__type_id="rfc").update(type_id="rfc")
DocHistory.objects.filter(
type_id="draft", doc__type_id="draft", name__startswith="rfc"
).annotate(
rfc_id=Subquery(
RelatedDocument.objects.filter(
source_id=OuterRef("doc_id"), relationship_id="became_rfc"
).values_list("target_id", flat=True)[:1]
)
).update(
doc_id=F("rfc_id"), type_id="rfc"
)
assert not DocHistory.objects.filter(
name__startswith="rfc", type_id="draft"
).exists()
class Migration(migrations.Migration):
dependencies = [
("doc", "0015_delete_docalias"),
]
# There is no going back
operations = [migrations.RunPython(forward)]

View file

@ -198,17 +198,28 @@ class DocumentInfo(models.Model):
self._cached_file_name = os.path.join(self.get_file_path(), self.get_base_name())
return self._cached_file_name
def revisions(self):
def revisions_by_dochistory(self):
revisions = []
doc = self.doc if isinstance(self, DocHistory) else self
for e in doc.docevent_set.filter(type='new_revision').distinct():
if e.rev and not e.rev in revisions:
revisions.append(e.rev)
if not doc.rev in revisions:
revisions.append(doc.rev)
revisions.sort()
if self.type_id != "rfc":
for h in self.history_set.order_by("time", "id"):
if h.rev and not h.rev in revisions:
revisions.append(h.rev)
if not self.rev in revisions:
revisions.append(self.rev)
return revisions
def revisions_by_newrevisionevent(self):
revisions = []
if self.type_id != "rfc":
doc = self.doc if isinstance(self, DocHistory) else self
for e in doc.docevent_set.filter(type='new_revision').distinct():
if e.rev and not e.rev in revisions:
revisions.append(e.rev)
if not doc.rev in revisions:
revisions.append(doc.rev)
revisions.sort()
return revisions
def get_href(self, meeting=None):
return self._get_ref(meeting=meeting,meeting_doc_refs=settings.MEETING_DOC_HREFS)
@ -654,6 +665,18 @@ class DocumentInfo(models.Model):
source__type__slug="rfc"
)
def became_rfc(self):
if not hasattr(self, "_cached_became_rfc"):
doc = self if isinstance(self, Document) else self.doc
self._cached_became_rfc = next(iter(doc.related_that_doc("became_rfc")), None)
return self._cached_became_rfc
def came_from_draft(self):
if not hasattr(self, "_cached_came_from_draft"):
doc = self if isinstance(self, Document) else self.doc
self._cached_came_from_draft = next(iter(doc.related_that("became_rfc")), None)
return self._cached_came_from_draft
class Meta:
abstract = True

View file

@ -2883,3 +2883,30 @@ class CanRequestConflictReviewTests(TestCase):
r = self.client.get(url)
self.assertContains(r, target_string)
class DocInfoMethodsTests(TestCase):
def test_became_rfc(self):
draft = WgDraftFactory()
rfc = WgRfcFactory()
draft.relateddocument_set.create(relationship_id="became_rfc",target=rfc)
self.assertEqual(draft.became_rfc(), rfc)
self.assertEqual(rfc.came_from_draft(), draft)
charter = CharterFactory()
self.assertIsNone(charter.became_rfc())
self.assertIsNone(charter.came_from_draft())
def test_revisions(self):
draft = WgDraftFactory(rev="09",create_revisions=range(0,10))
self.assertEqual(draft.revisions_by_dochistory(),[f"{i:02d}" for i in range(0,10)])
self.assertEqual(draft.revisions_by_newrevisionevent(),[f"{i:02d}" for i in range(0,10)])
rfc = WgRfcFactory()
self.assertEqual(rfc.revisions_by_newrevisionevent(),[])
self.assertEqual(rfc.revisions_by_dochistory(),[])
draft.history_set.filter(rev__lt="08").delete()
draft.docevent_set.filter(newrevisiondocevent__rev="05").delete()
self.assertEqual(draft.revisions_by_dochistory(),[f"{i:02d}" for i in range(8,10)])
self.assertEqual(draft.revisions_by_newrevisionevent(),[f"{i:02d}" for i in [*range(0,5), *range(6,10)]])

View file

@ -936,6 +936,8 @@ def make_rev_history(doc):
if document not in predecessors:
predecessors.append(document)
predecessors.extend(get_predecessors(document, predecessors))
if doc.came_from_draft():
predecessors.append(doc.came_from_draft())
return predecessors
def get_ancestors(doc, ancestors = None):
@ -946,6 +948,8 @@ def make_rev_history(doc):
if document not in ancestors:
ancestors.append(document)
ancestors.extend(get_ancestors(document, ancestors))
if doc.became_rfc():
ancestors.append(doc.became_rfc())
return ancestors
def get_replaces_tree(doc):
@ -971,6 +975,9 @@ def make_rev_history(doc):
history[url]['pages'] = d.history_set.filter(rev=e.newrevisiondocevent.rev).first().pages
if doc.type_id == "draft":
# Do nothing - all draft revisions are captured above already.
e = None
elif doc.type_id == "rfc":
# e.time.date() agrees with RPC publication date when shown in the RPC_TZINFO time zone
e = doc.latest_event(type='published_rfc')
else:
@ -983,7 +990,7 @@ def make_rev_history(doc):
'published': e.time.isoformat(),
'url': url
}
if hasattr(e, 'newrevisiondocevent') and doc.history_set.filter(rev=e.newrevisiondocevent.rev).exists():
if doc.type_id != "rfc" and hasattr(e, 'newrevisiondocevent') and doc.history_set.filter(rev=e.newrevisiondocevent.rev).exists():
history[url]['pages'] = doc.history_set.filter(rev=e.newrevisiondocevent.rev).first().pages
history = list(history.values())
return sorted(history, key=lambda x: x['published'])

View file

@ -190,23 +190,21 @@ def interesting_doc_relations(doc):
return interesting_relations_that, interesting_relations_that_doc
def document_main(request, name, rev=None, document_html=False):
if name.startswith("rfc") and rev is not None:
raise Http404()
doc = get_object_or_404(Document.objects.select_related(), name=name)
if doc.type_id == "rfc" and rev is not None:
raise Http404()
log.assertion('doc.type_id!="rfc" or doc.name.startswith("rfc")')
# take care of possible redirections
if document_html is False and rev is None:
became_rfc = next(iter(doc.related_that_doc("became_rfc")), None)
became_rfc = doc.became_rfc()
if became_rfc:
return redirect("ietf.doc.views_doc.document_main", name=became_rfc.name)
revisions = []
for h in doc.history_set.order_by("time", "id"):
if h.rev and not h.rev in revisions:
revisions.append(h.rev)
if not doc.rev in revisions:
revisions.append(doc.rev)
revisions = doc.revisions_by_dochistory()
latest_rev = doc.rev
snapshot = False
@ -239,7 +237,6 @@ def document_main(request, name, rev=None, document_html=False):
if telechat and (not telechat.telechat_date or telechat.telechat_date < date_today(settings.TIME_ZONE)):
telechat = None
# specific document types
if doc.type_id == "rfc":
split_content = request.COOKIES.get("full_draft", settings.USER_PREFERENCE_DEFAULTS["full_draft"]) == "off"
@ -277,13 +274,6 @@ def document_main(request, name, rev=None, document_html=False):
content = "This RFC is not available in plain text format."
split_content = False
# mailing list search archive
search_archive = "www.ietf.org/mail-archive/web/"
if doc.stream_id == "ietf" and group.type_id == "wg" and group.list_archive:
search_archive = group.list_archive
search_archive = quote(search_archive, safe="~")
# status changes
status_changes = []
proposed_status_changes = []
@ -303,34 +293,23 @@ def document_main(request, name, rev=None, document_html=False):
exp_comment = doc.latest_event(IanaExpertDocEvent,type="comment")
iana_experts_comment = exp_comment and exp_comment.desc
# Do not show the Auth48 URL in the "Additional URLs" section
additional_urls = doc.documenturl_set.exclude(tag_id='auth48')
html = None
js = None
css = None
diff_revisions = None
simple_diff_revisions = None
if document_html:
diff_revisions=get_diff_revisions(request, name, doc if isinstance(doc,Document) else doc.doc)
diff_revisions=get_diff_revisions(request, name, doc)
simple_diff_revisions = [t[1] for t in diff_revisions if t[0] == doc.name]
simple_diff_revisions.reverse()
if rev and rev != doc.rev:
# No DocHistory was found matching rev - snapshot will be false
# and doc will be a Document object, not a DocHistory
snapshot = True
doc = doc.fake_history_obj(rev)
else:
html = doc.html_body()
if request.COOKIES.get("pagedeps") == "inline":
js = Path(finders.find("ietf/js/document_html.js")).read_text()
css = Path(finders.find("ietf/css/document_html_inline.css")).read_text()
if html:
css += Path(finders.find("ietf/css/document_html_txt.css")).read_text()
draft_that_became_rfc = None
became_rfc = next(iter(doc.related_that("became_rfc")), None)
if became_rfc:
draft_that_became_rfc = became_rfc
html = doc.html_body()
if request.COOKIES.get("pagedeps") == "inline":
js = Path(finders.find("ietf/js/document_html.js")).read_text()
css = Path(finders.find("ietf/css/document_html_inline.css")).read_text()
if html:
css += Path(finders.find("ietf/css/document_html_txt.css")).read_text()
draft_that_became_rfc = doc.came_from_draft()
# submission
submission = ""
if group is None:
@ -370,7 +349,6 @@ def document_main(request, name, rev=None, document_html=False):
content=content,
split_content=split_content,
revisions=simple_diff_revisions if document_html else revisions,
snapshot=snapshot,
latest_rev=latest_rev,
can_edit=can_edit,
can_edit_authors=can_edit_authors,
@ -385,13 +363,11 @@ def document_main(request, name, rev=None, document_html=False):
proposed_status_changes=proposed_status_changes,
has_errata=doc.pk and doc.tags.filter(slug="errata"), # doc.pk == None if using a fake_history_obj
file_urls=file_urls,
additional_urls=additional_urls,
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,
search_archive=search_archive,
presentations=presentations,
diff_revisions=diff_revisions,
submission=submission
@ -1153,6 +1129,11 @@ def document_email(request,name):
def get_diff_revisions(request, name, doc):
""" Calculate what to offer for diff comparisons
returns list of (name, rev, time, url, is_this_doc, is_previous_doc)
ordered by -time for use by forms used to get to the diff tools.
"""
diffable = any(
[
name.startswith(prefix)
@ -1179,16 +1160,17 @@ def get_diff_revisions(request, name, doc):
relateddocument__relationship="replaces",
)
)
diff_documents.extend(
Document.objects.filter(
relateddocument__target=doc,
relateddocument__relationship="became_rfc"
)
)
if doc.came_from_draft():
diff_documents.append(doc.came_from_draft())
if doc.became_rfc():
rfc = doc.became_rfc()
e = rfc.latest_event(type="published_rfc")
diff_revisions.append((rfc.name, "", e.time if e else rfc.time, rfc.name, False, False))
if doc.type_id == "rfc":
e = doc.latest_event(type="published_rfc")
diff_revisions.append((name, "", e.time if e else doc.time, name))
diff_revisions.append((name, "", e.time if e else doc.time, name, True, False))
seen = set()
for e in (
@ -1217,7 +1199,16 @@ def get_diff_revisions(request, name, doc):
# rfcdiff tool has special support for IDs
url = e.doc.name + "-" + e.rev
diff_revisions.append((e.doc.name, e.rev, e.time, url))
diff_revisions.append((e.doc.name, e.rev, e.time, url, e.doc == doc and e.rev == doc.rev, False))
diff_revisions.sort(key=lambda t: t[2], reverse=True)
for index, t in enumerate(diff_revisions):
if t[4]: # is_this_doc
n = index+1
if n < len(diff_revisions):
t_name, rev, time, url, _, _ = diff_revisions[n]
diff_revisions[n] = (t_name, rev, time, url, False, True)
break
return diff_revisions
@ -1299,7 +1290,7 @@ def document_bibtex(request, name, rev=None):
if doc.type_id == "draft":
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
replaced_by = [d.name for d in doc.related_that("replaces")]
draft_became_rfc = next(iter(doc.related_that_doc("became_rfc")), None)
draft_became_rfc = doc.became_rfc()
if rev != None and rev != doc.rev:
# find the entry in the history
@ -1658,8 +1649,6 @@ def document_json(request, name, rev=None):
data["expires"] = doc.expires.strftime("%Y-%m-%d %H:%M:%S") if doc.expires else None
data["title"] = doc.title
data["abstract"] = doc.abstract
# Preserve aliases in this api? What about showing rfc_number directly?
data["aliases"] = list(doc.name)
data["state"] = extract_name(doc.get_state())
data["intended_std_level"] = extract_name(doc.intended_std_level)
data["std_level"] = extract_name(doc.std_level)
@ -1675,7 +1664,7 @@ def document_json(request, name, rev=None):
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
data["rev_history"] = make_rev_history(latest_revision.doc if latest_revision else doc)
if doc.type_id == "draft":
if doc.type_id == "draft": # These live only on drafts
data["iesg_state"] = extract_name(doc.get_state("draft-iesg"))
data["rfceditor_state"] = extract_name(doc.get_state("draft-rfceditor"))
data["iana_review_state"] = extract_name(doc.get_state("draft-iana-review"))
@ -1684,6 +1673,8 @@ def document_json(request, name, rev=None):
if doc.stream_id in ("ietf", "irtf", "iab"):
e = doc.latest_event(ConsensusDocEvent, type="changed_consensus")
data["consensus"] = e.consensus if e else None
if doc.type_id in ["draft", "rfc"]:
data["stream"] = extract_name(doc.stream)
return HttpResponse(json.dumps(data, indent=2), content_type='application/json')
@ -2189,7 +2180,7 @@ def idnits2_state(request, name, rev=None):
raise Http404
zero_revision = None
if doc.type_id == "rfc":
draft = next(iter(doc.related_that('became_rfc')), None)
draft = doc.came_from_draft()
if draft:
zero_revision = NewRevisionDocEvent.objects.filter(doc=draft,rev='00').first()
else:

View file

@ -33,7 +33,7 @@ def all_id_txt():
rfcs = dict()
for rfc in Document.objects.filter(type_id="rfc"):
draft = next(iter(rfc.related_that("became_rfc")), None)
draft = rfc.came_from_draft()
if draft is not None:
rfcs[draft.name] = rfc.name
@ -117,7 +117,7 @@ def all_id2_txt():
rfcs = dict()
for rfc in Document.objects.filter(type_id="rfc"):
draft = next(iter(rfc.related_that("became_rfc")), None)
draft = rfc.came_from_draft()
if draft is not None:
rfcs[draft.name] = rfc.name

View file

@ -2,7 +2,7 @@
from django.db import migrations
import django.db.models.deletion
from django.db.models import F, Subquery, OuterRef
from django.db.models import F, Subquery, OuterRef, ManyToManyField
import ietf.utils.models
def forward(apps, schema_editor):
@ -67,6 +67,11 @@ class Migration(migrations.Migration):
db_index=True,
),
),
migrations.AlterField(
model_name='iprdisclosurebase',
name='docs',
field=ManyToManyField(through='ipr.IprDocRel', to='doc.Document'),
),
migrations.RemoveField(
model_name="iprdocrel",
name="deprecated_document",

View file

@ -235,7 +235,7 @@ def _get_materials_doc(meeting, name):
docname, rev = name.rsplit("-", 1)
if len(rev) == 2 and rev.isdigit():
doc = Document.objects.get(name=docname) # may raise Document.DoesNotExist
if doc.get_related_meeting() == meeting and rev in doc.revisions():
if doc.get_related_meeting() == meeting and rev in doc.revisions_by_newrevisionevent():
return doc, rev
# give up
raise Document.DoesNotExist

View file

@ -11,7 +11,6 @@
<label for="url1" class="col-form-label col-sm-2 fw-bold">From revision</label>
<div class="col-sm-10">
{% endif %}
{% with prev_rev=doc.rev|add:"-1"|stringformat:"02d" %}
<select class="form-select{% if document_html %} form-select-sm mb-1{% endif %} select2-field"
data-max-entries="1"
data-width="resolve"
@ -19,26 +18,14 @@
data-minimum-input-length="0"
{% if not document_html %}id="url1"{% else %}aria-label="From revision"{% endif %}
name="url1">
{% for name, rev, time, url in diff_revisions %}
<option value="{{ url }}"
{% if document_html %}
{% if name == doc.name %}
{% if rev == prev_rev or doc.rev == "00" and rev == "00" %} selected{% endif %}
{% endif %}
{% else %}
{% if diff_revisions|length > 1 and forloop.counter == 2 %} selected{% endif %}
{% endif %}>
{% for name, rev, time, url, is_this_doc, is_previous_doc in diff_revisions %}
<option value="{{ url }}"{% if is_previous_doc %} selected{% endif %}>
{{ name|prettystdname }}{% if rev %}-{{ rev }}{% endif %}
{% if not document_html %}({{ time|date:"Y-m-d" }}){% endif %}
</option>
{% endfor %}
{% if doc.name|rfcbis %}
<option value="{{ doc.name|rfcbis }}"
{% if document_html %}
{% if rev == prev_rev %} selected{% endif %}
{% else %}
{% if diff_revisions and diff_revisions|length == 1 %} selected{% endif %}
{% endif %}>
{% if doc.name|rfcbis %} {# TODO - move this into the diffable versions logic #}
<option value="{{ doc.name|rfcbis }}"{% if diff_revisions and diff_revisions|length == 1 %} selected{% endif %}>
{{ doc.name|rfcbis|prettystdname }}
</option>
{% endif %}
@ -57,13 +44,8 @@
data-minimum-input-length="0"
{% if not document_html %}id="url2"{% else %}aria-label="To revision"{% endif %}
name="url2">
{% for name, rev, time, url in diff_revisions %}
<option value="{{ url }}"
{% if document_html %}
{% if not snapshot and doc.type_id == "rfc" and name == "rfc"|add:doc.rfc_number or snapshot and name == doc.name and rev == doc.rev %} selected{% endif %}
{% else %}
{% if forloop.counter == 1 %} selected{% endif %}
{% endif %}>
{% for name, rev, time, url, is_this_doc, is_previous_doc in diff_revisions %}
<option value="{{ url }}"{% if is_this_doc %} selected{%endif%}>
{{ name|prettystdname }}{% if rev %}-{{ rev }}{% endif %}
{% if not document_html %}({{ time|date:"Y-m-d" }}){% endif %}
</option>
@ -107,7 +89,6 @@
name="difftype">
Inline
</button>
{% endwith %}
{% if not document_html %}
</div>
</div>

View file

@ -33,8 +33,8 @@
{% endif %}
<link rel="alternate" type="application/atom+xml" title="Document changes" href="/feed/document-changes/{{ doc.name }}/">
<meta name="description"
{% if not snapshot and doc.type_id == 'rfc' %}
content="{{ doc.title }} (RFC {{ doc.rfc_number }}{% if published %}, {{ published.time|date:'F Y' }}{% endif %}{% if obsoleted_by %}; obsoleted by {% for rel in obsoleted_by %}{{ rel.source.name|prettystdname}}{% if not forloop.last%}, {% endif %}{% endfor %}{% endif %})"
{% if doc.type_id == "rfc" %}
content="{{ doc.title }} (RFC {{ doc.rfc_number }}, {{ published.time|date:'F Y' }}{% if obsoleted_by %}; obsoleted by {% for rel in obsoleted_by %}{{ rel.source.name|prettystdname}}{% if not forloop.last%}, {% endif %}{% endfor %}{% endif %})"
{% else %}
content="{{ doc.title }} (Internet-Draft, {{ doc.time|date:'Y' }})"
{% endif %}>
@ -98,9 +98,9 @@
<nav class="navbar bg-light-subtle px-1 fixed-top d-print-none d-md-none">
<a class="nav-link ps-1"
href="{% url 'ietf.doc.views_doc.document_main' name=doc.name %}">
{% if not snapshot and doc.type_id == "rfc" %}
{% if doc.type_id == "rfc" %}
RFC {{ doc.rfc_number }}
{% else %}
{% else %}
{{ doc.name }}-{{ doc.rev }}
{% endif %}
<br class="d-sm-none">
@ -175,7 +175,7 @@
<div class="pt-2 pt-lg-3 px-md-2 px-lg-3">
<a class="btn btn-primary btn-sm" href="{% url 'ietf.doc.views_doc.document_main' name=doc.name %}">Datatracker</a>
<p class="fw-bold pt-2">
{% if not snapshot and doc.type_id == "rfc" %}
{% if doc.type_id == "rfc" %}
RFC {{ doc.rfc_number }}
{% else %}
{{ doc.name }}-{{ doc.rev }}

View file

@ -31,7 +31,7 @@
{% if document_html %}View errata{% else %}Errata{% endif %}
</a>
{% endif %}
{% if document_html and doc.type_id == "rfc" and not snapshot %}
{% if document_html and doc.type_id == "rfc" %}
<a class="btn btn-sm btn-warning"
title="Click to report an error in the document."
href="https://www.rfc-editor.org/errata.php#reportnew"
@ -60,8 +60,8 @@
</div>
{% endif %}
{% else %}
{% if snapshot and doc.doc.type_id == 'rfc' %}
<div{% if document_html %} class="alert alert-warning small"{% endif %}>This is an older version of an Internet-Draft that was ultimately published as <a href="{% url 'ietf.doc.views_doc.document_html' name=doc.doc.name %}">{{doc.doc.name|prettystdname}}</a>.</div>
{% if snapshot and doc.doc.became_rfc %}
<div{% if document_html %} class="alert alert-warning small"{% endif %}>This is an older version of an Internet-Draft that was ultimately published as <a href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.doc.became_rfc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.doc.became_rfc.name %}{% endif %}">{{doc.doc.became_rfc.name|prettystdname}}</a>.</div>
{% elif snapshot and doc.rev != latest_rev %}
<div{% if document_html %} class="alert alert-warning small"{% endif %}>This is an older version of an Internet-Draft whose latest revision state is "{{ doc.doc.get_state }}".</div>
{% else %}
@ -70,7 +70,7 @@
{% if resurrected_by %}- resurrect requested by {{ resurrected_by }}{% endif %}
{% endif %}
{% endif %}
{% if doc.get_state_slug != "active" and doc.get_state_slug != "rfc" %}
{% if doc.get_state_slug != "active" and doc.type_id != "rfc" %}
<div class="badge rounded-pill text-bg-warning{% if not document_html %} float-end{% endif %}">
Expired &amp; archived
</div>

View file

@ -1,5 +1,5 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2016-2020, All Rights Reserved #}
{# Copyright The IETF Trust 2016-2023, All Rights Reserved #}
{% load origin %}
{% load static %}
{% load ietf_filters %}
@ -13,43 +13,19 @@
title="Document changes"
href="/feed/document-changes/{{ name }}/">
<meta name="description"
content="{{ doc.title }} {% if doc.type_id == 'rfc' and not snapshot %}(RFC {{ rfc_number }}{% if published %}, {{ doc.pub_date|date:'F Y' }}{% endif %}{% if obsoleted_by %}; obsoleted by {% for rel in obsoleted_by %}{{ rel.source.name|prettystdname}}{% if not forloop.last%}, {% endif %}{% endfor %}{% endif %}){% endif %}">
content="{{ doc.title }} (RFC {{ doc.rfc_number }}, {{ doc.pub_date|date:'F Y' }}{% if obsoleted_by %}; obsoleted by {% for rel in obsoleted_by %}{{ rel.source.name|prettystdname}}{% if not forloop.last%}, {% endif %}{% endfor %}{% endif %})">
{% endblock %}
{% block morecss %}.inline { display: inline; }{% endblock %}
{% block title %}
RFC {{ rfc_number }} - {{ doc.title }}
RFC {{ doc.rfc_number }} - {{ doc.title }}
{% endblock %}
{% block content %}
{% origin %}
{{ top|safe }}
<div id="timeline"></div>
{% if doc.rev != latest_rev %}
<div class="alert alert-warning my-3">The information below is for an old version of the document.</div>
{% endif %}
<div id="doc-timeline"></div>
<table class="table table-sm table-borderless">
{% include "doc/document_info.html" %}
<tbody class="meta border-top">
{% if milestones %}
<tr>
<td></td>
<th scope="row">
Associated
{% if doc.stream_id == 'ietf' %}
WG
{% else %}
{{ doc.stream }}
{% endif %} milestone{{ milestones|pluralize }}</th>
<td class="edit"></td>
<td>
<dl class="row">
{% for m in milestones %}
<dt class="col-sm-2 my-0">{{ m.due|date:"M Y" }}</dt>
<dd class="col-sm-10 my-0">{{ m.desc }}</dd>
{% endfor %}
</dl>
</td>
</tr>
{% endif %}
</tbody>
{% if doc.stream_id != 'iab' %}
<tbody class="meta border-top">
@ -84,7 +60,7 @@
Send notices to
</th>
<td class="edit">
{% if can_edit_notify and not snapshot %}
{% if can_edit_notify %}
<a class="btn btn-primary btn-sm"
href="{% url 'ietf.doc.views_doc.edit_notify' name=doc.name %}">
Edit
@ -103,47 +79,6 @@
</tr>
</tbody>
{% endif %}
{% if rfc_editor_state %}
<tbody class="meta border-top">
<tr>
<th scope="row">
RFC Editor
</th>
<th scope="row">
<a href="{% url "ietf.help.views.state" doc=doc.type.slug type="rfceditor" %}">
RFC Editor state
</a>
</th>
<td class="edit">
</td>
<td>
{{ rfc_editor_state }}
</td>
</tr>
<tr>
<td></td>
<th scope="row">
Details
</th>
<td class="edit">
</td>
<td>
<div>
<a href="https://www.rfc-editor.org/queue2.html#{{ doc.name }}">
Publication queue entry
</a>
</div>
{% if rfc_editor_auth48_url %}
<div>
<a href="{{ rfc_editor_auth48_url }}">
Auth48 status
</a>
</div>
{% endif %}
</td>
</tr>
</tbody>
{% endif %}
</table>
<div class="buttonlist">
<a class="btn btn-primary btn-sm"
@ -152,7 +87,7 @@
</i>
Email authors
</a>
{% if doc.group.type.slug == 'wg' or doc.group.type.slug == 'rg' %}
{% if doc.group.type_id == "wg" or doc.group.type_id == "rg" %}
<a class="btn btn-primary btn-sm"
href="mailto:{{ doc.group.list_email }}?subject=Mail%20regarding%20{{ doc.name }}">
<i class="bi bi-envelope">
@ -186,46 +121,12 @@
</i>
Referenced by
</a>
{# document_draft shows Nits here, excluded for RFCs #}
<div class="dropdown inline">
<button class="btn btn-primary btn-sm dropdown-toggle"
type="button"
id="ddSearchMenu"
data-bs-toggle="dropdown"
aria-expanded="true">
<i class="bi bi-search">
</i>
Search lists
</button>
<ul class="dropdown-menu" role="menu">
<li role="presentation">
<a class="dropdown-item"
href="https://mailarchive.ietf.org/arch/search?q=%22{{ doc.name }}%22"
rel="nofollow"
target="_blank">
IETF Mail Archive
</a>
</li>
<li role="presentation">
<a class="dropdown-item"
href="https://www.google.com/search?as_q={{ doc.name }}&amp;as_sitesearch={{ search_archive }}"
rel="nofollow"
target="_blank">
Google
</a>
</li>
{% if user|has_role:"Area Director" %}
<li role="presentation">
<a class="dropdown-item"
href="https://www.iesg.org/bin/c5i?mid=6&amp;rid=77&amp;target={{ doc.name }}"
rel="nofollow"
target="_blank">
ARO
</a>
</li>
{% endif %}
</ul>
</div>
<a class="btn btn-primary btn-sm"
href="https://mailarchive.ietf.org/arch/search?q=%22{{ doc.name }}%22"
rel="nofollow"
target="_blank">
Search Lists
</a>
{% if user.is_authenticated %}
<a class="btn btn-primary btn-sm track-untrack-doc {% if not doc.tracked_in_personal_community_list %}hide{% endif %}"
href="{% url "ietf.community.views.untrack_document" username=user.username name=doc.name %}"
@ -242,36 +143,6 @@
Track
</a>
{% endif %}
{% if user.review_teams %}
<a class="btn btn-primary btn-sm review-wish-add-remove-doc ajax {% if not doc.has_review_wish %}hide{% endif %}"
href="{% url "ietf.doc.views_review.review_wishes_remove" name=doc.name %}?next={{ request.get_full_path|urlencode }}"
title="Remove from your review wishes for all teams">
<i class="bi bi-chat-left-heart-fill">
</i>
Remove review wishes
</a>
<a class="btn btn-primary btn-sm review-wish-add-remove-doc {% if user.review_teams|length_is:"1" %}ajax {% endif %}{% if doc.has_review_wish %}hide{% endif %}"
href="{% url "ietf.doc.views_review.review_wish_add" name=doc.name %}?next={{ request.get_full_path|urlencode }}"
title="Add to your review wishes">
<i class="bi bi-chat-left-heart">
</i>
Add review wish
</a>
{% endif %}
{% if can_edit and iesg_state.slug != 'idexists' %}
<a class="btn btn-primary btn-sm"
href="{% url 'ietf.doc.views_ballot.lastcalltext' name=doc.name %}">
Last call text
</a>
<a class="btn btn-primary btn-sm"
href="{% url 'ietf.doc.views_ballot.ballot_writeupnotes' name=doc.name %}">
Ballot text
</a>
<a class="btn btn-primary btn-sm"
href="{% url 'ietf.doc.views_ballot.ballot_approvaltext' name=doc.name %}">
Announcement text
</a>
{% endif %}
{% if actions %}
{% for label, url in actions %}
<a class="btn btn-primary btn-sm" href="{{ url }}">
@ -280,56 +151,22 @@
{% endfor %}
{% endif %}
</div>
{% if doc.get_state_slug == "active" or doc.type_id == "rfc" %}
<div class="card mt-5">
<div class="card-header">
{% if doc.type_id == "rfc" and not snapshot %}
RFC {{ rfc_number }}
{% else %}
{{ name }}-{{ doc.rev }}
{% endif %}
</div>
<div class="card-body">
<pre>{{ content|sanitize|safe|default:"(Unavailable)" }}</pre>
</div>
<div class="card mt-5">
<div class="card-header">
RFC {{ doc.rfc_number }}
</div>
{% if split_content %}
<a class="btn btn-primary my-3" href="?include_text=1">
<i class="bi bi-caret-down">
</i>
Show full document
</a>
{% endif %}
{% else %}
<div class="card border-warning mt-5">
<div class="card-header bg-warning">
<p><b>This Internet-Draft is no longer active. A copy of
the expired Internet-Draft is available in these formats:</b></p>
{% include "doc/document_format_buttons.html" %}
</div>
<div class="card-body">
<p class="h5 card-title">
Abstract
</p>
<p class="card-text">
{{ doc.abstract }}
</p>
<p class="h5 card-title">
Authors
</p>
<p class="card-text">
{% for author in doc.documentauthor_set.all %}
{% person_link author.person %}
{% if not forloop.last %}<br>{% endif %}
{% endfor %}
</p>
<p class="text-body-secondary card-text">
(Note: The e-mail addresses provided for the authors of this Internet-Draft may no longer be valid.)
</p>
</div>
<div class="card-body">
<pre>{{ content|sanitize|safe|default:"(Unavailable)" }}</pre>
</div>
</div>
{% if split_content %}
<a class="btn btn-primary my-3" href="?include_text=1">
<i class="bi bi-caret-down">
</i>
Show full document
</a>
{% endif %}
{% endblock %}
{% block js %}
<script src="{% static 'ietf/js/d3.js' %}">

View file

@ -9,7 +9,7 @@
{% origin %}
{{ top|safe }}
{% include "doc/revisions_list.html" %}
<div id="timeline"></div>
<div id="doc-timeline"></div>
{% if doc.rev != latest_rev %}
<div class="alert alert-warning my-3">The information below is for an older version of this statement.</div>
{% endif %}

View file

@ -6,31 +6,46 @@
<nav class="mb-3">
{% endif %}
<ul class="revision-list{%if doc.type.slug == 'charter' %} charter{% endif %} pagination pagination-sm text-center flex-wrap{% if document_html %} my-0{% endif %}">
{% for rev in revisions %}
{% if rev %}
<li class="page-item {%if doc.type.slug == 'charter' and rev == rev|charter_major_rev %}fw-bold {% endif %}{% if rev == doc.rev %}{% if snapshot or doc.get_state_slug != 'rfc' %}active{% endif %}{% endif %}">
<a class="page-link"
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.name rev=rev %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.name rev=rev %}{% endif %}"
{% if rev != '00' and rev != latest_rev %}rel="nofollow"{% endif %}>
{{ rev }}
</a>
</li>
{% if doc.type_id == "rfc" %}
{% with doc.came_from_draft as draft %}
{% if draft %}
{% for rev in draft.revisions_by_dochistory %}
<li class="page-item">
<a class="page-link"
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=draft.name rev=rev %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=draft.name rev=rev %}{% endif %}"
rel="nofollow">
{{ rev }}
</a>
</li>
{% endfor %}
{% endif %}
{% endfor %}
{% if doc.type_id == 'rfc' %}
<li class="page-item rfc{% if not snapshot %} active{% endif %}">
{% endwith %}
<li class="page-item rfc active">
<a class="page-link"
href="{% if doc.doc %}{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.doc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.doc.name %}{% endif %}{% else %}{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.name %}{% endif %}{% endif %}">
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.name %}{% endif %}">
RFC {{ doc.rfc_number }}
</a>
</li>
{% elif doc.doc.type_id == 'rfc' %}
<li class="page-item rfc">
<a class="page-link"
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.doc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.doc.name %}{% endif %}">
RFC {{ doc.doc.rfc_number }}
</a>
</li>
{% else %}
{% for rev in revisions %}
{% if rev %} {# I think this guard is now unnecessary #}
<li class="page-item {%if doc.type.slug == 'charter' and rev == rev|charter_major_rev %}fw-bold {% endif %}{% if rev == doc.rev %}{% if snapshot or doc.get_state_slug != 'rfc' %}active{% endif %}{% endif %}">
<a class="page-link"
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.name rev=rev %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.name rev=rev %}{% endif %}"
{% if rev != '00' and rev != latest_rev %}rel="nofollow"{% endif %}>
{{ rev }}
</a>
</li>
{% endif %}
{% endfor %}
{% if doc.became_rfc %}
<li class="page-item rfc">
<a class="page-link"
href="{% if document_html %}{% url 'ietf.doc.views_doc.document_html' name=doc.became_rfc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.became_rfc.name %}{% endif %}">
RFC {{ doc.became_rfc.rfc_number }}
</a>
</li>
{% endif %}
{% endif %}
</ul>
{% if not document_html %}