Bug 661651 - Adding admin tool for the selection of addons of the month by locale.
This commit is contained in:
Родитель
0b0d751a60
Коммит
96073b59cf
|
@ -17,6 +17,7 @@ import amo.models
|
|||
import sharing.utils as sharing
|
||||
from amo.utils import sorted_groupby
|
||||
from amo.urlresolvers import reverse
|
||||
from product_details import product_details
|
||||
from addons.models import Addon, AddonRecommendation
|
||||
from applications.models import Application
|
||||
from stats.models import CollectionShareCountTotal
|
||||
|
@ -558,3 +559,21 @@ class FeaturedCollection(amo.models.ModelBase):
|
|||
def __unicode__(self):
|
||||
return u'%s (%s: %s)' % (self.collection, self.application,
|
||||
self.locale)
|
||||
|
||||
|
||||
def locale_generator():
|
||||
return (('', u'(Default Locale)'),) + tuple(
|
||||
(i, product_details.languages[i]['native'])
|
||||
for i in settings.AMO_LANGUAGES)
|
||||
|
||||
|
||||
class MonthlyPick(amo.models.ModelBase):
|
||||
LOCALES = locale_generator()
|
||||
|
||||
addon = models.ForeignKey(Addon)
|
||||
blurb = models.TextField()
|
||||
image = models.URLField()
|
||||
locale = models.CharField(max_length=30, choices=LOCALES, unique=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "monthly_pick"
|
||||
|
|
|
@ -15,7 +15,7 @@ import amo
|
|||
from product_details import product_details
|
||||
from amo.urlresolvers import reverse
|
||||
from applications.models import Application, AppVersion
|
||||
from bandwagon.models import Collection, FeaturedCollection
|
||||
from bandwagon.models import Collection, FeaturedCollection, MonthlyPick
|
||||
from zadmin.models import ValidationJob
|
||||
|
||||
|
||||
|
@ -165,3 +165,16 @@ class OAuthConsumerForm(happyforms.ModelForm):
|
|||
class Meta:
|
||||
model = Consumer
|
||||
fields = ['name', 'description', 'status']
|
||||
|
||||
|
||||
class MonthlyPickForm(happyforms.ModelForm):
|
||||
class Meta:
|
||||
model = MonthlyPick
|
||||
widgets = {
|
||||
'addon': forms.TextInput(),
|
||||
'blurb': forms.Textarea(attrs={'cols': 20, 'rows': 2})
|
||||
}
|
||||
|
||||
MonthlyPickFormSet = modelformset_factory(MonthlyPick,
|
||||
form=MonthlyPickForm,
|
||||
can_delete=True, extra=0)
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
{% extends "admin/base.html" %}
|
||||
|
||||
{% set title = 'Monthly Pick Manager' %}
|
||||
{% block title %}{{ page_title(title) }}{% endblock %}
|
||||
|
||||
{% block bodyattrs %}
|
||||
data-collections-url="{{ url('zadmin.collections_json') }}"
|
||||
data-featured-collection-url="{{ url('zadmin.featured_collection') }}"
|
||||
{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
<link rel="stylesheet" href="{{ media('css/zamboni/admin_features.css') }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ super() }}
|
||||
<script src="{{ media('js/zamboni/admin_features.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% macro fc(form) %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ form.id }}
|
||||
{{ form.addon }}
|
||||
{{ form.addon.errors }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form.locale }}
|
||||
{{ form.locale.errors }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form.blurb }}
|
||||
{{ form.blurb.errors }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form.image }}
|
||||
{{ form.image.errors }}
|
||||
</td>
|
||||
<td>
|
||||
<span class="js-hidden delete">{{ form.DELETE }}{{ form.DELETE.label_tag() }}</span>
|
||||
<a href="#" class="remove">×</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{{ title }}</h2>
|
||||
<form action="" method="post">
|
||||
{{ csrf() }}
|
||||
{% include "messages.html" %}
|
||||
{{ form.non_form_errors() }}
|
||||
{{ form.management_form }}
|
||||
<table>
|
||||
<thead>
|
||||
<th>Addon ID</th>
|
||||
<th>Locale</th>
|
||||
<th>Blurb</th>
|
||||
<th>Image URL</th>
|
||||
<th class="js-hidden">Delete</th>
|
||||
</thead>
|
||||
<tbody id="features">
|
||||
{% for form in form.forms %}
|
||||
{{ fc(form) }}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot class="hidden">
|
||||
{{ fc(form.empty_form) }}
|
||||
</tfoot>
|
||||
</table>
|
||||
<p><a href="#" id="add">Add a Featured Addon</a></p>
|
||||
<p>
|
||||
<button type="submit">Save Changes</button> or <a href="">Cancel</a>
|
||||
</p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -21,7 +21,7 @@ from amo.tests import (formset, initial, close_to_now,
|
|||
from amo.urlresolvers import reverse
|
||||
from addons.models import Addon
|
||||
from applications.models import AppVersion
|
||||
from bandwagon.models import FeaturedCollection
|
||||
from bandwagon.models import Collection, FeaturedCollection, MonthlyPick
|
||||
from devhub.models import ActivityLog
|
||||
from files.models import Approval, File
|
||||
from users.models import UserProfile
|
||||
|
@ -1028,6 +1028,55 @@ class TestEmailPreview(amo.tests.TestCase):
|
|||
'the subject', 'Hello Ivan Krsti\xc4\x87'])
|
||||
|
||||
|
||||
class TestMonthlyPick(amo.tests.TestCase):
|
||||
fixtures = ['base/addon_3615', 'base/apps', 'base/users']
|
||||
|
||||
def setUp(self):
|
||||
assert self.client.login(username='admin@mozilla.com',
|
||||
password='password')
|
||||
self.url = reverse('zadmin.monthly_pick')
|
||||
addon = Addon.objects.get(pk=3615)
|
||||
MonthlyPick.objects.create(addon=addon,
|
||||
locale='zh-CN',
|
||||
blurb="test data",
|
||||
image="http://www.google.com")
|
||||
self.f = self.client.get(self.url).context['form'].initial_forms[0]
|
||||
self.initial = self.f.initial
|
||||
|
||||
def test_form_initial(self):
|
||||
eq_(self.initial['addon'], 3615)
|
||||
eq_(self.initial['locale'], 'zh-CN')
|
||||
eq_(self.initial['blurb'], 'test data')
|
||||
eq_(self.initial['image'], 'http://www.google.com')
|
||||
|
||||
def test_success_insert(self):
|
||||
dupe = initial(self.f)
|
||||
del dupe['id']
|
||||
dupe.update(locale='fr')
|
||||
data = formset(initial(self.f), dupe, initial_count=1)
|
||||
r = self.client.post(self.url, data)
|
||||
eq_(MonthlyPick.objects.count(), 2)
|
||||
eq_(MonthlyPick.objects.all()[1].locale, 'fr')
|
||||
|
||||
def test_success_update(self):
|
||||
d = initial(self.f)
|
||||
d.update(locale='fr')
|
||||
r = self.client.post(self.url, formset(d, initial_count=1))
|
||||
eq_(r.status_code, 302)
|
||||
eq_(MonthlyPick.objects.all()[0].locale, 'fr')
|
||||
|
||||
def test_success_delete(self):
|
||||
d = initial(self.f)
|
||||
d.update(DELETE=True)
|
||||
r = self.client.post(self.url, formset(d, initial_count=1))
|
||||
eq_(MonthlyPick.objects.count(), 0)
|
||||
|
||||
def test_require_login(self):
|
||||
self.client.logout()
|
||||
r = self.client.get(self.url)
|
||||
eq_(r.status_code, 302)
|
||||
|
||||
|
||||
class TestFeatures(amo.tests.TestCase):
|
||||
fixtures = ['base/apps', 'base/users', 'base/collections']
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ urlpatterns = patterns('',
|
|||
url('^features/featured-collection$', views.featured_collection,
|
||||
name='zadmin.featured_collection'),
|
||||
|
||||
url('^monthly-pick$', views.monthly_pick,
|
||||
name='zadmin.monthly_pick'),
|
||||
|
||||
url('^elastic$', views.elastic, name='zadmin.elastic'),
|
||||
url('^mail$', views.mail, name='zadmin.mail'),
|
||||
url('^celery$', views.celery, name='zadmin.celery'),
|
||||
|
|
|
@ -43,7 +43,7 @@ from versions.models import Version
|
|||
|
||||
from . import tasks
|
||||
from .forms import (BulkValidationForm, FeaturedCollectionFormSet, NotifyForm,
|
||||
OAuthConsumerForm)
|
||||
OAuthConsumerForm, MonthlyPickFormSet)
|
||||
from .models import ValidationJob, EmailPreviewTopic, ValidationJobTally
|
||||
|
||||
log = commonware.log.getLogger('z.zadmin')
|
||||
|
@ -394,6 +394,16 @@ def features(request):
|
|||
return jingo.render(request, 'zadmin/features.html', dict(form=form))
|
||||
|
||||
|
||||
@admin.site.admin_view
|
||||
def monthly_pick(request):
|
||||
form = MonthlyPickFormSet(request.POST or None)
|
||||
if request.method == 'POST' and form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, 'Changes successfully saved.')
|
||||
return redirect('zadmin.monthly_pick')
|
||||
return jingo.render(request, 'zadmin/monthly_pick.html', dict(form=form))
|
||||
|
||||
|
||||
@admin.site.admin_view
|
||||
def elastic(request):
|
||||
INDEX = site_settings.ES_INDEX
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
CREATE TABLE `monthly_pick` (
|
||||
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||
`created` datetime NOT NULL,
|
||||
`modified` datetime NOT NULL,
|
||||
`addon_id` int(11) unsigned NOT NULL,
|
||||
`blurb` longtext NOT NULL,
|
||||
`image` varchar(200) NOT NULL,
|
||||
`locale` varchar(30) NOT NULL UNIQUE
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
ALTER TABLE `monthly_pick` ADD CONSTRAINT `addon_id_refs_id_a94677f3` FOREIGN KEY (`addon_id`) REFERENCES `addons` (`id`);
|
||||
CREATE INDEX `monthly_pick_cc3d5937` ON `monthly_pick` (`addon_id`);
|
Загрузка…
Ссылка в новой задаче