diff --git a/conf/defaults.py b/conf/defaults.py index 7ea0251..9701549 100644 --- a/conf/defaults.py +++ b/conf/defaults.py @@ -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") diff --git a/webant/api/archivant_api.py b/webant/api/archivant_api.py index 66b6dd6..82b8d88 100644 --- a/webant/api/archivant_api.py +++ b/webant/api/archivant_api.py @@ -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) diff --git a/webant/static/item_list.css b/webant/static/item_list.css index 5ac230c..fa2bae9 100644 --- a/webant/static/item_list.css +++ b/webant/static/item_list.css @@ -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; diff --git a/webant/static/js/ui-main.js b/webant/static/js/ui-main.js deleted file mode 100644 index e64bfd9..0000000 --- a/webant/static/js/ui-main.js +++ /dev/null @@ -1,3 +0,0 @@ -$( ".dyn-href" ).click(function() { - window.location.href = $(this).attr('href'); -}); diff --git a/webant/templates/pagination.html b/webant/templates/pagination.html new file mode 100644 index 0000000..184c27c --- /dev/null +++ b/webant/templates/pagination.html @@ -0,0 +1,27 @@ +{% macro pagination(prev, first, current, last, next, target_url) %} + +{% endmacro %} diff --git a/webant/templates/recents.html b/webant/templates/recents.html index c47e7e0..34b7712 100644 --- a/webant/templates/recents.html +++ b/webant/templates/recents.html @@ -45,20 +45,19 @@

{%trans%}Recently added items{%endtrans%}

{% for b in items %} -
+ + + {% endfor %}
@@ -92,5 +92,4 @@

{%trans%}Recently added items{%endtrans%}

$(this).text(date.toLocaleString()); }); - {% endblock scripts %} diff --git a/webant/templates/search.html b/webant/templates/search.html index dd4109f..ee9ed5a 100644 --- a/webant/templates/search.html +++ b/webant/templates/search.html @@ -28,13 +28,13 @@ {% block content %}
- + - +
- {% trans num = books|length%}{{num}} result was found for{%pluralize%}{{num}} results were found for{% endtrans %} {{ query }} + {% trans num = total%}{{num}} result was found for{%pluralize%}{{num}} results were found for{% endtrans %} {{ query }}
{% if not books %} @@ -50,20 +50,19 @@
{% for b in books %} - + + {% if pagination %} + {% set search_url = ("%s?q=%s&size=%d&page=" | format(url_for('search'), query, size))+"%d" %} + {% import 'pagination.html' as pag %} +
+ {{ pag.pagination(pagination['prev'], + pagination['first'], + pagination['current'], + pagination['last'], + pagination['next'], + target_url = search_url) }} +
+ {% endif %} + {% endif %}
{% endblock content %} - -{% block scripts %} - {{super()}} - -{% endblock scripts %} diff --git a/webant/util.py b/webant/util.py index 574e605..bd33d41 100644 --- a/webant/util.py +++ b/webant/util.py @@ -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' diff --git a/webant/webant.py b/webant/webant.py index cbbfdc6..d25be45 100644 --- a/webant/webant.py +++ b/webant/webant.py @@ -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) @@ -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'] @@ -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),