This commit is contained in:
Matt Claypotch 2011-05-04 15:01:16 -07:00
Родитель 2d36a61fd3
Коммит 5dc1cfe79f
50 изменённых файлов: 1286 добавлений и 160 удалений

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

@ -57,10 +57,34 @@ def performance_note(context, amount, listing=False):
return new_context(**locals())
@register.inclusion_tag('addons/impala/performance_note.html')
@jinja2.contextfunction
def impala_performance_note(context, amount, listing=False):
return new_context(**locals())
@register.inclusion_tag('addons/contribution.html')
@jinja2.contextfunction
def contribution(context, addon, text=None, src='', show_install=False,
show_help=True):
show_help=True, large=False):
"""
Show a contribution box.
Parameters:
addon
text: The begging text at the top of the box.
src: The page where the contribution link is coming from.
show_install: Whether or not to show the install button.
show_help: Show "What's this?" link?
"""
has_suggested = bool(addon.suggested_amount)
return new_context(**locals())
@register.inclusion_tag('addons/impala/contribution.html')
@jinja2.contextfunction
def impala_contribution(context, addon, text=None, src='', show_install=False,
show_help=True, large=False):
"""
Show a contribution box.

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

@ -346,7 +346,9 @@ class Addon(amo.models.OnChangeMixin, amo.models.ModelBase):
return urls
def get_url_path(self):
def get_url_path(self, impala=False):
if impala:
return reverse('addons.i_detail', args=[self.slug])
return reverse('addons.detail', args=[self.slug])
def meet_the_dev_url(self):

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

@ -6,7 +6,7 @@
{% for addon in page %}
<li>
<div class="item">
<a href="{{ addon.get_url_path() }}">
<a href="{{ addon.get_url_path(impala=True) }}">
<div class="icon">
{% if first_page %}
<img src="{{ addon.icon_url }}">

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

@ -0,0 +1,176 @@
{% if addon.charity %}
{% set charity_url = addon.charity.outgoing_url %}
{% set charity_name = addon.charity.name %}
{% endif %}
<div class="notice c" id="contribution">
<div class="aux{% if show_install %}-bottom{% endif %}">
<div class="button-wrapper">
<a class="button contribute prominent" id="contribute-button"
href="{{ url('addons.contribute', addon.slug)|urlparams(src=src) }}">
<b></b>{{ _('Contribute') }}
</a>
{% if show_install %}
{# L10n: Click Contribute button OR Install button #}
<span class="continue">{{ _('or') }}</span>
{% set ver = version or None %}
{{ install_button(addon, version=ver, show_contrib=False) }}
{% endif %}
</div>{# /button-wrapper #}
<p class="suggestion">
{% if has_suggested %}
{% trans amt = addon.suggested_amount|currencyfmt('USD') %}
<b>{{ amt }}</b> suggested
{% endtrans %}
{% endif %}
</p>{# /suggestion #}
</div>{# /aux #}
<h3>{{ _('Enjoy this add-on?') }}</h3>
<p class="{% if show_install %}show-install{% endif %}">
{% if text %}
{{ text }}
{% elif not addon.charity %}
{{ _('The developer of this add-on asks that you help support its '
'continued development by making a small contribution.') }}
{% elif addon.charity_id == amo.FOUNDATION_ORG %}
{% trans %}
The developer of this add-on asks that you show your support
by making a donation to the <a href="{{ charity_url }}">{{ charity_name }}</a>.
{% endtrans %}
{% else %}
{% trans %}
The developer of this add-on asks that you show your support
by making a small contribution to <a href="{{ charity_url }}">{{ charity_name }}</a>.
{% endtrans %}
{% endif %}
</p>
<div id="contribute-box" class="jqmWindow">
<form action="{{ url('addons.contribute', addon.slug) }}" method="get">
<input type="hidden" name="source" value="{{ request.GET.get('src', src) }}"/>
<h2>{{ _('Make a Contribution') }}</h2>
<p class="support">
{% with addon_name=addon.name, paypal_url='http://paypal.com' %}
{% if not addon.charity %}
{% trans %}
Help support the continued development of
<strong>{{ addon_name }}</strong> by making a small contribution
through <a href="{{ paypal_url }}">Paypal</a>.
{% endtrans %}
{% elif addon.charity_id == amo.FOUNDATION_ORG %}
{% trans %}
To show your support for <b>{{ addon_name }}</b>, the developer asks
that you make a donation to the <a href="{{ charity_url }}">{{ charity_name }}</a>
through <a href="{{ paypal_url }}">Paypal</a>.
{% endtrans %}
{% else %}
{% trans %}
To show your support for <b>{{ addon_name }}</b>, the developer asks
that you make a small contribution to <a href="{{ charity_url }}">{{ charity_name }}</a>
through <a href="{{ paypal_url }}">Paypal</a>.
{% endtrans %}
{% endif %}
{% endwith %}
</p>
<h4>{{ _('How much would you like to contribute?') }}</h4>
<div class="error" id="contrib-too-much"
data-max-amount="{{ settings.MAX_CONTRIBUTION }}">
{{ _('The maximum contribution amount is {0}.')|f(
settings.MAX_CONTRIBUTION|currencyfmt('USD')) }}
</div>
<div class="error" id="contrib-too-little">
{{ _('The minimum contribution amount is {0}.')|f(
0.01|currencyfmt('USD')) }}
</div>
<div class="error" id="contrib-not-entered">
{{ _('Contribution amount must be a number.') }}
</div>
<div class="error" id="paypal-error">
{{ _('There was an error communicating with paypal. Please try again later.') }}
</div>
<ul>
{% if has_suggested %}
<li>
<input type="radio" name="type" value="suggested"
id="contrib-suggested" checked="checked"/>
<label for="contrib-suggested">
{# L10n: {1} is a currency amount (e.g., $5.00) #}
{{ _('A one-time suggested contribution of {0}')|f(
addon.suggested_amount|currencyfmt('USD')) }}
</label>
</li>
{% endif %}
<li>
<input type="radio" name="type" value="onetime"
id="contrib-onetime"
{% if not has_suggested %}checked="checked"{% endif %}/>
<label>
{# L10n: {0} is a currency symbol (e.g., $),
{1} is an amount input field #}
{{ _('A one-time contribution of {0} {1}')|f(
'$', '<input type="text" name="onetime-amount" value=""/>')|safe }}
</label>
</li>
{% if not settings.PAYPAL_USE_EMBEDDED %}
<li>
<input type="radio" name="type" value="monthly"
id="contrib-monthly"/>
<label for="contrib-monthly">
{# L10n: {0} is a currency symbol (e.g., $),
{1} is an amount input field #}
{{ _('A regular monthly contribution of {0} {1}')|f(
'$', '</label><input type="text" name="monthly-amount" value=""/>')|safe }}
</li>
{% endif %}
</ul>
<h4 class="comment">
<label for="contrib-comment">
{{ _('Leave a comment or request with your contribution.') }}
</label>
</h4><span>{{ _('(optional)') }}</span>
<textarea name="comment" id="contrib-comment"></textarea>
<span class="commentlen"></span>
<button id="contribute-confirm" type="submit" class="prominent">
{{ _('Make Contribution') }}
</button>
<span class="cancel"><a href="#">{{ _('No Thanks') }}</a></span>
</form>
</div>{# /contribute-box #}
</div>{# /notification #}
<div class="hidden">
<div id="contribute-why" class="popup">
<p class="msg">
{% if addon.charity %}
{% if addon.charity_id == amo.FOUNDATION_ORG %}
{% trans %}
The developer of this add-on would like you to consider making a
donation to the <a href="{{ charity_url }}">{{ charity_name }}</a>
if you enjoy using it.
{% endtrans %}
{% else %}
{% trans %}
The developer of this add-on would like you to consider making a
small contribution to <a href="{{ charity_url }}">{{ charity_name }}</a>
if you enjoy using it.
{% endtrans %}
{% endif %}
{% else %}
{% trans %}
Mozilla is committed to supporting a vibrant and healthy developer
ecosystem. Your optional contribution helps sustain further development
of this add-on.
{% endtrans %}
{% endif %}
</p>
</div>
</div>

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

@ -0,0 +1,210 @@
{% extends "impala/base.html" %}
{% block title %}{{ page_title(addon.name) }}{% endblock %}
{% block js %}{% include("amo/recaptcha_js.html") %}{% endblock %}
{% block bodyclass %}gutter{% endblock %}
{% block extrahead %}
{% if settings.ENGAGE_ROBOTS and addon.status == amo.STATUS_UNREVIEWED %}
<meta name="robots" content="noindex">
{% endif %}
{% for preview in addon.all_previews %}
<link rel="prefetch" href="{{ preview.image_url }}">
{% endfor %}
{% endblock %}
{% block content %}
{{ impala_breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
(None, addon.name)]) }}
<aside class="secondary addon-vitals">
{{ addon.average_rating|stars(large=True) }}
<div><a href="#reviews">{{ _('{0} user reviews')|f(addon.total_reviews|numberfmt) }}</a></div>
<div>{{ _('<b>{0}</b> active users')|f(addon.average_daily_users|numberfmt)|safe }}</div>
<div class="widgets">
{{ favorites_widget(addon) }}
{% include 'addons/includes/collection_add_widget.html' %}
{{ sharing_widget(addon) }}
</div>
</aside>
{% set version = addon.current_version %}
<section class="primary">
<div id="addon" class="island c" role="main" data-id="{{ addon.id }}">
<hgroup>
<img src="{{ addon.get_icon_url(64) }}" class="icon">
<h2 class="addon"{{ addon.name|locale_html }}>
{{ addon.name }}
<span class="version">{{ version.version }}</span>
</h2>
<h4 class="author">{{ _('by') }} {{ users_list(addon.listed_authors) }}</h4>
</hgroup>
<p{{ addon.summary|locale_html }}>{{ addon.summary|nl2br }}</p>
{{ big_install_button(addon, show_warning=False) }}
</div>
{% if settings.PERF_THRESHOLD and addon.ts_slowness >= settings.PERF_THRESHOLD %}
{{ impala_performance_note(amount=addon.ts_slowness) }}
{% endif %}
{% if addon.takes_contributions %}
{{ impala_contribution(addon=addon, src='addon-detail') }}
{% endif %}
</section>
{% if addon.type != amo.ADDON_PERSONA %}
{% if addon.all_previews|length > 0 %}
<section class="previews carousel">
<a href="#" class="control prev">&laquo;</a>
<a href="#" class="control next">&raquo;</a>
<ul class="slider">
{%- for preview in addon.all_previews -%}
<li class="panel">
<a class="screenshot thumbnail" rel="jquery-lightbox"
href="{{ preview.image_url }}" title="{{ preview.caption }}">
<img src="{{ preview.thumbnail_url }}">
</a>
</li>
{%- endfor -%}
</ul>
</section>
{% endif %}
{% endif %}
{% if addon.description %}
<section class="primary island">
<h2>About this Add-on</h2>
<p{{ addon.description|locale_html }}>{{ addon.description|nl2br }}</p>
</section>
{% endif %}
{# addon recommendations #}
{% if recommendations %}
<section class="primary island">
<h2 class="compact-bottom">{{ _('Often used with&hellip;')|safe }}</h2>
{{ recommendations|addon_grid }}
</section>
{% endif %}
{# /recommendations #}
{% if author_addons %}
<section class="primary island">
<h2>
{% trans count = addon.listed_authors|length,
author = users_list(addon.listed_authors) %}
Other add-ons by {{ author }}
{% pluralize %}
Other add-ons by these authors
{% endtrans %}
</h2>
{{ author_addons|addon_grid }}
</section>
{% endif %}
<div class="secondary" role="navigation">
{% if addon.has_profile() and addon.listed_authors %}
<div class="highlight">
{% with single_dev = addon.listed_authors|random %}
<h3 class="compact-bottom">
{% trans count=addon.listed_authors|length %}
Meet the Developer
{% pluralize %}
Meet the Developers
{% endtrans %}
</h3>
<img class="avatar" alt="{{ single_dev.name }}" height="64"
width="64" src="{{ single_dev.picture_url }}"/>
<p>{{ _("Learn why {0} was created and find out what's next for this "
'add-on.')|f(addon.name) }}</p>
<p>
<a class="more-info" href="{{ addon.meet_the_dev_url() }}">
{% if addon.listed_authors|length > 1 %}
{{ _('Meet the Developers') }}
{% else %}
{{ _('Meet {0}')|f(single_dev.name) }}
{% endif %}
</a>
</p>
{% endwith %}
</div>
{% endif %}{# /meet the devs #}
{# categories and other add-ons #}
{% with categories = addon.categories.filter(application=APP.id) %}
{% if categories or author_addons %}
<div class="highlight">
{% if categories %}
<ul>
{# TODO reverse URL #}
{% for category in categories %}
<li>
<a href="{{ category.get_url_path() }}" class="more-info">
{# L10n: {0} is the name of a category #}
{{ _('See All {0} Add-ons')|f(category) }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
{% endwith %}
{# /categories #}
{# support box #}
{% if addon.support_email or addon.support_url or addon.has_satisfaction %}
<div id="support" class="highlight">
<h3 class="compact-bottom">{{ _('Need help with this add-on?') }}</h3>
<ul class="xoxo">
{% if addon.has_satisfaction %}
{# get satisfaction only supports en-US so no L10n here #}
<li>Ask others on
<a href="#" id="feedback_btn" class="feedback_btn"
data-company="{{ addon.get_satisfaction_company }}"
data-product="{{ addon.get_satisfaction_product }}"
>Get Satisfaction</a>
</li>
{% endif %}
{% if addon.support_email %}
<li>{{ emaillink(addon.support_email.localized_string,
_('E-mail your question')) }}</li>
{% endif %}
{% if addon.support_url %}
<li><a href="{{ addon.support_url|external_url }}">{{
_('Visit the support site') }}</a></li>
{% endif %}
</ul>
{% if addon.has_satisfaction %}
<div id="get_satisfaction_container"></div>
{% endif %}
</div>
{% endif %}
{# /support #}
{{ tags_box(addon=addon, tags=tags) }}
{# related collections #}
<div class="collections-add">
<h3 class="compact-bottom">{{ _('Related Collections') }}</h3>
{% if not collections %}
<p>{{ _('This add-on is not yet in any collections.') }}</p>
{% else %}
<ul class="addon-collections">
{% for coll in collections %}
<li><a href="{{ coll.get_url_path() }}"
class="collectionitem">{{ coll.name }}</a></li>
{% endfor %}
</ul>
{% endif %}
</div>
{# /collections #}
</div>{# /secondary #}
{% endblock content %}

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

@ -0,0 +1,30 @@
{% if request.APP == amo.FIREFOX %}
{% if listing %}
<div class="performance-note">
{{ _('This add-on can slow down Firefox.') }}
&nbsp;<a href="#">{{ _('More&hellip;')|safe }}</a>
<div class="popup warning hidden">
<p class="msg">
{% trans amount=amount|int %}
<b>Performance warning:</b> Installing this add-on can slow down
Firefox's start-up by <b>{{ amount }}%</b>.
{% endtrans %}
</p>
<p>
<a href="{{ url('perf.index' )}}">{{ _('Learn more&hellip;')|safe }}</a>
</p>
</div>
</div>
{% else %}
<div class="notice performance-note">
<h3>{{ _('This add-on can slow down Firefox.') }}</h3>
<p>
{% trans amount=amount|int %}
Installing this add-on can slow down
Firefox's start-up by <b>{{ amount }}%</b>.
{% endtrans %}
<a href="{{ url('perf.index' )}}">{{ _('Learn more&hellip;')|safe }}</a>
</p>
</div>
{% endif %}
{% endif %}

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

@ -46,6 +46,8 @@ urlpatterns = patterns('',
# URLs for a single add-on.
('^addon/%s/' % ADDON_ID, include(detail_patterns)),
# Impala deets.
url('^i/addon/%s/$' % ADDON_ID, views.impala_addon_detail, name='addons.i_detail'),
# Accept extra junk at the end for a cache-busting build id.
url('^addons/buttons.js(?:/.+)?$', 'addons.buttons.js'),

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

@ -87,6 +87,33 @@ def addon_detail(request, addon):
'addons.detail', args=[addon.slug]))
@author_addon_clicked
@addon_view
def impala_addon_detail(request, addon):
"""Add-ons details page dispatcher."""
# addon needs to have a version and be valid for this app.
if addon.type in request.APP.types:
if addon.type == amo.ADDON_PERSONA:
return persona_detail(request, addon)
else:
if not addon.current_version:
raise http.Http404
return impala_extension_detail(request, addon)
else:
# Redirect to an app that supports this type.
try:
new_app = [a for a in amo.APP_USAGE if addon.type
in a.types][0]
except IndexError:
raise http.Http404
else:
prefixer = urlresolvers.get_url_prefix()
prefixer.app = new_app.short
return http.HttpResponsePermanentRedirect(reverse(
'addons.i_detail', args=[addon.slug]))
def extension_detail(request, addon):
"""Extensions details page."""
@ -140,6 +167,59 @@ def extension_detail(request, addon):
return jingo.render(request, 'addons/details.html', data)
def impala_extension_detail(request, addon):
"""Extensions details page."""
# if current version is incompatible with this app, redirect
comp_apps = addon.compatible_apps
if comp_apps and request.APP not in comp_apps:
prefixer = urlresolvers.get_url_prefix()
prefixer.app = comp_apps.keys()[0].short
return http.HttpResponsePermanentRedirect(reverse(
'addons.detail', args=[addon.slug]))
# source tracking
src = request.GET.get('src', 'addondetail')
# get satisfaction only supports en-US
lang = translation.to_locale(translation.get_language())
addon.has_satisfaction = (lang == 'en_US' and
addon.get_satisfaction_company)
# other add-ons from the same author(s)
author_addons = order_by_translation(addon.authors_other_addons, 'name')
# tags
tags = addon.tags.not_blacklisted()
# addon recommendations
recommended = MiniAddon.objects.valid().filter(
recommended_for__addon=addon)[:5]
# popular collections this addon is part of
collections = Collection.objects.listed().filter(
addons=addon, application__id=request.APP.id)
data = {
'addon': addon,
'author_addons': author_addons,
'src': src,
'tags': tags,
'recommendations': recommended,
'review_form': ReviewForm(),
'reviews': Review.objects.latest().filter(addon=addon),
'get_replies': Review.get_replies,
'collections': collections.order_by('-subscribers')[:3],
}
if settings.REPORT_ABUSE:
data['abuse_form'] = AbuseForm(request=request)
return jingo.render(request, 'addons/impala/details.html', data)
@mobilized(extension_detail)
def extension_detail(request, addon):
return jingo.render(request, 'addons/mobile/details.html',

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

@ -252,6 +252,32 @@ def breadcrumbs(context, items=list(), add_default=True, crumb_size=40):
return jinja2.Markup(t)
@register.function
@jinja2.contextfunction
def impala_breadcrumbs(context, items=list(), add_default=True, crumb_size=40):
"""
show a list of breadcrumbs. If url is None, it won't be a link.
Accepts: [(url, label)]
"""
if add_default:
app = context['request'].APP
crumbs = [(urlresolvers.reverse('home'), page_name(app))]
else:
crumbs = []
# add user-defined breadcrumbs
if items:
try:
crumbs += items
except TypeError:
crumbs.append(items)
crumbs = [(url, truncate(label, crumb_size)) for (url, label) in crumbs]
c = {'breadcrumbs': crumbs}
t = env.get_template('amo/impala/breadcrumbs.html').render(**c)
return jinja2.Markup(t)
@register.filter
def json(s):
return jsonlib.dumps(s)

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

@ -0,0 +1,15 @@
{% if breadcrumbs %}
<nav id="breadcrumbs">
<ol>
{% for target, label in breadcrumbs %}
<li>
{% if target %}
<a href="{{ target }}">{{ label }}</a>
{% else %}
<span>{{ label }}</span>
{% endif %}
</li>
{% endfor %}
</ol>
</nav>
{% endif %}

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

@ -18,7 +18,7 @@
</li>
{% endmacro %}
<nav id="site-nav" class="c">
<nav id="site-nav" class="menu-nav c">
<ul>
{{ section(_('Extensions'), url('browse.extensions'), extras, extensions) }}
{{ section(_('Personas'), url('browse.personas'), extras, personas) }}

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

@ -5,7 +5,7 @@ from tower import ugettext as _
@jingo.register.filter
def stars(num):
def stars(num, large=False):
# check for 0.0 incase None was cast to a float. Should
# be safe since lowest rating you can give is 1.0
if num is None or num == 0.0:
@ -15,8 +15,9 @@ def stars(num):
rating = '<span itemprop="rating">%s</span>' % num
title = _('Rated %s out of 5 stars') % num
msg = _('Rated %s out of 5 stars') % rating
s = (u'<span class="stars stars-{num}" title="{title}">{msg}</span>'
.format(num=num, title=title, msg=msg))
size = 'large' if large else ''
s = (u'<span class="stars {size} stars-{num}" title="{title}">{msg}</span>'
.format(num=num, size=size, title=title, msg=msg))
return jinja2.Markup(s) # Inspected by #10

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

@ -37,7 +37,7 @@
<div class="piechart"></div>
<table data-report="apps" data-field="applications">
</table>
<a href="apps/">{{ _('See More Applications...') }}</a>
<a href="apps/">{{ _('See more applications&hellip;') }}</a>
</div>
</div>
<div class="toplist loading">
@ -46,7 +46,7 @@
<div class="piechart"></div>
<table data-report="locales" data-field="locales">
</table>
<a href="locales/">{{ _('See More languages...') }}</a>
<a href="locales/">{{ _('See more languages&hellip;') }}</a>
</div>
</div>
<div class="toplist loading">
@ -55,7 +55,7 @@
<div class="piechart"></div>
<table data-report="os" data-field="oses">
</table>
<a href="os/">{{ _('See more operating systems...') }}</a>
<a href="os/">{{ _('See more operating systems&hellip;') }}</a>
</div>
</div>
</div>

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

@ -0,0 +1,140 @@
@import 'lib';
#addon {
font-size: 1.2em;
padding: 20px 20px 20px 104px;
.icon {
position: absolute;
top: 20px;
left: 20px;
margin: 0 12px 1em 0;
}
h2 {
font-size: 24px;
}
}
.version {
color: #999;
}
.notice {
.border-radius(5px);
padding: 1em 1em 1em 104px;
background: #ECF5FE;
margin-bottom: 1em;
h3 {
font-style: italic;
font-size: 16px;
}
p {
margin-top: .5em;
}
b {
color: #333;
}
}
.notice.performance-note {
background: url("../../img/impala/turtle.png") no-repeat 28px 16px #FFF8DC;
}
.addon-vitals {
padding-top: 1em;
font-size: 16px;
line-height: 1.4em;
div {
margin-top: 4px;
}
.widgets {
margin-top: 23px;
font-size: 14px;
.widget {
color: #999;
display: block;
}
}
}
.widget {
padding-left: 21px;
background: url(../../img/impala/widgets.png) no-repeat 0 4px;
&:hover {
color: @link;
}
&.favorite {
&.faved {
.sprite-pos(2, 20, 4px);
}
&:hover {
.sprite-pos(1, 20, 4px);
}
}
&.collection-add {
.sprite-pos(3, 20, 4px);
&:hover {
.sprite-pos(4, 20, 4px);
}
}
&.share {
.sprite-pos(5, 20, 4px);
&:hover {
.sprite-pos(6, 20, 4px);
}
}
&.ajax-loading {
background: url(../../img/zamboni/loading-white.gif) no-repeat 0 2px !important;
}
}
#contribution {
.aux {
float: right;
text-align: center;
margin: 0 1em;
p {
font-size: 11px;
}
}
#contribute-box {
display: none;
}
}
.previews {
overflow: hidden;
position: relative;
margin: 2em 0;
padding: 0 5%;
.panel {
width: 100% / 3;
a {
display: block;
text-align: center;
}
}
.control {
font-size:
display: block;
position: absolute;
height: 100%;
width: 5%;
text-decoration: none;
font-size: 48px;
font-family: @serif-stack;
text-align: center;
line-height: 140px;
background: rgba(255,255,255,.5);
top: 0;
z-index: 100;
&.next {
right: 0;
}
&.prev {
left: 0;
}
&.disabled {
color: #ccc;
}
}
}

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

@ -0,0 +1,106 @@
@import 'lib';
.button {
display: inline-block;
position: relative;
font-size: 13px;
padding: 5px 10px 7px;
font-family: @head-sans;
font-weight: bold;
line-height: 1;
text-align: center;
text-decoration: none;
color: #fff;
.gradient-two-color(#669BE1, #5784BF);
text-shadow: 0 1px 0 rgba(0,0,0,.5);
.border-radius(6px);
.box-shadow(0 1px rgba(0, 0, 0, 0.1), 0 -2px rgba(0, 0, 0, 0.1) inset);
&.prominent {
padding: 8px 16px 12px;
font-size: 16px;
.box-shadow(0 3px rgba(0, 0, 0, 0.1), 0 -4px rgba(0, 0, 0, 0.1) inset);
}
&.add {
.gradient-two-color(#84C63C, #489615);
color: #fff;
span {
padding-left: 16px;
background: url(../../img/impala/button-icons.png) no-repeat 0 3px;
}
&.prominent {
span {
padding-left: 24px;
.sprite-pos(3, 64, 3px);
}
&.disabled span {
.sprite-pos(4, 64, 3px);
}
&.warning span {
.sprite-pos(5, 64, 3px);
}
}
&.warning {
background: url(../../img/impala/warning-bg.png);
color: #333;
text-shadow: 0 -1px 0 rgba(255,255,255,.5);
top: 0;
span {
.sprite-pos(2, 64, 3px);
}
}
&.disabled {
.gradient-two-color(#d1d4d7, #c1c5ca);
color: #919497;
.box-shadow(0 3px rgba(0, 0, 0, 0.05), 0 -4px rgba(0, 0, 0, 0.05) inset);
text-shadow: 0 1px 0 rgba(255,255,255,.5);
top: 0;
span {
.sprite-pos(1, 64, 3px);
}
}
}
&.contribute {
&.prominent b {
background: url(../../img/impala/button-icons.png) no-repeat;
padding-left: 24px;
margin-left: -4px;
.sprite-pos(7, 64, 3px);
}
}
&.developer {
background: -moz-linear-gradient(#f84b4e, #bc2b1a);
color: #fff;
span {
margin-left: -4px;
padding-left: 24px;
.sprite-pos(6, 64, 3px);
}
}
}
.button:hover,
.button:focus,
.button:active,
.button.selected {
text-decoration: none;
.box-shadow(0 3px rgba(0, 0, 0, 0.1), 0 -4px rgba(0, 0, 0, 0.1) inset, 0 0 100px rgba(255, 255, 255, 0.2) inset);
}
.button:active,
.button.selected {
top: 2px;
.box-shadow(0 1px rgba(0, 0, 0, 0.1), 0 -4px rgba(0, 0, 0, 0.1) inset, 0 0 100px rgba(255, 255, 255, 0.2) inset);
}
.button.small:hover,
.button.small:focus,
.button.small:active,
.button.small.selected {
.box-shadow(0 1px rgba(0, 0, 0, 0.1), 0 -2px rgba(0, 0, 0, 0.1) inset, 0 0 100px rgba(255, 255, 255, 0.2) inset);
}
.button.small:active,
.button.small.selected {
top: 2px;
.box-shadow(0 0px rgba(0, 0, 0, 0.1), 0 -2px rgba(0, 0, 0, 0.1) inset, 0 0 100px rgba(255, 255, 255, 0.2) inset);
}

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

@ -1,7 +1,7 @@
@import 'lib';
.pager {
font-family: @head-serif;
font-family: @serif-stack;
display: block;
.prev, .next {
height: 20px;
@ -50,4 +50,27 @@
}
.html-rtl .island .pager {
float: left;
}
}
.slider {
white-space: nowrap;
position: relative;
left: 0;
-moz-transition-duration: .3s;
-moz-transition-property: left, right;
-webkit-transition-duration: .3s;
-webkit-transition-property: left, right;
}
.slider.noslide {
-moz-transition: none;
-webkit-transition: none;
}
.slider > li {
width: 100%;
white-space: normal;
display: inline-block;
vertical-align: top;
top: 0;
}

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

@ -0,0 +1,136 @@
.sunbird,
.seamonkey,
.thunderbird,
.editor-tools,
.developer-hub {
#footer {
#footer-logo {
display: none;
}
#copyright {
clear: none;
padding-top: 20px;
}
}
}
#footer {
background: #33559b url(../../img/zamboni/global/bg-footer.png) 0 0 repeat-x;
padding: 123px 0 5px 0;
.section {
max-width: 960px;
margin: 0 auto;
position: relative;
}
line-height: 20px;
}
#footer-logo a,
#footer-logo a:link,
#footer-logo a:visited {
background: url(../../img/zamboni/global/header-logos.png) 15px 0 no-repeat;
}
#footer-logo a:hover,
#footer-logo a:active {
background: -moz-radial-gradient(center 45deg, ellipse closest-side, rgba(255,255,255,0.3) 0%, rgba(255,255,255,0) 100%),
url(../../img/zamboni/global/header-logos.png) 15px 0 no-repeat;
}
#footer-contents[dir="rtl"] {
text-align: right;
}
#copyright {
margin-left: 17px;
}
.footerlogo {
position: absolute;
right: 25px;
top: -64px;
}
.html-rtl .footerlogo {
right: auto;
left: 25px;
}
.developer-hub .footerlogo {
right: -10px;
top: -70px;
}
.html-rtl.developer-hub .footerlogo {
right: auto;
left: -10px;
}
#footer .section {
min-height: 0;
padding-bottom: 20px;
}
#footer-content {
margin-top: 10px;
}
#footer-logo {
margin-left: 3px;
width: 10%;
}
#footer-menu {
display: table;
width: 70%;
ul {
display: table-row;
}
li {
display: table-cell;
width: 10%;
padding: 11px 16px 0 0;
float: none;
}
}
.footer-devhub-link {
width: 25%;
}
#social-footer {
height: 68px;
margin-bottom: 4px;
display: table;
font-size: 18px;
font-style: italic;
width: 80%;
color: white;
a:after {
content: ' \00bb';
}
a:link,
a:visited {
color: white;
}
ul {
display: table-row;
li {
display: table-cell;
vertical-align: middle;
text-align: center;
&:first-child {
line-height: 1.2em;
font-size: 17px;
width: 128px;
}
b {
display: block;
font-family: MetaBlack;
font-style: normal;
font-size: 22px;
text-transform: uppercase;
}
}
}
}

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

@ -11,11 +11,10 @@
.gradient-two-color(#FCFDFE, #F4F8FC);
border: 1px solid #C9DDF2;
.border-radius(5px);
.box-shadow(0 -2px 0 rgba(204, 223, 243, 0.3) inset, 0 0 2px rgba(0, 0, 0, 0.1));
.box-shadow(0 -2px 0 rgba(204, 223, 243, 0.3) inset, 0 0 1px rgba(0, 0, 0, 0.1));
display: block;
margin-bottom: 15px;
padding: 14px 14px 16px;
float: left;
}
#masthead {
@ -30,14 +29,7 @@
float: left;
}
#aux-nav .context,
#aux-nav ul {
background: -moz-linear-gradient(#9FA7AF, fadeout(#9FA7AF, 100%)) no-repeat left top;
background-size: 1px 100%;
display: inline-block;
height: 32px;
line-height: 32px;
padding: 0 1em;
#aux-nav {
}
.site-title img {
@ -59,7 +51,7 @@
/** site navigation */
#site-nav {
.menu-nav {
font-size: 12px;
margin-left: 64px;
z-index: 50;
@ -68,15 +60,10 @@
> 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;
@ -93,7 +80,7 @@
}
&:after {
content: "";
width: 100px;
width: 160px;
z-index: 62;
height: 5px;
background: #fff;
@ -102,9 +89,6 @@
left: 1px;
}
}
&:first-child {
border: 0;
}
> ul {
width: 190px;
position: absolute;
@ -147,7 +131,7 @@
}
.html-rtl {
#site-nav > ul > li {
.menu-nav > ul > li {
border-left: 0;
border-right: 1px solid #9FA7AF;
float: right;
@ -161,11 +145,59 @@
}
}
#site-nav {
> ul {
> li {
border-left: 1px solid #9FA7AF;
left: -9px;
&:first-child {
border: 0;
}
> a {
padding: 4px 8px;
line-height: 12px;
text-transform: uppercase;
}
}
}
}
#aux-nav {
> ul {
> li:not(:first-child):before {
content: "";
display: block;
position: absolute;
top: 0;
left: -1px;
width: 1px;
height: 32px;
background: -moz-linear-gradient(#9FA7AF, fadeout(#9FA7AF, 100%)) no-repeat left top;
background-size: 1px 100%;
}
> li {
margin-left: 1px;
> a {
display: block;
line-height: 32px;
height: 32px;
padding: 0 1em;
.border-radius(0);
}
&:after {
top: 32px;
}
> ul {
top: 31px;
}
}
}
}
/** search box */
.header-search {
position: absolute;
top: 64px;
top: 63px;
right: 0;
background: #F8FBFF;
border: 1px solid #98B2C9;

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

@ -11,7 +11,6 @@
position: relative;
margin: 5px 5px 5px 61px;
border: 1px solid transparent;
float: left;
z-index: 20;
h3 {
color: #447BC4;
@ -40,9 +39,11 @@
}
a {
display: block;
color: black;
text-decoration: none;
}
.button {
display: inline-block;
}
.summary {
height: 48px;
width: 182px;
@ -75,6 +76,7 @@
z-index: 1;
}
&:hover {
float: left;
z-index: 25;
background: #fff;
border-color: #888;

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

@ -3,9 +3,9 @@
@note-gray: #999;
// Font Stacks
@copy-stack: "helvetica neue", arial, helvetica, sans-serif;
@sans-stack: "helvetica neue", arial, helvetica, sans-serif;
@head-sans: "trebuchet ms", sans-serif;
@head-serif: Georgia, serif;
@serif-stack: Georgia, serif;
@mono-stack: "andale mono", monospace;
// Mixins
@ -45,4 +45,12 @@
background-image: linear-gradient(@color1, @color2);
background-image: -moz-linear-gradient(@color1, @color2);
background-image: -webkit-linear-gradient(@color1, @color2);
}
.sprite(@url, @pos, @spacing, @offset) {
background: url(@url) no-repeat;
background-position: 0 (@spacing * @pos * -1 + @offset) + 0px;
}
.sprite-pos(@pos, @spacing, @offset) {
background-position: 0 (@spacing * @pos * -1 + @offset) + 0px;
}

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

@ -6,13 +6,24 @@
width: 63px;
height: 12px;
background: url(../../img/impala/stars.png) no-repeat left top;
text-indent: -9999px;
margin-right: 4px;
&.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;
&.large {
display: block;
background: url(../../img/impala/stars-16.png) no-repeat left top;
width: 89px;
height: 16px;
&.stars-4 { background-position: -18px 0; }
&.stars-3 { background-position: -36px 0; }
&.stars-2 { background-position: -54px 0; }
&.stars-1 { background-position: -70px 0; }
}
}
.html-rtl .stars {
text-indent: 9999px;
margin-right: 0;

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

@ -24,32 +24,32 @@ a {
}
.primary {
margin-left: 210px;
position: relative;
}
.primary, .html-rtl.gutter .primary {
margin-left: 210px;
.primary {
margin-right: 210px;
margin-left: 0;
}
.secondary {
float: right;
}
}
.secondary {
width: 180px;
.secondary, .html-rtl.gutter .primary {
float: left;
width: 180px;
}
.html-rtl {
.html-rtl, .gutter {
.primary {
margin-left: 0;
margin-right: 210px;
.primary {
margin-right: 0;
margin-left: 210px;
}
.secondary {
float: left;
}
@ -59,6 +59,7 @@ a {
}
}
.secondary {
ul, ol {
margin-bottom: 28px;
@ -85,6 +86,23 @@ a {
}
}
#breadcrumbs {
margin-bottom: 1.2em;
font-family: @serif-stack;
color: #666;
li {
display: inline;
&:before {
content: '\00bb';
font-size: 1.3em;
font-weight: bold;
}
&:first-child:before {
content: none;
}
}
}
#promos {
height: 270px;
max-height: 270px;

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

@ -13,7 +13,7 @@
body {
font-family: @copy-stack;
font-family: @sans-stack;
font-style: normal;
font-size: 13px;
}
@ -25,20 +25,42 @@ h1 {
text-transform: uppercase;
}
h4 {
font-size: 14px;
}
pre, code, kbd, tt, samp, tt {
font-family: @mono-stack;
}
.primary {
h2 {
color: #333;
font-family: @serif-stack;
font-style: italic;
}
p {
font-size: 14px;
margin-top: 1em;
color: #666;
line-height: 1.3em;
}
}
.gutter {
.primary, .secondary {
font-family: @serif-stack;
}
}
.island h2 {
color: #333;
font-family: @head-serif;
font-size: 18px;
font-style: italic;
margin-bottom: .5em;
}
.secondary h2 {
font-family: @copy-stack;
font-family: @sans-stack;
font-style: normal;
font-weight: bold;
text-transform: uppercase;
color: #484848;

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

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

После

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

Двоичные данные
media/img/impala/add-disabled-small.png Normal file

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

После

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

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

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

После

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

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

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

После

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

Двоичные данные
media/img/impala/add-warning-small.png Normal file

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

Двоичные данные
media/img/impala/button-icons Normal file

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

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

После

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

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

@ -0,0 +1,7 @@
$(function () {
$(".previews").zCarousel({
btnNext: ".previews .next",
btnPrev: ".previews .prev",
itemsPerPage: 3
});
});

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

@ -0,0 +1,81 @@
/**
* zCarousel: like jCarouselLite, but good.
* by potch
*
* handles fluid layouts like a champ!
*/
(function($) {
$.fn.zCarousel = function(o) {
o = $.extend({
itemsPerPage: 1,
circular: false
}, o);
this.each(function() {
var $self = $(this),
$strip = $(".slider", $self),
$lis = $strip.find(".panel"),
$prev = $(o.btnPrev),
$next = $(o.btnNext),
prop = $("body").hasClass("html-rtl") ? "right" : "left",
currentPos = 0,
maxPos = Math.ceil($lis.length / o.itemsPerPage) - 1;
function render(pos) {
if (o.circular) {
currentPos = pos;
if ($strip.hasClass("noslide")) {
currentPos = (pos > maxPos+1) ? 1 : (pos < 1 ? maxPos+1 : pos);
}
} else {
currentPos = Math.min(Math.max(0, pos), maxPos);
}
$strip.css(prop, currentPos * -100 + "%");
$prev.toggleClass("disabled", currentPos == 0 && !o.circular);
$next.toggleClass("disabled", currentPos == maxPos && !o.circular);
//wait for paint to clear the class. lame.
setTimeout(function() {
$strip.removeClass("noslide");
}, 0);
}
//wire up controls.
$next.click(_pd(function() {
render(currentPos+1);
}));
$prev.click(_pd(function() {
render(currentPos-1);
}));
// Strip text nodes so inline-block works properly.
var cn = $strip[0].childNodes;
for(var i = 0; i < cn.length; i++) {
if (cn[i].nodeType == 3) {
$strip[0].removeChild(cn[i]);
};
}
if (o.circular) {
//pad the beginning with a page from the end vice-versa.
$strip.prepend($lis.slice(-o.itemsPerPage).clone().addClass("cloned"))
.append($lis.slice(0,o.itemsPerPage).clone().addClass("cloned"));
render(o.itemsPerPage);
//if we're outside the bounds, disable transitions and snap back to the beginning.
$strip.bind("transitionend", function() {
if (currentPos > maxPos+1 || currentPos < 1) {
$strip.addClass("noslide");
setTimeout(function() {
render(currentPos);
}, 0);
}
});
} else {
render(0);
}
});
};
})(jQuery);

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

@ -57,6 +57,7 @@ $(function() {
};
});
// this belongs in a more global place.
$("img[data-defer-src]").each(function() {
var $img = $(this);
$img.attr('src', $img.attr('data-defer-src'));

16
media/js/lib/jquery-1.6.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Двоичные данные
media/js/share.png Normal file

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

После

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

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

@ -1,86 +1,3 @@
/**
* zCarousel: like jCarouselLite, but good.
* by potch
*
* handles fluid layouts like a champ!
*/
(function($) {
$.fn.zCarousel = function(o) {
o = $.extend({
itemsPerPage: 1,
circular: false
}, o);
this.each(function() {
var $self = $(this),
$strip = $(".slider", $self),
$lis = $strip.find(".panel"),
$prev = $(o.btnPrev),
$next = $(o.btnNext),
prop = $("body").hasClass("html-rtl") ? "right" : "left",
currentPos = 0,
maxPos = Math.ceil($lis.length / o.itemsPerPage) - 1;
function render(pos) {
if (o.circular) {
currentPos = pos;
if ($strip.hasClass("noslide")) {
currentPos = (pos > maxPos+1) ? 1 : (pos < 1 ? maxPos+1 : pos);
}
} else {
currentPos = Math.min(Math.max(0, pos), maxPos);
}
$strip.css(prop, currentPos * -100 + "%");
$prev.toggleClass("disabled", currentPos == 0 && !o.circular);
$next.toggleClass("disabled", currentPos == maxPos && !o.circular);
//wait for paint to clear the class. lame.
setTimeout(function() {
$strip.removeClass("noslide");
}, 0);
}
//wire up controls.
$next.click(_pd(function() {
render(currentPos+1);
}));
$prev.click(_pd(function() {
render(currentPos-1);
}));
// Strip text nodes so inline-block works properly.
var cn = $strip[0].childNodes;
for(var i = 0; i < cn.length; i++) {
if (cn[i].nodeType == 3) {
$strip[0].removeChild(cn[i]);
};
}
if (o.circular) {
//pad the beginning with a page from the end vice-versa.
$strip.prepend($lis.slice(-o.itemsPerPage).clone().addClass("cloned"))
.append($lis.slice(0,o.itemsPerPage).clone().addClass("cloned"));
render(o.itemsPerPage);
//if we're outside the bounds, disable transitions and snap back to the beginning.
$strip.bind("transitionend", function() {
if (currentPos > maxPos+1 || currentPos < 1) {
$strip.addClass("noslide");
setTimeout(function() {
render(currentPos);
}, 0);
}
});
} else {
render(0);
}
});
};
})(jQuery);
$(document).ready(function(){
if ($(".detail").length) {
initDetail();

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

@ -385,16 +385,19 @@ MINIFY_BUNDLES = {
),
'zamboni/impala': (
'css/impala/base.css',
'css/legacy/jquery-lightbox.css',
'css/impala/site.less',
'css/impala/typography.less',
'css/impala/header.less',
'css/global/headerfooter.css',
'css/impala/header.less',
'css/impala/footer.less',
'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',
'css/impala/buttons.less',
'css/impala/addon_details.less',
),
'zamboni/discovery-pane': (
'css/zamboni/discovery-pane.css',
@ -465,9 +468,10 @@ MINIFY_BUNDLES = {
'js/global/menu.js',
),
'impala': (
'js/lib/jquery-1.4.2.min.js',
'js/lib/jquery-1.6.min.js',
'js/lib/jquery-ui/custom-1.8.5.min.js',
'js/lib/underscore-min.js',
'js/impala/carousel.js',
'js/zamboni/browser.js',
'js/amo2009/addons.js',
'js/zamboni/init.js',
@ -490,7 +494,7 @@ MINIFY_BUNDLES = {
'js/lib/jquery-ui/ui.lightbox.js',
'js/get-satisfaction-v2.js',
'js/zamboni/contributions.js',
'js/zamboni/addon_details.js',
'js/impala/addon_details.js',
'js/zamboni/reviews.js',
# Personas
@ -518,6 +522,7 @@ MINIFY_BUNDLES = {
'js/zamboni/browser.js',
'js/zamboni/init.js',
'js/zamboni/format.js',
'js/impala/carousel.js',
# Add-ons details
'js/zamboni/buttons.js',

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

@ -67,28 +67,27 @@
<a href="http://mozilla.org/"><img src="{{ media('img/zamboni/mozilla-tab.png') }}"></a>
</div>
<div class="amo-header">
<div id="aux-nav" role="navigation" class="c">
{% block aux_nav %}
<ul id="other-apps" class="change"
title="{{ _('Find add-ons for other applications') }}">
<li>
<a href="#" class="controller">{{ _('Other Applications') }}</a>
<ul>
{% for app in amo.APP_USAGE %}
{% if app != request.APP %}
<li id="app-{{ app.short }}" class="{{ app.short }}">
<a href="{{ locale_url(app.short) }}">{{ app.pretty }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
<nav id="aux-nav" role="navigation" class="menu-nav">
<ul class="c">
{% if not settings.READ_ONLY %}
{% include "impala/user_login.html" %}
{% endif %}
{% block aux_nav %}
<li>
<a href="#" class="controller" title="{{ _('Find add-ons for other applications') }}">{{ _('Other Applications') }}</a>
<ul>
{% for app in amo.APP_USAGE %}
{% if app != request.APP %}
<li id="app-{{ app.short }}" class="{{ app.short }}">
<a href="{{ locale_url(app.short) }}">{{ app.pretty }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endblock aux_nav %}
</ul>
{% endblock aux_nav %}
{% if not settings.READ_ONLY %}
{% include "user_login.html" %}
{% endif %}
</div>
</nav>
<div class="header-search" role="search">
{% block search_form %}
{% include 'impala/search.html' %}

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

@ -0,0 +1,36 @@
<li class="account">
{% if user.is_authenticated() %}
<a href="#" class="user" title="{{ user.email }}">
{{ user.get_profile().welcome_name }}
</a>
{% if account_links %}
<ul>
{% for link in account_links %}
<li><a href="{{ link.href }}">{{ link.text }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% else %}
{# TODO(jbalogh): reverse #}
{% trans reg="/users/register", login=login_link() %}
<a href="{{ reg }}">Register</a> or <a href="{{ login }}">Log in</a>
{% endtrans %}
{% endif %}
</li>
{% if user.is_authenticated() %}
{% if tools_links and tools_links|count > 1 %}
<li class="tools">
<a href="#">{{ _('Tools') }}</a>
<ul>
{% for link in tools_links %}
<li><a href="{{ link.href }}">{{ link.text }}</a></li>
{% endfor %}
</ul>
</li>
{% else %}
<p class="context tools">
<a href="{{ tools_links[0].href }}">{{ tools_links[0].text }}</a>
</p>
{% endif %}
{% endif %}