This commit is contained in:
Chris Van 2011-07-26 12:28:31 -07:00
Родитель 4f7711a78d
Коммит 08d7b82bf6
26 изменённых файлов: 122 добавлений и 106 удалений

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

@ -30,7 +30,7 @@ def _install_button(context, addon, version=None, show_eula=True,
or request.GET.get('collection_uuid'))
button = install_button_factory(addon, app, lang, version,
show_eula, show_contrib, show_warning,
src, collection, size, detailed)
src, collection, size, detailed, impala)
installed = (request.user.is_authenticated() and
addon.id in request.amo_user.mobile_addons)
c = {'button': button, 'addon': addon, 'version': button.version,
@ -110,7 +110,7 @@ class InstallButton(object):
def __init__(self, addon, app, lang, version=None, show_eula=True,
show_contrib=True, show_warning=True, src='', collection=None,
size='', detailed=False):
size='', detailed=False, impala=False):
self.addon, self.app, self.lang = addon, app, lang
self.latest = version is None
self.version = version or addon.current_version
@ -118,6 +118,7 @@ class InstallButton(object):
self.collection = collection
self.size = size
self.detailed = detailed
self.impala = impala
self.is_beta = self.version and self.version.is_beta
version_unreviewed = self.version and self.version.is_unreviewed
@ -200,14 +201,15 @@ class InstallButton(object):
if self.show_eula:
# L10n: please keep   in the string so → does not wrap.
text = jinja2.Markup(_('Continue to Download →'))
url = file.eula_url()
url = file.eula_url(impala=self.impala)
elif self.accept_eula:
text = _('Accept and Download')
elif self.show_contrib:
# The eula doesn't exist or has been hit already.
# L10n: please keep   in the string so → does not wrap.
text = jinja2.Markup(_('Continue to Download →'))
roadblock = reverse('addons.roadblock', args=[self.addon.id])
u = '%saddons.roadblock' % ('i_' if self.impala else '')
roadblock = reverse(u, args=[self.addon.id])
url = urlparams(roadblock, eula='', version=self.version.version)
return text, url, os

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

@ -356,16 +356,17 @@ class Addon(amo.models.OnChangeMixin, amo.models.ModelBase):
return urls
def get_url_path(self, impala=False):
if impala:
return reverse('addons.i_detail', args=[self.slug])
return reverse('addons.detail', args=[self.slug])
u = '%saddons.detail' % ('i_' if impala else '')
return reverse(u, args=[self.slug])
def meet_the_dev_url(self):
return reverse('addons.meet', args=[self.slug])
def meet_the_dev_url(self, impala=False):
u = '%saddons.meet' % ('i_' if impala else '')
return reverse(u, args=[self.slug])
@property
def reviews_url(self):
return reverse('reviews.list', args=[self.slug])
def reviews_url(self, impala=False):
u = '%sreviews.list' % ('i_' if impala else '')
return reverse(u, args=[self.slug])
def type_url(self, impala=False):
"""The url for this add-on's AddonType."""

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

@ -36,7 +36,7 @@
show_eula=False, show_warning=False) }}
<p class="policy-link">
<a href ="{{ url('addons.detail', addon.slug) }}">
{{ _('Cancel Installation')|f(addon.name) }}
{{ _('Cancel Installation') }}
</a>
</p>
<p class="policy-link">

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

@ -43,7 +43,7 @@
<a class="button {{ b.button_class|join(' ') }} {{ extra }}"
data-hash="{{ link.file.hash }}"
{% if b.show_warning %}
href="{{ b.addon.get_url_path() }}"
href="{{ b.addon.get_url_path(impala=True) }}"
data-realurl="{{ link.url }}"
{% else %}
href="{{ link.url }}"
@ -67,7 +67,7 @@
{% if b.detailed %}
{% if addon.privacy_policy %}
<a class="privacy-policy badge" href="{{ url('addons.i_privacy', addon.slug) }}">
<a class="privacy-policy badge" href="{{ url('i_addons.privacy', addon.slug) }}">
<strong>{{ _('Privacy Policy') }}</strong>
</a>
{% endif %}

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

@ -1,4 +1,4 @@
{% set meet_url = url('addons.i_meet', addon.slug) %}
{% set meet_url = url('i_addons.meet', addon.slug) %}
{% if addon.charity %}
{% set charity_url = addon.charity.outgoing_url %}
{% set charity_name = addon.charity.name %}

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

@ -13,8 +13,9 @@
{% include "reviews/grouped_ratings.html" %}
{% set amo_user = request.amo_user if user.is_authenticated() else None %}
{% if not addon.has_author(amo_user) %}
{% set r_add = '%sreviews.add' % ('i_' if settings.IMPALA_REVIEWS else '') %}
<div>
<a class="button" id="add-review" href="{{ url('reviews.add', addon.slug) }}">{{ _('Write a review') }}</a>
<a class="button" id="add-review" href="{{ url(r_add) }}">{{ _('Write a review') }}</a>
</div>
{% endif %}
<a id="report-abuse" href="{{ remora_url('developers/docs/policies/contact') }}"
@ -36,7 +37,7 @@
<ul>
{% for category in categories %}
<li>
<a href="{{ category.get_url_path() }}">
<a href="{{ category.get_url_path(impala=True) }}">
{{ category }}
</a>
</li>
@ -79,4 +80,4 @@
</section>
{% endif %}
{% endcache %} {# cache addon #}
{% endcache %} {# cache addon #}

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

@ -14,12 +14,13 @@
{% endblock %}
{% block content %}
{{ impala_breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
(None, addon.name)]) }}
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(None, addon.name)]) }}
<aside class="secondary addon-vitals">
{{ addon.average_rating|stars(large=True) }}
<div><a id="reviews-link" href="{{ url('reviews.list', addon.slug) }}">
{% set r_list = '%sreviews.list' % ('i_' if settings.IMPALA_REVIEWS else '') %}
<div><a id="reviews-link" href="{{ url(r_list, addon.slug) }}">
{% trans cnt=addon.total_reviews, num=addon.total_reviews|numberfmt %}
{{ num }} user review
{% pluralize %}
@ -86,7 +87,7 @@
<h3>
{% trans count=addon.listed_authors|length,
name=single_dev.name,
url=addon.meet_the_dev_url() %}
url=addon.meet_the_dev_url(impala=settings.IMPALA_MEET) %}
Meet the Developer: <a href="{{ url }}">{{ name }}</a>
{% pluralize %}
<a href="{{ url }}">Meet the Developers</a>

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

@ -6,12 +6,14 @@
{{ page_title(_('End-User License Agreement for {0}')|f(addon.name)) }}
{% endblock %}
{% set detail_url = url('i_addons.detail', addon.slug) %}
{% block primary %}
<section class="primary">
<hgroup class="hero">
{# L10n: EULA stand for End User License Agreement #}
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(url('addons.i_detail', addon.slug), addon.name),
(detail_url, addon.name),
(None, _('EULA'))]) }}
{{ addon_heading(addon, version) }}
</hgroup>
@ -23,15 +25,14 @@
End-User License Agreement before installation can proceed:
{% endtrans %}
</p>
<div class="policy-statement">{{ addon.eula|nl2br }}</div>
<div class="policy-statement">{{ addon.eula|clean|nl2br }}</div>
{{ install_button(addon, version=version, show_contrib=False,
show_eula=False, show_warning=False, impala=True) }}
<p class="policy-cancel">
<a href="{{ url('addons.i_detail', addon.slug) }}">
{{ _('Cancel Installation')|f(addon.name) }}</a>
<a href="{{ detail_url }}">{{ _('Cancel Installation') }}</a>
</p>
<p class="policy-back">
&#x25C2; <a href="{{ url('addons.i_detail', addon.slug) }}">{{ _('Back to {0}...')|f(addon.name) }}</a>
<a href="{{ detail_url }}">{{ _('Back to {0}&hellip;')|f(addon.name)|safe }}</a>
</p>
</div>
</section>

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

@ -12,17 +12,17 @@
<hgroup class="hero">
{# L10n: The License for this add-on. #}
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(url('addons.i_detail', addon.slug), addon.name),
(url('i_addons.detail', addon.slug), addon.name),
(None, _('License'))]) }}
{{ addon_heading(addon, version) }}
</hgroup>
<div class="prose">
<h3>{{ _('Source Code License') }}</h3>
{% if license.url %}
<p><a href="{{ license.url }}">{{ license.name }}</a><//p>
<p><a href="{{ license.url }}">{{ license.name }}</a></p>
{% else %}
<h4>{{ license.name }}</h4>
<pre class="license" width="100%">{{ license.text|nl2br }}</pre>
<pre class="license">{{ license.text|clean|nl2br }}</pre>
{% endif %}
</div>
</section>

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

@ -7,21 +7,22 @@
{% endblock %}
{% set version = addon.current_version %}
{% set detail_url = url('i_addons.detail', addon.slug) %}
{% block primary %}
<section class="primary">
<hgroup class="hero">
{# L10n: The Privacy Policy for this add-on. #}
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(url('addons.i_detail', addon.slug), addon.name),
(detail_url, addon.name),
(None, _('Privacy Policy'))]) }}
{{ addon_heading(addon, version) }}
</hgroup>
<div class="prose">
<h3>{{ _('Privacy Policy') }}</h3>
<div class="policy-statement">{{ addon.privacy_policy|nl2br }}</div>
<div class="policy-statement">{{ addon.privacy_policy|clean|nl2br }}</div>
<p class="policy-back">
&#x25C2; <a href="{{ url('addons.i_detail', addon.slug) }}">{{ _('Back to {0}...')|f(addon.name) }}</a>
<a href="{{ detail_url }}">{{ _('Back to {0}&hellip;')|f(addon.name)|safe }}</a>
</p>
</div>
</section>

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

@ -40,18 +40,18 @@ detail_patterns = patterns('',
impala_detail_patterns = patterns('',
url('^$', views.impala_addon_detail, name='addons.i_detail'),
url('^eula/(?P<file_id>\d+)?$', views.impala_eula, name='addons.i_eula'),
url('^$', views.impala_addon_detail, name='i_addons.detail'),
url('^eula/(?P<file_id>\d+)?$', views.impala_eula, name='i_addons.eula'),
url('^license/(?P<version>[^/]+)?', views.impala_license,
name='addons.i_license'),
url('^privacy/', views.impala_privacy, name='addons.i_privacy'),
name='i_addons.license'),
url('^privacy/', views.impala_privacy, name='i_addons.privacy'),
url('^developers$', views.impala_developers, {'page': 'developers'},
name='addons.i_meet'),
name='i_addons.meet'),
url('^contribute/roadblock/', views.impala_developers,
{'page': 'roadblock'}, name='addons.i_roadblock'),
{'page': 'roadblock'}, name='i_addons.roadblock'),
url('^contribute/installed/', views.impala_developers,
{'page': 'installed'}, name='addons.i_installed'),
{'page': 'installed'}, name='i_addons.installed'),
('^reviews/', include('reviews.impala_urls')),
)

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

@ -120,7 +120,7 @@ def impala_addon_detail(request, addon):
prefixer = urlresolvers.get_url_prefix()
prefixer.app = new_app.short
return http.HttpResponsePermanentRedirect(reverse(
'addons.i_detail', args=[addon.slug]))
'i_addons.detail', args=[addon.slug]))
def extension_detail(request, addon):
@ -520,11 +520,10 @@ def eula(request, addon, file_id=None):
def impala_eula(request, addon, file_id=None):
if not addon.eula:
return http.HttpResponseRedirect(addon.get_url_path(impala=True))
if file_id is not None:
if file_id:
version = get_object_or_404(addon.versions, files__id=file_id)
else:
version = addon.current_version
return jingo.render(request, 'addons/impala/eula.html',
{'addon': addon, 'version': version})

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

@ -14,6 +14,7 @@ from babel.support import Format
import caching.base as caching
import jinja2
from jingo import register, env
from jingo.helpers import nl2br
from tower import ugettext as _
import amo

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

@ -24,7 +24,11 @@ from django.utils.translation import trans_real
from django.utils.functional import Promise
from django.utils.encoding import smart_str, smart_unicode
import bleach
from easy_thumbnails import processors
import html5lib
from html5lib.serializer.htmlserializer import HTMLSerializer
import jinja2
import pytz
from PIL import Image, ImageFile, PngImagePlugin
@ -283,6 +287,48 @@ def clear_messages(request):
pass
def clean_nl(string):
"""
This will clean up newlines so that nl2br can properly be called on the
cleaned text.
"""
html_blocks = ['blockquote', 'ol', 'li', 'ul']
if not string:
return string
def parse_html(tree):
prev_tag = ''
for i, node in enumerate(tree.childNodes):
if node.type == 4: # Text node
value = node.value
# Strip new lines directly inside block level elements.
if node.parent.name in html_blocks:
value = value.strip('\n')
# Remove the first new line after a block level element.
if (prev_tag in html_blocks and value.startswith('\n')):
value = value[1:]
tree.childNodes[i].value = value
else:
tree.insertBefore(parse_html(node), node)
tree.removeChild(node)
prev_tag = node.name
return tree
parse = parse_html(html5lib.parseFragment(string))
walker = html5lib.treewalkers.getTreeWalker('simpletree')
stream = walker(parse)
serializer = HTMLSerializer(quote_attr_values=True,
omit_optional_tags=False)
return jinja2.Markup(serializer.render(stream)).unescape()
# From: http://bit.ly/eTqloE
# Without this, you'll notice a slight grey line on the edges of
# the adblock plus icon.

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

@ -25,7 +25,7 @@
<a href="{{ services_url('discovery.addons.detail', addon.slug,
src='discovery-promo') }}" target="_self">
{% else %}
<a href="{{ url('addons.i_detail', addon.slug,
<a href="{{ url('i_addons.detail', addon.slug,
src='hp-dl-promo') }}" target="_self">
{% endif %}
{% if addon.type == amo.ADDON_PERSONA %}

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

@ -192,8 +192,9 @@ class File(amo.models.OnChangeMixin, amo.models.ModelBase):
url = reverse('downloads.latest', kwargs=kw)
return os.path.join(url, 'addon-%s-latest%s' % (addon, self.extension))
def eula_url(self):
return reverse('addons.eula', args=[self.version.addon_id, self.id])
def eula_url(self, impala=False):
u = '%saddons.eula' % ('i_' if impala else '')
return reverse(u, args=[self.version.addon_id, self.id])
@property
def file_path(self):

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

@ -8,7 +8,7 @@
{% block content %}
{{ impala_breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(addon.get_url_path(impala=True), addon.name),
(url('i_reviews.list', addon.slug), _('Reviews')),
(None, _('Add'))]) }}

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

@ -8,7 +8,7 @@
{% block content %}
{{ impala_breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(addon.get_url_path(impala=True), addon.name),
(url('i_reviews.list', addon.slug), _('Reviews')),
(None, _('Reply'))]) }}
@ -21,7 +21,7 @@
<h2>{{ title }}</h2>
{% include "reviews/impala/review.html" %}
<div class="review item reply">
<h2>{{ _('Write a Reply') }}</h2>
<form method="post" action="{{ url('i_reviews.reply', addon.slug, review.id) }}">

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

@ -11,7 +11,7 @@
{% endblock %}
{% block content %}
{{ impala_breadcrumbs([(addon.type_url(), amo.ADDON_TYPES[addon.type]),
{{ impala_breadcrumbs([(addon.type_url(impala=True), amo.ADDON_TYPES[addon.type]),
(addon.get_url_path(impala=True), addon.name),
(link, _('Reviews'))]) }}
@ -40,7 +40,7 @@
{% block review_header %}
<header>
{# Give a link back to reviews if we're looking at user reviews or a detail page. #}
{% with link = None if page == 'list' else url('reviews.list', addon.slug) %}
{% with link = None if page == 'list' else url('i_reviews.list', addon.slug) %}
{% endwith %}
<hgroup>
{% if page == "list" %}
@ -70,7 +70,7 @@
{% block review_list %}
{% if not reviews.object_list %}
<p><a href="{{ url('reviews.add', addon.slug) }}">
<p><a href="{{ url('i_reviews.add', addon.slug) }}">
{{ _('Be the first to write a review.') }}</a><p>
{% endif %}
{% for review in reviews.object_list %}

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

@ -1,4 +1,4 @@
{% set base = url('addons.i_detail', addon.slug)|urlparams('reviews') %}
{% set base = url('i_addons.detail', addon.slug)|urlparams('reviews') %}
{% if collection_uuid %}
{% set base = base|urlparams(collection_uuid=collection_uuid) %}
{% endif %}

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

@ -7,8 +7,6 @@ import bleach
import jinja2
import jingo
from .models import clean_nl
jingo.register.filter(to_language)
@ -72,4 +70,5 @@ def all_locales(addon, field_name, nl2br=False):
@jingo.register.filter
def clean(string):
return jinja2.Markup(clean_nl(bleach.clean(string)).strip())
from amo.utils import clean_nl
return jinja2.Markup(clean_nl(bleach.clean(unicode(string))).strip())

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

@ -2,8 +2,6 @@ from django.db import models, connection
from django.utils import encoding
import bleach
import html5lib
from html5lib.serializer.htmlserializer import HTMLSerializer
import amo.models
from amo import urlresolvers
@ -117,6 +115,7 @@ class PurifiedTranslation(Translation):
return unicode(self)
def clean(self):
from amo.utils import clean_nl
super(PurifiedTranslation, self).clean()
cleaned = bleach.clean(self.localized_string)
linkified = bleach.linkify(cleaned, nofollow=True,
@ -157,44 +156,3 @@ def delete_translation(obj, fieldname):
obj.update(**{field.name: None})
if trans:
Translation.objects.filter(id=trans.id).delete()
def clean_nl(string):
""" This will clean up newlines so that nl2br can properly
be called on the cleaned text. """
html_blocks = ['blockquote', 'ol', 'li', 'ul']
if not string:
return string
def parse_html(tree):
prev_tag = ''
for i, node in enumerate(tree.childNodes):
if node.type == 4: # Text node
value = node.value
# Strip new lines directly inside block level elements.
if node.parent.name in html_blocks:
value = value.strip('\n')
# Remove the first new line after a block level element
if (prev_tag in html_blocks and value.startswith('\n')):
value = value[1:]
tree.childNodes[i].value = value
else:
tree.insertBefore(parse_html(node), node)
tree.removeChild(node)
prev_tag = node.name
return tree
parse = parse_html(html5lib.parseFragment(string))
walker = html5lib.treewalkers.getTreeWalker('simpletree')
stream = walker(parse)
serializer = HTMLSerializer(quote_attr_values=True,
omit_optional_tags=False)
return serializer.render(stream)

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

@ -139,7 +139,7 @@ class Version(amo.models.ModelBase):
return os.path.join(settings.MIRROR_STAGE_PATH, str(self.addon_id))
def license_url(self, impala=False):
u = 'addons.i_license' if impala else 'addons.license'
u = '%saddons.license' % ('i_' if impala else '')
return reverse(u, args=[self.addon.slug, self.version])
def flush_urls(self):

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

@ -483,7 +483,8 @@ img.icon {
.hero h2:first-child {
margin-top: 1em;
}
hgroup.hero h2 {
hgroup.hero h2,
header.hero h2 {
margin-bottom: 1em;
}
&.about {
@ -526,12 +527,16 @@ img.icon {
border: 1px solid @border-black;
color: @medium-gray;
line-height: 1.4;
margin: 1.5em 0;
max-height: 300px;
overflow: auto;
padding: 2px 5px;
}
.policy-statement,
pre.license {
margin: 1.5em 0;
}
p.policy-cancel {
margin: 0;
}
@ -539,7 +544,3 @@ p.policy-cancel {
p.policy-back a {
color: @dark-gray;
}
pre.license {
margin-top: 1em;
}

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

@ -53,6 +53,7 @@ pre, code, kbd, tt, samp, tt {
pre {
line-height: 1.4;
white-space: pre-wrap;
}
.primary, .modal {

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

@ -971,8 +971,11 @@ UNLINK_SITE_STATS = True
# Use the new featured add-ons system which makes use of featured collections.
NEW_FEATURES = False
# Impala flags.
IMPALA_BROWSE = False
IMPALA_REVIEWS = False
IMPALA_MEET = False # Meet the Developer page.
# Set to True if we're allowed to use X-SENDFILE.
XSENDFILE = True