Commit 0de20def88c698cd8a23188dc1eb0ac043e6427c

Authored by Luan
2 parents f902ae63 6d21f9fb

Merge branch 'haystack'

src/search/forms.py
... ... @@ -8,13 +8,35 @@ from django.utils.translation import ugettext_lazy as _
8 8 from haystack.forms import SearchForm
9 9  
10 10 from accounts.models import User
11   -from super_archives.models import Message
  11 +from super_archives.models import Message, MailingList
12 12  
13 13  
14 14 class ColabSearchForm(SearchForm):
15 15 q = forms.CharField(label=_('Search'), required=False)
16 16 order = forms.CharField(widget=forms.HiddenInput(), required=False)
17 17 type = forms.CharField(required=False, label=_(u'Type'))
  18 + author = forms.CharField(required=False, label=_(u'Author'))
  19 + # ticket status
  20 + tag = forms.CharField(required=False, label=_(u'Status'))
  21 + # mailinglist tag
  22 + list = forms.MultipleChoiceField(
  23 + required=False,
  24 + label=_(u'Mailinglist'),
  25 + choices=[(v, v) for v in MailingList.objects.values('name')
  26 + for (v, v) in v.items()]
  27 + )
  28 + milestone = forms.CharField(required=False, label=_(u'Milestone'))
  29 + priority = forms.CharField(required=False, label=_(u'Priority'))
  30 + component = forms.CharField(required=False, label=_(u'Component'))
  31 + severity = forms.CharField(required=False, label=_(u'Severity'))
  32 + reporter = forms.CharField(required=False, label=_(u'Reporter'))
  33 + keywords = forms.CharField(required=False, label=_(u'Keywords'))
  34 + collaborators = forms.CharField(required=False, label=_(u'Collaborators'))
  35 + repository_name = forms.CharField(required=False, label=_(u'Repository'))
  36 + username = forms.CharField(required=False, label=_(u'Username'))
  37 + name = forms.CharField(required=False, label=_(u'Name'))
  38 + institution = forms.CharField(required=False, label=_(u'Institution'))
  39 + role = forms.CharField(required=False, label=_(u'Role'))
18 40  
19 41 def search(self):
20 42 if not self.is_valid():
... ... @@ -33,25 +55,44 @@ class ColabSearchForm(SearchForm):
33 55 types = self.cleaned_data['type']
34 56 sqs = sqs.filter(type__in=types.split())
35 57  
36   -
37 58 if self.cleaned_data['order']:
38 59 for option, dict_order in settings.ORDERING_DATA.items():
39 60 if self.cleaned_data['order'] == option:
40 61 if dict_order['fields']:
41 62 sqs = sqs.order_by(*dict_order['fields'])
42   - # if self.cleaned_data['type'] == 'user':
43   - # sqs = self.searchqueryset.models(User)
44   - # elif self.cleaned_data['type'] in ['message', 'thread']:
45   - # sqs = self.searchqueryset.models(Message)
46   - # elif self.cleaned_data['type'] == 'wiki':
47   - # sqs = self.searchqueryset.models(Wiki)
48   - # elif self.cleaned_data['type'] == 'changeset':
49   - # sqs = self.searchqueryset.models(Changeset)
50   - # elif self.cleaned_data['type'] == 'ticket':
51   - # sqs = self.searchqueryset.models(Ticket)
52   - # else:
53   - # sqs = self.searchqueryset.all()
54 63  
  64 + if self.cleaned_data['author']:
  65 + sqs = sqs.filter(author=self.cleaned_data['author'])
  66 +
  67 + if self.cleaned_data['milestone']:
  68 + sqs = sqs.filter(milestone=self.cleaned_data['milestone'])
  69 + if self.cleaned_data['priority']:
  70 + sqs = sqs.filter(priority=self.cleaned_data['priority'])
  71 + if self.cleaned_data['severity']:
  72 + sqs = sqs.filter(severity=self.cleaned_data['severity'])
  73 + if self.cleaned_data['reporter']:
  74 + sqs = sqs.filter(reporter=self.cleaned_data['reporter'])
  75 + if self.cleaned_data['keywords']:
  76 + sqs = sqs.filter(keywords=self.cleaned_data['keywords'])
  77 + if self.cleaned_data['collaborators']:
  78 + sqs = sqs.filter(collaborators=self.cleaned_data['collaborators'])
  79 + if self.cleaned_data['repository_name']:
  80 + sqs = sqs.filter(
  81 + repository_name=self.cleaned_data['repository_name']
  82 + )
  83 + if self.cleaned_data['username']:
  84 + sqs = sqs.filter(username=self.cleaned_data['username'])
  85 + if self.cleaned_data['name']:
  86 + sqs = sqs.filter(name=self.cleaned_data['name'])
  87 + if self.cleaned_data['institution']:
  88 + sqs = sqs.filter(institution=self.cleaned_data['institution'])
  89 + if self.cleaned_data['role']:
  90 + sqs = sqs.filter(role=self.cleaned_data['role'])
  91 + if self.cleaned_data['tag']:
  92 + sqs = sqs.filter(tag=self.cleaned_data['tag'])
  93 +
  94 + if self.cleaned_data['list']:
  95 + sqs = sqs.filter(tag__in=self.cleaned_data['list'])
55 96  
56 97 if self.load_all:
57 98 sqs = sqs.load_all()
... ...
src/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 from haystack.views import SearchView
5 7  
6 8  
7 9 class ColabSearchView(SearchView):
8 10 def extra_context(self, *args, **kwargs):
9   - # Retornar todos os campos de cada tipo a serem filtrados
10   - # retornar os nomes dos campos
11   - # retornar os ícones dos tipos
12   -
13   - # a critical point on the system
14 11 types = {
15 12 'wiki': {
16 13 'icon': 'file',
17   - 'fields': [
18   - 'title', 'description', 'author', 'collaborators',
19   - 'created', 'modified',
20   - ],
  14 + 'name': _(u'Wiki'),
  15 + 'fields': (
  16 + ('author', _(u'Author'), self.request.GET.get('author')),
  17 + ),
21 18 },
22   - 'discussion': {
  19 + 'thread': {
23 20 'icon': 'thread',
24   - 'fields': [
25   - 'title', 'description', 'created', 'modified', 'author',
26   - 'tag',
27   - ],
  21 + 'name': _(u'Discussion'),
  22 + 'fields': (
  23 + ('author', _(u'Author'), self.request.GET.get('author')),
  24 + (
  25 + 'list',
  26 + _(u'Mailinglist'),
  27 + self.request.GET.getlist('list')
  28 + ),
  29 + ),
28 30 },
29 31 'ticket': {
30 32 'icon': 'ticket',
31   - 'fields': [
32   - 'title', 'description', 'milestone', 'priority',
33   - 'component', 'version', 'severity', 'reporter', 'author',
34   - 'status', 'keywords', 'collaborators', 'created',
35   - 'modified',
36   - ],
  33 + 'name': _(u'Ticket'),
  34 + 'fields': (
  35 + (
  36 + 'milestone',
  37 + _(u'Milestone'),
  38 + self.request.GET.get('milestone')
  39 + ),
  40 + (
  41 + 'priority',
  42 + _(u'Priority'),
  43 + self.request.GET.get('priority')
  44 + ),
  45 + (
  46 + 'component',
  47 + _(u'Component'),
  48 + self.request.GET.get('component')
  49 + ),
  50 + (
  51 + 'severity',
  52 + _(u'Severity'),
  53 + self.request.GET.get('severity')
  54 + ),
  55 + (
  56 + 'reporter',
  57 + _(u'Reporter'),
  58 + self.request.GET.get('reporter')
  59 + ),
  60 + ('author', _(u'Author'), self.request.GET.get('author')),
  61 + ('tag', _(u'Status'), self.request.GET.get('tag')),
  62 + (
  63 + 'keywords',
  64 + _(u'Keywords'),
  65 + self.request.GET.get('keywords'),
  66 + ),
  67 + (
  68 + 'collaborators',
  69 + _(u'Collaborators'),
  70 + self.request.GET.get('collaborators')
  71 + ),
  72 + ),
37 73 },
38 74 'changeset': {
39 75 'icon': 'changeset',
40   - 'fields': [
41   - 'title', 'author', 'description', 'repository_name',
42   - 'created', 'modified',
43   - ],
  76 + 'name': _(u'Changeset'),
  77 + 'fields': (
  78 + ('author', _(u'Author'), self.request.GET.get('author')),
  79 + (
  80 + 'repository_name',
  81 + _(u'Repository'),
  82 + self.request.GET.get('repository_name'),
  83 + ),
  84 + )
44 85 },
45 86 'user': {
46 87 'icon': 'user',
47   - 'fields': [
48   - 'title', 'description', 'username', 'name',
49   - 'email', 'institution', 'role', 'google_talk', 'webpage',
50   - ],
  88 + 'name': _(u'User'),
  89 + 'fields': (
  90 + (
  91 + 'username',
  92 + _(u'Username'),
  93 + self.request.GET.get('username'),
  94 + ),
  95 + ('name', _(u'Name'), self.request.GET.get('name')),
  96 + (
  97 + 'institution',
  98 + _(u'Institution'),
  99 + self.request.GET.get('institution'),
  100 + ),
  101 + ('role', _(u'Role'), self.request.GET.get('role'))
  102 + ),
51 103 },
52 104 }
53   - types = self.form.cleaned_data['type']
  105 +
  106 + try:
  107 + type_chosen = self.form.cleaned_data.get('type')
  108 + except AttributeError:
  109 + type_chosen = ''
  110 +
54 111 return dict(
55   - types=types.split(),
56   - types_str=types,
  112 + filters=types.get(type_chosen),
  113 + type_chosen=type_chosen,
57 114 order_data=settings.ORDERING_DATA
58 115 )
... ...
src/super_archives/templates/message-list.html
... ... @@ -27,9 +27,12 @@
27 27 <h4>{% trans "Lists" %}</h4>
28 28 <ul class="unstyled-list">
29 29 {% for list in lists %}
30   - <li {% if list.name == selected_list %} title="{% trans "Remove filter" %}" class="selected" {% endif %}>
31   - <span class="glyphicon {% if list.name == selected_list %}glyphicon-remove{% else %}glyphicon-chevron-right{% endif %}"></span> <a href="{% ifnotequal list.name selected_list %} {% append_to_get list=list.name p=1 %} {% else %} {% append_to_get list="" p=1 %}
32   - {% endifnotequal %}">{{ list.name }}</a></li>
  30 + {% with list.name|add:" "|add:selected_lists as list_name %}
  31 + <li {% if list.name in selected_lists %} title="{% trans "Remove filter" %}" class="selected" {% endif %}>
  32 + <span class="glyphicon {% if list.name in selected_lists %}glyphicon-remove{% else %}glyphicon-chevron-right{% endif %}"></span>
  33 + <a href="{% if not list.name in selected_lists %}{% append_to_get list=list_name p=1 %}{% else %}{% pop_from_get list=list.name %}{% endif %}">{{ list.name }}</a>
  34 + </li>
  35 + {% endwith %}
33 36 {% endfor %}
34 37 </ul>
35 38 </div>
... ...
src/super_archives/utils/url.py
... ... @@ -19,6 +19,7 @@ def pop_from_get(path, query=None, **kwargs):
19 19 if query_dict[key] == value:
20 20 del query_dict[key]
21 21 continue
22   - if not query_dict:
23   - return u'{}?q='.format(path)
  22 + if value in query_dict[key]:
  23 + aux = query_dict[key].split(value)
  24 + query_dict[key] = u''.join(aux).strip()
24 25 return u'{}?{}'.format(path, urllib.urlencode(query_dict))
... ...
src/super_archives/views.py
... ... @@ -60,8 +60,9 @@ def thread(request, mailinglist, thread_token):
60 60  
61 61  
62 62 def list_messages(request):
63   -
64   - selected_list = request.GET.get('list')
  63 + selected_lists = request.GET.get('list', [])
  64 + if selected_lists:
  65 + selected_lists = selected_lists.split()
65 66  
66 67 order_by = request.GET.get('order')
67 68 if order_by == 'hottest':
... ... @@ -69,9 +70,9 @@ def list_messages(request):
69 70 else:
70 71 threads = queries.get_latest_threads()
71 72  
72   - mail_list = request.GET.get('list')
  73 + mail_list = selected_lists
73 74 if mail_list:
74   - threads = threads.filter(mailinglist__name=mail_list)
  75 + threads = threads.filter(mailinglist__name__in=mail_list)
75 76  
76 77 paginator = Paginator(threads, 16)
77 78 try:
... ... @@ -86,7 +87,7 @@ def list_messages(request):
86 87 'lists': lists,
87 88 'n_results': paginator.count,
88 89 'threads': threads,
89   - 'selected_list': selected_list,
  90 + 'selected_lists': ' '.join(selected_lists) if selected_lists else '',
90 91 'order_data': settings.ORDERING_DATA,
91 92 }
92 93 return render(request, 'message-list.html', template_data)
... ...
src/templates/search/search.html
... ... @@ -17,6 +17,42 @@
17 17 <div id="filters" class="hidden-xs hidden-sm col-md-2 col-lg-2">
18 18 <h3>{% trans "Filters" %}</h3>
19 19  
  20 + {% if filters %}
  21 + <ul class="unstyled-list">
  22 + <li class="selected" title="{% trans "Remove filter" %}">
  23 + <span class="glyphicon glyphicon-remove"></span>
  24 + <a href="{% url 'haystack_search' %}?q={{ request.GET.q }}">
  25 + <span class="glyphicon glyphicon-{{ filters.icon }}"></span>
  26 + {{ filters.name }}
  27 + </a>
  28 + </li>
  29 + </ul>
  30 + <hr />
  31 + <form role="form">
  32 + <input type="hidden" name="q" value="{{ request.GET.q }}" />
  33 + <input type="hidden" name="type" value="{{ type_chosen }}" />
  34 +
  35 + {% for field_lookup, field_display, field_value in filters.fields %}
  36 + <div class="form-group">
  37 + <label for="{{ field_lookup }}">{{ field_display }}</label>
  38 + {% ifequal field_lookup "list" %}
  39 + <select name="{{ field_lookup }}" class="form-control" multiple>
  40 + {% for value, option in form.fields.list.choices %}
  41 + <option value="{{ value }}" {% if value in field_value %}selected{% endif %}>{{ option }}</option>
  42 + {% endfor %}
  43 + </select>
  44 + {% else %}
  45 + <div class="input-group">
  46 + <input type="text" class="form-control" placeholder="{{ field_display }}" name="{{ field_lookup }}" {% if field_value %}value="{{ field_value }}"{% endif %}>
  47 + </div>
  48 + {% endifequal %}
  49 + </div>
  50 + {% endfor %}
  51 + <input type="submit" class="btn btn-default pull-right" value="{% trans 'Filter' %}" />
  52 + </form>
  53 + <br /><hr />
  54 + {% endif %}
  55 +
20 56 <h4>{% trans "Sort by" %}</h4>
21 57 <ul class="unstyled-list">
22 58 {% for option, dict_order in order_data.items %}
... ... @@ -33,30 +69,32 @@
33 69 {% endfor %}
34 70 </ul>
35 71  
36   - <h4>{% trans "Types" %}</h4>
  72 + {% if not request.GET.type %}
  73 + <h4>{% trans "Types" %}</h4>
37 74  
38   - <ul class="unstyled-list">
39   - <li>
40   - <span class="glyphicon glyphicon-file"></span>
41   - <a href="{% append_to_get type='wiki' %}">{% trans "Wiki" %}</a>
42   - </li>
43   - <li>
44   - <span class="glyphicon glyphicon-envelope"></span>
45   - <a href="{% append_to_get type='thread' %}">{% trans "Discussion" %}</a>
46   - </li>
47   - <li>
48   - <span class="glyphicon glyphicon-tag"></span>
49   - <a href="{% append_to_get type='ticket' %}">{% trans "Ticket" %}</a>
50   - </li>
51   - <li>
52   - <span class="glyphicon glyphicon-align-right"></span>
53   - <a href="{% append_to_get type='changeset' %}">{% trans "Changeset" %}</a>
54   - </li>
55   - <li>
56   - <span class="glyphicon glyphicon-user"></span>
57   - <a href="{% append_to_get type='user' %}">{% trans "User" %}</a>
58   - </li>
59   - </ul>
  75 + <ul class="unstyled-list">
  76 + <li>
  77 + <span class="glyphicon glyphicon-file"></span>
  78 + <a href="{% append_to_get type='wiki' %}">{% trans "Wiki" %}</a>
  79 + </li>
  80 + <li>
  81 + <span class="glyphicon glyphicon-envelope"></span>
  82 + <a href="{% append_to_get type='thread' %}">{% trans "Discussion" %}</a>
  83 + </li>
  84 + <li>
  85 + <span class="glyphicon glyphicon-tag"></span>
  86 + <a href="{% append_to_get type='ticket' %}">{% trans "Ticket" %}</a>
  87 + </li>
  88 + <li>
  89 + <span class="glyphicon glyphicon-align-right"></span>
  90 + <a href="{% append_to_get type='changeset' %}">{% trans "Changeset" %}</a>
  91 + </li>
  92 + <li>
  93 + <span class="glyphicon glyphicon-user"></span>
  94 + <a href="{% append_to_get type='user' %}">{% trans "User" %}</a>
  95 + </li>
  96 + </ul>
  97 + {% endif %}
60 98 </div>
61 99  
62 100 <div class="col-lg-10">
... ...