feat: Add disclaimer banner for unadopted I-Ds and non-IETF RFCs (#6786)

* feat: Add disclaimer banners for unadopted I-Ds and non-IETF RFCs

Fixes #6539

* Fixes

* Add test

* Use BofreqFactory

* Fix disclaimer logic

* fix: Wording changes from stream owners

* fix: Only insert <wbr> when there isn't a space before or after (#6821)

* fix: Only insert <wbr> when there isn't a space before or after.

* Fix @cabo's issue

* fix: Remove debug info from template (#6897)

Fixes #6895

* fix: remove link to Warren's draft from disclaimer text (#7429)

---------

Co-authored-by: Lars Eggert <lars@eggert.org>
This commit is contained in:
Robert Sparks 2024-05-23 10:55:21 -05:00 committed by GitHub
parent d5009ee794
commit 720f31b6ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 88 additions and 5 deletions

View file

@ -933,3 +933,28 @@ def url_for_path(path):
return f"{settings.IETF_ID_ARCHIVE_URL}{path.name}" return f"{settings.IETF_ID_ARCHIVE_URL}{path.name}"
else: else:
return "#" return "#"
@register.filter
def is_in_stream(doc):
"""
Check if the doc is in one of the states in it stream that
indicate that is actually adopted, i.e., part of the stream.
(There are various "candidate" states that necessitate this
filter.)
"""
if not doc.stream:
return False
stream = doc.stream.slug
state = doc.get_state_slug(f"draft-stream-{doc.stream.slug}")
if not state:
return True
if stream == "ietf":
return state not in ["wg-cand", "c-adopt"]
elif stream == "irtf":
return state != "candidat"
elif stream == "iab":
return state not in ["candidat", "diff-org"]
elif stream == "editorial":
return True
return False

View file

@ -7,9 +7,20 @@ from ietf.doc.factories import (
IndividualDraftFactory, IndividualDraftFactory,
CharterFactory, CharterFactory,
NewRevisionDocEventFactory, NewRevisionDocEventFactory,
StatusChangeFactory,
RgDraftFactory,
EditorialDraftFactory,
WgDraftFactory,
ConflictReviewFactory,
BofreqFactory,
StatementFactory,
) )
from ietf.doc.models import DocEvent from ietf.doc.models import DocEvent
from ietf.doc.templatetags.ietf_filters import urlize_ietf_docs, is_valid_url from ietf.doc.templatetags.ietf_filters import (
urlize_ietf_docs,
is_valid_url,
is_in_stream,
)
from ietf.person.models import Person from ietf.person.models import Person
from ietf.utils.test_utils import TestCase from ietf.utils.test_utils import TestCase
@ -19,13 +30,28 @@ import debug # pyflakes: ignore
class IetfFiltersTests(TestCase): class IetfFiltersTests(TestCase):
def test_is_in_stream(self):
for draft in [
IndividualDraftFactory(),
CharterFactory(),
StatusChangeFactory(),
ConflictReviewFactory(),
StatementFactory(),
BofreqFactory(),
]:
self.assertFalse(is_in_stream(draft))
for draft in [RgDraftFactory(), WgDraftFactory(), EditorialDraftFactory()]:
self.assertTrue(is_in_stream(draft))
for stream in ["iab", "ietf", "irtf", "ise", "editorial"]:
self.assertTrue(is_in_stream(IndividualDraftFactory(stream_id=stream)))
def test_is_valid_url(self): def test_is_valid_url(self):
cases = [(settings.IDTRACKER_BASE_URL, True), ("not valid", False)] cases = [(settings.IDTRACKER_BASE_URL, True), ("not valid", False)]
for url, result in cases: for url, result in cases:
self.assertEqual(is_valid_url(url), result) self.assertEqual(is_valid_url(url), result)
def test_urlize_ietf_docs(self): def test_urlize_ietf_docs(self):
rfc = WgRfcFactory(rfc_number=123456,std_level_id="bcp") rfc = WgRfcFactory(rfc_number=123456, std_level_id="bcp")
rfc.save_with_history( rfc.save_with_history(
[ [
DocEvent.objects.create( DocEvent.objects.create(
@ -57,7 +83,6 @@ class IetfFiltersTests(TestCase):
cases = [ cases = [
("no change", "no change"), ("no change", "no change"),
# TODO: rework subseries when we add them # TODO: rework subseries when we add them
# ("bCp123456", '<a href="/doc/bcp123456/">bCp123456</a>'), # ("bCp123456", '<a href="/doc/bcp123456/">bCp123456</a>'),
# ("Std 00123456", '<a href="/doc/std123456/">Std 00123456</a>'), # ("Std 00123456", '<a href="/doc/std123456/">Std 00123456</a>'),

View file

@ -57,7 +57,7 @@ $(document)
var text = $(this) var text = $(this)
.text(); .text();
// insert some <wbr> at strategic places // insert some <wbr> at strategic places
var newtext = text.replace(/([@._+])/g, "$1<wbr>"); var newtext = text.replace(/(\S)([@._+])(\S)/g, "$1$2<wbr>$3");
if (newtext === text) { if (newtext === text) {
return; return;
} }

View file

@ -0,0 +1,28 @@
{# Copyright The IETF Trust 2016-2023, All Rights Reserved #}
{% load origin %}
{% load ietf_filters %}
{% origin %}
{% if doc.type_id == "rfc" %}
{% if doc.stream.slug != "ietf" and doc.std_level.slug|default:"unk" not in "bcp,ds,ps,std"|split:"," %}
<div class="alert alert-warning {% if document_html %}small p-2 mt-2{% endif %}" role="alert">
This RFC was published on the {{ doc.stream.desc }} stream.
This RFC is <strong>not endorsed by the IETF</strong> and has <strong>no formal standing</strong> in the
<a href="{% url 'ietf.doc.views_doc.document_main' name='rfc2026' %}">IETF standards process</a>.
</div>
{% endif %}
{% elif doc|is_in_stream %}
{% if doc.stream.slug != "ietf" and doc.std_level.slug|default:"unk" not in "bcp,ds,ps,std"|split:"," %}
<div class="alert alert-warning {% if document_html %}small p-2 mt-2{% endif %}" role="alert">
This document is an Internet-Draft (I-D) that has been submitted to the {{ doc.stream.desc }} stream.
This I-D is <strong>not endorsed by the IETF</strong> and has <strong>no formal standing</strong> in the
<a href="{% url 'ietf.doc.views_doc.document_main' name='rfc2026' %}">IETF standards process</a>.
</div>
{% endif %}
{% else %}
<div class="alert alert-warning {% if document_html %}small p-2 mt-2{% endif %}" role="alert">
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is <strong>not endorsed by the IETF</strong> and has <strong>no formal standing</strong> in the
<a href="{% url 'ietf.doc.views_doc.document_main' name='rfc2026' %}">IETF standards process</a>.
</div>
{% endif %}

View file

@ -27,6 +27,7 @@
{% origin %} {% origin %}
{{ top|safe }} {{ top|safe }}
{% include "doc/revisions_list.html" with document_html=document_html %} {% include "doc/revisions_list.html" with document_html=document_html %}
{% include "doc/disclaimer.html" with document_html=document_html %}
<div id="doc-timeline"></div> <div id="doc-timeline"></div>
{% if doc.rev != latest_rev %} {% if doc.rev != latest_rev %}
<div class="alert alert-warning my-3">The information below is for an old version of the document.</div> <div class="alert alert-warning my-3">The information below is for an old version of the document.</div>

View file

@ -63,7 +63,7 @@
{% if doc.became_rfc %} {% if 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.became_rfc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.became_rfc.name %}{% endif %}">{{doc.became_rfc.name|prettystdname}}</a>.</div> <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.became_rfc.name %}{% else %}{% url 'ietf.doc.views_doc.document_main' name=doc.became_rfc.name %}{% endif %}">{{doc.became_rfc.name|prettystdname}}</a>.</div>
{% elif snapshot and doc.rev != latest_rev %} {% 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> <div{% if document_html %} class="alert alert-warning small p-2 mt-2"{% endif %}>This is an older version of an Internet-Draft whose latest revision state is "{{ doc.doc.get_state }}".</div>
{% else %} {% else %}
<span class="{% if doc.get_state_slug == 'active' %}text-success{% elif doc.get_state_slug == 'expired' or doc.get_state_slug == 'repl' %}text-danger{% endif %}">{% if snapshot and doc.rev == latest_rev %}{{ doc.doc.get_state }}{% else %}{{ doc.get_state }}{% endif %} Internet-Draft</span> <span class="{% if doc.get_state_slug == 'active' %}text-success{% elif doc.get_state_slug == 'expired' or doc.get_state_slug == 'repl' %}text-danger{% endif %}">{% if snapshot and doc.rev == latest_rev %}{{ doc.doc.get_state }}{% else %}{{ doc.get_state }}{% endif %} Internet-Draft</span>
{% if submission %}({{ submission|safe }}){% endif %} {% if submission %}({{ submission|safe }}){% endif %}
@ -75,6 +75,9 @@
Expired &amp; archived Expired &amp; archived
</div> </div>
{% endif %} {% endif %}
{% if document_html %}
{% include "doc/disclaimer.html" with document_html=document_html %}
{% endif %}
</td> </td>
</tr> </tr>
{% if document_html %} {% if document_html %}

View file

@ -22,6 +22,7 @@
{% block content %} {% block content %}
{% origin %} {% origin %}
{{ top|safe }} {{ top|safe }}
{% include "doc/disclaimer.html" with document_html=document_html %}
<div id="doc-timeline"></div> <div id="doc-timeline"></div>
<table class="table table-sm table-borderless"> <table class="table table-sm table-borderless">
{% include "doc/document_info.html" %} {% include "doc/document_info.html" %}