Merge branch 'master' of https://github.com/janeczku/calibre-web
This commit is contained in:
commit
d856c4d78e
|
@ -16,14 +16,14 @@ To receive fixes for security vulnerabilities it is required to always upgrade t
|
||||||
| V 0.6.7 |Hardcoded secret key for sessions |CVE-2020-12627 |
|
| V 0.6.7 |Hardcoded secret key for sessions |CVE-2020-12627 |
|
||||||
| V 0.6.13|Calibre-Web Metadata cross site scripting |CVE-2021-25964|
|
| V 0.6.13|Calibre-Web Metadata cross site scripting |CVE-2021-25964|
|
||||||
| V 0.6.13|Name of Shelves are only visible to users who can access the corresponding shelf Thanks to @ibarrionuevo||
|
| V 0.6.13|Name of Shelves are only visible to users who can access the corresponding shelf Thanks to @ibarrionuevo||
|
||||||
| V 0.6.13|JavaScript could get executed in the description field. Thanks to @ranjit-git ||
|
| V 0.6.13|JavaScript could get executed in the description field. Thanks to @ranjit-git and Hagai Wechsler (WhiteSource)||
|
||||||
| V 0.6.13|JavaScript could get executed in a custom column of type "comment" field ||
|
| V 0.6.13|JavaScript could get executed in a custom column of type "comment" field ||
|
||||||
| V 0.6.13|JavaScript could get executed after converting a book to another format with a title containing javascript code||
|
| V 0.6.13|JavaScript could get executed after converting a book to another format with a title containing javascript code||
|
||||||
| V 0.6.13|JavaScript could get executed after converting a book to another format with a username containing javascript code||
|
| V 0.6.13|JavaScript could get executed after converting a book to another format with a username containing javascript code||
|
||||||
| V 0.6.13|JavaScript could get executed in the description series, categories or publishers title||
|
| V 0.6.13|JavaScript could get executed in the description series, categories or publishers title||
|
||||||
| V 0.6.13|JavaScript could get executed in the shelf title||
|
| V 0.6.13|JavaScript could get executed in the shelf title||
|
||||||
| V 0.6.13|Login with the old session cookie after logout. Thanks to @ibarrionuevo||
|
| V 0.6.13|Login with the old session cookie after logout. Thanks to @ibarrionuevo||
|
||||||
| V 0.6.14|CSRF was possible. Thanks to @mik317 ||
|
| V 0.6.14|CSRF was possible. Thanks to @mik317 and Hagai Wechsler (WhiteSource) ||
|
||||||
| V 0.6.14|Cross-Site Scripting vulnerability on typeahead inputs. Thanks to @notdodo||
|
| V 0.6.14|Cross-Site Scripting vulnerability on typeahead inputs. Thanks to @notdodo||
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ from flask_principal import Principal
|
||||||
from . import config_sql, logger, cache_buster, cli, ub, db
|
from . import config_sql, logger, cache_buster, cli, ub, db
|
||||||
from .reverseproxy import ReverseProxied
|
from .reverseproxy import ReverseProxied
|
||||||
from .server import WebServer
|
from .server import WebServer
|
||||||
|
from .dep_check import dependency_check
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import lxml
|
import lxml
|
||||||
|
@ -100,6 +101,7 @@ _BABEL_TRANSLATIONS = set()
|
||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
|
||||||
|
|
||||||
from . import services
|
from . import services
|
||||||
|
|
||||||
db.CalibreDB.update_config(config)
|
db.CalibreDB.update_config(config)
|
||||||
|
@ -126,7 +128,11 @@ def create_app():
|
||||||
print('*** "flask-WTF" is needed for calibre-web to run. Please install it using pip: "pip install flask-WTF" ***')
|
print('*** "flask-WTF" is needed for calibre-web to run. Please install it using pip: "pip install flask-WTF" ***')
|
||||||
web_server.stop(True)
|
web_server.stop(True)
|
||||||
sys.exit(7)
|
sys.exit(7)
|
||||||
|
for res in dependency_check() + dependency_check(True):
|
||||||
|
log.info('*** "{}" version does not fit the requirements. Should: {}, Found: {}, please consider updating. ***'
|
||||||
|
.format(res['name'],
|
||||||
|
res['target'],
|
||||||
|
res['found']))
|
||||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||||
|
|
||||||
if os.environ.get('FLASK_DEBUG'):
|
if os.environ.get('FLASK_DEBUG'):
|
||||||
|
|
|
@ -780,7 +780,7 @@ class CalibreDB():
|
||||||
|
|
||||||
# read search results from calibre-database and return it (function is used for feed and simple search
|
# read search results from calibre-database and return it (function is used for feed and simple search
|
||||||
def get_search_results(self, term, offset=None, order=None, limit=None, *join):
|
def get_search_results(self, term, offset=None, order=None, limit=None, *join):
|
||||||
order = order or [Books.sort]
|
order = order[0] or [Books.sort]
|
||||||
pagination = None
|
pagination = None
|
||||||
result = self.search_query(term, *join).order_by(*order).all()
|
result = self.search_query(term, *join).order_by(*order).all()
|
||||||
result_count = len(result)
|
result_count = len(result)
|
||||||
|
|
83
cps/dep_check.py
Normal file
83
cps/dep_check.py
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .constants import BASE_DIR
|
||||||
|
try:
|
||||||
|
from importlib_metadata import version
|
||||||
|
importlib = True
|
||||||
|
ImportNotFound = BaseException
|
||||||
|
except ImportError:
|
||||||
|
importlib = False
|
||||||
|
|
||||||
|
|
||||||
|
if not importlib:
|
||||||
|
try:
|
||||||
|
import pkg_resources
|
||||||
|
from pkg_resources import DistributionNotFound as ImportNotFound
|
||||||
|
pkgresources = True
|
||||||
|
except ImportError as e:
|
||||||
|
pkgresources = False
|
||||||
|
|
||||||
|
def dependency_check(optional=False):
|
||||||
|
dep = list()
|
||||||
|
if importlib or pkgresources:
|
||||||
|
if optional:
|
||||||
|
req_path = os.path.join(BASE_DIR, "optional-requirements.txt")
|
||||||
|
else:
|
||||||
|
req_path = os.path.join(BASE_DIR, "requirements.txt")
|
||||||
|
if os.path.exists(req_path):
|
||||||
|
try:
|
||||||
|
with open(req_path, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if not line.startswith('#') and not line == '\n' and not line.startswith('git'):
|
||||||
|
res = re.match(r'(.*?)([<=>\s]+)([\d\.]+),?\s?([<=>\s]+)?([\d\.]+)?', line.strip())
|
||||||
|
try:
|
||||||
|
if importlib:
|
||||||
|
dep_version = version(res.group(1))
|
||||||
|
else:
|
||||||
|
dep_version = pkg_resources.get_distribution(res.group(1)).version
|
||||||
|
except ImportNotFound:
|
||||||
|
if optional:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
return [{'name':res.group(1),
|
||||||
|
'target': "available",
|
||||||
|
'found': "Not available"
|
||||||
|
}]
|
||||||
|
|
||||||
|
if res.group(2).strip() == "==":
|
||||||
|
if dep_version.split('.') != res.group(3).split('.'):
|
||||||
|
dep.append({'name': res.group(1),
|
||||||
|
'found': dep_version,
|
||||||
|
"target": res.group(2) + res.group(3)})
|
||||||
|
continue
|
||||||
|
elif res.group(2).strip() == ">=":
|
||||||
|
if dep_version.split('.') < res.group(3).split('.'):
|
||||||
|
dep.append({'name': res.group(1),
|
||||||
|
'found': dep_version,
|
||||||
|
"target": res.group(2) + res.group(3)})
|
||||||
|
continue
|
||||||
|
elif res.group(2).strip() == ">":
|
||||||
|
if dep_version.split('.') <= res.group(3).split('.'):
|
||||||
|
dep.append({'name': res.group(1),
|
||||||
|
'found': dep_version,
|
||||||
|
"target": res.group(2) + res.group(3)})
|
||||||
|
continue
|
||||||
|
if res.group(4) and res.group(5):
|
||||||
|
if res.group(4).strip() == "<":
|
||||||
|
if dep_version.split('.') >= res.group(5).split('.'):
|
||||||
|
dep.append(
|
||||||
|
{'name': res.group(1),
|
||||||
|
'found': dep_version,
|
||||||
|
"target": res.group(4) + res.group(5)})
|
||||||
|
continue
|
||||||
|
elif res.group(2).strip() == "<=":
|
||||||
|
if dep_version.split('.') > res.group(5).split('.'):
|
||||||
|
dep.append(
|
||||||
|
{'name': res.group(1),
|
||||||
|
'found': dep_version,
|
||||||
|
"target": res.group(4) + res.group(5)})
|
||||||
|
continue
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return dep
|
|
@ -30,6 +30,9 @@ $("#desc").click(function() {
|
||||||
if (direction === 0) {
|
if (direction === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$("#asc").removeClass("active");
|
||||||
|
$("#desc").addClass("active");
|
||||||
|
|
||||||
var page = $(this).data("id");
|
var page = $(this).data("id");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"post",
|
method:"post",
|
||||||
|
@ -50,6 +53,9 @@ $("#asc").click(function() {
|
||||||
if (direction === 1) {
|
if (direction === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$("#desc").removeClass("active");
|
||||||
|
$("#asc").addClass("active");
|
||||||
|
|
||||||
var page = $(this).data("id");
|
var page = $(this).data("id");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"post",
|
method:"post",
|
||||||
|
@ -66,6 +72,8 @@ $("#asc").click(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#all").click(function() {
|
$("#all").click(function() {
|
||||||
|
$(".char").removeClass("active");
|
||||||
|
$("#all").addClass("active");
|
||||||
// go through all elements and make them visible
|
// go through all elements and make them visible
|
||||||
$list.isotope({ filter: function() {
|
$list.isotope({ filter: function() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -74,6 +82,9 @@ $("#all").click(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".char").click(function() {
|
$(".char").click(function() {
|
||||||
|
$(".char").removeClass("active");
|
||||||
|
$(this).addClass("active");
|
||||||
|
$("#all").removeClass("active");
|
||||||
var character = this.innerText;
|
var character = this.innerText;
|
||||||
$list.isotope({ filter: function() {
|
$list.isotope({ filter: function() {
|
||||||
return this.attributes["data-id"].value.charAt(0).toUpperCase() === character;
|
return this.attributes["data-id"].value.charAt(0).toUpperCase() === character;
|
||||||
|
|
|
@ -19,6 +19,7 @@ var direction = $("#asc").data('order'); // 0=Descending order; 1= ascending or
|
||||||
var sort = 0; // Show sorted entries
|
var sort = 0; // Show sorted entries
|
||||||
|
|
||||||
$("#sort_name").click(function() {
|
$("#sort_name").click(function() {
|
||||||
|
$("#sort_name").toggleClass("active");
|
||||||
var className = $("h1").attr("Class") + "_sort_name";
|
var className = $("h1").attr("Class") + "_sort_name";
|
||||||
var obj = {};
|
var obj = {};
|
||||||
obj[className] = sort;
|
obj[className] = sort;
|
||||||
|
@ -68,6 +69,9 @@ $("#desc").click(function() {
|
||||||
if (direction === 0) {
|
if (direction === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$("#asc").removeClass("active");
|
||||||
|
$("#desc").addClass("active");
|
||||||
|
|
||||||
var page = $(this).data("id");
|
var page = $(this).data("id");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"post",
|
method:"post",
|
||||||
|
@ -112,10 +116,12 @@ $("#desc").click(function() {
|
||||||
|
|
||||||
|
|
||||||
$("#asc").click(function() {
|
$("#asc").click(function() {
|
||||||
|
|
||||||
if (direction === 1) {
|
if (direction === 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$("#desc").removeClass("active");
|
||||||
|
$("#asc").addClass("active");
|
||||||
|
|
||||||
var page = $(this).data("id");
|
var page = $(this).data("id");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"post",
|
method:"post",
|
||||||
|
@ -159,6 +165,8 @@ $("#asc").click(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#all").click(function() {
|
$("#all").click(function() {
|
||||||
|
$("#all").addClass("active");
|
||||||
|
$(".char").removeClass("active");
|
||||||
var cnt = $("#second").contents();
|
var cnt = $("#second").contents();
|
||||||
$("#list").append(cnt);
|
$("#list").append(cnt);
|
||||||
// Find count of middle element
|
// Find count of middle element
|
||||||
|
@ -176,6 +184,9 @@ $("#all").click(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".char").click(function() {
|
$(".char").click(function() {
|
||||||
|
$(".char").removeClass("active");
|
||||||
|
$(this).addClass("active");
|
||||||
|
$("#all").removeClass("active");
|
||||||
var character = this.innerText;
|
var character = this.innerText;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
|
@ -28,14 +28,17 @@ $(function () {
|
||||||
|
|
||||||
function populateForm (book) {
|
function populateForm (book) {
|
||||||
tinymce.get("description").setContent(book.description);
|
tinymce.get("description").setContent(book.description);
|
||||||
var uniqueTags = [];
|
var uniqueTags = $.map($("#tags").val().split(","), $.trim);
|
||||||
|
if ( uniqueTags.length == 1 && uniqueTags[0] == "") {
|
||||||
|
uniqueTags = [];
|
||||||
|
}
|
||||||
$.each(book.tags, function(i, el) {
|
$.each(book.tags, function(i, el) {
|
||||||
if ($.inArray(el, uniqueTags) === -1) uniqueTags.push(el);
|
if ($.inArray(el, uniqueTags) === -1) uniqueTags.push(el);
|
||||||
});
|
});
|
||||||
var ampSeparatedAuthors = (book.authors || []).join(" & ");
|
var ampSeparatedAuthors = (book.authors || []).join(" & ");
|
||||||
$("#bookAuthor").val(ampSeparatedAuthors);
|
$("#bookAuthor").val(ampSeparatedAuthors);
|
||||||
$("#book_title").val(book.title);
|
$("#book_title").val(book.title);
|
||||||
$("#tags").val(uniqueTags.join(","));
|
$("#tags").val(uniqueTags.join(", "));
|
||||||
$("#rating").data("rating").setValue(Math.round(book.rating));
|
$("#rating").data("rating").setValue(Math.round(book.rating));
|
||||||
if(book.cover !== null){
|
if(book.cover !== null){
|
||||||
$(".cover img").attr("src", book.cover);
|
$(".cover img").attr("src", book.cover);
|
||||||
|
|
|
@ -151,6 +151,7 @@ class TaskConvert(CalibreTask):
|
||||||
local_db.session.rollback()
|
local_db.session.rollback()
|
||||||
log.error("Database error: %s", e)
|
log.error("Database error: %s", e)
|
||||||
local_db.session.close()
|
local_db.session.close()
|
||||||
|
self._handleError(error_message)
|
||||||
return
|
return
|
||||||
self.results['path'] = cur_book.path
|
self.results['path'] = cur_book.path
|
||||||
self.title = cur_book.title
|
self.title = cur_book.title
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
<th>{{_('Downloads')}}</th>
|
<th>{{_('Downloads')}}</th>
|
||||||
<th class="hidden-xs ">{{_('Admin')}}</th>
|
<th class="hidden-xs ">{{_('Admin')}}</th>
|
||||||
<th class="hidden-xs hidden-sm">{{_('Password')}}</th>
|
<th class="hidden-xs hidden-sm">{{_('Password')}}</th>
|
||||||
|
{% if config.config_upload %}
|
||||||
<th class="hidden-xs hidden-sm">{{_('Upload')}}</th>
|
<th class="hidden-xs hidden-sm">{{_('Upload')}}</th>
|
||||||
|
{% endif %}
|
||||||
<th class="hidden-xs hidden-sm">{{_('Download')}}</th>
|
<th class="hidden-xs hidden-sm">{{_('Download')}}</th>
|
||||||
<th class="hidden-xs hidden-sm hidden-md">{{_('View Books')}}</th>
|
<th class="hidden-xs hidden-sm hidden-md">{{_('View Books')}}</th>
|
||||||
<th class="hidden-xs hidden-sm hidden-md">{{_('Edit')}}</th>
|
<th class="hidden-xs hidden-sm hidden-md">{{_('Edit')}}</th>
|
||||||
|
@ -32,7 +34,9 @@
|
||||||
<td>{{user.downloads.count()}}</td>
|
<td>{{user.downloads.count()}}</td>
|
||||||
<td class="hidden-xs">{{ display_bool_setting(user.role_admin()) }}</td>
|
<td class="hidden-xs">{{ display_bool_setting(user.role_admin()) }}</td>
|
||||||
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_passwd()) }}</td>
|
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_passwd()) }}</td>
|
||||||
|
{% if config.config_upload %}
|
||||||
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_upload()) }}</td>
|
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_upload()) }}</td>
|
||||||
|
{% endif %}
|
||||||
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_download()) }}</td>
|
<td class="hidden-xs hidden-sm">{{ display_bool_setting(user.role_download()) }}</td>
|
||||||
<td class="hidden-xs hidden-sm hidden-md">{{ display_bool_setting(user.role_viewer()) }}</td>
|
<td class="hidden-xs hidden-sm hidden-md">{{ display_bool_setting(user.role_viewer()) }}</td>
|
||||||
<td class="hidden-xs hidden-sm hidden-md">{{ display_bool_setting(user.role_edit()) }}</td>
|
<td class="hidden-xs hidden-sm hidden-md">{{ display_bool_setting(user.role_edit()) }}</td>
|
||||||
|
|
|
@ -23,12 +23,12 @@
|
||||||
<h3>{{_("In Library")}}</h3>
|
<h3>{{_("In Library")}}</h3>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="filterheader hidden-xs">
|
<div class="filterheader hidden-xs">
|
||||||
<a id="new" data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='new')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a id="new" data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" class="btn btn-primary{% if order == "new" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='new')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a id="old" data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='old')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a id="old" data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" class="btn btn-primary{% if order == "old" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='old')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
<a id="asc" data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a id="asc" data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" class="btn btn-primary{% if order == "abc" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
<a id="desc" data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
<a id="desc" data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" class="btn btn-primary{% if order == "zyx" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
<a id="pub_new" data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubnew')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a id="pub_new" data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" class="btn btn-primary{% if order == "pubnew" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubnew')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary{% if order == "pubold" %} active{% endif%}" href="{{url_for('web.books_list', data='author', book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% if entries[0] %}
|
{% if entries[0] %}
|
||||||
|
|
|
@ -95,17 +95,21 @@
|
||||||
<input type="checkbox" name="viewer_role" id="viewer_role" {% if conf.role_viewer() %}checked{% endif %}>
|
<input type="checkbox" name="viewer_role" id="viewer_role" {% if conf.role_viewer() %}checked{% endif %}>
|
||||||
<label for="viewer_role">{{_('Allow eBook Viewer')}}</label>
|
<label for="viewer_role">{{_('Allow eBook Viewer')}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% if config.config_upload %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="upload_role" id="upload_role" {% if conf.role_upload() %}checked{% endif %}>
|
<input type="checkbox" name="upload_role" id="upload_role" {% if conf.role_upload() %}checked{% endif %}>
|
||||||
<label for="upload_role">{{_('Allow Uploads')}}</label>
|
<label for="upload_role">{{_('Allow Uploads')}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="edit_role" id="edit_role" {% if conf.role_edit() %}checked{% endif %}>
|
<input type="checkbox" name="edit_role" data-control="edit_settings" id="edit_role" {% if conf.role_edit() %}checked{% endif %}>
|
||||||
<label for="edit_role">{{_('Allow Edit')}}</label>
|
<label for="edit_role">{{_('Allow Edit')}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div data-related="edit_settings">
|
||||||
<input type="checkbox" name="delete_role" id="delete_role" {% if conf.role_delete_books() %}checked{% endif %}>
|
<div class="form-group">
|
||||||
<label for="delete_role">{{_('Allow Delete Books')}}</label>
|
<input type="checkbox" name="delete_role" id="delete_role" {% if conf.role_delete_books() %}checked{% endif %}>
|
||||||
|
<label for="delete_role">{{_('Allow Delete Books')}}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="passwd_role" id="passwd_role" {% if conf.role_passwd() %}checked{% endif %}>
|
<input type="checkbox" name="passwd_role" id="passwd_role" {% if conf.role_passwd() %}checked{% endif %}>
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
|
|
||||||
<div class="filterheader hidden-xs">
|
<div class="filterheader hidden-xs">
|
||||||
{% if entries.__len__() and data == 'author' %}
|
{% if entries.__len__() and data == 'author' %}
|
||||||
<button id="sort_name" class="btn btn-primary"><b>B,A <-> A B</b></button>
|
<div id="sort_name" class="btn btn-primary"><b>B,A <-> A B</b></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
<button id="asc" data-id="series" data-order="{{ order }}" class="btn btn-primary"><span class="glyphicon glyphicon-sort-by-alphabet"></span></button>
|
<div id="asc" data-id="series" data-order="{{ order }}" class="btn btn-primary{% if order == 1 %} active{% endif%}"><span class="glyphicon glyphicon-sort-by-alphabet"></span></div>
|
||||||
<button id="desc" data-id="series" class="btn btn-primary"><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></button>
|
<div id="desc" data-id="series" class="btn btn-primary{% if order == 0 %} active{% endif%}"><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></div>
|
||||||
{% if charlist|length %}
|
{% if charlist|length %}
|
||||||
<button id="all" class="btn btn-primary {% if charlist|length > 9 %}hidden-sm{% endif %}">{{_('All')}}</button>
|
<div id="all" class="active btn btn-primary {% if charlist|length > 9 %}hidden-sm{% endif %}">{{_('All')}}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="btn-group character {% if charlist|length > 9 %}hidden-sm{% endif %}" role="group">
|
<div class="btn-group character {% if charlist|length > 9 %}hidden-sm{% endif %}" role="group">
|
||||||
{% for char in charlist%}
|
{% for char in charlist%}
|
||||||
<button class="btn btn-primary char">{{char.char}}</button>
|
<div class="btn btn-primary char">{{char.char}}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<button class="update-view btn btn-primary" data-target="series_view" id="list-button" data-view="list">List</button>
|
<div class="update-view btn btn-primary" data-target="series_view" id="list-button" data-view="list">List</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if entries[0] %}
|
{% if entries[0] %}
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].series[0].id )}}">
|
<a href="{{url_for('web.books_list', data=data, sort_param='stored', book_id=entry[0].series[0].id )}}">
|
||||||
<span class="img" title="{{entry[0].series[0].name}}">
|
<span class="img" title="{{entry[0].series[0].name}}">
|
||||||
<img src="{{ url_for('web.get_cover', book_id=entry[0].id) }}" alt="{{ entry[0].name }}"/>
|
<img src="{{ url_for('web.get_cover', book_id=entry[3]) }}" alt="{{ entry[0].series[0].name }}"/>
|
||||||
<span class="badge">{{entry.count}}</span>
|
<span class="badge">{{entry.count}}</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -65,18 +65,23 @@
|
||||||
<div class="discover load-more">
|
<div class="discover load-more">
|
||||||
<h2 class="{{title}}">{{title}}</h2>
|
<h2 class="{{title}}">{{title}}</h2>
|
||||||
<div class="filterheader hidden-xs">
|
<div class="filterheader hidden-xs">
|
||||||
<a data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" id="new" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='new')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
{% if page == 'hot' %}
|
||||||
<a data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" id="old" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='old')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort ascending according to download count')}}" id="hot_asc" class="btn btn-primary{% if order == "hotasc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='hotasc')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" id="asc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort descending according to download count')}}" id="hot_desc" class="btn btn-primary{% if order == "hotdesc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='hotdesc')}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" id="desc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
{% else %}
|
||||||
<a data-toggle="tooltip" title="{{_('Sort authors in alphabetical order')}}" id="auth_az" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='authaz')}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" id="new" class="btn btn-primary{% if order == "new" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='new')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort authors in reverse alphabetical order')}}" id="auth_za" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='authza')}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" id="old" class="btn btn-primary{% if order == "old" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='old')}}"><span class="glyphicon glyphicon-book"></span> <span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" id="pub_new" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='pubnew')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" id="asc" class="btn btn-primary{% if order == "abc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='abc')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" id="pub_old" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" id="desc" class="btn btn-primary{% if order == "zyx" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='zyx')}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
|
<a data-toggle="tooltip" title="{{_('Sort authors in alphabetical order')}}" id="auth_az" class="btn btn-primary{% if order == "authaz" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='authaz')}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
|
<a data-toggle="tooltip" title="{{_('Sort authors in reverse alphabetical order')}}" id="auth_za" class="btn btn-primary{% if order == "authza" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='authza')}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
|
<a data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" id="pub_new" class="btn btn-primary{% if order == "pubnew" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='pubnew')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
|
<a data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" id="pub_old" class="btn btn-primary{% if order == "pubold" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='pubold')}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
{% if page == 'series' %}
|
{% if page == 'series' %}
|
||||||
<a data-toggle="tooltip" title="{{_('Sort ascending according to series index')}}" id="series_asc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='seriesasc')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort ascending according to series index')}}" id="series_asc" class="btn btn-primary{% if order == "seriesasc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='seriesasc')}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a data-toggle="tooltip" title="{{_('Sort descending according to series index')}}" id="series_desc" class="btn btn-primary" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='seriesdesc')}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a data-toggle="tooltip" title="{{_('Sort descending according to series index')}}" id="series_desc" class="btn btn-primary{% if order == "seriesdesc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, book_id=id, sort_param='seriesdesc')}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
|
|
|
@ -5,16 +5,16 @@
|
||||||
<div class="filterheader hidden-xs">
|
<div class="filterheader hidden-xs">
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
{% if entries.__len__() and data == 'author' %}
|
{% if entries.__len__() and data == 'author' %}
|
||||||
<button id="sort_name" class="btn btn-primary"><b>B,A <-> A B</b></button>
|
<div id="sort_name" class="btn btn-primary"><b>B,A <-> A B</b></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button id="asc" data-order="{{ order }}" data-id="{{ data }}" class="btn btn-primary"><span class="glyphicon glyphicon-sort-by-alphabet"></span></button>
|
<div id="asc" data-order="{{ order }}" data-id="{{ data }}" class="btn btn-primary {% if order == 1 %} active{% endif%}"><span class="glyphicon glyphicon-sort-by-alphabet"></span></div>
|
||||||
<button id="desc" data-id="{{ data }}" class="btn btn-primary"><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></button>
|
<div id="desc" data-id="{{ data }}" class="btn btn-primary{% if order == 0 %} active{% endif%}"><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></div>
|
||||||
{% if charlist|length %}
|
{% if charlist|length %}
|
||||||
<button id="all" class="btn btn-primary {% if charlist|length > 9 %}hidden-sm{% endif %}">{{_('All')}}</button>
|
<div id="all" class="active btn btn-primary {% if charlist|length > 9 %}hidden-sm{% endif %}">{{_('All')}}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="btn-group character {% if charlist|length > 9 %}hidden-sm{% endif %}" role="group">
|
<div class="btn-group character {% if charlist|length > 9 %}hidden-sm{% endif %}" role="group">
|
||||||
{% for char in charlist%}
|
{% for char in charlist%}
|
||||||
<button class="btn btn-primary char">{{char.char}}</button>
|
<div class="btn btn-primary char">{{char.char}}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -26,14 +26,14 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="filterheader hidden-xs"><!-- ToDo: Implement filter for search results -->
|
<div class="filterheader hidden-xs"><!-- ToDo: Implement filter for search results -->
|
||||||
<a id="new" data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='new', query=query)}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a id="new" data-toggle="tooltip" title="{{_('Sort according to book date, newest first')}}" class="btn btn-primary{% if order == "new" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='new', query=query)}}"><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a id="old" data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='old', query=query)}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a id="old" data-toggle="tooltip" title="{{_('Sort according to book date, oldest first')}}" class="btn btn-primary{% if order == "old" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='old', query=query)}}"><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
<a id="asc" data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='abc', query=query)}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a id="asc" data-toggle="tooltip" title="{{_('Sort title in alphabetical order')}}" class="btn btn-primary{% if order == "abc" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='abc', query=query)}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
<a id="desc" data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='zyx', query=query)}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
<a id="desc" data-toggle="tooltip" title="{{_('Sort title in reverse alphabetical order')}}" class="btn btn-primary{% if order == "zyx" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='zyx', query=query)}}"><span class="glyphicon glyphicon-font"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
<a id="auth_az" data-toggle="tooltip" title="{{_('Sort authors in alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='authaz', query=query)}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
<a id="auth_az" data-toggle="tooltip" title="{{_('Sort authors in alphabetical order')}}" class="btn btn-primary{% if order == "authaz" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='authaz', query=query)}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet"></span></a>
|
||||||
<a id="auth_za" data-toggle="tooltip" title="{{_('Sort authors in reverse alphabetical order')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='authza', query=query)}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
<a id="auth_za" data-toggle="tooltip" title="{{_('Sort authors in reverse alphabetical order')}}" class="btn btn-primary{% if order == "authza" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='authza', query=query)}}"><span class="glyphicon glyphicon-user"></span><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span></a>
|
||||||
<a id="pub_new" data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='pubnew', query=query)}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
<a id="pub_new" data-toggle="tooltip" title="{{_('Sort according to publishing date, newest first')}}" class="btn btn-primary{% if order == "pubnew" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='pubnew', query=query)}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order"></span></a>
|
||||||
<a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary" href="{{url_for('web.books_list', data=page, sort_param='pubold', query=query)}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
<a id="pub_old" data-toggle="tooltip" title="{{_('Sort according to publishing date, oldest first')}}" class="btn btn-primary{% if order == "pubold" %} active{% endif%}" href="{{url_for('web.books_list', data=page, sort_param='pubold', query=query)}}"><span class="glyphicon glyphicon-calendar"></span><span class="glyphicon glyphicon-sort-by-order-alt"></span></a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
|
@ -101,29 +101,33 @@
|
||||||
<input type="checkbox" name="viewer_role" id="viewer_role" {% if content.role_viewer() %}checked{% endif %}>
|
<input type="checkbox" name="viewer_role" id="viewer_role" {% if content.role_viewer() %}checked{% endif %}>
|
||||||
<label for="viewer_role">{{_('Allow eBook Viewer')}}</label>
|
<label for="viewer_role">{{_('Allow eBook Viewer')}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% if config.config_upload %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="upload_role" id="upload_role" {% if content.role_upload() %}checked{% endif %}>
|
<input type="checkbox" name="upload_role" id="upload_role" {% if content.role_upload() %}checked{% endif %}>
|
||||||
<label for="upload_role">{{_('Allow Uploads')}}</label>
|
<label for="upload_role">{{_('Allow Uploads')}}</label>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="edit_role" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
|
<input type="checkbox" name="edit_role" data-control="edit_settings" id="edit_role" {% if content.role_edit() %}checked{% endif %}>
|
||||||
<label for="edit_role">{{_('Allow Edit')}}</label>
|
<label for="edit_role">{{_('Allow Edit')}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div data-related="edit_settings">
|
||||||
<input type="checkbox" name="delete_role" id="delete_role" {% if content.role_delete_books() %}checked{% endif %}>
|
<div class="form-group">
|
||||||
<label for="delete_role">{{_('Allow Delete Books')}}</label>
|
<input type="checkbox" name="delete_role" id="delete_role" {% if content.role_delete_books() %}checked{% endif %}>
|
||||||
|
<label for="delete_role">{{_('Allow Delete Books')}}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if not content.role_anonymous() %}
|
{% if not content.role_anonymous() %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}>
|
<input type="checkbox" name="passwd_role" id="passwd_role" {% if content.role_passwd() %}checked{% endif %}>
|
||||||
<label for="passwd_role">{{_('Allow Changing Password')}}</label>
|
<label for="passwd_role">{{_('Allow Changing Password')}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="edit_shelf_role" id="edit_shelf_role" {% if content.role_edit_shelfs() %}checked{% endif %}>
|
<input type="checkbox" name="edit_shelf_role" id="edit_shelf_role" {% if content.role_edit_shelfs() %}checked{% endif %}>
|
||||||
<label for="edit_shelf_role">{{_('Allow Editing Public Shelves')}}</label>
|
<label for="edit_shelf_role">{{_('Allow Editing Public Shelves')}}</label>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% if kobo_support and not content.role_anonymous() %}
|
{% if kobo_support and not content.role_anonymous() %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="kobo_only_shelves_sync" id="kobo_only_shelves_sync" {% if content.kobo_only_shelves_sync %}checked{% endif %}>
|
<input type="checkbox" name="kobo_only_shelves_sync" id="kobo_only_shelves_sync" {% if content.kobo_only_shelves_sync %}checked{% endif %}>
|
||||||
|
|
104
cps/web.py
104
cps/web.py
|
@ -339,7 +339,7 @@ def get_matching_tags():
|
||||||
|
|
||||||
|
|
||||||
def get_sort_function(sort, data):
|
def get_sort_function(sort, data):
|
||||||
order = [db.Books.timestamp.desc()]
|
order = [db.Books.sort]
|
||||||
if sort == 'stored':
|
if sort == 'stored':
|
||||||
sort = current_user.get_view_property(data, 'stored')
|
sort = current_user.get_view_property(data, 'stored')
|
||||||
else:
|
else:
|
||||||
|
@ -364,7 +364,13 @@ def get_sort_function(sort, data):
|
||||||
order = [db.Books.series_index.asc()]
|
order = [db.Books.series_index.asc()]
|
||||||
if sort == 'seriesdesc':
|
if sort == 'seriesdesc':
|
||||||
order = [db.Books.series_index.desc()]
|
order = [db.Books.series_index.desc()]
|
||||||
return order
|
if sort == 'hotdesc':
|
||||||
|
order = [func.count(ub.Downloads.book_id).desc()]
|
||||||
|
if sort == 'hotasc':
|
||||||
|
order = [func.count(ub.Downloads.book_id).asc()]
|
||||||
|
if sort is None:
|
||||||
|
sort = "abc"
|
||||||
|
return order, sort
|
||||||
|
|
||||||
|
|
||||||
def render_books_list(data, sort, book_id, page):
|
def render_books_list(data, sort, book_id, page):
|
||||||
|
@ -378,7 +384,7 @@ def render_books_list(data, sort, book_id, page):
|
||||||
elif data == "read":
|
elif data == "read":
|
||||||
return render_read_books(page, True, order=order)
|
return render_read_books(page, True, order=order)
|
||||||
elif data == "hot":
|
elif data == "hot":
|
||||||
return render_hot_books(page)
|
return render_hot_books(page, order)
|
||||||
elif data == "download":
|
elif data == "download":
|
||||||
return render_downloaded_books(page, order, book_id)
|
return render_downloaded_books(page, order, book_id)
|
||||||
elif data == "author":
|
elif data == "author":
|
||||||
|
@ -407,12 +413,12 @@ def render_books_list(data, sort, book_id, page):
|
||||||
return render_adv_search_results(term, offset, order, config.config_books_per_page)
|
return render_adv_search_results(term, offset, order, config.config_books_per_page)
|
||||||
else:
|
else:
|
||||||
website = data or "newest"
|
website = data or "newest"
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, order,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0, db.Books, True, order[0],
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series)
|
db.Series)
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
||||||
title=_(u"Books"), page=website)
|
title=_(u"Books"), page=website, order=order[1])
|
||||||
|
|
||||||
|
|
||||||
def render_rated_books(page, book_id, order):
|
def render_rated_books(page, book_id, order):
|
||||||
|
@ -420,13 +426,13 @@ def render_rated_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.ratings.any(db.Ratings.rating > 9),
|
db.Books.ratings.any(db.Ratings.rating > 9),
|
||||||
order,
|
order[0],
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series)
|
db.Series)
|
||||||
|
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
||||||
id=book_id, title=_(u"Top Rated Books"), page="rated")
|
id=book_id, title=_(u"Top Rated Books"), page="rated", order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -440,16 +446,21 @@ def render_discover_books(page, book_id):
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
def render_hot_books(page):
|
def render_hot_books(page, order):
|
||||||
if current_user.check_visibility(constants.SIDEBAR_HOT):
|
if current_user.check_visibility(constants.SIDEBAR_HOT):
|
||||||
|
if order[1] not in ['hotasc', 'hotdesc']:
|
||||||
|
# Unary expression comparsion only working (for this expression) in sqlalchemy 1.4+
|
||||||
|
#if not (order[0][0].compare(func.count(ub.Downloads.book_id).desc()) or
|
||||||
|
# order[0][0].compare(func.count(ub.Downloads.book_id).asc())):
|
||||||
|
order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc'
|
||||||
if current_user.show_detail_random():
|
if current_user.show_detail_random():
|
||||||
random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
||||||
.order_by(func.random()).limit(config.config_random_books)
|
.order_by(func.random()).limit(config.config_random_books)
|
||||||
else:
|
else:
|
||||||
random = false()
|
random = false()
|
||||||
off = int(int(config.config_books_per_page) * (page - 1))
|
off = int(int(config.config_books_per_page) * (page - 1))
|
||||||
all_books = ub.session.query(ub.Downloads, func.count(ub.Downloads.book_id)).order_by(
|
all_books = ub.session.query(ub.Downloads, func.count(ub.Downloads.book_id))\
|
||||||
func.count(ub.Downloads.book_id).desc()).group_by(ub.Downloads.book_id)
|
.order_by(*order[0]).group_by(ub.Downloads.book_id)
|
||||||
hot_books = all_books.offset(off).limit(config.config_books_per_page)
|
hot_books = all_books.offset(off).limit(config.config_books_per_page)
|
||||||
entries = list()
|
entries = list()
|
||||||
for book in hot_books:
|
for book in hot_books:
|
||||||
|
@ -462,7 +473,7 @@ def render_hot_books(page):
|
||||||
numBooks = entries.__len__()
|
numBooks = entries.__len__()
|
||||||
pagination = Pagination(page, config.config_books_per_page, numBooks)
|
pagination = Pagination(page, config.config_books_per_page, numBooks)
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
||||||
title=_(u"Hot Books (Most Downloaded)"), page="hot")
|
title=_(u"Hot Books (Most Downloaded)"), page="hot", order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -483,7 +494,10 @@ def render_downloaded_books(page, order, user_id):
|
||||||
0,
|
0,
|
||||||
db.Books,
|
db.Books,
|
||||||
ub.Downloads.user_id == user_id,
|
ub.Downloads.user_id == user_id,
|
||||||
order,
|
order[0],
|
||||||
|
db.books_series_link,
|
||||||
|
db.Books.id == db.books_series_link.c.book,
|
||||||
|
db.Series,
|
||||||
ub.Downloads, db.Books.id == ub.Downloads.book_id)
|
ub.Downloads, db.Books.id == ub.Downloads.book_id)
|
||||||
for book in entries:
|
for book in entries:
|
||||||
if not calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
if not calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
|
||||||
|
@ -496,7 +510,8 @@ def render_downloaded_books(page, order, user_id):
|
||||||
pagination=pagination,
|
pagination=pagination,
|
||||||
id=user_id,
|
id=user_id,
|
||||||
title=_(u"Downloaded books by %(user)s",user=user.name),
|
title=_(u"Downloaded books by %(user)s",user=user.name),
|
||||||
page="download")
|
page="download",
|
||||||
|
order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -505,7 +520,7 @@ def render_author_books(page, author_id, order):
|
||||||
entries, __, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, __, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.authors.any(db.Authors.id == author_id),
|
db.Books.authors.any(db.Authors.id == author_id),
|
||||||
[order[0], db.Series.name, db.Books.series_index],
|
[order[0][0], db.Series.name, db.Books.series_index],
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series)
|
db.Series)
|
||||||
|
@ -527,7 +542,7 @@ def render_author_books(page, author_id, order):
|
||||||
|
|
||||||
return render_title_template('author.html', entries=entries, pagination=pagination, id=author_id,
|
return render_title_template('author.html', entries=entries, pagination=pagination, id=author_id,
|
||||||
title=_(u"Author: %(name)s", name=author_name), author=author_info,
|
title=_(u"Author: %(name)s", name=author_name), author=author_info,
|
||||||
other_books=other_books, page="author")
|
other_books=other_books, page="author", order=order[1])
|
||||||
|
|
||||||
|
|
||||||
def render_publisher_books(page, book_id, order):
|
def render_publisher_books(page, book_id, order):
|
||||||
|
@ -536,12 +551,14 @@ def render_publisher_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.publishers.any(db.Publishers.id == book_id),
|
db.Books.publishers.any(db.Publishers.id == book_id),
|
||||||
[db.Series.name, order[0], db.Books.series_index],
|
[db.Series.name, order[0][0], db.Books.series_index],
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series)
|
db.Series)
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
||||||
title=_(u"Publisher: %(name)s", name=publisher.name), page="publisher")
|
title=_(u"Publisher: %(name)s", name=publisher.name),
|
||||||
|
page="publisher",
|
||||||
|
order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -552,9 +569,9 @@ def render_series_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.series.any(db.Series.id == book_id),
|
db.Books.series.any(db.Series.id == book_id),
|
||||||
[order[0]])
|
[order[0][0]])
|
||||||
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
||||||
title=_(u"Series: %(serie)s", serie=name.name), page="series")
|
title=_(u"Series: %(serie)s", serie=name.name), page="series", order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -564,10 +581,12 @@ def render_ratings_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.ratings.any(db.Ratings.id == book_id),
|
db.Books.ratings.any(db.Ratings.id == book_id),
|
||||||
[order[0]])
|
[order[0][0]])
|
||||||
if name and name.rating <= 10:
|
if name and name.rating <= 10:
|
||||||
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
||||||
title=_(u"Rating: %(rating)s stars", rating=int(name.rating / 2)), page="ratings")
|
title=_(u"Rating: %(rating)s stars", rating=int(name.rating / 2)),
|
||||||
|
page="ratings",
|
||||||
|
order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -578,9 +597,11 @@ def render_formats_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.data.any(db.Data.format == book_id.upper()),
|
db.Books.data.any(db.Data.format == book_id.upper()),
|
||||||
[order[0]])
|
[order[0][0]])
|
||||||
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
return render_title_template('index.html', random=random, pagination=pagination, entries=entries, id=book_id,
|
||||||
title=_(u"File format: %(format)s", format=name.format), page="formats")
|
title=_(u"File format: %(format)s", format=name.format),
|
||||||
|
page="formats",
|
||||||
|
order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -591,12 +612,12 @@ def render_category_books(page, book_id, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.tags.any(db.Tags.id == book_id),
|
db.Books.tags.any(db.Tags.id == book_id),
|
||||||
[order[0], db.Series.name, db.Books.series_index],
|
[order[0][0], db.Series.name, db.Books.series_index],
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series)
|
db.Series)
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=book_id,
|
||||||
title=_(u"Category: %(name)s", name=name.name), page="category")
|
title=_(u"Category: %(name)s", name=name.name), page="category", order=order[1])
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -610,13 +631,13 @@ def render_language_books(page, name, order):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db.Books.languages.any(db.Languages.lang_code == name),
|
db.Books.languages.any(db.Languages.lang_code == name),
|
||||||
[order[0]])
|
[order[0][0]])
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=name,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination, id=name,
|
||||||
title=_(u"Language: %(name)s", name=lang_name), page="language")
|
title=_(u"Language: %(name)s", name=lang_name), page="language", order=order[1])
|
||||||
|
|
||||||
|
|
||||||
def render_read_books(page, are_read, as_xml=False, order=None):
|
def render_read_books(page, are_read, as_xml=False, order=None):
|
||||||
order = order or []
|
sort = order[0] or []
|
||||||
if not config.config_read_column:
|
if not config.config_read_column:
|
||||||
if are_read:
|
if are_read:
|
||||||
db_filter = and_(ub.ReadBook.user_id == int(current_user.id),
|
db_filter = and_(ub.ReadBook.user_id == int(current_user.id),
|
||||||
|
@ -626,7 +647,7 @@ def render_read_books(page, are_read, as_xml=False, order=None):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db_filter,
|
db_filter,
|
||||||
order,
|
sort,
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series,
|
db.Series,
|
||||||
|
@ -640,7 +661,7 @@ def render_read_books(page, are_read, as_xml=False, order=None):
|
||||||
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
entries, random, pagination = calibre_db.fill_indexpage(page, 0,
|
||||||
db.Books,
|
db.Books,
|
||||||
db_filter,
|
db_filter,
|
||||||
order,
|
sort,
|
||||||
db.books_series_link,
|
db.books_series_link,
|
||||||
db.Books.id == db.books_series_link.c.book,
|
db.Books.id == db.books_series_link.c.book,
|
||||||
db.Series,
|
db.Series,
|
||||||
|
@ -663,11 +684,11 @@ def render_read_books(page, are_read, as_xml=False, order=None):
|
||||||
name = _(u'Unread Books') + ' (' + str(pagination.total_count) + ')'
|
name = _(u'Unread Books') + ' (' + str(pagination.total_count) + ')'
|
||||||
pagename = "unread"
|
pagename = "unread"
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
||||||
title=name, page=pagename)
|
title=name, page=pagename, order=order[1])
|
||||||
|
|
||||||
|
|
||||||
def render_archived_books(page, order):
|
def render_archived_books(page, sort):
|
||||||
order = order or []
|
order = sort[0] or []
|
||||||
archived_books = (
|
archived_books = (
|
||||||
ub.session.query(ub.ArchivedBook)
|
ub.session.query(ub.ArchivedBook)
|
||||||
.filter(ub.ArchivedBook.user_id == int(current_user.id))
|
.filter(ub.ArchivedBook.user_id == int(current_user.id))
|
||||||
|
@ -687,7 +708,7 @@ def render_archived_books(page, order):
|
||||||
name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')'
|
name = _(u'Archived Books') + ' (' + str(len(archived_book_ids)) + ')'
|
||||||
pagename = "archived"
|
pagename = "archived"
|
||||||
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
|
||||||
title=name, page=pagename)
|
title=name, page=pagename, order=sort[1])
|
||||||
|
|
||||||
|
|
||||||
def render_prepare_search_form(cc):
|
def render_prepare_search_form(cc):
|
||||||
|
@ -732,7 +753,8 @@ def render_search_results(term, offset=None, order=None, limit=None):
|
||||||
entries=entries,
|
entries=entries,
|
||||||
result_count=result_count,
|
result_count=result_count,
|
||||||
title=_(u"Search"),
|
title=_(u"Search"),
|
||||||
page="search")
|
page="search",
|
||||||
|
order=order[1])
|
||||||
|
|
||||||
|
|
||||||
# ################################### View Books list ##################################################################
|
# ################################### View Books list ##################################################################
|
||||||
|
@ -931,8 +953,9 @@ def series_list():
|
||||||
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
return render_title_template('list.html', entries=entries, folder='web.books_list', charlist=charlist,
|
||||||
title=_(u"Series"), page="serieslist", data="series", order=order_no)
|
title=_(u"Series"), page="serieslist", data="series", order=order_no)
|
||||||
else:
|
else:
|
||||||
entries = calibre_db.session.query(db.Books, func.count('books_series_link').label('count')) \
|
entries = calibre_db.session.query(db.Books, func.count('books_series_link').label('count'),
|
||||||
.join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters()) \
|
func.max(db.Books.series_index), db.Books.id) \
|
||||||
|
.join(db.books_series_link).join(db.Series).filter(calibre_db.common_filters())\
|
||||||
.group_by(text('books_series_link.series')).order_by(order).all()
|
.group_by(text('books_series_link.series')).order_by(order).all()
|
||||||
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
charlist = calibre_db.session.query(func.upper(func.substr(db.Series.sort, 1, 1)).label('char')) \
|
||||||
.join(db.books_series_link).join(db.Books).filter(calibre_db.common_filters()) \
|
.join(db.books_series_link).join(db.Books).filter(calibre_db.common_filters()) \
|
||||||
|
@ -1249,7 +1272,7 @@ def extend_search_term(searchterm,
|
||||||
|
|
||||||
|
|
||||||
def render_adv_search_results(term, offset=None, order=None, limit=None):
|
def render_adv_search_results(term, offset=None, order=None, limit=None):
|
||||||
order = order or [db.Books.sort]
|
sort = order[0] or [db.Books.sort]
|
||||||
pagination = None
|
pagination = None
|
||||||
|
|
||||||
cc = get_cc_columns(filter_config_custom_read=True)
|
cc = get_cc_columns(filter_config_custom_read=True)
|
||||||
|
@ -1347,7 +1370,7 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
||||||
log.debug_or_exception(ex)
|
log.debug_or_exception(ex)
|
||||||
flash(_("Error on search for custom columns, please restart Calibre-Web"), category="error")
|
flash(_("Error on search for custom columns, please restart Calibre-Web"), category="error")
|
||||||
|
|
||||||
q = q.order_by(*order).all()
|
q = q.order_by(*sort).all()
|
||||||
flask_session['query'] = json.dumps(term)
|
flask_session['query'] = json.dumps(term)
|
||||||
ub.store_ids(q)
|
ub.store_ids(q)
|
||||||
result_count = len(q)
|
result_count = len(q)
|
||||||
|
@ -1363,7 +1386,8 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
||||||
pagination=pagination,
|
pagination=pagination,
|
||||||
entries=q[offset:limit_all],
|
entries=q[offset:limit_all],
|
||||||
result_count=result_count,
|
result_count=result_count,
|
||||||
title=_(u"Advanced Search"), page="advsearch")
|
title=_(u"Advanced Search"), page="advsearch",
|
||||||
|
order=order[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ rarfile>=2.7
|
||||||
scholarly>=1.2.0, <1.3
|
scholarly>=1.2.0, <1.3
|
||||||
|
|
||||||
# other
|
# other
|
||||||
natsort>=2.2.0,<7.2.0
|
natsort>=2.2.0,<8.1.0
|
||||||
comicapi>= 2.2.0,<2.3.0
|
comicapi>=2.2.0,<2.3.0
|
||||||
|
|
||||||
#Kobo integration
|
#Kobo integration
|
||||||
jsonschema>=3.2.0,<3.3.0
|
jsonschema>=3.2.0,<3.3.0
|
||||||
|
|
Loading…
Reference in New Issue
Block a user