Skip to content

Commit d4d09a2

Browse files
committed
Refactor graphical timeline, by making the data available via doc.json. Also
refactor associated js/css/html. Finally, a lot of display tweaks. - Legacy-Id: 10550
1 parent e1ff3a5 commit d4d09a2

5 files changed

Lines changed: 181 additions & 141 deletions

File tree

ietf/doc/utils.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import urllib
44
import math
55
import datetime
6-
import operator
76

87
from django.conf import settings
98
from django.db.models.query import EmptyQuerySet
@@ -542,7 +541,7 @@ def uppercase_std_abbreviated_name(name):
542541
return name
543542

544543
def crawl_history(doc):
545-
# return document history data for use in ietf/templates/doc/timeline.html
544+
# return document history data for inclusion in doc.json (used by timeline)
546545
def ancestors(doc):
547546
retval = []
548547
if hasattr(doc, 'relateddocument_set'):
@@ -559,12 +558,20 @@ def ancestors(doc):
559558
for d in history:
560559
for e in d.docevent_set.filter(type='new_revision'):
561560
if hasattr(e, 'newrevisiondocevent'):
562-
retval.append((d.name, e.newrevisiondocevent.rev, e.time.isoformat()))
561+
retval.append({
562+
'name': d.name,
563+
'rev': e.newrevisiondocevent.rev,
564+
'published': e.time.isoformat()
565+
})
563566

564567
if doc.type_id == "draft":
565568
e = doc.latest_event(type='published_rfc')
566569
else:
567570
e = doc.latest_event(type='iesg_approved')
568571
if e:
569-
retval.append((doc.name, e.doc.canonical_name, e.time.isoformat()))
570-
return sorted(retval, key=operator.itemgetter(2))
572+
retval.append({
573+
'name': e.doc.canonical_name(),
574+
'rev': e.doc.canonical_name(),
575+
'published': e.time.isoformat()
576+
})
577+
return sorted(retval, key=lambda x: x['published'])

ietf/doc/views_doc.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,6 @@ def document_main(request, name, rev=None):
417417
search_archive=search_archive,
418418
actions=actions,
419419
tracking_document=tracking_document,
420-
rev_history=crawl_history(latest_revision.doc if latest_revision else doc),
421420
),
422421
context_instance=RequestContext(request))
423422

@@ -443,8 +442,6 @@ def document_main(request, name, rev=None):
443442

444443
can_manage = can_manage_group_type(request.user, doc.group.type_id)
445444

446-
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
447-
448445
return render_to_response("doc/document_charter.html",
449446
dict(doc=doc,
450447
top=top,
@@ -459,7 +456,6 @@ def document_main(request, name, rev=None):
459456
group=group,
460457
milestones=milestones,
461458
can_manage=can_manage,
462-
rev_history=crawl_history(latest_revision.doc if latest_revision else doc),
463459
),
464460
context_instance=RequestContext(request))
465461

@@ -477,8 +473,6 @@ def document_main(request, name, rev=None):
477473
if doc.get_state_slug() in ("iesgeval") and doc.active_ballot():
478474
ballot_summary = needed_ballot_positions(doc, doc.active_ballot().active_ad_positions().values())
479475

480-
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
481-
482476
return render_to_response("doc/document_conflict_review.html",
483477
dict(doc=doc,
484478
top=top,
@@ -490,7 +484,6 @@ def document_main(request, name, rev=None):
490484
conflictdoc=conflictdoc,
491485
ballot_summary=ballot_summary,
492486
approved_states=('appr-reqnopub-pend','appr-reqnopub-sent','appr-noprob-pend','appr-noprob-sent'),
493-
rev_history=crawl_history(latest_revision.doc if latest_revision else doc),
494487
),
495488
context_instance=RequestContext(request))
496489

@@ -515,8 +508,6 @@ def document_main(request, name, rev=None):
515508
else:
516509
sorted_relations=None
517510

518-
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
519-
520511
return render_to_response("doc/document_status_change.html",
521512
dict(doc=doc,
522513
top=top,
@@ -528,7 +519,6 @@ def document_main(request, name, rev=None):
528519
ballot_summary=ballot_summary,
529520
approved_states=('appr-pend','appr-sent'),
530521
sorted_relations=sorted_relations,
531-
rev_history=crawl_history(latest_revision.doc if latest_revision else doc),
532522
),
533523
context_instance=RequestContext(request))
534524

@@ -921,6 +911,9 @@ def extract_name(s):
921911
data["shepherd"] = doc.shepherd.formatted_email() if doc.shepherd else None
922912
data["ad"] = doc.ad.role_email("ad").formatted_email() if doc.ad else None
923913

914+
latest_revision = doc.latest_event(NewRevisionDocEvent, type="new_revision")
915+
data["rev_history"] = crawl_history(latest_revision.doc if latest_revision else doc)
916+
924917
if doc.type_id == "draft":
925918
data["iesg_state"] = extract_name(doc.get_state("draft-iesg"))
926919
data["rfceditor_state"] = extract_name(doc.get_state("draft-rfceditor"))
@@ -932,7 +925,7 @@ def extract_name(s):
932925
data["consensus"] = e.consensus if e else None
933926
data["stream"] = extract_name(doc.stream)
934927

935-
return HttpResponse(json.dumps(data, indent=2), content_type='text/plain')
928+
return HttpResponse(json.dumps(data, indent=2), content_type='application/json')
936929

937930
class AddCommentForm(forms.Form):
938931
comment = forms.CharField(required=True, widget=forms.Textarea)
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
var data;
2+
3+
d3.json("doc.json", function(error, json) {
4+
if (error) return console.warn(error);
5+
data = json["rev_history"];
6+
7+
// make js dates out of publication dates
8+
data.forEach(function(el) { el.published = new Date(el.published); });
9+
10+
// add pseudo entry for beginning of year of first publication
11+
var year = data[0].published.getFullYear();
12+
data.unshift({ name:'', rev: '', published: new Date(year, 0, 0)});
13+
14+
// add pseudo entry at end of year of last revision
15+
year = data[data.length - 1].published.getFullYear();
16+
data.push({ name:'', rev: '', published: new Date(year + 1, 0, 0)});
17+
18+
draw_timeline();
19+
});
20+
21+
22+
var xscale;
23+
var y;
24+
var bar_height;
25+
26+
27+
function offset(d, i) {
28+
if (i > 1 && data[i - 1].name !== d.name || d.rev.match("rfc"))
29+
y += bar_height;
30+
return "translate(" + xscale(d.published) + ", " + y + ")";
31+
}
32+
33+
34+
function bar_width(d, i) {
35+
if (i > 0 && i < data.length - 1)
36+
return xscale(data[i + 1].published) - xscale(d.published);
37+
}
38+
39+
40+
function draw_timeline() {
41+
var w = $("#timeline").width();
42+
// bar_height = parseFloat($("body").css('line-height'));
43+
bar_height = 30;
44+
45+
xscale = d3.time.scale().domain([
46+
d3.min(data, function(d) { return d.published; }),
47+
d3.max(data, function(d) { return d.published; })
48+
]).range([0, w]);
49+
50+
y = 0;
51+
var chart = d3.select("#timeline svg").attr("width", w);
52+
var bar = chart.selectAll("g").data(data);
53+
54+
// update
55+
bar
56+
.attr("transform", offset)
57+
.select("rect")
58+
.attr("width", bar_width);
59+
60+
// enter
61+
var g = bar.enter()
62+
.append("g")
63+
.attr({
64+
class: "bar",
65+
transform: offset
66+
});
67+
g.append("rect")
68+
.attr({
69+
height: bar_height,
70+
width: bar_width
71+
});
72+
g.append("text")
73+
.attr({
74+
x: 3,
75+
y: bar_height/2
76+
})
77+
.text(function(d) { return d.rev; });
78+
79+
// exit
80+
bar.exit().remove();
81+
82+
var xaxis = d3.svg.axis()
83+
.scale(xscale)
84+
.tickValues(data.slice(1, -1).map(function(d) { return d.published; }))
85+
.tickFormat(d3.time.format("%b %Y"))
86+
.orient("bottom");
87+
88+
var ids = data
89+
.map(function(elem) { return elem.name; })
90+
.filter(function(val, i, self) { return self.indexOf(val) === i; });
91+
ids.shift(); // first one is pseudo entry (last one, too, but filtered above)
92+
console.log(ids);
93+
94+
var yaxis = d3.svg.axis()
95+
.scale(d3.scale.ordinal().domain(ids).rangePoints([0, y - bar_height]))
96+
.tickValues(ids)
97+
.orient("left");
98+
99+
chart.append("g")
100+
.attr({
101+
class: "x axis",
102+
transform: "translate(0, " + y + ")"
103+
})
104+
.call(xaxis)
105+
.selectAll("text")
106+
.style("text-anchor", "end")
107+
.attr("transform", "translate(-18, 8) rotate(-90)");
108+
109+
chart.append("g")
110+
.attr({
111+
class: "y axis",
112+
transform: "translate(10, " + bar_height/2 + ")"
113+
})
114+
.call(yaxis)
115+
.selectAll("text")
116+
.style("text-anchor", "start");
117+
118+
chart.attr('height', y);
119+
}
120+
121+
122+
$(window).on({
123+
resize: function (event) {
124+
draw_timeline();
125+
}
126+
});

ietf/templates/doc/document_draft.html

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,40 @@
1010
{% endblock %}
1111

1212
{% block morecss %}
13-
.inline { display: inline; }
14-
{% endblock %}
13+
.inline { display: inline; }
1514

16-
{% block js %}
17-
<script>
18-
$(window).on({
19-
resize: function (event) {
20-
draw_timeline();
21-
},
22-
load: function (event) {
23-
draw_timeline();
24-
}
25-
});
26-
</script>
27-
{% endblock %}
15+
#timeline .axis text { font-size: small; }
16+
17+
#timeline .axis path, #timeline .axis line {
18+
fill: none;
19+
stroke: black;
20+
}
21+
22+
#timeline .axis.y path, #timeline .axis.y line { stroke: none; }
23+
24+
#timeline .axis.x text {
25+
dominant-baseline: central;
26+
fill: darkgrey;
27+
}
28+
29+
#timeline .bar text {
30+
fill: white;
31+
dominant-baseline: central;
32+
}
2833

34+
#timeline .bar:nth-child(odd) rect {
35+
fill: #3abf03;
36+
stroke: #32a602;
37+
stroke-width: 1;
38+
}
39+
40+
#timeline .bar:nth-child(even) rect {
41+
fill: #6b5bad;
42+
stroke: #5f4f9f;
43+
stroke-width: 1;
44+
}
45+
46+
{% endblock %}
2947

3048
{% block title %}
3149
{% if doc.get_state_slug == "rfc" %}
@@ -40,7 +58,7 @@
4058
{{ top|safe }}
4159

4260
{% include "doc/revisions_list.html" %}
43-
{% include "doc/timeline.html" %}
61+
<div id="timeline"><svg></svg></div>
4462

4563
<table class="table table-condensed">
4664
<thead id="message-row">
@@ -509,3 +527,9 @@ <h4>Authors</h4>
509527
{% endif %}
510528

511529
{% endblock %}
530+
531+
532+
{% block js %}
533+
<script src="{% static 'd3/d3.min.js' %}"></script>
534+
<script src="{% static 'ietf/js/document_timeline.js' %}"></script>
535+
{% endblock %}

0 commit comments

Comments
 (0)