Skip to content

Commit

Permalink
feat: subseries
Browse files Browse the repository at this point in the history
  • Loading branch information
rjsparks committed Sep 21, 2023
1 parent f15960d commit 0390f18
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 36 deletions.
21 changes: 21 additions & 0 deletions ietf/doc/migrations/0018_subseries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright The IETF Trust 2023, All Rights Reserved
from django.db import migrations


def forward(apps, schema_editor):
StateType = apps.get_model("doc", "StateType")
for slug in ["bcp", "std", "fyi"]:
StateType.objects.create(slug=slug, label=f"{slug} state")


def reverse(apps, schema_editor):
StateType = apps.get_model("doc", "StateType")
StateType.objects.filter(slug__in=["bcp", "std", "fyi"]).delete()


class Migration(migrations.Migration):
dependencies = [
("doc", "0017_move_dochistory"),
]

operations = [migrations.RunPython(forward, reverse)]
6 changes: 6 additions & 0 deletions ietf/doc/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,12 @@ def came_from_draft(self):
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

def contains(self):
return self.related_that_doc("contains")

def part_of(self):
return self.related_that("contains")

class Meta:
abstract = True
Expand Down
2 changes: 2 additions & 0 deletions ietf/doc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
url(r'^ballots/irsg/$', views_ballot.irsg_ballot_status),
url(r'^ballots/rsab/$', views_ballot.rsab_ballot_status),

url(r'^(?P<type_id>(bcp|std|fyi))/?$', views_search.index_subseries),

url(r'^%(name)s(?:/%(rev)s)?/$' % settings.URL_REGEXPS, views_doc.document_main),
url(r'^%(name)s(?:/%(rev)s)?/bibtex/$' % settings.URL_REGEXPS, views_doc.document_bibtex),
url(r'^%(name)s(?:/%(rev)s)?/idnits2-state/$' % settings.URL_REGEXPS, views_doc.idnits2_state),
Expand Down
20 changes: 7 additions & 13 deletions ietf/doc/views_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,16 @@ def render_document_top(request, doc, tab, name):
None,
)
)

tabs.append(("Email expansions","email",urlreverse('ietf.doc.views_doc.document_email', kwargs=dict(name=name)), True, None))
if not doc.type_id in ["bcp", "std", "fyi"]:
tabs.append(("Email expansions","email",urlreverse('ietf.doc.views_doc.document_email', kwargs=dict(name=name)), True, None))
tabs.append(("History", "history", urlreverse('ietf.doc.views_doc.document_history', kwargs=dict(name=name)), True, None))

if name.startswith("rfc"):
name = "RFC %s" % name[3:]
else:
name += "-" + doc.rev

return render_to_string("doc/document_top.html",
return render_to_string("doc/document_top.html" if not doc.type_id in ["bcp", "std", "fyi"] else "doc/document_subseries_top.html",
dict(doc=doc,
tabs=tabs,
selected=tab,
Expand Down Expand Up @@ -934,7 +934,7 @@ def document_main(request, name, rev=None, document_html=False):
)
)

if doc.type_id == "statement":
elif doc.type_id == "statement":
if doc.uploaded_filename:
basename = doc.uploaded_filename.split(".")[0] # strip extension
else:
Expand All @@ -955,7 +955,6 @@ def document_main(request, name, rev=None, document_html=False):
can_manage = has_role(request.user,["Secretariat"]) # Add IAB or IESG as appropriate
interesting_relations_that, interesting_relations_that_doc = interesting_doc_relations(doc)
published = doc.latest_event(type="published_statement").time

return render(request, "doc/document_statement.html",
dict(doc=doc,
top=top,
Expand All @@ -968,6 +967,9 @@ def document_main(request, name, rev=None, document_html=False):
replaced_by=interesting_relations_that.filter(relationship="replaces"),
can_manage=can_manage,
))
elif doc.type_id in ["bcp", "std", "fyi"]:
return render(request, "doc/document_subseries.html", {"doc": doc, "top": top})


raise Http404("Document not found: %s" % (name + ("-%s"%rev if rev else "")))

Expand Down Expand Up @@ -1230,13 +1232,6 @@ def document_history(request, name):
request.user, ("Area Director", "Secretariat", "IRTF Chair")
)

# Get related docs whose history should be linked
if doc.type_id == "draft":
related = doc.related_that_doc("became_rfc")
elif doc.type_id == "rfc":
related = doc.related_that("became_rfc")
else:
related = []

return render(
request,
Expand All @@ -1246,7 +1241,6 @@ def document_history(request, name):
"top": top,
"diff_revisions": diff_revisions,
"events": events,
"related": related,
"can_add_comment": can_add_comment,
},
)
Expand Down
8 changes: 8 additions & 0 deletions ietf/doc/views_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -895,3 +895,11 @@ def ajax_select2_search_docs(request, model_name, doc_type): # TODO - remove mod
objs = qs.distinct().order_by("name")[:20]

return HttpResponse(select2_id_doc_name_json(model, objs), content_type='application/json')

def index_subseries(request, type_id):
docs = sorted(Document.objects.filter(type_id=type_id),key=lambda o: int(o.name[3:]))
if len(docs)>0:
type = docs[0].type
else:
type = DocTypeName.objects.get(slug=type_id)
return render(request, "doc/index_subseries.html", {"type": type, "docs": docs})
38 changes: 38 additions & 0 deletions ietf/name/migrations/0010_subseries.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright The IETF Trust 2023, All Rights Reserved

from django.db import migrations


def forward(apps, schema_editor):
DocTypeName = apps.get_model("name", "DocTypeName")
DocRelationshipName = apps.get_model("name", "DocRelationshipName")
for slug, name, prefix in [
("std", "Standard", "std"),
("bcp", "Best Current Practice", "bcp"),
("fyi", "For Your Information", "fyi"),
]:
DocTypeName.objects.create(
slug=slug, name=name, prefix=prefix, desc="", used=True
)
DocRelationshipName.objects.create(
slug="contains",
name="Contains",
revname="Is part of",
desc="This document contains other documents (e.g., STDs contain RFCs)",
used=True,
)


def reverse(apps, schema_editor):
DocTypeName = apps.get_model("name", "DocTypeName")
DocRelationshipName = apps.get_model("name", "DocRelationshipName")
DocTypeName.objects.filter(slug__in=["std", "bcp", "fyi"]).delete()
DocRelationshipName.objects.filter(slug="contains").delete()


class Migration(migrations.Migration):
dependencies = [
("name", "0009_rfc_doctype_names"),
]

operations = [migrations.RunPython(forward, reverse)]
55 changes: 45 additions & 10 deletions ietf/sync/rfceditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,8 @@ def update_docs_from_rfc_index(

system = Person.objects.get(name="(System)")

first_sync_creating_subseries = not Document.objects.filter(type_id__in=["bcp","std","fyi"]).exists()

for (
rfc_number,
title,
Expand Down Expand Up @@ -511,8 +513,9 @@ def update_docs_from_rfc_index(
stream_slug = f"draft-stream-{draft.stream.slug}"
prev_state = draft.get_state(stream_slug)
if prev_state is None:
# TODO: main returns warnings to the caller rather tha logging to the system - look to see if we should be using that instead
log(f"Warning while processing {doc.name}: draft {draft.name} stream state was not set")
if prev_state.slug != "pub":
elif prev_state.slug != "pub":
new_state = State.objects.select_related("type").get(used=True, type__slug=stream_slug, slug="pub")
draft.set_state(new_state)
draft_changes.append(
Expand Down Expand Up @@ -650,15 +653,47 @@ def parse_relation_list(l):
)
)

# This block attempted to alias subseries names to RFCs.
# Handle that differently when we add subseries as a document type.
#
# if also:
# for a in also:
# a = a.lower()
# if not DocAlias.objects.filter(name=a):
# DocAlias.objects.create(name=a).docs.add(doc)
# rfc_changes.append(f"created alias {prettify_std_name(a)}")
if also:
# recondition also to have proper subseries document names:
conditioned_also = []
for a in also:
a = a.lower()
subseries_slug = a[:3]
if subseries_slug not in ["bcp", "std", "fyi"]:
log(f"Unexpected 'also' relationship of {a} encountered for {doc}")
next
maybe_number = a[3:].strip()
if not maybe_number.isdigit():
log(f"Unexpected 'also' subseries element identifier {a} encountered for {doc}")
next
else:
subseries_number = int(maybe_number)
conditioned_also.append(f"{subseries_slug}{subseries_number}") # Note the lack of leading zeros
also = conditioned_also

for a in also:
subseries_doc_name = a
subseries_slug=a[:3]
# Leaving most things to the default intentionally
# Of note, title and stream are left to the defaults of "" and none.
subseries_doc, created = Document.objects.get_or_create(type_id=subseries_slug, name=subseries_doc_name)
if created:
if first_sync_creating_subseries:
subseries_doc.docevent_set.create(type=f"{subseries_slug}_history_marker", by=system, desc=f"No history of this {subseries_slug.upper()} document is currently available in the datatracker before this point")
subseries_doc.docevent_set.create(type="subseries_doc_created", by=system, desc=f"Created {subseries_doc_name} via sync to the rfc-index")
if not subseries_doc.relateddocument_set.filter(relationship_id="contains", target=doc).exists():
subseries_doc.relateddocument_set.create(relationship_id="contains", target=doc)
subseries_doc.docevent_set.create(type="sync_from_rfc_editor", by=system, desc=f"Added {doc.name} to {subseries_doc.name}")
if first_sync_creating_subseries:
rfc_events.append(doc.docevent_set.create(type=f"{subseries_slug}_history_marker", by=system, desc=f"No history of {subseries_doc.name.upper()} is currently available in the datatracker before this point"))
rfc_events.append(doc.docevent_set.create(type="sync_from_rfc_editor", by=system, desc=f"Added {doc.name} to {subseries_doc.name}"))

for subdoc in doc.related_that("contains"):
if subdoc.name not in also:
assert(not first_sync_creating_subseries)
subseries_doc.relateddocument_set.filter(target=subdoc).delete()
rfc_events.append(doc.docevent_set.create(type="sync_from_rfc_editor", by=system, desc=f"Removed {doc.name} from {subseries_doc.name}"))
subseries_doc.docevent_set.create(type="sync_from_rfc_editor", by=system, desc=f"Removed {doc.name} from {subseries_doc.name}")

doc_errata = errata.get(f"RFC{rfc_number}", [])
all_rejected = doc_errata and all(
Expand Down
37 changes: 24 additions & 13 deletions ietf/templates/doc/document_history.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,28 @@
<h2 class="my-3">Revision differences</h2>
{% include "doc/document_history_form.html" with doc=doc diff_revisions=diff_revisions action=rfcdiff_base_url snapshot=snapshot only %}
{% endif %}
<h2 class="my-3">Document history
{% if related %}
<div class="float-end">
{% for related_document in related %}
<a class="btn btn-outline-primary btn-sm"
href="{% url 'ietf.doc.views_doc.document_history' name=related_document.name %}">
Related history for {{ related_document.name }}
</a>
{% endfor %}
</div>
{% endif %}</h2>
<h2 class="my-3">Document history</h2>
{% if doc.came_from_draft %}
<ul class="nav nav-tabs my-3">
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.doc.views_doc.document_history' name=doc.came_from_draft.name %}">{{doc.came_from_draft.name}}</a>
<li>
<li class="nav-item">
<a class="nav-link active">RFC {{doc.name|slice:"3:"}}</a>
</li>
</ul>
{% endif %}
{% if doc.became_rfc %}
<ul class="nav nav-tabs my-3">
<li class="nav-item">
<a class="nav-link active">{{doc.name}}</a>
<li>
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.doc.views_doc.document_history' name=doc.became_rfc.name %}">RFC {{doc.became_rfc.name|slice:"3:"}}</a>
</li>
</ul>
{% endif %}

{% if can_add_comment %}
<div class="buttonlist">
<a class="btn btn-primary"
Expand All @@ -44,7 +55,7 @@ <h2 class="my-3">Document history
<thead>
<tr>
<th scope="col" data-sort="date">Date</th>
{% if doc.type_id != "rfc" %}<th scope="col" data-sort="rev">Rev.</th>{% endif %}
{% if doc.type_id not in "rfc,bcp,std,fyi" %}<th scope="col" data-sort="rev">Rev.</th>{% endif %}
<th scope="col" data-sort="by">By</th>
<th scope="col" data-sort="action">Action</th>
</tr>
Expand All @@ -55,7 +66,7 @@ <h2 class="my-3">Document history
<td>
<div title="{{ e.time|date:'Y-m-d H:i:s O' }}">{{ e.time|date:"Y-m-d" }}</div>
</td>
{% if doc.type_id != "rfc" %}<td class="text-end">{{ e.rev }}</td>{% endif %}
{% if doc.type_id not in "rfc,bcp,std,fyi" %}<td class="text-end">{{ e.rev }}</td>{% endif %}
<td>{{ e.by|escape }}</td>
<td>{{ e.desc|format_history_text }}</td>
</tr>
Expand Down
13 changes: 13 additions & 0 deletions ietf/templates/doc/document_subseries.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2023, All Rights Reserved #}
{% load origin %}
{% load static %}
{% block title %}{{doc.type.name}}s{% endblock %}
{% block content %}
{% origin %}
{{ top|safe }}
<h2>{{ doc.name|slice:":3"|upper }} {{ doc.name|slice:"3:"}} consists of:</h2>
{% for rfc in doc.contains %}
<p><a href="{% url 'ietf.doc.views_doc.document_main' name=rfc.name %}"">RFC {{rfc.name|slice:"3:"}}</a> : {{rfc.title}}</p>
{% endfor %}
{% endblock %}
17 changes: 17 additions & 0 deletions ietf/templates/doc/document_subseries_top.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% origin %}
{% load ietf_filters %}
<h1>
{{ doc.name|slice:":3"|upper }} {{ doc.name|slice:"3:"}}
</h1>
<ul class="nav nav-tabs my-3">
{% for name, t, url, active, tooltip in tabs %}
<li {% if tooltip %}title="{{ tooltip }}"{% endif %} class="nav-item">
<a class="nav-link {% if t == selected %}active{% endif %}{% if not active %}disabled{% endif %}"
{% if active %}href="{{ url }}"{% endif %}>
{{ name|capfirst_allcaps }}
</a>
</li>
{% endfor %}
</ul>
19 changes: 19 additions & 0 deletions ietf/templates/doc/index_subseries.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2023, All Rights Reserved #}
{% load origin %}
{% load static %}
{% block title %}{{type.name}}s{% endblock %}
{% block content %}
{% origin %}
<h1>{{type.name}}s</h1>
{% for doc in docs %}
<div class="card mb-3" id={{doc.name}}>
<div class="card-header"><a href="{% url 'ietf.doc.views_doc.document_main' name=doc.name %}">{{doc.name}}</a></div>
<div class="card-body">
{% for rfc in doc.contains %}
<p><a href="{% url 'ietf.doc.views_doc.document_main' name=rfc.name %}"">{{rfc.name}}</a> : {{rfc.title}}</p>
{% endfor %}
</div>
</div>
{% endfor %}
{% endblock %}

0 comments on commit 0390f18

Please sign in to comment.