Skip to content

Commit 4515c75

Browse files
committed
search improvements
1 parent cd22791 commit 4515c75

File tree

5 files changed

+109
-44
lines changed

5 files changed

+109
-44
lines changed

CHANGES.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
1.7.4 (unreleased)
22
------------------
33

4-
- Nothing changed yet.
4+
- search improvements [amleczko]
55

66

77
1.7.3 (2013-04-30)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<input type="hidden" name="__start__" value="${field.name}:sequence"/>
2+
<select name="${field.name}"
3+
id="${field.oid}"
4+
multiple="multiple"
5+
class="i-can-haz-chzn-select"
6+
tal:attributes="size field.widget.size;
7+
style getattr(field.widget, 'style', nothing);
8+
data-placeholder getattr(field.widget, 'placeholder', nothing)">
9+
<option tal:repeat="(value, description) field.widget.values"
10+
tal:attributes="selected value in cstruct and 'selected';
11+
class field.widget.css_class"
12+
value="${value}">${description}</option>
13+
</select>
14+
15+
<script type="text/javascript">
16+
deform.addCallback(
17+
'${field.oid}',
18+
function(oid) {
19+
$('#' + oid).chosen();
20+
}
21+
);
22+
</script>
23+
<input type="hidden" name="__end__" value="${field.name}:sequence"/>

por/dashboard/search.py

+63-20
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sunburnt import SolrInterface
77
from pyramid.view import view_config
88
from pyramid.url import current_route_url
9-
from por.models.dashboard import Trac
9+
from por.models.dashboard import Trac, User
1010
from por.models import DBSession
1111
from por.dashboard.lib.widgets import SearchButton, PorInlineForm
1212
from deform_bootstrap.widget import ChosenMultipleWidget
@@ -41,18 +41,29 @@ def searchable_tracs(request):
4141

4242

4343
class SearchSchema(colander.MappingSchema):
44+
4445
tracs = colander.SchemaNode(deform.Set(allow_empty=True),
45-
widget=ChosenMultipleWidget(placeholder=u'Select tracs'),
46-
missing=colander.null,
47-
title=u'')
46+
widget=ChosenMultipleWidget(placeholder=u'Select tracs',
47+
style="width:250px"),
48+
missing=colander.null,
49+
title=u'')
50+
4851
realms = colander.SchemaNode(deform.Set(allow_empty=True),
49-
widget=ChosenMultipleWidget(placeholder=u'Select realms',
50-
values=[('', ''),
51-
('ticket', 'Ticket'),
52-
('wiki', 'Wiki'),
53-
('changeset','Changeset')]),
54-
missing=colander.null,
55-
title=u'')
52+
widget=ChosenMultipleWidget(placeholder=u'Select realms',
53+
style="width:250px",
54+
values=[('', ''),
55+
('ticket', 'Ticket'),
56+
('wiki', 'Wiki'),
57+
('changeset','Changeset')]),
58+
missing=colander.null,
59+
title=u'')
60+
61+
authors = colander.SchemaNode(deform.Set(allow_empty=True),
62+
widget=ChosenMultipleWidget(placeholder=u'Select author',
63+
style="width:250px"),
64+
missing=colander.null,
65+
title=u'')
66+
5667
searchable = colander.SchemaNode(typ=colander.String(),
5768
title=u'',
5869
widget = deform.widget.TextInputWidget(
@@ -72,7 +83,12 @@ def search(request):
7283
)
7384

7485
tracs = searchable_tracs(request)
75-
form['tracs'].widget.values = [('', '')] + [(t.trac_name, t.project_name) for t in tracs]
86+
form['tracs'].widget.values = [('', '')] \
87+
+ [(t.trac_name, t.project_name) for t in tracs]
88+
89+
users = DBSession.query(User).order_by(User.fullname)
90+
form['authors'].widget.values = [('', '')] \
91+
+ [(a.email, a.fullname) for a in users]
7692

7793
controls = request.GET.items()
7894
if not controls:
@@ -96,37 +112,45 @@ def search(request):
96112

97113
if results:
98114
docs = [FullTextSearchObject(**doc) for doc in results]
99-
base_query = dict(request.params)
100115
records_len = results.result.numFound
101116
if not fs.page_start + fs.page_size >= records_len: # end of set
102-
next_query = base_query.copy()
103-
next_query['page_start'] = fs.page_start + fs.page_size
117+
next_query = add_param(request, 'page_start', fs.page_start + fs.page_size)
104118
next_url = current_route_url(request, _query=next_query)
105119

106120
if not fs.page_start == 0:
107121
previous_page = fs.page_start - fs.page_size
108122
if previous_page < 0:
109123
previous_page = 0
110-
previous_query = base_query.copy()
111-
previous_query['page_start'] = previous_page
124+
previous_query = add_param(request, 'page_start', previous_page)
112125
previous_url = current_route_url(request, _query=previous_query)
113126

114127
return {'docs': docs,
115128
'next': next_url,
116129
'form': form.render(appstruct=appstruct),
117130
'previous': previous_url,
131+
'add_param': add_param,
118132
'results': results}
119133

120134

135+
def add_param(request, key, value):
136+
base_query = request.params.copy()
137+
base_query[key] = value
138+
return base_query
139+
140+
121141
class FullTextSearch(object):
122142

123-
def __init__(self, request, tracs=None, searchable=None, realms=None):
143+
def __init__(self, request, tracs=None, searchable=None,
144+
realms=None, authors=None):
124145
if not realms:
125146
realms = []
147+
if not authors:
148+
authors = []
126149
self.request = request
127-
self.viewable_tracs = list(tracs)
128150
self.searchable = searchable.split(' ') # always a sequence
151+
self.viewable_tracs = list(tracs)
129152
self.realms = list(realms)
153+
self.authors = list(authors)
130154
self.solr_endpoint = request.registry.settings.get('por.solr')
131155

132156
@property
@@ -193,6 +217,21 @@ def query(items):
193217
return ""
194218
return query(self.realms)
195219

220+
def _build_author_filter(self, si):
221+
222+
Q = si.query().Q
223+
224+
def query(items):
225+
if len(items) > 2:
226+
return Q(author=items.pop()) | query(items)
227+
elif len(items) == 2:
228+
return Q(author=items.pop()) | Q(author=items.pop())
229+
elif len(items) == 1:
230+
return Q(author=items.pop())
231+
else:
232+
return ""
233+
return query(self.authors)
234+
196235
def _do_search(self, sort_by=None):
197236
si = SolrInterface(self.solr_endpoint)
198237
query = si.query().field_limit(score=True)
@@ -204,6 +243,10 @@ def _do_search(self, sort_by=None):
204243
if realm_query:
205244
query = query.filter(realm_query)
206245

246+
author_query = self._build_author_filter(si)
247+
if author_query:
248+
query = query.filter(author_query)
249+
207250
trac_query = self._build_trac_filter(si)
208251
if trac_query:
209252
query = query.filter(trac_query)
@@ -253,7 +296,7 @@ def __init__(self, project, realm, id=None, score=None,
253296
if not author:
254297
author = ()
255298
self.project = project
256-
self.author = ', '.join(author + involved)
299+
self.author = ', '.join(author)
257300
self.created = created
258301
self.popularity = popularity
259302
self.comments = comments

por/dashboard/skins/search.pt

+10-23
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,16 @@
1212
<li tal:condition="previous"><a href="${previous}">Previous</a></li>
1313
<li tal:condition="next"><a href="${next}">Next</a></li>
1414
</ul>
15-
<table class="table table-bordered time-entries table-condensed table-search">
16-
<thead>
17-
<tr>
18-
<th>type</th>
19-
<th>project</th>
20-
<th>title</th>
21-
<th>description</th>
22-
<th>authors</th>
23-
<th>score</th>
24-
</tr>
25-
</thead>
26-
<tbody>
27-
<tr tal:repeat="doc docs">
28-
<td>${doc.realm}</td>
29-
<td>${doc.project}</td>
30-
<td><a href="${request.application_url}/${doc.href()}"
31-
tal:content="structure doc.title"></a></td>
32-
<td tal:content="structure doc.oneline"></td>
33-
<td>${doc.author}</td>
34-
<td>${doc.score}</td>
35-
</tr>
36-
</tbody>
37-
</table>
15+
<div id="results">
16+
<tal:result repeat="doc docs">
17+
<dt><a href="${request.application_url}/${doc.href()}"
18+
tal:content="structure doc.title"></a></dt>
19+
<dd tal:content="structure doc.oneline"></dd>
20+
<dd>By <a href="${request.current_route_url(_query=add_param(request,'authors',doc.author))}">${doc.author}</a>
21+
in <a href="${request.current_route_url(_query=add_param(request,'tracs',doc.project))}">${doc.project}</a>
22+
</dd>
23+
</tal:result>
24+
</div>
3825
<ul class="pager">
3926
<li tal:condition="previous"><a href="${previous}">Previous</a></li>
4027
<li tal:condition="next"><a href="${next}">Next</a></li>

por/dashboard/static/css/dashboard.css

+12
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,18 @@ table.time-entries tbody tr:hover th {
223223
{display: none;}
224224
}
225225

226+
div#results dt{
227+
margin: 1.5em 0 0;
228+
}
229+
230+
div#results .author{
231+
color: #090;
232+
}
233+
234+
div#results dd{
235+
font-size: 0.9em;
236+
margin: 0.2em 1em;
237+
}
226238

227239

228240
/* XXX unused? */

0 commit comments

Comments
 (0)