impala homepage, now with more homepage

This commit is contained in:
Matt Claypotch 2011-04-26 15:58:20 -07:00
Родитель 2ea94f49e4
Коммит 6a96536a48
17 изменённых файлов: 535 добавлений и 278 удалений

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

@ -6,6 +6,7 @@ from jingo import register, env
from tower import ugettext as _
from . import buttons
from amo.utils import chunked
import amo
@ -133,14 +134,15 @@ def addon_listing_header(context, url_base, sort_opts, selected):
@register.filter
@jinja2.contextfilter
@register.inclusion_tag('addons/impala/addon_grid.html')
def addon_grid(context, addons, src=None):
def addon_grid(context, addons, src=None, pagesize=6):
pages = chunked(addons, pagesize)
return new_context(**locals())
@register.filter
@jinja2.contextfilter
@register.inclusion_tag('addons/impala/toplist.html')
def addon_toplist(context, addons, vital=None, src=None):
def addon_toplist(context, addons, vital='users', src=None):
return new_context(**locals())

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

@ -1,24 +1,33 @@
{% cache addons %}
<ul class="addon-grid c">
{% for addon in addons %}
<li>
<div class="item">
<a href="{{ addon.get_url_path() }}">
<div class="icon">
<img src="{{ addon.icon_url }}">
{% for page in pages %}
{% set first_page = loop.first %}
<section>
{% for addon in page %}
<li>
<div class="item">
<a href="{{ addon.get_url_path() }}">
<div class="icon">
{% if first_page %}
<img src="{{ addon.icon_url }}">
{% else %}
<img data-defer-src="{{ addon.icon_url }}">
{% endif %}
</div>
<div class="summary">
<h3>{{ addon.name }}</h3>
<div class="category" class="more-info">{{ addon.get_category(APP.id) }}</div>
<div class="rating">{{ addon.average_rating|stars }} ({{ addon.total_reviews|numberfmt }})</div>
</div>
</a>
<div class="more">
{{ install_button(addon) }}
{{ addon.summary|truncate(250)|nl2br }}
</div>
<div class="summary">
<h3>{{ addon.name }}</h3>
<div class="category" class="more-info">{{ addon.get_category(APP.id) }}</div>
<div class="rating">&#x2605;&#x2605;&#x2605;&#x2605;&#x2605;</div>
</div>
</a>
<div class="more">
{{ addon.summary|truncate(250)|nl2br }}
{{ install_button(addon) }}
</div>
</div>
</li>
</li>
{% endfor %}
</section>
{% endfor %}
</ul>
{% endcache %}

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

@ -27,7 +27,7 @@
</section>
<section class="primary" id="homepage">
<div class="island">
<div id="promos" class="island">
<h1>Promos</h1>
Morbi laoreet, lorem nec volutpat ullamcorper, mauris dui vulputate nulla, sed aliquet ipsum diam euismod tellus. Fusce congue adipiscing quam eget posuere. Mauris in ipsum ut dui varius eleifend et placerat erat. Nulla pretium elementum nulla hendrerit dapibus. Sed in commodo mauris. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sagittis egestas tortor a adipiscing. Pellentesque consequat consectetur porttitor. Praesent et dictum elit. Vestibulum vulputate porta hendrerit.<br>
Curabitur lobortis blandit consectetur. Phasellus ac eros quam. Mauris interdum molestie magna, in vehicula nisi laoreet in. Aenean et convallis mi. Phasellus lobortis tempus felis, vel tincidunt ante aliquam id. Ut lectus eros, tincidunt vitae porta eget, vestibulum non mauris. Curabitur venenatis fringilla tortor sed pulvinar. Vivamus turpis nibh, facilisis auctor aliquet id, iaculis eu arcu. Maecenas vestibulum volutpat elit eget euismod.
@ -37,11 +37,14 @@
{{ popular|addon_toplist }}
</section>
<section class="primary">
{% for key, addons in addon_sets.items() %}
<div id="list-{{ key }}" class="island">
{{ addons|addon_grid }}
</div>
{% endfor %}
<div class="island">
<h2>{{ _('Featured Extensions') }}</h2>
{{ featured|addon_grid }}
</div>
<div class="island">
<h2>{{ _('Up &amp; Coming Extensions') }}</h2>
{{ hotness|addon_grid }}
</div>
</section>
</section>

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

@ -1,8 +1,9 @@
<ol class="toplist">
{% for addon in addons %}
<li><a href="{{ addon.get_url_path() }}">
<b>{{ loop.index }}.</b>
{{ addon.name }}
<br><span class="vital">999 users</span>
<small>{{ _('{0} users')|f(addon.average_daily_users|numberfmt) }}</small>
</a></li>
{% endfor %}
</ol>

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

@ -311,19 +311,20 @@ def home(request):
def impala_home(request):
# Add-ons.
base = Addon.objects.listed(request.APP).exclude(type=amo.ADDON_PERSONA)
filter = HomepageFilter(request, base, key='browse', default='featured')
addon_sets = dict((key, qs[:4]) for key, qs in filter.all().items())
# Collections.
q = Collection.objects.filter(listed=True, application=request.APP.id)
collections = q.order_by('-weekly_subscribers')[:3]
promobox = CollectionPromoBox(request)
featured = Addon.featured(request.APP, request.LANG)
featured = Addon.objects.filter(id__in=random.sample(featured, 18))
popular = Addon.objects.listed(request.APP).order_by('-weekly_downloads')[:10]
hotness = Addon.objects.listed(request.APP).order_by('-hotness')[:18]
return jingo.render(request, 'addons/impala/home.html',
{'popular': popular,
'filter': filter, 'addon_sets': addon_sets,
{'popular': popular, 'featured': featured,
'filter': filter, 'hotness': hotness,
'collections': collections, 'promobox': promobox})

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

@ -0,0 +1,48 @@
@import 'lib';
.pager {
font-family: @head-serif;
display: block;
.prev, .next {
height: 22px;
width: 22px;
margin: 0;
overflow: hidden;
text-indent: 0;
font-size: 20px;
.border-radius(0);
background: transparent;
color: lighten(@link, 20%);
&:hover {
color: darken(@link, 10%);
background: transparent;
}
}
a {
display: inline-block;
text-align: center;
margin: 4px 0;
overflow: hidden;
position: relative;
text-indent: -1000em;
vertical-align: bottom;
height: 8px;
width: 8px;
margin: 0 3px 6px;
.border-radius(4px);
background: #ddd;
&.selected {
background: #447BC4;
}
&:hover {
background: #888;
text-decoration: none;
}
}
}
.island .pager {
float: right;
}
.html-rtl .island .pager {
float: left;
}

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

@ -3,7 +3,7 @@
.amo-header {
font-family: @head-sans;
height: 120px;
margin-bottom: 25px;
margin-bottom: 15px;
}
.island {
@ -19,7 +19,7 @@
}
#masthead {
padding-top: 40px;
padding-top: 35px;
max-width: 600px;
}
@ -32,7 +32,8 @@
#aux-nav .context,
#aux-nav ul {
border-left: 1px solid #9FA7AF;
background: -moz-linear-gradient(#9FA7AF, fadeout(#9FA7AF, 100%)) no-repeat left top;
background-size: 1px 100%;
display: inline-block;
height: 32px;
line-height: 32px;
@ -41,7 +42,7 @@
.site-title img {
float: left;
margin-right: 12px;
margin-right: 10px;
}
.html-rtl .site-title img {
float: right;
@ -49,119 +50,115 @@
}
.site-title {
margin-bottom: 8px;
}
.site-title a {
color: #333;
text-decoration: none;
margin-bottom: 7px;
a {
color: #333;
text-decoration: none;
}
}
/** site navigation */
#site-nav {
font-size: 12px;
margin-left: 66px;
margin-left: 64px;
z-index: 50;
> ul {
> li {
float: left;
position: relative;
border-left: 1px solid #9FA7AF;
left: -9px;
> a {
position: relative;
font-weight: bold;
text-transform: uppercase;
z-index: 60;
padding: 4px 8px;
line-height: 12px;
border-style: solid;
.border-radius(3px 3px 0 0);
border-color: transparent;
border-width: 1px 1px 0;
}
&:hover {
> a {
background: #fff;
border-color: #98B2C9 #98B2C9 #fff;
.box-shadow(0 0 4px rgba(0, 0, 0, 0.4));
}
> ul {
display: block;
}
&:after {
content: "";
width: 100px;
z-index: 62;
height: 5px;
background: #fff;
position: absolute;
top: 18px;
left: 1px;
}
}
&:first-child {
border: 0;
}
> ul {
width: 190px;
position: absolute;
top: 17px;
z-index: 59;
padding: 8px;
display: none;
background: #fff;
border: 1px solid #98B2C9;
.border-radius(0 3px 3px);
.box-shadow(0 0 4px rgba(0, 0, 0, 0.4));
a {
text-decoration: none;
display: block;
padding: 6px 8px;
&:hover {
background: #ebf4fe;
}
}
&.two-col {
.columns(2, 8px);
width: 340px;
}
}
}
em a:hover {
background: #e1edfb;
}
}
hr {
border: 0;
margin: 6px 8px;
border-top: 1px dotted #ccc;
}
em {
background: #F4F8FC;
display: block;
font-weight: bold;
}
}
#site-nav > ul > li > a {
position: relative;
font-weight: bold;
text-transform: uppercase;
z-index: 60;
padding: 4px 8px;
line-height: 12px;
border-style: solid;
.border-radius(3px 3px 0 0);
border-color: transparent;
border-width: 1px 1px 0;
}
.html-rtl {
#site-nav > ul > li {
border-left: 0;
border-right: 1px solid #9FA7AF;
float: right;
left: auto;
right: -9px;
#site-nav > ul > li:hover > a {
background: #fff;
border-color: #98B2C9 #98B2C9 #fff;
.box-shadow(0 0 4px rgba(0, 0, 0, 0.4));
}
#site-nav > ul > li:hover:after {
content: "";
width: 100px;
z-index: 62;
height: 5px;
background: #fff;
position: absolute;
top: 18px;
left: 1px;
}
.html-rtl #site-nav > ul > li:hover:after {
left: auto;
right: 1px;
}
#site-nav > ul > li {
float: left;
position: relative;
border-left: 1px solid #9FA7AF;
left: -9px;
}
.html-rtl #site-nav > ul > li {
border-left: 0;
border-right: 1px solid #9FA7AF;
float: right;
left: auto;
right: -9px;
}
#site-nav > ul > li:first-child {
border: 0;
}
#site-nav > ul > li > ul {
width: 190px;
position: absolute;
top: 17px;
z-index: 59;
padding: 8px;
display: none;
background: #fff;
border: 1px solid #98B2C9;
.border-radius(0 3px 3px);
.box-shadow(0 0 4px rgba(0, 0, 0, 0.4));
}
#site-nav > ul > li:hover > ul {
display: block;
}
#site-nav > ul > li > ul.two-col {
.columns(2, 8px);
width: 340px;
}
#site-nav hr {
border: 0;
margin: 6px 8px;
border-top: 1px dotted #ccc;
}
#site-nav em {
background: #F4F8FC;
display: block;
font-weight: bold;
}
#site-nav > ul > li > ul a {
text-decoration: none;
display: block;
padding: 6px 8px;
}
#site-nav > ul ul a:hover {
background: #ebf4fe;
}
#site-nav > ul em a:hover {
background: #e1edfb;
&:hover:after {
left: auto;
right: 1px;
}
}
}
/** search box */

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

@ -1,117 +1,144 @@
@import 'lib';
.addon-grid li {
width: 50%;
height: 76px;
overflow: visible;
float: left;
}
.addon-grid .item {
position: relative;
margin: 5px 5px 5px 61px;
border: 1px solid transparent;
float: left;
z-index: 20;
}
.addon-grid .item h3 {
font-family: Georgia;
color: #447BC4;
margin: 0 0 2px 0;
font-weight: normal;
font-size: 14px;
line-height: 16px;
}
.addon-grid .category {
font-family: Georgia;
color: #666;
font-size: 12px;
line-height: 14px;
white-space: nowrap;
}
.addon-grid .item .more,
.addon-grid .item .summary,
.addon-grid .item .icon {
position: relative;
padding: 8px;
}
.addon-grid .item .more {
color: #666;
font-size: .9em;
display: none;
z-index: 29;
padding: 0 14px 8px 12px;
}
.addon-grid .item img {
margin: 8px;
width: 32px;
height: 32px;
border: 0;
padding: 0;
}
.addon-grid .item a {
display: block;
color: black;
text-decoration: none;
}
.addon-grid .item .summary {
height: 48px;
width: 182px;
z-index: 21;
overflow: hidden;
}
.addon-grid .item .summary h3,
.addon-grid .item .summary div {
white-space: nowrap;
}
.addon-grid .item .icon {
position: absolute;
left: -57px;
top: -1px;
padding-right: 0;
height: 48px;
width: 48px;
border-width: 1px 0 1px 1px;
border-style: solid;
z-index: 22;
border-color: transparent;
}
.addon-grid .item:before {
content: "";
display: block;
position: absolute;
height: 66px;
width: 56px;
top: -1px;
left: -57px;
z-index: 1;
}
.addon-grid .item:hover {
z-index: 25;
background: #fff;
border-color: #888;
.box-shadow(0 0 4px rgba(0,0,0,.4));
}
.addon-grid .item:hover .summary {
background: white;
z-index: 26;
}
.addon-grid .item:hover .icon {
background: #fff;
border-color: #888;
z-index: 27;
}
.addon-grid .item:hover:before {
.box-shadow(0 0 4px rgba(0,0,0,.4));
}
.addon-grid .item:hover .more {
background: #fff;
display: block;
z-index: 28;
}
.addon-grid .item:hover h3 {
text-decoration: underline;
}
.addon-grid .rating {
font-size: 14px;
color: #fc0;
.addon-grid {
li {
width: 50%;
overflow: visible;
float: left;
height: 66px;
}
.item {
position: relative;
margin: 5px 5px 5px 61px;
border: 1px solid transparent;
float: left;
z-index: 20;
h3 {
color: #447BC4;
font-weight: bold;
margin: 0 0 2px 0;
font-size: 13px;
line-height: 16px;
}
.more, .summary, .icon {
position: relative;
padding: 8px;
}
.more {
color: #666;
font-size: .9em;
display: none;
z-index: 29;
padding: 0 14px 8px 12px;
}
img {
margin: 8px;
width: 32px;
height: 32px;
border: 0;
padding: 0;
}
a {
display: block;
color: black;
text-decoration: none;
}
.summary {
height: 48px;
width: 182px;
z-index: 21;
overflow: hidden;
h3, div {
white-space: nowrap;
}
}
.icon {
position: absolute;
left: -57px;
top: -1px;
padding-right: 0;
height: 48px;
width: 48px;
border-width: 1px 0 1px 1px;
border-style: solid;
z-index: 22;
border-color: transparent;
}
&:before {
content: "";
display: block;
position: absolute;
height: 66px;
width: 56px;
top: -1px;
left: -57px;
z-index: 1;
}
&:hover {
z-index: 25;
background: #fff;
border-color: #888;
.box-shadow(0 0 4px rgba(0,0,0,.4));
.summary {
background: white;
z-index: 26;
}
.icon {
background: #fff;
border-color: #888;
z-index: 27;
}
&:before {
.box-shadow(0 0 4px rgba(0,0,0,.4));
}
.more {
background: #fff;
display: block;
z-index: 28;
}
h3 {
text-decoration: underline;
}
}
}
.category, .rating {
color: #666;
font-size: 11px;
line-height: 10px;
white-space: nowrap;
}
.rating {
margin-top: 4px;
font-size: 10px;
line-height: 12px;
}
section {
display: none;
&:first-child {
display: block;
}
}
}
.html-rtl .addon-grid {
li {
float: right;
}
.item {
margin: 5px 61px 5px 5px;
float: right;
.more {
padding: 0 12px 8px 14px;
}
.icon {
left: auto;
right: -57px;
padding-left: 0;
padding-right: 8px;
border-width: 1px 1px 1px 0;
}
&:before {
left: auto;
right: -57px;
}
}
}

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

@ -20,11 +20,15 @@
-moz-box-shadow: @shadow;
-webkit-box-shadow: @shadow;
}
.box-shadow(@shadow, @shadow2, @shadow3:0 0, @shadow4:0 0) {
box-shadow: @shadow, @shadow2, @shadow3, @shadow4;
-moz-box-shadow: @shadow, @shadow2, @shadow3, @shadow4;
-webkit-box-shadow: @shadow, @shadow2, @shadow3, @shadow4;
.box-shadow(@shadow, @shadow2) {
box-shadow: @shadow, @shadow2;
-moz-box-shadow: @shadow, @shadow2;
-webkit-box-shadow: @shadow, @shadow2;
}
.box-shadow(@shadow, @shadow2, @shadow3) {
box-shadow: @shadow, @shadow2, @shadow3;
-moz-box-shadow: @shadow, @shadow2, @shadow3;
-webkit-box-shadow: @shadow, @shadow2, @shadow3;
}
.columns(@count, @gap: 1em) {

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

@ -0,0 +1,20 @@
@import 'lib';
.stars {
display: inline-block;
vertical-align: middle;
width: 63px;
height: 12px;
background: url(../../img/impala/stars.png) no-repeat left top;
&.stars-4 { background-position: -13px 0; }
&.stars-3 { background-position: -26px 0; }
&.stars-2 { background-position: -39px 0; }
&.stars-1 { background-position: -52px 0; }
text-indent: -9999px;
margin-right: 4px;
}
.html-rtl .stars {
text-indent: 9999px;
margin-right: 0;
margin-left: 4px;
}

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

@ -4,6 +4,10 @@ html {
background: #fff url(../../img/zamboni/global/bg-header.png) left top repeat-x;
}
body {
border-top: 2px solid #686868;
}
#page {
max-width: 960px;
width: 960px;
@ -57,17 +61,18 @@ a {
.secondary {
ul, ol {
margin-bottom: 2em;
margin-bottom: 28px;
font-size: 12px;
}
li {
line-height: 28px;
border: 1px solid rgba(3, 48, 81, 0.2);
border-width: 0 0 1px 0;
&:first-child {
border-top-width: 1px;
}
a:hover {
background: #ECF5FE;
}
}
h2 {
font-size: 14px;
@ -75,5 +80,14 @@ a {
li a, h2 {
display: block;
padding: 0 6px;
text-decoration: none;
line-height: 28px;
}
}
#promos {
height: 270px;
max-height: 270px;
margin-bottom: 30px;
padding: 0;
}

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

@ -2,28 +2,35 @@
.toplist {
li {
list-style: decimal inside;
line-height: 1em;
white-space: nowrap;
height: 30px;
position: relative;
a {
vertical-align: top;
padding: 10px 0 10px 20px;
position: absolute;
top: 0;
line-height: 1.1em;
padding: .5em 0;
overflow: hidden;
&:hover {
small {
text-decoration: none;
}
}
}
&::-moz-list-number {
margin-top: 9px;
width: 1em;
text-align: right;
color: #444;
b {
float: left;
color: #888;
width: 2em;
text-align: center;
height: 2em;
}
}
.vital {
small {
color: @note-gray;
font-size: .9em;
display: block;
}
}
}
.html-rtl {
.toplist {
li b {
float: right;
}
}
}

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

@ -21,6 +21,7 @@ body {
h1 {
font-size: 40px;
font-family: MetaBlack;
letter-spacing: -1px;
text-transform: uppercase;
}
@ -28,8 +29,17 @@ pre, code, kbd, tt, samp, tt {
font-family: @mono-stack;
}
.island h2 {
color: #333;
font-family: @head-serif;
font-size: 18px;
font-style: italic;
margin-bottom: .5em;
}
.secondary h2 {
font-family: @head-sans;
font-family: @copy-stack;
font-weight: bold;
text-transform: uppercase;
color: #484848;
}

Двоичные данные
media/img/impala/stars.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

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

@ -0,0 +1,64 @@
//bind pager controls to our addon grids
$('.island .addon-grid').bind('grid.init', function(e, data) {
var $grid = data.self,
numPages = data.maxPage;
if (numPages > 1) {
var $nav = $('<nav class="pager">');
$nav.append('<a href="#" class="prev">&laquo;</a>');
for (var i=0; i<=numPages; i++) {
$nav.append('<a href="#" class="' + (i==0 ? 'selected ': '') + 'dot"></a>');
}
$nav.append('<a href="#" class="next">&raquo;</a>');
$grid.parents('.island').prepend($nav);
$nav.delegate('a', 'click', function(e) {
e.preventDefault();
var $tgt = $(this);
if ($tgt.hasClass('dot')) {
$grid.goto($tgt.index() - 1);
} else if ($tgt.hasClass('prev')){
$grid.prev();
} else if ($tgt.hasClass('next')){
$grid.next();
}
});
$grid.bind('grid.update', function(e, data) {
$nav.find('.dot').removeClass('selected')
.eq(data.current).addClass('selected');
});
}
});
$(function() {
"use strict";
$('.addon-grid').each(function() {
var $grid = $(this),
$pages = $grid.find('section'),
current = 0,
maxPage = $pages.length-1;
$grid.trigger("grid.init", {self: $grid, current: current, maxPage: maxPage});
$grid.goto = function(n) {
if (n != current) {
n = n < 0 ? 0 : (n > maxPage ? maxPage : n);
current = n;
$pages.hide().eq(n).show();
$grid.trigger("grid.update", {self: $grid, current: current, maxPage: maxPage})
}
};
$grid.prev = function() {
$grid.goto(current-1);
};
$grid.next = function() {
$grid.goto(current+1);
};
});
$("img[data-defer-src]").each(function() {
var $img = $(this);
$img.attr('src', $img.attr('data-defer-src'));
});
});

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

@ -390,6 +390,8 @@ MINIFY_BUNDLES = {
'css/impala/moz-tab.css',
'css/impala/hovercards.less',
'css/impala/toplist.less',
'css/impala/carousel.less',
'css/impala/reviews.less',
# 'css/zamboni/amo_headerfooter.css',
),
'zamboni/discovery-pane': (
@ -459,6 +461,54 @@ MINIFY_BUNDLES = {
# Hover delay for global header
'js/global/menu.js',
),
'impala': (
'js/lib/jquery-1.4.2.min.js',
'js/lib/jquery-ui/custom-1.8.5.min.js',
'js/lib/underscore-min.js',
'js/zamboni/browser.js',
'js/amo2009/addons.js',
'js/zamboni/init.js',
'js/zamboni/format.js',
'js/zamboni/buttons.js',
'js/zamboni/tabs.js',
'js/lib/jquery.cookie.js',
'js/zamboni/global.js',
'js/amo2009/global.js',
'js/lib/jquery-ui/jqModal.js',
'js/amo2009/home.js',
'js/zamboni/l10n.js',
'js/zamboni/storage.js',
# Homepage
'js/impala/homepage.js',
# Add-ons details page
'js/lib/jquery-ui/ui.lightbox.js',
'js/get-satisfaction-v2.js',
'js/zamboni/contributions.js',
'js/zamboni/addon_details.js',
'js/zamboni/reviews.js',
# Personas
'js/lib/jquery.hoverIntent.min.js',
'js/zamboni/personas.js',
# Collections
'js/zamboni/collections.js',
# Performance
'js/zamboni/perf.js',
# Users
'js/zamboni/users.js',
# Fix-up outgoing links
'js/zamboni/outgoing_links.js',
# Hover delay for global header
'js/global/menu.js',
),
'zamboni/discovery': (
'js/lib/jquery-1.4.2.min.js',
'js/lib/underscore-min.js',

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

@ -123,7 +123,7 @@
{# js #}
{% block site_js %}
<script src="{{ url('jsi18n') }}/build:{{ BUILD_ID_JS }}"></script>
{{ js('common') }}
{{ js('impala') }}
<script async defer src="{{ url('addons.buttons.js') }}/build:{{ BUILD_ID_JS }}"></script>
{% endblock %}
{% block js %}{% endblock %}