Filter Editor Review Queue by search terms (Bug 531910)

This commit is contained in:
Gregory Koberger 2011-05-20 14:52:15 -07:00
Родитель 7d424845b6
Коммит 828ea06408
12 изменённых файлов: 236 добавлений и 21 удалений

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

@ -377,7 +377,7 @@ def log(action, *args, **kw):
e.g. amo.log(amo.LOG.CREATE_ADDON, []),
amo.log(amo.LOG.ADD_FILE_TO_VERSION, file, version)
"""
from devhub.models import ActivityLog, AddonLog, UserLog
from devhub.models import ActivityLog, AddonLog, UserLog, CommentLog
from addons.models import Addon
from users.models import UserProfile
from amo import get_user, logger_log
@ -394,6 +394,9 @@ def log(action, *args, **kw):
al.details = kw['details']
al.save()
if 'details' in kw and 'comments' in al.details:
CommentLog(comments=al.details['comments'], activity_log=al).save()
# TODO(davedash): post-remora this may not be necessary.
if 'created' in kw:
al.created = kw['created']
@ -406,6 +409,7 @@ def log(action, *args, **kw):
AddonLog(addon_id=arg[1], activity_log=al).save()
elif arg[0] == UserProfile:
UserLog(user_id=arg[1], activity_log=al).save()
if isinstance(arg, Addon):
AddonLog(addon=arg, activity_log=al).save()
elif isinstance(arg, UserProfile):

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

@ -84,6 +84,19 @@ class AddonLog(amo.models.ModelBase):
ordering = ('-created',)
class CommentLog(amo.models.ModelBase):
"""
This table is for indexing the activity log by user.
Note: This includes activity performed unto the user.
"""
activity_log = models.ForeignKey('ActivityLog')
comments = models.CharField(max_length=255)
class Meta:
db_table = 'log_activity_comment'
ordering = ('-created',)
class UserLog(amo.models.ModelBase):
"""
This table is for indexing the activity log by user.

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

@ -52,6 +52,24 @@ class ReviewLogForm(happyforms.Form):
label=_lazy(u'View entries between'))
end = forms.DateField(required=False,
label=_lazy(u'and'))
search = forms.CharField(required=False,
label=_lazy(u'containing'))
def __init__(self, *args, **kw):
super(ReviewLogForm, self).__init__(*args, **kw)
# L10n: start, as in "start date"
self.fields['start'].widget.attrs = {'placeholder': _('start'),
'size': 10}
# L10n: end, as in "end date"
self.fields['end'].widget.attrs = {'size': 10, 'placeholder': _('end')}
# L10n: Description of what can be searched for
search_ph = _('add-on, editor or comment')
self.fields['search'].widget.attrs = {'placeholder': search_ph,
'size': 30}
def clean(self):
data = self.cleaned_data

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

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

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

@ -0,0 +1,16 @@
from django.core.management.base import BaseCommand
from addons.models import Addon
from amo.utils import chunked
from devhub.models import ActivityLog
from editors.tasks import add_commentlog
class Command(BaseCommand):
help = 'Add a CommentLog entry for all ActivityLog items'
def handle(self, *args, **options):
pks = ActivityLog.objects.review_queue().values_list('pk', flat=True).order_by('id')
for chunk in chunked(pks, 100):
add_commentlog.delay(chunk)

30
apps/editors/tasks.py Normal file
Просмотреть файл

@ -0,0 +1,30 @@
from django.conf import settings
import commonware.log
import celery.task
from celeryutils import task
from hera.contrib.django_utils import flush_urls
from devhub.models import ActivityLog, CommentLog
log = commonware.log.getLogger('z.task')
# We use celery.task.ping in /monitor, so we need it to return results.
celery.task.PingTask.ignore_result = False
@task
def add_commentlog(items, **kw):
log.info('[%s@%s] Adding CommentLog starting with ActivityLog: %s' %
(len(items), add_commentlog.rate_limit, items[0]))
for al in ActivityLog.objects.filter(pk__in=items):
import pdb; pdb.set_trace()
# Delete existing entries:
CommentLog.objects.filter(activity_log=al).delete()
# Create a new entry:
if 'comments' in al.details:
CommentLog(comments=al.details['comments'], activity_log=al).save()

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

@ -5,24 +5,28 @@
{% endblock %}
{% block content %}
<div id="log-filter" class="log-filter-outside">
<form action="{{ url('editors.reviewlog') }}" method="get">
<div class="date_range">
{{ form.start.label_tag() }}
{{ form.start }}
{{ form.end.label_tag() }}
{{ form.end }}
{{ form.search.label_tag() }}
{{ form.search }}
{# L10n: "Filter" is a button label (verb) #}
<button type="submit">
{{ _('Filter', 'editorcp_reviewlog_page_heading') }}
</button>
</div>
</form>
</div><!-- #log-filter -->
<h2>{{ _('Add-on Review Log', 'editorcp_reviewlog_page_heading') }}</h2>
<div class="listing results"><div class="results-inner controls">
<div id="log-filter">
<form action="{{ url('editors.reviewlog') }}" method="get">
<div class="date_range">
{{ form.start.label_tag() }}
{{ form.start }}
{{ form.end.label_tag() }}
{{ form.end }}
{# L10n: "Filter" is a button label (verb) #}
<button type="submit">
{{ _('Filter', 'editorcp_reviewlog_page_heading') }}
</button>
</div>
</form>
</div><!-- #log-filter -->
{% if pager.object_list %}
<table id="log-listing" class="data-grid">
<thead>

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

@ -124,18 +124,26 @@ class TestReviewLog(EditorTest):
amo.log(amo.LOG.REJECT_VERSION, a, v, user=u,
details={'comments': 'youwin'})
def make_an_approval(self, action):
u = UserProfile.objects.filter()[0]
a = Addon.objects.create(type=amo.ADDON_EXTENSION)
def make_an_approval(self, action, **kw):
comment = kw.pop('comment', 'youwin')
username = kw.pop('username', False)
addon_name = kw.pop('addon_name', None)
user_filter = {}
if username:
user_filter['username'] = username
u = UserProfile.objects.filter(**user_filter)[0]
a = Addon.objects.create(type=amo.ADDON_EXTENSION, name=addon_name)
v = Version.objects.create(addon=a)
amo.log(action, a, v, user=u, details={'comments': 'youwin'})
amo.log(action, a, v, user=u, details={'comments': comment})
def test_basic(self):
self.make_approvals()
r = self.client.get(reverse('editors.reviewlog'))
eq_(r.status_code, 200)
doc = pq(r.content)
assert doc('.listing button'), 'No filters.'
assert doc('#log-filter button'), 'No filters.'
# Should have 6 showing.
eq_(len(doc('tbody tr').not_('.hide')), 6)
eq_(doc('tbody tr.hide').eq(0).text(), 'youwin')
@ -186,6 +194,88 @@ class TestReviewLog(EditorTest):
doc = pq(r.content)
eq_(doc('#log-listing tr:not(.hide)').length, 7)
def test_search_comment_exists(self):
"""
Search by comment.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, comment='hello')
r = self.client.get(reverse('editors.reviewlog') + '?search=hello')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 1)
eq_(doc('tbody tr.hide').eq(0).text(), 'hello')
def test_search_comment_doesnt_exist(self):
"""
Search by comment, with no results.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, comment='hello')
r = self.client.get(reverse('editors.reviewlog') + '?search=bye')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 0)
def test_search_author_exists(self):
"""
Search by author.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, username='editor',
comment='hi')
r = self.client.get(reverse('editors.reviewlog') + '?search=editor')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 1)
eq_(doc('tbody tr.hide').eq(0).text(), 'hi')
def test_search_author_doesnt_exist(self):
"""
Search by author, with no results.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, user_name='editor')
r = self.client.get(reverse('editors.reviewlog') + '?search=wrong')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 0)
def test_search_addon_exists(self):
"""
Search by add-on name.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, addon_name='abcd',
comment='ab')
r = self.client.get(reverse('editors.reviewlog') + '?search=ab')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 1)
eq_(doc('tbody tr.hide').eq(0).text(), 'ab')
def test_search_addon_doesnt_exist(self):
"""
Search by add-on name, with no results.
"""
self.make_approvals()
self.make_an_approval(amo.LOG.REQUEST_SUPER_REVIEW, addon_name='abcd',
comment='ab')
r = self.client.get(reverse('editors.reviewlog') + '?search=by')
eq_(r.status_code, 200)
doc = pq(r.content)
eq_(len(doc('tbody tr').not_('.hide')), 0)
def test_breadcrumbs(self):
r = self.client.get(reverse('editors.reviewlog'))
doc = pq(r.content)

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

@ -6,6 +6,7 @@ import time
from django import http
from django.conf import settings
from django.core.cache import cache
from django.db.models import Q
from django.shortcuts import redirect, get_object_or_404
from django.utils.datastructures import SortedDict
from django.views.decorators.cache import never_cache
@ -504,6 +505,13 @@ def reviewlog(request):
approvals = approvals.filter(created__gte=data['start'])
if data['end']:
approvals = approvals.filter(created__lt=data['end'])
if data['search']:
term = data['search']
approvals = approvals.filter(
Q(commentlog__comments__contains=term) |
Q(addonlog__addon__name__localized_string__contains=term) |
Q(user__display_name__contains=term) |
Q(user__username__contains=term)).distinct()
pager = amo.utils.paginate(request, approvals, 50)
ad = {

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

@ -423,6 +423,24 @@ div.editor-stats-table > div.editor-stats-dark {
#log-filter form {
margin: 0;
}
.log-filter-outside {
float: right;
}
.log-filter-outside label {
font-weight: normal;
}
.log-filter-outside input::-webkit-input-placeholder {
color: #BBB;
}
.log-filter-outside input:-moz-placeholder {
color: #BBB;
}
.log-filter-outside div.date_range {
padding: 0.5em 0 0;
}
.queue-outer #queue-search table {
margin: 0;
padding: 0;
@ -672,3 +690,4 @@ span.currently_viewing_warning {
margin-bottom: 0;
}

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

@ -0,0 +1,13 @@
DROP TABLE IF EXISTS log_activity_comment;
CREATE TABLE `log_activity_comment` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`activity_log_id` integer NOT NULL,
`comments` longtext NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
;
ALTER TABLE `log_activity_comment` ADD CONSTRAINT `activity_log_id_refs_id_4f8d99d4` FOREIGN KEY (`activity_log_id`) REFERENCES `log_activity` (`id`);
CREATE INDEX `log_activity_comment_3bf68f54` ON `log_activity_comment` (`activity_log_id`);