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": | ||||
|             # Delete all books in shelfs belonging to user, all shelfs of user, downloadstat of user, read status | ||||
|             # and user itself | ||||
|             ub.session.query(ub.ReadBook).filter(ub.User.id == ub.ReadBook.user_id).delete() | ||||
|             ub.session.query(ub.Downloads).filter(ub.User.id == ub.Downloads.user_id).delete() | ||||
|             for us in ub.session.query(ub.Shelf).filter(ub.User.id == ub.Shelf.user_id): | ||||
|             ub.session.query(ub.ReadBook).filter(content.id == ub.ReadBook.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(content.id == ub.Shelf.user_id): | ||||
|                 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_commit() | ||||
|             log.info(u"User {} deleted".format(content.name)) | ||||
|  |  | |||
|  | @ -20,6 +20,9 @@ from __future__ import division, print_function, unicode_literals | |||
| import sys | ||||
| import os | ||||
| 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) | ||||
| HOME_CONFIG = os.path.isfile(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.HOMEDIR')) | ||||
|  |  | |||
|  | @ -690,6 +690,8 @@ class CalibreDB(): | |||
|             randm = false() | ||||
|         off = int(int(pagesize) * (page - 1)) | ||||
|         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: | ||||
|             query = query.outerjoin(join[0], join[1]).outerjoin(join[2]) | ||||
|         elif len(join) == 2: | ||||
|  | @ -755,6 +757,8 @@ class CalibreDB(): | |||
|         for authorterm in authorterms: | ||||
|             q.append(Books.authors.any(func.lower(Authors.name).ilike("%" + authorterm + "%"))) | ||||
|         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: | ||||
|             query = query.outerjoin(join[0], join[1]).outerjoin(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.sql.expression import and_, or_ | ||||
| from sqlalchemy.exc import StatementError | ||||
| from sqlalchemy import __version__ as sql_version | ||||
| from sqlalchemy.sql import select | ||||
| import requests | ||||
| 
 | ||||
| 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 .services import SyncToken as SyncToken | ||||
| from .web import download_required | ||||
|  | @ -66,7 +66,6 @@ kobo_auth.register_url_value_preprocessor(kobo) | |||
| 
 | ||||
| log = logger.create() | ||||
| 
 | ||||
| sql2 = ([int(x) for x in sql_version.split('.')] >= [2,0,0]) | ||||
| 
 | ||||
| def get_store_url_for_current_request(): | ||||
|     # 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 | ||||
| 
 | ||||
|     if only_kobo_shelves: | ||||
|         if sql2: | ||||
|         if sqlalchemy_version2: | ||||
|             changed_entries = select(db.Books, | ||||
|                                      ub.ArchivedBook.last_modified, | ||||
|                                      ub.BookShelf.date_added, | ||||
|  | @ -183,7 +182,7 @@ def HandleSyncRequest(): | |||
|                 .distinct() | ||||
|         ) | ||||
|     else: | ||||
|         if sql2: | ||||
|         if sqlalchemy_version2: | ||||
|             changed_entries = select(db.Books, ub.ArchivedBook.last_modified, ub.ArchivedBook.is_archived) | ||||
|         else: | ||||
|             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) | ||||
| 
 | ||||
|     reading_states_in_new_entitlements = [] | ||||
|     if sql2: | ||||
|     if sqlalchemy_version2: | ||||
|         books = calibre_db.session.execute(changed_entries.limit(SYNC_ITEM_LIMIT)) | ||||
|     else: | ||||
|         books = changed_entries.limit(SYNC_ITEM_LIMIT) | ||||
|  | @ -246,7 +245,7 @@ def HandleSyncRequest(): | |||
| 
 | ||||
|         new_books_last_created = max(ts_created, new_books_last_created) | ||||
| 
 | ||||
|     if sql2: | ||||
|     if sqlalchemy_version2: | ||||
|         max_change = calibre_db.session.execute(changed_entries | ||||
|                                                 .filter(ub.ArchivedBook.is_archived) | ||||
|                                                 .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) | ||||
| 
 | ||||
|     # no. of books returned | ||||
|     if sql2: | ||||
|     if sqlalchemy_version2: | ||||
|         entries = calibre_db.session.execute(changed_entries).all() | ||||
|         book_count = len(entries) | ||||
|     else: | ||||
|  | @ -697,7 +696,7 @@ def sync_shelves(sync_token, sync_results, only_kobo_shelves=False): | |||
|             }) | ||||
|         extra_filters.append(ub.Shelf.kobo_sync) | ||||
| 
 | ||||
|     if sql2: | ||||
|     if sqlalchemy_version2: | ||||
|         shelflist = ub.session.execute(select(ub.Shelf).outerjoin(ub.BookShelf).filter( | ||||
|             or_(func.datetime(ub.Shelf.last_modified) > 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 xhr: | ||||
|             flash(_(u"Sorry you are not allowed to add a book to the the shelf: %(shelfname)s", shelfname=shelf.name), | ||||
|                   category="error") | ||||
|             flash(_(u"Sorry you are not allowed to add a book to that shelf"), category="error") | ||||
|             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, | ||||
|                                                           ub.BookShelf.book_id == book_id).first() | ||||
|  | @ -228,18 +227,21 @@ def remove_from_shelf(shelf_id, book_id): | |||
| @login_required | ||||
| def create_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"]) | ||||
| @login_required | ||||
| def edit_shelf(shelf_id): | ||||
|     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 | ||||
| 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 | ||||
|     # calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id).filter(ub.Shelf.kobo_sync).count() | ||||
|     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 | ||||
|         if config.config_kobo_sync: | ||||
|             shelf.kobo_sync = True if to_save.get("kobo_sync") else False | ||||
| 
 | ||||
|         if check_shelf_is_unique(shelf, to_save, shelf_id): | ||||
|             shelf.name = to_save["title"] | ||||
|         shelf_title = to_save.get("title", "") | ||||
|         if check_shelf_is_unique(shelf, shelf_title, shelf_id): | ||||
|             shelf.name = shelf_title | ||||
|             if not shelf_id: | ||||
|                 shelf.user_id = int(current_user.id) | ||||
|                 ub.session.add(shelf) | ||||
|                 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: | ||||
|                 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: | ||||
|                 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") | ||||
|                 return redirect(url_for('shelf.show_shelf', shelf_id=shelf.id)) | ||||
|             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") | ||||
|     return render_title_template('shelf_edit.html', | ||||
|                                  shelf=shelf, | ||||
|                                  title=title, | ||||
|                                  title=page_title, | ||||
|                                  page=page, | ||||
|                                  kobo_sync_enabled=config.config_kobo_sync, | ||||
|                                  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: | ||||
|         ident = ub.Shelf.id != shelf_id | ||||
|     else: | ||||
|         ident = true() | ||||
|     if shelf.is_public == 1: | ||||
|         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) \ | ||||
|                                    .first() is None | ||||
| 
 | ||||
|         if not is_shelf_name_unique: | ||||
|             log.error("A public shelf with the name '{}' already exists.".format(to_save["title"])) | ||||
|             flash(_(u"A public shelf with the name '%(title)s' already exists.", title=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=title), | ||||
|                   category="error") | ||||
|     else: | ||||
|         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))) \ | ||||
|                                    .filter(ident) \ | ||||
|                                    .first() is None | ||||
| 
 | ||||
|         if not is_shelf_name_unique: | ||||
|             log.error("A private shelf with the name '{}' already exists.".format(to_save["title"])) | ||||
|             flash(_(u"A private shelf with the name '%(title)s' already exists.", title=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=title), | ||||
|                   category="error") | ||||
|     return is_shelf_name_unique | ||||
| 
 | ||||
|  | @ -378,7 +380,9 @@ def order_shelf(shelf_id): | |||
| 
 | ||||
| 
 | ||||
| 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() | ||||
|     for index, entry in enumerate(result): | ||||
|         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': | ||||
|                 change_shelf_order(shelf_id, [db.Books.timestamp]) | ||||
|             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': | ||||
|                 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" | ||||
|             pagesize = 0 | ||||
|         else: | ||||
|  |  | |||
|  | @ -611,7 +611,10 @@ $(function() { | |||
|                             if (xhr.status < 400) { | ||||
|                                 $("#spinning_success").hide(); | ||||
|                                 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(); | ||||
| 
 | ||||
|     if (! $._data($(".multi_head").get(0), "events") ) { | ||||
|         // Functions have to be here, otherwise the callbacks are not fired if visible columns are changed
 | ||||
|         $(".multi_head").on("click", function () { | ||||
|             var val = $(this).data("set"); | ||||
|             var field = $(this).data("name"); | ||||
|             var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id); | ||||
|             var values = $("#" + field).val(); | ||||
|             confirmDialog( | ||||
|                 "restrictions", | ||||
|                 "GeneralChangeModal", | ||||
|                 0, | ||||
|                 function () { | ||||
|                     $.ajax({ | ||||
|                         method: "post", | ||||
|                         url: window.location.pathname + "/../../ajax/editlistusers/" + field, | ||||
|                         data: {"pk": result, "value": values, "action": val}, | ||||
|                         success: function (data) { | ||||
|                             handleListServerResponse(data); | ||||
|                         }, | ||||
|                         error: function (data) { | ||||
|                             handleListServerResponse([{type: "danger", message: data.responseText}]) | ||||
|                         }, | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         }); | ||||
|     if ($(".multi_head").length) { | ||||
|         if (!$._data($(".multi_head").get(0), "events")) { | ||||
|             // Functions have to be here, otherwise the callbacks are not fired if visible columns are changed
 | ||||
|             $(".multi_head").on("click", function () { | ||||
|                 var val = $(this).data("set"); | ||||
|                 var field = $(this).data("name"); | ||||
|                 var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id); | ||||
|                 var values = $("#" + field).val(); | ||||
|                 confirmDialog( | ||||
|                     "restrictions", | ||||
|                     "GeneralChangeModal", | ||||
|                     0, | ||||
|                     function () { | ||||
|                         $.ajax({ | ||||
|                             method: "post", | ||||
|                             url: window.location.pathname + "/../../ajax/editlistusers/" + field, | ||||
|                             data: {"pk": result, "value": values, "action": val}, | ||||
|                             success: function (data) { | ||||
|                                 handleListServerResponse(data); | ||||
|                             }, | ||||
|                             error: function (data) { | ||||
|                                 handleListServerResponse([{type: "danger", message: data.responseText}]) | ||||
|                             }, | ||||
|                         }); | ||||
|                     } | ||||
|                 ); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     $("#user_delete_selection").click(function () { | ||||
|  | @ -699,38 +700,41 @@ function move_header_elements() { | |||
|     $("#select_default_language").on("change", function () { | ||||
|         selectHeader(this, "default_language"); | ||||
|     }); | ||||
| 
 | ||||
|     if (! $._data($(".check_head").get(0), "events") ) { | ||||
|         $(".check_head").on("change", function () { | ||||
|             var val = $(this).data("set"); | ||||
|             var name = $(this).data("name"); | ||||
|             var data = $(this).data("val"); | ||||
|             checkboxHeader(val, name, data); | ||||
|         }); | ||||
|     if ($(".check_head").length) { | ||||
|         if (!$._data($(".check_head").get(0), "events")) { | ||||
|             $(".check_head").on("change", function () { | ||||
|                 var val = $(this).data("set"); | ||||
|                 var name = $(this).data("name"); | ||||
|                 var data = $(this).data("val"); | ||||
|                 checkboxHeader(val, name, data); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|     if (! $._data($(".button_head").get(0), "events") ) { | ||||
|         $(".button_head").on("click", function () { | ||||
|             var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id); | ||||
|             confirmDialog( | ||||
|                 "btndeluser", | ||||
|                 "GeneralDeleteModal", | ||||
|                 0, | ||||
|                 function () { | ||||
|                     $.ajax({ | ||||
|                         method: "post", | ||||
|                         url: window.location.pathname + "/../../ajax/deleteuser", | ||||
|                         data: {"userid": result}, | ||||
|                         success: function (data) { | ||||
|                             selections = selections.filter((el) => !result.includes(el)); | ||||
|                             handleListServerResponse(data); | ||||
|                         }, | ||||
|                         error: function (data) { | ||||
|                             handleListServerResponse([{type: "danger", message: data.responseText}]) | ||||
|                         }, | ||||
|                     }); | ||||
|                 } | ||||
|             ); | ||||
|         }); | ||||
|     if ($(".button_head").length) { | ||||
|         if (!$._data($(".button_head").get(0), "events")) { | ||||
|             $(".button_head").on("click", function () { | ||||
|                 var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id); | ||||
|                 confirmDialog( | ||||
|                     "btndeluser", | ||||
|                     "GeneralDeleteModal", | ||||
|                     0, | ||||
|                     function () { | ||||
|                         $.ajax({ | ||||
|                             method: "post", | ||||
|                             url: window.location.pathname + "/../../ajax/deleteuser", | ||||
|                             data: {"userid": result}, | ||||
|                             success: function (data) { | ||||
|                                 selections = selections.filter((el) => !result.includes(el)); | ||||
|                                 handleListServerResponse(data); | ||||
|                             }, | ||||
|                             error: function (data) { | ||||
|                                 handleListServerResponse([{type: "danger", message: data.responseText}]) | ||||
|                             }, | ||||
|                         }); | ||||
|                     } | ||||
|                 ); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -67,15 +67,14 @@ | |||
|     </div> | ||||
|     {% endif %} | ||||
|     <div class="col-sm-6"> | ||||
|         {% for element in sidebar %} | ||||
|           {% if element['config_show'] %} | ||||
|             <div class="form-group"> | ||||
|               <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> | ||||
|             </div> | ||||
|           {% endif %} | ||||
|         {% endfor %} | ||||
| 
 | ||||
|     {% for element in sidebar %} | ||||
|       {% if element['config_show'] %} | ||||
|         <div class="form-group"> | ||||
|           <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> | ||||
|         </div> | ||||
|       {% endif %} | ||||
|     {% endfor %} | ||||
|       <div class="form-group"> | ||||
|           <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> | ||||
|  | @ -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_column_values" data-id="{{content.id}}" class="btn btn-default" data-toggle="modal" data-target="#restrictModal">{{_('Add allowed/Denied Custom Column Values')}}</a> | ||||
|       {% endif %} | ||||
|       </div> | ||||
|     </div> | ||||
|       <div class="col-sm-6"> | ||||
|     {% if g.user and g.user.role_admin() and not profile %} | ||||
|  | @ -131,32 +131,32 @@ | |||
|     </div> | ||||
|     {% endif %} | ||||
|     </div> | ||||
|       <div class="col-sm-12"> | ||||
|     <div id="user_submit" class="btn btn-default">{{_('Save')}}</div> | ||||
|     {% if not profile %} | ||||
|       <div class="btn btn-default" data-back="{{ url_for('admin.admin') }}" id="back">{{_('Cancel')}}</div> | ||||
|     {% endif %} | ||||
|     {% 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> | ||||
|     {% endif %} | ||||
|     <div class="col-sm-12"> | ||||
|       <div id="user_submit" class="btn btn-default">{{_('Save')}}</div> | ||||
|       {% if not profile %} | ||||
|         <div class="btn btn-default" data-back="{{ url_for('admin.admin') }}" id="back">{{_('Cancel')}}</div> | ||||
|       {% endif %} | ||||
|       {% 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> | ||||
|       {% endif %} | ||||
|     </div> | ||||
|   </form> | ||||
| </div> | ||||
| 
 | ||||
|     <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-content"> | ||||
|           <div class="modal-header"> | ||||
|             <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> | ||||
|           </div> | ||||
|           <div class="modal-body">...</div> | ||||
|           <div class="modal-footer"> | ||||
|             <button type="button" id="kobo_close" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button> | ||||
|           </div> | ||||
|         </div> | ||||
| <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-content"> | ||||
|       <div class="modal-header"> | ||||
|         <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> | ||||
|       </div> | ||||
|       <div class="modal-body">...</div> | ||||
|       <div class="modal-footer"> | ||||
|         <button type="button" id="kobo_close" class="btn btn-default" data-dismiss="modal">{{_('Close')}}</button> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
| {% block modal %} | ||||
|  |  | |||
							
								
								
									
										51
									
								
								cps/web.py
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								cps/web.py
									
									
									
									
									
								
							|  | @ -360,9 +360,9 @@ def get_sort_function(sort, data): | |||
|     if sort == 'old': | ||||
|         order = [db.Books.timestamp] | ||||
|     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': | ||||
|         order = [db.Books.author_sort.desc()] | ||||
|         order = [db.Books.author_sort.desc(), db.Series.name.desc(), db.Books.series_index.desc()] | ||||
|     if sort == 'seriesasc': | ||||
|         order = [db.Books.series_index.asc()] | ||||
|     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) | ||||
|     else: | ||||
|         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, | ||||
|                                      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"), | ||||
|               category="error") | ||||
|         return redirect(url_for("web.index")) | ||||
| 
 | ||||
|     author = calibre_db.session.query(db.Authors).get(author_id) | ||||
|     if constants.sqlalchemy_version2: | ||||
|         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_info = None | ||||
|  | @ -713,7 +718,8 @@ def render_prepare_search_form(cc): | |||
| 
 | ||||
| 
 | ||||
| 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', | ||||
|                                  searchterm=term, | ||||
|                                  pagination=pagination, | ||||
|  | @ -775,8 +781,10 @@ def list_books(): | |||
|         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 | ||||
|         order = [db.Authors.name.asc(), db.Series.name, db.Books.series_index] if order == "asc" \ | ||||
|             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": | ||||
|         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 | ||||
|  | @ -793,7 +801,7 @@ def list_books(): | |||
|             filtered_count = len(books) | ||||
|         else: | ||||
|             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: | ||||
|         entries, filtered_count, __ = calibre_db.get_search_results(search, off, order, limit, *join) | ||||
|     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) | ||||
|     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 | ||||
|     tags = dict() | ||||
|  | @ -1587,15 +1597,14 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations, | |||
|         if to_save.get("password"): | ||||
|             current_user.password = generate_password_hash(to_save["password"]) | ||||
|     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: | ||||
|             current_user.kindle_mail = valid_email(to_save["kindle_mail"]) | ||||
|         if to_save.get("email", current_user.email) != current_user.email: | ||||
|             current_user.email = check_email(to_save["email"]) | ||||
|         if to_save.get("name", current_user.name) != current_user.name: | ||||
|             # Query User name, if not existing, change | ||||
|             current_user.name = check_username(to_save["name"]) | ||||
|         if current_user.role_admin(): | ||||
|             if to_save.get("name", current_user.name) != current_user.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 | ||||
|         if to_save.get("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: | ||||
|         flash(str(ex), category="error") | ||||
|         return render_title_template("user_edit.html", content=current_user, | ||||
|                                      title=_(u"%(name)s's profile", name=current_user.name), page="me", | ||||
|         return render_title_template("user_edit.html", | ||||
|                                      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, | ||||
|                                      registered_oauth=local_oauth_check, oauth_status=oauth_status) | ||||
|                                      registered_oauth=local_oauth_check, | ||||
|                                      oauth_status=oauth_status) | ||||
| 
 | ||||
|     val = 0 | ||||
|     for key, __ in to_save.items(): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user