impala collections listing pages

This commit is contained in:
Chris Van 2011-07-14 14:50:10 -07:00
Родитель 9e87c057b4
Коммит f70023642e
23 изменённых файлов: 405 добавлений и 116 удалений

Просмотреть файл

@ -165,8 +165,8 @@ def addon_listing_items(context, addons, show_date=False,
@register.inclusion_tag('addons/impala/listing/items.html')
@jinja2.contextfunction
def impala_addon_listing_items(context, addons, show_date=False,
show_downloads=False, src=None, notes={}):
def impala_addon_listing_items(context, addons, show_date=False, src=None,
notes={}):
return new_context(**locals())

Просмотреть файл

@ -1,31 +1,47 @@
{% from "addons/impala/listing/macros.html" import heading, item_info %}
{% set collection = collection or None %}
{% set username = request.amo_user.username if request.user.is_authenticated() else '' %}
{% cache addons, extra=[collection, username] %}
{% cache addons %}
{% for addon in addons %}
<div class="item addon">
<div class="info">
{{ heading(request, addon, collection=collection) }}
<h3>
<a href="{{ addon.get_url_path(impala=True) }}">
<img src="{{ addon.icon_url }}">{{ addon.name }}</a>
{% if addon.is_no_restart() %}
<span class="no-restart">{{ _('No Restart') }}</span>
{% endif %}
{% if addon.is_featured(request.APP, request.LANG) %}
<span class="featured">{{ _('Featured') }}</span>
{% endif %}
</h3>
{% if addon.is_persona() %}
{{ persona_preview(addon.persona, linked=False) }}
{% else %}
<p class="desc">{{ addon.summary|truncate(250)|nl2br }}</p>
{% endif %}
{% if notes and notes[addon.id] %}
<div class="collector-note">
<b>{{ _("Collector's Note") }}</b>
{{ notes[addon.id] }}
<div class="vitals c">
{{ impala_reviews_link(addon) }}
<div class="adu">
{% with num=addon.average_daily_users %}
{# L10n: {0} is the number of users. #}
{{ ngettext('{0} user', '{0} users', num)|f(num|numberfmt) }}
{% endwith %}
</div>
{% endif %}
<div class="more c">
{{ item_info(addon, amo, show_date) }}
{% if show_date in ('created', 'new', 'newest', 'updated') %}
<div class="updated">
{% if show_date in ('created', 'new', 'newest') %}
{# L10n: {0} is a date. #}
{{ _('Added {0}')|f(addon.created|datetime) }}
{% elif show_date == 'updated' %}
{# L10n: {0} is a date. #}
{{ _('Updated {0}')|f(addon.last_updated|datetime) }}
{% endif %}
</div>
{% endif %}
</div>
{% if settings.PERF_THRESHOLD and addon.ts_slowness >= settings.PERF_THRESHOLD %}
{{ impala_performance_note(amount=addon.ts_slowness, listing=True) }}
{% endif %}
</div>
{{ install_button(addon, impala=True, collection=collection) }}
{{ install_button(addon, impala=True) }}
</div>
{% endfor %}
{% endcache %}

Просмотреть файл

@ -1,36 +0,0 @@
{% macro heading(request, addon, collection) %}
<h3>
{% if collection %}
{% set collection_path = '?src=collection&collection_id=' + collection.uuid %}
{% else %}
{% set collection_path = '' %}
{% endif %}
<a href="{{ addon.get_url_path(impala=True) + collection_path }}">
<img src="{{ addon.icon_url }}">{{ addon.name }}</a>
{% if addon.is_no_restart() %}
<span class="no-restart">{{ _('No Restart') }}</span>
{% endif %}
{% if addon.is_featured(request.APP, request.LANG) %}
<span class="featured">{{ _('Featured') }}</span>
{% endif %}
</h3>
{% endmacro %}
{% macro item_info(addon, amo, show_date) %}
{{ impala_reviews_link(addon) }}
<div class="adu">
{% with num=addon.average_daily_users %}
{# L10n: {0} is the number of users. #}
{{ ngettext('{0} user', '{0} users', num)|f(num|numberfmt) }}
{% endwith %}
</div>
{% if show_date in ('created', 'new', 'newest', 'updated') %}
<div class="updated">
{% if show_date in ('created', 'new', 'newest') %}
{{ _('Added {0}')|f(addon.created|datetime) }}
{% elif show_date == 'updated' %}
{{ _('Updated {0}')|f(addon.last_updated|datetime) }}
{% endif %}
</div>
{% endif %}
{% endmacro %}

Просмотреть файл

@ -1,9 +1,14 @@
{% if pager.paginator.num_pages > 1 %}
<nav class="paginator c">
<p class="num">
{# L10n: {0} is a page number. #}
<a href="{{ pager.url|urlparams(page=pager.number) }}">
{{ _('Page {0}')|f(pager.number) }}</a>
{# L10n: This is a page range (e.g., Page 1 of 50). #}
{% trans current_pg=pager.number,
last_pg=pager.paginator.num_pages,
current_pg_url=pager.url|urlparams(page=pager.number),
last_pg_url=pager.url|urlparams(page=pager.paginator.num_pages) %}
Page <a href="{{ current_pg_url }}">{{ current_pg }}</a> of
<a href="{{ last_pg_url }}">{{ last_pg }}</a>
{% endtrans %}
</p>
<p class="rel">
<a href="{{ pager.url|urlparams(page=1) }}"
@ -20,7 +25,7 @@
&#x25B8;&#x25B8;</a>
</p>
<p class="pos">
{# L10n: first and second arguments are the result range (e.g., 1-20);
{# L10n: First and second arguments are the result range (e.g., 1-20);
third argument is the number of total results (e.g., 1,000). #}
{% trans begin=pager.start_index(), end=pager.end_index(),
count=pager.paginator.count|numberfmt %}

Просмотреть файл

@ -21,6 +21,16 @@ def collection_listing_items(context, collections, show_weekly=False,
return c
@register.inclusion_tag('bandwagon/impala/collection_listing_items.html')
@jinja2.contextfunction
def impala_collection_listing_items(context, collections, show_weekly=False,
show_date=None):
c = dict(context.items())
c.update(collections=collections, show_weekly=show_weekly,
show_date=show_date)
return c
@register.function
def user_collection_list(collections=[], heading='', link=None):
"""list of collections, as used on the user profile page"""

Просмотреть файл

@ -1,7 +1,7 @@
<div class="barometer">
<form method="post" class="upvote" action="{{ up_action }}">
<input class="{{ up_class }}" value="{{ c.upvotes }}" type="submit"
title="{{ up_title }}"/>
title="{{ up_title }}">
</form>
<form method="post" class="downvote" action="{{ down_action }}">
<input class="{{ down_class }}" value="{{ c.downvotes }}" type="submit"
@ -12,13 +12,10 @@
<div class="collection-rate-dropdown install-note">
<div class="collection-rate-login">
<p>
{% trans %}
To rate collections, you must have an add-ons
account.
{% endtrans %}
{{ _('To rate collections, you must have an add-ons account.') }}
</p>
<p class="register-button">
<a class="button" href="{{ remora_url('users/register') }}">{{ _('Create an Add-ons Account') }}</a>
<a class="button" href="{{ url('users.register') }}">{{ _('Create an Add-ons Account') }}</a>
</p>
<p>
{% trans login=login_link() %}

Просмотреть файл

@ -0,0 +1,19 @@
{% extends "impala/base.html" %}
{% block title %}
{{ page_title(category.name if category else _('Extensions')) }}
{% endblock %}
{% block bodyclass %}collections listing s-{{ sorting }}{% endblock %}
{% set sort = {'featured': 'featured',
'created': 'newest',
'popular': 'popular',
'rating': 'averagerating'}.get(sorting, 'updated') %}
{% block content %}
<section class="secondary">
{% include "bandwagon/impala/collection_sidebar.html" %}
</section>
{% block primary %}{% endblock %}
{% endblock %}

Просмотреть файл

@ -0,0 +1,39 @@
{% extends "bandwagon/impala/base_collection.html" %}
{% set url_base = url('i_collections.list') %}
{% set title = {'featured': _('Featured Collections'),
'popular': _('Popular Collections'),
'created': _('Recently Added Collections'),
'rating': _('Top Rated Collections'),
'updated': _('Last Updated Collections')}.get(sorting) %}
{% block title %}{{ page_title(title) }}{% endblock %}
{% block primary %}
<section class="primary">
<div class="island hero c">
<header>
{% if request.GET %}
<h2>{{ title }}</h2>
{% else %}
<h2>{{ _('Collections') }}</h2>
<p>
{% trans url=url('collections.add') %}
Collections are groups of related add-ons that anyone can create and
share. Explore collections created by other users or
<a href="{{ url }}">create your own</a>.
{% endtrans %}
</p>
{% endif %}
{{ impala_addon_listing_header(url_base, filter.opts, sorting) }}
</header>
{{ impala_collection_listing_items(collections.object_list,
show_weekly=filter.field == 'popular',
show_date=filter.field) }}
{% if sorting != 'featured' %}
{{ collections|impala_paginator }}
{% endif %}
</div>
</section>
{% endblock %}

Просмотреть файл

@ -0,0 +1,49 @@
{% for c in collections %}
{% set is_watching = request.user.is_authenticated() and c.id in request.amo_user.watching %}
<div class="item{{ ' watching' if is_watching }}">
<div class="info">
<h3>
<a href="{{ c.get_url_path() }}">
<img src="{{ c.icon_url }}">{{ c.name }}</a>
{% if c.author %}
<span class="author">{{ _('by {0}')|f(c.author|user_link)|safe }}</span>
{% endif %}
</h3>
<p class="desc">{{ c.description|truncate(250)|nl2br }}</p>
<div class="vitals c">
<div class="followers">
{% if show_weekly %}
{% trans cnt=c.weekly_subscribers, num=c.weekly_subscribers|numberfmt %}
<span>{{ num }}</span> new follower
{% pluralize %}
<span>{{ num }}</span> new followers
{% endtrans %}
{% else %}
{# L10n: People "follow" collections to get notified of updates.
Like Twitter followers. #}
{% trans cnt=c.subscribers, num=c.subscribers|numberfmt %}
<span>{{ num }}</span> follower
{% pluralize %}
<span>{{ num }}</span> followers
{% endtrans %}
{% endif %}
</div>
{% if show_date in ('created', 'newest') %}
<div class="updated">
{# L10n: {0} is a date. #}
{{ _('Added {0}')|f(c.created|datetime) }}
</div>
{% endif %}
</div>
</div>
<div class="install-shell">
{% if request.user.is_authenticated() %}
{% if is_watching %}
<span class="is-watching">{{ _('Following') }}</span>
{% endif %}
<a href="{{ c.watch_url() }}" class="watch button">
<span>{{ _('Stop Following') if is_watching else _('Follow this Collection') }}</span></a>
{% endif %}
</div>
</div>
{% endfor %}

Просмотреть файл

@ -0,0 +1,43 @@
{% set base_url = url('i_collections.list') %}
<nav id="side-nav" class="c">
<h2><a href="{{ base_url }}">{{ _('Collections') }}</a></h2>
<ul>
{% for sort, title in filter.opts %}
<li class="s-{{ sort }}"><em><a href="{{ base_url|urlparams(sort=sort) }}">{{ title }}</a></em></li>
{% endfor %}
</ul>
{% if request.user.is_authenticated() %}
<ul>
<li id="p-following">
<a href="{{ url('collections.following') }}">
{{ _("Collections I'm Following") }}</a></li>
<li id="p-mine">
<a href="{{ url('collections.user', amo_user.username) }}">
{{ _("Collections I've Made") }}</a></li>
<li><a href="{{ url('collections.detail', amo_user.username, 'favorites') }}">
{{ _('My Favorite Add-ons') }}</a></li>
</ul>
{% endif %}
<section>
<h3>{{ _('Create a New Collection') }}</h3>
<p>{% trans %}
Collections make it easy to keep track of favorite add-ons and share your
perfectly customized browser with others.
{% endtrans %}</p>
<p><a href="{{ url('collections.add') }}" class="button">
{{ _('Create a Collection') }}</a></p>
</section>
<section id="recently-viewed">
<h3>{{ _('Recently Viewed') }}</h3>
</section>
<section>
<h3>{{ _('Add-on Collector') }}</h3>
<p>
{% trans app=request.APP.pretty %}
Get updates on followed collections or manage your own collections
directly from {{ app }} with this add-on.
{% endtrans %}
</p>
{{ addon_collector|addon_hovercard }}
</section>
</nav>

Просмотреть файл

@ -42,6 +42,9 @@ urlpatterns = patterns('',
{'edit': True}),
url('^collections/$', views.collection_listing, name='collections.list'),
url('^i/collections/$', views.impala_collection_listing,
name='i_collections.list'),
url('^collections/(editors_picks|popular|favorites)/?$',
views.legacy_directory_redirects),
url('^collections/mine/(?P<slug>[^/]+)?$', views.mine,

Просмотреть файл

@ -115,6 +115,17 @@ def collection_listing(request, base=None, extra={}):
collection_votes=votes, **extra))
def impala_collection_listing(request, base=None):
filter = get_filter(request, base)
collections = amo.utils.paginate(request, filter.qs)
votes = get_votes(request, collections.object_list)
addon_collector = Addon.objects.get(id=11950)
return render(request, 'bandwagon/impala/collection_listing.html',
dict(collections=collections, filter=filter,
sorting=filter.field, collection_votes=votes,
addon_collector=addon_collector))
def get_votes(request, collections):
if not request.user.is_authenticated():
return {}

Просмотреть файл

@ -24,10 +24,7 @@
{% set sort = {'featured': 'featured',
'created': 'newest',
'popular': 'popular',
'rating': 'averagerating'}[sorting] %}
{% if not sort %}
{% set sort = 'updated' %}
{% endif %}
'rating': 'averagerating'}.get(sorting, 'updated') %}
{% if category %}
{% set feed = url('browse.extensions.rss', category.slug) %}

Просмотреть файл

@ -27,10 +27,8 @@
<a href="{{ feed_url }}" class="feed">{{ _('Subscribe') }}</a>
{{ impala_addon_listing_header(url_base, extras, sorting) }}
</header>
{{ impala_addon_listing_items(addons.object_list, src='category',
show_date=sorting, show_downloads=sorting=='popular') }}
show_date=sorting) }}
{% if sorting != 'featured' %}
{{ addons|impala_paginator }}
{% endif %}

Просмотреть файл

@ -2,11 +2,8 @@
.button, button, input[type=submit] {
position: relative;
font-size: 13px;
font: bold 13px/1em @head-sans;
padding: 6px 10px 7px;
font-family: @head-sans;
font-weight: bold;
line-height: 1em;
text-align: center;
text-decoration: none;
color: #fff;
@ -91,6 +88,11 @@
.sprite-pos(6, 64, 3px);
}
}
&.watch:not(.watching) { // Orange
background: #ea0;
.gradient-two-color(#ea0, darken(#ea0, 10%));
color: #fff;
}
&.platform {
display: none;
}
@ -173,4 +175,3 @@
.thunderbird .listing-grid .install-shell {
display: none;
}

Просмотреть файл

@ -1,11 +1,11 @@
@import 'lib';
#ajax_collections_list {
margin: 0 0 .5em 0;
li {
cursor: pointer;
padding: 5px 0 3px 30px;
background-repeat: no-repeat;
background-position: 0 4px;
background-image: url(../../img/zamboni/icons/checks.png);
background: url(../../img/zamboni/icons/checks.png) no-repeat 0 4px;
}
li:hover {
background-position: 0 -36px;
@ -99,9 +99,65 @@
}
#collection_listed {
margin-bottom: 1.5em;
margin: 0 0 1.5em;
}
#collection_listed ul label {
font-weight: normal;
}
#recently-viewed {
ul {
margin: 0 0 4px;
}
h3 {
border: none;
margin: 0;
}
#clear-recents {
color: #666;
padding: 0 6px;
}
}
.listing .item {
&.watching {
.install-shell {
visibility: visible;
.is-watching {
display: block;
font-weight: bold;
float: right;
padding: 7px 10px;
position: absolute;
right: 25px;
text-align: right;
}
a {
visibility: hidden;
}
}
&:hover {
.install-shell {
.is-watching {
display: none;
}
a {
visibility: visible;
}
}
}
}
}
.secondary {
.listing-grid {
border: none;
li {
border: none;
}
.item.addon {
margin-left: 0;
}
}
}

Просмотреть файл

@ -5,6 +5,7 @@
@error-red: #C00000;
@orange: #D16B00;
@border-blue: #C9DDF2;
@green: #093;
// Font Stacks

Просмотреть файл

@ -47,7 +47,7 @@ header .feed {
}
}
.listing .item {
.listing .primary .item {
border-top: 1px dotted @border-blue;
color: @note-gray;
display: table;
@ -88,29 +88,40 @@ header .feed {
height: 32px;
width: 32px;
}
.author {
color: #666;
font-size: 12px;
a {
color: #333;
}
}
}
h3, .desc {
margin-bottom: 5px;
h3,
.desc {
margin: 0 0 5px;
}
p {
font-size: 12px;
margin: 0;
}
.rating a {
color: @note-gray;
}
.rating,
.adu,
.updated {
display: inline-block;
}
.adu {
color: #093;
}
.adu:before,
.updated:before {
color: @note-gray;
content: '\00B7';
.vitals {
margin-top: 2px;
div {
display: inline-block;
font-size: 11px;
margin: 0;
&.rating a {
color: @note-gray;
}
&.adu,
&.followers {
color: @green;
}
&.adu:before,
&.updated:before {
color: @note-gray;
content: '\00B7';
}
}
}
.info,
.install-shell {
@ -121,8 +132,8 @@ header .feed {
}
.install-shell {
text-align: right;
padding: 0 10px;
min-width: 190px;
padding: 0 10px;
visibility: hidden;
white-space: nowrap;
.install-note {
@ -146,7 +157,7 @@ header .feed {
}
}
.html-rtl .listing .item {
.html-rtl .listing .primary .item {
.collector-note,
.performance-note {
float: right;

Просмотреть файл

@ -8,11 +8,10 @@
float: left;
margin-top: 0;
white-space: nowrap;
}
.pos,
.num a {
color: #999;
font-size: 12px;
&.num a {
color: inherit;
}
}
.pos,
.num {
@ -34,7 +33,6 @@
}
}
.html-rtl .paginator {
p {
float: right;

Просмотреть файл

@ -97,7 +97,7 @@ a {
.html-rtl.gutter {
.secondary {
float: left;
float: left;
}
}
@ -106,12 +106,15 @@ a {
}
.secondary {
ul, ol {
margin-bottom: 28px;
ul, ol, section {
color: #666;
font-size: 12px;
line-height: 16px;
margin-bottom: 28px;
}
li {
border: 1px solid rgba(3, 48, 81, 0.2);
nav > ul li,
#recently-viewed li {
border: 1px solid fadeOut(#000, 80%);
border-width: 0 0 1px 0;
position: relative;
&:first-child {
@ -125,8 +128,6 @@ a {
a:hover {
background: #ECF5FE;
}
}
nav li {
a:after {
content: '\203a';
position: absolute;
@ -146,25 +147,53 @@ a {
}
h2 {
font-size: 14px;
a {
color: inherit;
}
}
li a, h2 {
nav > ul a,
#recently-viewed > ul a,
h2 {
display: block;
padding: 0 6px;
text-decoration: none;
line-height: 28px;
}
nav > ul a,
#recently-viewed a,
h2,
p {
padding: 0 6px;
}
section > h3 {
border-bottom: 1px solid fadeOut(#000, 80%);
color: #484848;
font-size: 12px;
font-weight: bold;
line-height: 14px;
margin-bottom: 8px;
padding: 0 6px 8px;
text-transform: uppercase;
}
p {
margin-bottom: 8px;
}
section section {
margin: 0;
}
}
.s-featured #side-nav .s-featured a,
.s-popular #side-nav .s-popular a,
.s-rating #side-nav .s-rating a {
.s-rating #side-nav .s-rating a,
.s-created #side-nav .s-created a {
background: #ecf5fe;
color: #333;
font-weight: bold;
}
.s-featured #side-nav .s-featured a:after,
.s-popular #side-nav .s-popular a:after,
.s-rating #side-nav .s-rating a:after {
.s-rating #side-nav .s-rating a:after,
.s-created #side-nav .s-created a:after {
color: inherit;
}

Просмотреть файл

@ -59,6 +59,15 @@ pre, code, kbd, tt, samp, tt {
color: #666;
line-height: 1.3em;
}
.install-note,
.popup {
p {
margin-top: 0;
&:last-child {
margin-bottom: 0;
}
}
}
}
.popup h3 {
color: #333;

Просмотреть файл

@ -0,0 +1,32 @@
$(function() {
if (!$(document.body).hasClass('collections')) {
return;
}
$('.watch').click(_pd(function() {
var $widget = $(this),
$parent = $widget.closest('.item');
if ($widget.hasClass('ajax-loading')) return;
$widget.addClass('ajax-loading');
var follow_text = gettext('Follow this Collection');
$.ajax({
url: $(this).attr('href'),
type: 'POST',
success: function(data) {
$parent.removeClass('watching');
$widget.removeClass('ajax-loading');
if (data.watching) {
$parent.addClass('watching');
follow_text = gettext('Stop following');
$('<span>', {text: gettext('Following'),
class: 'is-watching'}).insertBefore($widget);
} else {
$parent.find('.is-watching').remove();
}
$widget.text(follow_text);
},
error: function() {
$widget.removeClass('ajax-loading');
}
});
}));
});

Просмотреть файл

@ -429,11 +429,11 @@ MINIFY_BUNDLES = {
'css/impala/lightbox.less',
'css/impala/copy.less',
'css/impala/sharing.less',
'css/impala/collections.less',
'css/impala/abuse.less',
'css/impala/prose.less',
'css/impala/paginator.less',
'css/impala/listing.less',
'css/impala/collections.less',
),
'zamboni/discovery-pane': (
'css/zamboni/discovery-pane.css',
@ -552,6 +552,7 @@ MINIFY_BUNDLES = {
# Collections
'js/zamboni/collections.js',
'js/impala/collections.js',
# Performance
'js/zamboni/perf.js',