diff options
author | Aurélien Bompard <aurelien@bompard.org> | 2013-07-31 09:12:12 +0200 |
---|---|---|
committer | Aurélien Bompard <aurelien@bompard.org> | 2013-08-02 10:54:14 +0200 |
commit | f7521efee66e5297528f52290b670df6c2ddb2aa (patch) | |
tree | aa265d38a7957244f771fc1067e127aca7d3c015 /hyperkitty | |
parent | 36555737b8773b765cbeb81a2417eb431d2da008 (diff) | |
download | hyperkitty-f7521efee66e5297528f52290b670df6c2ddb2aa.tar.gz hyperkitty-f7521efee66e5297528f52290b670df6c2ddb2aa.tar.xz hyperkitty-f7521efee66e5297528f52290b670df6c2ddb2aa.zip |
Add User profiles
Diffstat (limited to 'hyperkitty')
-rw-r--r-- | hyperkitty/models.py | 7 | ||||
-rw-r--r-- | hyperkitty/static/hyperkitty/css/hyperkitty-message.css | 9 | ||||
-rw-r--r-- | hyperkitty/static/hyperkitty/css/hyperkitty-user.css | 5 | ||||
-rw-r--r-- | hyperkitty/templates/messages/message.html | 9 | ||||
-rw-r--r-- | hyperkitty/templates/user_public_profile.html | 80 | ||||
-rw-r--r-- | hyperkitty/urls.py | 2 | ||||
-rw-r--r-- | hyperkitty/views/accounts.py | 75 |
7 files changed, 176 insertions, 11 deletions
diff --git a/hyperkitty/models.py b/hyperkitty/models.py index ac7e091..f734952 100644 --- a/hyperkitty/models.py +++ b/hyperkitty/models.py @@ -29,14 +29,9 @@ from paintstore.fields import ColorPickerField class Rating(models.Model): - # @TODO: instead of list_address, user list model from kittystore? list_address = models.CharField(max_length=255, db_index=True) - - # @TODO: instead of messsageid, use message model from kittystore? messageid = models.CharField(max_length=100, db_index=True) - user = models.ForeignKey(User) - vote = models.SmallIntegerField() def __unicode__(self): @@ -65,9 +60,7 @@ class UserProfile(models.Model): class Tag(models.Model): - # @TODO: instead of list_address, user list model from kittystore? list_address = models.CharField(max_length=255, db_index=True) - # @TODO: instead of threadid, use thread model from kittystore? threadid = models.CharField(max_length=100, db_index=True) user = models.ForeignKey(User) tag = models.CharField(max_length=255) diff --git a/hyperkitty/static/hyperkitty/css/hyperkitty-message.css b/hyperkitty/static/hyperkitty/css/hyperkitty-message.css index 2f76e4e..4efd882 100644 --- a/hyperkitty/static/hyperkitty/css/hyperkitty-message.css +++ b/hyperkitty/static/hyperkitty/css/hyperkitty-message.css @@ -199,7 +199,6 @@ .email-header .gravatar { margin-right: 10px; display: inline-block; - vertical-align: middle; } .email-author .name{ @@ -211,6 +210,14 @@ font-size: 80%; font-weight: bold; } +.email-author .messagelink { + font-style: italic; + font-size: 90%; + color: rgb(167, 169, 172); +} +.email-author .messagelink a { + color: rgb(167, 169, 172); +} .email-first .email-date { text-align: right; diff --git a/hyperkitty/static/hyperkitty/css/hyperkitty-user.css b/hyperkitty/static/hyperkitty/css/hyperkitty-user.css index 17b1fa9..23a8c2c 100644 --- a/hyperkitty/static/hyperkitty/css/hyperkitty-user.css +++ b/hyperkitty/static/hyperkitty/css/hyperkitty-user.css @@ -91,3 +91,8 @@ table.user-data input { margin-left: 0; position: absolute; } + + +#user-profile table.subscriptions { + width: auto; +} diff --git a/hyperkitty/templates/messages/message.html b/hyperkitty/templates/messages/message.html index 453e248..7140d75 100644 --- a/hyperkitty/templates/messages/message.html +++ b/hyperkitty/templates/messages/message.html @@ -28,9 +28,14 @@ </div> <div class="email-author inline-block"> <span class="name"><a - href="{% url 'message_index' mlist_fqdn=mlist.name message_id_hash=email.message_id_hash %}" - title="{{ email.subject }}" + href="{% url 'public_user_profile' email=email.sender_email %}" + title="See {{ email.sender_name|escapeemail|escape }}'s profile" >{{email.sender_name|escapeemail}}</a></span> + <br /> + <span class="messagelink"> + (<a href="{% url 'message_index' mlist_fqdn=mlist.name message_id_hash=email.message_id_hash %}" + title="{{ email.subject }}">permalink</a>) + </span> {% if use_mockups %} <br /> <span class="rank"> diff --git a/hyperkitty/templates/user_public_profile.html b/hyperkitty/templates/user_public_profile.html new file mode 100644 index 0000000..b62002d --- /dev/null +++ b/hyperkitty/templates/user_public_profile.html @@ -0,0 +1,80 @@ +{% extends "base.html" %} +{% load url from future %} +{% load i18n %} +{% load hk_generic %} +{% load gravatar %} + + +{% block title %} +{% trans 'User Profile' %} for {{ email }} - {{ app_name|title }} +{% endblock %} + +{% block content %} + +<div id="user-profile"> + + <h1>User profile <small>for {{ email }}</small></h1> + + <table class="table table-bordered table-striped user-data"> + <tbody> + <tr> + <th>{% trans 'Name:' %}</th> + <td>{{ fullname }}</td> + </tr> + <tr> + <th>{% trans 'Email:' %}</th> + <td>{{ email }}</td> + </tr> + {% if creation %} + <tr> + <th>{% trans 'Creation:' %}</th> + <td>{{ creation|date:"l, j F Y H:i:s" }} ({{ creation|timesince }})</td> + </tr> + {% endif %} + <tr> + <th>{% trans 'Votes for this user:' %}</th> + <td><span class="likestatus {{ likestatus }}">+{{ likes }}/-{{ dislikes }}</span></td> + </tr> + </tbody> + </table> + + <h3>Subscriptions</h3> + {% if subscriptions %} + <table class="table table-striped table-bordered table-condensed subscriptions"> + <thead> + <tr> + <th>List</th> + <th>Time of first activity</th> + <th>First post</th> + <th>Posts to this list</th> + <th>Votes</th> + </tr> + </thead> + <tbody> + {% for sub in subscriptions %} + <tr> + <td> + <a href="{% url 'list_overview' sub.list_name %}">{{ sub.list_name }}</a> + </td> + {% if sub.first_post %} + <td> + {{ sub.first_post|get_date|date:"l, j F Y H:i:s" }} + {{ sub.first_post|get_date|timesince }} + </td> + <td>{{ sub.first_post.subject }}</td> + <td><a href="{{ sub.all_posts_url }}">{{ sub.posts_count }} post{{ sub.posts_count|pluralize }}</a></td> + <td><span class="likestatus {{ sub.likestatus }}">+{{ sub.likes }}/-{{ sub.dislikes }}</span></td> + {% else %} + <td colspan="4" style="text-align:center"><em>no post yet</em></td> + {% endif %} + </tr> + {% endfor %} + </tbody> + </table> + {% else %} + <p><em>no subscriptions</em></p> + {% endif %} + +</div> + +{% endblock %} diff --git a/hyperkitty/urls.py b/hyperkitty/urls.py index 9dfe63c..3cc24e5 100644 --- a/hyperkitty/urls.py +++ b/hyperkitty/urls.py @@ -50,6 +50,8 @@ urlpatterns = patterns('hyperkitty.views', url(r'^accounts/profile/votes$', 'accounts.votes', name='user_votes'), url(r'^accounts/register/$', 'accounts.user_registration', {'SSL': True}, name='user_registration'), + # Users + url(r'^user/(?P<email>[^/@]+@[^/@]+)/$', 'accounts.public_profile', name='public_user_profile'), # List archives and overview url(r'^list/(?P<mlist_fqdn>[^/@]+@[^/@]+)/(?P<year>\d{4})/(?P<month>\d\d?)/(?P<day>\d\d?)/$', diff --git a/hyperkitty/views/accounts.py b/hyperkitty/views/accounts.py index 373390b..5d7a9fc 100644 --- a/hyperkitty/views/accounts.py +++ b/hyperkitty/views/accounts.py @@ -20,6 +20,7 @@ # import logging +from urllib2 import HTTPError from django.conf import settings from django.core.urlresolvers import reverse @@ -29,10 +30,12 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.contrib.auth.views import login as django_login_view from django.shortcuts import render, redirect -from django.utils.http import is_safe_url +from django.utils.http import is_safe_url, urlquote from django.utils.timezone import utc, get_current_timezone +from django.http import Http404 #from django.utils.translation import gettext as _ from social_auth.backends import SocialAuthBackend +import dateutil.parser from hyperkitty.models import UserProfile, Rating, Favorite, LastView from hyperkitty.views.forms import RegistrationForm, UserProfileForm @@ -203,3 +206,73 @@ def votes(request): return render(request, 'ajax/votes.html', { "votes": votes, }) + + +def public_profile(request, email): + from mailmanclient import Client, MailmanConnectionError + try: + client = Client('%s/3.0' % settings.MAILMAN_REST_SERVER, + settings.MAILMAN_API_USER, settings.MAILMAN_API_PASS) + mm_user = client.get_user(email) + except HTTPError: + raise Http404("No user with this email: %s" % email) + except MailmanConnectionError: + class EmptyMailmanUser: + created_on = None + subscription_list_ids = [] + mm_user = EmptyMailmanUser() + subscriptions = [] + store = get_store(request) + # Subscriptions + for mlist_id in mm_user.subscription_list_ids: + mlist = client.get_list(mlist_id).fqdn_listname + # de-duplicate subscriptions + if mlist in [ s["list_name"] for s in subscriptions ]: + continue + email_hashes = store.get_message_hashes_by_sender(email, mlist) + try: # Compute the average vote value + votes = Rating.objects.filter(list_address=mlist, + messageid__in=email_hashes) + except Rating.DoesNotExist: + votes = [] + likes = dislikes = 0 + for v in votes: + if v.vote == 1: + likes += 1 + elif v.vote == -1: + dislikes += 1 + all_posts_url = "%s?list=%s&query=sender:%s" % \ + (reverse("search"), mlist, urlquote(email)) + likestatus = "neutral" + if likes - dislikes >= 10: + likestatus = "likealot" + elif likes - dislikes > 0: + likestatus = "like" + subscriptions.append({ + "list_name": mlist, + "first_post": store.get_first_post(mlist, email), + "likes": likes, + "dislikes": dislikes, + "likestatus": likestatus, + "all_posts_url": all_posts_url, + "posts_count": len(email_hashes), + }) + likes = sum([s["likes"] for s in subscriptions]) + dislikes = sum([s["dislikes"] for s in subscriptions]) + likestatus = "neutral" + if likes - dislikes >= 10: + likestatus = "likealot" + elif likes - dislikes > 0: + likestatus = "like" + context = { + "email": email, + "fullname": store.get_sender_name(email), + "mm_user": mm_user, + "creation": dateutil.parser.parse(mm_user.created_on), + "subscriptions": subscriptions, + "posts_count": sum([s["posts_count"] for s in subscriptions]), + "likes": likes, + "dislikes": dislikes, + "likestatus": likestatus, + } + return render(request, "user_public_profile.html", context) |