mirror of
https://github.com/janeczku/calibre-web
synced 2024-12-25 09:30:31 +00:00
Merge remote-tracking branch 'origin/back' into Develop
This commit is contained in:
commit
4fbd064b85
@ -60,6 +60,7 @@ from .tasks.upload import TaskUpload
|
|||||||
from .render_template import render_title_template
|
from .render_template import render_title_template
|
||||||
from .usermanagement import login_required_if_no_ano
|
from .usermanagement import login_required_if_no_ano
|
||||||
from .kobo_sync_status import change_archived_books
|
from .kobo_sync_status import change_archived_books
|
||||||
|
from .redirect import get_redirect_location
|
||||||
|
|
||||||
|
|
||||||
editbook = Blueprint('edit-book', __name__)
|
editbook = Blueprint('edit-book', __name__)
|
||||||
@ -96,7 +97,7 @@ def delete_book_from_details(book_id):
|
|||||||
@editbook.route("/delete/<int:book_id>/<string:book_format>", methods=["POST"])
|
@editbook.route("/delete/<int:book_id>/<string:book_format>", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_book_ajax(book_id, book_format):
|
def delete_book_ajax(book_id, book_format):
|
||||||
return delete_book_from_table(book_id, book_format, False)
|
return delete_book_from_table(book_id, book_format, False, request.form.to_dict().get('location', ""))
|
||||||
|
|
||||||
|
|
||||||
@editbook.route("/admin/book/<int:book_id>", methods=['GET'])
|
@editbook.route("/admin/book/<int:book_id>", methods=['GET'])
|
||||||
@ -823,7 +824,7 @@ def delete_whole_book(book_id, book):
|
|||||||
calibre_db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
calibre_db.session.query(db.Books).filter(db.Books.id == book_id).delete()
|
||||||
|
|
||||||
|
|
||||||
def render_delete_book_result(book_format, json_response, warning, book_id):
|
def render_delete_book_result(book_format, json_response, warning, book_id, location=""):
|
||||||
if book_format:
|
if book_format:
|
||||||
if json_response:
|
if json_response:
|
||||||
return json.dumps([warning, {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
return json.dumps([warning, {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||||
@ -835,16 +836,16 @@ def render_delete_book_result(book_format, json_response, warning, book_id):
|
|||||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||||
else:
|
else:
|
||||||
if json_response:
|
if json_response:
|
||||||
return json.dumps([warning, {"location": url_for('web.index'),
|
return json.dumps([warning, {"location": get_redirect_location(location, "web.index"),
|
||||||
"type": "success",
|
"type": "success",
|
||||||
"format": book_format,
|
"format": book_format,
|
||||||
"message": _('Book Successfully Deleted')}])
|
"message": _('Book Successfully Deleted')}])
|
||||||
else:
|
else:
|
||||||
flash(_('Book Successfully Deleted'), category="success")
|
flash(_('Book Successfully Deleted'), category="success")
|
||||||
return redirect(url_for('web.index'))
|
return redirect(get_redirect_location(location, "web.index"))
|
||||||
|
|
||||||
|
|
||||||
def delete_book_from_table(book_id, book_format, json_response):
|
def delete_book_from_table(book_id, book_format, json_response, location=""):
|
||||||
warning = {}
|
warning = {}
|
||||||
if current_user.role_delete_books():
|
if current_user.role_delete_books():
|
||||||
book = calibre_db.get_book(book_id)
|
book = calibre_db.get_book(book_id)
|
||||||
@ -891,7 +892,7 @@ def delete_book_from_table(book_id, book_format, json_response):
|
|||||||
else:
|
else:
|
||||||
# book not found
|
# book not found
|
||||||
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
||||||
return render_delete_book_result(book_format, json_response, warning, book_id)
|
return render_delete_book_result(book_format, json_response, warning, book_id, location)
|
||||||
message = _("You are missing permissions to delete books")
|
message = _("You are missing permissions to delete books")
|
||||||
if json_response:
|
if json_response:
|
||||||
return json.dumps({"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
return json.dumps({"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||||
|
@ -692,15 +692,15 @@ def valid_password(check_password):
|
|||||||
if config.config_password_policy:
|
if config.config_password_policy:
|
||||||
verify = ""
|
verify = ""
|
||||||
if config.config_password_min_length > 0:
|
if config.config_password_min_length > 0:
|
||||||
verify += "^(?=.{" + str(config.config_password_min_length) + ",}$)"
|
verify += r"^(?=.{" + str(config.config_password_min_length) + ",}$)"
|
||||||
if config.config_password_number:
|
if config.config_password_number:
|
||||||
verify += "(?=.*?\d)"
|
verify += r"(?=.*?\d)"
|
||||||
if config.config_password_lower:
|
if config.config_password_lower:
|
||||||
verify += "(?=.*?[a-z])"
|
verify += r"(?=.*?[a-z])"
|
||||||
if config.config_password_upper:
|
if config.config_password_upper:
|
||||||
verify += "(?=.*?[A-Z])"
|
verify += r"(?=.*?[A-Z])"
|
||||||
if config.config_password_special:
|
if config.config_password_special:
|
||||||
verify += "(?=.*?[^A-Za-z\s0-9])"
|
verify += r"(?=.*?[^A-Za-z\s0-9])"
|
||||||
match = re.match(verify, check_password)
|
match = re.match(verify, check_password)
|
||||||
if not match:
|
if not match:
|
||||||
raise Exception(_("Password doesn't comply with password validation rules"))
|
raise Exception(_("Password doesn't comply with password validation rules"))
|
||||||
@ -1039,7 +1039,7 @@ def check_calibre(calibre_location):
|
|||||||
binaries_available = [os.path.isfile(binary_path) for binary_path in supported_binary_paths]
|
binaries_available = [os.path.isfile(binary_path) for binary_path in supported_binary_paths]
|
||||||
binaries_executable = [os.access(binary_path, os.X_OK) for binary_path in supported_binary_paths]
|
binaries_executable = [os.access(binary_path, os.X_OK) for binary_path in supported_binary_paths]
|
||||||
if all(binaries_available) and all(binaries_executable):
|
if all(binaries_available) and all(binaries_executable):
|
||||||
values = [process_wait([binary_path, "--version"], pattern='\(calibre (.*)\)')
|
values = [process_wait([binary_path, "--version"], pattern=r'\(calibre (.*)\)')
|
||||||
for binary_path in supported_binary_paths]
|
for binary_path in supported_binary_paths]
|
||||||
if all(values):
|
if all(values):
|
||||||
version = values[0].group(1)
|
version = values[0].group(1)
|
||||||
|
@ -44,9 +44,9 @@ def remove_prefix(text, prefix):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def redirect_back(endpoint, **values):
|
def get_redirect_location(next, endpoint, **values):
|
||||||
target = request.form.get('next', None) or url_for(endpoint, **values)
|
target = next or url_for(endpoint, **values)
|
||||||
adapter = current_app.url_map.bind(urlparse(request.host_url).netloc)
|
adapter = current_app.url_map.bind(urlparse(request.host_url).netloc)
|
||||||
if not len(adapter.allowed_methods(remove_prefix(target, request.environ.get('HTTP_X_SCRIPT_NAME',"")))):
|
if not len(adapter.allowed_methods(remove_prefix(target, request.environ.get('HTTP_X_SCRIPT_NAME',"")))):
|
||||||
target = url_for(endpoint, **values)
|
target = url_for(endpoint, **values)
|
||||||
return redirect(target)
|
return target
|
||||||
|
@ -20,7 +20,7 @@ function getPath() {
|
|||||||
return jsFileLocation.substr(0, jsFileLocation.search("/static/js/libs/jquery.min.js")); // the js folder path
|
return jsFileLocation.substr(0, jsFileLocation.search("/static/js/libs/jquery.min.js")); // the js folder path
|
||||||
}
|
}
|
||||||
|
|
||||||
function postButton(event, action){
|
function postButton(event, action, location=""){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var newForm = jQuery('<form>', {
|
var newForm = jQuery('<form>', {
|
||||||
"action": action,
|
"action": action,
|
||||||
@ -30,7 +30,14 @@ function postButton(event, action){
|
|||||||
'name': 'csrf_token',
|
'name': 'csrf_token',
|
||||||
'value': $("input[name=\'csrf_token\']").val(),
|
'value': $("input[name=\'csrf_token\']").val(),
|
||||||
'type': 'hidden'
|
'type': 'hidden'
|
||||||
})).appendTo('body');
|
})).appendTo('body')
|
||||||
|
if(location !== "") {
|
||||||
|
newForm.append(jQuery('<input>', {
|
||||||
|
'name': 'location',
|
||||||
|
'value': location,
|
||||||
|
'type': 'hidden'
|
||||||
|
})).appendTo('body');
|
||||||
|
}
|
||||||
newForm.submit();
|
newForm.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,17 +219,20 @@ $("#delete_confirm").click(function(event) {
|
|||||||
$( ".navbar" ).after( '<div class="row-fluid text-center" >' +
|
$( ".navbar" ).after( '<div class="row-fluid text-center" >' +
|
||||||
'<div id="flash_'+item.type+'" class="alert alert-'+item.type+'">'+item.message+'</div>' +
|
'<div id="flash_'+item.type+'" class="alert alert-'+item.type+'">'+item.message+'</div>' +
|
||||||
'</div>');
|
'</div>');
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#books-table").bootstrapTable("refresh");
|
$("#books-table").bootstrapTable("refresh");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
postButton(event, getPath() + "/delete/" + deleteId);
|
var loc = sessionStorage.getItem("back");
|
||||||
|
if (!loc) {
|
||||||
|
loc = $(this).data("back");
|
||||||
|
}
|
||||||
|
sessionStorage.removeItem("back");
|
||||||
|
postButton(event, getPath() + "/delete/" + deleteId, location=loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//triggered when modal is about to be shown
|
//triggered when modal is about to be shown
|
||||||
@ -541,6 +551,7 @@ $(function() {
|
|||||||
$.get(e.relatedTarget.href).done(function(content) {
|
$.get(e.relatedTarget.href).done(function(content) {
|
||||||
$modalBody.html(content);
|
$modalBody.html(content);
|
||||||
preFilters.remove(useCache);
|
preFilters.remove(useCache);
|
||||||
|
$("#back").remove();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on("hidden.bs.modal", function() {
|
.on("hidden.bs.modal", function() {
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div id="books" class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div id="books" class="col-sm-3 col-lg-2 col-xs-6 book session">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||||
<span class="img" title="{{entry.Books.title}}">
|
<span class="img" title="{{entry.Books.title}}">
|
||||||
@ -99,7 +99,7 @@
|
|||||||
<h3>{{_("More by")}} {{ author.name.replace('|',',') }}</h3>
|
<h3>{{_("More by")}} {{ author.name.replace('|',',') }}</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for entry in other_books %}
|
{% for entry in other_books %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div class="col-sm-3 col-lg-2 col-xs-6 book session">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="https://www.goodreads.com/book/show/{{ entry.gid['#text'] }}" target="_blank" rel="noopener">
|
<a href="https://www.goodreads.com/book/show/{{ entry.gid['#text'] }}" target="_blank" rel="noopener">
|
||||||
<img title="{{entry.title}}" src="{{ entry.image_url }}" />
|
<img title="{{entry.title}}" src="{{ entry.image_url }}" />
|
||||||
|
7
cps/templates/detail.html
Executable file → Normal file
7
cps/templates/detail.html
Executable file → Normal file
@ -333,15 +333,15 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if current_user.role_edit() %}
|
{% if current_user.role_edit() %}
|
||||||
<div class="btn-toolbar" role="toolbar">
|
<div class="col-sm-12">
|
||||||
<div class="btn-group" role="group" aria-label="Edit/Delete book">
|
<div class="btn-group" role="group" aria-label="Edit/Delete book">
|
||||||
<a href="{{ url_for('edit-book.show_edit_book', book_id=entry.id) }}"
|
<a href="{{ url_for('edit-book.show_edit_book', book_id=entry.id) }}"
|
||||||
class="btn btn-sm btn-primary" id="edit_book" role="button"><span
|
class="btn btn-sm btn-primary" id="edit_book" role="button"><span
|
||||||
class="glyphicon glyphicon-edit"></span> {{ _('Edit Metadata') }}</a>
|
class="glyphicon glyphicon-edit"></span> {{ _('Edit Metadata') }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="btn btn-default" data-back="{{ url_for('web.index') }}" id="back">{{_('Cancel')}}</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -367,4 +367,3 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<h2 class="random-books">{{_('Discover (Random Books)')}}</h2>
|
<h2 class="random-books">{{_('Discover (Random Books)')}}</h2>
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% for entry in random %}
|
{% for entry in random %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book" id="books_rand">
|
<div class="col-sm-3 col-lg-2 col-xs-6 book session" id="books_rand">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||||
<span class="img" title="{{ entry.Books.title }}">
|
<span class="img" title="{{ entry.Books.title }}">
|
||||||
@ -89,7 +89,7 @@
|
|||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% if entries[0] %}
|
{% if entries[0] %}
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book" id="books">
|
<div class="col-sm-3 col-lg-2 col-xs-6 book session" id="books">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||||
<span class="img" title="{{ entry.Books.title }}">
|
<span class="img" title="{{ entry.Books.title }}">
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div class="col-sm-3 col-lg-2 col-xs-6 book session">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
{% if entry.Books.has_cover is defined %}
|
{% if entry.Books.has_cover is defined %}
|
||||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row display-flex">
|
<div class="row display-flex">
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<div class="col-sm-3 col-lg-2 col-xs-6 book">
|
<div class="col-sm-3 col-lg-2 col-xs-6 book session">
|
||||||
<div class="cover">
|
<div class="cover">
|
||||||
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
<a href="{{ url_for('web.show_book', book_id=entry.Books.id) }}" {% if simple==false %}data-toggle="modal" data-target="#bookDetailsModal" data-remote="false"{% endif %}>
|
||||||
<span class="img" title="{{entry.Books.title}}" >
|
<span class="img" title="{{entry.Books.title}}" >
|
||||||
|
@ -50,7 +50,7 @@ from .helper import check_valid_domain, check_email, check_username, \
|
|||||||
send_registration_mail, check_send_to_ereader, check_read_formats, tags_filters, reset_password, valid_email, \
|
send_registration_mail, check_send_to_ereader, check_read_formats, tags_filters, reset_password, valid_email, \
|
||||||
edit_book_read_status, valid_password
|
edit_book_read_status, valid_password
|
||||||
from .pagination import Pagination
|
from .pagination import Pagination
|
||||||
from .redirect import redirect_back
|
from .redirect import get_redirect_location
|
||||||
from .babel import get_available_locale
|
from .babel import get_available_locale
|
||||||
from .usermanagement import login_required_if_no_ano
|
from .usermanagement import login_required_if_no_ano
|
||||||
from .kobo_sync_status import remove_synced_book
|
from .kobo_sync_status import remove_synced_book
|
||||||
@ -1342,7 +1342,7 @@ def handle_login_user(user, remember, message, category):
|
|||||||
ub.store_user_session()
|
ub.store_user_session()
|
||||||
flash(message, category=category)
|
flash(message, category=category)
|
||||||
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
|
[limiter.limiter.storage.clear(k.key) for k in limiter.current_limits]
|
||||||
return redirect_back("web.index")
|
return redirect(get_redirect_location(request.form.get('next', None), "web.index"))
|
||||||
|
|
||||||
|
|
||||||
def render_login(username="", password=""):
|
def render_login(username="", password=""):
|
||||||
|
Loading…
Reference in New Issue
Block a user