summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAurélien Bompard <aurelien@bompard.org>2013-06-18 16:30:38 +0200
committerAurélien Bompard <aurelien@bompard.org>2013-06-18 16:30:38 +0200
commit5924b67e6716be1530436dd986ddb941125fa5e3 (patch)
tree299f4e209b6f9a0f524375af527c49423077b698
parentc8f2ecc0476b0caf2c8a87033c5ffcdf6ac6263b (diff)
downloadhyperkitty-5924b67e6716be1530436dd986ddb941125fa5e3.tar.gz
hyperkitty-5924b67e6716be1530436dd986ddb941125fa5e3.tar.xz
hyperkitty-5924b67e6716be1530436dd986ddb941125fa5e3.zip
Add Top Posters and Popular Threads widgets to the overview
-rw-r--r--hyperkitty/lib/voting.py10
-rw-r--r--hyperkitty/static/css/hyperkitty-overview.css12
-rw-r--r--hyperkitty/templates/recent_activities.html52
-rw-r--r--hyperkitty/views/list.py25
4 files changed, 77 insertions, 22 deletions
diff --git a/hyperkitty/lib/voting.py b/hyperkitty/lib/voting.py
index 7d7cc64..8624d75 100644
--- a/hyperkitty/lib/voting.py
+++ b/hyperkitty/lib/voting.py
@@ -23,14 +23,16 @@
from hyperkitty.models import Rating
-def get_votes(message_id_hash, user=None):
+def get_votes(msgid, user=None):
"""Extract all the votes for this message"""
- likes = dislikes = 0
+ likes = dislikes = myvote = 0
try:
- votes = Rating.objects.filter(messageid=message_id_hash)
+ if isinstance(msgid, basestring):
+ votes = Rating.objects.filter(messageid=msgid)
+ elif isinstance(msgid, list):
+ votes = Rating.objects.filter(messageid__in=msgid)
except Rating.DoesNotExist:
votes = {}
- myvote = 0
for vote in votes:
if vote.vote == 1:
likes += 1
diff --git a/hyperkitty/static/css/hyperkitty-overview.css b/hyperkitty/static/css/hyperkitty-overview.css
index 7898764..e96f7a2 100644
--- a/hyperkitty/static/css/hyperkitty-overview.css
+++ b/hyperkitty/static/css/hyperkitty-overview.css
@@ -7,6 +7,13 @@
text-align: center;
}
+#recent_activities h3 {
+ font-size: 20px;
+ line-height: 28px;
+ margin-bottom: 0.5em;
+ text-align: center;
+}
+
#graph h2 {
text-align: center;
}
@@ -37,10 +44,7 @@
}
-#top-discussion,
-#discussion-by-topic,
-#most-active,
-#discussion-maker {
+#recent_activities .widget {
padding: 1em;
padding-bottom: 0;
border: 1px solid #ddd;
diff --git a/hyperkitty/templates/recent_activities.html b/hyperkitty/templates/recent_activities.html
index 5b175d6..fb22d92 100644
--- a/hyperkitty/templates/recent_activities.html
+++ b/hyperkitty/templates/recent_activities.html
@@ -33,8 +33,8 @@
<div class="row-fluid">
<div class="span6">
- <section id="most-active">
- <h2>Recently active discussions</h2>
+ <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 %}
@@ -42,8 +42,8 @@
</div>
<div class="span6">
- <section id="top-discussion">
- <h2>Top discussions the last 30 days</h2>
+ <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 %}
{% endfor %}
@@ -51,12 +51,44 @@
</div>
</div>
+
<div class="row-fluid">
+ <div class="span6">
+ <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">
+ <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 %}
+ {% endfor %}
+ </section>
+ </div>
+ </div>
+ <div class="row-fluid">
<div class="span6">
{% if top_author %}
- <section id="discussion-maker">
- <h2>Prominent discussion maker</h2>
+ <section id="discussion-maker" class="widget">
+ <h3>Prominent discussion maker</h3>
{% for author in top_author %}
<!-- Start discussion maker -->
<div class="maker">
@@ -78,7 +110,7 @@
<!-- End discussion maker -->
{% endfor %}
- <h2>Tag cloud</h2>
+ <h3>Tag cloud</h3>
</section>
{% endif %}
</div>
@@ -86,11 +118,11 @@
<div class="span6">
{% if threads_per_category %}
- <section id="discussion-by-topic">
- <h2>Discussion by topic the last 30 days</h2>
+ <section id="discussion-by-topic" class="widget">
+ <h3>Discussion by topic the last 30 days</h3>
{% for category, thread in threads_per_category.items %}
<div>
- <h2 class="category type_{{category}}"> {{category}} </h2>
+ <h3 class="category type_{{category}}"> {{category}} </h3>
<ul class="category_entry">
{% for email in thread %}
<li>
diff --git a/hyperkitty/views/list.py b/hyperkitty/views/list.py
index c1fda99..896edb2 100644
--- a/hyperkitty/views/list.py
+++ b/hyperkitty/views/list.py
@@ -175,17 +175,21 @@ def overview(request, mlist_fqdn=None):
mlist = store.get_list(mlist_fqdn)
if mlist is None:
raise Http404("No archived mailing-list by that name.")
- threads_result = store.get_threads(list_name=mlist.name, start=begin_date,
- end=end_date)
+ threads_result = store.get_threads(
+ list_name=mlist.name, start=begin_date, end=end_date)
threads = []
Thread = namedtuple('Thread', ["thread_id", "subject", "participants",
- "length", "date_active"])
+ "length", "date_active", "likes", "dislikes"])
participants = set()
for thread_obj in threads_result:
+ # Votes
+ # XXX: 1 SQL request per thread, possible optimization here
+ likes, dislikes, myvote = get_votes(thread_obj.email_id_hashes)
thread = Thread(thread_obj.thread_id, thread_obj.subject,
thread_obj.participants, len(thread_obj),
- thread_obj.date_active.replace(tzinfo=utc))
+ thread_obj.date_active.replace(tzinfo=utc),
+ likes, dislikes)
# Statistics on how many participants and threads this month
participants.update(thread.participants)
threads.append(thread)
@@ -205,6 +209,17 @@ def overview(request, mlist_fqdn=None):
else:
authors = []
+ # Top posters
+ top_posters = []
+ for poster in store.get_top_participants(list_name=mlist.name,
+ start=begin_date, end=end_date, limit=5):
+ top_posters.append({"name": poster[0], "email": poster[1],
+ "count": poster[2]})
+
+ # Popular threads
+ pop_threads = sorted(threads, key=lambda t: t.likes - t.dislikes,
+ reverse=True)[:5]
+
# List activity
# Use get_messages and not get_threads to count the emails, because
# recently active threads include messages from before the start date
@@ -238,6 +253,8 @@ def overview(request, mlist_fqdn=None):
'top_threads': top_threads[:5],
'most_active_threads': active_threads[:5],
'top_author': authors,
+ 'top_posters': top_posters,
+ 'pop_threads': pop_threads,
'threads_per_category': threads_per_category,
'months_list': get_months(store, mlist.name),
'evolution': evolution,