mirror of
https://github.com/janeczku/calibre-web
synced 2025-09-12 07:46:01 +00:00
Merge remote-tracking branch 'massedit/bulk-delete' into Develop
This commit is contained in:
129
cps/editbooks.py
129
cps/editbooks.py
@@ -214,6 +214,76 @@ def table_get_custom_enum(c_id):
|
||||
@edit_required
|
||||
def edit_list_book(param):
|
||||
vals = request.form.to_dict()
|
||||
return edit_book_param(param, vals)
|
||||
|
||||
@editbook.route("/ajax/editselectedbooks", methods=['POST'])
|
||||
@login_required_if_no_ano
|
||||
@edit_required
|
||||
def edit_selected_books():
|
||||
d = request.get_json()
|
||||
selections = d.get('selections')
|
||||
title = d.get('title')
|
||||
title_sort = d.get('title_sort')
|
||||
author_sort = d.get('author_sort')
|
||||
authors = d.get('authors')
|
||||
categories = d.get('categories')
|
||||
series = d.get('series')
|
||||
languages = d.get('languages')
|
||||
publishers = d.get('publishers')
|
||||
comments = d.get('comments')
|
||||
checkA = d.get('checkA')
|
||||
|
||||
if len(selections) != 0:
|
||||
for book_id in selections:
|
||||
vals = {
|
||||
"pk": book_id,
|
||||
"value": None,
|
||||
"checkA": checkA,
|
||||
}
|
||||
if title:
|
||||
vals['value'] = title
|
||||
edit_book_param('title', vals)
|
||||
if title_sort:
|
||||
vals['value'] = title_sort
|
||||
edit_book_param('sort', vals)
|
||||
if author_sort:
|
||||
vals['value'] = author_sort
|
||||
edit_book_param('author_sort', vals)
|
||||
if authors:
|
||||
vals['value'] = authors
|
||||
edit_book_param('authors', vals)
|
||||
if categories:
|
||||
vals['value'] = categories
|
||||
edit_book_param('tags', vals)
|
||||
if series:
|
||||
vals['value'] = series
|
||||
edit_book_param('series', vals)
|
||||
if languages:
|
||||
vals['value'] = languages
|
||||
edit_book_param('languages', vals)
|
||||
if publishers:
|
||||
vals['value'] = publishers
|
||||
edit_book_param('publishers', vals)
|
||||
if comments:
|
||||
vals['value'] = comments
|
||||
edit_book_param('comments', vals)
|
||||
return json.dumps({'success': True})
|
||||
return ""
|
||||
|
||||
# Separated from /editbooks so that /editselectedbooks can also use this
|
||||
#
|
||||
# param: the property of the book to be changed
|
||||
# vals - JSON Object:
|
||||
# {
|
||||
# 'pk': "the book id",
|
||||
# 'value': "changes value of param to what's passed here"
|
||||
# 'checkA': "Optional. Used to check if autosort author is enabled. Assumed as true if not passed"
|
||||
# 'checkT': "Optional. Used to check if autotitle author is enabled. Assumed as true if not passed"
|
||||
# }
|
||||
#
|
||||
@login_required_if_no_ano
|
||||
@edit_required
|
||||
def edit_book_param(param, vals):
|
||||
book = calibre_db.get_book(vals['pk'])
|
||||
calibre_db.create_functions(config)
|
||||
sort_param = ""
|
||||
@@ -321,7 +391,6 @@ def get_sorted_entry(field, bookid):
|
||||
return make_response(jsonify(authors=" & ".join([a.name for a in calibre_db.order_authors([book])])))
|
||||
return ""
|
||||
|
||||
|
||||
@editbook.route("/ajax/simulatemerge", methods=['POST'])
|
||||
@user_login_required
|
||||
@edit_required
|
||||
@@ -337,6 +406,64 @@ def simulate_merge_list_book():
|
||||
return make_response(jsonify({'to': to_book, 'from': from_book}))
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/displayselectedbooks", methods=['POST'])
|
||||
@user_login_required
|
||||
@edit_required
|
||||
def display_selected_books():
|
||||
vals = request.get_json().get('selections')
|
||||
books = []
|
||||
if vals:
|
||||
for book_id in vals:
|
||||
books.append(calibre_db.get_book(book_id).title)
|
||||
return json.dumps({'books': books})
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/archiveselectedbooks", methods=['POST'])
|
||||
@login_required_if_no_ano
|
||||
@edit_required
|
||||
def archive_selected_books():
|
||||
vals = request.get_json().get('selections')
|
||||
state = request.get_json().get('archive')
|
||||
if vals:
|
||||
for book_id in vals:
|
||||
is_archived = change_archived_books(book_id, state,
|
||||
message="Book {} archive bit set to: {}".format(book_id, state))
|
||||
if is_archived:
|
||||
kobo_sync_status.remove_synced_book(book_id)
|
||||
return json.dumps({'success': True})
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/deleteselectedbooks", methods=['POST'])
|
||||
@user_login_required
|
||||
@edit_required
|
||||
def delete_selected_books():
|
||||
vals = request.get_json().get('selections')
|
||||
if vals:
|
||||
for book_id in vals:
|
||||
delete_book_from_table(book_id, "", True)
|
||||
return json.dumps({'success': True})
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/readselectedbooks", methods=['POST'])
|
||||
@user_login_required
|
||||
@edit_required
|
||||
def read_selected_books():
|
||||
vals = request.get_json().get('selections')
|
||||
markAsRead = request.get_json().get('markAsRead')
|
||||
if vals:
|
||||
try:
|
||||
for book_id in vals:
|
||||
ret = helper.edit_book_read_status(book_id, markAsRead)
|
||||
|
||||
except (OperationalError, IntegrityError, StaleDataError) as e:
|
||||
calibre_db.session.rollback()
|
||||
log.error_or_exception("Database error: {}".format(e))
|
||||
ret = Response(json.dumps({'success': False,
|
||||
'msg': 'Database error: {}'.format(e.orig if hasattr(e, "orig") else e)}),
|
||||
mimetype='application/json')
|
||||
|
||||
return json.dumps({'success': True})
|
||||
return ""
|
||||
|
||||
@editbook.route("/ajax/mergebooks", methods=['POST'])
|
||||
@user_login_required
|
||||
|
@@ -314,7 +314,7 @@ def edit_book_read_status(book_id, read_status=None):
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED if read_status else ub.ReadBook.STATUS_UNREAD
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED if read_status == True else ub.ReadBook.STATUS_UNREAD
|
||||
else:
|
||||
read_book = ub.ReadBook(user_id=current_user.id, book_id=book_id)
|
||||
read_book.read_status = ub.ReadBook.STATUS_FINISHED
|
||||
|
@@ -51,13 +51,15 @@ def remove_synced_book(book_id, all=False, session=None):
|
||||
ub.session_commit(_session=session)
|
||||
|
||||
|
||||
# If state == none, it will toggle the archive state of the passed book_id.
|
||||
# state = true archives it, state = false unarchives it
|
||||
def change_archived_books(book_id, state=None, message=None):
|
||||
archived_book = ub.session.query(ub.ArchivedBook).filter(and_(ub.ArchivedBook.user_id == int(current_user.id),
|
||||
ub.ArchivedBook.book_id == book_id)).first()
|
||||
if not archived_book:
|
||||
if not archived_book and (state == True or state == None):
|
||||
archived_book = ub.ArchivedBook(user_id=current_user.id, book_id=book_id)
|
||||
|
||||
archived_book.is_archived = state if state else not archived_book.is_archived
|
||||
archived_book.is_archived = state if state != None else not archived_book.is_archived
|
||||
archived_book.last_modified = datetime.now(timezone.utc) # toDo. Check utc timestamp
|
||||
|
||||
ub.session.merge(archived_book)
|
||||
|
@@ -81,6 +81,43 @@ $(function() {
|
||||
$("#merge_books").addClass("disabled");
|
||||
$("#merge_books").attr("aria-disabled", true);
|
||||
}
|
||||
if (selections.length >= 1) {
|
||||
$("#delete_selected_books").removeClass("disabled");
|
||||
$("#delete_selected_books").attr("aria-disabled", false);
|
||||
|
||||
$("#archive_selected_books").removeClass("disabled");
|
||||
$("#archive_selected_books").attr("aria-disabled", false);
|
||||
|
||||
$("#unarchive_selected_books").removeClass("disabled");
|
||||
$("#unarchive_selected_books").attr("aria-disabled", false);
|
||||
|
||||
$("#read_selected_books").removeClass("disabled");
|
||||
$("#read_selected_books").attr("aria-disabled", false);
|
||||
|
||||
$("#unread_selected_books").removeClass("disabled");
|
||||
$("#unread_selected_books").attr("aria-disabled", false);
|
||||
|
||||
$("#edit_selected_books").removeClass("disabled");
|
||||
$("#edit_selected_books").attr("aria-disabled", false);
|
||||
} else {
|
||||
$("#delete_selected_books").addClass("disabled");
|
||||
$("#delete_selected_books").attr("aria-disabled", true);
|
||||
|
||||
$("#archive_selected_books").addClass("disabled");
|
||||
$("#archive_selected_books").attr("aria-disabled", true);
|
||||
|
||||
$("#unarchive_selected_books").addClass("disabled");
|
||||
$("#unarchive_selected_books").attr("aria-disabled", true);
|
||||
|
||||
$("#read_selected_books").addClass("disabled");
|
||||
$("#read_selected_books").attr("aria-disabled", true);
|
||||
|
||||
$("#unread_selected_books").addClass("disabled");
|
||||
$("#unread_selected_books").attr("aria-disabled", true);
|
||||
|
||||
$("#edit_selected_books").addClass("disabled");
|
||||
$("#edit_selected_books").attr("aria-disabled", true);
|
||||
}
|
||||
if (selections.length < 1) {
|
||||
$("#delete_selection").addClass("disabled");
|
||||
$("#delete_selection").attr("aria-disabled", true);
|
||||
@@ -93,7 +130,29 @@ $(function() {
|
||||
$("#table_xchange").attr("aria-disabled", false);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Small block to initialize the state of the author/title sort inputs in metadata form
|
||||
{
|
||||
let checkA = $('#autoupdate_authorsort').prop('checked');
|
||||
$('#author_sort_input').prop('disabled', checkA);
|
||||
let checkT = $('#autoupdate_titlesort').prop('checked');
|
||||
$('#title_sort_input').prop('disabled', checkT);
|
||||
}
|
||||
|
||||
// Disable/enable author and title sort input in respect to auto-update title/author sort being checked on or not
|
||||
$("#autoupdate_authorsort").on('change', function(event) {
|
||||
let checkA = $('#autoupdate_authorsort').prop('checked');
|
||||
$('#author_sort_input').prop('disabled', checkA);
|
||||
})
|
||||
|
||||
$("#autoupdate_titlesort").on('change', function(event) {
|
||||
let checkT = $('#autoupdate_titlesort').prop('checked');
|
||||
$('#title_sort_input').prop('disabled', checkT);
|
||||
})
|
||||
/////
|
||||
|
||||
$("#delete_selection").click(function() {
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
});
|
||||
@@ -135,6 +194,232 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#edit_selected_books").click(function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#edit_selected_modal').modal("show");
|
||||
}
|
||||
});
|
||||
|
||||
$("#edit_selected_confirm").click(function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/editselectedbooks",
|
||||
data: JSON.stringify({
|
||||
"selections": selections,
|
||||
"title": $("#title_input").val(),
|
||||
"title_sort": $("#title_sort_input").val(),
|
||||
"author_sort": $("#author_sort_input").val(),
|
||||
"authors": $("#authors_input").val(),
|
||||
"categories": $("#categories_input").val(),
|
||||
"series": $("#series_input").val(),
|
||||
"languages": $("#languages_input").val(),
|
||||
"publishers": $("#publishers_input").val(),
|
||||
"comments": $("#comments_input").val().toString(),
|
||||
"checkA": $('#autoupdate_authorsort').prop('checked').toString()
|
||||
}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
|
||||
$("#title_input").val("");
|
||||
$("#title_sort_input").val("");
|
||||
$("#author_sort_input").val("");
|
||||
$("#authors_input").val("");
|
||||
$("#categories_input").val("");
|
||||
$("#series_input").val("");
|
||||
$("#languages_input").val("");
|
||||
$("#publishers_input").val("");
|
||||
$("#comments_input").val("");
|
||||
|
||||
handleListServerResponse;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#archive_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#archive_selected_modal').modal("show");
|
||||
}
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-archive-selected-books').empty();
|
||||
$.each(booTitles.books, function(i, item) {
|
||||
$("<span>- " + item + "</span><p></p>").appendTo("#display-archive-selected-books");
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#archive_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/archiveselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "archive": true}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#unarchive_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#unarchive_selected_modal').modal("show");
|
||||
}
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-unarchive-selected-books').empty();
|
||||
$.each(booTitles.books, function(i, item) {
|
||||
$("<span>- " + item + "</span><p></p>").appendTo("#display-unarchive-selected-books");
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#unarchive_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/archiveselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "archive": false}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#delete_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#delete_selected_modal').modal("show");
|
||||
}
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-delete-selected-books').empty();
|
||||
$.each(booTitles.books, function(i, item) {
|
||||
$("<span>- " + item + "</span><p></p>").appendTo("#display-delete-selected-books");
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#delete_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/deleteselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#read_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#read_selected_modal').modal("show");
|
||||
}
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-read-selected-books').empty();
|
||||
$.each(booTitles.books, function(i, item) {
|
||||
$("<span>- " + item + "</span><p></p>").appendTo("#display-read-selected-books");
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#read_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/readselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "markAsRead": true}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#unread_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
$('#unread_selected_modal').modal("show");
|
||||
}
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-unread-selected-books').empty();
|
||||
$.each(booTitles.books, function(i, item) {
|
||||
$("<span>- " + item + "</span><p></p>").appendTo("#display-unread-selected-books");
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#unread_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/readselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "markAsRead": false}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#table_xchange").click(function() {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
@@ -863,7 +1148,6 @@ function BookCheckboxChange(checkbox, userId, field) {
|
||||
console.log("test");
|
||||
}
|
||||
|
||||
|
||||
function selectHeader(element, field) {
|
||||
if (element.value !== "None") {
|
||||
confirmDialog(element.id, "GeneralChangeModal", 0, function () {
|
||||
|
@@ -15,10 +15,28 @@
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro book_checkbox_row(parameter, show_text, sort) -%}
|
||||
<th data-name="{{parameter}}" data-field="{{parameter}}"
|
||||
<th data-name="{{parameter}}" data-field="{{parameter}}" data-switchable="false"
|
||||
{% if sort %}data-sortable="true" {% endif %}
|
||||
data-visible="{{visiblility.get(parameter)}}"
|
||||
data-formatter="bookCheckboxFormatter">
|
||||
{% if parameter == "is_archived" %}
|
||||
<div class="btn btn-default disabled" id="archive_selected_books" aria-disabled="true">
|
||||
{{_('Archive selected books')}}
|
||||
</div>
|
||||
<br>
|
||||
<div class="btn btn-default disabled" id="unarchive_selected_books" aria-disabled="true">
|
||||
{{_('Unarchive selected books')}}
|
||||
</div>
|
||||
<br>
|
||||
{% elif parameter == "read_status" %}
|
||||
<div class="btn btn-default disabled" id="read_selected_books" aria-disabled="true">
|
||||
{{_('Mark selected books as read')}}
|
||||
</div>
|
||||
<br>
|
||||
<div class="btn btn-default disabled" id="unread_selected_books" aria-disabled="true">
|
||||
{{_('Mark selected books as unread')}}</div>
|
||||
<br>
|
||||
{% endif %}
|
||||
{{show_text}}
|
||||
</th>
|
||||
{%- endmacro %}
|
||||
@@ -34,8 +52,15 @@
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
<div class="row form-group">
|
||||
<div class="btn btn-default disabled" id="merge_books" 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="merge_books" aria-disabled="true">
|
||||
{{_('Merge selected books')}}
|
||||
</div>
|
||||
<div class="btn btn-default disabled" id="delete_selection" aria-disabled="true">
|
||||
{{_('Clear selections')}}
|
||||
</div>
|
||||
<div class="btn btn-default disabled" id="edit_selected_books" aria-disabled="true">
|
||||
{{_('Edit selected books')}}
|
||||
</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>
|
||||
@@ -97,11 +122,18 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if current_user.role_delete_books() and current_user.role_edit()%}
|
||||
<th data-align="right" data-formatter="EbookActions" data-switchable="false">{{_('Delete')}}</th>
|
||||
<th data-align="right" data-formatter="EbookActions" data-switchable="false">
|
||||
<div class="btn btn-default disabled" id="delete_selected_books" aria-disabled="true">
|
||||
{{_('Delete selected books')}}
|
||||
</div>
|
||||
<br>
|
||||
{{_('Delete')}}
|
||||
</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
{% block modal %}
|
||||
{{ delete_book(current_user.role_delete_books()) }}
|
||||
@@ -123,15 +155,170 @@
|
||||
<div class="text-left" id="merge_to"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input id="merge_confirm" type="button" class="btn btn-danger" value="{{_('Merge')}}" name="merge_confirm" id="merge_confirm" data-dismiss="modal">
|
||||
<input id="merge_confirm" type="button" class="btn btn-danger" value="{{_('Merge')}}" name="merge_confirm" data-dismiss="modal">
|
||||
<button id="merge_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="modal fade" id="delete_selected_modal" role="dialog" aria-labelledby="metaDeleteSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-center">
|
||||
<span>{{_('Are you really sure?')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="text-left">{{_('The following books will be deleted:')}}</div>
|
||||
<p></p>
|
||||
<div class="text-left" id="display-delete-selected-books"></div>
|
||||
<div class="modal-footer">
|
||||
<input id="delete_selected_confirm" type="button" class="btn btn-danger" value="{{_('Delete')}}" name="delete_selected_confirm" data-dismiss="modal">
|
||||
<button id="delete_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="archive_selected_modal" role="dialog" aria-labelledby="metaArchiveSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-center">
|
||||
<span>{{_('Are you really sure?')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="text-left">{{_('The following books will be archived:')}}</div>
|
||||
<p></p>
|
||||
<div class="text-left" id="display-archive-selected-books"></div>
|
||||
<div class="modal-footer">
|
||||
<input id="archive_selected_confirm" type="button" class="btn btn-danger" value="{{_('Archive')}}" name="archive_selected_confirm" data-dismiss="modal">
|
||||
<button id="archive_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="unarchive_selected_modal" role="dialog" aria-labelledby="metaUnArchiveSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-center">
|
||||
<span>{{_('Are you really sure?')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="text-left">{{_('The following books will be unarchived:')}}</div>
|
||||
<p></p>
|
||||
<div class="text-left" id="display-unarchive-selected-books"></div>
|
||||
<div class="modal-footer">
|
||||
<input id="unarchive_selected_confirm" type="button" class="btn btn-danger" value="{{_('Unarchive')}}" name="unarchive_selected_confirm" data-dismiss="modal">
|
||||
<button id="unarchive_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="read_selected_modal" role="dialog" aria-labelledby="metaReadSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-center">
|
||||
<span>{{_('Are you really sure?')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="text-left">{{_('The following books will be marked read:')}}</div>
|
||||
<p></p>
|
||||
<div class="text-left" id="display-read-selected-books"></div>
|
||||
<div class="modal-footer">
|
||||
<input id="read_selected_confirm" type="button" class="btn btn-danger" value="{{_('Mark as read')}}" name="read_selected_confirm" data-dismiss="modal">
|
||||
<button id="read_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="unread_selected_modal" role="dialog" aria-labelledby="metaReadSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-center">
|
||||
<span>{{_('Are you really sure?')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="text-left">{{_('The following books will be marked unread:')}}</div>
|
||||
<p></p>
|
||||
<div class="text-left" id="display-unread-selected-books"></div>
|
||||
<div class="modal-footer">
|
||||
<input id="unread_selected_confirm" type="button" class="btn btn-danger" value="{{_('Mark as unread')}}" name="unread_selected_confirm" data-dismiss="modal">
|
||||
<button id="read_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="edit_selected_modal" role="dialog" aria-labelledby="metaEditSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-center">
|
||||
<span>{{_('Edit Metadata')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-left">{{_('Edit the fields you want changed. Blank fields will be ignored:')}}</div>
|
||||
<br>
|
||||
Title:
|
||||
<input class="form-control" id="title_input">
|
||||
<p></p>
|
||||
|
||||
Title Sort:
|
||||
<input class="form-control" id="title_sort_input">
|
||||
<p></p>
|
||||
|
||||
Author Sort:
|
||||
<input class="form-control" id="author_sort_input">
|
||||
<p></p>
|
||||
|
||||
Authors:
|
||||
<input class="form-control" id="authors_input">
|
||||
<p></p>
|
||||
|
||||
Categories:
|
||||
<input class="form-control" id="categories_input">
|
||||
<p></p>
|
||||
|
||||
Series:
|
||||
<input class="form-control" id="series_input">
|
||||
<p></p>
|
||||
|
||||
Languages:
|
||||
<input class="form-control" id="languages_input">
|
||||
<p></p>
|
||||
|
||||
Publishers:
|
||||
<input class="form-control" id="publishers_input">
|
||||
<p></p>
|
||||
|
||||
Comments:
|
||||
<input class="form-control" id="comments_input">
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<input id="edit_selected_confirm" type="button" class="btn btn-danger" value="{{_('Edit')}}" name="edit_selected_confirm" id="edit_selected_confirm" data-dismiss="modal">
|
||||
<button id="edit_selected_abort" type="button" class="btn btn-default" data-dismiss="modal">{{_('Cancel')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-locale-all.min.js') }}"></script>
|
||||
|
Reference in New Issue
Block a user