Skip to content
This repository has been archived by the owner on Aug 26, 2022. It is now read-only.

Commit

Permalink
Fix bug 1246459 - Prioritize web by default
Browse files Browse the repository at this point in the history
  • Loading branch information
robhudson committed Mar 28, 2016
1 parent c70f7f6 commit 4be458d
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 40 deletions.
5 changes: 4 additions & 1 deletion kuma/landing/jinja2/landing/homepage.html
Expand Up @@ -40,7 +40,7 @@ <h1>{{ _('Shared knowledge <span>for the Open Web</span>') }}</h1>
<i class="icon-search" aria-hidden="true"></i>
</span>
<input class="search-input" type="search" id="home-q" name="q" placeholder="{{ _('Search the docs') }}" />
<div class="filters"></div>
<div class="filters" data-default="{{ default_filters|jsonencode|forceescape }}"></div>
<button class="show-topics only-icon" type="button">
<span>{{ _('Show topics') }}</span>
<i class="icon-caret-down" aria-hidden="true"></i>
Expand All @@ -58,6 +58,9 @@ <h1>{{ _('Shared knowledge <span>for the Open Web</span>') }}</h1>
</span>
<input class="search-input" type="search" id="home-q" name="q" placeholder="{{ _('Search the docs') }}" />
<button type="submit" class="offscreen">{{ _('Search') }}</button>
{% for group, tag, shortcut in default_filters %}
<input type="hidden" name="{{ group }}" value="{{ shortcut|default(tag, true) }}">
{% endfor %}
</div>
</form>
{% endif %}
Expand Down
28 changes: 22 additions & 6 deletions kuma/landing/test_templates.py
@@ -1,19 +1,35 @@
from constance.test import override_config
from pyquery import PyQuery as pq

from kuma.core.tests import KumaTestCase, eq_, ok_
from kuma.core.urlresolvers import reverse
from kuma.search.models import Filter, FilterGroup


class HomeTests(KumaTestCase):
def test_google_analytics(self):
url = reverse('home')

with override_config(GOOGLE_ANALYTICS_ACCOUNT='0'):
r = self.client.get(url, follow=True)
eq_(200, r.status_code)
ok_('ga(\'create' not in r.content)
response = self.client.get(url, follow=True)
eq_(200, response.status_code)
ok_('ga(\'create' not in response.content)

with override_config(GOOGLE_ANALYTICS_ACCOUNT='UA-99999999-9'):
r = self.client.get(url, follow=True)
eq_(200, r.status_code)
ok_('ga(\'create' in r.content)
response = self.client.get(url, follow=True)
eq_(200, response.status_code)
ok_('ga(\'create' in response.content)

def test_default_search_filters(self):
url = reverse('home')
group = FilterGroup.objects.create(name='Topic', slug='topic')
for name in ['CSS', 'HTML', 'JavaScript']:
Filter.objects.create(group=group, name=name, slug=name.lower(),
default=True)

response = self.client.get(url, follow=True)
page = pq(response.content)
filters = page.find('#home-search-form input[type=hidden]')
filter_vals = [p.val() for p in filters.items()]
eq_(filters.eq(0).attr('name'), 'topic')
eq_(sorted(filter_vals), ['css', 'html', 'javascript'])
6 changes: 4 additions & 2 deletions kuma/landing/views.py
Expand Up @@ -5,7 +5,7 @@
from kuma.core.sections import SECTION_USAGE
from kuma.core.cache import memcache
from kuma.feeder.models import Bundle
from kuma.search.models import FilterGroup
from kuma.search.models import Filter, FilterGroup
from kuma.search.serializers import GroupWithFiltersSerializer


Expand All @@ -22,11 +22,13 @@ def home(request):

groups = FilterGroup.objects.all()
serializer = GroupWithFiltersSerializer(groups, many=True)
default_filters = Filter.objects.default_filters()

context = {
'updates': updates,
'stats': community_stats,
'command_search_filters': serializer.data
'command_search_filters': serializer.data,
'default_filters': default_filters,
}
return render(request, 'landing/homepage.html', context)

Expand Down
4 changes: 2 additions & 2 deletions kuma/search/admin.py
Expand Up @@ -67,10 +67,10 @@ class FilterGroupAdmin(admin.ModelAdmin):

@admin.register(Filter)
class FilterAdmin(admin.ModelAdmin):
list_display = ('name', 'slug', 'group', 'enabled')
list_display = ('name', 'slug', 'group', 'enabled', 'default')
list_filter = ('group',)
search_fields = ('name', 'slug')
list_editable = ('enabled',)
list_editable = ('enabled', 'default')
list_select_related = True
radio_fields = {
'operator': admin.VERTICAL,
Expand Down
19 changes: 17 additions & 2 deletions kuma/search/filters.py
@@ -1,7 +1,6 @@
import collections

from django.conf import settings

from elasticsearch_dsl import F, Q, query
from rest_framework.filters import BaseFilterBackend

Expand All @@ -11,11 +10,27 @@


def get_filters(getter_func):
"""
Returns the values of all filter groups, intended to pull key/value pairs
from requests.
E.g. if 'topic' is a `FilterGroup` slug and given the URL::
?q=test&topic=css&topic=html
this will return `['css', 'html']`.
"""
filters = collections.OrderedDict()
for slug in FilterGroup.objects.values_list('slug', flat=True):
for filters_slug in getter_func(slug, []):
filters[filters_slug] = None
return filters.keys()
if filters:
return filters.keys()
else:
# Given a list of [<group_slug>, <tag_slug>, <shortcut>] we only want
# the tags.
return [x[1] for x in Filter.objects.default_filters()]


class LanguageFilterBackend(BaseFilterBackend):
Expand Down
14 changes: 13 additions & 1 deletion kuma/search/managers.py
@@ -1,6 +1,5 @@
from django.conf import settings
from django.db import models

from elasticsearch.exceptions import RequestError

from kuma.wiki.search import WikiDocumentType
Expand All @@ -12,6 +11,19 @@ class FilterManager(models.Manager):
def visible_only(self):
return self.filter(visible=True)

def default_filters(self):
"""
Return default filters as a list of lists of the form::
[[<group_slug>, <filter_slug>], ...]
Converting to lists of lists so we can json encode it.
"""
return [list(f) for f in
self.filter(default=True).values_list('group__slug', 'slug',
'shortcut')]


class IndexManager(models.Manager):
"""
Expand Down
19 changes: 19 additions & 0 deletions kuma/search/migrations/0002_filter_default.py
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('search', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='filter',
name='default',
field=models.BooleanField(default=False, help_text=b'Whether this filter is applied in the absence of a user-chosen filter'),
),
]
8 changes: 6 additions & 2 deletions kuma/search/models.py
Expand Up @@ -170,8 +170,8 @@ class Filter(models.Model):
group = models.ForeignKey(FilterGroup, related_name='filters',
help_text='E.g. "Topic", "Skill level" etc')
tags = TaggableManager(help_text='A comma-separated list of tags. '
'If more than one tag given a OR '
'query is executed')
'If more than one tag given the operator '
'specified is used')
operator = models.CharField(max_length=3, choices=OPERATOR_CHOICES,
default=OPERATOR_OR,
help_text='The logical operator to use '
Expand All @@ -183,6 +183,10 @@ class Filter(models.Model):
help_text='Whether this filter is shown '
'at public places, e.g. the '
'command and query UI')
default = models.BooleanField(default=False,
help_text='Whether this filter is applied in '
'the absence of a user-chosen '
'filter')

objects = FilterManager()

Expand Down
8 changes: 8 additions & 0 deletions kuma/search/tests/test_store.py
Expand Up @@ -28,6 +28,14 @@ def test_basic(self, get_current):
request = self.generate_request('en-US', url)
assert get_search_url_from_referer(request) == url

@mock.patch.object(Site.objects, 'get_current')
def test_basic_with_topics(self, get_current):
get_current.return_value.domain = 'testserver'

url = 'https://testserver/en-US/search?q=javascript&topic=js'
request = self.generate_request('en-US', url)
assert get_search_url_from_referer(request) == url

# FIXME: These tests aren't great because we can't verify exactly why we
# got a None so we can't distinguish between "right answer" and "right
# answer, but for the wrong reasons".
Expand Down
11 changes: 5 additions & 6 deletions kuma/search/views.py
Expand Up @@ -6,21 +6,20 @@
from django.shortcuts import render
from django.utils.translation import ugettext
from django.views.decorators.cache import cache_page

from rest_framework.generics import ListAPIView
from rest_framework.renderers import JSONRenderer

from kuma.wiki.search import WikiDocumentType

from .filters import (AdvancedSearchQueryBackend, DatabaseFilterBackend,
get_filters, HighlightFilterBackend,
LanguageFilterBackend, SearchQueryBackend)
HighlightFilterBackend, LanguageFilterBackend,
SearchQueryBackend, get_filters)
from .jobs import AvailableFiltersJob
from .queries import Filter, FilterGroup
from .pagination import SearchPagination
from .queries import Filter, FilterGroup
from .renderers import ExtendedTemplateHTMLRenderer
from .serializers import (DocumentSerializer, FilterWithGroupSerializer,
SearchQuerySerializer, FacetedFilterSerializer)
from .serializers import (DocumentSerializer, FacetedFilterSerializer,
FilterWithGroupSerializer, SearchQuerySerializer)
from .utils import QueryURLObject


Expand Down
15 changes: 0 additions & 15 deletions kuma/settings/common.py
Expand Up @@ -1209,21 +1209,6 @@ def _get_languages_and_locales():
]),
"JSON array listing tag suggestions for documents"
),
SEARCH_FILTER_TAG_OPTIONS=(
json.dumps([
"Accessibility", "AJAX", "API", "Apps",
"Canvas", "CSS", "Device", "DOM", "Events",
"Extensions", "Firefox", "Firefox OS", "Games",
"Gecko", "Graphics", "Internationalization", "History", "HTML", "HTTP", "JavaScript", "Layout",
"Localization", "MDN", "Mobile", "Mozilla",
"Networking", "Persona", "Places", "Plugins", "Protocols",

"Reference", "Tutorial", "Landing",

"junk", "NeedsMarkupWork", "NeedsContent", "NeedsExample",
]),
"JSON array of tags that are enabled for search faceting"
),
SESSION_CLEANUP_CHUNK_SIZE=(
1000,
'Number of expired sessions to cleanup up in one go.',
Expand Down
12 changes: 9 additions & 3 deletions kuma/static/js/search-suggestions.js
Expand Up @@ -22,7 +22,7 @@
// Mixin options
var settings = $.extend({
sizeLimit: 25,
filters: false,
filters: null,
onAddFilter: noop,
onRemoveFilter: noop,
}, options);
Expand Down Expand Up @@ -196,7 +196,7 @@
fnSuggestions.prepareInput();

// load previouly selected filters
if (settings.filters) {
if (settings.filters !== null) {
$.each(settings.filters, function(sidx, sfilter) {
// foreach filters to get the correct shortcut
$.each(filtersData, function(index, group) {
Expand All @@ -210,7 +210,13 @@
}
});
});
$searchInput.focus();
} else {
var filterDefaults = $searchFilters.data('default');
$.each(filterDefaults, function(i, tuple) {
// The tuple is [<group slug>, <filter slug>, <shortcut>]
fnSuggestions.addFilter(tuple[1], tuple[0], tuple[2]);
fnSuggestions.removeFilterFromList(tuple[1]);
});
}

// events
Expand Down

0 comments on commit 4be458d

Please sign in to comment.