Skip to content

Commit

Permalink
Merge pull request #269 from ael-code/pagination
Browse files Browse the repository at this point in the history
Pagination
  • Loading branch information
boyska committed Mar 16, 2016
2 parents 70bb7cc + 770ba4c commit 2ca45e1
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 30 deletions.
3 changes: 2 additions & 1 deletion conf/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
'PRESET_PATHS': ([], "list of paths where to look for presets definition"),
'AGHERANT_DESCRIPTIONS': (None, "list of description urls of nodes to aggregate"),
'BOOTSTRAP_SERVE_LOCAL': (True, "decide to serve bootstrap related files as local content"),
'MAX_RESULTS_PER_PAGE': (50, "number of max results for one request"),
'RESULTS_PER_PAGE': (30, "number of results displayed per page"),
'MAX_RESULTS_PER_PAGE': (100, "maximum number of results that can be delivered to one request"),
'USERS_DATABASE': (None, "url of the database used for users managment"),
'PWD_SALT_SIZE': (16, "size of the salt used by password hashing algorithm"),
'PWD_ROUNDS': (pbkdf2_sha256.default_rounds, "number of rounds runs by password hashing algorithm")
Expand Down
2 changes: 1 addition & 1 deletion webant/api/archivant_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def get_volumes():
size = int(request.args.get('size', 10))
except ValueError:
raise ApiError("Bad Request", 400, details="could not covert 'size' parameter to number")
if size > current_app.config.get('MAX_RESULTS_PER_PAGE', 50):
if size > current_app.config['MAX_RESULTS_PER_PAGE']:
raise ApiError("Request Entity Too Large", 413, details="'size' parameter is too high")

q_res = current_app.archivant._db.get_books_querystring(query=q, from_=from_, size=size)
Expand Down
7 changes: 6 additions & 1 deletion webant/static/item_list.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@
.meta-list .glyphicon{
margin-right: 4px;
}
#item-list .item-div:first-of-type{
#item-list > a:nth-child(1) > .item-div:nth-child(1) {
border-top: 1px solid #EEE;
}

#item-list > a, #item-list > a:hover {
color: #232323;
text-decoration: none;
}

#item-list .item-div{
border-bottom: 1px solid #EEE;
margin: 0px;
Expand Down
3 changes: 0 additions & 3 deletions webant/static/js/ui-main.js

This file was deleted.

27 changes: 27 additions & 0 deletions webant/templates/pagination.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% macro pagination(prev, first, current, last, next, target_url) %}
<nav>
<ul class="pagination">
{% if prev %}
<li>
<a rel="prev" href="{{ target_url | format(prev) }}" aria-label="Previous page">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}
{% for i in range(first, last+1) %}
{% if i == current %}
<li class="active"><a>{{i}}</a></li>
{% else %}
<li><a href="{{ target_url | format(i) }}">{{i}}</a></li>
{% endif %}
{% endfor %}
{% if next %}
<li>
<a rel="next" href="{{ target_url | format(next) }}" aria-label="Next page">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endmacro %}
13 changes: 6 additions & 7 deletions webant/templates/recents.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,19 @@ <h1>{%trans%}Recently added items{%endtrans%}</h1>

<div id="item-list">
{% for b in items %}
<div class="item-div row dyn-href" href="{{url_for('view_volume', volumeID=b['_id'])}}">
<a href="{{url_for('view_volume', volumeID=b['_id'])}}">
<div class="item-div row">
<div class="item-thumbnail hidden-xs col-sm-1 vcenter">
<a href="{{url_for('view_volume', volumeID=b['_id'])}}">
<span class="glyphicon glyphicon-book"></span>
</a>
<span class="glyphicon glyphicon-book"></span>
</div>
<div class="item-main col-xs-12 col-sm-7 vcenter">
<a class="item-title" href="{{url_for('view_volume', volumeID=b['_id'])}}"
<p class="item-title"
{% if 'title' in b['_source'] %}
title="{{ b['_source']['title'] }}"> {{ b['_source']['title'] }}
{% else %}
title="{{ b['_id'] }}"> {{ b['_id'] }}
{% endif %}
</a>
</p>
</div>
<div class="item-sub col-xs-12 col-sm-3 vcenter">
<ul class="meta-list list-unstyled">
Expand All @@ -77,6 +76,7 @@ <h1>{%trans%}Recently added items{%endtrans%}</h1>
</ul>
</div>
</div>
</a>
{% endfor %}
</div>

Expand All @@ -92,5 +92,4 @@ <h1>{%trans%}Recently added items{%endtrans%}</h1>
$(this).text(date.toLocaleString());
});
</script>
<script src="{{ url_for('static', filename='js/ui-main.js') }}"></script>
{% endblock scripts %}
37 changes: 23 additions & 14 deletions webant/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@

{% block content %}
<div class="container">

<div class="search-bar">
{{ searchbar.searchbar(search_query=query) }}
</div>

<div class='search-info'>
{% trans num = books|length%}{{num}} result was found for{%pluralize%}{{num}} results were found for{% endtrans %} <strong>{{ query }}</strong>
{% trans num = total%}{{num}} result was found for{%pluralize%}{{num}} results were found for{% endtrans %} <strong>{{ query }}</strong>
</div>

{% if not books %}
Expand All @@ -50,20 +50,19 @@

<div id="item-list">
{% for b in books %}
<div class="item-div row dyn-href" href="{{url_for('view_volume', volumeID=b['_id'])}}">
<a href="{{url_for('view_volume', volumeID=b['_id'])}}">
<div class="item-div row">
<div class="item-thumbnail hidden-xs col-sm-1 vcenter">
<a href="{{url_for('view_volume', volumeID=b['_id'])}}">
<span class="glyphicon glyphicon-book"></span>
</a>
<span class="glyphicon glyphicon-book"></span>
</div>
<div class="item-main col-xs-12 col-sm-7 vcenter">
<a class="item-title" href="{{url_for('view_volume', volumeID=b['_id'])}}"
<p class="item-title"
{% if 'title' in b %}
title="{{ b['title'] }}"> {{ b['title'] }}
{% else %}
title="{{ b['_id'] }}"> {{ b['_id'] }}
{% endif %}
</a>
</p>
</div>
<div class="item-sub col-xs-12 col-sm-3 vcenter">
<ul class="meta-list list-unstyled">
Expand All @@ -77,14 +76,24 @@
</ul>
</div>
</div>
</a>
{% endfor %}
</div>


{% if pagination %}
{% set search_url = ("%s?q=%s&size=%d&page=" | format(url_for('search'), query, size))+"%d" %}
{% import 'pagination.html' as pag %}
<div class='text-center'>
{{ pag.pagination(pagination['prev'],
pagination['first'],
pagination['current'],
pagination['last'],
pagination['next'],
target_url = search_url) }}
</div>
{% endif %}

{% endif %}
</div>
{% endblock content %}

{% block scripts %}
{{super()}}
<script src="{{ url_for('static', filename='js/ui-main.js') }}"></script>
{% endblock scripts %}
32 changes: 32 additions & 0 deletions webant/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,38 @@ def add_routes(fapp, routes, prefix=""):
fapp.add_url_rule(**r)


def get_centered_pagination(current, total, visible=5):
''' Return the range of pages to render in a pagination menu.
The current page is always kept in the middle except
for the edge cases.
Reeturns a dict
{ prev, first, current, last, next }
:param current: the current page
:param total: total number of pages available
:param visible: number of pages visible
'''
inc = visible/2
first = current - inc
last = current + inc
if (total <= visible):
first = 1
last = total
elif (last > total):
first = total - (visible-1)
last = total
elif (first < 1):
first = 1
last = visible
return dict(prev = current-1 if(current > 1) else None,
first=first,
current = current,
last=last,
next = current+1 if(current < total) else None)


class AuthtFromSession(Authenticator):

USERID_KEY = 'user_id'
Expand Down
37 changes: 34 additions & 3 deletions webant/webant.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ def __init__(self, import_name, conf={}):
defaults = {
'BOOTSTRAP_SERVE_LOCAL': True,
'AGHERANT_DESCRIPTIONS': [],
'API_URL': "/api/v1"
'API_URL': '/api/v1',
'RESULTS_PER_PAGE': 30,
'MAX_RESULTS_PER_PAGE': 100
}
defaults.update(conf)
super(LibreantViewApp, self).__init__(import_name, defaults)
Expand Down Expand Up @@ -98,7 +100,31 @@ def search():
query = request.args.get('q', None)
if query is None:
return renderErrorPage(message='No query given', httpCode=400)
res = app.archivant._db.user_search(query)['hits']['hits']

try:
page = int(request.args.get('page', 1))
except ValueError:
return renderErrorPage(message='Invalid page number', httpCode=400)
if(page < 1):
return renderErrorPage(message='Invalid page number', httpCode=400)

try:
size = int(request.args.get('size', app.config['RESULTS_PER_PAGE']))
except ValueError:
return renderErrorPage(message='Invalid size number', httpCode=400)
if(size < 1 or size > app.config['MAX_RESULTS_PER_PAGE']):
return renderErrorPage(message='Invalid size number', httpCode=400)

from_ = (page-1)*size
res = app.archivant._db.get_books_querystring(query, from_=from_, size=size)
totalRes = res['hits']['total']
totalPages = (totalRes == 0) + totalRes/size + (totalRes % size > 0)
if(page > totalPages):
return renderErrorPage(message='Page number too high, maximum is {}'.format(totalPages), httpCode=400)
pagination=util.get_centered_pagination(current=page, total=totalPages)
if pagination['first'] == pagination['last']:
pagination = None
res = res['hits']['hits']
books = []
for b in res:
src = b['_source']
Expand All @@ -109,7 +135,12 @@ def search():
['text/html',
'text/xml', 'application/rss+xml', 'opensearch'])
if (not format) or (format is 'text/html'):
return render_template('search.html', books=books, query=query)
return render_template('search.html',
books=books,
query=query,
total=totalRes,
pagination=pagination,
size=size)
elif format in ['opensearch', 'text/xml', 'application/rss+xml']:
return Response(render_template('opens.xml',
books=books, query=query),
Expand Down

0 comments on commit 2ca45e1

Please sign in to comment.