Merge branch 'master' into Develop

This commit is contained in:
Ozzie Isaacs 2021-05-28 18:22:43 +02:00
commit 59987ed359
5 changed files with 86 additions and 11 deletions

View File

@ -2,7 +2,12 @@
Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing [Calibre](https://calibre-ebook.com) database. Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing [Calibre](https://calibre-ebook.com) database.
![GitHub License](https://img.shields.io/github/license/janeczku/calibre-web) ![GitHub Downloads](https://img.shields.io/github/downloads/janeczku/calibre-web/total) ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github) [![Discord](https://img.shields.io/discord/838810113564344381?label=Discord&logo=discord)](https://discord.gg/h2VsJ2NEfB) [![GitHub License](https://img.shields.io/github/license/janeczku/calibre-web?style=flat-square)](https://github.com/janeczku/calibre-web/blob/master/LICENSE)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/janeczku/calibre-web?logo=github&style=flat-square&label=commits)]()
[![GitHub all releases](https://img.shields.io/github/downloads/janeczku/calibre-web/total?logo=github&style=flat-square)](https://github.com/janeczku/calibre-web/releases)
[![PyPI](https://img.shields.io/pypi/v/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/calibreweb?logo=pypi&logoColor=fff&style=flat-square)](https://pypi.org/project/calibreweb/)
[![Discord](https://img.shields.io/discord/838810113564344381?label=Discord&logo=discord&style=flat-square)](https://discord.gg/h2VsJ2NEfB)
*This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.* *This software is a fork of [library](https://github.com/mutschler/calibreserver) and licensed under the GPL v3 License.*

View File

@ -1148,11 +1148,15 @@ def edit_list_book(param):
'newValue': ' & '.join([author.replace('|',',') for author in input_authors])}), 'newValue': ' & '.join([author.replace('|',',') for author in input_authors])}),
mimetype='application/json') mimetype='application/json')
book.last_modified = datetime.utcnow() book.last_modified = datetime.utcnow()
try:
calibre_db.session.commit() calibre_db.session.commit()
# revert change for sort if automatic fields link is deactivated # revert change for sort if automatic fields link is deactivated
if param == 'title' and vals.get('checkT') == "false": if param == 'title' and vals.get('checkT') == "false":
book.sort = sort book.sort = sort
calibre_db.session.commit() calibre_db.session.commit()
except (OperationalError, IntegrityError) as e:
calibre_db.session.rollback()
log.error("Database error: %s", e)
return ret return ret
@ -1224,3 +1228,43 @@ def merge_list_book():
delete_book(from_book.id,"", True) delete_book(from_book.id,"", True)
return json.dumps({'success': True}) return json.dumps({'success': True})
return "" return ""
@editbook.route("/ajax/xchange", methods=['POST'])
@login_required
@edit_required
def table_xchange_author_title():
vals = request.get_json().get('xchange')
if vals:
for val in vals:
modif_date = False
book = calibre_db.get_book(val)
authors = book.title
entries = calibre_db.order_authors(book)
author_names = []
for authr in entries.authors:
author_names.append(authr.name.replace('|', ','))
title_change = handle_title_on_edit(book, " ".join(author_names))
input_authors, authorchange = handle_author_on_edit(book, authors)
if authorchange or title_change:
edited_books_id = book.id
modif_date = True
if config.config_use_google_drive:
gdriveutils.updateGdriveCalibreFromLocal()
if edited_books_id:
helper.update_dir_stucture(edited_books_id, config.config_calibre_dir, input_authors[0])
if modif_date:
book.last_modified = datetime.utcnow()
try:
calibre_db.session.commit()
except (OperationalError, IntegrityError) as e:
calibre_db.session.rollback()
log.error("Database error: %s", e)
return json.dumps({'success': False})
if config.config_use_google_drive:
gdriveutils.updateGdriveCalibreFromLocal()
return json.dumps({'success': True})
return ""

View File

@ -46,9 +46,14 @@ $(function() {
if (selections.length < 1) { if (selections.length < 1) {
$("#delete_selection").addClass("disabled"); $("#delete_selection").addClass("disabled");
$("#delete_selection").attr("aria-disabled", true); $("#delete_selection").attr("aria-disabled", true);
$("#table_xchange").addClass("disabled");
$("#table_xchange").attr("aria-disabled", true);
} else { } else {
$("#delete_selection").removeClass("disabled"); $("#delete_selection").removeClass("disabled");
$("#delete_selection").attr("aria-disabled", false); $("#delete_selection").attr("aria-disabled", false);
$("#table_xchange").removeClass("disabled");
$("#table_xchange").attr("aria-disabled", false);
} }
}); });
$("#delete_selection").click(function() { $("#delete_selection").click(function() {
@ -86,6 +91,20 @@ $(function() {
}); });
}); });
$("#table_xchange").click(function() {
$.ajax({
method:"post",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: window.location.pathname + "/../../ajax/xchange",
data: JSON.stringify({"xchange":selections}),
success: function success() {
$("#books-table").bootstrapTable("refresh");
$("#books-table").bootstrapTable("uncheckAll");
}
});
});
var column = []; var column = [];
$("#books-table > thead > tr > th").each(function() { $("#books-table > thead > tr > th").each(function() {
var element = {}; var element = {};

View File

@ -20,17 +20,20 @@
{% block body %} {% block body %}
<h2 class="{{page}}">{{_(title)}}</h2> <h2 class="{{page}}">{{_(title)}}</h2>
<div class="col-xs-12 col-sm-6"> <div class="col-xs-12 col-sm-6">
<div class="row"> <div class="row form-group">
<div class="btn btn-default disabled" id="merge_books" data-toggle="modal" data-target="#mergeModal" aria-disabled="true">{{_('Merge selected books')}}</div> <div class="btn btn-default disabled" id="merge_books" data-toggle="modal" data-target="#mergeModal" aria-disabled="true">{{_('Merge selected books')}}</div>
<div class="btn btn-default disabled" id="delete_selection" aria-disabled="true">{{_('Remove Selections')}}</div> <div class="btn btn-default disabled" id="delete_selection" aria-disabled="true">{{_('Remove Selections')}}</div>
</div> </div>
<div class="row form-group">
<div class="btn btn-default disabled" id="table_xchange" ><span class="glyphicon glyphicon-arrow-up"></span><span class="glyphicon glyphicon-arrow-down"></span>{{_('Exchange author and title')}}</div>
</div> </div>
<div class="col-xs-12 col-sm-6"> </div>
<div class="row"> <div class="filterheader col-xs-12 col-sm-6">
<div class="row form-group">
<input type="checkbox" id="autoupdate_titlesort" name="autoupdate_titlesort" checked> <input type="checkbox" id="autoupdate_titlesort" name="autoupdate_titlesort" checked>
<label for="autoupdate_titlesort">{{_('Update Title Sort automatically')}}</label> <label for="autoupdate_titlesort">{{_('Update Title Sort automatically')}}</label>
</div> </div>
<div class="row"> <div class="row form-group">
<input type="checkbox" id="autoupdate_authorsort" name="autoupdate_authorsort" checked> <input type="checkbox" id="autoupdate_authorsort" name="autoupdate_authorsort" checked>
<label for="autoupdate_authorsort">{{_('Update Author Sort automatically')}}</label> <label for="autoupdate_authorsort">{{_('Update Author Sort automatically')}}</label>
</div> </div>

View File

@ -1211,7 +1211,7 @@ def extend_search_term(searchterm,
for key, db_element in elements.items(): for key, db_element in elements.items():
tag_names = calibre_db.session.query(db_element).filter(db_element.id.in_(tags['include_' + key])).all() tag_names = calibre_db.session.query(db_element).filter(db_element.id.in_(tags['include_' + key])).all()
searchterm.extend(tag.name for tag in tag_names) searchterm.extend(tag.name for tag in tag_names)
tag_names = calibre_db.session.query(db_element).filter(db.Tags.id.in_(tags['exclude_' + key])).all() tag_names = calibre_db.session.query(db_element).filter(db_element.id.in_(tags['exclude_' + key])).all()
searchterm.extend(tag.name for tag in tag_names) searchterm.extend(tag.name for tag in tag_names)
language_names = calibre_db.session.query(db.Languages). \ language_names = calibre_db.session.query(db.Languages). \
filter(db.Languages.id.in_(tags['include_language'])).all() filter(db.Languages.id.in_(tags['include_language'])).all()
@ -1327,7 +1327,11 @@ def render_adv_search_results(term, offset=None, order=None, limit=None):
q = q.filter(db.Books.comments.any(func.lower(db.Comments.text).ilike("%" + description + "%"))) q = q.filter(db.Books.comments.any(func.lower(db.Comments.text).ilike("%" + description + "%")))
# search custom culumns # search custom culumns
try:
q = adv_search_custom_columns(cc, term, q) q = adv_search_custom_columns(cc, term, q)
except AttributeError as ex:
log.debug_or_exception(ex)
flash(_("Error on search for custom columns, please restart Calibre-Web"), category="error")
q = q.order_by(*order).all() q = q.order_by(*order).all()
flask_session['query'] = json.dumps(term) flask_session['query'] = json.dumps(term)