Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ietf/doc/templatetags/ietf_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -779,3 +779,10 @@ def is_valid_url(url):
except ValidationError:
return False
return True

@register.filter
def get_hash(h, key):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest naming this get_from_dict or something that better matches the dict Python data type. (There's a similar filter lookup in agenda_custom_tags.py that could perhaps be moved and reused - this is a better place for it.)

"""
Get a key from hash
"""
return h[key]
2 changes: 1 addition & 1 deletion ietf/doc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
url(r'^$', views_search.search),
url(r'^search/?$', views_search.search),
url(r'^in-last-call/?$', views_search.drafts_in_last_call),
url(r'^ad/(?P<name>[^/]+)/?$', views_search.docs_for_ad),
url(r'^ad/(?:(?P<name>[^/]+)/)?$', views_search.docs_for_ad),
url(r'^ad2/(?P<name>[\w.-]+)/$', RedirectView.as_view(url='/doc/ad/%(name)s/', permanent=True)),
url(r'^rfc-status-changes/?$', views_status_change.rfc_status_changes),
url(r'^start-rfc-status-change/(?:%(name)s/)?$' % settings.URL_REGEXPS, views_status_change.start_rfc_status_change),
Expand Down
124 changes: 121 additions & 3 deletions ietf/doc/views_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,32 @@ def cached_redirect(cache_key, url):

return cached_redirect(cache_key, urlreverse('ietf.doc.views_search.search') + search_args)

def ad_dashboard_group_type(doc):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds a new point of maintenance when new document types are created. Instead of literal strings, why isn't this using DocTypeName.name? (see

content = markdown.markdown(doc.text_or_error())
) and, for instance, at #L315, just iterating over the DocTypeNames that are used?

# Return group type for document for dashboard.
# If doc is not defined return list of all possible
# group types
if not doc:
return ('I-D', 'RFC', 'Conflict Review', 'Status Change', 'Charter')
if doc.type.slug=='draft':
if doc.get_state_slug('draft') == 'rfc':
return 'RFC'
elif doc.get_state_slug('draft') == 'active' and doc.get_state_slug('draft-iesg') and doc.get_state('draft-iesg').name in ('RFC Ed Queue'):
return 'RFC'
elif doc.get_state_slug('draft') == 'active' and doc.get_state_slug('draft-iesg') and doc.get_state('draft-iesg').name in ('Dead', 'I-D Exists', 'AD is watching'):
return None
elif doc.get_state('draft').name in ('Expired', 'Replaced'):
return None
else:
return 'I-D'
elif doc.type.slug=='conflrev':

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to @rjsparks's comment above would be better to make use of the DocTypeName data rather than repeating it here. A single doc.type.slug in [] test could replace a bunch of these cases

return 'Conflict Review'
elif doc.type.slug=='statchg':
return 'Status Change'
elif doc.type.slug=='charter':
return "Charter"
else:
return "Document"

def ad_dashboard_group(doc):

if doc.type.slug=='draft':
Expand Down Expand Up @@ -395,14 +421,106 @@ def ad_dashboard_sort_key(doc):

def docs_for_ad(request, name):
ad = None
ads = []
responsible = Document.objects.values_list('ad', flat=True).distinct()
for p in Person.objects.filter(Q(role__name__in=("pre-ad", "ad"),
role__group__type="area",
role__group__state="active")
| Q(pk__in=responsible)).distinct():
if name == p.full_name_as_key():
ad = p
break
if not name:
if p in get_active_ads():
ads.append(p)
else:
if name == p.full_name_as_key():
ad = p
break
if not name:
doctypes = list(DocTypeName.objects.filter(used=True).exclude(slug='draft').values_list("pk", flat=True))

group_types = ad_dashboard_group_type(None)

groups = {}
group_names = {}
for g in group_types:
groups[g] = {}
group_names[g] = []

# Prefill groups in preferred sort order
id = 0
for g in [
'Publication Requested Internet-Draft',
'Waiting for Writeup Internet-Draft',
'AD Evaluation Internet-Draft',
'In Last Call Internet-Draft',
'IESG Evaluation - Defer Internet-Draft',
'IESG Evaluation Internet-Draft',
'Waiting for AD Go-Ahead Internet-Draft',
'Approved-announcement to be sent Internet-Draft',
'Approved-announcement sent Internet-Draft']:
groups['I-D'][g] = id
group_names['I-D'].append(g)
id += 1;
id = 0
for g in ['RFC Ed Queue Internet-Draft', 'RFC']:
groups['RFC'][g] = id
group_names['RFC'].append(g)
id += 1;
id = 0
for g in ['AD Review Conflict Review',
'Needs Shepherd Conflict Review',
'IESG Evaluation Conflict Review',
'Approved Conflict Review',
'Withdrawn Conflict Review']:
groups['Conflict Review'][g] = id
group_names['Conflict Review'].append(g)
id += 1;
id = 0
for g in [ 'Start Chartering/Rechartering (Internal Steering Group/IAB Review) Charter',
'Replaced Charter',
'Approved Charter',
'Not currently under review Charter']:
groups['Charter'][g] = id
group_names['Charter'].append(g)
id += 1;

for ad in ads:
form = SearchForm({'by':'ad','ad': ad.id,
'rfcs':'on', 'activedrafts':'on',
'olddrafts':'on',
'doctypes': doctypes})
data = retrieve_search_results(form)
ad.dashboard = urlreverse("ietf.doc.views_search.docs_for_ad") + ad.full_name_as_key()
counts = {}
for g in group_types:
counts[g] = []
for doc in data:
group_type = ad_dashboard_group_type(doc)
if group_type:
group = ad_dashboard_group(doc)
if group not in groups[group_type]:
groups[group_type][group] = len(groups[group_type])
group_names[group_type].append(group)
if len(counts[group_type]) < len(groups[group_type]):
counts[group_type].extend([0] * (len(groups[group_type]) - len(counts[group_type])))
counts[group_type][groups[group_type][group]] += 1
ad.counts = counts
for ad in ads:
for group_type in group_types:
if len(ad.counts[group_type]) < len(groups[group_type]):
ad.counts[group_type].extend([0] * (len(groups[group_type]) - len(ad.counts[group_type])))
# Shorten the names of groups
for gt in group_types:
for idx,g in enumerate(group_names[gt]):
for s in [' Internet-Draft', ' Charter', ' Conflict Review', ' Status Change', ' (Internal Steering Group/IAB Review) Charter']:
if g.endswith(s):
group_names[gt][idx] = g[:-len(s)]
return render(request, 'doc/ad_list.html', {
'ads': ads,
'group_types': group_types,
'group_names': group_names,
'groups': groups
})

if not ad:
raise Http404
form = SearchForm({'by':'ad','ad': ad.id,
Expand Down
41 changes: 41 additions & 0 deletions ietf/templates/doc/ad_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "base.html" %}
{# Copyright The IETF Trust 2015, All Rights Reserved #}
{% load origin static %}
{% load ietf_filters %}
{% block pagehead %}
<link rel="stylesheet" href="{% static "ietf/css/list.css" %}">
{% endblock %}
{% block title %}Area directors{% endblock %}
{% block content %}
{% origin %}
<h1>Area Directors Workload</h1>
{% for gt in group_types %}
<h2>{{ gt }}</h2>
<table class="table table-sm table-striped tablesorter">
<thead>
<tr>
<th scope="col" data-sort="name">Name</th>
{% for g in group_names|get_hash:gt %}
<th scope="col" data-sort="{{ g|slugify }}-num">
{{ g }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for ad in ads %}
<tr>
<td><A HREF="{{ ad.dashboard }}">{{ ad.name }}</A></td>
{% for c in ad.counts|get_hash:gt %}
{% if forloop.counter0 < groups|get_hash:gt|length %}
<td>{{ c }}</th>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
{% endblock %}
{% block js %}
<script src="{% static "ietf/js/list.js" %}"></script>
{% endblock %}