Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f363a52

Browse files
first pass of the search, filtering, and sorting
1 parent 6cbca92 commit f363a52

File tree

7 files changed

+214
-101
lines changed

7 files changed

+214
-101
lines changed

‎mpeds_coder.py‎

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import assign_lib
4646

4747
## db
48-
from sqlalchemy import func, desc, distinct, or_, text
48+
from sqlalchemy import func, desc, distinct, and_, or_, text
4949
from sqlalchemy.sql import select
5050

5151
## app-specific
@@ -573,13 +573,19 @@ def adj():
573573
"""Initial rendering for adjudication page."""
574574

575575
## TODO: These are placeholders which will be gathered from queries later
576-
query1 = 'Chicago'
577-
query2 = '2016年05月24日'
576+
filter_field1 = 'start_date'
577+
filter_compare1 = '__eq__'
578+
filter_value1 = '2016年05月24日'
578579

579-
## perform the query on the web
580-
search_events = db_session.query(EventMetadata).\
581-
filter(EventMetadata.location.like('%{}%'.format(query1)),
582-
EventMetadata.start_date == query2).all()
580+
filter_field2 = 'location'
581+
filter_compare2 = 'like'
582+
filter_value2 = 'Chicago'
583+
584+
filter_expr1 = getattr(getattr(EventMetadata, filter_field1), filter_compare1)(filter_value1)
585+
filter_expr2 = getattr(getattr(EventMetadata, filter_field2), filter_compare2)('%{}%'.format(filter_value2))
586+
587+
## perform the query and get the results
588+
search_events = db_session.query(EventMetadata).filter(filter_expr1, filter_expr2).all()
583589

584590
## Get five recent events
585591
recent_events = [x[0] for x in db_session.query(EventMetadata, RecentEvent).\
@@ -653,13 +659,99 @@ def do_search():
653659
which meet the search criteria."""
654660
search_params = request.args.to_dict()
655661

656-
filter_field = search_params.get('filter_field')
657-
filter_value = search_params.get('filter_value')
658-
filter_compare = search_params.get('filter_compare')
662+
filter_field = search_params.get('adj-filter-field')
663+
filter_value = search_params.get('adj-filter-value')
664+
filter_compare = search_params.get('adj-filter-compare')
665+
666+
search_str = search_params.get('adj-search-input')
667+
668+
sort_field = search_params.get('adj-sort-field')
669+
sort_order = search_params.get('adj-sort-order')
670+
671+
## TODO: Need to account for multiple different filters and sorting terms.
672+
673+
filter_expr = None
674+
if filter_field and filter_value and filter_compare:
675+
## Translate the filter compare to a SQLAlchemy expression.
676+
if filter_compare == 'eq':
677+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__eq__')(filter_value)
678+
elif filter_compare == 'ne':
679+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__ne__')(filter_value)
680+
elif filter_compare == 'lt':
681+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__lt__')(filter_value)
682+
elif filter_compare == 'le':
683+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__le__')(filter_value)
684+
elif filter_compare == 'gt':
685+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__gt__')(filter_value)
686+
elif filter_compare == 'ge':
687+
filter_expr = getattr(getattr(EventMetadata, filter_field), '__ge__')(filter_value)
688+
elif filter_compare == 'like':
689+
filter_expr = getattr(getattr(EventMetadata, filter_field), 'like')('%{}%'.format(filter_value))
690+
elif filter_compare == 'startswith':
691+
filter_expr = getattr(getattr(EventMetadata, filter_field), 'like')('{}%'.format(filter_value))
692+
elif filter_compare == 'endswith':
693+
filter_expr = getattr(getattr(EventMetadata, filter_field), 'like')('%{}'.format(filter_value))
694+
else:
695+
raise Exception('Invalid filter compare: {}'.format(filter_compare))
696+
697+
search_expr = None
698+
if search_str:
699+
## Get all fields that are searchable.
700+
search_fields = EventMetadata.__table__.columns.keys()
701+
search_fields.remove('id')
702+
703+
## Build the search expression. For now, it can only do an AND or OR search.
704+
operator = and_
705+
if ' AND ' in search_str:
706+
search_terms = search_str.split(' AND ')
707+
operator = and_
708+
elif ' OR ' in search_str:
709+
search_terms = search_str.split(' OR ')
710+
operator = or_
711+
else:
712+
search_terms = [search_str]
713+
714+
## Build the search by creating an expression for each search term and search field.
715+
search_expr = []
716+
for term in search_terms:
717+
term_expr = []
718+
for field in search_fields:
719+
term_expr.append(getattr(getattr(EventMetadata, field), 'like')('%{}%'.format(term)))
720+
search_expr.append(or_(*term_expr))
721+
search_expr = operator(*search_expr)
722+
723+
## Sort by the specified field.
724+
sort_expr = None
725+
if sort_field and sort_order:
726+
sort_expr = getattr(getattr(EventMetadata, sort_field), sort_order)()
727+
728+
print(sort_expr)
729+
730+
a_filter_expr = None
731+
if filter_expr is not None and search_expr is not None:
732+
a_filter_expr = and_(filter_expr, search_expr)
733+
elif filter_expr is not None:
734+
a_filter_expr = filter_expr
735+
elif search_expr is not None:
736+
a_filter_expr = search_expr
737+
else:
738+
return make_response("Please enter a search term or a filter.", 400)
739+
740+
search_events = db_session.query(EventMetadata).\
741+
filter(a_filter_expr).\
742+
order_by(sort_expr).all()
743+
744+
## TODO: Eventually need to load candidate events
745+
response = make_response(
746+
render_template('adj-search-block.html',
747+
search_events = search_events,
748+
cand_events = {})
749+
)
750+
751+
## make and return results. add in the number of results to update the button.
752+
response.headers['Search-Results'] = len(search_events)
753+
return response
659754

660-
## TODO: Do the filtering. Find a way to translate the filter compare
661-
## to a SQLAlchemy expression.
662-
pass
663755

664756
@app.route('/adj_search/<function>', methods = ['POST'])
665757
@login_required

‎static/adj.js‎

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -536,20 +536,7 @@ $(function () {
536536
})
537537
});
538538

539-
// Listener for searches additions
540-
$('#adj-search-button').click(function() {
541-
var req = $.ajax({
542-
url: $SCRIPT_ROOT + '/adj_search/search',
543-
type: "POST",
544-
data: {
545-
is_addition: true,
546-
search_str: $('#adj-search-input').val()
547-
}
548-
})
549-
.done(function() {$('#adj-search-form').append(req.responseText); })
550-
.fail(function() { return makeError(req.responseText); });
551-
});
552-
539+
// Listener for filters and sorting
553540
$('#adj-filter-button').click(function() {
554541
var req = $.ajax({
555542
url: $SCRIPT_ROOT + '/adj_search/filter',
@@ -574,6 +561,37 @@ $(function () {
574561
.fail(function() { return makeError(req.responseText); });
575562
});
576563

564+
// Listener for search button.
565+
$('#adj-search-button').click(function() {
566+
var req = $.ajax({
567+
url: $SCRIPT_ROOT + '/do_search',
568+
type: "GET",
569+
data:
570+
$('#adj-search-form, #adj-filter-form, #adj-sort-form').serialize(),
571+
beforeSend: function () {
572+
$('.flash').removeClass('alert-danger');
573+
$('.flash').addClass('alert-info');
574+
$('.flash').text("Loading...");
575+
$('.flash').show();
576+
}
577+
})
578+
.done(function() {
579+
$('#cand-search_block').html(req.responseText);
580+
581+
// TODO: Update the URL search params.
582+
583+
// Update the search button text.
584+
n_results = req.getResponseHeader('Search-Results');
585+
$('#cand-search-text').text("Search (" + n_results + " results)");
586+
587+
// get rid of loading flash
588+
$('.flash').hide();
589+
$('.flash').removeClass('alert-info');
590+
return true;
591+
})
592+
.fail(function() { return makeError(req.responseText); });
593+
});
594+
577595
loadSearch();
578596

579597
// initialize the grid

‎templates/adj-filter.html‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
<select class="form-control"
1414
name="adj-filter-compare"
1515
id="adj-filter-compare">
16-
<option>equals</option>
17-
<option>is greater than</option>
18-
<option>is greater than or equal to</option>
19-
<option>is less than</option>
20-
<option>is less than or equal to</option>
21-
<option>contains</option>
22-
<option>starts with</option>
23-
<option>ends with</option>
16+
<optionvalue="eq">equals</option>
17+
<optionvalue="gt">is greater than</option>
18+
<optionvalue="gte">is greater than or equal to</option>
19+
<optionvalue="lt">is less than</option>
20+
<optionvalue="lte">is less than or equal to</option>
21+
<optionvalue="like">contains</option>
22+
<optionvalue="starts">starts with</option>
23+
<optionvalue="ends">ends with</option>
2424
</select>
2525
</div>
2626
<div class="col-sm-3">

‎templates/adj-search-block.html‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<div class="cand-event-group">
2+
{% for e in search_events %}
3+
<div class="event-desc" id="cand-event_{{ e.event_id }}">
4+
<div class="row">
5+
<div class="col-sm-6">
6+
<b>start_date:</b> {{e.start_date}}</br>
7+
<b>location:</b> {{e.location | safe }}<br/>
8+
<b>title:</b> {{e.title | safe }}<br/>
9+
</div>
10+
<div class="col-sm-3">
11+
<b>event_id:</b> {{ e.event_id }}<br/>
12+
<b>article_id:</b>
13+
<a href="{{ url_for('eventCreator', aid = e.article_id) }}"
14+
target="_blank"
15+
title="{{ e.publication }} ({{ e.pub_date }}) --- {{ e.article_desc|safe }}">{{e.article_id}}</a><br/>
16+
<b>coder:</b> {{ e.coder_id }} <br/>
17+
</div>
18+
<div class="col-sm-3">
19+
{% if e.event_id in cand_events.keys() %}
20+
<b class="text-muted">In the expanded view</b> <br/>
21+
{% else %}
22+
<b><a href="#">Add to Expand <span class="glyphicon glyphicon-plus"></span></a></b><br/>
23+
{% endif %}
24+
{% if e.event_id in flags %}
25+
{% if flags[e.event_id] == 'for-review' %}
26+
<b class="text-danger">Flagged</b>
27+
{% elif flags[e.event_id] == 'completed' %}
28+
<b class="text-success">Completed</b>
29+
{% endif %}
30+
{% endif %}
31+
</div>
32+
</div>
33+
<div class="row">
34+
<div class="col-sm-12">
35+
<b>desc:</b> {{ e.desc | safe }}<br/>
36+
</div>
37+
</div>
38+
</div>
39+
{% endfor %}
40+
</div>
41+
<nav aria-label="cand-event-pagination">
42+
<ul class="pagination">
43+
<li class="page-item">
44+
<a class="page-link" href="#" aria-label="Previous">
45+
<span aria-hidden="true">&laquo;</span>
46+
<span class="sr-only">Previous</span>
47+
</a>
48+
</li>
49+
<li class="page-item"><a class="page-link" href="#">1</a></li>
50+
<li class="page-item"><a class="page-link" href="#">2</a></li>
51+
<li class="page-item"><a class="page-link" href="#">3</a></li>
52+
<li class="page-item">
53+
<a class="page-link" href="#" aria-label="Next">
54+
<span aria-hidden="true">&raquo;</span>
55+
<span class="sr-only">Next</span>
56+
</a>
57+
</li>
58+
</ul>
59+
</nav>

‎templates/adj-search.html‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<div class="row form-row">
22
<div class="col-sm-11">
33
<input class="form-control"
4-
name="search_value"
4+
name="adj-search-input"
55
id="adj-search-input"
66
type="text"
7-
placeholder = "Value..."/>
7+
placeholder = "Example: Mizzou OR Missouri, Quebec AND students"/>
88
</div>
9-
<div class="col-sm-1">
9+
<!-- <div >
1010
<a id="adj-search-button" class="btn btm-primary glyphicon glyphicon-{{ 'minus' if is_addition else 'plus' }}"></a>
11-
</div>
11+
</div> -->
1212
</div>

‎templates/adj-sort.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
<select class="form-control"
1414
name="adj-sort-order"
1515
id="adj-sort-order">
16-
<option>ascending</option>
17-
<option>descending</option>
16+
<optionvalue="asc">ascending</option>
17+
<optionvalue="desc">descending</option>
1818
</select>
1919
</div>
2020
<div class="col-sm-1">

‎templates/adj.html‎

Lines changed: 4 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -60,76 +60,20 @@ <h5>Sort</h5>
6060
{% include 'adj-sort.html' %}
6161
</form>
6262
</div>
63+
<hr/>
64+
<button id="adj-search-button" class="btn btn-primary">Search</button>
6365
</div>
6466
<div class="tab-pane" id="cand_block">
6567
<ul class="nav nav-pills nav-justified" id="adj-subtabselecter">
6668
<li class="subtablinks active nav-item" id="cand-search_button">
67-
<a href="#">Search</a>
69+
<a href="#"id="cand-search-text">Search</a>
6870
</li>
6971
<li class="subtablinks nav-item" id="cand-recent_button">
7072
<a href="#">Recent</a>
7173
</li>
7274
</ul>
7375
<div class="subtab-pane" id="cand-search_block">
74-
<div class="cand-event-group">
75-
{% for e in search_events %}
76-
<div class="event-desc" id="cand-event_{{ e.event_id }}">
77-
<div class="row">
78-
<div class="col-sm-6">
79-
<b>start_date:</b> {{e.start_date}}</br>
80-
<b>location:</b> {{e.location | safe }}<br/>
81-
<b>title:</b> {{e.title | safe }}<br/>
82-
</div>
83-
<div class="col-sm-3">
84-
<b>event_id:</b> {{ e.event_id }}<br/>
85-
<b>article_id:</b>
86-
<a href="{{ url_for('eventCreator', aid = e.article_id) }}"
87-
target="_blank"
88-
title="{{ e.publication }} ({{ e.pub_date }}) --- {{ e.article_desc|safe }}">{{e.article_id}}</a><br/>
89-
<b>coder:</b> {{ e.coder_id }} <br/>
90-
</div>
91-
<div class="col-sm-3">
92-
{% if e.event_id in cand_events.keys() %}
93-
<b class="text-muted">In the expanded view</b> <br/>
94-
{% else %}
95-
<b><a href="#">Add to Expand <span class="glyphicon glyphicon-plus"></span></a></b><br/>
96-
{% endif %}
97-
{% if e.event_id in flags %}
98-
{% if flags[e.event_id] == 'for-review' %}
99-
<b class="text-danger">Flagged</b>
100-
{% elif flags[e.event_id] == 'completed' %}
101-
<b class="text-success">Completed</b>
102-
{% endif %}
103-
{% endif %}
104-
</div>
105-
</div>
106-
<div class="row">
107-
<div class="col-sm-12">
108-
<b>desc:</b> {{ e.desc | safe }}<br/>
109-
</div>
110-
</div>
111-
</div>
112-
{% endfor %}
113-
</div>
114-
<nav aria-label="cand-event-pagination">
115-
<ul class="pagination">
116-
<li class="page-item">
117-
<a class="page-link" href="#" aria-label="Previous">
118-
<span aria-hidden="true">&laquo;</span>
119-
<span class="sr-only">Previous</span>
120-
</a>
121-
</li>
122-
<li class="page-item"><a class="page-link" href="#">1</a></li>
123-
<li class="page-item"><a class="page-link" href="#">2</a></li>
124-
<li class="page-item"><a class="page-link" href="#">3</a></li>
125-
<li class="page-item">
126-
<a class="page-link" href="#" aria-label="Next">
127-
<span aria-hidden="true">&raquo;</span>
128-
<span class="sr-only">Next</span>
129-
</a>
130-
</li>
131-
</ul>
132-
</nav>
76+
{% include 'adj-search-block.html' %}
13377
</div>
13478
<div class="subtab-pane" id="cand-recent_block" style="display:none;">
13579
<div class="cand-event-group">

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /