bug 562667, Collections search on the frontend.

This commit is contained in:
Dave Dash 2010-05-06 14:11:26 -07:00
Родитель 6eabe5244d
Коммит 7bf634a532
8 изменённых файлов: 215 добавлений и 24 удалений

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

@ -32,6 +32,14 @@ sort_by = (
'advanced_search_form_popularity')),
)
collection_sort_by = (
('weekly', _lazy('Most popular this week')),
('monthly', _lazy('Most popular this month')),
('all', _lazy('Most popular all time')),
('rating', _lazy('Highest Rated')),
('newest', _lazy('Newest')),
)
per_page = (20, 50, 100)
tuplize = lambda x: divmod(int(x * 10), 10)
@ -163,3 +171,20 @@ def SearchForm(request):
d = request.GET.copy()
return _SearchForm(d)
class CollectionsSearchForm(forms.Form):
q = forms.CharField(widget=forms.HiddenInput, required=False)
cat = forms.CharField(widget=forms.HiddenInput)
pp = forms.IntegerField(widget=forms.HiddenInput, required=False)
sortby = forms.ChoiceField(label=_('Sort By'), choices=collection_sort_by,
initial='weekly', required=False)
page = forms.IntegerField(widget=forms.HiddenInput, required=False)
def clean(self):
d = self.cleaned_data
if not d.get('pp'):
d['pp'] = per_page[0]
return d

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

@ -0,0 +1,112 @@
{% extends "base.html" %}
{% block title %}
{% if query %}
{{ page_title(_('Collection Search Results for {0}')|f(query)) }}
{% else %}
{{ page_title(_('Collection Search Results')) }}
{% endif %}
{% endblock %}
{% block bodyclass %}inverse{% endblock %}
{% block content %}
<div class="primary" role="main">
<h2>{{ _('Collection Search Results') }}</h2>
<div class="featured listing">
{% if pager.object_list %}
<div class="featured-inner">
<div class="listing-header">
<div class="num-results">
{{ pagination_result_count(pager) }}
</div>
<form class="item-sort go" action="" method="get">
<div>
{{ form['q']|safe }}
{{ form['cat']|safe }}
{{ form['pp']|safe }}
<label for="id_sortby">
{{ form['sortby'].label }}
</label>
{{ form['sortby']|safe }}
</div>
</form>
</div>
{% for c in pager.object_list %}
<div class="item">
<div class="item-info">
<ul>
<li class="addons">
{{ _('<strong>{0}</strong> add-ons')|f(c.addon_count)|safe }}
</li>
<li class="subscribers">
{{ _('<strong>{0}</strong> subscribers')|f(c.subscribers)|safe }}
</li>
<li>
{{ barometer(c) }}
</li>
{% if request.user.is_authenticated() %}
<li>
{{ collection_favorite(c) }}
</li>
{% endif %}
</ul>
</div> {# /item-info #}
<h3>
<a href="{{ c.get_url_path() }}">{{ c.name }}</a>
<span>{{ _('created by {0}')|f(c.author|user_link)|safe }}</span>
<a href="{{ c.get_url_path() }}">
<img class="icon" alt="" src="{{ c.icon_url }}">
</a>
</h3>
<blockquote>{{ c.description|nl2br }}</blockquote>
</div>
{% endfor %}
</div>
<div class="listing-footer">{{ pager|paginator }}</div>
{% else %}
{% include 'search/no_results.html' %}
{% endif %}
</div>
</div> {# /primary #}
<div class="secondary" role="complementary">
<div class="highlight">
<h3>{{ _('What are Collections?') }}</h3>
<p>
{{ _('Collections are groups of related add-ons assembled for easy sharing.') }}
</p>
<p>
<a class="more-info" href="{{ remora_url('collections/add') }}">
{{ _('Create a Collection', 'collections_index_a_create') }}
</a>
</p>
</div>
<div class="highlight">
<h3>{{ _('Add-on Collector', 'collections_index_header_collector') }}</h3>
<p class="teaser-img">
<a href="{{ remora_url('pages/collector') }}">
<img alt="" src="{{ MEDIA_URL }}img/amo2009/illustrations/logo-collections-download-146x159.png">
</a>
</p>
<p>
{{ _("There's a new way to manage and find favorite add-ons. Comment, share and sync collections, all from your browser.") }}
</p>
<p>
<a class="more-info" href="{{ remora_url('pages/collector') }}">
{{ _('Check out Add-on Collector') }}
</a>
</p>
</div>
</div> {# /secondary #}
{# TODO(davedash): parcel this out into a jinja function. #}
<div class="secondary">
<div id="recently-viewed" class="collections-add">
<h3 class="compact-bottom">{{ _('Recently Viewed') }}</h3>
</div>
</div>
{% endblock %}

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

@ -0,0 +1,7 @@
<div class="featured-inner">
<div class="listing-header">
<p class="no-results">
{{ _('No results found.') }}
</p>
</div>
</div>

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

@ -19,21 +19,16 @@
{% endfor %}
</ul>
</div>
{{ addon_listing_items(pager.object_list, show_added_date=(sort == 'newest'),
{{ addon_listing_items(pager.object_list,
show_added_date=(sort == 'newest'),
src='search') }}
</div>
<div class="listing-footer">
{{ pager|paginator}}
{{ pager|paginator }}
</div>
{% else %}
<div class="featured-inner">
<div class="listing-header">
<p class="no-results">
{{ _('No results found.') }}
</p>
</div>
</div>
{% include 'search/no_results.html' %}
{% endif %}
</div>

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

@ -121,6 +121,7 @@ class GetCategoryIdTest(TestCase):
query = lambda *args, **kwargs: SearchClient().query(*args, **kwargs)
cquery = lambda *args, **kwargs: CollectionsClient().query(*args, **kwargs)
@mock.patch('search.client.sphinx.SphinxClient')
def test_sphinx_timeout(sphinx_mock):
def sphinx_error(cls):
@ -157,6 +158,12 @@ class SearchDownTest(TestCase):
doc = pq(resp.content)
eq_(doc('.no-results').length, 1)
def test_collections_search_down(self):
self.client.get('/')
resp = self.client.get(reverse('search.search') + '?cat=collections')
doc = pq(resp.content)
eq_(doc('.no-results').length, 1)
class CollectionsSearchTest(SphinxTestCase):
@ -321,6 +328,12 @@ class FrontendSearchTest(SphinxTestCase):
# Verify that we have the Refine Results.
eq_(doc('.secondary .highlight h3').length, 1)
def test_default_collections_query(self):
r = self.get_response(cat='collections')
doc = pq(r.content)
eq_(doc('title').text(),
'Collection Search Results :: Add-ons for Firefox')
def test_basic_query(self):
"Test a simple query"
resp = self.get_response(q='delicious')

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

@ -12,8 +12,8 @@ from amo.helpers import urlparams
from amo import urlresolvers
from versions.compare import dict_from_int
from search import forms
from search.client import Client as SearchClient, SearchError
from search.forms import SearchForm
from search.client import Client as SearchClient, SearchError, CollectionsClient
from search.forms import SearchForm, CollectionsSearchForm
DEFAULT_NUM_RESULTS = 20
@ -146,13 +146,44 @@ def _get_sorts(request, sort):
return items
def _collections(request):
"""Handle the request for collections."""
form = CollectionsSearchForm(request.GET)
form.is_valid()
query = form.cleaned_data.get('q', '')
search_opts = {}
search_opts['limit'] = form.cleaned_data.get('pp', DEFAULT_NUM_RESULTS)
page = form.cleaned_data.get('page') or 1
search_opts['offset'] = (page - 1) * search_opts['limit']
search_opts['sort'] = form.cleaned_data.get('sortby')
client = CollectionsClient()
try:
results = client.query(query, **search_opts)
except SearchError, e:
return jingo.render(request, 'search/down.html', {}, status=503)
pager = amo.utils.paginate(request, results, search_opts['limit'])
c = {
'pager': pager,
'form': form,
}
return jingo.render(request, 'search/collections.html', c)
def search(request):
title = _('Search Add-ons')
# If the form is invalid we still want to have a query.
query = request.REQUEST.get('q', '')
search_opts = {
'meta': ('versions', 'categories', 'tags'),
'version': None
@ -161,6 +192,22 @@ def search(request):
form = SearchForm(request)
form.is_valid() # Let the form try to clean data.
# TODO(davedash): remove this feature when we remove Application for
# the search advanced form
# Redirect if appid != request.APP.id
appid = form.cleaned_data['appid']
if request.APP.id != appid:
new_app = amo.APP_IDS.get(appid)
return HttpResponseRedirect(
urlresolvers.get_app_redirect(new_app))
category = form.cleaned_data.get('cat')
if category == 'collections':
return _collections(request)
# TODO: Let's change the form values to something less gross when
# Remora dies in a fire.
query = form.cleaned_data['q']
@ -168,18 +215,7 @@ def search(request):
if query:
title = _('Search for %s' % query)
appid = form.cleaned_data['appid']
# TODO(davedash): remove this feature when we remove Application for
# the search advanced form
# Redirect if appid != request.APP.id
if request.APP.id != appid:
new_app = amo.APP_IDS.get(appid)
return HttpResponseRedirect(
urlresolvers.get_app_redirect(new_app))
addon_type = form.cleaned_data.get('atype', 0)
category = form.cleaned_data.get('cat')
tag = form.cleaned_data.get('tag')
page = form.cleaned_data['page']
last_updated = form.cleaned_data.get('lup')

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

@ -280,7 +280,7 @@ $(document).ready(function() {
.find('form').submit(callback);
});
};
$('.user-login .barometer form').submit(callback);
$('body[data-anonymous["false"]] .barometer form').submit(callback);
})
$(document).ready(function(){

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

@ -318,6 +318,9 @@ MINIFY_BUNDLES = {
# Personas
'js/zamboni/jquery.hoverIntent.min.js',
'js/zamboni/personas.js',
# Collections
'js/zamboni/collections.js',
),
}
}