From 5924b67e6716be1530436dd986ddb941125fa5e3 Mon Sep 17 00:00:00 2001 From: Aurélien Bompard Date: Tue, 18 Jun 2013 16:30:38 +0200 Subject: Add Top Posters and Popular Threads widgets to the overview --- hyperkitty/lib/voting.py | 10 +++--- hyperkitty/static/css/hyperkitty-overview.css | 12 ++++--- hyperkitty/templates/recent_activities.html | 52 +++++++++++++++++++++------ hyperkitty/views/list.py | 25 ++++++++++--- 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 @@
-
-

Recently active discussions

+
+

Recently active discussions

{% for thread in most_active_threads %} {% include "threads/summary_thread.html" with counter=forloop.counter %} {% endfor %} @@ -42,8 +42,8 @@
-
-

Top discussions the last 30 days

+
+

Most active discussions

{% for thread in top_threads %} {% include "threads/summary_thread.html" with counter=forloop.counter %} {% endfor %} @@ -51,12 +51,44 @@
+
+
+
+

Most active posters

+ {% for poster in top_posters %} +
+
+ #{{forloop.counter}} +
+
+ {% gravatar poster.email 40 %} +
+
+
+ {{ poster.name }} +
+ {{ poster.count }} posts +
+
+ {% endfor %} +
+
+
+ +
+
+
{% if top_author %} -
-

Prominent discussion maker

+
+

Prominent discussion maker

{% for author in top_author %}
@@ -78,7 +110,7 @@ {% endfor %} -

Tag cloud

+

Tag cloud

{% endif %}
@@ -86,11 +118,11 @@
{% if threads_per_category %} -
-

Discussion by topic the last 30 days

+
+

Discussion by topic the last 30 days

{% for category, thread in threads_per_category.items %}
-

{{category}}

+

{{category}}

    {% for email in thread %}
  • 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, -- cgit