summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurélien Bompard <aurelien@bompard.org>2013-11-20 10:14:51 -0800
committerAurélien Bompard <aurelien@bompard.org>2013-11-20 10:14:51 -0800
commitc8ef5f4be18890bfee301df3bfd41e4f0434451e (patch)
tree243ce6eac57d016569bd2dc014f4da40ab724a36
parentf38e0d666c86220089a6d5afe940aabb762a0a21 (diff)
parent174ab43c1c2bca4d01626a73379d0f2aed23b2d9 (diff)
downloadhyperkitty-c8ef5f4be18890bfee301df3bfd41e4f0434451e.tar.gz
hyperkitty-c8ef5f4be18890bfee301df3bfd41e4f0434451e.tar.xz
hyperkitty-c8ef5f4be18890bfee301df3bfd41e4f0434451e.zip
Merge pull request #10 from mairin/master
List overview redesign
-rw-r--r--doc/database.rst3
-rw-r--r--hyperkitty/static/hyperkitty/css/hyperkitty-common.css7
-rw-r--r--hyperkitty/static/hyperkitty/css/hyperkitty-overview.css189
-rw-r--r--hyperkitty/static/hyperkitty/css/hyperkitty-threadslist.css7
-rw-r--r--hyperkitty/static/hyperkitty/js/hyperkitty-overview.js200
-rw-r--r--hyperkitty/templates/overview.html139
-rw-r--r--hyperkitty/templates/threads/summary_thread.html20
-rw-r--r--hyperkitty/templatetags/storm.py4
8 files changed, 461 insertions, 108 deletions
diff --git a/doc/database.rst b/doc/database.rst
index c71162f..ade71f9 100644
--- a/doc/database.rst
+++ b/doc/database.rst
@@ -61,7 +61,8 @@ where:
``django-admin`` command)
* ``NAME`` is the fully-qualified list name (including the ``@`` sign and the
domain name)
-* The ``mbox_file`` arguments are the existing archives to import.
+* The ``mbox_file`` arguments are the existing archives to import. Make sure you point
+at the *.txt version of the files and not the *.gz.
If the previous archives aren't available locally, you need to download them
from your current Mailman 2.1 installation. The ``kittystore-download21``
diff --git a/hyperkitty/static/hyperkitty/css/hyperkitty-common.css b/hyperkitty/static/hyperkitty/css/hyperkitty-common.css
index dab65bb..c262308 100644
--- a/hyperkitty/static/hyperkitty/css/hyperkitty-common.css
+++ b/hyperkitty/static/hyperkitty/css/hyperkitty-common.css
@@ -325,4 +325,9 @@ a.thread-new strong {
display: none; /* Displayed manually */
}
-
+h1 {
+ margin-top: 0px;
+ font-size: 28px !important; /* override bootstrap */
+ line-height: 32px;
+ margin-bottom: 0.5em;
+}
diff --git a/hyperkitty/static/hyperkitty/css/hyperkitty-overview.css b/hyperkitty/static/hyperkitty/css/hyperkitty-overview.css
index a54c281..c91ea36 100644
--- a/hyperkitty/static/hyperkitty/css/hyperkitty-overview.css
+++ b/hyperkitty/static/hyperkitty/css/hyperkitty-overview.css
@@ -1,53 +1,62 @@
/* Summary page */
-#overview h2 {
- font-size: 22px;
- line-height: 32px;
- margin-bottom: 0.5em;
- text-align: center;
+#overview h2 #breadcrumb {
+ font-weight: normal;
+ font-size: 12px;
}
#overview h3 {
- font-size: 20px;
+ font-size: 14px;
line-height: 28px;
margin-bottom: 0.5em;
margin-top: 0;
- text-align: center;
}
-#graph h2 {
- text-align: center;
-}
-#graph rect {
+#chart-data rect {
cursor: pointer;
}
-#fig {
+#fig, #chart-data {
position: relative;
margin: auto;
- width: 540px;
- height: 300px;
+ font-size: 8pt;
+ font-family: "Droid Sans", sans-serf;
+ font-color: #777;
}
-#fig .axis path, #fig .axis line {
+
+#fig .axis path, #fig .axis line,
+#chart-data .axis path, #chart-data .axis line {
+/*
fill: none;
- stroke: #000;
+ stroke: #bbb;
shape-rendering: geometricPrecision;
+*/
+ display: none;
}
-#fig .area {
+#fig .area,
+#chart-data .bars rect {
fill: steelBlue;
}
-#overview .list-stats {
- text-align: center;
-}
-#overview p.thread-new {
- text-align: center;
+/* Next 2 blocks for grid lines */
+
+/*
+#fig .grid .tick,
+#chart-data .grid .tick {
+ stroke: lightgrey;
+ opacity: 0.3;
}
+#fig .grid path,
+#chart-data .grid path {
+ stroke-width: 0;
+}
+*/
+/*
#overview .widget {
padding: 1em;
border: 1px solid #ddd;
@@ -56,6 +65,7 @@
border-radius: 10px;
margin: 1em 0;
}
+*/
#overview .thread {
margin: 1.5em 0 0 0;
@@ -107,7 +117,7 @@
font-weight: bold;
font-size: 115%;
vertical-align: top;
- padding-right: 20px;
+ padding-right: 3px;
}
.maker .gravatar {
@@ -140,3 +150,136 @@
#discussion-by-category .thread .category {
display: none;
}
+
+
+section#title h2 {
+
+ margin-bottom: 0px;
+}
+
+
+section#title #description {
+ font-size: 12pt;
+ font-weight: normal;
+}
+
+section#title svg {
+ padding-top: 3px;
+ border: 1px solid #bbb;
+}
+
+section#title #chart {
+ margin-top: 2em;
+}
+
+section#title p.thread-new {
+ text-align: left;
+ margin-top: 1em;
+}
+
+section#statistics {
+ color: #555;
+}
+
+section#statistics .caption {
+ font-size: x-small;
+ color: #aaa;
+ margin-top: -.5%;
+ margin-left: .25em;
+ margin-bottom: 0px;
+}
+
+section#statistics ul {
+ list-style-type: none;
+ margin-left: 0px;
+}
+
+section#statistics li {
+ font-size: small;
+}
+
+section#statistics h3 {
+ margin-bottom: .5em;
+ margin-top: 3em;
+}
+
+#overview h3 {
+ color: #999;
+ text-transform: uppercase;
+ font-size: small;
+ font-weight: normal;
+}
+
+
+#title {
+ float: left;
+ width: 23%;
+ min-width: 20%;
+ margin-right: 2%;
+}
+
+#discussions {
+ margin-top: 3em;
+ padding-left: 1%;
+ float: right;
+ width: 74%;
+}
+
+/* this needs to be integrated into hyperkitty-threadslist.css eventually */
+div.thread {
+ border: 1px solid #e5e5e5;
+ padding: 1%;
+ margin: .5% !important;
+}
+
+.thread {
+ min-height: 1.2em;
+}
+
+.widget {
+ clear: both;
+ margin-bottom: 2em;
+}
+
+.thread ul.inline-block {
+ width: 28%;
+}
+
+.thread ul.inline-block li,
+.thread ul.inline-block span {
+ text-align: left;
+ min-width: 6.5%;
+}
+
+.thread-title {
+ width: 68%;
+ float: left;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-right: 2%;
+}
+
+
+.maker-name, .maker-id {
+ font-size: small;
+}
+
+.maker-id {
+ color: #aaa;
+}
+
+.thread-id {
+ float: left;
+}
+
+.maker-name {
+ display: block !important;
+ max-width: 152px !important;
+ word-wrap: break-word !important;
+}
+
+.maker .gravatar {
+ padding-right: 5px;
+}
+
diff --git a/hyperkitty/static/hyperkitty/css/hyperkitty-threadslist.css b/hyperkitty/static/hyperkitty/css/hyperkitty-threadslist.css
index a2e49ad..6effca1 100644
--- a/hyperkitty/static/hyperkitty/css/hyperkitty-threadslist.css
+++ b/hyperkitty/static/hyperkitty/css/hyperkitty-threadslist.css
@@ -53,7 +53,6 @@
.thread-title {
font-weight: bold;
- font-size: 125%;
}
.thread-date {
@@ -74,6 +73,12 @@
float: left;
}
+.thread-title .category {
+ width: 15%;
+ text-align: center;
+ margin-right: 1%;
+}
+
.thread-info .tags {
display: inline;
margin-right: 1em;
diff --git a/hyperkitty/static/hyperkitty/js/hyperkitty-overview.js b/hyperkitty/static/hyperkitty/js/hyperkitty-overview.js
index bf88118..e020554 100644
--- a/hyperkitty/static/hyperkitty/js/hyperkitty-overview.js
+++ b/hyperkitty/static/hyperkitty/js/hyperkitty-overview.js
@@ -21,8 +21,9 @@
/*
- * Recent activity graph
+ * Recent activity graph (area graph)
*/
+
function activity_graph(elem_id, dates, counts, baseurl) {
function merge(dates, counts) {
result = []
@@ -34,13 +35,30 @@ function activity_graph(elem_id, dates, counts, baseurl) {
}
return result;
}
+
+ /* Function for grid lines, for x-axis */
+ function make_x_axis() {
+ return d3.svg.axis()
+ .scale(x)
+ .orient("bottom")
+ .ticks(d3.time.days, 1)
+ }
+
+ /* Function for grid lines, for y-axis */
+ function make_y_axis() {
+ return d3.svg.axis()
+ .scale(y)
+ .orient("left")
+ .ticks(5)
+ }
+
var data = merge(dates, counts);
- var margin = {top: 20, right: 20, bottom: 100, left: 50},
- width = 540 - margin.left - margin.right,
- height = 330 - margin.top - margin.bottom;
+ var margin = {top: 20, right: 20, bottom: 50, left: 40},
+ width = 350 - margin.left - margin.right,
+ height = 150 - margin.top - margin.bottom;
var format_in = d3.time.format("%Y-%m-%d");
- var format_out = d3.time.format("%m-%d");
+ var format_out = d3.time.format("");
var x = d3.time.scale()
.range([0, width]);
@@ -51,16 +69,19 @@ function activity_graph(elem_id, dates, counts, baseurl) {
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
+ .tickSize(2,2)
.tickFormat(format_out)
- .ticks(d3.time.days, 2);
-
+ .ticks(d3.time.days, 1);
+
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
- .ticks(5)
+ .tickSize(4,3)
+ .ticks(2)
.tickSubdivide(1);
var area = d3.svg.area()
+ .interpolate("monotone")
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.count); });
@@ -78,6 +99,23 @@ function activity_graph(elem_id, dates, counts, baseurl) {
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.count; })]);
+
+ /* Draw the grid lines, for x-axis */
+ svg.append("g")
+ .attr("class", "grid")
+ .attr("Transform", "translate(0, " + height + ")")
+ .call(make_x_axis()
+ .tickSize(height, 0, 0)
+ .tickFormat("")
+ )
+
+ /* Draw the grid lines, for y-axis */
+ svg.append("g")
+ .attr("class", "grid")
+ .call(make_y_axis()
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ )
svg.append("path")
.datum(data)
@@ -95,13 +133,153 @@ function activity_graph(elem_id, dates, counts, baseurl) {
return "rotate(-90)"
});
+ /* Y-axis label */
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
- .attr("y", 6)
- .attr("dy", ".71em")
- .style("text-anchor", "end")
+ .attr("y", 0)
+ .attr("x", 0 - height/2)
+ .attr("dy", "-3em")
+ .style("text-anchor", "middle")
+ .style("fill", "#777")
.text("Messages");
+
+}
+
+
+/*
+ * Recent activity bar chart
+ */
+function chart(elem_id, dates, counts, baseurl) {
+ function merge(dates, counts) {
+ result = []
+ for(i = 0; i < dates.length; i++) {
+ result.push({
+ "date": dates[i],
+ "count": counts[i]
+ })
+ }
+ return result;
+ }
+
+ /* Function for grid lines, for x-axis */
+ function make_x_axis() {
+ return d3.svg.axis()
+ .scale(x)
+ .orient("bottom")
+ .ticks(d3.time.days, 1)
+ }
+
+ /* Function for grid lines, for y-axis */
+ function make_y_axis() {
+ return d3.svg.axis()
+ .scale(y)
+ .orient("left")
+ .ticks(5)
+ }
+
+ var data = merge(dates, counts);
+ var margin = {top: 0, right: 0, bottom: 0, left: 0},
+ width = 200 - margin.left - margin.right,
+ height = 50 - margin.top - margin.bottom;
+
+ var w = 5;
+
+ var format_in = d3.time.format("%Y-%m-%d");
+ var format_out = d3.time.format("");
+
+ var x = d3.time.scale()
+ .range([0, width]);
+
+ var y = d3.scale.linear()
+ .range([height, 0]);
+
+ var xAxis = d3.svg.axis()
+ .scale(x)
+ .orient("bottom")
+ .tickSize(0,0) // change to 2,2 for ticks
+ .tickFormat(format_out)
+ .ticks(d3.time.days, 1);
+
+ var yAxis = d3.svg.axis()
+ .scale(y)
+ .orient("left")
+ .tickSize(0,0) // change to 4,3 for ticks
+ .ticks("") // change to 2 for y-axis tick labels
+ .tickSubdivide(1);
+
+ var area = d3.svg.area()
+ .x(function(d) { return x(d.date); })
+ // .y0(height)
+ .y(function(d) { return y(d.count); });
+
+ var svg = d3.select(elem_id).append("svg")
+ .attr("id", "chart-data")
+ .attr("width", width + margin.left + margin.right)
+ .attr("height", height + margin.top + margin.bottom)
+ .append("g")
+ .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+
+ data.forEach(function(d) {
+ d.date = format_in.parse(d.date);
+ d.count = parseInt(d.count);
+ });
+
+ x.domain(d3.extent(data, function(d) { return d.date; }));
+ y.domain([0, d3.max(data, function(d) { return d.count; })]);
+
+
+ /* Draw the grid lines, for x-axis */
+ svg.append("g")
+ .attr("class", "grid")
+ .attr("Transform", "translate(0, " + height + ")")
+ .call(make_x_axis()
+ .tickSize(height, 0, 0)
+ .tickFormat("")
+ )
+
+ /* Draw the grid lines, for y-axis */
+ svg.append("g")
+ .attr("class", "grid")
+ .call(make_y_axis()
+ .tickSize(-width, 0, 0)
+ .tickFormat("")
+ )
+
+ svg.append("g").attr("class","bars").selectAll("rect")
+ .data(data)
+ .enter().append("rect")
+ .attr("x", function(d) { return x(d.date); })
+ //.attr("y0", height)
+ .attr("y", function(d) { return y(d.count); })
+ .attr("width", w)
+ .attr("height", function(d) { return height - y(d.count); });
+
+ /* draw x-axis */
+ svg.append("g")
+ .attr("class", "x axis")
+ .attr("transform", "translate(0," + height + ")")
+ .call(xAxis)
+ /*.selectAll("text")
+ .attr("y", -5)
+ .attr("x", -30)
+ .attr("transform", function(d) {
+ return "rotate(-90)"
+ });*/
+
+ /* Y-axis label */
+ svg.append("g")
+ .attr("class", "y axis")
+ .call(yAxis)
+ /*.append("text")
+ .attr("transform", "rotate(-90)")
+ .attr("y", 0)
+ .attr("x", 0 - height/2)
+ .attr("dy", "-3em")
+ .style("text-anchor", "middle")
+ .style("fill", "#777")
+ .text("Messages"); */
+
}
diff --git a/hyperkitty/templates/overview.html b/hyperkitty/templates/overview.html
index 8d521a6..098e609 100644
--- a/hyperkitty/templates/overview.html
+++ b/hyperkitty/templates/overview.html
@@ -18,66 +18,71 @@
{% include 'threads/month_list.html' %}
<section id="overview" class="span10">
-
- <section id="graph">
- <h2>Activities on the list over the last 30 days</h2>
- <ul class="list-stats inline">
- <li><span class="participant">{{ num_participants }} participants</span></li>
- <li><span class="discussion">{{ num_threads }} discussions</span></li>
- </ul>
-
- <div id="fig" />
- </section>
-
- <p class="thread-new">
- <a href="{% url "message_new" mlist_fqdn=mlist.name %}"
- class="thread-new btn{% if not user.is_authenticated %} disabled" title="You must be logged-in to create a thread.{% endif %}"
- ><strong>+</strong> Start a new thread</a>
- </p>
-
- <div class="row-fluid">
- <div class="span6"> <!-- Column 1 -->
-
- <section id="most-active" class="widget">
- <h3>Recently active discussions</h3>
- {% for thread in most_active_threads %}
- {% include "threads/summary_thread.html" with counter=forloop.counter %}
- {% endfor %}
- </section>
-
- <section id="popular-threads" class="widget">
- <h3>Most popular discussions</h3>
- {% for thread in pop_threads %}
- {% include "threads/summary_thread.html" with counter=forloop.counter %}
- {% empty %}
- <p>No vote has been cast this month (yet).</p>
- {% endfor %}
- </section>
-
- <section id="discussion-maker" class="widget">
- <h3>Most active posters</h3>
- {% for poster in top_posters %}
- <div class="maker">
- <div class="inline-block maker-id">
- #{{forloop.counter}}
- </div>
- <div class="inline-block gravatar">
- {% gravatar poster.email 40 %}
- <br />
- </div>
- <div class="inline-block">
- <span class="maker-name">{{ poster.name }}</span>
- <br />
- <span class="score">{{ poster.count }}</span> posts
- </div>
- </div>
- {% endfor %}
- </section>
-
- </div>
- <div class="span6"> <!-- Column 2 -->
-
- <section id="top-discussion" class="widget">
+
+ <section id="title">
+ <h2>{{ mlist.display_name }}</h2>
+ <p id="description">{{ mlist.description}}</p>
+
+ <section id="statistics">
+
+ <div id="chart"></div>
+ <p class="caption">Post volume over the past <strong>30</strong> days.</p>
+
+ <p class="thread-new">
+ <a href="{% url "message_new" mlist_fqdn=mlist.name %}"
+ class="thread-new btn{% if not user.is_authenticated %} disabled" title="You must be logged-in to create a thread.{% endif %}">
+ <strong>+</strong> Start a new thread</a>
+ </p>
+
+ <h3>Activity Summary</h3>
+ <p>The following statistics are from the past <strong>30</strong> days:</p>
+ <ul class="list-stats">
+ <li><span class="participant">{{ num_participants }} participants</span></li>
+ <li><span class="discussion">{{ num_threads }} discussions</span></li>
+ </ul>
+
+ <section id="discussion-maker" class="widget">
+ <h3>Most active posters</h3>
+ {% for poster in top_posters %}
+ <div class="maker">
+ <div class="inline-block maker-id">
+ #{{forloop.counter}}
+ </div>
+ <div class="inline-block gravatar">
+ {% gravatar poster.email 40 %}
+ <br />
+ </div>
+ <div class="inline-block">
+ <span class="maker-name">{{ poster.name }}</span>
+ <span class="score">{{ poster.count }}</span> posts
+ </div>
+ </div>
+ {% endfor %}
+ </section>
+
+ <!-- <div id="fig"></div> -->
+ </section>
+ </section>
+
+ <section id="discussions">
+
+ <section id="most-active" class="widget">
+ <h3>Recently active discussions</h3>
+ {% for thread in most_active_threads %}
+ {% include "threads/summary_thread.html" %} <!-- cut - with counter=forloop.counter -->
+ {% endfor %}
+ </section>
+
+ <section id="popular-threads" class="widget">
+ <h3>Most popular discussions</h3>
+ {% for thread in pop_threads %}
+ {% include "threads/summary_thread.html" with counter=forloop.counter %}
+ {% empty %}
+ <p>No vote has been cast this month (yet).</p>
+ {% endfor %}
+ </section>
+
+ <section id="top-discussion" class="widget">
<h3>Most active discussions</h3>
{% for thread in top_threads %}
{% include "threads/summary_thread.html" with counter=forloop.counter %}
@@ -129,8 +134,7 @@
</section>
{% endif %}
- </div>
- </div>
+ </section>
</section>
@@ -141,6 +145,7 @@
{% block additionaljs %}
<script type="text/javascript" >
+/*
$(function() {
activity_graph(
"#fig",
@@ -149,6 +154,16 @@
"{{ archives_baseurl }}"
)
});
+*/
+
+ $(function() {
+ chart(
+ "#chart",
+ ["{{days|join:'","'}}"],
+ {{evolution}},
+ "{{ archives_baseurl }}"
+ )
+ });
</script>
{% endblock %}
diff --git a/hyperkitty/templates/threads/summary_thread.html b/hyperkitty/templates/threads/summary_thread.html
index 2176936..e9b2b1f 100644
--- a/hyperkitty/templates/threads/summary_thread.html
+++ b/hyperkitty/templates/threads/summary_thread.html
@@ -3,21 +3,23 @@
{% load storm %}
<div class="thread">
- {% if counter %}<span class="thread-id">#{{counter}}</span>{% endif %}
- <span class="thread-title"><a name="{{thread.thread_id}}"
+ <span class="thread-title">
+ {% if counter %}<span class="thread-id">#{{counter}}</span>{% endif %}
+ <a name="{{thread.thread_id}}"
href="{% url 'thread' threadid=thread.thread_id mlist_fqdn=mlist.name %}"
- >{{ thread.subject|strip_subject:mlist }}</a>
- {% if thread.unread %}
+ >
+ {% if thread.category %}
+ <span class="label category" style="background-color:{{thread.category.color}}">
+ {{ thread.category.name|upper }}
+ </span>
+ {% endif %}
+ {% if thread.unread %}
<i class="unread icon-eye-close" title="New messages in this thread"></i>
{% endif %}
+ {{ thread.subject|strip_subject:mlist }}</a>
</span>
<div class="thread-stats">
<ul class="inline-block">
- {% if thread.category %}
- <span class="label category" style="background-color:{{thread.category.color}}">
- {{ thread.category.name|upper }}
- </span>
- {% endif %}
<li class="participant">
{{ thread.participants|length }}
</li>
diff --git a/hyperkitty/templatetags/storm.py b/hyperkitty/templatetags/storm.py
index b2112d2..0195dc7 100644
--- a/hyperkitty/templatetags/storm.py
+++ b/hyperkitty/templatetags/storm.py
@@ -33,3 +33,7 @@ def count(expr):
@register.filter(name="strip_subject")
def strip_subject(subject, mlist):
return stripped_subject(mlist, subject)
+
+@register.filter(name="shorten_list_name")
+def shorten_list_name(mlist):
+ return mlist.name.title().split('@')[0]