This commit is contained in:
Gregory Koberger 2011-03-25 16:03:32 -07:00
Родитель ef14266c9d
Коммит b487a41ce4
8 изменённых файлов: 201 добавлений и 68 удалений

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

@ -6,10 +6,10 @@ from django.utils.datastructures import SortedDict
import django_tables as tables import django_tables as tables
import jinja2 import jinja2
from jingo import register from jingo import register
from tower import ugettext_lazy as _, ungettext as ngettext from tower import ugettext as _, ugettext_lazy as _lazy, ungettext as ngettext
import amo import amo
from amo.helpers import page_title, absolutify from amo.helpers import breadcrumbs, page_title, absolutify
from amo.urlresolvers import reverse from amo.urlresolvers import reverse
from amo.utils import send_mail as amo_send_mail from amo.utils import send_mail as amo_send_mail
@ -22,10 +22,10 @@ from editors.sql_table import SQLTable
@register.function @register.function
def file_review_status(addon, file): def file_review_status(addon, file):
if addon.status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]: if addon.status in [amo.STATUS_UNREVIEWED, amo.STATUS_LITE]:
return _('Pending Preliminary Review') return _lazy('Pending Preliminary Review')
elif addon.status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED, elif addon.status in [amo.STATUS_NOMINATED, amo.STATUS_LITE_AND_NOMINATED,
amo.STATUS_PUBLIC]: amo.STATUS_PUBLIC]:
return _('Pending Full Review') return _lazy('Pending Full Review')
return amo.STATUS_CHOICES[file.status] return amo.STATUS_CHOICES[file.status]
@ -36,20 +36,60 @@ def editor_page_title(context, title=None, addon=None):
if addon: if addon:
title = u'%s :: %s' % (title, addon.name) title = u'%s :: %s' % (title, addon.name)
else: else:
section = _('Editor Tools') section = _lazy('Editor Tools')
title = u'%s :: %s' % (title, section) if title else section title = u'%s :: %s' % (title, section) if title else section
return page_title(context, title) return page_title(context, title)
@register.function
@jinja2.contextfunction
def editors_breadcrumbs(context, queue=None, queue_id=None, items=None):
"""
Wrapper function for ``breadcrumbs``. Prepends 'Editor Tools'
breadcrumbs.
**items**
list of [(url, label)] to be inserted after Add-on.
**addon**
Adds the Add-on name to the end of the trail. If items are
specified then the Add-on will be linked.
**add_default**
Prepends trail back to home when True. Default is False.
"""
crumbs = [(reverse('editors.home'), _('Editor Tools'))]
if queue_id:
queue_ids = {4: 'pending', 3: 'nominated', 1: 'prelim'}
queue = queue_ids.get(queue_id, 'queue')
if queue:
queues = {'queue': _("Queue"),
'pending': _("Pending Updates"),
'nominated': _("Full Reviews"),
'prelim': _("Preliminary Reviews"),
'moderated': _("Moderated Reviews")}
if items and not queue == 'queue':
url = reverse('editors.queue_%s' % queue)
else:
# The Addon is the end of the trail.
url = None
crumbs.append((url, queues[queue]))
if items:
crumbs.extend(items)
return breadcrumbs(context, crumbs, add_default=False)
class EditorQueueTable(SQLTable): class EditorQueueTable(SQLTable):
addon_name = tables.Column(verbose_name=_(u'Addon')) addon_name = tables.Column(verbose_name=_lazy(u'Addon'))
addon_type_id = tables.Column(verbose_name=_(u'Type')) addon_type_id = tables.Column(verbose_name=_lazy(u'Type'))
waiting_time_min = tables.Column(verbose_name=_(u'Waiting Time')) waiting_time_min = tables.Column(verbose_name=_lazy(u'Waiting Time'))
flags = tables.Column(verbose_name=_(u'Flags'), sortable=False) flags = tables.Column(verbose_name=_lazy(u'Flags'), sortable=False)
applications = tables.Column(verbose_name=_(u'Applications'), applications = tables.Column(verbose_name=_lazy(u'Applications'),
sortable=False) sortable=False)
additional_info = tables.Column(verbose_name=_(u'Additional Information'), additional_info = tables.Column(
sortable=False) verbose_name=_lazy(u'Additional Information'), sortable=False)
def render_addon_name(self, row): def render_addon_name(self, row):
url = '%s?num=%s' % (reverse('editors.review', url = '%s?num=%s' % (reverse('editors.review',
@ -66,16 +106,16 @@ class EditorQueueTable(SQLTable):
def render_additional_info(self, row): def render_additional_info(self, row):
info = [] info = []
if row.is_site_specific: if row.is_site_specific:
info.append(_(u'Site Specific')) info.append(_lazy(u'Site Specific'))
if (len(row.file_platform_ids) == 1 if (len(row.file_platform_ids) == 1
and row.file_platform_ids != [amo.PLATFORM_ALL.id]): and row.file_platform_ids != [amo.PLATFORM_ALL.id]):
k = row.file_platform_ids[0] k = row.file_platform_ids[0]
# L10n: first argument is the platform such as Linux, Mac OS X # L10n: first argument is the platform such as Linux, Mac OS X
info.append(_(u'{0} only').format(amo.PLATFORMS[k].name)) info.append(_lazy(u'{0} only').format(amo.PLATFORMS[k].name))
if row.external_software: if row.external_software:
info.append(_(u'Requires External Software')) info.append(_lazy(u'Requires External Software'))
if row.binary: if row.binary:
info.append(_(u'Binary Components')) info.append(_lazy(u'Binary Components'))
return u', '.join([jinja2.escape(i) for i in info]) return u', '.join([jinja2.escape(i) for i in info])
def render_applications(self, row): def render_applications(self, row):
@ -88,11 +128,11 @@ class EditorQueueTable(SQLTable):
if not row.admin_review: if not row.admin_review:
return '' return ''
return (u'<div class="app-icon ed-sprite-admin-review" title="%s">' return (u'<div class="app-icon ed-sprite-admin-review" title="%s">'
u'</div>' % _('Admin Review')) u'</div>' % _lazy('Admin Review'))
def render_waiting_time_min(self, row): def render_waiting_time_min(self, row):
if row.waiting_time_min == 0: if row.waiting_time_min == 0:
r = _('moments ago') r = _lazy('moments ago')
elif row.waiting_time_hours == 0: elif row.waiting_time_hours == 0:
# L10n: first argument is number of minutes # L10n: first argument is number of minutes
r = ngettext(u'{0} minute', u'{0} minutes', r = ngettext(u'{0} minute', u'{0} minutes',
@ -193,19 +233,19 @@ class ReviewHelper:
hasattr(self.handler, 'process_public')): hasattr(self.handler, 'process_public')):
actions['public'] = {'method': self.handler.process_public, actions['public'] = {'method': self.handler.process_public,
'minimal': False, 'minimal': False,
'label': _('Push to public')} 'label': _lazy('Push to public')}
actions['prelim'] = {'method': self.handler.process_preliminary, actions['prelim'] = {'method': self.handler.process_preliminary,
'label': labels['prelim'], 'label': labels['prelim'],
'minimal': False} 'minimal': False}
actions['reject'] = {'method': self.handler.process_sandbox, actions['reject'] = {'method': self.handler.process_sandbox,
'label': _('Reject'), 'label': _lazy('Reject'),
'minimal': False} 'minimal': False}
actions['info'] = {'method': self.handler.request_information, actions['info'] = {'method': self.handler.request_information,
'label': _('Request more information'), 'label': _lazy('Request more information'),
'minimal': True} 'minimal': True}
actions['super'] = {'method': self.handler.process_super_review, actions['super'] = {'method': self.handler.process_super_review,
'label': _('Request super-review'), 'label': _lazy('Request super-review'),
'minimal': True} 'minimal': True}
for k, v in actions.items(): for k, v in actions.items():
v['details'] = details.get(k) v['details'] = details.get(k)
@ -213,46 +253,51 @@ class ReviewHelper:
return actions return actions
def _review_actions(self): def _review_actions(self):
labels = {'prelim': _('Grant preliminary review')} labels = {'prelim': _lazy('Grant preliminary review')}
details = {'prelim': _('This will mark the files as ' details = {'prelim': _lazy('This will mark the files as '
'premliminary reviewed.'), 'premliminary reviewed.'),
'info': _('Use this form to request more information from ' 'info': _lazy('Use this form to request more information '
'the author. They will receive an email and be ' 'from the author. They will receive an email '
'able to answer here. You will be notified by ' 'and be able to answer here. You will be '
'email when they reply.'), 'notified by email when they reply.'),
'super': _('If you have concerns about this add-on\'s ' 'super': _lazy('If you have concerns about this add-on\'s '
'security, copyright issues, or other concerns ' 'security, copyright issues, or other '
'that an administrator should look into, enter ' 'concerns that an administrator should look '
'your comments in the area below. They will be ' 'into, enter your comments in the area '
'sent to administrators, not the author.'), 'below. They will be sent to '
'reject': _('This will reject the add-on and remove ' 'administrators, not the author.'),
'it from the review queue.')} 'reject': _lazy('This will reject the add-on and remove '
'it from the review queue.')}
if self.addon.status == amo.STATUS_LITE: if self.addon.status == amo.STATUS_LITE:
details['reject'] = _('This will reject the files and remove ' details['reject'] = _lazy('This will reject the files and remove '
'them from the review queue.') 'them from the review queue.')
if self.addon.status in (amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED): if self.addon.status in (amo.STATUS_UNREVIEWED, amo.STATUS_NOMINATED):
details['prelim'] = _('This will mark the add-on as preliminarily ' details['prelim'] = _lazy('This will mark the add-on as '
'reviewed. Future versions will undergo ' 'preliminarily reviewed. Future '
'preliminary review.') 'versions will undergo '
'preliminary review.')
elif self.addon.status == amo.STATUS_LITE: elif self.addon.status == amo.STATUS_LITE:
details['prelim'] = _('This will mark the files as preliminarily ' details['prelim'] = _lazy('This will mark the files as '
'reviewed. Future versions will undergo ' 'preliminarily reviewed. Future '
'preliminary review.') 'versions will undergo '
'preliminary review.')
elif self.addon.status == amo.STATUS_LITE_AND_NOMINATED: elif self.addon.status == amo.STATUS_LITE_AND_NOMINATED:
labels['prelim'] = _('Retain preliminary review') labels['prelim'] = _lazy('Retain preliminary review')
details['prelim'] = _('This will retain the add-on as ' details['prelim'] = _lazy('This will retain the add-on as '
'preliminarily reviewed. Future versions ' 'preliminarily reviewed. Future '
'will undergo preliminary review.') 'versions will undergo preliminary '
'review.')
if self.review_type == 'pending': if self.review_type == 'pending':
details['reject'] = _('This will reject a version of a public ' details['reject'] = _lazy('This will reject a version of a public '
'add-on and remove it from the queue.') 'add-on and remove it from the queue.')
else: else:
details['public'] = _('This will mark the add-on and its most ' details['public'] = _lazy('This will mark the add-on and its most '
'recent version and files as public. Future ' 'recent version and files as public. '
'versions will go into the sandbox until ' 'Future versions will go into the '
'they are reviewed by an editor.') 'sandbox until they are reviewed by an '
'editor.')
return labels, details return labels, details
@ -321,14 +366,14 @@ class ReviewBase:
log.info(u'Sending request for information for %s to %s' % log.info(u'Sending request for information for %s to %s' %
(self.addon, emails)) (self.addon, emails))
send_mail('editors/emails/info.ltxt', send_mail('editors/emails/info.ltxt',
_('Mozilla Add-ons: %s %s') % _lazy('Mozilla Add-ons: %s %s') %
(self.addon.name, self.version.version), (self.addon.name, self.version.version),
emails, Context(self.get_context_data())) emails, Context(self.get_context_data()))
def send_super_mail(self): def send_super_mail(self):
log.info(u'Super review requested for %s' % (self.addon)) log.info(u'Super review requested for %s' % (self.addon))
send_mail('editors/emails/super_review.ltxt', send_mail('editors/emails/super_review.ltxt',
_('Super review requested: %s') % (self.addon.name), _lazy('Super review requested: %s') % (self.addon.name),
[settings.SENIOR_EDITORS_EMAIL], [settings.SENIOR_EDITORS_EMAIL],
Context(self.get_context_data())) Context(self.get_context_data()))
@ -349,7 +394,7 @@ class ReviewAddon(ReviewBase):
self.log_approval(amo.LOG.APPROVE_VERSION) self.log_approval(amo.LOG.APPROVE_VERSION)
self.notify_email('%s_to_public' % self.review_type, self.notify_email('%s_to_public' % self.review_type,
_('Mozilla Add-ons: %s %s Fully Reviewed')) _lazy('Mozilla Add-ons: %s %s Fully Reviewed'))
log.info(u'Making %s public' % (self.addon)) log.info(u'Making %s public' % (self.addon))
log.info(u'Sending email for %s' % (self.addon)) log.info(u'Sending email for %s' % (self.addon))
@ -363,7 +408,7 @@ class ReviewAddon(ReviewBase):
self.log_approval(amo.LOG.REJECT_VERSION) self.log_approval(amo.LOG.REJECT_VERSION)
self.notify_email('%s_to_sandbox' % self.review_type, self.notify_email('%s_to_sandbox' % self.review_type,
# L10n: addon name, version string # L10n: addon name, version string
_('Mozilla Add-ons: %s %s Reviewed')) _lazy('Mozilla Add-ons: %s %s Reviewed'))
log.info(u'Making %s disabled' % (self.addon)) log.info(u'Making %s disabled' % (self.addon))
log.info(u'Sending email for %s' % (self.addon)) log.info(u'Sending email for %s' % (self.addon))
@ -387,7 +432,7 @@ class ReviewAddon(ReviewBase):
self.log_approval(amo.LOG.PRELIMINARY_VERSION) self.log_approval(amo.LOG.PRELIMINARY_VERSION)
self.notify_email(template, self.notify_email(template,
# L10n: addon name, version string # L10n: addon name, version string
_('Mozilla Add-ons: %s %s Preliminary Reviewed')) _lazy('Mozilla Add-ons: %s %s Preliminary Reviewed'))
log.info(u'Making %s preliminary' % (self.addon)) log.info(u'Making %s preliminary' % (self.addon))
log.info(u'Sending email for %s' % (self.addon)) log.info(u'Sending email for %s' % (self.addon))
@ -407,7 +452,7 @@ class ReviewFiles(ReviewBase):
self.log_approval(amo.LOG.REJECT_VERSION) self.log_approval(amo.LOG.REJECT_VERSION)
self.notify_email('%s_to_preliminary' % self.review_type, self.notify_email('%s_to_preliminary' % self.review_type,
_('Mozilla Add-ons: %s %s Reviewed')) _lazy('Mozilla Add-ons: %s %s Reviewed'))
log.info(u'Making %s files %s disabled' % log.info(u'Making %s files %s disabled' %
(self.addon, (self.addon,
@ -421,7 +466,7 @@ class ReviewFiles(ReviewBase):
self.log_approval(amo.LOG.PRELIMINARY_VERSION) self.log_approval(amo.LOG.PRELIMINARY_VERSION)
self.notify_email('%s_to_preliminary' % self.review_type, self.notify_email('%s_to_preliminary' % self.review_type,
_('Mozilla Add-ons: %s %s Preliminary Reviewed')) _lazy('Mozilla Add-ons: %s %s Preliminary Reviewed'))
log.info(u'Making %s files %s preliminary' % log.info(u'Making %s files %s preliminary' %
(self.addon, (self.addon,

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

@ -57,6 +57,7 @@
</li> </li>
</ul> </ul>
</div> </div>
{% block breadcrumbs %}{% endblock %}
{% endblock %} {% endblock %}
{% block js %} {% block js %}

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

@ -1,5 +1,9 @@
{% extends "editors/base.html" %} {% extends "editors/base.html" %}
{% block breadcrumbs %}
{{ editors_breadcrumbs(items=[(None, _('Event Log'))]) }}
{% endblock %}
{% block content %} {% block content %}
<h2>{{ _('Event Log') }}</h2> <h2>{{ _('Event Log') }}</h2>

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

@ -1,5 +1,9 @@
{% extends "editors/base.html" %} {% extends "editors/base.html" %}
{% block breadcrumbs %}
{{ editors_breadcrumbs(items=[(None, _('Message of the Day'))]) }}
{% endblock %}
{% block content %} {% block content %}
<div id="editor-motd"> <div id="editor-motd">
{% if form %} {% if form %}

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

@ -1,5 +1,9 @@
{% extends "editors/base.html" %} {% extends "editors/base.html" %}
{% block breadcrumbs %}
{{ editors_breadcrumbs(queue=tab) }}
{% endblock %}
{% block content %} {% block content %}
<ul class="tabnav"> <ul class="tabnav">

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

@ -6,7 +6,12 @@
{% block bodyclass %}inverse{% endblock %} {% block bodyclass %}inverse{% endblock %}
{% block breadcrumbs %}
{{ editors_breadcrumbs(queue_id=addon.status, items=[(None, addon.name)]) }}
{% endblock %}
{% block content %} {% block content %}
<hgroup> <hgroup>
<h2 class="addon"{{ addon.name|locale_html }}> <h2 class="addon"{{ addon.name|locale_html }}>
<img src="{{ addon.icon_url }}" class="icon"/> <img src="{{ addon.icon_url }}" class="icon"/>

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

@ -1,4 +1,9 @@
{% extends "editors/base.html" %} {% extends "editors/base.html" %}
{% block breadcrumbs %}
{{ editors_breadcrumbs(items=[(None, _('Review Log'))]) }}
{% endblock %}
{% block content %} {% block content %}
<h2>{{ _('Add-on Editor Review Log', 'editorcp_reviewlog_page_heading') }}</h2> <h2>{{ _('Add-on Editor Review Log', 'editorcp_reviewlog_page_heading') }}</h2>
@ -33,15 +38,17 @@
<tr> <tr>
<td>{{ item.created|datetime('%Y-%m-%d') }}</td> <td>{{ item.created|datetime('%Y-%m-%d') }}</td>
<td> <td>
{{ item.arguments.0|link }} {% if item.arguments.0 %}
{% if item.arguments|count >= 2 %} {{ item.arguments.0|link }}
{{ item.arguments[1] }} {% if item.arguments|count >= 2 %}
{{ item.arguments[1] }}
<a href="{{ url('editors.review', item.arguments[1].id) }}"> <a href="{{ url('editors.review', item.arguments[1].id) }}">
{{ ACTION_DICT.get(item.action) }}
</a>
{% else %}
{{ ACTION_DICT.get(item.action) }} {{ ACTION_DICT.get(item.action) }}
</a> {% endif %}
{% else %}
{{ ACTION_DICT.get(item.action) }}
{% endif %} {% endif %}
</td> </td>
<td>{{ item.user.display_name }}</td> <td>{{ item.user.display_name }}</td>

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

@ -91,6 +91,15 @@ class TestEventLog(EditorTest):
assert 'No events found for this period.' in r.content assert 'No events found for this period.' in r.content
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.eventlog'))
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 2)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).text(), "Event Log")
class TestEventLogDetail(TestEventLog): class TestEventLogDetail(TestEventLog):
def test_me(self): def test_me(self):
@ -135,6 +144,15 @@ class TestReviewLog(EditorTest):
eq_(len(doc('tbody tr').not_('.hide')), 50) eq_(len(doc('tbody tr').not_('.hide')), 50)
eq_(doc('tbody tr.hide').eq(0).text(), 'youwin') eq_(doc('tbody tr.hide').eq(0).text(), 'youwin')
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.reviewlog'))
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 2)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).text(), "Review Log")
class TestHome(EditorTest): class TestHome(EditorTest):
"""Test the page at /editors.""" """Test the page at /editors."""
@ -347,6 +365,15 @@ class TestPendingQueue(QueueTest):
eq_(doc('.tabnav li a:eq(1)').attr('href'), eq_(doc('.tabnav li a:eq(1)').attr('href'),
reverse('editors.queue_pending')) reverse('editors.queue_pending'))
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.queue_pending'))
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 2)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).text(), "Pending Updates")
class TestNominatedQueue(QueueTest): class TestNominatedQueue(QueueTest):
@ -399,6 +426,15 @@ class TestPreliminaryQueue(QueueTest):
eq_(doc('.tabnav li a:eq(2)').attr('href'), eq_(doc('.tabnav li a:eq(2)').attr('href'),
reverse('editors.queue_prelim')) reverse('editors.queue_prelim'))
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.queue_prelim'))
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 2)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).text(), "Preliminary Reviews")
class TestModeratedQueue(QueueTest): class TestModeratedQueue(QueueTest):
fixtures = ['base/users', 'base/apps', 'reviews/dev-reply.json'] fixtures = ['base/users', 'base/apps', 'reviews/dev-reply.json']
@ -509,6 +545,15 @@ class TestModeratedQueue(QueueTest):
eq_(doc('.tabnav li a:eq(3)').attr('href'), eq_(doc('.tabnav li a:eq(3)').attr('href'),
reverse('editors.queue_moderated')) reverse('editors.queue_moderated'))
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.queue_moderated'))
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 2)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).text(), "Moderated Reviews")
class SearchTest(EditorTest): class SearchTest(EditorTest):
@ -985,6 +1030,15 @@ class TestReview(ReviewBase):
r = self.client.get(self.url) r = self.client.get(self.url)
assert "View Privacy Policy" in r.content assert "View Privacy Policy" in r.content
def test_breadcrumbs(self):
r = self.client.get(self.url)
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 3)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).find('a').text(), "Pending Updates")
class TestReviewPreliminary(ReviewBase): class TestReviewPreliminary(ReviewBase):
@ -1071,6 +1125,15 @@ class TestReviewPreliminary(ReviewBase):
eq_([amo.STATUS_DISABLED, amo.STATUS_LISTED], eq_([amo.STATUS_DISABLED, amo.STATUS_LISTED],
[v.status for v in version.files.all().order_by('status')]) [v.status for v in version.files.all().order_by('status')])
def test_breadcrumbs(self):
r = self.client.get(self.url)
doc = pq(r.content)
list_items = doc('ol.breadcrumbs li')
eq_(list_items.length, 3)
eq_(list_items.eq(0).find('a').text(), "Editor Tools")
eq_(list_items.eq(1).find('a').text(), "Pending Updates")
class TestEditorMOTD(EditorTest): class TestEditorMOTD(EditorTest):