mirror of
https://github.com/janeczku/calibre-web
synced 2025-06-03 23:14:11 +00:00
Add bulk read/unread buttons; Fix buttons not working when moved into table
This commit is contained in:
parent
34fec0ed97
commit
4ed0633edf
@ -525,6 +525,27 @@ def delete_selected_books():
|
||||
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
|
||||
@edit_required
|
||||
|
@ -90,6 +90,12 @@ $(function() {
|
||||
|
||||
$("#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);
|
||||
} else {
|
||||
$("#delete_selected_books").addClass("disabled");
|
||||
$("#delete_selected_books").attr("aria-disabled", true);
|
||||
@ -99,6 +105,12 @@ $(function() {
|
||||
|
||||
$("#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);
|
||||
}
|
||||
if (selections.length < 1) {
|
||||
$("#delete_selection").addClass("disabled");
|
||||
@ -154,7 +166,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#archive_selected_books").click(function(event) {
|
||||
$(document).on('click', '#archive_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
@ -176,7 +188,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#archive_selected_confirm").click(function(event) {
|
||||
$(document).on('click', '#archive_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
@ -190,7 +202,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#unarchive_selected_books").click(function(event) {
|
||||
$(document).on('click', '#unarchive_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
@ -212,7 +224,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#unarchive_selected_confirm").click(function(event) {
|
||||
$(document).on('click', '#unarchive_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
@ -226,7 +238,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#delete_selected_books").click(function(event) {
|
||||
$(document).on('click', '#delete_selected_books', function(event) {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
event.stopPropagation()
|
||||
} else {
|
||||
@ -248,7 +260,7 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("#delete_selected_confirm").click(function(event) {
|
||||
$(document).on('click', '#delete_selected_confirm', function(event) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
@ -262,6 +274,78 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$(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",
|
||||
|
@ -15,14 +15,26 @@
|
||||
{%- 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>
|
||||
{% 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>
|
||||
<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}}
|
||||
@ -40,8 +52,12 @@
|
||||
<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">{{_('Clear 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>
|
||||
<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>
|
||||
@ -103,7 +119,13 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if current_user.role_delete_books() and current_user.role_edit()%}
|
||||
<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>
|
||||
<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>
|
||||
@ -130,7 +152,7 @@
|
||||
<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>
|
||||
@ -149,7 +171,7 @@
|
||||
<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" id="delete_selected_confirm" data-dismiss="modal">
|
||||
<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>
|
||||
@ -169,7 +191,7 @@
|
||||
<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" id="archive_selected_confirm" data-dismiss="modal">
|
||||
<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>
|
||||
@ -189,13 +211,53 @@
|
||||
<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" id="unarchive_selected_confirm" data-dismiss="modal">
|
||||
<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>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user