Merge pull request #808 from muffinresearch/price-tiers-ui-868179

Price tiers UI (bug 868179)
This commit is contained in:
Stuart Colville 2013-06-14 11:22:28 -07:00
Родитель 0cf174dc80 afb110484e
Коммит 6f8b459c34
13 изменённых файлов: 288 добавлений и 68 удалений

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

@ -62,7 +62,7 @@ class Price(amo.models.ModelBase):
return _('Tier %s' % self.name)
def __unicode__(self):
return u'%s - $%s' % (self.tier_name(), self.price)
return u'$%s' % self.price
@staticmethod
def transformer(prices):

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

@ -457,6 +457,24 @@ button.loading-submit:after,
table td {
border-top: 0;
}
.regions table {
tr:last-child th,
th {
border-top: 0;
font-size: 12px;
padding: 1em 0;
}
td {
border-top: 1px dotted $border-taupe;
vertical-align: middle;
}
tr:first-child th {
padding: 0 0 1em;
}
tr:first-child td {
padding: 1em 0;
}
}
.screenshot.thumbnail {
width: 100px;
height: 75px;

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

@ -333,12 +333,12 @@ form .char-count b {
padding-top: 0;
}
.checkbox-choices {
.checkbox-choices:not(.regions) {
columns(3, 1.5em);
margin-bottom: .5em;
}
td .checkbox-choices {
td .checkbox-choices:not(.regions) {
column-count(2);
}

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

@ -420,3 +420,30 @@
.rejected .modify-account {
display: none;
}
label.disabled {
color: #ccc;
}
.devhub-form table td.region-container {
border: 0;
padding-top: 0;
}
.devhub-form table th.region-toggle {
padding-bottom: 0;
}
.regions {
.region-heading {
display: block;
hidetext();
}
.local-currency-heading,
.my-currency {
display: block;
}
td .local-retail {
display: block;
}
}

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

@ -3,9 +3,9 @@
var $this = $(this);
var $choices = $this.closest('td, div').find('.checkbox-choices input[type=checkbox]:not(:disabled)');
if ($this.hasClass('all')) {
$choices.attr('checked', true);
$choices.prop('checked', true).trigger('change');
} else {
$choices.removeAttr('checked');
$choices.prop('checked', false).trigger('change');
}
})).on('editLoaded.disableCheckboxes', function(e) {
// Disable individual checkbox fields when we see them.

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

@ -1,6 +1,10 @@
define('payments', [], function() {
'use strict';
var currentPrice;
var $regions = $('.regions');
var pricesApiEndpoint = $regions.data('pricelistApiUrl') + '{0}/';
function getOverlay(opts) {
var id = opts;
if (_.isObject(opts)) {
@ -18,7 +22,7 @@ define('payments', [], function() {
}
function setupPaymentAccountOverlay($overlay, onsubmit) {
$overlay.on('submit', 'form', _pd(function(e) {
$overlay.on('submit', 'form', _pd(function() {
var $form = $(this);
var $waiting_overlay = getOverlay('bango-waiting');
var $old_overlay = $overlay.children('section');
@ -68,18 +72,80 @@ define('payments', [], function() {
}));
}
function updatePrices() {
/*jshint validthis:true */
var $this = $(this);
var selectedPrice = $this.val() || '';
var apiUrl = format(pricesApiEndpoint, parseInt(selectedPrice, 10));
var disabledRegions = $regions.data('disabledRegions');
if (currentPrice == selectedPrice) {
return;
}
// Clear out existing price data.
$regions.find('.local-retail').text('');
$.ajax({
url: apiUrl,
success: function(data) {
var prices = data.prices || [];
var tierPrice = data.price;
var seen = [];
// Iterate over the prices for the regions
for (var i=0, j=prices.length; i<j; i++) {
var price = prices[i];
var region = price.region;
var $chkbox = $regions.find('input:checkbox[value=' + region + ']');
// Skip if over regions that should be disabled e.g games app in Brazil.
if (disabledRegions.indexOf(region) > -1) {
continue;
}
// Enable checkboxes for those that we have price info for.
$chkbox.prop('disabled', false)
.parent('label').removeClass('disabled')
.closest('tr').find('.local-retail')
.text(price.price +' '+ price.currency)
.toggle($chkbox.prop('checked'));
seen.push($chkbox[0]);
}
// Disable everything else.
$regions.find('input[type=checkbox]').not(seen)
.prop('checked', false)
.prop('disabled', true)
.parent('label').addClass('disabled')
.trigger('change');
},
dataType: "json"
});
currentPrice = selectedPrice;
}
function handleCheckboxChange() {
/*jshint validthis:true */
var $this = $(this);
$this.closest('tr').find('.local-retail').toggle($this.prop('checked'));
}
function init() {
$('#regions').trigger('editLoaded');
$('.update-payment-type button').click(function(e) {
$('.update-payment-type button').click(function() {
$('input[name=toggle-paid]').val($(this).data('type'));
});
var $paid_island = $('#paid-island, #paid-upsell-island');
var $paid_island = $('#paid-island, #paid-upsell-island, #paid-regions-island');
var $free_island = $('#regions-island');
$('#submit-payment-type.hasappendix').on('tabs-changed', function(e, tab) {
$paid_island.toggle(tab.id == 'paid-tab-header');
$free_island.toggle(tab.id == 'free-tab-header');
});
$('#id_price').on('change', updatePrices)
.each(updatePrices);
$('.regions').on('change', 'input[type=checkbox]', handleCheckboxChange);
}
return {

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

@ -0,0 +1,4 @@
<p class="note disabled-regions">
<a href="https://developer.mozilla.org/en-US/docs/Apps/Marketplace_Review" target="_blank">
{{ _('Learn why some regions are restricted.') }}</a>
</p>

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

@ -0,0 +1,7 @@
<div class="island warning">
{% trans %}
Your app will no longer be listed in certain regions because those
regions do not support payments. We have transferred your region
choices. Please review the changes before saving.
{% endtrans %}
</div>

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

@ -0,0 +1,11 @@
{{ region_form.other_regions }}
{{ region_form.other_regions.label_tag() }}
{{ region_form.other_regions.errors }}
<div class="hint note">
{%- trans %}
Your app will be displayed in the worldwide Marketplace and
in any regional marketplace that is added in the future.
You will receive an email notification when a new region
is added.
{% endtrans -%}
</div>

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

@ -0,0 +1,6 @@
<label data-for="region">{{ region_form.regions.label }}</label>
{{ region_form.non_field_errors() }}
<p class="toggles">
<a href="#" class="all">{{ _('Select All') }}</a> &middot;
<a href="#" class="none">{{ _('None') }}</a>
</p>

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

@ -105,7 +105,7 @@
{% if is_paid %}
<div id="paid-island">
{{ disabled_payments_notice() }}
<h2>{{ _('Prices and payment accounts') }}</h2>
<h2>{{ _('Payment accounts') }}</h2>
{% if is_incomplete %}
<div class="island warning">
{%- trans %}
@ -115,6 +115,38 @@
</div>
{% endif %}
<section class="island payments">
<table>
<tbody>
<tr>
<th><label data-for="accounts">{{ _('Payment Account') }}</label></th>
<td>
<div id="bango-account-list" data-url="{{ url('mkt.developers.bango.payment_accounts_form') }}">
{{ bango_account_list_form.errors }}
{% include 'developers/payments/includes/bango_accounts_form.html' %}
</div>
<a href="#" class="payment-account-actions" data-action="add">
{{- _('Add or manage payment accounts') -}}
</a>
</td>
</tr>
</tbody>
</table>
<div class="listing-footer">
<button>{{ _('Save Changes') }}</button>
</div>
</section>
</div>
{% endif %}
{% if is_paid %}
<div id="paid-regions-island">
<h2>{{ _('Prices and countries') }}</h2>
{% if region_form.has_inappropriate_regions() %}
{% include 'developers/payments/includes/regions_inappropriate.html' %}
{% endif %}
<section id="regions" class="island">
<table>
<tbody>
<tr>
@ -134,6 +166,91 @@
{{ form.allow_inapp }}
</td>
</tr>
<tr>
<th colspan="2" class="region-toggle">
{% include 'developers/payments/includes/regions_toggle.html' %}
</th>
</tr>
<tr>
<td colspan="2" class="region-container">
<div class="checkbox-choices regions"
data-disabled-regions="{{ region_form.disabled_regions|json }}"
data-pricelist-api-url="{{ api_pricelist_url }}">
{{ region_form.regions.errors }}
<table>
<thead>
<th><span class="region-heading">{{ _('Region') }}</span></th>
<th>{{ _('Retail price') }}
<span class="local-currency-heading">({{ _('local currency') }})</span></th>
</thead>
<tbody>
{% for value, text in region_form.regions.field.choices %}
<tr>
<td>
<label class="disabled">
<input type="checkbox" disabled
{% if value in region_form.initial.regions %}checked{% endif %}
name="regions" value="{{ value }}" />{{ text }}</label>
</td>
<td><span class="local-retail"></span></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</td>
</tr>
{% if region_form.disabled_regions %}
<tr>
<td colspan="2">
{% include 'developers/payments/includes/regions_disabled.html' %}
</td>
</tr>
{% endif %}
<tr>
<td colspan="2">
{% include 'developers/payments/includes/regions_other.html' %}
</td>
</tr>
</tbody>
</table>
<div class="listing-footer">
<button class="button">{{ _('Save Changes') }}</button>
</div>
</section>
</div>
{% else %}
{# Non-paid app region lists #}
<div id="regions-island">
<h2>{{ _('Regions and listings') }}</h2>
{% if region_form.has_inappropriate_regions() %}
{% include 'developers/payments/includes/regions_inappropriate.html' %}
{% endif %}
<section id="regions" class="island">
{% include 'developers/payments/includes/regions_toggle.html' %}
{{ region_form.regions.errors }}
<div class="checkbox-choices"
data-disabled="{{ region_form.disabled_regions|json }}">
{{ region_form.regions }}
</div>
{% if region_form.disabled_regions %}
{% include 'developers/payments/includes/regions_disabled.html' %}
{% endif %}
<div class="other-regions">
{% include 'developers/payments/includes/regions_other.html' %}
</div>
<button>{{ _('Save Changes') }}</button>
</section>
</div>
{% endif %}
{% if is_paid %}
<div id="paid-upsell-island">
{{ disabled_payments_notice() }}
<h2>{{ _('Promote as upgrade to free version') }}</h2>
<section class="island upsell">
<table>
<tbody>
<tr>
<th>
{{ tip(_('This is a paid upgrade of'),
@ -157,72 +274,14 @@
{% endif %}
</td>
</tr>
<tr>
<th><label data-for="accounts">{{ _('Payment Account') }}</label>
</th>
<td>
<div id="bango-account-list" data-url="{{ url('mkt.developers.bango.payment_accounts_form') }}">
{{ bango_account_list_form.errors }}
{% include 'developers/payments/includes/bango_accounts_form.html' %}
</div>
<a href="#" class="payment-account-actions" data-action="add">
{{- _('Add or manage payment accounts') -}}
</a>
</td>
</tr>
</tbody>
</table>
<div class="listing-footer">
<button>{{ _('Save Changes') }}</button>
</div>
</section>
</div>
{% endif %}
<h2>{{ _('Regions and listings') }}</h2>
{% if region_form.has_inappropriate_regions() %}
<div class="island warning">
{% trans %}
Your app will no longer be listed in certain regions because those
regions do not support payments. We have transferred your region
choices. Please review the changes before saving.
{% endtrans %}
</div>
{% endif %}
<section id="regions" class="island">
{{ region_form.non_field_errors() }}
{{ region_form.regions.label }}
<p class="toggles">
<a href="#" class="all">{{ _('Select All') }}</a> &middot;
<a href="#" class="none">{{ _('None') }}</a>
</p>
{{ region_form.regions.errors }}
<div class="checkbox-choices"
data-disabled="{{ region_form.disabled_regions|json }}">
{{ region_form.regions }}
</div>
{% if region_form.disabled_regions %}
<p class="note disabled-regions">
<a href="https://developer.mozilla.org/en-US/docs/Apps/Marketplace_Review" target="_blank">
{{ _('Learn why some regions are restricted.') }}</a>
</p>
{% endif %}
<div class="other-regions">
{{ region_form.other_regions }}
{{ region_form.other_regions.label_tag() }}
{{ region_form.other_regions.errors }}
<div class="hint note">
{%- trans %}
Your app will be displayed in the worldwide Marketplace and
in any regional marketplace that is added in the future.
You will receive an email notification when a new region
is added.
{% endtrans -%}
</div>
</div>
<button>{{ _('Save Changes') }}</button>
</section>
</form>
</section>
{% include 'developers/includes/addons_edit_nav.html' %}

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

@ -273,6 +273,25 @@ class TestPayments(amo.tests.TestCase):
self.assert3xx(res, self.url)
eq_(self.get_webapp().premium_type, amo.ADDON_PREMIUM)
def test_check_api_url_in_context(self):
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.get(self.url)
eq_(res.context['api_pricelist_url'],
reverse('api_dispatch_list', kwargs={'resource_name': 'prices',
'api_name': 'webpay'}))
def test_regions_display_free(self):
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.get(self.url)
self.assertIn('id="regions-island"', res.content)
self.assertNotIn('id="paid-regions-island"', res.content)
def test_regions_display_premium(self):
self.webapp.update(premium_type=amo.ADDON_PREMIUM)
res = self.client.get(self.url)
self.assertIn('id="paid-regions-island"', res.content)
self.assertNotIn('id="regions-island"', res.content)
def test_premium_in_app_passes(self):
self.webapp.update(premium_type=amo.ADDON_FREE)
res = self.client.post(

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

@ -134,7 +134,10 @@ def payments(request, addon_id, addon, webapp=False):
# Waffles
'payments_enabled':
waffle.flag_is_active(request, 'allow-b2g-paid-submission') and
not waffle.switch_is_active('disabled-payments')})
not waffle.switch_is_active('disabled-payments'),
'api_pricelist_url':
reverse('api_dispatch_list', kwargs={'resource_name': 'prices',
'api_name': 'webpay'})})
@login_required