rm all the legacy addon views (#11086)
This commit is contained in:
Родитель
4e2e5d4368
Коммит
01f267050b
|
@ -664,13 +664,11 @@ class Addon(OnChangeMixin, ModelBase):
|
|||
|
||||
return data
|
||||
|
||||
def get_url_path(self, more=False, add_prefix=True):
|
||||
def get_url_path(self, add_prefix=True):
|
||||
if not self.current_version:
|
||||
return ''
|
||||
# If more=True you get the link to the ajax'd middle chunk of the
|
||||
# detail page.
|
||||
view = 'addons.detail_more' if more else 'addons.detail'
|
||||
return reverse(view, args=[self.slug], add_prefix=add_prefix)
|
||||
return reverse(
|
||||
'addons.detail', args=[self.slug], add_prefix=add_prefix)
|
||||
|
||||
def get_dev_url(self, action='edit', args=None, prefix_only=False):
|
||||
args = args or []
|
||||
|
@ -687,9 +685,6 @@ class Addon(OnChangeMixin, ModelBase):
|
|||
args = []
|
||||
return reverse('addons.%s' % action, args=[self.slug] + args)
|
||||
|
||||
def meet_the_dev_url(self):
|
||||
return reverse('addons.meet', args=[self.slug])
|
||||
|
||||
@property
|
||||
def ratings_url(self):
|
||||
return reverse('addons.ratings.list', args=[self.slug])
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<div class="install {{ button.install_class|join(' ') }}"
|
||||
data-addon="{{ addon.id }}"
|
||||
data-icon="{{ addon.get_icon_url(32) }}"
|
||||
data-developers="{{ addon.meet_the_dev_url() }}"
|
||||
data-versions="{{ url('addons.versions', addon.id) }}"
|
||||
data-name="{{ addon.name }}"
|
||||
{{ button.attrs()|xmlattr }}
|
||||
|
@ -54,16 +53,6 @@
|
|||
</div> {# install #}
|
||||
|
||||
{% if button.detailed %}
|
||||
{% if addon.privacy_policy %}
|
||||
<a class="privacy-policy" href="{{ url('addons.privacy', addon.slug) }}">
|
||||
<strong>{{ _('View privacy policy') }}</strong>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if addon.eula %}
|
||||
<a class="eula" href="{{ url('addons.eula', addon.slug) }}">
|
||||
<strong>{{ _('View End-User License Agreement') }}</strong>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if addon.is_unreviewed() %}
|
||||
<p class="warning">{% trans %}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
{% extends "impala/base_side_categories.html" %}
|
||||
{% from "addons/macros.html" import addon_heading %}
|
||||
|
||||
{% block title %}
|
||||
{# L10n: {0} is the name of the add-on. #}
|
||||
{{ page_title(_('End-User License Agreement for {0}')|format_html(addon.name)) }}
|
||||
{% endblock %}
|
||||
|
||||
{% set addon_type = addon.type %}
|
||||
{% set detail_url = addon.get_url_path() %}
|
||||
|
||||
{% block primary %}
|
||||
<section class="primary" id="eula">
|
||||
<hgroup class="hero">
|
||||
{{ addon_heading(addon, version) }}
|
||||
</hgroup>
|
||||
<div class="prose">
|
||||
<h2>{{ _('End-User License Agreement') }}</h2>
|
||||
<p>
|
||||
{% trans addon_name = addon.name %}
|
||||
{{ addon_name }} requires that you accept the following
|
||||
End-User License Agreement before installation can proceed:
|
||||
{% endtrans %}
|
||||
</p>
|
||||
<div class="policy-statement">{{ addon.eula|nl2br }}</div>
|
||||
<div class="policy-install">
|
||||
{{ install_button(addon, version=version,
|
||||
show_warning=False, impala=True) }}
|
||||
</div>
|
||||
<p class="policy-back">
|
||||
<a href="{{ detail_url }}">{{ _('Back to {0}…')|format_html(addon.name) }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -22,16 +22,6 @@
|
|||
|
||||
{% if button.detailed %}
|
||||
<div class="detailed">
|
||||
{% if addon.privacy_policy %}
|
||||
<a class="privacy-policy badge" href="{{ url('addons.privacy', addon.slug) }}">
|
||||
{{ _('Privacy Policy') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if addon.eula %}
|
||||
<a class="eula badge" href="{{ url('addons.eula', addon.slug) }}">
|
||||
{{ _('End-User License Agreement') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if addon.should_show_permissions(version) %}
|
||||
<a class="webext-permissions badge" href="#">
|
||||
{% if not version.all_files[0].is_webextension %}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
{# The front of the detail page content is in details.html.
|
||||
We want the above-the-fold portion to return and render really fast
|
||||
so we pull in reviews and links to other add-ons with js.
|
||||
This view returns a chunk of HTML that's injected into the DOM. #}
|
||||
{% set version = addon.current_version %}
|
||||
{% set reviews = reviews[:3] %}
|
||||
|
||||
<aside class="secondary addon-reviews c">
|
||||
{% if reviews %}
|
||||
<div>
|
||||
{{ addon.average_rating|stars }}
|
||||
{{ _('Average') }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% include "ratings/grouped_ratings.html" %}
|
||||
{% if addon.can_review(user) %}
|
||||
<div>
|
||||
<a class="button" id="add-review" href="{{ url('addons.ratings.add', addon.slug) }}">{{ _('Write a review') }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<a id="report-abuse" href="{{ url('addons.abuse', addon.pk) }}"
|
||||
class="abuse-image">{{ _('Report Abuse') }}</a>
|
||||
</aside>
|
||||
|
||||
<section id="reviews" class="primary island c">
|
||||
<h2>{{ _('Reviews') }}</h2>
|
||||
{{ impala_review_list_box(addon=addon, reviews=reviews) }}
|
||||
</section>
|
||||
|
||||
<aside id="related" class="secondary metadata c">
|
||||
{% with categories = addon.categories.filter(application=APP.id) %}
|
||||
{% if categories %}
|
||||
<h3>{{ _('Related Categories') }}</h3>
|
||||
<ul>
|
||||
{% for category in categories %}
|
||||
<li>
|
||||
<a href="{{ category.get_url_path() }}">
|
||||
{{ category }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{{ tags_box(addon=addon, tags=tags) }}
|
||||
</aside>
|
||||
|
||||
{% if author_addons %}
|
||||
<section class="primary island c">
|
||||
{% if author_addons %}
|
||||
<section id="author-addons">
|
||||
<h2>
|
||||
{% with count=addon.listed_authors|length,
|
||||
author=users_list(addon.listed_authors) %}
|
||||
{% trans count=count %}
|
||||
Other add-ons by {{ author }}
|
||||
{% pluralize %}
|
||||
Other add-ons by these authors
|
||||
{% endtrans %}
|
||||
{% endwith %}
|
||||
</h2>
|
||||
{{ author_addons|addon_grid(cols=3, src='dp-hc-othersby',
|
||||
dl_src='dp-dl-othersby') }}
|
||||
</section>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
|
@ -1,329 +0,0 @@
|
|||
{% extends "impala/base_shared.html" %}
|
||||
{% from "addons/macros.html" import addon_flags %}
|
||||
|
||||
{% set is_author = request.check_ownership(addon, require_owner=False) %}
|
||||
{% set is_reviewer = action_allowed(amo.permissions.ADDONS_REVIEW) %}
|
||||
{% set is_admin = action_allowed(amo.permissions.REVIEWS_ADMIN) %}
|
||||
|
||||
{% block title %}{{ page_title(addon.name) }}{% endblock %}
|
||||
{% block bodyclass %}gutter addon-details {{ super() }}{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
{% if settings.ENGAGE_ROBOTS and addon.status == amo.STATUS_NOMINATED %}
|
||||
<meta name="robots" content="noindex">
|
||||
{% endif %}
|
||||
<meta property="og:title" content="{{ addon.name }}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:image" content="{{ addon.get_icon_url(64)|absolutify }}">
|
||||
<meta property="og:url" content="{{ addon.get_url_path()|absolutify }}">
|
||||
<meta property="og:description" content="{{ addon.summary|striptags }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block header_content %}
|
||||
<div itemscope itemtype="http://schema.org/WebApplication">
|
||||
<link itemprop="SoftwareApplicationCategory" href="http://schema.org/OtherApplication" />
|
||||
<aside class="secondary addon-vitals">
|
||||
|
||||
{# This assumes we'll never charge for add-ons. Ha. #}
|
||||
<span itemprop="offers" itemscope itemtype="http://schema.org/Offer">
|
||||
<meta itemprop="price" content="$0" />
|
||||
<meta itemprop="priceCurrency" content="USD" />
|
||||
<link itemprop="availability" href="http://schema.org/InStock" />
|
||||
</span>
|
||||
|
||||
<div itemprop="aggregateRating" itemscope="" itemtype="http://schema.org/AggregateRating">
|
||||
<meta content="{{ addon.average_rating }}" itemprop="ratingValue">
|
||||
{{ addon.average_rating|stars(large=True) }}
|
||||
|
||||
<div>
|
||||
<a id="reviews-link" href="{{ addon.ratings_url }}">
|
||||
{% trans cnt=addon.total_ratings, num=addon.total_ratings|numberfmt %}
|
||||
<span itemprop="ratingCount">{{ num }}</span> user review
|
||||
{% pluralize %}
|
||||
<span itemprop="ratingCount">{{ num }}</span> user reviews
|
||||
{% endtrans %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if addon.show_adu() %}
|
||||
{% set cnt = addon.average_daily_users %}
|
||||
{% if cnt %}
|
||||
{% set cnt_id = 'daily-users' %}
|
||||
{% set cnt_pretty = ngettext(
|
||||
'{0} user', '{0} users', cnt)|format_html(cnt|numberfmt) %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set cnt = addon.weekly_downloads %}
|
||||
{% if cnt %}
|
||||
{% set cnt_id = 'weekly-downloads' %}
|
||||
{% set cnt_pretty = ngettext('{0} weekly download',
|
||||
'{0} weekly downloads', cnt)|format_html(cnt|numberfmt) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if cnt %}
|
||||
<div id="{{ cnt_id }}">
|
||||
{% if addon.public_stats or is_author %}
|
||||
<a class="stats" title="{{ _('View statistics') }}"
|
||||
href="{{ url('stats.overview', addon.slug) }}">{{ cnt_pretty }}</a>
|
||||
{% else %}
|
||||
{{ cnt_pretty }}
|
||||
{% endif %}
|
||||
<meta itemprop="interactionCount" content="UserDownloads:{{ addon.total_downloads }}" />
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if is_author %}
|
||||
<p class="manage-button"><a href="{{ addon.get_dev_url() }}" class="button developer prominent"><span>{{ _('Manage') }}</span></a></p>
|
||||
{% endif %}
|
||||
{% if is_reviewer %}
|
||||
<p class="manage-button"><a href="{{ url('reviewers.review', addon.slug) }}" class="button"><span>{{ _('Add-on Review') }}</span></a></p>
|
||||
{% endif %}
|
||||
{% if is_admin %}
|
||||
<p class="manage-button"><a href="{{ url('zadmin.addon_manage', addon.slug) }}" class="button"><span>{{ _('Admin Manage') }}</span></a></p>
|
||||
{% endif %}
|
||||
</aside>
|
||||
|
||||
{% set version = addon.current_version %}
|
||||
|
||||
{# All this depends on the addon or version, and nothing needs the user,
|
||||
so we can cache it all against the addon. #}
|
||||
<section class="primary addon-description-header">
|
||||
<div id="addon" class="island c" role="main" data-id="{{ addon.id }}">
|
||||
<hgroup>
|
||||
{# L10n: {0} is an add-on name. #}
|
||||
<img id="addon-icon" itemprop="image" src="{{ addon.get_icon_url(64) }}" class="icon" alt="{{ _('Icon of {0}')|format_html(addon.name) }}">
|
||||
<h1 class="addon"{{ addon.name|locale_html }}>
|
||||
<span itemprop="name">{{ addon.name }}</span>
|
||||
{% if version %}
|
||||
<span class="version-number" itemprop="version">{{ version.version }}</span>
|
||||
{{ addon_flags(addon, version) }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
<h4 class="author">{{ _('by') }} {{ users_list(addon.listed_authors) }}</h4>
|
||||
</hgroup>
|
||||
<p id="addon-summary" itemprop="description" {{ addon.summary|locale_html }}>{{ addon.summary|nl2br }}</p>
|
||||
{% if version %}
|
||||
{{ big_install_button(addon, show_warning=False, impala=True) }}
|
||||
{% endif %}
|
||||
{% if addon.is_featured(APP, LANG) %}
|
||||
<div class="banner-box">
|
||||
<div class="banner featured">{{ _('Featured') }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if addon.contributions %}
|
||||
<div class="notice c author">
|
||||
<div class="button-wrapper">
|
||||
<a class="button contribute prominent" id="contribution-url-button"
|
||||
target="_blank" rel="noopener"
|
||||
href="{{ addon.contributions|external_url }}">
|
||||
<b></b>{{ _('Contribute') }}
|
||||
</a>
|
||||
</div>
|
||||
<h3>{{ _('Enjoy this add-on?') }}</h3>
|
||||
<p>
|
||||
{% trans %}
|
||||
The developer of this add-on asks that you help support its
|
||||
continued development by making a small contribution.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
</div>
|
||||
{% endblock header_content %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% set version = addon.current_version %}
|
||||
|
||||
{% if addon.type != amo.ADDON_PERSONA %}
|
||||
{% if addon.current_previews|length > 0 %}
|
||||
<section class="previews">
|
||||
<div class="carousel">
|
||||
<a href="#" class="control prev">«</a>
|
||||
<a href="#" class="control next">»</a>
|
||||
<ul id="preview" class="slider">
|
||||
{%- for preview in addon.current_previews -%}
|
||||
<li class="panel">
|
||||
<a class="screenshot thumbnail" rel="jquery-lightbox"
|
||||
href="{{ preview.image_url }}" title="{{ preview.caption }}">
|
||||
{# L10n: {0} is an index. #}
|
||||
<img src="{{ preview.thumbnail_url }}" alt="{{ _('Add-on screenshot #{0}')|format_html(loop.index) }}">
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<div id="lightbox">
|
||||
<section>
|
||||
<div class="content">
|
||||
<a class="close" href="#">Close</a>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<a href="#" class="control next">»</a>
|
||||
<a href="#" class="control prev">«</a>
|
||||
<div class="caption"><span></span></div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<aside class="secondary metadata c">
|
||||
<ul class="links">
|
||||
{% if addon.homepage %}
|
||||
<li><a class="home" href="{{ addon.homepage|external_url }}">
|
||||
{{ _('Add-on home page') }}</a></li>
|
||||
{% endif %}
|
||||
{% if addon.support_url %}
|
||||
<li><a class="support" href="{{ addon.support_url|external_url }}">{{ _('Support site') }}</a></li>
|
||||
{% endif %}
|
||||
{% if addon.support_email %}
|
||||
<li>{{ emaillink(addon.support_email.localized_string,
|
||||
_('Support E-mail')) }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if version %}
|
||||
<ul>
|
||||
<li>{{ _('Version {0}')|format_html(version.version) }} <a class="scrollto" href="#detail-relnotes">{{ _('Info') }}</a></li>
|
||||
<li>{% trans %}Last Updated:{% endtrans %} {{ version.created|date }}</li>
|
||||
<li class="source-license">
|
||||
{% set license = version.license %}
|
||||
{% if license %}
|
||||
{% if license.url %}
|
||||
{% trans url = license.url,
|
||||
name = license if license.builtin else _('Custom License') %}
|
||||
Released under <a href="{{ url }}">{{ name }}</a>
|
||||
{% endtrans %}
|
||||
{% else %}
|
||||
{% trans url = version.license_url(),
|
||||
name = license if license.builtin else _('Custom License') %}
|
||||
Released under <a href="{{ url }}">{{ name }}</a>
|
||||
{% endtrans %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</aside>
|
||||
|
||||
<section class="primary island c">
|
||||
<h2>{{ _('About this Add-on') }}</h2>
|
||||
<div class="prose">
|
||||
{% if addon.description %}
|
||||
<div id="addon-description" class="prose" {{ addon.description|locale_html }}>{{ addon.description|nl2br }}</div>
|
||||
{% else %}
|
||||
<div id="addon-description" class="prose" {{ addon.description|locale_html }}>{{ addon.summary|nl2br }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="more-webpage" class="primary c" data-more-url="{{ addon.get_url_path(more=True) }}"></div>
|
||||
|
||||
{% if version or addon.developer_comments %}
|
||||
<section class="primary island more-island">
|
||||
{% if addon.developer_comments %}
|
||||
<section class="expando" id="developer-comments">
|
||||
<h2>{{ _('Developer’s Comments') }}<a class="toggle" href="#developer-comments"><b></b></a></h2>
|
||||
<div class="content prose">
|
||||
<p{{ addon.developer_comments|locale_html }}>
|
||||
{{ addon.developer_comments|nl2br }}</p>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if version %}
|
||||
<section id="detail-relnotes" class="expando">
|
||||
<h2>{{ _('Version Information') }}<a class="toggle" href="#detail-relnotes"><b></b></a></h2>
|
||||
<div class="content listing">
|
||||
<div class="items">
|
||||
{{ version_detail(addon, version, src=version_src, impala=True) }}
|
||||
</div>
|
||||
<p class="more c">
|
||||
<a class="more-info" href="{{ url('addons.versions', addon.slug) }}">
|
||||
{{ _('See complete version history') }}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
{# The rest of the detail page content is in details-more.html.
|
||||
We want above-the-fold to return and render really fast so we pull
|
||||
in reviews and links to other add-ons with js. #}
|
||||
{% endblock content %}
|
||||
|
||||
{% block popups %}
|
||||
{% if addon.privacy_policy %}
|
||||
<div class="modal" id="privacy-policy">
|
||||
<a href="#" class="close">{{ _('close') }}</a>
|
||||
<h2>{{ _('Privacy Policy') }}</h2>
|
||||
<div class="prose">
|
||||
{{ addon.privacy_policy|nl2br }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if addon.should_show_permissions() %}
|
||||
<div class="modal" id="webext-permissions">
|
||||
<a href="#" class="close">{{ _('close') }}</a>
|
||||
<h2>{{ _('Permissions') }}</h2>
|
||||
{% if addon.current_version.all_files[0].is_webextension %}
|
||||
{% set permissions = addon.current_version.all_files[0].webext_permissions_list %}
|
||||
<div class="prose">
|
||||
<p>
|
||||
{{ _('Some add-ons ask for permission to perform certain functions (example: a tab management add-on will ask permission to access your browser’s tab system).') }}
|
||||
</p><p>
|
||||
{{ _('Since you’re in control of your Firefox, the choice to grant or deny these requests is yours. Accepting permissions does not inherently compromise your browser’s performance or security, but in some rare cases risk may be involved.') }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
{# l10n: This is a header of a list of things the add-on can do. #}
|
||||
<h3>{{ _('This add-on can:') }}</h3>
|
||||
<ul class="webext-permissions-list">
|
||||
{% for perm in permissions %}
|
||||
<li class="webext-permissions-list">{{ perm|e }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="prose">
|
||||
<img src="{{ static('img/developers/test-warning.png') }}" alt="{{ _('[Warning]') }}">
|
||||
<p>
|
||||
{{ _('Some add-ons ask for permission to perform certain functions. Since you’re in control of your Firefox, the choice to grant or deny these requests is yours.') }}
|
||||
</p><p>
|
||||
{{ _('Please note this add-on uses legacy technology, which gives it access to all browser functions and data without requesting your permission.') }}
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if addon.eula %}
|
||||
<div class="modal" id="eula">
|
||||
<a href="#" class="close">{{ _('close') }}</a>
|
||||
<h2>{{ _('End-User License Agreement') }}</h2>
|
||||
<div class="prose">
|
||||
{{ addon.eula|nl2br }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if review_form and request.user.is_authenticated %}
|
||||
{{ impala_review_add_box(addon=addon) }}
|
||||
{% endif %}
|
||||
{% if abuse_form %}
|
||||
<div id="abuse-modal" class="modal">
|
||||
<a href="#" class="close">{{ _('close') }}</a>
|
||||
<h2>{{ _('Report Abuse') }}</h2>
|
||||
{{ addon_report_abuse(hide=False, addon=addon) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -1,20 +0,0 @@
|
|||
{% extends "impala/base_shared.html" %}
|
||||
|
||||
{% block title %}{{ page_title(addon.name) }}{% endblock %}
|
||||
{% block bodyclass %}gutter{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<aside class="secondary">
|
||||
{{ addon|sidebar_listing }}
|
||||
</aside>
|
||||
|
||||
<div class="primary">
|
||||
<div class="notification-box error {{ 'removed' if addon.disabled_by_user else 'disabled' }}">
|
||||
{% if addon.disabled_by_user %}
|
||||
{{ _('This add-on has been removed by its author.') }}
|
||||
{% elif addon.status == amo.STATUS_DISABLED %}
|
||||
{{ _('This add-on has been disabled by an administrator.') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
|
@ -1,27 +0,0 @@
|
|||
{% extends "impala/base_side_categories.html" %}
|
||||
{% from "addons/macros.html" import addon_heading %}
|
||||
|
||||
{% block title %}
|
||||
{{ page_title(_('Source Code License for {addon}'))|format_html(addon=addon.name) }}
|
||||
{% endblock %}
|
||||
|
||||
{% set addon_type = addon.type %}
|
||||
{% set license = version.license %}
|
||||
|
||||
{% block primary %}
|
||||
<section class="primary">
|
||||
<hgroup class="hero">
|
||||
{# L10n: The License for this add-on. #}
|
||||
{{ addon_heading(addon, version) }}
|
||||
</hgroup>
|
||||
<div class="prose">
|
||||
<h2>{{ _('Source Code License') }}</h2>
|
||||
{% if license.url %}
|
||||
<p><a href="{{ license.url }}">{{ license }}</a></p>
|
||||
{% else %}
|
||||
<h3>{{ license }}</h3>
|
||||
<pre class="license">{{ license.text|nl2br }}</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,47 +0,0 @@
|
|||
<div id="review-add-box" class="modal">
|
||||
{% if addon.can_review(user) %}
|
||||
<a class="close" href="#">{{ _('close') }}</a>
|
||||
<h2>{{ _('What do you think?') }}</h2>
|
||||
<div id="review-box" class="c">
|
||||
{% if not user.is_authenticated %}
|
||||
<p>
|
||||
{% trans login=login_link() %}
|
||||
Please <a href="{{ login }}">log in</a> to submit a review
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{{ url('addons.ratings.add', addon.slug) }}">
|
||||
{% set attrs = {} if user.is_authenticated else {'disabled': 'disabled'} %}
|
||||
{% csrf_token %}
|
||||
{{ field(review_form.body, _('Review:'), **attrs) }}
|
||||
{{ field(review_form.rating, _('Rating:'), **attrs) }}
|
||||
<p><input type="submit" value="{{ _('Submit review') }}" {{ attrs|xmlattr }}></p>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
{% trans %}
|
||||
Please do not post bug reports here. We do not make your email
|
||||
address available to add-on developers, so they can't contact you
|
||||
to resolve your issue.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% if addon.support_url or addon.support_email %}
|
||||
<p>
|
||||
See this add-on's
|
||||
{% if addon.support_url %}
|
||||
<a class="support" href="{{ addon.support_url|external_url }}">{{ _('support section') }}</a>
|
||||
{% elif addon.support_email %}
|
||||
{{ emaillink(addon.support_email.localized_string, _('support email')) }}
|
||||
{% endif %}
|
||||
to find out if assistance is available.
|
||||
You can also try asking the <a href="https://discourse.mozilla-community.org/c/add-ons/add-on-support">add-on community</a> for help.
|
||||
</p>
|
||||
{% endif %}
|
||||
<p><a href="{{ url('pages.review_guide') }}">{{ _('Review Guidelines') }}</a></p>
|
||||
</div>
|
||||
|
||||
</div>{# /#review-box #}
|
||||
{% endif %}{# /is_author #}
|
||||
</div>
|
|
@ -1,46 +0,0 @@
|
|||
{% set reviews = reviews[:3] %}
|
||||
{% if reviews %}
|
||||
{% set replies = get_replies(reviews) %}
|
||||
{% for review in reviews %}
|
||||
<div class="review">
|
||||
<h3>
|
||||
{{ review.rating|stars }}
|
||||
</h3>
|
||||
<p class="byline">
|
||||
{% trans user=review.user|user_link, date=review.created|date %}
|
||||
by {{ user }} on {{ date }}
|
||||
{% endtrans %}
|
||||
·
|
||||
<a class="permalink"
|
||||
href="{{ url('addons.ratings.detail', addon.slug, review.id) }}">{{ _('permalink') }}</a>
|
||||
</p>
|
||||
<p class="description">{{ review.body|nl2br }}</p>
|
||||
{% if replies[review.id] %}
|
||||
<a class="more-info" href="{{ replies[review.id].get_url_path() }}">
|
||||
{{ _("Show the developer's reply to this review") }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if addon %}
|
||||
<p>
|
||||
<a class="more-info" href="{{ addon.ratings_url }}">
|
||||
{% trans num=addon.total_ratings, cnt=addon.total_ratings|numberfmt %}
|
||||
See all user reviews
|
||||
{% pluralize %}
|
||||
See all {{ cnt }} user reviews
|
||||
{% endtrans %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<div class="review no-reviews">
|
||||
<h3>
|
||||
{{ _('This add-on has not yet been reviewed.') }}
|
||||
{% if addon.can_review(user) %}
|
||||
<a id="add-first-review" href="{{ url('addons.ratings.add', addon.slug) }}">
|
||||
{{ _('Be the first!') }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -1,7 +1,6 @@
|
|||
{# these are custom attributes on <div class="install ..."> found in src/olympia/addons/templates/addons/impala/button.html #}
|
||||
data-addon="{{ addon.id }}"
|
||||
data-icon="{{ addon.get_icon_url(32) }}"
|
||||
data-developers="{{ addon.meet_the_dev_url() }}"
|
||||
data-versions="{{ url('addons.versions', addon.id) }}"
|
||||
data-name="{{ addon.name }}"
|
||||
{{ button.attrs()|xmlattr }}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<div class="featured">
|
||||
<div class="featured-inner object-lead">
|
||||
<div id="addon-summary-wrapper">
|
||||
<div id="persona-summary" class="{{ addon|statusflags }}">
|
||||
{{ persona_preview(persona, linked=False) }}
|
||||
<table itemscope itemtype="http://data-vocabulary.org/Review-aggregate">
|
||||
{% with addon_name='<span itemprop="itemreviewed">{0}</span>'|format_html(addon.name) %}
|
||||
{# L10n: This is a caption for a table. {0} is an add-on name. #}
|
||||
<caption>{{ _('Add-on Information for {0}')|format_html(addon_name) }}</caption>
|
||||
{% endwith %}
|
||||
{% include "addons/persona_detail_table.html" %}
|
||||
</table>
|
||||
|
||||
<p{{ addon.description|locale_html }}>{{ addon.description|nl2br }}</p>
|
||||
|
||||
{{ big_install_button(addon, show_warning=False) }}
|
||||
|
||||
{% if is_artist %}
|
||||
<p><a href="{{ addon.get_dev_url() }}" class="button developer prominent">{{ _('Edit Theme') }}</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if is_reviewer %}
|
||||
{# TODO: Move Reviewer Tools to AMO so we don't need to hack. #}
|
||||
<p><a href="{{ url('reviewers.themes.single', addon.slug) }}" class="button prominent">
|
||||
{{ _('Approve / Reject') if addon.is_pending() else _('Review History') }}</a>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>{# /addon-summary and -wrapper #}
|
||||
</div>
|
||||
</div>{# /featured-inner and featured #}
|
|
@ -1,11 +0,0 @@
|
|||
{% if persona.addon.is_pending() and not is_artist %}
|
||||
<div class="persona featured pending-notice">
|
||||
<strong>{{ _('Sorry, this theme is pending. Please come back later.') }}</strong>
|
||||
</div>
|
||||
{% else %}
|
||||
{% if persona.addon.is_pending() and is_artist %}
|
||||
<div class="persona featured pending-notice">
|
||||
<strong>{{ _('This theme is pending. It is invisible to everyone but you.') }}</strong>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
|
@ -1,85 +0,0 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ page_title(addon.name) }}{% endblock %}
|
||||
{% block bodyclass %}inverse{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{% set is_artist = request.check_ownership(addon, require_owner=False) %}
|
||||
|
||||
<hgroup>
|
||||
<h2 class="addon"{{ addon.name|locale_html }}>
|
||||
<img src="{{ addon.get_icon_url(32) }}" class="icon" alt="" />
|
||||
<span>
|
||||
{{ addon.name }}
|
||||
</span>
|
||||
</h2>
|
||||
<h4 class="author">{{ _('by') }} {{ users_list(addon.listed_authors) or persona.display_username }}</h4>
|
||||
</hgroup>
|
||||
|
||||
{% include "addons/includes/persona_pending_notice.html" %}
|
||||
|
||||
<div id="persona" class="primary" role="main" data-id="{{ addon.id }}">
|
||||
{% if not persona.addon.is_pending() or request.check_ownership(addon, require_owner=False) %}
|
||||
{# If theme is pending, only artist should see theme listing. #}
|
||||
{% include "addons/includes/persona.html" %}
|
||||
{% endif %}
|
||||
|
||||
<div id="more-personas">
|
||||
{% if category_personas %}
|
||||
<div id="more-category" class="persona-list {{ 'persona-list-3col' if not author_personas else 'persona-list-2col' }}">
|
||||
{# L10n: {0} is a category name, such as Nature #}
|
||||
<h3>{{ _('More {0} Themes')|format_html(categories[0].name) }}</h3>
|
||||
<div class="article">
|
||||
{% for other in category_personas %}
|
||||
{{ persona_preview(other.persona, size='small') }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{# L10n: {0} is a category name, such as Nature #}
|
||||
<a href="{{ categories[0].get_url_path() }}" class="more-link">{{ _('See all {0} Themes')|format_html(categories[0].name) }}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if author_personas %}
|
||||
<div id="more-artist">
|
||||
<h3>{{ _('More by this Artist') }}</h3>
|
||||
<div class="article">
|
||||
{% for other in author_personas %}
|
||||
{{ persona_preview(other.persona, size='small') }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if author_gallery %}
|
||||
<a href="{{ author_gallery }}" class="more-link">{{ _('See all Themes by this Artist') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>{# /more-personas #}
|
||||
|
||||
{{ review_list_box(addon=addon, reviews=reviews) }}
|
||||
{% if request.user.is_authenticated %}
|
||||
{{ review_add_box(addon=addon) }}
|
||||
{% endif %}
|
||||
|
||||
{% if abuse_form %}
|
||||
{{ addon_report_abuse(hide=True, addon=addon) }}
|
||||
{% endif %}
|
||||
</div>{# /primary #}
|
||||
|
||||
<div id="persona-side" class="secondary" role="navigation">
|
||||
{% if categories %}
|
||||
<div class="category-list">
|
||||
<h3 class="compact-bottom">{{ _('Categories') }}</h3>
|
||||
<ul>
|
||||
{# TODO reverse URL #}
|
||||
{% for category in categories %}
|
||||
<li>
|
||||
<a href="{{ category.get_url_path() }}" class="category">{{ category }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ tags_box(addon=addon, tags=user_tags) }}
|
||||
|
||||
</div>{# /secondary #}
|
||||
{% endblock content %}
|
|
@ -1,30 +0,0 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<th>{{ _('Updated') }}</th>
|
||||
<td>
|
||||
<time datetime="{{ addon.modified|isotime }}">{{
|
||||
addon.modified|date }}</time>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="artist">
|
||||
<th>{{ _('Artist') }}</th>
|
||||
<td>{{ users_list(addon.listed_authors, max_text_length=20) or
|
||||
persona.display_username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ _('Rating') }}</th>
|
||||
<td>{{ reviews_link(addon) }}</td>
|
||||
</tr>
|
||||
<tr class="meta-stats">
|
||||
<th>{{ _('Daily Users') }}</th>
|
||||
<td>
|
||||
<strong class="downloads">{{ persona.popularity|numberfmt }}</strong>
|
||||
</td>
|
||||
</tr>
|
||||
{% if persona.license %}
|
||||
<tr>
|
||||
<th>{{ _('License') }}</th>
|
||||
<td>{{ license_link(amo.PERSONA_LICENSES_IDS[persona.license]) }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
|
@ -1,27 +0,0 @@
|
|||
{% extends "impala/base_side_categories.html" %}
|
||||
{% from "addons/macros.html" import addon_heading %}
|
||||
|
||||
{% block title %}
|
||||
{# L10n: {0} is the name of the add-on. #}
|
||||
{{ page_title(_('Privacy Policy for {0}')|format_html(addon.name)) }}
|
||||
{% endblock %}
|
||||
|
||||
{% set addon_type = addon.type %}
|
||||
{% set version = addon.current_version %}
|
||||
{% set detail_url = addon.get_url_path() %}
|
||||
|
||||
{% block primary %}
|
||||
<section class="primary">
|
||||
<hgroup class="hero">
|
||||
{# L10n: The Privacy Policy for this add-on. #}
|
||||
{{ addon_heading(addon, version) }}
|
||||
</hgroup>
|
||||
<div class="prose">
|
||||
<h2>{{ _('Privacy Policy') }}</h2>
|
||||
<div class="policy-statement">{{ addon.privacy_policy|nl2br }}</div>
|
||||
<p class="policy-back">
|
||||
<a href="{{ detail_url }}">{{ _('Back to {0}…')|format_html(addon.name) }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,34 +0,0 @@
|
|||
<form method="post" action="{{ url('addons.abuse', addon.slug) }}" data-no-csrf="anon-only">
|
||||
{% csrf_token %}
|
||||
<fieldset class="abuse">
|
||||
{% if hide %}
|
||||
<legend><a href="{{ url('devhub.docs', 'policies/contact') }}"
|
||||
class="abuse-image">{{ _('Report Abuse') }}</a></legend>
|
||||
{% endif %}
|
||||
<ol {% if hide %}style="display: none"{% endif %}>
|
||||
<li>
|
||||
<p>{% trans amo_policy_link_open='<a href="https://developer.mozilla.org/en-US/Add-ons/AMO/Policy">'|safe,
|
||||
link_close='</a>'|safe %}
|
||||
If you suspect this add-on violates {{ amo_policy_link_open }}our policies{{ link_close }} or
|
||||
has security or privacy issues, please use the form below to describe your
|
||||
concerns. Please do not use this form for any other reason.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
{{ abuse_form.text }}
|
||||
{{ abuse_form.text.errors }}
|
||||
</li>
|
||||
{% if abuse_form.has_recaptcha %}
|
||||
{{ abuse_form.recaptcha }}
|
||||
{{ abuse_form.recaptcha.errors }}
|
||||
{% endif %}
|
||||
<li class="footer-submit">
|
||||
<button type="submit">{{ _('Send Report') }}</button>
|
||||
{% if hide %}
|
||||
{{ _('or') }} <a href="#" class="cancel">{{ _('Cancel') }}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
</form>
|
|
@ -1,13 +0,0 @@
|
|||
{% extends "impala/base_shared.html" %}
|
||||
|
||||
{% set title = 'Report abuse for {0}'|format_html(addon.name) %}
|
||||
{% block bodyclass %}gutter abuse{% endblock %}
|
||||
{% block title %}{{ page_title(title) }}{% endblock %}
|
||||
{% block content %}
|
||||
<header>
|
||||
<h1>{{ title }}</h1>
|
||||
</header>
|
||||
<section class="primary island c prettyform">
|
||||
{{ addon_report_abuse(hide=False, addon=addon) }}
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,40 +0,0 @@
|
|||
{% if not addon.has_author(user) %}
|
||||
<h3>{{ _('What do you think?') }}</h3>
|
||||
<div id="review-box" class="highlight">
|
||||
{% if not user.is_authenticated %}
|
||||
<p>
|
||||
{% trans login=login_link() %}
|
||||
Please <a href="{{ login }}">log in</a> to submit a review
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<form disabled method="post" action="{{ url('addons.ratings.add', addon.slug) }}">
|
||||
{% set attrs = {} if user.is_authenticated else {'disabled': 'disabled'} %}
|
||||
{% csrf_token %}
|
||||
{{ field(review_form.body, _('Review:'), **attrs) }}
|
||||
{{ field(review_form.rating, _('Rating:'), **attrs) }}
|
||||
<input type="submit" value="{{ _('Submit review') }}" {{ attrs|xmlattr }}>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
{% trans %}
|
||||
Please do not post bug reports here. We do not make your email
|
||||
address available to add-on developers, so they can't contact you
|
||||
to resolve your issue.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% if addon.support_url or addon.support_email %}
|
||||
<p>
|
||||
{% trans support='#support' %}
|
||||
See this add-on's <a href="{{ support }}">support section</a> to find out if assistance is available.
|
||||
You can also try asking the <a href="https://discourse.mozilla-community.org/c/add-ons/add-on-support">add-on community</a> for help.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p><a href="{{ url('pages.review_guide') }}">{{ _('Review Guidelines') }}</a></p>
|
||||
</div>
|
||||
|
||||
</div>{# /#review-box #}
|
||||
{% endif %}{# /is_author #}
|
|
@ -1,32 +0,0 @@
|
|||
{% set reviews = reviews[:3] %}
|
||||
{% set replies = get_replies(reviews) %}
|
||||
{% if reviews %}
|
||||
<h3 id="reviews">{{ _('Reviews') }}</h3>
|
||||
<div class="article">
|
||||
{% for review in reviews %}
|
||||
<div class="review-detail">
|
||||
<p class="description">{{ review.body|nl2br }}</p>
|
||||
<p>{{ review.rating|stars }}
|
||||
{% trans user=review.user|user_link, date=review.created|date %}
|
||||
by {{ user }} on {{ date }}
|
||||
{% endtrans %}
|
||||
{% if replies[review.id] %}
|
||||
<a class="show-more" href="{{ replies[review.id].get_url_path() }}">
|
||||
{{ _("Show the developer's reply to this review") }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if addon %}
|
||||
<p>
|
||||
<a class="more-info" href="{{ url('addons.ratings.list', addon.slug) }}">
|
||||
{% trans num=addon.total_ratings, cnt=addon.total_ratings|numberfmt %}
|
||||
See all reviews of this add-on
|
||||
{% pluralize %}
|
||||
See all {{ cnt }} reviews of this add-on
|
||||
{% endtrans %}
|
||||
</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
|
@ -1,9 +0,0 @@
|
|||
{% if tags %}
|
||||
<div class="clearboth">
|
||||
<h3 class="compact-bottom">{{ _('Tags') }}</h3>
|
||||
|
||||
<div id="tagbox">
|
||||
{{ tag_list(addon, tags=tags) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
|
@ -41,60 +41,6 @@ def flag(context, addon):
|
|||
return ''
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/review_list_box.html')
|
||||
@jinja2.contextfunction
|
||||
def review_list_box(context, addon, reviews):
|
||||
"""Details page: Show a box with three add-on reviews."""
|
||||
c = dict(context.items())
|
||||
c.update(addon=addon, reviews=reviews)
|
||||
return c
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/impala/review_list_box.html')
|
||||
@jinja2.contextfunction
|
||||
def impala_review_list_box(context, addon, reviews):
|
||||
"""Details page: Show a box with three add-on reviews."""
|
||||
c = dict(context.items())
|
||||
c.update(addon=addon, reviews=reviews)
|
||||
return c
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/review_add_box.html')
|
||||
@jinja2.contextfunction
|
||||
def review_add_box(context, addon):
|
||||
"""Details page: Show a box for the user to post a review."""
|
||||
c = dict(context.items())
|
||||
c['addon'] = addon
|
||||
return c
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/impala/review_add_box.html')
|
||||
@jinja2.contextfunction
|
||||
def impala_review_add_box(context, addon):
|
||||
"""Details page: Show a box for the user to post a review."""
|
||||
c = dict(context.items())
|
||||
c['addon'] = addon
|
||||
return c
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/tags_box.html')
|
||||
@jinja2.contextfunction
|
||||
def tags_box(context, addon, tags=None):
|
||||
"""
|
||||
Details page: Show a box with existing tags along with a form to add new
|
||||
ones.
|
||||
"""
|
||||
c = dict(context.items())
|
||||
c.update({'addon': addon,
|
||||
'tags': tags})
|
||||
return c
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/listing/items.html')
|
||||
@jinja2.contextfunction
|
||||
|
@ -264,10 +210,3 @@ def theme_grid(context, themes, src=None, dl_src=None):
|
|||
if not dl_src:
|
||||
dl_src = context.get('dl_src', src)
|
||||
return new_context(**locals())
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('addons/report_abuse.html')
|
||||
@jinja2.contextfunction
|
||||
def addon_report_abuse(context, hide, addon):
|
||||
return new_context(**locals())
|
||||
|
|
|
@ -223,7 +223,6 @@ class TestButton(ButtonTest):
|
|||
|
||||
def test_file_details(self):
|
||||
file = self.get_file(amo.PLATFORM_ALL.id)
|
||||
self.addon.meet_the_dev_url.return_value = 'meet.dev'
|
||||
b = self.get_button()
|
||||
|
||||
# Normal.
|
||||
|
@ -314,7 +313,6 @@ class TestButtonHtml(ButtonTest):
|
|||
a = self.addon
|
||||
a.id = '12345'
|
||||
a.get_icon_url.return_value = 'icon url'
|
||||
a.meet_the_dev_url.return_value = 'meet.dev'
|
||||
a.name = 'addon name'
|
||||
self.file.hash = 'file hash'
|
||||
|
||||
|
@ -328,7 +326,6 @@ class TestButtonHtml(ButtonTest):
|
|||
install = doc('.install')
|
||||
assert '12345' == install.attr('data-addon')
|
||||
assert 'icon url' == install.attr('data-icon')
|
||||
assert 'meet.dev' == install.attr('data-developers')
|
||||
assert reverse('addons.versions', args=[a.id]) == (
|
||||
install.attr('data-versions'))
|
||||
assert 'addon name' == install.attr('data-name')
|
||||
|
@ -348,14 +345,6 @@ class TestButtonHtml(ButtonTest):
|
|||
doc('.install').attr('class').split())
|
||||
assert 'Featured' == doc('.install strong:last-child').text()
|
||||
|
||||
def test_detailed_privacy_policy(self):
|
||||
policy = self.render(detailed=True)('.install-shell .privacy-policy')
|
||||
assert policy.length == 0
|
||||
|
||||
self.addon.privacy_policy = 'privacy!'
|
||||
policy = self.render(detailed=True)('.install-shell .privacy-policy')
|
||||
assert policy.text() == 'View privacy policy'
|
||||
|
||||
def test_experimental_detailed_warning(self):
|
||||
self.addon.status = amo.STATUS_PUBLIC
|
||||
self.addon.is_experimental = True
|
||||
|
@ -467,16 +456,3 @@ class TestButtonHtml(ButtonTest):
|
|||
|
||||
doc = self.render(impala=True, show_download_anyway=True)
|
||||
assert doc('.download-anyway')
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
django.VERSION[0] >= 2,
|
||||
reason='Legacy UI tests')
|
||||
class TestViews(TestCase):
|
||||
fixtures = ['addons/eula+contrib-addon']
|
||||
|
||||
def test_eula_with_contrib_roadblock(self):
|
||||
url = reverse('addons.eula', args=[11730, 53612])
|
||||
response = self.client.get(url, follow=True)
|
||||
doc = PyQuery(response.content)
|
||||
assert doc('[data-search]').attr('class') == 'install '
|
||||
|
|
|
@ -1867,11 +1867,6 @@ class TestAddonGetURLPath(TestCase):
|
|||
addon = addon_factory(slug='woo')
|
||||
assert addon.get_url_path() == '/en-US/firefox/addon/woo/'
|
||||
|
||||
def test_get_url_path_more(self):
|
||||
addon = addon_factory(slug='yeah')
|
||||
assert addon.get_url_path(more=True) == (
|
||||
'/en-US/firefox/addon/yeah/more')
|
||||
|
||||
def test_unlisted_addon_get_url_path(self):
|
||||
addon = addon_factory(
|
||||
slug='woo', version_kw={'channel': amo.RELEASE_CHANNEL_UNLISTED})
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,6 +1,6 @@
|
|||
from django.conf.urls import include, url
|
||||
from django.shortcuts import redirect
|
||||
|
||||
from olympia.amo.views import frontend_view
|
||||
from olympia.stats.urls import stats_patterns
|
||||
|
||||
from . import views
|
||||
|
@ -11,46 +11,12 @@ ADDON_ID = r"""(?P<addon_id>[^/<>"']+)"""
|
|||
|
||||
# These will all start with /addon/<addon_id>/
|
||||
detail_patterns = [
|
||||
url(r'^$', views.addon_detail, name='addons.detail'),
|
||||
url(r'^more$', views.addon_detail, name='addons.detail_more'),
|
||||
url(r'^eula/(?P<file_id>\d+)?$', views.eula, name='addons.eula'),
|
||||
url(r'^license/(?P<version>[^/]+)?', views.license, name='addons.license'),
|
||||
url(r'^privacy/', views.privacy, name='addons.privacy'),
|
||||
url(r'^abuse/', views.report_abuse, name='addons.abuse'),
|
||||
url(r'^$', frontend_view, name='addons.detail'),
|
||||
url(r'^license/(?P<version>[^/]+)?', frontend_view, name='addons.license'),
|
||||
|
||||
url(r'^reviews/', include('olympia.ratings.urls')),
|
||||
url(r'^statistics/', include(stats_patterns)),
|
||||
url(r'^versions/', include('olympia.versions.urls')),
|
||||
|
||||
# Old contribution urls
|
||||
url(r'^developers$',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.meet'),
|
||||
url(r'^contribute/roadblock/',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.roadblock'),
|
||||
url(r'^contribute/installed/',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.installed'),
|
||||
url(r'^contribute/thanks',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.thanks'),
|
||||
url(r'^contribute/$',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.contribute'),
|
||||
url(r'^contribute/(?P<status>cancel|complete)$',
|
||||
lambda r, addon_id, status: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.contribute_status'),
|
||||
url(r'^about$',
|
||||
lambda r, addon_id: redirect('addons.detail',
|
||||
addon_id, permanent=True),
|
||||
name='addons.about'),
|
||||
]
|
||||
|
||||
|
||||
|
@ -58,25 +24,9 @@ urlpatterns = [
|
|||
# Promo modules for the homepage
|
||||
url(r'^i/promos$', views.homepage_promos, name='addons.homepage_promos'),
|
||||
|
||||
# See https://github.com/mozilla/addons-server/issues/3130
|
||||
# Hardcode because there is no relation from blocklist items and the
|
||||
# add-on they block :-(
|
||||
url(r'^addon/icloud-bookmarks/$', views.icloud_bookmarks_redirect,
|
||||
name='addons.icloudbookmarksredirect'),
|
||||
|
||||
# URLs for a single add-on.
|
||||
url(r'^addon/%s/' % ADDON_ID, include(detail_patterns)),
|
||||
|
||||
# Remora EULA and Privacy policy URLS
|
||||
url(r'^addons/policy/0/(?P<addon_id>\d+)/(?P<file_id>\d+)',
|
||||
lambda r, addon_id, file_id: redirect(
|
||||
'addons.eula', addon_id, file_id, permanent=True)),
|
||||
url(r'^addons/policy/0/(?P<addon_id>\d+)/',
|
||||
lambda r, addon_id: redirect(
|
||||
'addons.privacy', addon_id, permanent=True)),
|
||||
|
||||
url(r'^versions/license/(\d+)$', views.license_redirect),
|
||||
|
||||
url(r'^find-replacement/$', views.find_replacement_addon,
|
||||
name='addons.find_replacement'),
|
||||
]
|
||||
|
|
|
@ -3,14 +3,10 @@ from collections import OrderedDict
|
|||
from django import http
|
||||
from django.db.models import Prefetch
|
||||
from django.db.transaction import non_atomic_requests
|
||||
from django.shortcuts import get_list_or_404, get_object_or_404, redirect
|
||||
from django.shortcuts import redirect
|
||||
from django.utils.cache import patch_cache_control
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext
|
||||
from django.views.decorators.cache import cache_control, cache_page
|
||||
from django.views.decorators.vary import vary_on_headers
|
||||
|
||||
import waffle
|
||||
from django.views.decorators.cache import cache_page
|
||||
|
||||
from elasticsearch_dsl import Q, query, Search
|
||||
from rest_framework import exceptions, serializers
|
||||
|
@ -24,20 +20,15 @@ from rest_framework.viewsets import GenericViewSet
|
|||
import olympia.core.logger
|
||||
|
||||
from olympia import amo
|
||||
from olympia.abuse.models import send_abuse_report
|
||||
from olympia.access import acl
|
||||
from olympia.amo import messages
|
||||
from olympia.amo.forms import AbuseForm
|
||||
from olympia.amo.models import manual_order
|
||||
from olympia.amo.urlresolvers import get_outgoing_url, get_url_prefix, reverse
|
||||
from olympia.amo.utils import randslice, render
|
||||
from olympia.amo.urlresolvers import get_outgoing_url
|
||||
from olympia.amo.utils import render
|
||||
from olympia.api.pagination import ESPageNumberPagination
|
||||
from olympia.api.permissions import (
|
||||
AllowAddonAuthor, AllowReadOnlyIfPublic, AllowRelatedObjectPermissions,
|
||||
AllowReviewer, AllowReviewerUnlisted, AnyOf, GroupPermission)
|
||||
from olympia.constants.categories import CATEGORIES_BY_ID
|
||||
from olympia.ratings.forms import RatingForm
|
||||
from olympia.ratings.models import GroupedRating, Rating
|
||||
from olympia.search.filters import (
|
||||
AddonAppQueryParam, AddonAppVersionQueryParam, AddonAuthorQueryParam,
|
||||
AddonCategoryQueryParam, AddonGuidQueryParam, AddonTypeQueryParam,
|
||||
|
@ -45,12 +36,11 @@ from olympia.search.filters import (
|
|||
SortingFilter)
|
||||
from olympia.translations.query import order_by_translation
|
||||
from olympia.versions.models import Version
|
||||
from olympia.lib.cache import make_key, cache_get_or_set
|
||||
|
||||
from .decorators import addon_view_factory
|
||||
from .indexers import AddonIndexer
|
||||
from .models import (
|
||||
Addon, CompatOverride, FrozenAddon, Persona, ReplacementAddon)
|
||||
Addon, CompatOverride, FrozenAddon, ReplacementAddon)
|
||||
from .serializers import (
|
||||
AddonEulaPolicySerializer,
|
||||
AddonSerializer, AddonSerializerWithUnlistedData, CompatOverrideSerializer,
|
||||
|
@ -67,129 +57,6 @@ addon_valid_disabled_pending_view = addon_view_factory(
|
|||
qs=Addon.objects.valid_and_disabled_and_pending)
|
||||
|
||||
|
||||
@addon_valid_disabled_pending_view
|
||||
@non_atomic_requests
|
||||
def addon_detail(request, addon):
|
||||
"""Add-ons details page dispatcher."""
|
||||
if addon.is_deleted or (addon.is_pending() and not addon.is_persona()):
|
||||
# Allow pending themes to be listed.
|
||||
raise http.Http404
|
||||
if addon.is_disabled:
|
||||
return render(request, 'addons/impala/disabled.html',
|
||||
{'addon': addon}, status=404)
|
||||
|
||||
# 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 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 = get_url_prefix()
|
||||
prefixer.app = new_app.short
|
||||
return http.HttpResponsePermanentRedirect(reverse(
|
||||
'addons.detail', args=[addon.slug]))
|
||||
|
||||
|
||||
@vary_on_headers('X-Requested-With')
|
||||
@non_atomic_requests
|
||||
def 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 = get_url_prefix()
|
||||
prefixer.app = list(comp_apps.keys())[0].short
|
||||
return redirect('addons.detail', addon.slug, permanent=True)
|
||||
|
||||
ctx = {
|
||||
'addon': addon,
|
||||
'src': request.GET.get('src', 'dp-btn-primary'),
|
||||
'version_src': request.GET.get('src', 'dp-btn-version'),
|
||||
'tags': addon.tags.not_denied(),
|
||||
'grouped_ratings': GroupedRating.get(addon.id),
|
||||
'review_form': RatingForm(),
|
||||
'reviews': Rating.without_replies.all().filter(
|
||||
addon=addon, is_latest=True).exclude(body=None),
|
||||
'get_replies': Rating.get_replies,
|
||||
'abuse_form': AbuseForm(request=request),
|
||||
}
|
||||
|
||||
# details.html just returns the top half of the page for speed. The bottom
|
||||
# does a lot more queries we don't want on the initial page load.
|
||||
if request.is_ajax():
|
||||
# Other add-ons/apps from the same author(s).
|
||||
ctx['author_addons'] = addon.authors_other_addons(app=request.APP)[:6]
|
||||
return render(request, 'addons/impala/details-more.html', ctx)
|
||||
else:
|
||||
return render(request, 'addons/impala/details.html', ctx)
|
||||
|
||||
|
||||
def _category_personas(qs, limit):
|
||||
def fetch_personas():
|
||||
return randslice(qs, limit=limit)
|
||||
key = make_key('cat-personas:' + str(qs.query), normalize=True)
|
||||
return cache_get_or_set(key, fetch_personas)
|
||||
|
||||
|
||||
@non_atomic_requests
|
||||
def persona_detail(request, addon):
|
||||
"""Details page for Personas."""
|
||||
if not (addon.is_public() or addon.is_pending()):
|
||||
raise http.Http404
|
||||
|
||||
try:
|
||||
persona = addon.persona
|
||||
except Persona.DoesNotExist:
|
||||
raise http.Http404
|
||||
|
||||
# This persona's categories.
|
||||
categories = addon.categories.all()
|
||||
category_personas = None
|
||||
if categories.exists():
|
||||
qs = Addon.objects.public().filter(categories=categories[0])
|
||||
category_personas = _category_personas(qs, limit=6)
|
||||
|
||||
data = {
|
||||
'addon': addon,
|
||||
'persona': persona,
|
||||
'categories': categories,
|
||||
'author_personas': persona.authors_other_addons()[:3],
|
||||
'category_personas': category_personas,
|
||||
}
|
||||
|
||||
try:
|
||||
author = addon.authors.all()[0]
|
||||
except IndexError:
|
||||
author = None
|
||||
else:
|
||||
author = author.get_url_path(src='addon-detail')
|
||||
data['author_gallery'] = author
|
||||
|
||||
dev_tags, user_tags = addon.tags_partitioned_by_developer
|
||||
data.update({
|
||||
'dev_tags': dev_tags,
|
||||
'user_tags': user_tags,
|
||||
'review_form': RatingForm(),
|
||||
'reviews': Rating.without_replies.all().filter(
|
||||
addon=addon, is_latest=True),
|
||||
'get_replies': Rating.get_replies,
|
||||
'search_cat': 'themes',
|
||||
'abuse_form': AbuseForm(request=request),
|
||||
})
|
||||
|
||||
return render(request, 'addons/persona_detail.html', data)
|
||||
|
||||
|
||||
class BaseFilter(object):
|
||||
"""
|
||||
Filters help generate querysets for add-on listings.
|
||||
|
@ -311,88 +178,6 @@ def homepage_promos(request):
|
|||
return promos(request, 'home', version, platform)
|
||||
|
||||
|
||||
@addon_view
|
||||
@non_atomic_requests
|
||||
def eula(request, addon, file_id=None):
|
||||
if not addon.eula:
|
||||
return http.HttpResponseRedirect(addon.get_url_path())
|
||||
if file_id:
|
||||
version = get_object_or_404(addon.versions, files__id=file_id)
|
||||
else:
|
||||
version = addon.current_version
|
||||
return render(request, 'addons/eula.html',
|
||||
{'addon': addon, 'version': version})
|
||||
|
||||
|
||||
@addon_view
|
||||
@non_atomic_requests
|
||||
def privacy(request, addon):
|
||||
if not addon.privacy_policy:
|
||||
return http.HttpResponseRedirect(addon.get_url_path())
|
||||
|
||||
return render(request, 'addons/privacy.html', {'addon': addon})
|
||||
|
||||
|
||||
@addon_view
|
||||
@non_atomic_requests
|
||||
def license(request, addon, version=None):
|
||||
if version is not None:
|
||||
qs = addon.versions.filter(channel=amo.RELEASE_CHANNEL_LISTED,
|
||||
files__status__in=amo.VALID_FILE_STATUSES)
|
||||
version = get_list_or_404(qs, version=version)[0]
|
||||
else:
|
||||
version = addon.current_version
|
||||
if not (version and version.license):
|
||||
raise http.Http404
|
||||
return render(request, 'addons/impala/license.html',
|
||||
dict(addon=addon, version=version))
|
||||
|
||||
|
||||
@non_atomic_requests
|
||||
def license_redirect(request, version):
|
||||
version = get_object_or_404(Version.objects, pk=version)
|
||||
return redirect(version.license_url(), permanent=True)
|
||||
|
||||
|
||||
@addon_view
|
||||
@non_atomic_requests
|
||||
def report_abuse(request, addon):
|
||||
form = AbuseForm(request.POST or None, request=request)
|
||||
if request.method == "POST" and form.is_valid():
|
||||
send_abuse_report(request, addon, form.cleaned_data['text'])
|
||||
messages.success(request, ugettext('Abuse reported.'))
|
||||
return http.HttpResponseRedirect(addon.get_url_path())
|
||||
else:
|
||||
return render(request, 'addons/report_abuse_full.html',
|
||||
{'addon': addon, 'abuse_form': form})
|
||||
|
||||
|
||||
@cache_control(max_age=60 * 60 * 24)
|
||||
@non_atomic_requests
|
||||
def persona_redirect(request, persona_id):
|
||||
if persona_id == 0:
|
||||
# Newer themes have persona_id == 0, doesn't mean anything.
|
||||
return http.HttpResponseNotFound()
|
||||
|
||||
persona = get_object_or_404(Persona.objects, persona_id=persona_id)
|
||||
try:
|
||||
to = reverse('addons.detail', args=[persona.addon.slug])
|
||||
except Addon.DoesNotExist:
|
||||
# Would otherwise throw 500. Something funky happened during GP
|
||||
# migration which caused some Personas to be without Addons (problem
|
||||
# with cascading deletes?). Tell GoogleBot these are dead with a 404.
|
||||
return http.HttpResponseNotFound()
|
||||
return http.HttpResponsePermanentRedirect(to)
|
||||
|
||||
|
||||
@non_atomic_requests
|
||||
def icloud_bookmarks_redirect(request):
|
||||
if (waffle.switch_is_active('icloud_bookmarks_redirect')):
|
||||
return redirect('/blocked/i1214/', permanent=False)
|
||||
else:
|
||||
return addon_detail(request, 'icloud-bookmarks')
|
||||
|
||||
|
||||
DEFAULT_FIND_REPLACEMENT_PATH = '/collections/mozilla/featured-add-ons/'
|
||||
FIND_REPLACEMENT_SRC = 'find-replacement'
|
||||
|
||||
|
|
|
@ -1,29 +1,9 @@
|
|||
from django import forms
|
||||
from django.conf import settings
|
||||
|
||||
from olympia.amo.fields import ReCaptchaField
|
||||
from olympia.translations.fields import TranslatedField
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
|
||||
class AbuseForm(forms.Form):
|
||||
recaptcha = ReCaptchaField(label='')
|
||||
text = forms.CharField(required=True,
|
||||
label='',
|
||||
widget=forms.Textarea())
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request = kwargs.pop('request')
|
||||
self.has_recaptcha = True
|
||||
|
||||
super(AbuseForm, self).__init__(*args, **kwargs)
|
||||
|
||||
if (not self.request.user.is_anonymous or
|
||||
not settings.NOBOT_RECAPTCHA_PRIVATE_KEY):
|
||||
del self.fields['recaptcha']
|
||||
self.has_recaptcha = False
|
||||
|
||||
|
||||
class AMOModelForm(forms.ModelForm):
|
||||
|
||||
@cached_property
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
{# Due to URL changes we have to use * here and hope most crawlers respect it #}
|
||||
Disallow: /*{{ url('addons.contribute', 0, add_prefix=False)|replace('0', '*') }}
|
||||
|
||||
{# The downloads live at locale-agnostic URLs now. #}
|
||||
{% for app in apps -%}
|
||||
Disallow: /{{ app.short }}/downloads/
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Check all our redirects from remora to zamboni."""
|
||||
from django.db import connection
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import Category
|
||||
|
@ -16,20 +15,6 @@ class TestRedirects(TestCase):
|
|||
assert r.redirect_chain[-1][0].endswith(
|
||||
'/en-US/firefox/themes/film-and-tv/')
|
||||
|
||||
def test_contribute_installed(self):
|
||||
r"""`/addon/\d+/about` should go to
|
||||
`/addon/\d+/contribute/installed`."""
|
||||
r = self.client.get(u'/addon/5326/about', follow=True)
|
||||
redirect = r.redirect_chain[-1][0]
|
||||
assert redirect.endswith(
|
||||
'/en-US/firefox/addon/5326/')
|
||||
|
||||
def test_contribute(self):
|
||||
"""`/addons/contribute/$id` should go to `/addon/$id/contribute`."""
|
||||
response = self.client.get(u'/addon/5326/contribute', follow=True)
|
||||
redirect = response.redirect_chain[-1][0]
|
||||
assert redirect.endswith('/en-US/firefox/addon/5326/')
|
||||
|
||||
def test_reviews(self):
|
||||
response = self.client.get('/reviews/display/4', follow=True)
|
||||
self.assert3xx(response, '/en-US/firefox/addon/a4/reviews/',
|
||||
|
@ -137,32 +122,3 @@ class TestRedirects(TestCase):
|
|||
r = self.client.get('/addons/reviews/4/format:rss', follow=True)
|
||||
self.assert3xx(r, '/en-US/firefox/addon/4/reviews/format:rss',
|
||||
status_code=302)
|
||||
|
||||
|
||||
class TestPersonaRedirect(TestCase):
|
||||
fixtures = ['addons/persona']
|
||||
|
||||
def test_persona_redirect(self):
|
||||
r"""`/persona/\d+` should go to `/addon/\d+`."""
|
||||
r = self.client.get('/persona/813', follow=True)
|
||||
self.assert3xx(r, '/en-US/firefox/addon/a15663/', status_code=302)
|
||||
|
||||
def test_persona_redirect_addon_no_exist(self):
|
||||
"""When the persona exists but not its addon, throw a 404."""
|
||||
# Got get shady to separate Persona/Addons.
|
||||
try:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("""
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
UPDATE personas SET addon_id=123 WHERE persona_id=813;
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
""")
|
||||
r = self.client.get('/persona/813', follow=True)
|
||||
assert r.status_code == 404
|
||||
finally:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("""
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
UPDATE personas SET addon_id=15663 WHERE persona_id=813;
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
""")
|
||||
|
|
|
@ -147,13 +147,6 @@ class TestVersion(TestCase):
|
|||
assert ActivityLog.objects.filter(
|
||||
action=amo.LOG.DELETE_VERSION.id).count() == 1
|
||||
|
||||
def test_delete_version_then_detail(self):
|
||||
version, file = self._extra_version_and_file(amo.STATUS_PUBLIC)
|
||||
self.client.post(self.delete_url, self.delete_data)
|
||||
response = self.client.get(
|
||||
reverse('addons.detail', args=[self.addon.slug]))
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_version_delete_version_deleted(self):
|
||||
self.version.delete()
|
||||
response = self.client.post(self.delete_url, self.delete_data)
|
||||
|
|
|
@ -243,9 +243,6 @@ class File(OnChangeMixin, ModelBase):
|
|||
return os.path.join(reverse('downloads.latest', kwargs=kw),
|
||||
'addon-%s-latest%s' % (addon.pk, self.extension))
|
||||
|
||||
def eula_url(self):
|
||||
return reverse('addons.eula', args=[self.version.addon_id, self.id])
|
||||
|
||||
@property
|
||||
def file_path(self):
|
||||
return os.path.join(user_media_path('addons'),
|
||||
|
|
|
@ -194,10 +194,6 @@ class TestFile(TestCase, amo.tests.AMOPaths):
|
|||
'/firefox/downloads/latest/a3615/type:attachment/'
|
||||
'addon-3615-latest.xpi')
|
||||
|
||||
def test_eula_url(self):
|
||||
f = File.objects.get(id=67442)
|
||||
assert f.eula_url() == '/en-US/firefox/addon/3615/eula/67442'
|
||||
|
||||
def test_generate_filename(self):
|
||||
f = File.objects.get(id=67442)
|
||||
assert f.generate_filename() == 'delicious_bookmarks-2.1.072-fx.xpi'
|
||||
|
|
|
@ -395,7 +395,6 @@ class TestCreate(ReviewTest):
|
|||
self.addon = Addon.objects.get(pk=1865)
|
||||
self.user = UserProfile.objects.get(email='root_x@ukr.net')
|
||||
self.qs = Rating.objects.filter(addon=self.addon)
|
||||
self.more_url = self.addon.get_url_path(more=True)
|
||||
self.list_url = jinja_helpers.url(
|
||||
'addons.ratings.list', self.addon.slug)
|
||||
|
||||
|
@ -496,40 +495,6 @@ class TestCreate(ReviewTest):
|
|||
review = Rating.objects.latest('pk')
|
||||
assert six.text_type(review.body) == "foo\nbar"
|
||||
|
||||
def test_add_link_visitor(self):
|
||||
"""
|
||||
Ensure non-logged user can see Add Review links on details page
|
||||
and Reviews listing page.
|
||||
"""
|
||||
self.client.logout()
|
||||
r = self.client.get_ajax(self.more_url)
|
||||
assert pq(r.content)('#add-review').length == 1
|
||||
r = self.client.get(jinja_helpers.url(
|
||||
'addons.ratings.list', self.addon.slug))
|
||||
doc = pq(r.content)
|
||||
assert doc('#add-review').length == 1
|
||||
assert doc('#add-first-review').length == 0
|
||||
|
||||
def test_add_link_logged(self):
|
||||
"""Ensure logged user can see Add Review links."""
|
||||
r = self.client.get_ajax(self.more_url)
|
||||
assert pq(r.content)('#add-review').length == 1
|
||||
r = self.client.get(self.list_url)
|
||||
doc = pq(r.content)
|
||||
assert doc('#add-review').length == 1
|
||||
assert doc('#add-first-review').length == 0
|
||||
|
||||
def test_add_link_dev(self):
|
||||
"""Ensure developer cannot see Add Review links."""
|
||||
self.login_dev()
|
||||
r = self.client.get_ajax(self.more_url)
|
||||
assert pq(r.content)('#add-review').length == 0
|
||||
r = self.client.get(jinja_helpers.url(
|
||||
'addons.ratings.list', self.addon.slug))
|
||||
doc = pq(r.content)
|
||||
assert doc('#add-review').length == 0
|
||||
assert doc('#add-first-review').length == 0
|
||||
|
||||
def test_list_none_add_review_link_visitor(self):
|
||||
"""If no reviews, ensure visitor user cannot see Add Review link."""
|
||||
Rating.objects.all().delete()
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
{% macro tag_li(tag, addon=None, css_class='') -%}
|
||||
<li id="taglink-{{ tag.id }}" class="{{ css_class }}">
|
||||
{% if tag.can_reverse() %}
|
||||
<a href="{{ url('tags.detail', tag.tag_text) }}" class="tagitem">
|
||||
{{ tag.tag_text }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="tagitem">{{ tag.tag_text }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
{%- endmacro %}
|
||||
|
||||
{% if tags %}
|
||||
<ul class="addon-tags nojs" id="addonid-{{ addon.id }}">
|
||||
{% for tag in tags %}
|
||||
{{ tag_li(tag, addon=addon, css_class='tag') }}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
|
@ -1,17 +0,0 @@
|
|||
import jinja2
|
||||
|
||||
from django_jinja import library
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('tags/tag_list.html')
|
||||
@jinja2.contextfunction
|
||||
def tag_list(context, addon, tags=None):
|
||||
"""Display list of tags, with delete buttons."""
|
||||
if tags is None:
|
||||
tags = []
|
||||
|
||||
c = dict(context.items())
|
||||
c.update({'addon': addon,
|
||||
'tags': tags})
|
||||
return c
|
|
@ -1,42 +0,0 @@
|
|||
from mock import Mock
|
||||
from pyquery import PyQuery as pq
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import Addon
|
||||
|
||||
|
||||
def render(s, context=None):
|
||||
"""Taken from jingo.tests.utils, previously jingo.tests.test_helpers."""
|
||||
if context is None:
|
||||
context = {}
|
||||
t = amo.utils.from_string(s)
|
||||
return t.render(context)
|
||||
|
||||
|
||||
class TestHelpers(amo.tests.TestCase):
|
||||
fixtures = ('base/addon_3615', 'base/user_2519', 'base/user_4043307',
|
||||
'tags/tags')
|
||||
|
||||
def test_tag_list(self):
|
||||
addon = Addon.objects.get(id=3615)
|
||||
|
||||
request = Mock()
|
||||
request.user = addon.authors.all()[0]
|
||||
|
||||
tags = addon.tags.not_denied()
|
||||
|
||||
ctx = {
|
||||
'APP': amo.FIREFOX,
|
||||
'LANG': 'en-us',
|
||||
'request': request,
|
||||
'addon': addon,
|
||||
'tags': tags}
|
||||
|
||||
# no tags, no list
|
||||
s = render('{{ tag_list(addon) }}', ctx)
|
||||
assert s.strip() == ""
|
||||
|
||||
s = render('{{ tag_list(addon, tags=tags) }}', ctx)
|
||||
assert s, "Non-empty tags must return tag list."
|
||||
doc = pq(s)
|
||||
assert doc('li').length == len(tags)
|
|
@ -1,84 +0,0 @@
|
|||
from django.urls import NoReverseMatch, reverse
|
||||
|
||||
from pyquery import PyQuery as pq
|
||||
|
||||
from olympia.addons.models import Addon
|
||||
from olympia.amo.tests import TestCase
|
||||
|
||||
|
||||
class TestManagement(TestCase):
|
||||
fixtures = ['base/addon_3615',
|
||||
'tags/tags.json']
|
||||
|
||||
def test_tags_details_view(self):
|
||||
"""Test that there are some tags being shown on the details page."""
|
||||
url = reverse('addons.detail_more', args=['a3615'])
|
||||
response = self.client.get_ajax(url, follow=True)
|
||||
doc = pq(response.content)
|
||||
assert len(doc('li.tag')) == 4
|
||||
assert 'Tags' in [d.text for d in doc('h3')]
|
||||
|
||||
|
||||
class TestXSS(TestCase):
|
||||
fixtures = ['base/addon_3615',
|
||||
'tags/tags.json']
|
||||
|
||||
xss = "<script src='foo.bar'>"
|
||||
escaped = "<script src='foo.bar'>"
|
||||
|
||||
def setUp(self):
|
||||
self.addon = Addon.objects.get(pk=3615)
|
||||
self.tag = self.addon.tags.all()[0]
|
||||
self.tag.tag_text = self.xss
|
||||
self.tag.num_addons = 1
|
||||
self.tag.save()
|
||||
|
||||
def test_tags_xss_detail(self):
|
||||
"""Test xss tag detail."""
|
||||
url = reverse('addons.detail_more', args=['a3615'])
|
||||
response = self.client.get_ajax(url, follow=True)
|
||||
content = response.content.decode('utf-8')
|
||||
assert self.escaped in content
|
||||
assert self.xss not in content
|
||||
|
||||
|
||||
class TestXSSURLFail(TestCase):
|
||||
fixtures = ['base/addon_3615',
|
||||
'tags/tags.json']
|
||||
|
||||
xss = "<script>alert('xss')</script>"
|
||||
escaped = "<script>alert('xss')</script>"
|
||||
|
||||
def setUp(self):
|
||||
self.addon = Addon.objects.get(pk=3615)
|
||||
self.tag = self.addon.tags.all()[0]
|
||||
self.tag.tag_text = self.xss
|
||||
self.tag.num_addons = 1
|
||||
self.tag.save()
|
||||
|
||||
def test_tags_xss(self):
|
||||
"""Test xss tag detail."""
|
||||
url = reverse('addons.detail_more', args=['a3615'])
|
||||
response = self.client.get_ajax(url, follow=True)
|
||||
content = response.content.decode('utf-8')
|
||||
assert self.escaped in content
|
||||
assert self.xss not in content
|
||||
|
||||
def test_tags_xss_home(self):
|
||||
"""Test xss tag home."""
|
||||
self.assertRaises(NoReverseMatch, reverse,
|
||||
'tags.detail', args=[self.xss])
|
||||
|
||||
def test_no_reverse(self):
|
||||
assert not self.tag.can_reverse()
|
||||
|
||||
|
||||
class TestNoTags(TestCase):
|
||||
fixtures = ['base/addon_3615']
|
||||
|
||||
def test_tags_no_details_view(self):
|
||||
"""Test that there is no tag header tags being shown."""
|
||||
url = reverse('addons.detail', args=['a3615'])
|
||||
response = self.client.get(url, follow=True)
|
||||
doc = pq(response.content)
|
||||
assert 'Tags' not in [d.text for d in doc('h3')]
|
|
@ -100,14 +100,6 @@ urlpatterns = [
|
|||
url(r'^pages/about$',
|
||||
lambda r: redirect('pages.about', permanent=True)),
|
||||
|
||||
# Redirect persona/xxx
|
||||
url(r'^getpersonas$',
|
||||
lambda r: redirect('http://www.getpersonas.com/gallery/All/Popular',
|
||||
permanent=True)),
|
||||
|
||||
url(r'^persona/(?P<persona_id>\d+)',
|
||||
addons_views.persona_redirect, name='persona'),
|
||||
|
||||
url(r'^personas/film and tv/?$',
|
||||
lambda r: redirect('browse.personas', 'film-and-tv', permanent=True)),
|
||||
|
||||
|
|
|
@ -84,16 +84,6 @@ def _user_link(user, max_text_length=None):
|
|||
jinja2.escape(force_text(name)))
|
||||
|
||||
|
||||
@library.global_function
|
||||
@library.render_with('users/report_abuse.html')
|
||||
@jinja2.contextfunction
|
||||
def user_report_abuse(context, hide, profile):
|
||||
new = dict(context.items())
|
||||
new.update({'hide': hide, 'profile': profile,
|
||||
'abuse_form': context['abuse_form']})
|
||||
return new
|
||||
|
||||
|
||||
@library.global_function
|
||||
@jinja2.contextfunction
|
||||
def manage_fxa_link(context):
|
||||
|
|
|
@ -9,8 +9,7 @@ from pyquery import PyQuery as pq
|
|||
from six.moves.urllib_parse import parse_qs, urlparse
|
||||
|
||||
from olympia import amo
|
||||
from olympia.addons.models import Addon
|
||||
from olympia.addons.tests.test_views import TestPersonas
|
||||
from olympia.addons.models import Addon, AddonUser
|
||||
from olympia.amo.tests import TestCase
|
||||
from olympia.users.models import UserProfile
|
||||
from olympia.users.templatetags.jinja_helpers import (
|
||||
|
@ -110,7 +109,8 @@ def test_user_link_unicode():
|
|||
u.display_name))
|
||||
|
||||
|
||||
class TestAddonUsersList(TestPersonas, TestCase):
|
||||
class TestAddonUsersList(TestCase):
|
||||
fixtures = ['addons/persona', 'base/users']
|
||||
|
||||
def setUp(self):
|
||||
super(TestAddonUsersList, self).setUp()
|
||||
|
@ -118,6 +118,9 @@ class TestAddonUsersList(TestPersonas, TestCase):
|
|||
self.persona = self.addon.persona
|
||||
self.create_addon_user(self.addon)
|
||||
|
||||
def create_addon_user(self, addon):
|
||||
return AddonUser.objects.create(addon=addon, user_id=999)
|
||||
|
||||
def test_by(self):
|
||||
"""Test that the by... bit works."""
|
||||
# Need to re-fetch the add-on since the user was attached after the
|
||||
|
|
Загрузка…
Ссылка в новой задаче