Merge branch 'master' of https://github.com/janeczku/calibre-web
This commit is contained in:
commit
1ef2a96465
|
@ -20,16 +20,18 @@
|
||||||
from __future__ import division, print_function, unicode_literals
|
from __future__ import division, print_function, unicode_literals
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
from sqlalchemy import exc, Column, String, Integer, SmallInteger, Boolean, BLOB, JSON
|
from sqlalchemy import Column, String, Integer, SmallInteger, Boolean, BLOB, JSON
|
||||||
from sqlalchemy.exc import OperationalError
|
from sqlalchemy.exc import OperationalError
|
||||||
|
from sqlalchemy.sql.expression import text
|
||||||
try:
|
try:
|
||||||
# Compatibility with sqlalchemy 2.0
|
# Compatibility with sqlalchemy 2.0
|
||||||
from sqlalchemy.orm import declarative_base
|
from sqlalchemy.orm import declarative_base
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
|
||||||
from . import constants, cli, logger, ub
|
from . import constants, cli, logger
|
||||||
|
|
||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
@ -260,7 +262,6 @@ class _ConfigSQL(object):
|
||||||
"""
|
"""
|
||||||
new_value = dictionary.get(field, default)
|
new_value = dictionary.get(field, default)
|
||||||
if new_value is None:
|
if new_value is None:
|
||||||
# log.debug("_ConfigSQL set_from_dictionary field '%s' not found", field)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if field not in self.__dict__:
|
if field not in self.__dict__:
|
||||||
|
@ -277,7 +278,6 @@ class _ConfigSQL(object):
|
||||||
if current_value == new_value:
|
if current_value == new_value:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# log.debug("_ConfigSQL set_from_dictionary '%s' = %r (was %r)", field, new_value, current_value)
|
|
||||||
setattr(self, field, new_value)
|
setattr(self, field, new_value)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -368,20 +368,23 @@ def _migrate_table(session, orm_class):
|
||||||
column_default = ""
|
column_default = ""
|
||||||
else:
|
else:
|
||||||
if isinstance(column.default.arg, bool):
|
if isinstance(column.default.arg, bool):
|
||||||
column_default = ("DEFAULT %r" % int(column.default.arg))
|
column_default = "DEFAULT {}".format(int(column.default.arg))
|
||||||
else:
|
else:
|
||||||
column_default = ("DEFAULT '%r'" % column.default.arg)
|
column_default = "DEFAULT `{}`".format(column.default.arg)
|
||||||
if isinstance(column.type, JSON):
|
if isinstance(column.type, JSON):
|
||||||
column_type = "JSON"
|
column_type = "JSON"
|
||||||
else:
|
else:
|
||||||
column_type = column.type
|
column_type = column.type
|
||||||
alter_table = "ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__,
|
alter_table = text("ALTER TABLE %s ADD COLUMN `%s` %s %s" % (orm_class.__tablename__,
|
||||||
column_name,
|
column_name,
|
||||||
column_type,
|
column_type,
|
||||||
column_default)
|
column_default))
|
||||||
log.debug(alter_table)
|
log.debug(alter_table)
|
||||||
session.execute(alter_table)
|
session.execute(alter_table)
|
||||||
changed = True
|
changed = True
|
||||||
|
except json.decoder.JSONDecodeError as e:
|
||||||
|
log.error("Database corrupt column: {}".format(column_name))
|
||||||
|
log.debug(e)
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
try:
|
try:
|
||||||
|
|
19
cps/db.py
19
cps/db.py
|
@ -121,6 +121,8 @@ class Identifiers(Base):
|
||||||
return u"Douban"
|
return u"Douban"
|
||||||
elif format_type == "goodreads":
|
elif format_type == "goodreads":
|
||||||
return u"Goodreads"
|
return u"Goodreads"
|
||||||
|
elif format_type == "babelio":
|
||||||
|
return u"Babelio"
|
||||||
elif format_type == "google":
|
elif format_type == "google":
|
||||||
return u"Google Books"
|
return u"Google Books"
|
||||||
elif format_type == "kobo":
|
elif format_type == "kobo":
|
||||||
|
@ -148,6 +150,8 @@ class Identifiers(Base):
|
||||||
return u"https://dx.doi.org/{0}".format(self.val)
|
return u"https://dx.doi.org/{0}".format(self.val)
|
||||||
elif format_type == "goodreads":
|
elif format_type == "goodreads":
|
||||||
return u"https://www.goodreads.com/book/show/{0}".format(self.val)
|
return u"https://www.goodreads.com/book/show/{0}".format(self.val)
|
||||||
|
elif format_type == "babelio":
|
||||||
|
return u"https://www.babelio.com/livres/titre/{0}".format(self.val)
|
||||||
elif format_type == "douban":
|
elif format_type == "douban":
|
||||||
return u"https://book.douban.com/subject/{0}".format(self.val)
|
return u"https://book.douban.com/subject/{0}".format(self.val)
|
||||||
elif format_type == "google":
|
elif format_type == "google":
|
||||||
|
@ -702,14 +706,21 @@ class CalibreDB():
|
||||||
return self.session.query(Books) \
|
return self.session.query(Books) \
|
||||||
.filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first()
|
.filter(and_(Books.authors.any(and_(*q)), func.lower(Books.title).ilike("%" + title + "%"))).first()
|
||||||
|
|
||||||
def search_query(self, term):
|
def search_query(self, term, *join):
|
||||||
term.strip().lower()
|
term.strip().lower()
|
||||||
self.session.connection().connection.connection.create_function("lower", 1, lcase)
|
self.session.connection().connection.connection.create_function("lower", 1, lcase)
|
||||||
q = list()
|
q = list()
|
||||||
authorterms = re.split("[, ]+", term)
|
authorterms = re.split("[, ]+", term)
|
||||||
for authorterm in authorterms:
|
for authorterm in authorterms:
|
||||||
q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%")))
|
q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%")))
|
||||||
return self.session.query(Books).filter(self.common_filters(True)).filter(
|
query = self.session.query(Books)
|
||||||
|
if len(join) == 3:
|
||||||
|
query = query.outerjoin(join[0], join[1]).outerjoin(join[2])
|
||||||
|
elif len(join) == 2:
|
||||||
|
query = query.outerjoin(join[0], join[1])
|
||||||
|
elif len(join) == 1:
|
||||||
|
query = query.outerjoin(join[0])
|
||||||
|
return query.filter(self.common_filters(True)).filter(
|
||||||
or_(Books.tags.any(func.lower(Tags.name).ilike("%" + term + "%")),
|
or_(Books.tags.any(func.lower(Tags.name).ilike("%" + term + "%")),
|
||||||
Books.series.any(func.lower(Series.name).ilike("%" + term + "%")),
|
Books.series.any(func.lower(Series.name).ilike("%" + term + "%")),
|
||||||
Books.authors.any(and_(*q)),
|
Books.authors.any(and_(*q)),
|
||||||
|
@ -718,10 +729,10 @@ 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):
|
def get_search_results(self, term, offset=None, order=None, limit=None, *join):
|
||||||
order = order or [Books.sort]
|
order = order or [Books.sort]
|
||||||
pagination = None
|
pagination = None
|
||||||
result = self.search_query(term).order_by(*order).all()
|
result = self.search_query(term, *join).order_by(*order).all()
|
||||||
result_count = len(result)
|
result_count = len(result)
|
||||||
if offset != None and limit != None:
|
if offset != None and limit != None:
|
||||||
offset = int(offset)
|
offset = int(offset)
|
||||||
|
|
|
@ -49,5 +49,5 @@ except ImportError as err:
|
||||||
try:
|
try:
|
||||||
from . import gmail
|
from . import gmail
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
log.debug("Cannot import Gmail, sending books via G-Mail Accounts will not work: %s", err)
|
log.debug("Cannot import gmail, sending books via Gmail Oauth2 Verification will not work: %s", err)
|
||||||
gmail = None
|
gmail = None
|
||||||
|
|
|
@ -53,6 +53,7 @@ def setup_gmail(token):
|
||||||
'expiry': creds.expiry.isoformat(),
|
'expiry': creds.expiry.isoformat(),
|
||||||
'email': user_info
|
'email': user_info
|
||||||
}
|
}
|
||||||
|
return {}
|
||||||
|
|
||||||
def get_user_info(credentials):
|
def get_user_info(credentials):
|
||||||
user_info_service = build(serviceName='oauth2', version='v2',credentials=credentials)
|
user_info_service = build(serviceName='oauth2', version='v2',credentials=credentials)
|
||||||
|
|
|
@ -84,15 +84,24 @@ body {
|
||||||
#progress .bar-load,
|
#progress .bar-load,
|
||||||
#progress .bar-read {
|
#progress .bar-read {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
transition: width 150ms ease-in-out;
|
transition: width 150ms ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#progress .from-left {
|
||||||
|
left: 0;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress .from-right {
|
||||||
|
right: 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
#progress .bar-load {
|
#progress .bar-load {
|
||||||
color: #000;
|
color: #000;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
|
|
|
@ -171,7 +171,10 @@ kthoom.ImageFile = function(file) {
|
||||||
|
|
||||||
function initProgressClick() {
|
function initProgressClick() {
|
||||||
$("#progress").click(function(e) {
|
$("#progress").click(function(e) {
|
||||||
var page = Math.max(1, Math.ceil((e.offsetX / $(this).width()) * totalImages)) - 1;
|
var offset = $(this).offset();
|
||||||
|
var x = e.pageX - offset.left;
|
||||||
|
var rate = settings.direction === 0 ? x / $(this).width() : 1 - x / $(this).width();
|
||||||
|
var page = Math.max(1, Math.ceil(rate * totalImages)) - 1;
|
||||||
currentImage = page;
|
currentImage = page;
|
||||||
updatePage();
|
updatePage();
|
||||||
});
|
});
|
||||||
|
@ -285,6 +288,22 @@ function updatePage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProgress(loadPercentage) {
|
function updateProgress(loadPercentage) {
|
||||||
|
if (settings.direction === 0) {
|
||||||
|
$("#progress .bar-read")
|
||||||
|
.removeClass("from-right")
|
||||||
|
.addClass("from-left");
|
||||||
|
$("#progress .bar-load")
|
||||||
|
.removeClass("from-right")
|
||||||
|
.addClass("from-left");
|
||||||
|
} else {
|
||||||
|
$("#progress .bar-read")
|
||||||
|
.removeClass("from-left")
|
||||||
|
.addClass("from-right");
|
||||||
|
$("#progress .bar-load")
|
||||||
|
.removeClass("from-left")
|
||||||
|
.addClass("from-right");
|
||||||
|
}
|
||||||
|
|
||||||
// Set the load/unzip progress if it's passed in
|
// Set the load/unzip progress if it's passed in
|
||||||
if (loadPercentage) {
|
if (loadPercentage) {
|
||||||
$("#progress .bar-load").css({ width: loadPercentage + "%" });
|
$("#progress .bar-load").css({ width: loadPercentage + "%" });
|
||||||
|
@ -526,18 +545,17 @@ function keyHandler(evt) {
|
||||||
break;
|
break;
|
||||||
case kthoom.Key.SPACE:
|
case kthoom.Key.SPACE:
|
||||||
var container = $("#mainContent");
|
var container = $("#mainContent");
|
||||||
var atTop = container.scrollTop() === 0;
|
// var atTop = container.scrollTop() === 0;
|
||||||
var atBottom = container.scrollTop() >= container[0].scrollHeight - container.height();
|
// var atBottom = container.scrollTop() >= container[0].scrollHeight - container.height();
|
||||||
|
|
||||||
if (evt.shiftKey && atTop) {
|
if (evt.shiftKey) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
// If it's Shift + Space and the container is at the top of the page
|
// If it's Shift + Space and the container is at the top of the page
|
||||||
showLeftPage();
|
showPrevPage();
|
||||||
} else if (!evt.shiftKey && atBottom) {
|
} else {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
// If you're at the bottom of the page and you only pressed space
|
// If you're at the bottom of the page and you only pressed space
|
||||||
showRightPage();
|
showNextPage();
|
||||||
container.scrollTop(0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -114,6 +114,20 @@ $(document).ready(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(".session").click(function() {
|
||||||
|
window.sessionStorage.setItem("back", window.location.pathname);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#back").click(function() {
|
||||||
|
var loc = sessionStorage.getItem("back");
|
||||||
|
if (!loc) {
|
||||||
|
loc = $(this).data("back");
|
||||||
|
}
|
||||||
|
sessionStorage.removeItem("back");
|
||||||
|
window.location.href = loc;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
function confirmDialog(id, dialogid, dataValue, yesFn, noFn) {
|
function confirmDialog(id, dialogid, dataValue, yesFn, noFn) {
|
||||||
var $confirm = $("#" + dialogid);
|
var $confirm = $("#" + dialogid);
|
||||||
$confirm.modal('show');
|
$confirm.modal('show');
|
||||||
|
|
|
@ -177,7 +177,6 @@ $(function() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$("#domain_allow_submit").click(function(event) {
|
$("#domain_allow_submit").click(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$("#domain_add_allow").ajaxForm();
|
$("#domain_add_allow").ajaxForm();
|
||||||
|
@ -388,7 +387,6 @@ $(function() {
|
||||||
var target = $(e.relatedTarget).attr('id');
|
var target = $(e.relatedTarget).attr('id');
|
||||||
var dataId;
|
var dataId;
|
||||||
$(e.relatedTarget).one('focus', function(e){$(this).blur();});
|
$(e.relatedTarget).one('focus', function(e){$(this).blur();});
|
||||||
//$(e.relatedTarget).blur();
|
|
||||||
if ($(e.relatedTarget).hasClass("button_head")) {
|
if ($(e.relatedTarget).hasClass("button_head")) {
|
||||||
dataId = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
dataId = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -454,18 +452,28 @@ $(function() {
|
||||||
$(this).next().text(elText);
|
$(this).next().text(elText);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onLoadSuccess: function () {
|
onPostHeader () {
|
||||||
var guest = $(".editable[data-name='name'][data-value='Guest']");
|
deactivateHeaderButtons();
|
||||||
guest.editable("disable");
|
|
||||||
$(".editable[data-name='locale'][data-pk='"+guest.data("pk")+"']").editable("disable");
|
|
||||||
$("input[data-name='admin_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
|
||||||
$("input[data-name='passwd_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
|
||||||
$("input[data-name='edit_shelf_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
|
||||||
$("input[data-name='sidebar_read_and_unread'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
|
||||||
$(".user-remove[data-pk='"+guest.data("pk")+"']").hide();
|
|
||||||
},
|
},
|
||||||
onSort: function(a, b) {
|
onLoadSuccess: function () {
|
||||||
console.log("huh");
|
loadSuccess();
|
||||||
|
var element = $(".header_select");
|
||||||
|
element.each(function() {
|
||||||
|
var item = $(this).parent();
|
||||||
|
var parent = item.parent().parent();
|
||||||
|
if (parent.prop('nodeName') === "TH") {
|
||||||
|
item.prependTo(parent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var element = $(".form-check");
|
||||||
|
element.each(function() {
|
||||||
|
var item = $(this).parent();
|
||||||
|
var parent = item.parent().parent();
|
||||||
|
if (parent.prop('nodeName') === "TH") {
|
||||||
|
item.prependTo(parent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
onColumnSwitch: function () {
|
onColumnSwitch: function () {
|
||||||
var visible = $("#user-table").bootstrapTable("getVisibleColumns");
|
var visible = $("#user-table").bootstrapTable("getVisibleColumns");
|
||||||
|
@ -491,7 +499,18 @@ $(function() {
|
||||||
$("#user_delete_selection").click(function() {
|
$("#user_delete_selection").click(function() {
|
||||||
$("#user-table").bootstrapTable("uncheckAll");
|
$("#user-table").bootstrapTable("uncheckAll");
|
||||||
});
|
});
|
||||||
|
$("#select_locale").on("change",function() {
|
||||||
|
selectHeader(this, "locale");
|
||||||
|
});
|
||||||
|
$("#select_default_language").on("change",function() {
|
||||||
|
selectHeader(this, "default_language");
|
||||||
|
});
|
||||||
|
$(".check_head").on("change",function() {
|
||||||
|
var val = $(this).val() === "on";
|
||||||
|
var name = $(this).data("name");
|
||||||
|
var data = $(this).data("val");
|
||||||
|
checkboxHeader(val, name, data);
|
||||||
|
});
|
||||||
function user_handle (userId) {
|
function user_handle (userId) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method:"post",
|
method:"post",
|
||||||
|
@ -505,6 +524,7 @@ $(function() {
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
success:function(data) {
|
success:function(data) {
|
||||||
$("#user-table").bootstrapTable("load", data);
|
$("#user-table").bootstrapTable("load", data);
|
||||||
|
loadSuccess();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -560,10 +580,6 @@ function TableActions (value, row) {
|
||||||
].join("");
|
].join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function editEntry(param)
|
|
||||||
{
|
|
||||||
console.log(param);
|
|
||||||
}
|
|
||||||
/* Function for deleting domain restrictions */
|
/* Function for deleting domain restrictions */
|
||||||
function RestrictionActions (value, row) {
|
function RestrictionActions (value, row) {
|
||||||
return [
|
return [
|
||||||
|
@ -582,7 +598,7 @@ function EbookActions (value, row) {
|
||||||
].join("");
|
].join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Function for deleting books */
|
/* Function for deleting Users */
|
||||||
function UserActions (value, row) {
|
function UserActions (value, row) {
|
||||||
return [
|
return [
|
||||||
"<div class=\"user-remove\" data-value=\"delete\" onclick=\"deleteUser(this, '" + row.id + "')\" data-pk=\"" + row.id + "\" title=\"Remove\">",
|
"<div class=\"user-remove\" data-value=\"delete\" onclick=\"deleteUser(this, '" + row.id + "')\" data-pk=\"" + row.id + "\" title=\"Remove\">",
|
||||||
|
@ -600,7 +616,7 @@ function responseHandler(res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function singleUserFormatter(value, row) {
|
function singleUserFormatter(value, row) {
|
||||||
return '<a class="btn btn-default" href="' + window.location.pathname + '/../../admin/user/' + row.id + '">' + this.buttontext + '</a>'
|
return '<a class="btn btn-default" onclick="storeLocation()" href="' + window.location.pathname + '/../../admin/user/' + row.id + '">' + this.buttontext + '</a>'
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkboxFormatter(value, row, index){
|
function checkboxFormatter(value, row, index){
|
||||||
|
@ -610,15 +626,22 @@ function checkboxFormatter(value, row, index){
|
||||||
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
|
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkboxChange(checkbox, userId, field, field_index) {
|
function loadSuccess() {
|
||||||
$.ajax({
|
var guest = $(".editable[data-name='name'][data-value='Guest']");
|
||||||
method: "post",
|
guest.editable("disable");
|
||||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
$(".editable[data-name='locale'][data-pk='"+guest.data("pk")+"']").editable("disable");
|
||||||
data: {"pk": userId, "field_index": field_index, "value": checkbox.checked},
|
$(".editable[data-name='locale'][data-pk='"+guest.data("pk")+"']").hide();
|
||||||
success: function (data) {
|
$("input[data-name='admin_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||||
if (!jQuery.isEmptyObject(data)) {
|
$("input[data-name='passwd_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||||
|
$("input[data-name='edit_shelf_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||||
|
$("input[data-name='sidebar_read_and_unread'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||||
|
$(".user-remove[data-pk='"+guest.data("pk")+"']").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleListServerResponse (data, disableButtons) {
|
||||||
$("#flash_success").remove();
|
$("#flash_success").remove();
|
||||||
$("#flash_danger").remove();
|
$("#flash_danger").remove();
|
||||||
|
if (!jQuery.isEmptyObject(data)) {
|
||||||
$( ".navbar" ).after( '<div class="row-fluid text-center" style="margin-top: -20px;">' +
|
$( ".navbar" ).after( '<div class="row-fluid text-center" style="margin-top: -20px;">' +
|
||||||
'<div id="flash_'+data.type+'" class="alert alert-'+data.type+'">'+data.message+'</div>' +
|
'<div id="flash_'+data.type+'" class="alert alert-'+data.type+'">'+data.message+'</div>' +
|
||||||
'</div>');
|
'</div>');
|
||||||
|
@ -630,13 +653,28 @@ function checkboxChange(checkbox, userId, field, field_index) {
|
||||||
timeout: 900,
|
timeout: 900,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$("#user-table").bootstrapTable("load", data);
|
$("#user-table").bootstrapTable("load", data);
|
||||||
|
if (disableButtons) {
|
||||||
|
deactivateHeaderButtons();
|
||||||
}
|
}
|
||||||
});
|
loadSuccess();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deactivateHeaderButtons(e) {
|
|
||||||
|
function checkboxChange(checkbox, userId, field, field_index) {
|
||||||
|
$.ajax({
|
||||||
|
method: "post",
|
||||||
|
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||||
|
data: {"pk": userId, "field_index": field_index, "value": checkbox.checked},
|
||||||
|
error: function(data) {
|
||||||
|
handleListServerResponse({type:"danger", message:data.responseText})
|
||||||
|
},
|
||||||
|
success: handleListServerResponse
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deactivateHeaderButtons() {
|
||||||
$("#user_delete_selection").addClass("disabled");
|
$("#user_delete_selection").addClass("disabled");
|
||||||
$("#user_delete_selection").attr("aria-disabled", true);
|
$("#user_delete_selection").attr("aria-disabled", true);
|
||||||
$(".check_head").attr("aria-disabled", true);
|
$(".check_head").attr("aria-disabled", true);
|
||||||
|
@ -655,18 +693,10 @@ function selectHeader(element, field) {
|
||||||
method: "post",
|
method: "post",
|
||||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||||
data: {"pk": result, "value": element.value},
|
data: {"pk": result, "value": element.value},
|
||||||
success: function () {
|
error: function (data) {
|
||||||
$.ajax({
|
handleListServerResponse({type:"danger", message:data.responseText})
|
||||||
method: "get",
|
},
|
||||||
url: window.location.pathname + "/../../ajax/listusers",
|
success: handleListServerResponse,
|
||||||
async: true,
|
|
||||||
timeout: 900,
|
|
||||||
success: function (data) {
|
|
||||||
$("#user-table").bootstrapTable("load", data);
|
|
||||||
deactivateHeaderButtons();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -679,25 +709,12 @@ function checkboxHeader(CheckboxState, field, field_index) {
|
||||||
method: "post",
|
method: "post",
|
||||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||||
data: {"pk": result, "field_index": field_index, "value": CheckboxState},
|
data: {"pk": result, "field_index": field_index, "value": CheckboxState},
|
||||||
success: function () {
|
error: function (data) {
|
||||||
$.ajax({
|
handleListServerResponse({type:"danger", message:data.responseText}, true)
|
||||||
method: "get",
|
},
|
||||||
url: window.location.pathname + "/../../ajax/listusers",
|
|
||||||
async: true,
|
|
||||||
timeout: 900,
|
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$("#user-table").bootstrapTable("load", data);
|
handleListServerResponse (data, true)
|
||||||
$("#user_delete_selection").addClass("disabled");
|
},
|
||||||
$("#user_delete_selection").attr("aria-disabled", true);
|
|
||||||
$(".check_head").attr("aria-disabled", true);
|
|
||||||
$(".check_head").attr("disabled", true);
|
|
||||||
$(".check_head").prop('checked', false);
|
|
||||||
$(".button_head").attr("aria-disabled", true);
|
|
||||||
$(".button_head").addClass("disabled");
|
|
||||||
$(".header_select").attr("disabled", true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -712,24 +729,10 @@ function deleteUser(a,b){
|
||||||
method:"post",
|
method:"post",
|
||||||
url: window.location.pathname + "/../../ajax/deleteuser",
|
url: window.location.pathname + "/../../ajax/deleteuser",
|
||||||
data: {"userid":b},
|
data: {"userid":b},
|
||||||
success:function(data) {
|
success: handleListServerResponse,
|
||||||
$("#flash_success").remove();
|
error: function (data) {
|
||||||
$("#flash_danger").remove();
|
handleListServerResponse({type:"danger", message:data.responseText})
|
||||||
if (!jQuery.isEmptyObject(data)) {
|
},
|
||||||
$( ".navbar" ).after( '<div class="row-fluid text-center" style="margin-top: -20px;">' +
|
|
||||||
'<div id="flash_'+data.type+'" class="alert alert-'+data.type+'">'+data.message+'</div>' +
|
|
||||||
'</div>');
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
method: "get",
|
|
||||||
url: window.location.pathname + "/../../ajax/listusers",
|
|
||||||
async: true,
|
|
||||||
timeout: 900,
|
|
||||||
success: function (data) {
|
|
||||||
$("#user-table").bootstrapTable("load", data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -741,6 +744,6 @@ function queryParams(params)
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
function test(){
|
function storeLocation() {
|
||||||
console.log("hello");
|
window.sessionStorage.setItem("back", window.location.pathname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
{% for user in allUser %}
|
{% for user in allUser %}
|
||||||
{% if not user.role_anonymous() or config.config_anonbrowse %}
|
{% if not user.role_anonymous() or config.config_anonbrowse %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{url_for('admin.edit_user', user_id=user.id)}}">{{user.name}}</a></td>
|
<td><a class="session" href="{{url_for('admin.edit_user', user_id=user.id)}}">{{user.name}}</a></td>
|
||||||
<td>{{user.email}}</td>
|
<td>{{user.email}}</td>
|
||||||
<td>{{user.kindle_mail}}</td>
|
<td>{{user.kindle_mail}}</td>
|
||||||
<td>{{user.downloads.count()}}</td>
|
<td>{{user.downloads.count()}}</td>
|
||||||
|
|
|
@ -47,13 +47,13 @@
|
||||||
{{ text_table_row('title', _('Enter Title'),_('Title'), true, true) }}
|
{{ text_table_row('title', _('Enter Title'),_('Title'), true, true) }}
|
||||||
{{ text_table_row('sort', _('Enter Title Sort'),_('Title Sort'), false, true) }}
|
{{ text_table_row('sort', _('Enter Title Sort'),_('Title Sort'), false, true) }}
|
||||||
{{ text_table_row('author_sort', _('Enter Author Sort'),_('Author Sort'), false, true) }}
|
{{ text_table_row('author_sort', _('Enter Author Sort'),_('Author Sort'), false, true) }}
|
||||||
{{ text_table_row('authors', _('Enter Authors'),_('Authors'), true) }}
|
{{ text_table_row('authors', _('Enter Authors'),_('Authors'), true, true) }}
|
||||||
{{ text_table_row('tags', _('Enter Categories'),_('Categories'), false, false) }}
|
{{ text_table_row('tags', _('Enter Categories'),_('Categories'), false, true) }}
|
||||||
{{ text_table_row('series', _('Enter Series'),_('Series'), false, false) }}
|
{{ text_table_row('series', _('Enter Series'),_('Series'), false, true) }}
|
||||||
<th data-field="series_index" id="series_index" data-visible="{{visiblility.get('series_index')}}" data-edit-validate="{{ _('This Field is Required') }}" data-sortable="true" {% if g.user.role_edit() %} data-editable-type="number" data-editable-placeholder="1" data-editable-step="0.01" data-editable-min="0" data-editable-url="{{ url_for('editbook.edit_list_book', param='series_index')}}" data-edit="true" data-editable-title="{{_('Enter title')}}"{% endif %}>{{_('Series Index')}}</th>
|
<th data-field="series_index" id="series_index" data-visible="{{visiblility.get('series_index')}}" data-edit-validate="{{ _('This Field is Required') }}" data-sortable="true" {% if g.user.role_edit() %} data-editable-type="number" data-editable-placeholder="1" data-editable-step="0.01" data-editable-min="0" data-editable-url="{{ url_for('editbook.edit_list_book', param='series_index')}}" data-edit="true" data-editable-title="{{_('Enter title')}}"{% endif %}>{{_('Series Index')}}</th>
|
||||||
{{ text_table_row('languages', _('Enter Languages'),_('Languages'), false, false) }}
|
{{ text_table_row('languages', _('Enter Languages'),_('Languages'), false, true) }}
|
||||||
<!--th data-field="pubdate" data-type="date" data-visible="{{visiblility.get('pubdate')}}" data-viewformat="dd.mm.yyyy" id="pubdate" data-sortable="true">{{_('Publishing Date')}}</th-->
|
<!--th data-field="pubdate" data-type="date" data-visible="{{visiblility.get('pubdate')}}" data-viewformat="dd.mm.yyyy" id="pubdate" data-sortable="true">{{_('Publishing Date')}}</th-->
|
||||||
{{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false, false) }}
|
{{ text_table_row('publishers', _('Enter Publishers'),_('Publishers'), false, true) }}
|
||||||
{% if g.user.role_delete_books() and g.user.role_edit()%}
|
{% if g.user.role_delete_books() and g.user.role_edit()%}
|
||||||
<th data-align="right" data-formatter="EbookActions" data-switchable="false">{{_('Delete')}}</th>
|
<th data-align="right" data-formatter="EbookActions" data-switchable="false">{{_('Delete')}}</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<label for="mail_server_type">{{_('Choose Server Type')}}</label>
|
<label for="mail_server_type">{{_('Choose Server Type')}}</label>
|
||||||
<select name="mail_server_type" id="config_email_type" class="form-control" data-control="email-settings">
|
<select name="mail_server_type" id="config_email_type" class="form-control" data-control="email-settings">
|
||||||
<option value="0" {% if content.mail_server_type == 0 %}selected{% endif %}>{{_('Use Standard E-Mail Account')}}</option>
|
<option value="0" {% if content.mail_server_type == 0 %}selected{% endif %}>{{_('Use Standard E-Mail Account')}}</option>
|
||||||
<option value="1" {% if content.mail_server_type == 1 %}selected{% endif %}>{{_('G-Mail Account with OAuth2 Verfification')}}</option>
|
<option value="1" {% if content.mail_server_type == 1 %}selected{% endif %}>{{_('Gmail Account with OAuth2 Verfification')}}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div data-related="email-settings-1">
|
<div data-related="email-settings-1">
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
{% if content.mail_gmail_token == {} %}
|
{% if content.mail_gmail_token == {} %}
|
||||||
<button type="submit" id="gmail_server" name="gmail" value="submit" class="btn btn-default">{{_('Setup Gmail Account as E-Mail Server')}}</button>
|
<button type="submit" id="gmail_server" name="gmail" value="submit" class="btn btn-default">{{_('Setup Gmail Account as E-Mail Server')}}</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="submit" id="invalidate_server" name="invalidate" value="submit" class="btn btn-danger">{{_('Revoke G-Mail Access')}}</button>
|
<button type="submit" id="invalidate_server" name="invalidate" value="submit" class="btn btn-danger">{{_('Revoke Gmail Access')}}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
{% if feature_support['gmail'] %}
|
{% if feature_support['gmail'] %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url_for('admin.admin') }}" id="back" class="btn btn-default">{{_('Back')}}</a>
|
<a href="{{ url_for('admin.admin') }}" id="email_back" class="btn btn-default">{{_('Back')}}</a>
|
||||||
</form>
|
</form>
|
||||||
{% if g.allow_registration %}
|
{% if g.allow_registration %}
|
||||||
<div class="col-md-10 col-lg-6">
|
<div class="col-md-10 col-lg-6">
|
||||||
|
|
|
@ -60,12 +60,12 @@
|
||||||
<a id="fullscreen" class="icon-resize-full">Fullscreen</a>
|
<a id="fullscreen" class="icon-resize-full">Fullscreen</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="progress" role="progressbar" class="loading">
|
<div id="progress" role="progressbar" class="loading">
|
||||||
<div class="bar-load">
|
<div class="bar-load from-left">
|
||||||
<div class="text load">
|
<div class="text load">
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bar-read">
|
<div class="bar-read from-left">
|
||||||
<div class="text page"></div>
|
<div class="text page"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -129,7 +129,7 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div id="user_submit" class="btn btn-default">{{_('Save')}}</div>
|
<div id="user_submit" class="btn btn-default">{{_('Save')}}</div>
|
||||||
{% if not profile %}
|
{% if not profile %}
|
||||||
<a href="{{ url_for('admin.admin') }}" id="back" class="btn btn-default">{{_('Cancel')}}</a>
|
<div class="btn btn-default" data-back="{{ url_for('admin.admin') }}" id="back">{{_('Cancel')}}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %}
|
{% if g.user and g.user.role_admin() and not profile and not new_user and not content.role_anonymous() %}
|
||||||
<div class="btn btn-danger" id="btndeluser" data-value="{{ content.id }}" data-remote="false" >{{_('Delete User')}}</div>
|
<div class="btn btn-danger" id="btndeluser" data-value="{{ content.id }}" data-remote="false" >{{_('Delete User')}}</div>
|
||||||
|
|
|
@ -24,15 +24,17 @@
|
||||||
data-column="{{value.get(array_field)}}"
|
data-column="{{value.get(array_field)}}"
|
||||||
data-formatter="checkboxFormatter">
|
data-formatter="checkboxFormatter">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" class="check_head" name="options_{{array_field}}" onchange="checkboxHeader('false', '{{parameter}}', {{value.get(array_field)}})" disabled>{{_('Deny')}}
|
<input type="radio" class="check_head" data-val={{value.get(array_field)}} name="options_{{array_field}}" data-name="{{parameter}}" disabled>{{_('Deny')}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div>
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" class="check_head" name="options_{{array_field}}" onchange="checkboxHeader('true', '{{parameter}}', {{value.get(array_field)}})" disabled>{{_('Allow')}}
|
<input type="radio" class="check_head" data-val={{value.get(array_field)}} name="options_{{array_field}}" data-name="{{parameter}}" disabled>{{_('Allow')}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{{show_text}}
|
{{show_text}}
|
||||||
</th>
|
</th>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
@ -48,14 +50,13 @@
|
||||||
data-editable-source={{url}}
|
data-editable-source={{url}}
|
||||||
{% if validate %}data-edit-validate="{{ _('This Field is Required') }}"{% endif %}>
|
{% if validate %}data-edit-validate="{{ _('This Field is Required') }}"{% endif %}>
|
||||||
<div>
|
<div>
|
||||||
<select id="select_{{ parameter }}" class="header_select" onchange="selectHeader(this, '{{parameter}}')" disabled="">
|
<select id="select_{{ parameter }}" class="header_select" disabled="">
|
||||||
<option value="all">{{ _('Show All') }}</option>
|
<option value="all">{{ _('Show All') }}</option>
|
||||||
{% for language in languages %}
|
{% for language in languages %}
|
||||||
<option value="{{language.lang_code}}">{{language.name}}</option>
|
<option value="{{language.lang_code}}">{{language.name}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div><br>
|
</div>
|
||||||
|
|
||||||
{{ show_text }}
|
{{ show_text }}
|
||||||
</th>
|
</th>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
@ -71,13 +72,13 @@
|
||||||
data-editable-source={{url}}
|
data-editable-source={{url}}
|
||||||
{% if validate %}data-edit-validate="{{ _('This Field is Required') }}"{% endif %}>
|
{% if validate %}data-edit-validate="{{ _('This Field is Required') }}"{% endif %}>
|
||||||
<div>
|
<div>
|
||||||
<select id="select_{{ parameter }}" class="header_select" onchange="selectHeader(this, '{{parameter}}')" disabled="">
|
<select id="select_{{ parameter }}" class="header_select" disabled="">
|
||||||
<option value="None">{{_('Select...')}}</option>
|
<option value="None">{{_('Select...')}}</option>
|
||||||
{% for translation in translations %}
|
{% for translation in translations %}
|
||||||
<option value="{{translation}}">{{translation.display_name|capitalize}}</option>
|
<option value="{{translation}}">{{translation.display_name|capitalize}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div><br>
|
</div>
|
||||||
{{ show_text }}
|
{{ show_text }}
|
||||||
</th>
|
</th>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
@ -137,6 +138,9 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
<div class="errorlink">
|
||||||
|
<div class="btn btn-default" data-back="{{ url_for('admin.admin') }}" id="back">{{_('Back')}}</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block modal %}
|
{% block modal %}
|
||||||
{{ delete_confirm_modal() }}
|
{{ delete_confirm_modal() }}
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -75,8 +75,9 @@ def load_user_from_auth_header(header_val):
|
||||||
basic_username = basic_password = '' # nosec
|
basic_username = basic_password = '' # nosec
|
||||||
try:
|
try:
|
||||||
header_val = base64.b64decode(header_val).decode('utf-8')
|
header_val = base64.b64decode(header_val).decode('utf-8')
|
||||||
basic_username = header_val.split(':')[0]
|
# Users with colon are invalid: rfc7617 page 4
|
||||||
basic_password = header_val.split(':')[1]
|
basic_username = header_val.split(':', 1)[0]
|
||||||
|
basic_password = header_val.split(':', 1)[1]
|
||||||
except (TypeError, UnicodeDecodeError, binascii.Error):
|
except (TypeError, UnicodeDecodeError, binascii.Error):
|
||||||
pass
|
pass
|
||||||
user = _fetch_user_by_name(basic_username)
|
user = _fetch_user_by_name(basic_username)
|
||||||
|
|
22
cps/web.py
22
cps/web.py
|
@ -760,10 +760,26 @@ def list_books():
|
||||||
sort = request.args.get("sort", "id")
|
sort = request.args.get("sort", "id")
|
||||||
order = request.args.get("order", "").lower()
|
order = request.args.get("order", "").lower()
|
||||||
state = None
|
state = None
|
||||||
|
join = tuple()
|
||||||
|
|
||||||
if sort == "state":
|
if sort == "state":
|
||||||
state = json.loads(request.args.get("state", "[]"))
|
state = json.loads(request.args.get("state", "[]"))
|
||||||
if sort != "state" and order:
|
elif sort == "tags":
|
||||||
|
order = [db.Tags.name.asc()] if order == "asc" else [db.Tags.name.desc()]
|
||||||
|
join = db.books_tags_link,db.Books.id == db.books_tags_link.c.book, db.Tags
|
||||||
|
elif sort == "series":
|
||||||
|
order = [db.Series.name.asc()] if order == "asc" else [db.Series.name.desc()]
|
||||||
|
join = db.books_series_link,db.Books.id == db.books_series_link.c.book, db.Series
|
||||||
|
elif sort == "publishers":
|
||||||
|
order = [db.Publishers.name.asc()] if order == "asc" else [db.Publishers.name.desc()]
|
||||||
|
join = db.books_publishers_link,db.Books.id == db.books_publishers_link.c.book, db.Publishers
|
||||||
|
elif sort == "authors":
|
||||||
|
order = [db.Authors.name.asc()] if order == "asc" else [db.Authors.name.desc()]
|
||||||
|
join = db.books_authors_link,db.Books.id == db.books_authors_link.c.book, db.Authors
|
||||||
|
elif sort == "languages":
|
||||||
|
order = [db.Languages.lang_code.asc()] if order == "asc" else [db.Languages.lang_code.desc()]
|
||||||
|
join = db.books_languages_link,db.Books.id == db.books_languages_link.c.book, db.Languages
|
||||||
|
elif order and sort in ["sort", "title", "authors_sort", "series_index"]:
|
||||||
order = [text(sort + " " + order)]
|
order = [text(sort + " " + order)]
|
||||||
elif not state:
|
elif not state:
|
||||||
order = [db.Books.timestamp.desc()]
|
order = [db.Books.timestamp.desc()]
|
||||||
|
@ -778,9 +794,9 @@ def list_books():
|
||||||
books = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).all()
|
books = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).all()
|
||||||
entries = calibre_db.get_checkbox_sorted(books, state, off, limit,order)
|
entries = calibre_db.get_checkbox_sorted(books, state, off, limit,order)
|
||||||
elif search:
|
elif search:
|
||||||
entries, filtered_count, __ = calibre_db.get_search_results(search, off, order, limit)
|
entries, filtered_count, __ = calibre_db.get_search_results(search, off, order, limit, *join)
|
||||||
else:
|
else:
|
||||||
entries, __, __ = calibre_db.fill_indexpage((int(off) / (int(limit)) + 1), limit, db.Books, True, order)
|
entries, __, __ = calibre_db.fill_indexpage((int(off) / (int(limit)) + 1), limit, db.Books, True, order, *join)
|
||||||
|
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
for index in range(0, len(entry.languages)):
|
for index in range(0, len(entry.languages)):
|
||||||
|
|
539
messages.pot
539
messages.pot
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user