diff --git a/apps/users/templates/users/impala/profile.html b/apps/users/templates/users/impala/profile.html new file mode 100644 index 0000000000..4636aa8a0d --- /dev/null +++ b/apps/users/templates/users/impala/profile.html @@ -0,0 +1,77 @@ +{% extends "impala/base.html" %} + +{% block title %}{{ page_title(_('User Info for {0}')|f(profile.name)) }}{% endblock %} +{% block js %}{% include("amo/recaptcha_js.html") %}{% endblock %} +{% block bodyclass %}meet gutter{% endblock %} + +{% block content %} + +{% include "messages.html" %} + +{{ impala_breadcrumbs([(None, profile.name)]) }} +

{{ profile.name }}

+ +
+ +
+

{{ _('About Me')}}

+
+ {% with table_class='person-info' %} + {% include "users/impala/vcard.html" %} + {% endwith %} +
+
+ {% if profile.bio %} +

{{ _('In a little more detail...') }}

+

{{ profile.bio|nl2br }}

+ {% endif %} +
+
+
+ +{% if addons.object_list %} +
+

{{ _("Add-ons I've created") }}

+ {% cache addons.object_list %} + {{ impala_addon_listing_items(addons.object_list, src='category', + show_date=sorting) }} + {% endcache %} +
+{% endif %} + +{% cache reviews %} +
+

{{ _('My Reviews') }}

+
+ {% if reviews %} + {% for review in reviews %} + {% set addon = review.addon %} + {% include "reviews/impala/review.html" %} + {% endfor %} + {% else %} +

{{ _('No add-on reviews yet.') }}

+ {% endif %} +
{# /article #} +
{# /primary #} +{% endcache %} + +{% if abuse_form %} +
{{ user_report_abuse(hide=True, profile=profile) }}
+{% endif %} + + +{% endblock %} diff --git a/apps/users/urls.py b/apps/users/urls.py index e790fba900..64efa9b63c 100644 --- a/apps/users/urls.py +++ b/apps/users/urls.py @@ -20,6 +20,10 @@ detail_patterns = patterns('', url('^abuse', views.report_abuse, name='users.abuse'), ) +impala_detail_patterns = patterns('', + url('^$', views.impala_profile, name='i_users.profile'), +) + impala_users_patterns = patterns('', url('^edit$', views.edit_impala, name='users.edit_impala'), url('^edit(?:/(?P\d+))?$', views.admin_edit_impala, @@ -52,6 +56,7 @@ users_patterns = patterns('', urlpatterns = patterns('', # URLs for a single user. + ('^i/user/(?P\d+)/', include(impala_detail_patterns)), ('^user/(?P\d+)/', include(detail_patterns)), ('^i/users/', include(impala_users_patterns)), ('^users/', include(users_patterns)), diff --git a/apps/users/views.py b/apps/users/views.py index 611fc7521b..fe2bbca42a 100644 --- a/apps/users/views.py +++ b/apps/users/views.py @@ -459,6 +459,51 @@ def profile(request, user_id): return jingo.render(request, 'users/profile.html', data) +def impala_profile(request, user_id): + """user profile display page""" + user = get_object_or_404(UserProfile, id=user_id) + + # get user's own and favorite collections, if they allowed that + if user.display_collections: + own_coll = (Collection.objects.listed().filter(author=user) + .order_by('-created'))[:10] + else: + own_coll = [] + if user.display_collections_fav: + fav_coll = (Collection.objects.listed() + .filter(following__user=user) + .order_by('-following__created'))[:10] + else: + fav_coll = [] + + edit_any_user = acl.action_allowed(request, 'Admin', 'EditAnyUser') + own_profile = request.user.is_authenticated() and ( + request.amo_user.id == user.id) + + if user.is_developer: + addons = amo.utils.paginate( + request, + user.addons_listed.order_by('-weekly_downloads')) + else: + addons = [] + + def get_addons(reviews): + if not reviews: + return + qs = Addon.objects.filter(id__in=set(r.addon_id for r in reviews)) + addons = dict((addon.id, addon) for addon in qs) + for review in reviews: + review.addon = addons.get(review.addon_id) + reviews = user.reviews.transform(get_addons) + + data = {'profile': user, 'own_coll': own_coll, 'reviews': reviews, + 'fav_coll': fav_coll, 'edit_any_user': edit_any_user, + 'addons': addons, 'own_profile': own_profile, + 'abuse_form': AbuseForm(request=request)} + + return jingo.render(request, 'users/impala/profile.html', data) + + @anonymous_csrf def register(request): if request.user.is_authenticated(): diff --git a/media/css/impala/listing.less b/media/css/impala/listing.less index 7d1290181e..a549a1133a 100644 --- a/media/css/impala/listing.less +++ b/media/css/impala/listing.less @@ -46,7 +46,7 @@ header .feed { } } -.listing .primary .item { +.listing .item { border-top: 1px dotted @border-blue; color: @note-gray; display: table; diff --git a/media/css/impala/site.less b/media/css/impala/site.less index 609aa7009c..0a888b76ec 100644 --- a/media/css/impala/site.less +++ b/media/css/impala/site.less @@ -49,9 +49,10 @@ a { border-bottom: 0; } } - &.hero { - width: 720px; - } +} + +header + .island { + margin-top: 1em; } .primary { @@ -68,6 +69,9 @@ a { .secondary { float: right; } + .island.hero { + width: 720px; + } } .html-rtl.gutter .primary { diff --git a/media/css/impala/users.less b/media/css/impala/users.less index 6687391620..827c354181 100644 --- a/media/css/impala/users.less +++ b/media/css/impala/users.less @@ -72,6 +72,12 @@ table.person-info { img.avatar { border: 3px solid #fff; } +.user-role { + font-weight: bold; + color: @dark-gray; + margin: 0 4px 1em; + text-align: center; +} img.icon { padding: 4px; diff --git a/media/js/impala/addon_details.js b/media/js/impala/addon_details.js index c8c26b4f26..9b58b21c4f 100644 --- a/media/js/impala/addon_details.js +++ b/media/js/impala/addon_details.js @@ -1,22 +1,20 @@ $(function () { - if ($('body').hasClass('listing')) { - $('.performance-note .popup').each(function(i,p) { - var $p = $(this), - $a = $p.siblings('a').first(); - $p.popup($a, {width: 300, pointTo: $a}); - }); - $('.item.addon').each(function(i,p){ - var $this = $(this); - if ($this.find('.concealed').length == $this.find('.button').length) { - $this.addClass('incompatible'); - } - }); - $(document.body).bind('newStatic', function() { - $('.install-note:visible').closest('.item').addClass('static'); - }).bind('closeStatic', function() { - $('.item.static').removeClass('static'); - }); - } + $('.performance-note .popup').each(function(i,p) { + var $p = $(this), + $a = $p.siblings('a').first(); + $p.popup($a, {width: 300, pointTo: $a}); + }); + $('.item.addon').each(function(i,p){ + var $this = $(this); + if ($this.find('.concealed').length == $this.find('.button').length) { + $this.addClass('incompatible'); + } + }); + $(document.body).bind('newStatic', function() { + $('.install-note:visible').closest('.item').addClass('static'); + }).bind('closeStatic', function() { + $('.item.static').removeClass('static'); + }); if (!$("body").hasClass('addon-details')) return; $(".previews").zCarousel({