mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-19 06:30:29 +00:00
Merge branch 'master' of https://github.com/janeczku/calibre-web
This commit is contained in:
commit
0db837c0ce
@ -1370,11 +1370,11 @@ def _delete_user(content):
|
|||||||
if content.name != "Guest":
|
if content.name != "Guest":
|
||||||
# Delete all books in shelfs belonging to user, all shelfs of user, downloadstat of user, read status
|
# Delete all books in shelfs belonging to user, all shelfs of user, downloadstat of user, read status
|
||||||
# and user itself
|
# and user itself
|
||||||
ub.session.query(ub.ReadBook).filter(ub.User.id == ub.ReadBook.user_id).delete()
|
ub.session.query(ub.ReadBook).filter(content.id == ub.ReadBook.user_id).delete()
|
||||||
ub.session.query(ub.Downloads).filter(ub.User.id == ub.Downloads.user_id).delete()
|
ub.session.query(ub.Downloads).filter(content.id == ub.Downloads.user_id).delete()
|
||||||
for us in ub.session.query(ub.Shelf).filter(ub.User.id == ub.Shelf.user_id):
|
for us in ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id):
|
||||||
ub.session.query(ub.BookShelf).filter(us.id == ub.BookShelf.shelf).delete()
|
ub.session.query(ub.BookShelf).filter(us.id == ub.BookShelf.shelf).delete()
|
||||||
ub.session.query(ub.Shelf).filter(ub.User.id == ub.Shelf.user_id).delete()
|
ub.session.query(ub.Shelf).filter(content.id == ub.Shelf.user_id).delete()
|
||||||
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
|
ub.session.query(ub.User).filter(ub.User.id == content.id).delete()
|
||||||
ub.session_commit()
|
ub.session_commit()
|
||||||
log.info(u"User {} deleted".format(content.name))
|
log.info(u"User {} deleted".format(content.name))
|
||||||
|
@ -20,6 +20,9 @@ from __future__ import division, print_function, unicode_literals
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
from sqlalchemy import __version__ as sql_version
|
||||||
|
|
||||||
|
sqlalchemy_version2 = ([int(x) for x in sql_version.split('.')] >= [2,0,0])
|
||||||
|
|
||||||
# if installed via pip this variable is set to true (empty file with name .HOMEDIR present)
|
# if installed via pip this variable is set to true (empty file with name .HOMEDIR present)
|
||||||
HOME_CONFIG = os.path.isfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.HOMEDIR'))
|
HOME_CONFIG = os.path.isfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.HOMEDIR'))
|
||||||
|
@ -690,6 +690,8 @@ class CalibreDB():
|
|||||||
randm = false()
|
randm = false()
|
||||||
off = int(int(pagesize) * (page - 1))
|
off = int(int(pagesize) * (page - 1))
|
||||||
query = self.session.query(database)
|
query = self.session.query(database)
|
||||||
|
if len(join) == 6:
|
||||||
|
query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5])
|
||||||
if len(join) == 3:
|
if len(join) == 3:
|
||||||
query = query.outerjoin(join[0], join[1]).outerjoin(join[2])
|
query = query.outerjoin(join[0], join[1]).outerjoin(join[2])
|
||||||
elif len(join) == 2:
|
elif len(join) == 2:
|
||||||
@ -755,6 +757,8 @@ class CalibreDB():
|
|||||||
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 + "%")))
|
||||||
query = self.session.query(Books)
|
query = self.session.query(Books)
|
||||||
|
if len(join) == 6:
|
||||||
|
query = query.outerjoin(join[0], join[1]).outerjoin(join[2]).outerjoin(join[3], join[4]).outerjoin(join[5])
|
||||||
if len(join) == 3:
|
if len(join) == 3:
|
||||||
query = query.outerjoin(join[0], join[1]).outerjoin(join[2])
|
query = query.outerjoin(join[0], join[1]).outerjoin(join[2])
|
||||||
elif len(join) == 2:
|
elif len(join) == 2:
|
||||||
|
15
cps/kobo.py
15
cps/kobo.py
@ -44,11 +44,11 @@ from werkzeug.datastructures import Headers
|
|||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.sql.expression import and_, or_
|
from sqlalchemy.sql.expression import and_, or_
|
||||||
from sqlalchemy.exc import StatementError
|
from sqlalchemy.exc import StatementError
|
||||||
from sqlalchemy import __version__ as sql_version
|
|
||||||
from sqlalchemy.sql import select
|
from sqlalchemy.sql import select
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub
|
from . import config, logger, kobo_auth, db, calibre_db, helper, shelf as shelf_lib, ub
|
||||||
|
from .constants import sqlalchemy_version2
|
||||||
from .helper import get_download_link
|
from .helper import get_download_link
|
||||||
from .services import SyncToken as SyncToken
|
from .services import SyncToken as SyncToken
|
||||||
from .web import download_required
|
from .web import download_required
|
||||||
@ -66,7 +66,6 @@ kobo_auth.register_url_value_preprocessor(kobo)
|
|||||||
|
|
||||||
log = logger.create()
|
log = logger.create()
|
||||||
|
|
||||||
sql2 = ([int(x) for x in sql_version.split('.')] >= [2,0,0])
|
|
||||||
|
|
||||||
def get_store_url_for_current_request():
|
def get_store_url_for_current_request():
|
||||||
# Programmatically modify the current url to point to the official Kobo store
|
# Programmatically modify the current url to point to the official Kobo store
|
||||||
@ -159,7 +158,7 @@ def HandleSyncRequest():
|
|||||||
only_kobo_shelves = current_user.kobo_only_shelves_sync
|
only_kobo_shelves = current_user.kobo_only_shelves_sync
|
||||||
|
|
||||||
if only_kobo_shelves:
|
if only_kobo_shelves:
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
changed_entries = select(db.Books,
|
changed_entries = select(db.Books,
|
||||||
ub.ArchivedBook.last_modified,
|
ub.ArchivedBook.last_modified,
|
||||||
ub.BookShelf.date_added,
|
ub.BookShelf.date_added,
|
||||||
@ -183,7 +182,7 @@ def HandleSyncRequest():
|
|||||||
.distinct()
|
.distinct()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
changed_entries = select(db.Books, ub.ArchivedBook.last_modified, ub.ArchivedBook.is_archived)
|
changed_entries = select(db.Books, ub.ArchivedBook.last_modified, ub.ArchivedBook.is_archived)
|
||||||
else:
|
else:
|
||||||
changed_entries = calibre_db.session.query(db.Books,
|
changed_entries = calibre_db.session.query(db.Books,
|
||||||
@ -202,7 +201,7 @@ def HandleSyncRequest():
|
|||||||
changed_entries = changed_entries.filter(db.Books.id > sync_token.books_last_id)
|
changed_entries = changed_entries.filter(db.Books.id > sync_token.books_last_id)
|
||||||
|
|
||||||
reading_states_in_new_entitlements = []
|
reading_states_in_new_entitlements = []
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT))
|
books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT))
|
||||||
else:
|
else:
|
||||||
books = changed_entries.limit(SYNC_ITEM_LIMIT)
|
books = changed_entries.limit(SYNC_ITEM_LIMIT)
|
||||||
@ -246,7 +245,7 @@ def HandleSyncRequest():
|
|||||||
|
|
||||||
new_books_last_created = max(ts_created, new_books_last_created)
|
new_books_last_created = max(ts_created, new_books_last_created)
|
||||||
|
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
max_change = calibre_db.session.execute(changed_entries
|
max_change = calibre_db.session.execute(changed_entries
|
||||||
.filter(ub.ArchivedBook.is_archived)
|
.filter(ub.ArchivedBook.is_archived)
|
||||||
.order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\
|
.order_by(func.datetime(ub.ArchivedBook.last_modified).desc()))\
|
||||||
@ -260,7 +259,7 @@ def HandleSyncRequest():
|
|||||||
new_archived_last_modified = max(new_archived_last_modified, max_change)
|
new_archived_last_modified = max(new_archived_last_modified, max_change)
|
||||||
|
|
||||||
# no. of books returned
|
# no. of books returned
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
entries = calibre_db.session.execute(changed_entries).all()
|
entries = calibre_db.session.execute(changed_entries).all()
|
||||||
book_count = len(entries)
|
book_count = len(entries)
|
||||||
else:
|
else:
|
||||||
@ -697,7 +696,7 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False):
|
|||||||
})
|
})
|
||||||
extra_filters.append(ub.Shelf.kobo_sync)
|
extra_filters.append(ub.Shelf.kobo_sync)
|
||||||
|
|
||||||
if sql2:
|
if sqlalchemy_version2:
|
||||||
shelflist = ub.session.execute(select(ub.Shelf).outerjoin(ub.BookShelf).filter(
|
shelflist = ub.session.execute(select(ub.Shelf).outerjoin(ub.BookShelf).filter(
|
||||||
or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified,
|
or_(func.datetime(ub.Shelf.last_modified) > sync_token.tags_last_modified,
|
||||||
func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified),
|
func.datetime(ub.BookShelf.date_added) > sync_token.tags_last_modified),
|
||||||
|
52
cps/shelf.py
52
cps/shelf.py
@ -72,10 +72,9 @@ def add_to_shelf(shelf_id, book_id):
|
|||||||
|
|
||||||
if not check_shelf_edit_permissions(shelf):
|
if not check_shelf_edit_permissions(shelf):
|
||||||
if not xhr:
|
if not xhr:
|
||||||
flash(_(u"Sorry you are not allowed to add a book to the the shelf: %(shelfname)s", shelfname=shelf.name),
|
flash(_(u"Sorry you are not allowed to add a book to that shelf"), category="error")
|
||||||
category="error")
|
|
||||||
return redirect(url_for('web.index'))
|
return redirect(url_for('web.index'))
|
||||||
return "Sorry you are not allowed to add a book to the the shelf: %s" % shelf.name, 403
|
return "Sorry you are not allowed to add a book to the that shelf", 403
|
||||||
|
|
||||||
book_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id,
|
book_in_shelf = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id,
|
||||||
ub.BookShelf.book_id == book_id).first()
|
ub.BookShelf.book_id == book_id).first()
|
||||||
@ -228,18 +227,21 @@ def remove_from_shelf(shelf_id, book_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def create_shelf():
|
def create_shelf():
|
||||||
shelf = ub.Shelf()
|
shelf = ub.Shelf()
|
||||||
return create_edit_shelf(shelf, title=_(u"Create a Shelf"), page="shelfcreate")
|
return create_edit_shelf(shelf, page_title=_(u"Create a Shelf"), page="shelfcreate")
|
||||||
|
|
||||||
|
|
||||||
@shelf.route("/shelf/edit/<int:shelf_id>", methods=["GET", "POST"])
|
@shelf.route("/shelf/edit/<int:shelf_id>", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def edit_shelf(shelf_id):
|
def edit_shelf(shelf_id):
|
||||||
shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
shelf = ub.session.query(ub.Shelf).filter(ub.Shelf.id == shelf_id).first()
|
||||||
return create_edit_shelf(shelf, title=_(u"Edit a shelf"), page="shelfedit", shelf_id=shelf_id)
|
if not check_shelf_edit_permissions(shelf):
|
||||||
|
flash(_(u"Sorry you are not allowed to edit this shelf"), category="error")
|
||||||
|
return redirect(url_for('web.index'))
|
||||||
|
return create_edit_shelf(shelf, page_title=_(u"Edit a shelf"), page="shelfedit", shelf_id=shelf_id)
|
||||||
|
|
||||||
|
|
||||||
# if shelf ID is set, we are editing a shelf
|
# if shelf ID is set, we are editing a shelf
|
||||||
def create_edit_shelf(shelf, title, page, shelf_id=False):
|
def create_edit_shelf(shelf, page_title, page, shelf_id=False):
|
||||||
sync_only_selected_shelves = current_user.kobo_only_shelves_sync
|
sync_only_selected_shelves = current_user.kobo_only_shelves_sync
|
||||||
# calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id).filter(ub.Shelf.kobo_sync).count()
|
# calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id).filter(ub.Shelf.kobo_sync).count()
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
@ -247,20 +249,20 @@ def create_edit_shelf(shelf, title, page, shelf_id=False):
|
|||||||
shelf.is_public = 1 if to_save.get("is_public") else 0
|
shelf.is_public = 1 if to_save.get("is_public") else 0
|
||||||
if config.config_kobo_sync:
|
if config.config_kobo_sync:
|
||||||
shelf.kobo_sync = True if to_save.get("kobo_sync") else False
|
shelf.kobo_sync = True if to_save.get("kobo_sync") else False
|
||||||
|
shelf_title = to_save.get("title", "")
|
||||||
if check_shelf_is_unique(shelf, to_save, shelf_id):
|
if check_shelf_is_unique(shelf, shelf_title, shelf_id):
|
||||||
shelf.name = to_save["title"]
|
shelf.name = shelf_title
|
||||||
if not shelf_id:
|
if not shelf_id:
|
||||||
shelf.user_id = int(current_user.id)
|
shelf.user_id = int(current_user.id)
|
||||||
ub.session.add(shelf)
|
ub.session.add(shelf)
|
||||||
shelf_action = "created"
|
shelf_action = "created"
|
||||||
flash_text = _(u"Shelf %(title)s created", title=to_save["title"])
|
flash_text = _(u"Shelf %(title)s created", title=shelf_title)
|
||||||
else:
|
else:
|
||||||
shelf_action = "changed"
|
shelf_action = "changed"
|
||||||
flash_text = _(u"Shelf %(title)s changed", title=to_save["title"])
|
flash_text = _(u"Shelf %(title)s changed", title=shelf_title)
|
||||||
try:
|
try:
|
||||||
ub.session.commit()
|
ub.session.commit()
|
||||||
log.info(u"Shelf {} {}".format(to_save["title"], shelf_action))
|
log.info(u"Shelf {} {}".format(shelf_title, shelf_action))
|
||||||
flash(flash_text, category="success")
|
flash(flash_text, category="success")
|
||||||
return redirect(url_for('shelf.show_shelf', shelf_id=shelf.id))
|
return redirect(url_for('shelf.show_shelf', shelf_id=shelf.id))
|
||||||
except (OperationalError, InvalidRequestError) as ex:
|
except (OperationalError, InvalidRequestError) as ex:
|
||||||
@ -274,37 +276,37 @@ def create_edit_shelf(shelf, title, page, shelf_id=False):
|
|||||||
flash(_(u"There was an error"), category="error")
|
flash(_(u"There was an error"), category="error")
|
||||||
return render_title_template('shelf_edit.html',
|
return render_title_template('shelf_edit.html',
|
||||||
shelf=shelf,
|
shelf=shelf,
|
||||||
title=title,
|
title=page_title,
|
||||||
page=page,
|
page=page,
|
||||||
kobo_sync_enabled=config.config_kobo_sync,
|
kobo_sync_enabled=config.config_kobo_sync,
|
||||||
sync_only_selected_shelves=sync_only_selected_shelves)
|
sync_only_selected_shelves=sync_only_selected_shelves)
|
||||||
|
|
||||||
|
|
||||||
def check_shelf_is_unique(shelf, to_save, shelf_id=False):
|
def check_shelf_is_unique(shelf, title, shelf_id=False):
|
||||||
if shelf_id:
|
if shelf_id:
|
||||||
ident = ub.Shelf.id != shelf_id
|
ident = ub.Shelf.id != shelf_id
|
||||||
else:
|
else:
|
||||||
ident = true()
|
ident = true()
|
||||||
if shelf.is_public == 1:
|
if shelf.is_public == 1:
|
||||||
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
||||||
.filter((ub.Shelf.name == to_save["title"]) & (ub.Shelf.is_public == 1)) \
|
.filter((ub.Shelf.name == title) & (ub.Shelf.is_public == 1)) \
|
||||||
.filter(ident) \
|
.filter(ident) \
|
||||||
.first() is None
|
.first() is None
|
||||||
|
|
||||||
if not is_shelf_name_unique:
|
if not is_shelf_name_unique:
|
||||||
log.error("A public shelf with the name '{}' already exists.".format(to_save["title"]))
|
log.error("A public shelf with the name '{}' already exists.".format(title))
|
||||||
flash(_(u"A public shelf with the name '%(title)s' already exists.", title=to_save["title"]),
|
flash(_(u"A public shelf with the name '%(title)s' already exists.", title=title),
|
||||||
category="error")
|
category="error")
|
||||||
else:
|
else:
|
||||||
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
is_shelf_name_unique = ub.session.query(ub.Shelf) \
|
||||||
.filter((ub.Shelf.name == to_save["title"]) & (ub.Shelf.is_public == 0) &
|
.filter((ub.Shelf.name == title) & (ub.Shelf.is_public == 0) &
|
||||||
(ub.Shelf.user_id == int(current_user.id))) \
|
(ub.Shelf.user_id == int(current_user.id))) \
|
||||||
.filter(ident) \
|
.filter(ident) \
|
||||||
.first() is None
|
.first() is None
|
||||||
|
|
||||||
if not is_shelf_name_unique:
|
if not is_shelf_name_unique:
|
||||||
log.error("A private shelf with the name '{}' already exists.".format(to_save["title"]))
|
log.error("A private shelf with the name '{}' already exists.".format(title))
|
||||||
flash(_(u"A private shelf with the name '%(title)s' already exists.", title=to_save["title"]),
|
flash(_(u"A private shelf with the name '%(title)s' already exists.", title=title),
|
||||||
category="error")
|
category="error")
|
||||||
return is_shelf_name_unique
|
return is_shelf_name_unique
|
||||||
|
|
||||||
@ -378,7 +380,9 @@ def order_shelf(shelf_id):
|
|||||||
|
|
||||||
|
|
||||||
def change_shelf_order(shelf_id, order):
|
def change_shelf_order(shelf_id, order):
|
||||||
result = calibre_db.session.query(db.Books).join(ub.BookShelf, ub.BookShelf.book_id == db.Books.id) \
|
result = calibre_db.session.query(db.Books).outerjoin(db.books_series_link,
|
||||||
|
db.Books.id == db.books_series_link.c.book)\
|
||||||
|
.outerjoin(db.Series).join(ub.BookShelf, ub.BookShelf.book_id == db.Books.id) \
|
||||||
.filter(ub.BookShelf.shelf == shelf_id).order_by(*order).all()
|
.filter(ub.BookShelf.shelf == shelf_id).order_by(*order).all()
|
||||||
for index, entry in enumerate(result):
|
for index, entry in enumerate(result):
|
||||||
book = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id) \
|
book = ub.session.query(ub.BookShelf).filter(ub.BookShelf.shelf == shelf_id) \
|
||||||
@ -408,9 +412,11 @@ def render_show_shelf(shelf_type, shelf_id, page_no, sort_param):
|
|||||||
if sort_param == 'old':
|
if sort_param == 'old':
|
||||||
change_shelf_order(shelf_id, [db.Books.timestamp])
|
change_shelf_order(shelf_id, [db.Books.timestamp])
|
||||||
if sort_param == 'authaz':
|
if sort_param == 'authaz':
|
||||||
change_shelf_order(shelf_id, [db.Books.author_sort.asc()])
|
change_shelf_order(shelf_id, [db.Books.author_sort.asc(), db.Series.name, db.Books.series_index])
|
||||||
if sort_param == 'authza':
|
if sort_param == 'authza':
|
||||||
change_shelf_order(shelf_id, [db.Books.author_sort.desc()])
|
change_shelf_order(shelf_id, [db.Books.author_sort.desc(),
|
||||||
|
db.Series.name.desc(),
|
||||||
|
db.Books.series_index.desc()])
|
||||||
page = "shelf.html"
|
page = "shelf.html"
|
||||||
pagesize = 0
|
pagesize = 0
|
||||||
else:
|
else:
|
||||||
|
@ -611,7 +611,10 @@ $(function() {
|
|||||||
if (xhr.status < 400) {
|
if (xhr.status < 400) {
|
||||||
$("#spinning_success").hide();
|
$("#spinning_success").hide();
|
||||||
clearInterval(rebootInterval);
|
clearInterval(rebootInterval);
|
||||||
handle_response(data.result);
|
if (data.result) {
|
||||||
|
handle_response(data.result);
|
||||||
|
data.result = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -661,33 +661,34 @@ function move_header_elements() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(".multi_selector").selectpicker();
|
$(".multi_selector").selectpicker();
|
||||||
|
if ($(".multi_head").length) {
|
||||||
if (! $._data($(".multi_head").get(0), "events") ) {
|
if (!$._data($(".multi_head").get(0), "events")) {
|
||||||
// Functions have to be here, otherwise the callbacks are not fired if visible columns are changed
|
// Functions have to be here, otherwise the callbacks are not fired if visible columns are changed
|
||||||
$(".multi_head").on("click", function () {
|
$(".multi_head").on("click", function () {
|
||||||
var val = $(this).data("set");
|
var val = $(this).data("set");
|
||||||
var field = $(this).data("name");
|
var field = $(this).data("name");
|
||||||
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
||||||
var values = $("#" + field).val();
|
var values = $("#" + field).val();
|
||||||
confirmDialog(
|
confirmDialog(
|
||||||
"restrictions",
|
"restrictions",
|
||||||
"GeneralChangeModal",
|
"GeneralChangeModal",
|
||||||
0,
|
0,
|
||||||
function () {
|
function () {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
method: "post",
|
method: "post",
|
||||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||||
data: {"pk": result, "value": values, "action": val},
|
data: {"pk": result, "value": values, "action": val},
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
handleListServerResponse(data);
|
handleListServerResponse(data);
|
||||||
},
|
},
|
||||||
error: function (data) {
|
error: function (data) {
|
||||||
handleListServerResponse([{type: "danger", message: data.responseText}])
|
handleListServerResponse([{type: "danger", message: data.responseText}])
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#user_delete_selection").click(function () {
|
$("#user_delete_selection").click(function () {
|
||||||
@ -699,38 +700,41 @@ function move_header_elements() {
|
|||||||
$("#select_default_language").on("change", function () {
|
$("#select_default_language").on("change", function () {
|
||||||
selectHeader(this, "default_language");
|
selectHeader(this, "default_language");
|
||||||
});
|
});
|
||||||
|
if ($(".check_head").length) {
|
||||||
if (! $._data($(".check_head").get(0), "events") ) {
|
if (!$._data($(".check_head").get(0), "events")) {
|
||||||
$(".check_head").on("change", function () {
|
$(".check_head").on("change", function () {
|
||||||
var val = $(this).data("set");
|
var val = $(this).data("set");
|
||||||
var name = $(this).data("name");
|
var name = $(this).data("name");
|
||||||
var data = $(this).data("val");
|
var data = $(this).data("val");
|
||||||
checkboxHeader(val, name, data);
|
checkboxHeader(val, name, data);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (! $._data($(".button_head").get(0), "events") ) {
|
if ($(".button_head").length) {
|
||||||
$(".button_head").on("click", function () {
|
if (!$._data($(".button_head").get(0), "events")) {
|
||||||
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
$(".button_head").on("click", function () {
|
||||||
confirmDialog(
|
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
||||||
"btndeluser",
|
confirmDialog(
|
||||||
"GeneralDeleteModal",
|
"btndeluser",
|
||||||
0,
|
"GeneralDeleteModal",
|
||||||
function () {
|
0,
|
||||||
$.ajax({
|
function () {
|
||||||
method: "post",
|
$.ajax({
|
||||||
url: window.location.pathname + "/../../ajax/deleteuser",
|
method: "post",
|
||||||
data: {"userid": result},
|
url: window.location.pathname + "/../../ajax/deleteuser",
|
||||||
success: function (data) {
|
data: {"userid": result},
|
||||||
selections = selections.filter((el) => !result.includes(el));
|
success: function (data) {
|
||||||
handleListServerResponse(data);
|
selections = selections.filter((el) => !result.includes(el));
|
||||||
},
|
handleListServerResponse(data);
|
||||||
error: function (data) {
|
},
|
||||||
handleListServerResponse([{type: "danger", message: data.responseText}])
|
error: function (data) {
|
||||||
},
|
handleListServerResponse([{type: "danger", message: data.responseText}])
|
||||||
});
|
},
|
||||||
}
|
});
|
||||||
);
|
}
|
||||||
});
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +67,14 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
{% for element in sidebar %}
|
{% for element in sidebar %}
|
||||||
{% if element['config_show'] %}
|
{% if element['config_show'] %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="show_{{element['visibility']}}" id="show_{{element['visibility']}}" {% if content.check_visibility(element['visibility']) %}checked{% endif %}>
|
<input type="checkbox" name="show_{{element['visibility']}}" id="show_{{element['visibility']}}" {% if content.check_visibility(element['visibility']) %}checked{% endif %}>
|
||||||
<label for="show_{{element['visibility']}}">{{element['show_text']}}</label>
|
<label for="show_{{element['visibility']}}">{{element['show_text']}}</label>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="checkbox" name="Show_detail_random" id="Show_detail_random" {% if content.show_detail_random() %}checked{% endif %}>
|
<input type="checkbox" name="Show_detail_random" id="Show_detail_random" {% if content.show_detail_random() %}checked{% endif %}>
|
||||||
<label for="Show_detail_random">{{_('Show Random Books in Detail View')}}</label>
|
<label for="Show_detail_random">{{_('Show Random Books in Detail View')}}</label>
|
||||||
@ -84,6 +83,7 @@
|
|||||||
<a href="#" id="get_user_tags" class="btn btn-default" data-id="{{content.id}}" data-toggle="modal" data-target="#restrictModal">{{_('Add Allowed/Denied Tags')}}</a>
|
<a href="#" id="get_user_tags" class="btn btn-default" data-id="{{content.id}}" data-toggle="modal" data-target="#restrictModal">{{_('Add Allowed/Denied Tags')}}</a>
|
||||||
<a href="#" id="get_user_column_values" data-id="{{content.id}}" class="btn btn-default" data-toggle="modal" data-target="#restrictModal">{{_('Add allowed/Denied Custom Column Values')}}</a>
|
<a href="#" id="get_user_column_values" data-id="{{content.id}}" class="btn btn-default" data-toggle="modal" data-target="#restrictModal">{{_('Add allowed/Denied Custom Column Values')}}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
{% if g.user and g.user.role_admin() and not profile %}
|
{% if g.user and g.user.role_admin() and not profile %}
|
||||||
@ -131,32 +131,32 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<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 %}
|
||||||
<div class="btn btn-default" data-back="{{ url_for('admin.admin') }}" id="back">{{_('Cancel')}}</div>
|
<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>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="modal_kobo_token" tabindex="-1" role="dialog" aria-labelledby="kobo_tokenModalLabel">
|
<div class="modal fade" id="modal_kobo_token" tabindex="-1" role="dialog" aria-labelledby="kobo_tokenModalLabel">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
<h4 class="modal-title" id="kobo_tokenModalLabel">{{_('Generate Kobo Auth URL')}}</h4>
|
<h4 class="modal-title" id="kobo_tokenModalLabel">{{_('Generate Kobo Auth URL')}}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">...</div>
|
<div class="modal-body">...</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" id="kobo_close" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button>
|
<button type="button" id="kobo_close" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block modal %}
|
{% block modal %}
|
||||||
|
51
cps/web.py
51
cps/web.py
@ -360,9 +360,9 @@ def get_sort_function(sort, data):
|
|||||||
if sort == 'old':
|
if sort == 'old':
|
||||||
order = [db.Books.timestamp]
|
order = [db.Books.timestamp]
|
||||||
if sort == 'authaz':
|
if sort == 'authaz':
|
||||||
order = [db.Books.author_sort.asc()]
|
order = [db.Books.author_sort.asc(), db.Series.name, db.Books.series_index]
|
||||||
if sort == 'authza':
|
if sort == 'authza':
|
||||||
order = [db.Books.author_sort.desc()]
|
order = [db.Books.author_sort.desc(), db.Series.name.desc(), db.Books.series_index.desc()]
|
||||||
if sort == 'seriesasc':
|
if sort == 'seriesasc':
|
||||||
order = [db.Books.series_index.asc()]
|
order = [db.Books.series_index.asc()]
|
||||||
if sort == 'seriesdesc':
|
if sort == 'seriesdesc':
|
||||||
@ -410,7 +410,10 @@ 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,
|
||||||
|
db.books_series_link,
|
||||||
|
db.Books.id == db.books_series_link.c.book,
|
||||||
|
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)
|
||||||
|
|
||||||
@ -509,8 +512,10 @@ def render_author_books(page, author_id, order):
|
|||||||
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"),
|
flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"),
|
||||||
category="error")
|
category="error")
|
||||||
return redirect(url_for("web.index"))
|
return redirect(url_for("web.index"))
|
||||||
|
if constants.sqlalchemy_version2:
|
||||||
author = calibre_db.session.query(db.Authors).get(author_id)
|
author = calibre_db.session.get(db.Authors, author_id)
|
||||||
|
else:
|
||||||
|
author = calibre_db.session.query(db.Authors).get(author_id)
|
||||||
author_name = author.name.replace('|', ',')
|
author_name = author.name.replace('|', ',')
|
||||||
|
|
||||||
author_info = None
|
author_info = None
|
||||||
@ -713,7 +718,8 @@ def render_prepare_search_form(cc):
|
|||||||
|
|
||||||
|
|
||||||
def render_search_results(term, offset=None, order=None, limit=None):
|
def render_search_results(term, offset=None, order=None, limit=None):
|
||||||
entries, result_count, pagination = calibre_db.get_search_results(term, offset, order, limit)
|
join = db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series
|
||||||
|
entries, result_count, pagination = calibre_db.get_search_results(term, offset, order, limit, *join)
|
||||||
return render_title_template('search.html',
|
return render_title_template('search.html',
|
||||||
searchterm=term,
|
searchterm=term,
|
||||||
pagination=pagination,
|
pagination=pagination,
|
||||||
@ -775,8 +781,10 @@ def list_books():
|
|||||||
order = [db.Publishers.name.asc()] if order == "asc" else [db.Publishers.name.desc()]
|
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
|
join = db.books_publishers_link,db.Books.id == db.books_publishers_link.c.book, db.Publishers
|
||||||
elif sort == "authors":
|
elif sort == "authors":
|
||||||
order = [db.Authors.name.asc()] if order == "asc" else [db.Authors.name.desc()]
|
order = [db.Authors.name.asc(), db.Series.name, db.Books.series_index] if order == "asc" \
|
||||||
join = db.books_authors_link,db.Books.id == db.books_authors_link.c.book, db.Authors
|
else [db.Authors.name.desc(), db.Series.name.desc(), db.Books.series_index.desc()]
|
||||||
|
join = db.books_authors_link, db.Books.id == db.books_authors_link.c.book, db.Authors, \
|
||||||
|
db.books_series_link, db.Books.id == db.books_series_link.c.book, db.Series
|
||||||
elif sort == "languages":
|
elif sort == "languages":
|
||||||
order = [db.Languages.lang_code.asc()] if order == "asc" else [db.Languages.lang_code.desc()]
|
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
|
join = db.books_languages_link,db.Books.id == db.books_languages_link.c.book, db.Languages
|
||||||
@ -793,7 +801,7 @@ def list_books():
|
|||||||
filtered_count = len(books)
|
filtered_count = len(books)
|
||||||
else:
|
else:
|
||||||
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, *join)
|
entries, filtered_count, __ = calibre_db.get_search_results(search, off, order, limit, *join)
|
||||||
else:
|
else:
|
||||||
@ -1242,7 +1250,9 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
|
|||||||
|
|
||||||
cc = get_cc_columns(filter_config_custom_read=True)
|
cc = get_cc_columns(filter_config_custom_read=True)
|
||||||
calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase)
|
calibre_db.session.connection().connection.connection.create_function("lower", 1, db.lcase)
|
||||||
q = calibre_db.session.query(db.Books).filter(calibre_db.common_filters(True))
|
q = calibre_db.session.query(db.Books).outerjoin(db.books_series_link, db.Books.id == db.books_series_link.c.book)\
|
||||||
|
.outerjoin(db.Series)\
|
||||||
|
.filter(calibre_db.common_filters(True))
|
||||||
|
|
||||||
# parse multiselects to a complete dict
|
# parse multiselects to a complete dict
|
||||||
tags = dict()
|
tags = dict()
|
||||||
@ -1587,15 +1597,14 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
|
|||||||
if to_save.get("password"):
|
if to_save.get("password"):
|
||||||
current_user.password = generate_password_hash(to_save["password"])
|
current_user.password = generate_password_hash(to_save["password"])
|
||||||
try:
|
try:
|
||||||
if to_save.get("allowed_tags", current_user.allowed_tags) != current_user.allowed_tags:
|
|
||||||
current_user.allowed_tags = to_save["allowed_tags"].strip()
|
|
||||||
if to_save.get("kindle_mail", current_user.kindle_mail) != current_user.kindle_mail:
|
if to_save.get("kindle_mail", current_user.kindle_mail) != current_user.kindle_mail:
|
||||||
current_user.kindle_mail = valid_email(to_save["kindle_mail"])
|
current_user.kindle_mail = valid_email(to_save["kindle_mail"])
|
||||||
if to_save.get("email", current_user.email) != current_user.email:
|
if to_save.get("email", current_user.email) != current_user.email:
|
||||||
current_user.email = check_email(to_save["email"])
|
current_user.email = check_email(to_save["email"])
|
||||||
if to_save.get("name", current_user.name) != current_user.name:
|
if current_user.role_admin():
|
||||||
# Query User name, if not existing, change
|
if to_save.get("name", current_user.name) != current_user.name:
|
||||||
current_user.name = check_username(to_save["name"])
|
# Query User name, if not existing, change
|
||||||
|
current_user.name = check_username(to_save["name"])
|
||||||
current_user.random_books = 1 if to_save.get("show_random") == "on" else 0
|
current_user.random_books = 1 if to_save.get("show_random") == "on" else 0
|
||||||
if to_save.get("default_language"):
|
if to_save.get("default_language"):
|
||||||
current_user.default_language = to_save["default_language"]
|
current_user.default_language = to_save["default_language"]
|
||||||
@ -1605,10 +1614,16 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
|
|||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
flash(str(ex), category="error")
|
flash(str(ex), category="error")
|
||||||
return render_title_template("user_edit.html", content=current_user,
|
return render_title_template("user_edit.html",
|
||||||
title=_(u"%(name)s's profile", name=current_user.name), page="me",
|
content=current_user,
|
||||||
|
translations=translations,
|
||||||
|
profile=1,
|
||||||
|
languages=languages,
|
||||||
|
title=_(u"%(name)s's profile", name=current_user.name),
|
||||||
|
page="me",
|
||||||
kobo_support=kobo_support,
|
kobo_support=kobo_support,
|
||||||
registered_oauth=local_oauth_check, oauth_status=oauth_status)
|
registered_oauth=local_oauth_check,
|
||||||
|
oauth_status=oauth_status)
|
||||||
|
|
||||||
val = 0
|
val = 0
|
||||||
for key, __ in to_save.items():
|
for key, __ in to_save.items():
|
||||||
|
Loading…
Reference in New Issue
Block a user