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,13 +8,35 @@ from django.utils.translation import ugettext_lazy as _
8 from haystack.forms import SearchForm 8 from haystack.forms import SearchForm
9 9
10 from accounts.models import User 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 class ColabSearchForm(SearchForm): 14 class ColabSearchForm(SearchForm):
15 q = forms.CharField(label=_('Search'), required=False) 15 q = forms.CharField(label=_('Search'), required=False)
16 order = forms.CharField(widget=forms.HiddenInput(), required=False) 16 order = forms.CharField(widget=forms.HiddenInput(), required=False)
17 type = forms.CharField(required=False, label=_(u'Type')) 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 def search(self): 41 def search(self):
20 if not self.is_valid(): 42 if not self.is_valid():
@@ -33,25 +55,44 @@ class ColabSearchForm(SearchForm): @@ -33,25 +55,44 @@ class ColabSearchForm(SearchForm):
33 types = self.cleaned_data['type'] 55 types = self.cleaned_data['type']
34 sqs = sqs.filter(type__in=types.split()) 56 sqs = sqs.filter(type__in=types.split())
35 57
36 -  
37 if self.cleaned_data['order']: 58 if self.cleaned_data['order']:
38 for option, dict_order in settings.ORDERING_DATA.items(): 59 for option, dict_order in settings.ORDERING_DATA.items():
39 if self.cleaned_data['order'] == option: 60 if self.cleaned_data['order'] == option:
40 if dict_order['fields']: 61 if dict_order['fields']:
41 sqs = sqs.order_by(*dict_order['fields']) 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 if self.load_all: 97 if self.load_all:
57 sqs = sqs.load_all() 98 sqs = sqs.load_all()
src/search/views.py
1 # -*- coding:utf-8 -*- 1 # -*- coding:utf-8 -*-
2 2
3 from django.conf import settings 3 from django.conf import settings
  4 +from django.utils.translation import ugettext as _
  5 +
4 from haystack.views import SearchView 6 from haystack.views import SearchView
5 7
6 8
7 class ColabSearchView(SearchView): 9 class ColabSearchView(SearchView):
8 def extra_context(self, *args, **kwargs): 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 types = { 11 types = {
15 'wiki': { 12 'wiki': {
16 'icon': 'file', 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 'icon': 'thread', 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 'ticket': { 31 'ticket': {
30 'icon': 'ticket', 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 'changeset': { 74 'changeset': {
39 'icon': 'changeset', 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 'user': { 86 'user': {
46 'icon': 'user', 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 return dict( 111 return dict(
55 - types=types.split(),  
56 - types_str=types, 112 + filters=types.get(type_chosen),
  113 + type_chosen=type_chosen,
57 order_data=settings.ORDERING_DATA 114 order_data=settings.ORDERING_DATA
58 ) 115 )
src/super_archives/templates/message-list.html
@@ -27,9 +27,12 @@ @@ -27,9 +27,12 @@
27 <h4>{% trans "Lists" %}</h4> 27 <h4>{% trans "Lists" %}</h4>
28 <ul class="unstyled-list"> 28 <ul class="unstyled-list">
29 {% for list in lists %} 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 {% endfor %} 36 {% endfor %}
34 </ul> 37 </ul>
35 </div> 38 </div>
src/super_archives/utils/url.py
@@ -19,6 +19,7 @@ def pop_from_get(path, query=None, **kwargs): @@ -19,6 +19,7 @@ def pop_from_get(path, query=None, **kwargs):
19 if query_dict[key] == value: 19 if query_dict[key] == value:
20 del query_dict[key] 20 del query_dict[key]
21 continue 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 return u'{}?{}'.format(path, urllib.urlencode(query_dict)) 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,8 +60,9 @@ def thread(request, mailinglist, thread_token):
60 60
61 61
62 def list_messages(request): 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 order_by = request.GET.get('order') 67 order_by = request.GET.get('order')
67 if order_by == 'hottest': 68 if order_by == 'hottest':
@@ -69,9 +70,9 @@ def list_messages(request): @@ -69,9 +70,9 @@ def list_messages(request):
69 else: 70 else:
70 threads = queries.get_latest_threads() 71 threads = queries.get_latest_threads()
71 72
72 - mail_list = request.GET.get('list') 73 + mail_list = selected_lists
73 if mail_list: 74 if mail_list:
74 - threads = threads.filter(mailinglist__name=mail_list) 75 + threads = threads.filter(mailinglist__name__in=mail_list)
75 76
76 paginator = Paginator(threads, 16) 77 paginator = Paginator(threads, 16)
77 try: 78 try:
@@ -86,7 +87,7 @@ def list_messages(request): @@ -86,7 +87,7 @@ def list_messages(request):
86 'lists': lists, 87 'lists': lists,
87 'n_results': paginator.count, 88 'n_results': paginator.count,
88 'threads': threads, 89 'threads': threads,
89 - 'selected_list': selected_list, 90 + 'selected_lists': ' '.join(selected_lists) if selected_lists else '',
90 'order_data': settings.ORDERING_DATA, 91 'order_data': settings.ORDERING_DATA,
91 } 92 }
92 return render(request, 'message-list.html', template_data) 93 return render(request, 'message-list.html', template_data)
src/templates/search/search.html
@@ -17,6 +17,42 @@ @@ -17,6 +17,42 @@
17 <div id="filters" class="hidden-xs hidden-sm col-md-2 col-lg-2"> 17 <div id="filters" class="hidden-xs hidden-sm col-md-2 col-lg-2">
18 <h3>{% trans "Filters" %}</h3> 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 <h4>{% trans "Sort by" %}</h4> 56 <h4>{% trans "Sort by" %}</h4>
21 <ul class="unstyled-list"> 57 <ul class="unstyled-list">
22 {% for option, dict_order in order_data.items %} 58 {% for option, dict_order in order_data.items %}
@@ -33,30 +69,32 @@ @@ -33,30 +69,32 @@
33 {% endfor %} 69 {% endfor %}
34 </ul> 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 </div> 98 </div>
61 99
62 <div class="col-lg-10"> 100 <div class="col-lg-10">