Commit aa5f7fe12dedefd86329699d3c6652f7900aa705

Authored by Alexandre A. Barbosa
2 parents 16a5527f e1694f21

Merge pull request #90 from colab/search_filters

Search filters
colab/accounts/filters.py 0 → 100644
... ... @@ -0,0 +1,24 @@
  1 +from django.utils.translation import ugettext as _
  2 +
  3 +
  4 +def get_filters(request):
  5 + return {
  6 + 'user': {
  7 + 'name': _(u'User'),
  8 + 'icon': 'user',
  9 + 'fields': (
  10 + (
  11 + 'username',
  12 + _(u'Username'),
  13 + request.get('username'),
  14 + ),
  15 + ('name', _(u'Name'), request.get('name')),
  16 + (
  17 + 'institution',
  18 + _(u'Institution'),
  19 + request.get('institution'),
  20 + ),
  21 + ('role', _(u'Role'), request.get('role'))
  22 + ),
  23 + },
  24 + }
... ...
colab/plugins/utils/filters_importer.py 0 → 100644
... ... @@ -0,0 +1,22 @@
  1 +#!/usr/bin/env python
  2 +
  3 +import importlib
  4 +
  5 +from django.conf import settings
  6 +
  7 +
  8 +def import_plugin_filters(request):
  9 + plugin_filters = {}
  10 + for app_name in settings.INSTALLED_APPS:
  11 +
  12 + module_name = '{}.filters'.format(app_name)
  13 + try:
  14 + module = importlib.import_module(module_name)
  15 + except ImportError:
  16 + continue
  17 +
  18 + get_filters = getattr(module, 'get_filters', None)
  19 + if get_filters:
  20 + plugin_filters.update(get_filters(request))
  21 +
  22 + return plugin_filters
... ...
colab/search/forms.py
... ... @@ -35,6 +35,10 @@ class ColabSearchForm(SearchForm):
35 35 keywords = forms.CharField(required=False, label=_(u'Keywords'))
36 36 collaborators = forms.CharField(required=False, label=_(u'Collaborators'))
37 37 repository_name = forms.CharField(required=False, label=_(u'Repository'))
  38 + body = forms.CharField(required=False, label=_(u'Content'))
  39 + description = forms.CharField(required=False, label=_(u'Description'))
  40 + category = forms.CharField(required=False, label=_(u'Category'))
  41 + title = forms.CharField(required=False, label=_(u'Title'))
38 42 username = forms.CharField(required=False, label=_(u'Username'))
39 43 name = forms.CharField(required=False, label=_(u'Name'))
40 44 institution = forms.CharField(required=False, label=_(u'Institution'))
... ... @@ -151,6 +155,14 @@ class ColabSearchForm(SearchForm):
151 155 sqs = sqs.filter(
152 156 repository_name=self.cleaned_data['repository_name']
153 157 )
  158 + if self.cleaned_data['body']:
  159 + sqs = sqs.filter(body=self.cleaned_data['body'])
  160 + if self.cleaned_data['description']:
  161 + sqs = sqs.filter(description=self.cleaned_data['description'])
  162 + if self.cleaned_data['category']:
  163 + sqs = sqs.filter(category=self.cleaned_data['category'])
  164 + if self.cleaned_data['title']:
  165 + sqs = sqs.filter(title=self.cleaned_data['title'])
154 166 if self.cleaned_data['username']:
155 167 sqs = sqs.filter(username=self.cleaned_data['username'])
156 168 if self.cleaned_data['name']:
... ...
colab/search/templates/search/includes/search_filters.html
... ... @@ -16,12 +16,12 @@
16 16 <input type="hidden" name="since" value="{{ request.GET.since }}" />
17 17 <input type="hidden" name="until" value="{{ request.GET.until }}" />
18 18  
19   - {% for field_lookup, field_display, field_value in filters.fields %}
  19 + {% for field_lookup, field_display, field_value, field_type, field_choices in filters.fields %}
20 20 <div class="form-group">
21 21 <label for="{{ field_lookup }}">{{ field_display }}</label>
22   - {% if field_lookup == "list" %}
  22 + {% if field_type == "list" %}
23 23 <select name="{{ field_lookup }}" class="form-control" multiple>
24   - {% for value, option in form.fields.list.choices %}
  24 + {% for value, option in field_choices %}
25 25 <option value="{{ value }}" {% if value in field_value %}selected{% endif %}>{{ option }}</option>
26 26 {% endfor %}
27 27 </select>
... ... @@ -112,10 +112,12 @@
112 112  
113 113 <ul class="unstyled-list">
114 114  
115   - <li>
116   - <span class="glyphicon glyphicon-envelope"></span>
117   - <a href="{% append_to_get type='thread' %}">{% trans "Discussion" %}</a>
118   - </li>
  115 + {% for type, name, icon in filters_options %}
  116 + <li>
  117 + <span class="glyphicon glyphicon-{{icon}}"></span>
  118 + <a href="{% append_to_get type=type %}">{% trans name %}</a>
  119 + </li>
  120 + {% endfor %}
119 121 </ul>
120 122 {% endif %}
121 123 <hr />
... ...
colab/search/templates/search/search.html
... ... @@ -25,13 +25,6 @@ We must use STATIC_URL because we have a language composing the URL
25 25 {% endif %}
26 26 });
27 27  
28   - $('#collapseFilters').on('hide.bs.collapse', function() {
29   - $('.collapse-icon-controller').toggleClass('glyphicon-collapse-down glyphicon-collapse-up');
30   - });
31   - $('#collapseFilters').on('show.bs.collapse', function() {
32   - $('.collapse-icon-controller').toggleClass('glyphicon-collapse-down glyphicon-collapse-up');
33   - });
34   -
35 28 });
36 29 </script>
37 30 {% endblock %}
... ... @@ -74,28 +67,6 @@ We must use STATIC_URL because we have a language composing the URL
74 67 <h3>{% trans "Filters" %}</h3>
75 68 {% include "search/includes/search_filters.html" %}
76 69 </div>
77   -
78   - <div class="col-xs-12 col-sm-12 hidden-md hidden-lg">
79   - <div class="panel-group" id="accordion">
80   - <div class="panel panel-default">
81   - <div class="panel-heading subject">
82   - <a data-toggle="collapse" data-parent="#accordion" href="#collapseFilters">
83   - <h4 class="panel-title">
84   - {% trans "Filters" %}
85   - <span class="glyphicon glyphicon-collapse-down pull-right collapse-icon-controller"></span>
86   - </h4>
87   - </a>
88   - </div>
89   - <div id="collapseFilters" class="panel-collapse collapse">
90   - <div class="panel-body">
91   - {% include "search/includes/search_filters.html" %}
92   - </div>
93   - </div>
94   - </div>
95   - </div>
96   - <hr />
97   - </div>
98   -
99 70 <div class="col-md-10 col-lg-10">
100 71 <ul class="list-unstyled">
101 72 {% for result in page.object_list %}
... ...
colab/search/tests.py
1 1 # -*- coding:utf-8 -*-
2 2  
  3 +import mock
  4 +
  5 +from colab.plugins.utils import filters_importer
3 6 from django.test import TestCase, Client
4 7 from django.core.management import call_command
5 8  
... ... @@ -57,3 +60,23 @@ class SearchViewTest(TestCase):
57 60 self.assertIn('Chuck', user_list[0].object.first_name)
58 61 self.assertIn('Norris', user_list[0].object.last_name)
59 62 self.assertIn('chucknorris', user_list[0].object.username)
  63 +
  64 + def test_search_plugin_filters(self):
  65 + plugin_filter = {
  66 + 'plugin_name': {
  67 + 'name': 'PluginData',
  68 + 'icon': 'plugin_icon',
  69 + 'fields': (
  70 + ('field_1', 'Field1', ''),
  71 + ('field_2', 'Field2', ''),
  72 + ),
  73 + },
  74 + }
  75 + filters_importer.import_plugin_filters = mock.Mock(
  76 + return_value=plugin_filter)
  77 +
  78 + request = self.client.get('/search/?q=')
  79 +
  80 + value = [('plugin_name', 'PluginData', 'plugin_icon')]
  81 +
  82 + self.assertEqual(request.context['filters_options'], value)
... ...
colab/search/views.py
1 1 # -*- coding:utf-8 -*-
2 2  
3 3 from django.conf import settings
4   -from django.utils.translation import ugettext as _
5 4  
6 5 from haystack.views import SearchView
  6 +from colab.plugins.utils import filters_importer
7 7  
8 8  
9 9 class ColabSearchView(SearchView):
... ... @@ -13,127 +13,6 @@ class ColabSearchView(SearchView):
13 13 self.request.LANGUAGE_CODE, (None, None)
14 14 )
15 15  
16   - types = {
17   - 'thread': {
18   - 'name': _(u'Discussion'),
19   - 'fields': (
20   - ('author', _(u'Author'), self.request.GET.get('author')),
21   - (
22   - 'list',
23   - _(u'Mailinglist'),
24   - self.request.GET.getlist('list')
25   - ),
26   - ),
27   - },
28   - }
29   - # TODO: Replace for a more generic plugin architecture
30   - # if settings.TRAC_ENABLED:
31   - # types['wiki'] = {
32   - # 'name': _(u'Wiki'),
33   - # 'fields': (
34   - # ('author', _(u'Author'), self.request.GET.get('author')),
35   - # (
36   - # 'collaborators',
37   - # _(u'Collaborators'),
38   - # self.request.GET.get('collaborators'),
39   - # ),
40   - # ),
41   - # }
42   -
43   - # types['ticket'] = {
44   - # 'name': _(u'Ticket'),
45   - # 'fields': (
46   - # (
47   - # 'milestone',
48   - # _(u'Milestone'),
49   - # self.request.GET.get('milestone')
50   - # ),
51   - # (
52   - # 'priority',
53   - # _(u'Priority'),
54   - # self.request.GET.get('priority')
55   - # ),
56   - # (
57   - # 'component',
58   - # _(u'Component'),
59   - # self.request.GET.get('component')
60   - # ),
61   - # (
62   - # 'severity',
63   - # _(u'Severity'),
64   - # self.request.GET.get('severity')
65   - # ),
66   - # (
67   - # 'reporter',
68   - # _(u'Reporter'),
69   - # self.request.GET.get('reporter')
70   - # ),
71   - # ('author', _(u'Author'), self.request.GET.get('author')),
72   - # ('tag', _(u'Status'), self.request.GET.get('tag')),
73   - # (
74   - # 'keywords',
75   - # _(u'Keywords'),
76   - # self.request.GET.get('keywords'),
77   - # ),
78   - # (
79   - # 'collaborators',
80   - # _(u'Collaborators'),
81   - # self.request.GET.get('collaborators')
82   - # ),
83   - # ),
84   - # }
85   -
86   - # types['changeset'] = {
87   - # 'name': _(u'Changeset'),
88   - # 'fields': (
89   - # ('author', _(u'Author'), self.request.GET.get('author')),
90   - # (
91   - # 'repository_name',
92   - # _(u'Repository'),
93   - # self.request.GET.get('repository_name'),
94   - # ),
95   - # )
96   - # }
97   -
98   - # types['user'] = {
99   - # 'name': _(u'User'),
100   - # 'fields': (
101   - # (
102   - # 'username',
103   - # _(u'Username'),
104   - # self.request.GET.get('username'),
105   - # ),
106   - # ('name', _(u'Name'), self.request.GET.get('name')),
107   - # (
108   - # 'institution',
109   - # _(u'Institution'),
110   - # self.request.GET.get('institution'),
111   - # ),
112   - # ('role', _(u'Role'), self.request.GET.get('role'))
113   - # ),
114   - # }
115   -
116   - # types['attachment'] = {
117   - # 'name': _(u'Attachment'),
118   - # 'fields': (
119   - # (
120   - # 'filename',
121   - # _(u'Filename'),
122   - # self.request.GET.get('filename')
123   - # ),
124   - # ('author', _(u'Author'), self.request.GET.get('author')),
125   - # (
126   - # 'used_by',
127   - # _(u'Used by'), self.request.GET.get('used_by')),
128   - # (
129   - # 'mimetype',
130   - # _(u'File type'),
131   - # self.request.GET.get('mimetype')
132   - # ),
133   - # ('size', _(u'Size'), self.request.GET.get('size')),
134   - # )
135   - # }
136   -
137 16 try:
138 17 type_chosen = self.form.cleaned_data.get('type')
139 18 except AttributeError:
... ... @@ -143,26 +22,17 @@ class ColabSearchView(SearchView):
143 22 size_choices = ()
144 23 used_by_choices = ()
145 24  
146   - # if type_chosen == 'attachment':
147   - # mimetype_choices = [
148   - # (type_, display)
149   - # for type_, display, mimelist_ in settings.FILE_TYPE_GROUPINGS]
150   - # size_choices = [
151   - # ('<500KB', u'< 500 KB'),
152   - # ('500KB__10MB', u'>= 500 KB <= 10 MB'),
153   - # ('>10MB', u'> 10 MB'),
154   - # ]
155   - # used_by_choices = set([
156   - # (v, v) for v in Attachment.objects.values_list('used_by',
157   - # flat=True)
158   - # ])
159   -
160 25 mimetype_chosen = self.request.GET.get('mimetype')
161 26 size_chosen = self.request.GET.get('size')
162 27 used_by_chosen = self.request.GET.get('used_by')
163 28  
  29 + types = filters_importer.import_plugin_filters(self.request.GET)
  30 +
  31 + filters_options = [(k, v['name'], v['icon'])
  32 + for (k, v) in types.iteritems()]
164 33 return dict(
165 34 filters=types.get(type_chosen),
  35 + filters_options=filters_options,
166 36 type_chosen=type_chosen,
167 37 order_data=settings.ORDERING_DATA,
168 38 date_format=date_format,
... ...
colab/super_archives/filters.py 0 → 100644
... ... @@ -0,0 +1,22 @@
  1 +from django.utils.translation import ugettext as _
  2 +from colab.super_archives.models import MailingList
  3 +
  4 +
  5 +def get_filters(request):
  6 + return {
  7 + 'thread': {
  8 + 'name': _(u'Discussion'),
  9 + 'icon': 'envelope',
  10 + 'fields': (
  11 + ('author', _(u'Author'), request.get('author')),
  12 + (
  13 + 'list',
  14 + _(u'Mailinglist'),
  15 + request.get('list'),
  16 + 'list',
  17 + [(v, v) for v in MailingList.objects.values_list(
  18 + 'name', flat=True)]
  19 + ),
  20 + ),
  21 + },
  22 + }
... ...