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 .usermanagement import login_required_if_no_ano
|
||||
from .kobo_sync_status import change_archived_books
|
||||
from .redirect import get_redirect_location
|
||||
|
||||
|
||||
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"])
|
||||
@login_required
|
||||
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'])
|
||||
@ -823,7 +824,7 @@ def delete_whole_book(book_id, book):
|
||||
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 json_response:
|
||||
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))
|
||||
else:
|
||||
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",
|
||||
"format": book_format,
|
||||
"message": _('Book Successfully Deleted')}])
|
||||
else:
|
||||
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 = {}
|
||||
if current_user.role_delete_books():
|
||||
book = calibre_db.get_book(book_id)
|
||||
@ -891,7 +892,7 @@ def delete_book_from_table(book_id, book_format, json_response):
|
||||
else:
|
||||
# book not found
|
||||
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")
|
||||
if json_response:
|
||||
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:
|
||||
verify = ""
|
||||
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:
|
||||
verify += "(?=.*?\d)"
|
||||
verify += r"(?=.*?\d)"
|
||||
if config.config_password_lower:
|
||||
verify += "(?=.*?[a-z])"
|
||||
verify += r"(?=.*?[a-z])"
|
||||
if config.config_password_upper:
|
||||
verify += "(?=.*?[A-Z])"
|
||||
verify += r"(?=.*?[A-Z])"
|
||||
if config.config_password_special:
|
||||
verify += "(?=.*?[^A-Za-z\s0-9])"
|
||||
verify += r"(?=.*?[^A-Za-z\s0-9])"
|
||||
match = re.match(verify, check_password)
|
||||
if not match:
|
||||
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_executable = [os.access(binary_path, os.X_OK) for binary_path in supported_binary_paths]
|
||||
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]
|
||||
if all(values):
|
||||
version = values[0].group(1)
|
||||
|
@ -44,9 +44,9 @@ def remove_prefix(text, prefix):
|
||||
return ""
|
||||
|
||||
|
||||
def redirect_back(endpoint, **values):
|
||||
target = request.form.get('next', None) or url_for(endpoint, **values)
|
||||
def get_redirect_location(next, endpoint, **values):
|
||||
target = next or url_for(endpoint, **values)
|
||||
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',"")))):
|
||||
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
|
||||
}
|
||||
|
||||
function postButton(event, action){
|
||||
function postButton(event, action, location=""){
|
||||
event.preventDefault();
|
||||
var newForm = jQuery('<form>', {
|
||||
"action": action,
|
||||
@ -30,7 +30,14 @@ function postButton(event, action){
|
||||
'name': 'csrf_token',
|
||||
'value': $("input[name=\'csrf_token\']").val(),
|
||||
'type': 'hidden'
|
||||
})).appendTo('body');
|
||||
})).appendTo('body')
|
||||
if(location !== "") {
|
||||
newForm.append(jQuery('<input>', {
|
||||
'name': 'location',
|
||||
'value': location,
|
||||
'type': 'hidden'
|
||||
})).appendTo('body');
|
||||
}
|
||||
newForm.submit();
|
||||
}
|
||||
|
||||
@ -212,17 +219,20 @@ $("#delete_confirm").click(function(event) {
|
||||
$( ".navbar" ).after( '<div class="row-fluid text-center" >' +
|
||||
'<div id="flash_'+item.type+'" class="alert alert-'+item.type+'">'+item.message+'</div>' +
|
||||
'</div>');
|
||||
|
||||
}
|
||||
});
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
}
|
||||
});
|
||||
} 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
|
||||
@ -541,6 +551,7 @@ $(function() {
|
||||
$.get(e.relatedTarget.href).done(function(content) {
|
||||
$modalBody.html(content);
|
||||
preFilters.remove(useCache);
|
||||
$("#back").remove();
|
||||
});
|
||||
})
|
||||
.on("hidden.bs.modal", function() {
|
||||
|
@ -32,7 +32,7 @@
|
||||
</div>
|
||||
<div class="row display-flex">
|
||||
{% 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">
|
||||
<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}}">
|
||||
@ -99,7 +99,7 @@
|
||||
<h3>{{_("More by")}} {{ author.name.replace('|',',') }}</h3>
|
||||
<div class="row">
|
||||
{% 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">
|
||||
<a href="https://www.goodreads.com/book/show/{{ entry.gid['#text'] }}" target="_blank" rel="noopener">
|
||||
<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 %}
|
||||
{% 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">
|
||||
<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="glyphicon glyphicon-edit"></span> {{ _('Edit Metadata') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn btn-default" data-back="{{ url_for('web.index') }}" id="back">{{_('Cancel')}}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -367,4 +367,3 @@
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
<h2 class="random-books">{{_('Discover (Random Books)')}}</h2>
|
||||
<div class="row display-flex">
|
||||
{% 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">
|
||||
<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 }}">
|
||||
@ -89,7 +89,7 @@
|
||||
<div class="row display-flex">
|
||||
{% if entries[0] %}
|
||||
{% 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">
|
||||
<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 }}">
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
<div class="row display-flex">
|
||||
{% 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">
|
||||
{% 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 %}>
|
||||
|
@ -31,7 +31,7 @@
|
||||
{% endif %}
|
||||
<div class="row display-flex">
|
||||
{% 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">
|
||||
<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}}" >
|
||||
|
@ -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, \
|
||||
edit_book_read_status, valid_password
|
||||
from .pagination import Pagination
|
||||
from .redirect import redirect_back
|
||||
from .redirect import get_redirect_location
|
||||
from .babel import get_available_locale
|
||||
from .usermanagement import login_required_if_no_ano
|
||||
from .kobo_sync_status import remove_synced_book
|
||||
@ -1342,7 +1342,7 @@ def handle_login_user(user, remember, message, category):
|
||||
ub.store_user_session()
|
||||
flash(message, category=category)
|
||||
[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=""):
|
||||
|
Loading…
Reference in New Issue
Block a user