Push some stuff before a mergeable commit.

- Legacy-Id: 19712
This commit is contained in:
Lars Eggert 2021-11-29 17:19:39 +00:00
parent 089754d5f8
commit 9e54310ee7
17 changed files with 1209 additions and 942 deletions

View file

@ -1 +0,0 @@
@import "~/node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css";

View file

@ -139,4 +139,55 @@ $timeline-even-hover-color: shift-color($timeline-even-color, $link-shade-percen
#timeline .bar:nth-child(even) rect:hover,
#timeline .bar:nth-child(even) rect:focus {
fill: $timeline-even-hover-color;
}
// Styles needed for the ballot table
.ballot-icon table td {
border: $table-border-width solid $table-border-color;
height: 10px;
width: 8px;
}
.ballot-icon table .my {
border: 2 * $table-border-width solid #000;
}
.ballot-icon table {
// margin: 0 0 10px 10px;
}
.is-blocking {
box-shadow: 0 0 8px 8px #dc0d12;
padding: 3px 0px 3px 3px;
margin: 5px 1px 3px 0px;
border: 1px solid #dc0d12;
}
.position-moretime,
.position-notready,
.position-discuss,
.position-block {
background-color: $danger;
}
.position-yes {
background-color: $success;
}
.position-noobj {
background-color: $info;
}
.position-abstain {
background-color: hsl(hue($warning), 80%, 70%);
}
.position-recuse {
background-color: hsl(hue($primary), 80%, 70%);
}
.position-norecord {
// background-color: $secondary;
}

View file

@ -0,0 +1,5 @@
import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
global.FullCalendar = Calendar;
global.dayGridPlugin = dayGridPlugin;

View file

@ -104,4 +104,82 @@ $(document)
$("ul.nav li.dropdown, ul.nav li.dropend")
.on("mouseenter mouseleave", dropdown_hover);
}
});
// Automatically add a navigation pane to long pages
$(document)
.ready(function () {
var headings = $("#content")
.find("h1, h2, h3, h4, h5, h6");
if ($(headings)
.length > 0 && $(headings)
.last()
.offset()
.top > $(window)
.height()) {
console.log("Enabling nav.");
var n = 0;
var last_level;
var nav;
$("#content")
.attr("data-bs-offset", 0)
.attr("tabindex", 0)
.after($(`
<div class="col-md-2 small">
<nav id="righthand-nav" class="position-fixed navbar navbar-light bg-light overflow-auto" style="height: 70vh;">
<!--<a class="navbar-brand" href="#">Navbar</a>-->
</nav>
</div>
`))
.find("h1, h2, h3, h4, h5, h6")
.each(function () {
var id = $(this)
.attr("id");
if (id === undefined) {
id = `autoid-${++n}`;
$(this)
.attr("id", id);
}
var text = $(this)
.text();
if (nav === undefined) {
nav = $("#righthand-nav");
nav = $(nav)
.append(`<nav class="nav nav-pills flex-column align-self-start">`)
.children()
.last();
}
var level = parseInt(this.nodeName.substring(1)) - 1;
if (last_level == undefined) {
last_level = level;
}
if (level > last_level) {
last_level = level;
} else
while (level < last_level) {
last_level--;
}
$(nav)
.append(`<a class="nav-link" href="#${id}">${text}</a>`);
});
$(window)
.on("scroll", function () {
var item = $('#righthand-nav')
.find(".active")
.last();
if (item.length) {
item[0].scrollIntoView({ block: "center" });
}
});
}
});

View file

@ -32,7 +32,7 @@ $(document)
})
.toArray();
if (fields.length == 0) {
if (fields.length && fields.filter(field => field != "")) {
console.log("No table fields defined, disabling search/sort.");
} else {

View file

@ -2,351 +2,340 @@
{% extends "base.html" %}
{% load static %}
{% block title %}API Notes{% endblock %}
{% block bodyAttrs %}data-bs-spy="scroll" data-bs-target="#affix"{% endblock %}
{% block content %}
<h2>Datatracker API Notes</h2>
<div class="col-md-11 bio-text">
<div class="bio-text">
<h3 id="framework" class="anchor-target">Framework API</h3>
<div>
<p>
This section describes the autogenrated read-only API towards the database tables. See also
the <a href="{% url 'ietf.submit.views.api_submit' %}">draft submission API description</a> and the
<a href="#iesg-position-api">IESG ballot position API description</a>
</p>
<p>
The datatracker API uses <a href="https://django-tastypie.readthedocs.org/">tastypie</a>
to generate an API which mirrors the Django ORM (Object Relational Mapping)
for the database. Each Django model class maps down to the SQL database
tables and up to the API. The Django models classes are defined in the
models.py files of the datatracker:
</p>
<p>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/doc/models.py">https://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/doc/models.py</a>
<br>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/group/models.py">https://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/group/models.py</a>
<br>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/iesg/models.py">http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/iesg/models.py</a>
<br>
&hellip;
</p>
<p>
The API top endpoint is at <a href="https://datatracker.ietf.org/api/v1/">https://datatracker.ietf.org/api/v1/</a>. The top
endpoint lists inferior endpoints, and thus permits some autodiscovery,
but there's really no substitute for looking at the actual ORM model classes.
Comparing a class in models.py with the equivalent endpoint may give
some clue (note that in the case of Group, it's a subclass of GroupInfo):
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/group/group/">https://datatracker.ietf.org/api/v1/group/group/</a>
<br>
<a href="https://trac.ietf.org/trac/ietfdb/browser/trunk/ietf/group/models.py">https://trac.ietf.org/trac/ietfdb/browser/trunk/ietf/group/models.py</a>
</p>
<p>
Data is currently provided in JSON and XML format. Adding new formats is
fairly easy, if it should be found desriable.
</p>
</div>
<p>
This section describes the autogenerated read-only API towards the database tables. See also
the
<a href="{% url 'ietf.submit.views.api_submit' %}">draft submission API description</a>
and the
<a href="#iesg-position-api">IESG ballot position API description</a>
</p>
<p>
The datatracker API uses
<a href="https://django-tastypie.readthedocs.org/">tastypie</a>
to generate an API which mirrors the Django ORM (Object Relational Mapping)
for the database. Each Django model class maps down to the SQL database
tables and up to the API. The Django models classes are defined in the
models.py files of the datatracker:
</p>
<p>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/doc/models.py">
https://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/doc/models.py
</a>
<br>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/group/models.py">
https://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/group/models.py
</a>
<br>
<a href="http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/iesg/models.py">
http://svn.ietf.org/svn/tools/ietfdb/trunk/ietf/iesg/models.py
</a>
<br>
&hellip;
</p>
<p>
The API top endpoint is at
<a href="https://datatracker.ietf.org/api/v1/">https://datatracker.ietf.org/api/v1/</a>
. The top
endpoint lists inferior endpoints, and thus permits some autodiscovery,
but there's really no substitute for looking at the actual ORM model classes.
Comparing a class in models.py with the equivalent endpoint may give
some clue (note that in the case of Group, it's a subclass of GroupInfo):
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/group/group/">https://datatracker.ietf.org/api/v1/group/group/</a>
<br>
<a href="https://trac.ietf.org/trac/ietfdb/browser/trunk/ietf/group/models.py">
https://trac.ietf.org/trac/ietfdb/browser/trunk/ietf/group/models.py
</a>
</p>
<p>
Data is currently provided in JSON and XML format. Adding new formats is
fairly easy, if it should be found desriable.
</p>
<h4 id="framework-documents" class="anchor-target">Framework API: Documents</h4>
<div>
<p>
Documents are listed at
<a href="https://datatracker.ietf.org/api/v1/doc/document/">/api/v1/doc/document/</a>.
</p>
<p>
In general, individual database objects are represented in the api with a path
composed of the model collection, the object name, and the object key. Most
objects have simple numerical keys, but documents have the document name as
key. Take draft-ietf-eppext-keyrelay. Documents have a model 'Document' which
is described in the 'doc' models.py file. Assembling the path components
'doc', 'document' (lowercase!) and 'draft-ietf-eppext-keyrelay', we get the
URL:
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/doc/document/draft-ietf-eppext-keyrelay/">
https://datatracker.ietf.org/api/v1/doc/document/draft-ietf-eppext-keyrelay/
<p>
Documents are listed at
<a href="https://datatracker.ietf.org/api/v1/doc/document/">/api/v1/doc/document/</a>
.
</p>
<p>
In general, individual database objects are represented in the api with a path
composed of the model collection, the object name, and the object key. Most
objects have simple numerical keys, but documents have the document name as
key. Take draft-ietf-eppext-keyrelay. Documents have a model 'Document' which
is described in the 'doc' models.py file. Assembling the path components
'doc', 'document' (lowercase!) and 'draft-ietf-eppext-keyrelay', we get the
URL:
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/doc/document/draft-ietf-eppext-keyrelay/">
https://datatracker.ietf.org/api/v1/doc/document/draft-ietf-eppext-keyrelay/
</a>
</p>
<p>
If you instead do a search for this document, you will get a machine-readable
search result, which is composed of some meta-information about the search,
and a list with one element:
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/doc/document/?name=draft-ietf-eppext-keyrelay">
api/v1/doc/document/?name=draft-ietf-eppext-keyrelay
</a>
</p>
<p>
To search for documents based on state, you need to know that documents have
multiple orthogonal states:
</p>
<ul>
<li>
If a document has an rfc-editor state, you can select for it by asking for e.g.
<a href="https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor">
v6ops documents which match 'states__type__slug__in=draft-rfceditor'
</a>
</p>
<p>
If you instead do a search for this document, you will get a machine-readable
search result, which is composed of some meta-information about the search,
and a list with one element:
</p>
<p>
<a href="https://datatracker.ietf.org/api/v1/doc/document/?name=draft-ietf-eppext-keyrelay">
api/v1/doc/document/?name=draft-ietf-eppext-keyrelay
</li>
<li>
If a document has an IESG state, you can select for it by asking for e.g.
<a href="https://datatracker.ietf.org/api/v1/doc/document/?name__contains=-v6ops&states__type__slug__in=draft-iesg">
v6ops documents which match 'states__type__slug__in=draft-iesg'
</a>
</p>
<p>
To search for documents based on state, you need to know that documents have
multiple orthogonal states:
</p>
<ul>
<li>
If a document has an rfc-editor state, you can select for it by asking for e.g.
<a href="https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor">
v6ops documents which match 'states__type__slug__in=draft-rfceditor'
</a>
</li>
<li>
If a document has an IESG state, you can select for it by asking for e.g.
<a href="https://datatracker.ietf.org/api/v1/doc/document/?name__contains=-v6ops&states__type__slug__in=draft-iesg">
v6ops documents which match 'states__type__slug__in=draft-iesg'
</a>
</li>
<li>
If a document has a WG state, you can select for it by asking for
documents which match 'states__type__slug__in=draft-stream-ietf'
(but without additional filters, that's going to be a lot of documents)
</li>
<li>
States which match 'states__type__slug__in=draft' describe the basic
Active/Expired/Dead whatever state of the draft.
</li>
</ul>
<p>
You could use this in at least two alternative ways:
</p>
<p>
You could either fetch and remember the different state groups of interest to you
with queries like
</p>
<pre>
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-rfceditor'
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-iesg'
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-stream-ietf'
</pre>
<p>
and then match the listed "resource_uri" of the results to the states listed for each
document when you ask for
</p>
<pre>
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-'
</pre>
<p>
Or alternatively you could do a series of queries asking for matches to the RFC Editor
state first, then the IESG state, then the Stream state, and exclude earlier hits:
</p>
<pre>
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor' ...
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-iesg' ...
</pre>
<p>
etc.
</p>
</div>
</li>
<li>
If a document has a WG state, you can select for it by asking for
documents which match 'states__type__slug__in=draft-stream-ietf'
(but without additional filters, that's going to be a lot of documents)
</li>
<li>
States which match 'states__type__slug__in=draft' describe the basic
Active/Expired/Dead whatever state of the draft.
</li>
</ul>
<p>
You could use this in at least two alternative ways:
</p>
<p>
You could either fetch and remember the different state groups of interest to you
with queries like
</p>
<pre class="text-wrap">
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-rfceditor'
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-iesg'
$ curl 'https://datatracker.ietf.org/api/v1/doc/state/?format=json&limit=0&type__slug__in=draft-stream-ietf'
</pre>
<p>
and then match the listed "resource_uri" of the results to the states listed for each
document when you ask for
</p>
<pre class="text-wrap">
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-'
</pre>
<p>
Or alternatively you could do a series of queries asking for matches to the RFC Editor
state first, then the IESG state, then the Stream state, and exclude earlier hits:
</p>
<pre class="text-wrap">
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-rfceditor' ...
$ curl 'https://datatracker.ietf.org/api/v1/doc/document/?limit=0&name__contains=-v6ops-&states__type__slug__in=draft-iesg' ...
</pre>
<p>
etc.
</p>
<h3 id="simplified-documents" class="anchor-target">Simplified documents API</h3>
<div>
<p>
A simplified Documents API, intended for cases where only a limited set of
document attributes are necessary for an application is
available for all documents at the relative url <code>doc.json</code>, e.g.,
<code>{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}</code>
<a href="{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}"><span class="bi bi-box-arrow-up-right"></span></a>.
You can also specify an RFC: <code>{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}</code>
<a href="{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}"><span class="bi bi-box-arrow-up-right"></span></a>.
No API key is needed to access this.
</p>
<p>
The simplified document API takes no parameters, and is invoked with a HTTP GET.
</p>
</div>
<p>
A simplified Documents API, intended for cases where only a limited set of
document attributes are necessary for an application is
available for all documents at the relative url <code>doc.json</code>, e.g.,
<code>{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}</code>
<a href="{% url 'ietf.doc.views_doc.document_json' name='draft-ietf-poised95-std-proc-3' %}">
<span class="bi bi-box-arrow-up-right"></span>
</a>
.
You can also specify an RFC: <code>{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}</code>
<a href="{% url 'ietf.doc.views_doc.document_json' name='rfc2026' %}">
<span class="bi bi-box-arrow-up-right"></span>
</a>
.
No API key is needed to access this.
</p>
<p>
The simplified document API takes no parameters, and is invoked with a HTTP GET.
</p>
<h3 id="iesg-position-api" class="anchor-target">IESG ballot position API</h3>
<div>
<p>
A simplified IESG ballot position interface, intended for automation, is
available at <code>{% url 'ietf.doc.views_ballot.api_set_position' %}
</code>. Access is limited to area directors.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li><code>apikey</code> (required) which is the personal API key hash</li>
<li><code>doc</code> (required) which is the balloted document name</li>
<li><code>position</code> (required) which is the position slug, one of: <span class="samp">yes, noobj, block, discuss, abstain, recuse, norecord</span>. </li>
<li><code>discuss</code> (required if position is 'discuss') which is the discuss text</li>
<li><code>comment</code> (optional) which is comment text</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre>
$ curl -S -F "apikey=AwAAABVR3D5GHkVMhspKSxBCVknGMmqikNIhT85kSnghjaV_pYy26WV92mm-jpdi" -F "doc=draft-ietf-lamps-eai-addresses" -F "position=noobj" -F "comment=Comment text" https://datatracker.ietf.org/api/iesg/position
Done
</pre>
</div>
<h3 id="session-video-url-api" class="anchor-target">Set session video URL</h3>
<div>
<p>
This interface is intended for Meetecho, to provide a way to set the
URL of a video recording for a given session. It is available at
<code>{% url 'ietf.meeting.views.api_set_session_video_url' %}</code>.
Access is limited to recording managers.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li><code>apikey</code> (required) which is the personal API key hash</li>
<li><code>meeting</code> (required) which is the meeting number</li>
<li><code>group</code> (required) which is the group acronym</li>
<li><code>item</code> (required) which is the chronological sequence number of the session (1 for a group's first session, 2 for the second, etc.)</li>
<li><code>url</code> (required) which is the url that points to the video recording</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre>
$ curl -S -F "apikey=DgAAAMLSi3coaE5TjrRs518xO8eBRlCmFF3eQcC8_SjUTtRGLGiJh7-1SYPT5WiS" -F "meeting=101" -F "group=mptcp" -F "item=1" -F "url=https://foo.example/beer/mptcp" https://datatracker.ietf.org/api/meeting/session/video/url
Done
</pre>
</div>
<h3 id="openid-connect" class="anchor-target">OpenID Connect</h3>
<div>
<p>
The datatracker supports <a href="https://openid.net/connect/">OpenID Connect</a>, but
not dynamic registration. The OpenID Connect Issuer is
<code> {{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.urls.oidc_issuer' %} </code>
</p>
</div>
<h3 id="datatracker-version" class="anchor-target">Datatracker Version</h3>
<div>
<p>
The datatracker version and release/patch date is available as a JSON blob at
<code><a href="{% url 'ietf.api.views.version' %}">{% url 'ietf.api.views.version' %}</a></code>.
</p>
</div>
<h3 id="personal-api-keys" class="anchor-target">Personal API Keys</h3>
<div>
<p>
The datatracker has some API endpoints that uses Personal API keys,
rather than having general access or requiring username/password
login, see for example details for
<code>{% url 'ietf.doc.views_ballot.api_set_position' %}</code>
<a href="#iesg-position-api">above</a>.
Personal API keys are available from your
<a href="{% url 'ietf.ietfauth.views.apikey_index'%}">Account API Keys</a>
page when you are logged in.
</p>
<p>
Personal API keys have some characteristics you should be aware of:
</p>
<ul>
<li>
Each API key is valid only for a specific endpoint. If you try to use a key for
a different API endpoint than it's created for, it will not work.
</li>
<li>
The API keys will cause you to be given access with the datatracker
roles you have, thus giving you appropriate access to the various
API endpoints according to the role limitations indicated for each
endpoint.
</li>
<li>
An API key will only give you access to its related endpoint if you have logged
in to the datatracker using your regular login and password during the last
{{ settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS }} days. If you receive the
error message "<code>Too long since last regular login</code>" you should do
a regular login in order to activate access.
</li>
</ul>
</div>
<h3 id="signing-keys" class="anchor-target">Signing Keys</h3>
<div>
<p>
When sending notifications to other APIs, the datatracker may sign
information with a <a href="https://datatracker.ietf.org/doc/html/rfc7515">RFC
7515: JSON Web Signature (JWS)</a>, using a public/private keypair with
this public key:
</p>
<p><code>{{key.export_public}}</code></p>
<p>or alternatively:</p>
<pre>{{key.export_to_pem}}</pre>
<p>
To verify a signature and get the verified data using Python with the
<a href="https://jwcrypto.readthedocs.io/en/latest/">jwcrypto</a> module,
you could do:
</p>
<pre>
<p>
A simplified IESG ballot position interface, intended for automation, is
available at <code>{% url 'ietf.doc.views_ballot.api_set_position' %}
</code>. Access is limited to area directors.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li>
<code>apikey</code> (required) which is the personal API key hash
</li>
<li>
<code>doc</code> (required) which is the balloted document name
</li>
<li>
<code>position</code> (required) which is the position slug, one of:
<span class="samp">yes, noobj, block, discuss, abstain, recuse, norecord</span>
.
</li>
<li>
<code>discuss</code> (required if position is 'discuss') which is the discuss text
</li>
<li>
<code>comment</code> (optional) which is comment text
</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre class="text-wrap">
$ curl -S -F "apikey=AwAAABVR3D5GHkVMhspKSxBCVknGMmqikNIhT85kSnghjaV_pYy26WV92mm-jpdi" -F "doc=draft-ietf-lamps-eai-addresses" -F "position=noobj" -F "comment=Comment text" https://datatracker.ietf.org/api/iesg/position
Done
</pre>
<h3 id="session-video-url-api" class="anchor-target">Set session video URL</h3>
<p>
This interface is intended for Meetecho, to provide a way to set the
URL of a video recording for a given session. It is available at
<code>{% url 'ietf.meeting.views.api_set_session_video_url' %}</code>.
Access is limited to recording managers.
</p>
<p>
The interface requires the use of a personal API key, which can be created at
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">{% url 'ietf.ietfauth.views.apikey_index' %}</a>
</p>
<p>
The ballot position API takes the following parameters:
</p>
<ul>
<li>
<code>apikey</code> (required) which is the personal API key hash
</li>
<li>
<code>meeting</code> (required) which is the meeting number
</li>
<li>
<code>group</code> (required) which is the group acronym
</li>
<li>
<code>item</code> (required) which is the chronological sequence number of the session (1 for a group's first session, 2 for the second, etc.)
</li>
<li>
<code>url</code> (required) which is the url that points to the video recording
</li>
</ul>
<p>
It returns an appropriate http result code, and a brief explanatory text message.
</p>
<p>
Here is an example:
</p>
<pre class="text-wrap">
$ curl -S -F "apikey=DgAAAMLSi3coaE5TjrRs518xO8eBRlCmFF3eQcC8_SjUTtRGLGiJh7-1SYPT5WiS" -F "meeting=101" -F "group=mptcp" -F "item=1" -F "url=https://foo.example/beer/mptcp" https://datatracker.ietf.org/api/meeting/session/video/url
Done
</pre>
<h3 id="openid-connect" class="anchor-target">OpenID Connect</h3>
<p>
The datatracker supports
<a href="https://openid.net/connect/">
OpenID Connect
</a>
, but
not dynamic registration. The OpenID Connect Issuer is
<code> {{ settings.IDTRACKER_BASE_URL }}{% url 'ietf.api.urls.oidc_issuer' %} </code>
</p>
<h3 id="datatracker-version" class="anchor-target">
Datatracker Version
</h3>
<p>
The datatracker version and release/patch date is available as a JSON blob at
<code>
<a href="{% url 'ietf.api.views.version' %}">
{% url 'ietf.api.views.version' %}
</a>
</code>.
</p>
<h3 id="personal-api-keys" class="anchor-target">
Personal API Keys
</h3>
<p>
The datatracker has some API endpoints that uses Personal API keys,
rather than having general access or requiring username/password
login, see for example details for
<code>{% url 'ietf.doc.views_ballot.api_set_position' %}</code>
<a href="#iesg-position-api">
above
</a>
.
Personal API keys are available from your
<a href="{% url 'ietf.ietfauth.views.apikey_index' %}">
Account API Keys
</a>
page when you are logged in.
</p>
<p>
Personal API keys have some characteristics you should be aware of:
</p>
<ul>
<li>
Each API key is valid only for a specific endpoint. If you try to use a key for
a different API endpoint than it's created for, it will not work.
</li>
<li>
The API keys will cause you to be given access with the datatracker
roles you have, thus giving you appropriate access to the various
API endpoints according to the role limitations indicated for each
endpoint.
</li>
<li>
An API key will only give you access to its related endpoint if you have logged
in to the datatracker using your regular login and password during the last
{{ settings.UTILS_APIKEY_GUI_LOGIN_LIMIT_DAYS }} days. If you receive the
error message "<code>Too long since last regular login</code>" you should do
a regular login in order to activate access.
</li>
</ul>
<h3 id="signing-keys" class="anchor-target">
Signing Keys
</h3>
<p>
When sending notifications to other APIs, the datatracker may sign
information with a
<a href="https://datatracker.ietf.org/doc/html/rfc7515">
RFC
7515: JSON Web Signature (JWS)
</a>
, using a public/private keypair with
this public key:
</p>
<p>
<code>{{ key.export_public }}</code>
</p>
<p>
or alternatively:
</p>
<pre class="text-wrap">{{ key.export_to_pem }}</pre>
<p>
To verify a signature and get the verified data using Python with the
<a href="https://jwcrypto.readthedocs.io/en/latest/">
jwcrypto
</a>
module,
you could do:
</p>
<pre class="text-wrap">
from jwcrypto import jwk, jws
# ... receive json web signed data as 'data', used below ...
@ -357,27 +346,6 @@ jwstoken = jws.JWS()
jwstoken.deserialize(data)
jwstoken.verify(key)
payload = jwstoken.payload
</pre>
</div>
</div>
<div class="col-md-1 d-print-none" id="affix">
<ul class="nav nav-pills nav-stacked small fixed" data-bs-spy="affix">
<li><a href="#framework">Framework API</a></li>
<li><a href="#framework-documents">&nbsp; Framework API: Documents</a></li>
<li><a href="#simplified-documents">Simplified documents API</a></li>
<li><a href="#iesg-position-api">IESG ballot position API</a></li>
<li><a href="#session-video-url-api">Set session video URL API</a></li>
<li><a href="#openid-connect">OpenID Connect</a></li>
<li><a href="#datatracker-version">Datatracker Version</a></li>
<li><a href="#personal-api-keys">Personal API keys</a></li>
<li><a href="#signing-keys">Signing keys</a></li>
</ul>
</div>
{% endblock %}
</pre>
</div>
{% endblock %}

View file

@ -1,48 +1,61 @@
{# Copyright The IETF Trust 2015-2021, All Rights Reserved #}
<!doctype html>
{% load ietf_filters static %}
{% load origin %}{% origin %}
{% load origin %}
{% origin %}
{% load django_bootstrap5 %}
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>{% block title %}No title{% endblock title %}</title>
<title>
{% block title %}
No title
{% endblock title %}
</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
{% comment Halloween %}
<link href='https://fonts.googleapis.com/css?family=IM+Fell+English+SC|IM+Fell+DW+Pica:400,400italic|Nova+Mono|IM+Fell+English:400,400italic&subset=latin-ext,latin' rel='stylesheet' type='text/css'/>
{% endcomment %}
<link rel="stylesheet" href="{% static 'ietf/css/ietf.css' %}"/>
<style>
{% block morecss %}{% endblock morecss %}
.leftmenu { width: 13em; }
</style>
{% block pagehead %}{% endblock pagehead %}
{% block pagehead %}
{% endblock pagehead %}
{% if server_mode and server_mode == "production" %}
<link rel="shortcut icon" href="{% static 'ietf/images/ietf-icon-blue3.png' %}"/>
<link rel="shortcut icon"
href="{% static 'ietf/images/ietf-icon-blue3.png' %}"/>
{% else %}
<link rel="shortcut icon" href="{% static 'ietf/images/ietf-icon-red3.png' %}"/>
<link rel="shortcut icon"
href="{% static 'ietf/images/ietf-icon-red3.png' %}"/>
{% endif %}
<link rel="apple-touch-icon" href="{% static 'ietf/images/apple-touch-icon.png' %}"/>
<script src="{% static 'ietf/js/ietf.js' %}"></script>
<link rel="apple-touch-icon"
href="{% static 'ietf/images/apple-touch-icon.png' %}"/>
<script src="{% static 'ietf/js/ietf.js' %}"/></script>
</head>
<body class="position-relative" data-bs-spy="scroll" data-bs-target="#righthand-nav" {% block bodyAttrs %}
{% endblock bodyAttrs %}
data-group-menu-data-url="{% url 'ietf.group.views.group_menu_data' %}">
<nav class="navbar navbar-expand-lg
{% if server_mode and server_mode != "production" %}
navbar-light bg-warning
{% else %}
navbar-dark bg-secondary
{% endif %}
<body {% block bodyAttrs %}{% endblock bodyAttrs %} data-group-menu-data-url="{% url 'ietf.group.views.group_menu_data' %}">
<nav class="navbar navbar-expand-lg {% if server_mode and server_mode != " production" %}navbar-light bg-warning{% else %}navbar-dark bg-secondary{% endif %} {% if navbar_mode %}{{ navbar_mode }}{% else %}fixed-top{% endif %}">
{% if navbar_mode %}
{{ navbar_mode }}
{% else %}
fixed-top
{% endif %}">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img alt="IETF Logo" src="{% static 'ietf/images/ietflogo-small-transparent.png' %}"/>
<img alt="IETF Logo"
src="{% static 'ietf/images/ietflogo-small-transparent.png' %}"/>
Datatracker
{% if server_mode and server_mode != "production" %}
Dev Mode
{% endif %}
{% if server_mode and server_mode != "production" %}Dev Mode{% endif %}
</a>
<div class="collapse navbar-collapse" id="navbar-collapse">
<ul class="nav navbar-nav">
@ -50,20 +63,38 @@
</ul>
</div>
{% if not user.is_authenticated %}
<a class="d-none d-sm-block mx-5 btn {% if server_mode and server_mode == " production" %}btn-warning{% else %}btn-info{% endif %}" rel="nofollow" href="/accounts/login/?next={{ request.get_full_path|urlencode }}">Sign
in</a>
<a class="d-none d-sm-block mx-5 btn
{% if server_mode and server_mode == "production" %}
btn-warning
{% else %}
btn-info
{% endif %}"
rel="nofollow"
href="/accounts/login/?next={{ request.get_full_path|urlencode }}">
Sign
in
</a>
{% endif %}
<form class="d-flex d-none d-lg-block" action="/doc/search/">
<input class="form-control" type="text" name="name" placeholder="Document search" required/>
<input class="form-control"
type="text"
name="name"
placeholder="Document search"
required/>
<input type="hidden" name="activedrafts" value="on"/>
<input type="hidden" name="rfcs" value="on"/>
</form>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation">
<button class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbar-collapse"
aria-controls="navbar-collapse"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</nav>
<div class="pt-3 container-fluid">
<div class="row">
{% if request.COOKIES.left_menu == "on" and not hide_menu %}
@ -74,18 +105,36 @@
</div>
{% endif %}
<div class="col mx-3" id="content">
{% comment %} {% bootstrap_messages %} {% endcomment %}
{% for message in messages %}
<div class="alert{% if message.level_tag %} alert-{% if message.level_tag == 'error' %}danger{% else %}{{ message.level_tag }}{% endif %}{% endif %}{% if message.extra_tags %} {{ message.extra_tags }}{% endif %} alert-dismissable fade show">
<button type="button" class="btn-close float-end" data-bs-dismiss="alert" aria-label="Close"></button>
<div class="alert
{% if message.level_tag %}
alert-
{% if message.level_tag == 'error' %}
danger
{% else %}
{{ message.level_tag }}
{% endif %}
{% endif %}
{% if message.extra_tags %}
{{ message.extra_tags }}
{% endif %} alert-dismissable fade show">
<button type="button"
class="btn-close float-end"
data-bs-dismiss="alert"
aria-label="Close"></button>
{{ message }}
</div>
{% endfor %}
{% block content %}{{ content|safe }}{% endblock content %}
{% block content_end %}{% endblock content_end %}
{% block content %}
{{ content|safe }}
{% endblock content %}
{% block content_end %}
{% endblock content_end %}
</div>
</div>
<hr/>
<hr />
{% block footer %}
<footer class="col-md-12 col-sm-12 text-center">
<a href="https://www.ietf.org/" class="p-3">IETF</a>
@ -97,7 +146,6 @@
<a href="https://www.rfc-editor.org/" class="p-3">RFC&nbsp;Editor</a>
<a href="https://www.iana.org/" class="p-3">IANA</a>
<a href="https://www.ietf.org/privacy-statement/" class="p-3">Privacy&nbsp;Statement</a>
<p class="small text-muted p-3">
{% if version_num %}
<a href="/release/about">About</a>
@ -105,26 +153,29 @@
<a href="/release/{{ version_num }}/">Version {{ version_num }}</a>
{{ revision_date }}
{% endif %}
Report a bug:
<a href="https://trac.ietf.org/trac/ietfdb/newticket">Tracker <span class="bi bi-bug"></span></a>
<a href="https://trac.ietf.org/trac/ietfdb/newticket">
Tracker
<span class="bi bi-bug"></span>
</a>
{% if bugreport_email %}
<a href="mailto:{{ bugreport_email }}">Email <span class="bi bi-envelope"></span></a>
<a href="mailto:{{ bugreport_email }}">
Email
<span class="bi bi-envelope"></span>
</a>
{% endif %}
<br/>
<br />
{% if python_version %}Python {{ python_version }}{% endif %}
{% if django_version %}Django {{ django_version }}{% endif %}
</p>
</footer>
{% endblock footer %}
</div>
{% include "debug.html" %}
{% block js %}{% endblock js %}
{% block js %}
{% endblock js %}
{% if debug %}
<script src="{% static 'ietf/js/list.js' %}"></script>
{% endif %}
</body>
</html>

View file

@ -1,138 +1,136 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load ietf_filters %}
{% block pagehead %}
<link rel="alternate" type="application/atom+xml" href="/feed/iesg-agenda/">
{% endblock %}
{% block morecss %}
.dl-horizontal dd:before, .dl-horizontal dd:after, .card-body:after {
content: none;
}
{% endblock %}
{% block title %}IESG agenda: {{ date }}{% endblock %}
{% block bodyAttrs %}data-bs-spy="scroll" data-bs-target="#affix"{% endblock %}
<link rel="alternate" type="application/atom+xml" href="/feed/iesg-agenda/"/>
{% endblock pagehead %}
{% block title %}
IESG agenda: {{ date }}
{% endblock title %}
{% block content %}
{% origin %}
<div class="row">
<div class="col-md-10">
<h1>IESG agenda: {{ date }} </h1>
<ul class="nav nav-tabs">
<li class="nav-item ><a class="nav-link active" href="{% url 'ietf.iesg.views.agenda' %}">IESG Agenda</a></li>
<li class="nav-item "><a class="nav-link" href="{% url 'ietf.iesg.views.agenda_documents' %}">Documents on future agendas</a></li>
<li class="nav-item "><a class="nav-link" href="{% url 'ietf.iesg.views.discusses' %}">DISCUSS positions</a></li>
<li class="nav-item "><a class="nav-link" href="{% url 'ietf.iesg.views.past_documents' %}">Documents on recent agendas</a></li>
<li class="nav-item "><a class="nav-link" href="{% url 'ietf.iesg.views.photos' %}">IESG Photos</a></li>
</ul>
{% for num, section in sections %}
{% if num|sectionlevel == 1 %}<h2 class="anchor-target" id="{{num}}">{{ num }}. {{ section.title|safe }}</h2>{% endif %}
{% if num|sectionlevel == 2 %}<h3 class="anchor-target" id="{{num}}">{{ num }} {{ section.title|safe }}</h3>{% endif %}
{% if num|sectionlevel == 3 %}<h4 class="anchor-target" id="{{num}}">{{ num }} {{ section.title|safe }}</h4>{% endif %}
{% if num == "1.4" %}
<pre>
{{ section.text }}
</pre>
{% endif %}
{% if num >= "2" and num < "5" %}
{% if num == "2" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Is this document a
reasonable basis on which to build the salient part of the Internet
infrastructure? If not, what changes would make it so?"
</p>
<h1>IESG agenda: {{ date }}</h1>
<ul class="nav nav-tabs mb-3">
<li class="nav-item">
<a class="nav-link active" href="{% url 'ietf.iesg.views.agenda' %}">IESG Agenda</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.iesg.views.agenda_documents' %}">Documents on future agendas</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.iesg.views.discusses' %}">DISCUSS positions</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.iesg.views.past_documents' %}">Documents on recent agendas</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'ietf.iesg.views.photos' %}">IESG Photos</a>
</li>
</ul>
{% for num, section in sections %}
{% if num|sectionlevel == 1 %}
<h2 class="anchor-target" id="sec-{{ num|slugify }}">{{ num }}. {{ section.title|safe }}</h2>
{% elif num|sectionlevel == 2 %}
<h3 class="anchor-target" id="sec-{{ num|slugify }}">{{ num }} {{ section.title|safe }}</h3>
{% elif num|sectionlevel == 3 %}
<h4 class="anchor-target" id="sec-{{ num|slugify }}">{{ num }} {{ section.title|safe }}</h4>
{% endif %}
{% if num == "1.4" %}<pre>{{ section.text }}</pre>{% endif %}
{% if num >= "2" and num < "5" %}
{% if num == "2" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Is this document a
reasonable basis on which to build the salient part of the Internet
infrastructure? If not, what changes would make it so?"
</p>
{% endif %}
{% if num == "3.1" or num == "3.2" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Is this document a
reasonable contribution to the area of Internet engineering
which it covers? If not, what changes would make it so?"
</p>
{% endif %}
{% if num == "3.3" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Are the proposed
changes to document status appropriate? Have all requirements
for such a change been met? If not, what changes to the proposal
would make it appropriate?"
</p>
{% endif %}
{% if num == "3.4" %}
<p class="alert alert-info">
The IESG will use RFC 5742 responses:
</p>
<ol>
<li>
The IESG has concluded
that there is no conflict between this document and IETF work;
</li>
<li>
The IESG has concluded that this work is related to IETF work done
in WG &lt;X&gt;, but this relationship does not prevent
publishing;
</li>
<li>
The IESG has concluded that publication could
potentially disrupt the IETF work done in WG &lt;X&gt; and
recommends not publishing the document at this time;
</li>
<li>
The IESG
has concluded that this document violates IETF procedures for
&lt;Y&gt; and should therefore not be published without IETF
review and IESG approval; or
</li>
<li>
The IESG has concluded that this
document extends an IETF protocol in a way that requires IETF
review and should therefore not be published without IETF review
and IESG approval.
</li>
</ol>
<p>
The document shepherd must propose one of these responses in the
conflict-review document, and the document shepherd may supply text
for an IESG Note in that document. The Area Director ballot positions
indicate consensus with the response proposed by the document shepherd
and agreement that the IESG should request inclusion of the IESG Note.
</p>
<p>
Other matters may be recorded in comments, and the comments will
be passed on to the RFC Editor as community review of the document.
</p>
{% endif %}
{% if "docs" in section %}
{% for doc in section.docs %}
{% if doc.type_id == "draft" or doc.type_id == "statchg" %}
{% include "iesg/agenda_doc.html" %}
{% endif %}
{% if num == "3.1" or num == "3.2" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Is this document a
reasonable contribution to the area of Internet engineering
which it covers? If not, what changes would make it so?"
</p>
{% if doc.type_id == "conflrev" %}
{% include "iesg/agenda_conflict_doc.html" %}
{% endif %}
{% if num == "3.3" %}
<p class="alert alert-info">
Reviews should focus on these questions: "Are the proposed
changes to document status appropriate? Have all requirements
for such a change been met? If not, what changes to the proposal
would make it appropriate?"
</p>
{% endif %}
{% if num == "3.4" %}
<p class="alert alert-info">
The IESG will use RFC 5742 responses:
</p>
<ol>
<li>The IESG has concluded
that there is no conflict between this document and IETF work;</li>
<li>The IESG has concluded that this work is related to IETF work done
in WG &lt;X&gt;, but this relationship does not prevent
publishing;</li>
<li>The IESG has concluded that publication could
potentially disrupt the IETF work done in WG &lt;X&gt; and
recommends not publishing the document at this time;</li>
<li>The IESG
has concluded that this document violates IETF procedures for
&lt;Y&gt; and should therefore not be published without IETF
review and IESG approval; or</li>
<li>The IESG has concluded that this
document extends an IETF protocol in a way that requires IETF
review and should therefore not be published without IETF review
and IESG approval.</li>
</ol>
<p>
The document shepherd must propose one of these responses in the
conflict-review document, and the document shepherd may supply text
for an IESG Note in that document. The Area Director ballot positions
indicate consensus with the response proposed by the document shepherd
and agreement that the IESG should request inclusion of the IESG Note.</p>
<p>
Other matters may be recorded in comments, and the comments will
be passed on to the RFC Editor as community review of the document.
</p>
{% endif %}
{% if "docs" in section %}
{% for doc in section.docs %}
{% if doc.type_id == "draft" or doc.type_id == "statchg" %}{% include "iesg/agenda_doc.html" %}{% endif %}
{% if doc.type_id == "conflrev" %}{% include "iesg/agenda_conflict_doc.html" %}{% endif %}
{% if doc.type_id == "charter" %}{% include "iesg/agenda_charter.html" %}{% endif %}
{% if not forloop.last %}<hr>{% endif %}
{% empty %}
<p class="text-muted">(None)</p>
{% endfor %}
{% endif %}
{% endif %}
{% if num|startswith:"6." and user|has_role:"Area Director,IAB Chair,Secretariat" %}
<pre>{{ section.text|wordwrap:"80" }}</pre>
{% endif %}
{% endfor %}
</div>
<div class="col-md-2 d-print-none" id="affix">
<ul class="nav nav-pills nav-stacked small" data-bs-spy="affix">
{% for num, section in sections %}
{% if num|sectionlevel <= 1 %}
<li><a href="#{{num}}">{{ section.title|safe }}</a></li>
{% if doc.type_id == "charter" %}
{% include "iesg/agenda_charter.html" %}
{% endif %}
{% empty %}
<p class="text-muted">
(None)
</p>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
{% endif %}
{% if num|startswith:"6." and user|has_role:"Area Director,IAB Chair,Secretariat" %}
<pre class="border p-3">{{ section.text|wordwrap:"80" }}</pre>
{% endif %}
{% endfor %}
{% endblock content %}
{% block js %}
<script>
// automatically generate a right-hand navigation tab for long pages
</script>
{% endblock %}

View file

@ -1,19 +1,34 @@
{% load ietf_filters ballot_icon %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}{% origin %}
<div class="float-end">{% ballot_icon doc %}</div>
<dl class="dl-horizontal">
<dt>{{ doc.group.type }} name</dt>
<dd><b>{{ doc.group.name }} ({{doc.group.acronym}})</b></dd>
<dt>Charter</dt>
<dd>
<a href="{{ doc.get_href }}"><span class="bi bi-file"></span></a>
<a href="{{ doc.get_absolute_url }}">{{ doc.name}}-({{doc.rev}})</a>
</dd>
<dt>Area</dt>
<dd>{{ doc.group.parent.acronym|upper }} ({{ doc.ad|default:"(None)" }})</dd>
</dl>
{% load origin %}
{% origin %}
{% load ietf_filters ballot_icon person_filters %}
<div class="card mb-3">
<div class="card-body">
<div class="float-end">{% ballot_icon doc %}</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">{{ doc.group.type }} name</div>
<div class="col">
<b>{{ doc.group.name }} <a href="{{ doc.group.about_url }}">({{ doc.group.acronym|upper }})</a></b>
</div>
</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">Charter</div>
<div class="col">
<a href="{{ doc.get_href }}">
<i class="bi bi-file-earmark-fill"></i>
</a>
<a href="{{ doc.get_absolute_url }}">{{ doc.name }}-({{ doc.rev }})</a>
</div>
</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">Area</div>
<div class="col">
<a href="{% url 'ietf.group.views.active_groups' group_type='wg' %}#{{ doc.group.parent.acronym }}">
{{ doc.group.parent.acronym|upper }}
</a>
({% person_link doc.ad %})
</div>
</div>
</div>
</div>

View file

@ -1,52 +1,63 @@
{# Copyright The IETF Trust 2015, All Rights Reserved #}{% load origin %}{% origin %}
{% load ietf_filters ballot_icon %}
<div class="float-end">{% ballot_icon doc %}</div>
<dl class="dl-horizontal">
{% with doc.conflictdoc as conflictdoc %}
<dt>Conflict review</dt>
<dd>
<a href="{{doc.get_href}}">
<span class="bi bi-file"></span>
</a>
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}">{{ doc.canonical_name }}</a>
<br>
<i>{{ doc.title }}</i>
</dd>
<dt>{{ conflictdoc.stream }} {{ conflictdoc.intended_std_level }}</dt>
<dd>
<a href="{{settings.IETF_ID_ARCHIVE_URL}}{{ conflictdoc.name }}-{{ conflictdoc.rev }}.txt">
<span class="bi bi-file"></span>
</a>
<a href="{% url "ietf.doc.views_doc.document_main" name=conflictdoc.name %}">{{ conflictdoc.name }}</a>
<br>
<i>{{ conflictdoc.title }}</i>
</dd>
{% if conflictdoc.note %}
<dt>Note</dt><dd>{{ conflictdoc.note|linebreaksbr }}</dd>
{% endif %}
<dt>Token</dt><dd>{{ doc.ad }}</dd>
{% with doc.active_defer_event as defer %}
{% if defer %}
<dt>Deferred by</dt><dd>{{ defer.by }} on {{ defer.time|date:"Y-m-d" }}</dd>
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% origin %}
{% load ietf_filters ballot_icon person_filters %}
<div class="card mb-3">
<div class="card-body">
<div class="float-end">{% ballot_icon doc %}</div>
{% with doc.conflictdoc as conflictdoc %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Conflict review</div>
<div class="col">
<div class="fw-bold">{{ doc.title }}</div>
<a href="{{ doc.get_href }}">
<i class="bi bi-file-earmark-fill"></i>
</a>
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}">{{ doc.canonical_name }}</a>
</div>
</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">{{ conflictdoc.stream }} {{ conflictdoc.intended_std_level }}</div>
<div class="col">
<div class="fw-bold">{{ conflictdoc.title }}</div>
<a href="{{ settings.IETF_ID_ARCHIVE_URL }}{{ conflictdoc.name }}-{{ conflictdoc.rev }}.txt">
<i class="bi bi-file-earmark-fill"></i>
</a>
<a href="{% url "ietf.doc.views_doc.document_main" name=conflictdoc.name %}">{{ conflictdoc.name }}</a>
</div>
</div>
{% if conflictdoc.note %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Note</div>
<div class="col">{{ conflictdoc.note|linebreaksbr }}</div>
</div>
{% endif %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Token</div>
<div class="col">{% person_link doc.ad %}</div>
</div>
{% with doc.active_defer_event as defer %}
{% if defer %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Deferred by</div>
<div class="col">{{ defer.by }} on {{ defer.time|date:"Y-m-d" }}</div>
</div>
{% endif %}
{% endwith %}
{% if conflictdoc.ipr %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">IPR</div>
<div class="col">
{% for ipr in conflictdoc.ipr %}
{% if ipr.disclosure.state_id == "posted" %}
<div>
<a href="/ipr/{{ ipr.disclosure.id }}/">{{ ipr.disclosure.title }}</a>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
{% endwith %}
{% if conflictdoc.ipr %}
<dt>IPR</dt>
<dd>
{% for ipr in conflictdoc.ipr %}
{% if ipr.disclosure.state_id == "posted" %}
<a href="/ipr/{{ ipr.disclosure.id }}/">{{ ipr.disclosure.title }}</a><br>
{% endif %}
{% endfor %}
</dd>
{% endif %}
{% endwith %}
</dl>
</div>
</div>

View file

@ -1,73 +1,103 @@
{# Copyright The IETF Trust 2016, All Rights Reserved #}{% load origin %}{% origin %}
{% load ietf_filters ballot_icon %}
<div class="float-end">{% ballot_icon doc %}</div>
<dl class="dl-horizontal">
<dt>
{% if doc.stream %}
{{ doc.stream }} stream
{% endif %}
</dt>
<dd class="no-table">
{% with doc.rfc_number as rfc_number %}
{% if rfc_number %}
<a href="https://www.rfc-editor.org/rfc/rfc{{rfc_number}}/">
{% else %}
<a href="{{doc.get_href}}">
{% endif %}
<span class="bi bi-file"></span></a>
{% endwith %}
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}">{{ doc.canonical_name }}</a>
{% if doc.has_rfc_editor_note %}
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}writeup/"> <em>(Has RFC Editor Note)</em></a>
{% endif %}
</dd>
<dt>{{ doc.intended_std_level }}</dt><dd><b>{{ doc.title }}</b></dd>
{% if doc.note %}
<dt>Note</dt><dd>{{ doc.note|linebreaksbr }}</dd>
{% endif %}
<dt>Token</dt><dd>{{ doc.ad }} ({{ doc.area_acronym|upper }} area)</dd>
{% with doc.active_defer_event as defer %}
{% if defer %}
<dt>Deferred by</dt><dd>{{ defer.by }} on {{ defer.time|date:"Y-m-d" }}</dd>
{% endif %}
{% endwith %}
{% if doc.iana_review_state %}
<dt>IANA review</dt><dd>{{ doc.iana_review_state }}<dd>
{% endif %}
{% if doc.consensus %}
<dt>Consensus</dt><dd>{{ doc.consensus }}</dd>
{% endif %}
{% if doc.review_assignments %}
<dt>Reviews</dt>
<dd>
{% for review_assignment in doc.review_assignments %}
{% include "doc/review_assignment_summary.html" with current_doc_name=doc.name current_rev=doc.rev %}
{% endfor %}
</dd>
{% endif %}
{% if doc.lastcall_expires %}
<dt>Last call expires</dt><dd>{{ doc.lastcall_expires|date:"Y-m-d" }}</dd>
{% endif %}
{% if doc.ipr %}
<dt>IPR</dt>
<dd>
{% for ipr in doc.ipr %}
{% if ipr.disclosure.state_id == "posted" %}
<a href="/ipr/{{ ipr.disclosure.id }}/">{{ ipr.disclosure.title }}</a><br>
{# Copyright The IETF Trust 2016, All Rights Reserved #}
{% load origin %}
{% origin %}
{% load ietf_filters ballot_icon person_filters %}
<div class="card mb-3">
<div class="card-body">
<div class="float-end">{% ballot_icon doc %}</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">{{ doc.intended_std_level }}</div>
<div class="col">
<b>{{ doc.title }}</b>
</div>
</div>
<div class="row">
<div class="col-sm-3 text-end fw-bold">
{% if doc.stream %}{{ doc.stream }} stream{% endif %}
</div>
<div class="col">
{% with doc.rfc_number as rfc_number %}
<a href="{% if rfc_number %}
https://www.rfc-editor.org/rfc/rfc{{ rfc_number }}/
{% else %}
{{ doc.get_href }}
{% endif %}">
<i class="bi bi-file-earmark-fill"></i>
</a>
{% endwith %}
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}">
{{ doc.canonical_name }}</a>
{% if doc.has_rfc_editor_note %}
<a href="{% url "ietf.doc.views_doc.document_main" name=doc.canonical_name %}writeup/">
<em>(Has RFC Editor Note)</em>
</a>
{% endif %}
{% endfor %}
</dd>
{% endif %}
</dl>
</div>
</div>
{% if doc.note %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Note</div>
<div class="col">{{ doc.note|linebreaksbr }}</div>
</div>
{% endif %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Token</div>
<div class="col">
{% person_link doc.ad %}
<a href="{% url 'ietf.group.views.active_groups' group_type='wg' %}#{{ doc.group.parent.acronym }}">
({{ doc.group.parent.acronym|upper }})
</a>
</div>
</div>
{% with doc.active_defer_event as defer %}
{% if defer %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Deferred by</div>
<div class="col">{{ defer.by }} on {{ defer.time|date:"Y-m-d" }}</div>
</div>
{% endif %}
{% endwith %}
{% if doc.iana_review_state %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">IANA review</div>
<div class="col">{{ doc.iana_review_state }}</div>
</div>
{% endif %}
{% if doc.consensus %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Consensus</div>
<div class="col {% if doc.consensus != "Yes" %}text-danger{% endif %}">{{ doc.consensus }}</div>
</div>
{% endif %}
{% if doc.review_assignments %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Reviews</div>
<div class="col">
{% for review_assignment in doc.review_assignments %}
{% include "doc/review_assignment_summary.html" with current_doc_name=doc.name current_rev=doc.rev %}
{% endfor %}
</div>
</div>
{% endif %}
{% if doc.lastcall_expires %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">Last call expires</div>
<div class="col">{{ doc.lastcall_expires|date:"Y-m-d" }}</div>
</div>
{% endif %}
{% if doc.ipr %}
<div class="row">
<div class="col-sm-3 text-end fw-bold">IPR</div>
<div class="col">
{% for ipr in doc.ipr %}
{% if ipr.disclosure.state_id == "posted" %}
<div>
<a href="/ipr/{{ ipr.disclosure.id }}/">{{ ipr.disclosure.title }}</a>
</div>
{% endif %}
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>

View file

@ -88,4 +88,4 @@ Some parts Copyright (c) 2009 The IETF Trust, all rights reserved.
{% endfilter %}
</body>
</html>
</html>

View file

@ -1,10 +1,8 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin %}
{% load ietf_filters static %}
{% block morecss %}
{% block morecssXX %}
.proceedings-title {
display: flex;
flex-direction: column;
@ -38,219 +36,209 @@
{% for host in meeting.meetinghosts.all %}
{% widthratio host.logo.width host.logo.height 1 as logo_aspect %}
.host-logo img.host{{ forloop.counter }} {
{% if logo_aspect > displayed_aspect %}width: 100%; height: auto;{% else %}width: auto; height: 100%;{% endif %}
{% if logo_aspect > displayed_aspect %}
width: 100%; height: auto;
{% else %}
width: auto; height: 100%;
{% endif %}
}
{% endfor %}
{% endblock %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block bodyAttrs %}data-bs-spy="scroll" data-bs-target="#affix"{% endblock %}
{% block title %}IETF {{ meeting.number }} {% if not meeting.proceedings_final %}Draft{% endif %} Proceedings {% endblock %}
{% block title %}
IETF {{ meeting.number }}
{% if not meeting.proceedings_final %}Draft{% endif %}
Proceedings
{% endblock %}
{% block content %}
{% origin %}
<div class="row">
<div class="col-md-10">
{% if user|has_role:"Secretariat" and not meeting.proceedings_final %}
<a class="btn btn-primary finalize-button"
href="{% url 'ietf.meeting.views.finalize_proceedings' num=meeting.number %}">
Finalize Proceedings
</a>
{% if user|has_role:"Secretariat" and not meeting.proceedings_final %}
<a class="btn btn-primary finalize-button"
href="{% url 'ietf.meeting.views.finalize_proceedings' num=meeting.number %}">
Finalize Proceedings
</a>
{% endif %}
{# cache for 15 minutes, as long as there's no proceedings activity. takes 4-8 seconds to generate. #}
{% load cache %}
{% cache 900 ietf_meeting_proceedings meeting.number cache_version %}
{% include 'meeting/proceedings/title.html' with meeting=meeting attendance=attendance only %}
{% include 'meeting/proceedings/introduction.html' with meeting=meeting only %}
{% with "True" as show_agenda %}
<!-- Plenaries -->
{% if plenaries %}
<h2 class="anchor-target" id="plenaries">Plenaries</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-1" data-sort="group">Group</th>
<th class="col-1" data-sort="artifacts">Artifacts</th>
<th class="col-2" data-sort="recordings">Recordings</th>
<th class="col-4" data-sort="slides">Slides</th>
<th class="col-3" data-sort="drafts">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in plenaries %}
{% include "meeting/group_proceedings.html" %}
{% endfor %}
</tbody>
</table>
{% endif %}
<!-- Working groups -->
{% for area, meeting_sessions, not_meeting_sessions in ietf_areas %}
<h2 class="anchor-target" id="{{ area.acronym }}">
{{ area.acronym|upper }} <small class="text-muted">{{ area.name }}</small>
</h2>
{% if meeting_sessions %}
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-1" data-sort="group">Group</th>
<th class="col-1" data-sort="artifacts">Artifacts</th>
<th class="col-2" data-sort="recordings">Recordings</th>
<th class="col-4" data-sort="slides">Slides</th>
<th class="col-3" data-sort="drafts">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in meeting_sessions %}
{% ifchanged session.group.acronym %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
{# cache for 15 minutes, as long as there's no proceedings activity. takes 4-8 seconds to generate. #}
{% load cache %}
{% cache 900 ietf_meeting_proceedings meeting.number cache_version %}
{% include 'meeting/proceedings/title.html' with meeting=meeting attendance=attendance only %}
{% include 'meeting/proceedings/introduction.html' with meeting=meeting only %}
{% with "True" as show_agenda %}
<!-- Plenaries -->
{% if plenaries %}
<h2 class="anchor-target" id="plenaries">Plenaries</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-md-1">Group</th>
<th class="col-md-1">Artifacts</th>
<th class="col-md-2">Recordings</th>
<th class="col-md-4">Slides</th>
<th class="col-md-3">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in plenaries %}
{% if not_meeting_sessions %}
<p>
<small class="text-muted">{{ area.name }} groups not meeting:</small>
{% for session in not_meeting_sessions %}
{% ifchanged session.group.acronym %}
<a href="{% url 'ietf.group.views.group_home' acronym=session.group.acronym %}">{{ session.group.acronym }}</a>
{% if not forloop.last %},{% endif %}
{% endifchanged %}
{% endfor %}
</p>
<table class="table table-sm table-striped">
<thead>
<tr>
<th class="col-1">data-sort="nbsp"&nbsp;</th>
<th class="col-1">data-sort="nbsp"&nbsp;</th>
<th class="col-2">data-sort="nbsp"&nbsp;</th>
<th class="col-4">data-sort="nbsp"&nbsp;</th>
<th class="col-3">data-sort="nbsp"&nbsp;</th>
</tr>
</thead>
<tbody>
{% for session in not_meeting_sessions %}
{% ifchanged session.group.acronym %}
{% if session.sessionpresentation_set.exists %}
{% include "meeting/group_proceedings.html" %}
{% endfor %}
</tbody>
</table>
{% endif %}
<!-- Working groups -->
{% for area, meeting_sessions, not_meeting_sessions in ietf_areas %}
<h2 class="anchor-target" id="{{ area.acronym }}">{{ area.acronym|upper }} <small>{{ area.name }}</small></h2>
{% if meeting_sessions %}
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-md-1">Group</th>
<th class="col-md-1">Artifacts</th>
<th class="col-md-2">Recordings</th>
<th class="col-md-4">Slides</th>
<th class="col-md-3">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in meeting_sessions %}
{% ifchanged session.group.acronym %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
{% if not_meeting_sessions %}
<p><small>{{ area.name }} groups not meeting: </small>
{% for session in not_meeting_sessions %}
{% ifchanged session.group.acronym %}
<a href="{% url 'ietf.group.views.group_home' acronym=session.group.acronym %}">{{ session.group.acronym }}</a>{% if not forloop.last %},{% endif %}
{% endifchanged %}
{% endfor %}
</p>
<table class="table table-sm table-striped">
<thead>
<tr>
<th class="col-md-1">&nbsp;</th>
<th class="col-md-1">&nbsp;</th>
<th class="col-md-2">&nbsp;</th>
<th class="col-md-4">&nbsp;</th>
<th class="col-md-3">&nbsp;</th>
</tr>
</thead>
<tbody>
{% for session in not_meeting_sessions %}
{% ifchanged session.group.acronym %}
{% if session.sessionpresentation_set.exists %}
{% include "meeting/group_proceedings.html" %}
{% endif %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
{% endif %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
{% endfor %}
<!-- Training Sessions -->
{% if training %}
{% with "False" as show_agenda %}
<h2 class="anchor-target" id="training">Training</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-1" data-sort="group">Group</th>
<th class="col-1" data-sort="artifacts">Artifacts</th>
<th class="col-2" data-sort="recordings">Recordings</th>
<th class="col-4" data-sort="slides">Slides</th>
<th class="col-3" data-sort="drafts">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in training %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endwith %}
{% endif %}
<!-- IAB Sessions -->
{% if iab %}
<h2 class="anchor-target" id="iab">
IAB <small class="text-muted">Internet Architecture Board</small>
</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-1" data-sort="group">
Group
</th>
<th class="col-1" data-sort="artifacts">
Artifacts
</th>
<th class="col-2" data-sort="recordings">
Recordings
</th>
<th class="col-4" data-sort="slides">
Slides
</th>
<th class="col-3" data-sort="drafts">
Drafts
</th>
</tr>
</thead>
<tbody>
{% for session in iab %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
<!-- Training Sessions -->
{% if training %}
{% with "False" as show_agenda %}
<h2 class="anchor-target" id="training">Training</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-md-1">Group</th>
<th class="col-md-1">Artifacts</th>
<th class="col-md-2">Recordings</th>
<th class="col-md-4">Slides</th>
<th class="col-md-3">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in training %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endwith %}
{% endif %}
<!-- IAB Sessions -->
{% if iab %}
<h2 class="anchor-target" id="iab">IAB <small>Internet Architecture Board</small></h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-md-1">Group</th>
<th class="col-md-1">Artifacts</th>
<th class="col-md-2">Recordings</th>
<th class="col-md-4">Slides</th>
<th class="col-md-3">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in iab %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
<!-- IRTF Sessions -->
{% if irtf %}
<h2 class="anchor-target" id="irtf">IRTF <small>Internet Research Task Force</small></h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-md-1">Group</th>
<th class="col-md-1">Artifacts</th>
<th class="col-md-2">Recordings</th>
<th class="col-md-4">Slides</th>
<th class="col-md-3">Drafts</th>
</tr>
</thead>
<tbody>
{% for session in irtf|dictsort:"group.acronym" %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
</tbody>
</table>
{% endif %}
{% endwith %}
{% endcache %}
</div>
<div class="col-md-2 d-print-none" id="affix">
<ul class="nav nav-pills nav-stacked small" data-bs-spy="affix">
<li><a href="#introduction">Introduction</a></li>
{% if plenaries %}
<li><a href="#plenaries">Plenaries</a></li>
{% endif %}
{% if ietf %}
{% regroup ietf|dictsort:"group.parent.acronym" by group.parent as areas %}
{% for area in areas %}
<li><a href="#{{area.grouper.acronym}}">{{ area.grouper.acronym|upper }}</a></li>
</tbody>
</table>
{% endif %}
<!-- IRTF Sessions -->
{% if irtf %}
<h2 class="anchor-target" id="irtf">
IRTF <small class="text-muted">Internet Research Task Force</small>
</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th class="col-1" data-sort="group">
Group
</th>
<th class="col-1" data-sort="artifacts">
Artifacts
</th>
<th class="col-2" data-sort="recordings">
Recordings
</th>
<th class="col-4" data-sort="slides">
Slides
</th>
<th class="col-3" data-sort="drafts">
Drafts
</th>
</tr>
</thead>
<tbody>
{% for session in irtf|dictsort:"group.acronym" %}
{% ifchanged %}
{% include "meeting/group_proceedings.html" %}
{% endifchanged %}
{% endfor %}
{% endif %}
{% if training %}
<li><a href="#training">Training</a></li>
{% endif %}
{% if iab %}
<li><a href="#iab">IAB</a></li>
{% endif %}
{% if irtf %}
<li><a href="#irtf">IRTF</a></li>
{% endif %}
</ul>
</div>
</div>
</tbody>
</table>
{% endif %}
{% endwith %}
{% endcache %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}
<script src="{% static "ietf/js/list.js" %}">
</script>
{% endblock %}

View file

@ -3,34 +3,27 @@
This renders the title block for the meeting proceedings page.
{% endcomment %}
{% load ietf_filters %}
<div class="proceedings-title">
<h1>
IETF {{ meeting.number }} {% if not meeting.proceedings_final %}Draft{% endif %}
IETF {{ meeting.number }}
{% if not meeting.proceedings_final %}Draft{% endif %}
Proceedings
</h1>
<div class="proceedings-date">
{{ meeting.date|date:"d F Y" }} - {{ meeting.end_date|date:"d F Y" }}
</div>
<div class="proceedings-date">{{ meeting.date|date:"d F Y" }} - {{ meeting.end_date|date:"d F Y" }}</div>
{% if attendance is not None %}
<div class="proceedings-info">
{% if attendance.onsite > 0 %}{{ attendance.onsite }} onsite participant{{ attendance.onsite|pluralize }}{% if attendance.online > 0 %},{% endif %}{% endif %}
{% if attendance.onsite > 0 %}
{{ attendance.onsite }} onsite participant{{ attendance.onsite|pluralize }}
{% if attendance.online > 0 %},{% endif %}
{% endif %}
{% if attendance.online > 0 %}{{ attendance.online }} online participant{{ attendance.online|pluralize }}{% endif %}
</div>
{% endif %}
</div>
<div class="proceedings-intro with-divider">
<div class="proceedings-column">
<div class="proceedings-row">
Location: {{ meeting.city|default:"TBD" }}
</div>
{% if meeting.venue_name %}
<div class="proceedings-row">
Venue: {{ meeting.venue_name }}
</div>
{% endif %}
<div class="proceedings-row">Location: {{ meeting.city|default:"TBD" }}</div>
{% if meeting.venue_name %}<div class="proceedings-row">Venue: {{ meeting.venue_name }}</div>{% endif %}
</div>
{% with hosts=meeting.meetinghosts.all %}
{% if hosts.exists %}
@ -40,13 +33,14 @@ This renders the title block for the meeting proceedings page.
{% for host in hosts %}
<div class="host-logo">
<img class="host{{ forloop.counter }}"
src="{% url 'ietf.meeting.views_proceedings.meetinghost_logo' num=meeting.number host_id=host.pk %}"
height="{{ host.logo_height }}"
width="{{ host.logo_width }}"
title="{{ host.name }}">
</div>{% endfor %}
src="{% url 'ietf.meeting.views_proceedings.meetinghost_logo' num=meeting.number host_id=host.pk %}"
height="{{ host.logo_height }}"
width="{{ host.logo_width }}"
title="{{ host.name }}">
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endwith %}
</div>
</div>

View file

@ -6,16 +6,13 @@
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
<link rel="stylesheet" href="{% static "fullcalendar/core/main.css" %}">
<link rel="stylesheet" href="{% static "fullcalendar/daygrid/main.css" %}">
<link rel="stylesheet" href="{% static "ietf/css/fullcalendar.css" %}">
{% endblock %}
{% block bodyAttrs %}data-bs-spy="scroll" data-bs-target="#affix"{% endblock %}
{% block title %}Upcoming Meetings{% endblock %}
{% block morecss %}
{% block morecssXXX %}
div.title-buttons {
margin-bottom: 0.5em;
margin-top: 1em;
@ -176,8 +173,7 @@
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
<script src="{% static 'fullcalendar/core/main.js' %}"></script>
<script src="{% static 'fullcalendar/daygrid/main.js' %}"></script>
<script src="{% static 'ietf/js/fullcalendar.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script src="{% static 'ietf/js/agenda_filter.js' %}"></script>
@ -282,14 +278,15 @@
* filtered events.
*/
var calendarEl = document.getElementById('calendar')
event_calendar = new FullCalendar.Calendar(calendarEl, {
plugins: ['dayGrid'],
displayEventTime: false,
events: function (fInfo, success) {success(display_events)},
eventRender: function (info) {
$(info.el).tooltip({ title: info.event.title })
},
timeFormat: 'H:mm',
event_calendar = new FullCalendar(calendarEl, {
plugins: ['dayGridPlugin'],
initialView: 'dayGridMonth',
// displayEventTime: false,
// events: function (fInfo, success) {success(display_events)},
// eventRender: function (info) {
// $(info.el).tooltip({ title: info.event.title })
// },
// timeFormat: 'H:mm',
})
event_calendar.render()
}

140
package-lock.json generated
View file

@ -5,6 +5,8 @@
"packages": {
"": {
"dependencies": {
"@fullcalendar/core": "^5.10.1",
"@fullcalendar/daygrid": "^5.10.1",
"@popperjs/core": "^2.10.2",
"bootstrap": "^5.1.3",
"bootstrap-datepicker": "^1.9.0",
@ -517,6 +519,33 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@fullcalendar/common": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.10.1.tgz",
"integrity": "sha512-EumKIJcQTvQdTs75/9dmeREFgjcRVWzqHJS1Xvlz5mNsmB+w9EINCHETRjChtAQg1WD/lTQyVj4sHsKO7vCMSw==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/core": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-5.10.1.tgz",
"integrity": "sha512-8sVuC6ywXV+cxqsqTZaR1hgUqeyjVed20NyZ7lGW9AY0kma1GIEwLgqPS5Q6uVhHyin68lmgecKfJCwhxENE8w==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"preact": "^10.0.5",
"tslib": "^2.1.0"
}
},
"node_modules/@fullcalendar/daygrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-5.10.1.tgz",
"integrity": "sha512-sfUMP+rew0krsBffgNcWWKhBCiyytGfRKZJoc64E8ohX7VWjPcPZuB1xgO5U4wPLmNkT0rZiHoGeQGTXw1+ZKg==",
"dependencies": {
"@fullcalendar/common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
@ -2509,9 +2538,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001282",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001282.tgz",
"integrity": "sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==",
"version": "1.0.30001283",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
"integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==",
"dev": true,
"funding": {
"type": "opencollective",
@ -3451,9 +3480,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.0.tgz",
"integrity": "sha512-+oXCt6SaIu8EmFTPx8wNGSB0tHQ5biDscnlf6Uxuz17e9CjzMRtGk9B8705aMPnj0iWr3iC74WuIkngCsLElmA==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.3.tgz",
"integrity": "sha512-hfpppjYhqIZB8jrNb0rNceQRkSnBN7QJl3W26O1jUv3F3BkQknqy1YTqVXkFnIcFtBc3Qnv5M7r5Lez2iOLgZA==",
"dev": true
},
"node_modules/elliptic": {
@ -6125,9 +6154,9 @@
}
},
"node_modules/ordered-binary": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.1.3.tgz",
"integrity": "sha512-tDTls+KllrZKJrqRXUYJtIcWIyoQycP7cVN7kzNNnhHKF2bMKHflcAQK+pF2Eb1iVaQodHxqZQr0yv4HWLGBhQ==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.2.1.tgz",
"integrity": "sha512-Zl2RCcj/wRCakW9/yI83gutgNf7JFOPEHrCK72z+boIrU+PWAnIt6HADd1w+3keDQ90GCKbp1BduKZgkeNbz7A==",
"dev": true
},
"node_modules/os-browserify": {
@ -6324,9 +6353,9 @@
"dev": true
},
"node_modules/postcss": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.0.tgz",
"integrity": "sha512-BRMNx3Wy7UI89jN8H4ZVS5lQMPM2OSMkOkvDCSjwXa7PWTs24k7Lm55NXLbMbs070LvraXaxN5l1npSOS6wMVw==",
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.1.tgz",
"integrity": "sha512-WqLs/TTzXdG+/A4ZOOK9WDZiikrRaiA+eoEb/jz2DT9KUhMNHgP7yKPO8vwi62ZCsb703Gwb7BMZwDzI54Y2Ag==",
"dev": true,
"dependencies": {
"nanoid": "^3.1.30",
@ -7323,6 +7352,15 @@
"node": ">=12"
}
},
"node_modules/preact": {
"version": "10.6.1",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.1.tgz",
"integrity": "sha512-ydCg+ISIq70vqiThvNWStZWLRjR9U2awP/JAmGdWUKm9+Tyuy+MqVdAIyEByeIspAVtD4GWC/SJtxO8XD4knVA==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/preact"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -7765,9 +7803,9 @@
"dev": true
},
"node_modules/sass": {
"version": "1.43.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
"integrity": "sha512-/ptG7KE9lxpGSYiXn7Ar+lKOv37xfWsZRtFYal2QHNigyVQDx685VFT/h7ejVr+R8w7H4tmUgtulsKl5YpveOg==",
"version": "1.43.5",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.5.tgz",
"integrity": "sha512-WuNm+eAryMgQluL7Mbq9M4EruyGGMyal7Lu58FfnRMVWxgUzIvI7aSn60iNt3kn5yZBMR7G84fAGDcwqOF5JOg==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0"
@ -8378,6 +8416,11 @@
"node": ">=6"
}
},
"node_modules/tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/tty-browserify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
@ -9231,6 +9274,33 @@
"strip-json-comments": "^3.1.1"
}
},
"@fullcalendar/common": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/common/-/common-5.10.1.tgz",
"integrity": "sha512-EumKIJcQTvQdTs75/9dmeREFgjcRVWzqHJS1Xvlz5mNsmB+w9EINCHETRjChtAQg1WD/lTQyVj4sHsKO7vCMSw==",
"requires": {
"tslib": "^2.1.0"
}
},
"@fullcalendar/core": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-5.10.1.tgz",
"integrity": "sha512-8sVuC6ywXV+cxqsqTZaR1hgUqeyjVed20NyZ7lGW9AY0kma1GIEwLgqPS5Q6uVhHyin68lmgecKfJCwhxENE8w==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"preact": "^10.0.5",
"tslib": "^2.1.0"
}
},
"@fullcalendar/daygrid": {
"version": "5.10.1",
"resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-5.10.1.tgz",
"integrity": "sha512-sfUMP+rew0krsBffgNcWWKhBCiyytGfRKZJoc64E8ohX7VWjPcPZuB1xgO5U4wPLmNkT0rZiHoGeQGTXw1+ZKg==",
"requires": {
"@fullcalendar/common": "~5.10.1",
"tslib": "^2.1.0"
}
},
"@humanwhocodes/config-array": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
@ -10641,9 +10711,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001282",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001282.tgz",
"integrity": "sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==",
"version": "1.0.30001283",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
"integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==",
"dev": true
},
"caseless": {
@ -11395,9 +11465,9 @@
}
},
"electron-to-chromium": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.0.tgz",
"integrity": "sha512-+oXCt6SaIu8EmFTPx8wNGSB0tHQ5biDscnlf6Uxuz17e9CjzMRtGk9B8705aMPnj0iWr3iC74WuIkngCsLElmA==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.3.tgz",
"integrity": "sha512-hfpppjYhqIZB8jrNb0rNceQRkSnBN7QJl3W26O1jUv3F3BkQknqy1YTqVXkFnIcFtBc3Qnv5M7r5Lez2iOLgZA==",
"dev": true
},
"elliptic": {
@ -13434,9 +13504,9 @@
}
},
"ordered-binary": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.1.3.tgz",
"integrity": "sha512-tDTls+KllrZKJrqRXUYJtIcWIyoQycP7cVN7kzNNnhHKF2bMKHflcAQK+pF2Eb1iVaQodHxqZQr0yv4HWLGBhQ==",
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.2.1.tgz",
"integrity": "sha512-Zl2RCcj/wRCakW9/yI83gutgNf7JFOPEHrCK72z+boIrU+PWAnIt6HADd1w+3keDQ90GCKbp1BduKZgkeNbz7A==",
"dev": true
},
"os-browserify": {
@ -13593,9 +13663,9 @@
"dev": true
},
"postcss": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.0.tgz",
"integrity": "sha512-BRMNx3Wy7UI89jN8H4ZVS5lQMPM2OSMkOkvDCSjwXa7PWTs24k7Lm55NXLbMbs070LvraXaxN5l1npSOS6wMVw==",
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.1.tgz",
"integrity": "sha512-WqLs/TTzXdG+/A4ZOOK9WDZiikrRaiA+eoEb/jz2DT9KUhMNHgP7yKPO8vwi62ZCsb703Gwb7BMZwDzI54Y2Ag==",
"dev": true,
"requires": {
"nanoid": "^3.1.30",
@ -14326,6 +14396,11 @@
"is-json": "^2.0.1"
}
},
"preact": {
"version": "10.6.1",
"resolved": "https://registry.npmjs.org/preact/-/preact-10.6.1.tgz",
"integrity": "sha512-ydCg+ISIq70vqiThvNWStZWLRjR9U2awP/JAmGdWUKm9+Tyuy+MqVdAIyEByeIspAVtD4GWC/SJtxO8XD4knVA=="
},
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -14652,9 +14727,9 @@
"dev": true
},
"sass": {
"version": "1.43.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.4.tgz",
"integrity": "sha512-/ptG7KE9lxpGSYiXn7Ar+lKOv37xfWsZRtFYal2QHNigyVQDx685VFT/h7ejVr+R8w7H4tmUgtulsKl5YpveOg==",
"version": "1.43.5",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.43.5.tgz",
"integrity": "sha512-WuNm+eAryMgQluL7Mbq9M4EruyGGMyal7Lu58FfnRMVWxgUzIvI7aSn60iNt3kn5yZBMR7G84fAGDcwqOF5JOg==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0"
@ -15125,6 +15200,11 @@
}
}
},
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tty-browserify": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",

View file

@ -1,5 +1,7 @@
{
"dependencies": {
"@fullcalendar/core": "^5.10.1",
"@fullcalendar/daygrid": "^5.10.1",
"@popperjs/core": "^2.10.2",
"bootstrap": "^5.1.3",
"bootstrap-datepicker": "^1.9.0",
@ -23,6 +25,7 @@
"ietf/static/js/list.js",
"ietf/static/js/document_timeline.js",
"ietf/static/js/d3.js",
"ietf/static/js/fullcalendar.js",
"ietf/static/js/datepicker.js",
"ietf/static/js/highcharts-highcharts.js",
"ietf/static/js/highcharts-highstock.js",
@ -41,7 +44,6 @@
"ietf/static/js/moment-timezone-with-data-10-year-range.js",
"ietf/static/css/ietf.scss",
"ietf/static/css/list.scss",
"ietf/static/css/datepicker.scss",
"ietf/static/images/ietflogo-small-transparent.png",
"ietf/static/images/ietflogo.png",
"ietf/static/images/apple-touch-icon.png",