diff --git a/cps/admin.py b/cps/admin.py index d32d6d7c..5b18bb64 100644 --- a/cps/admin.py +++ b/cps/admin.py @@ -289,15 +289,30 @@ def list_users(): @login_required @admin_required def delete_user(): - user_id = request.values.get('userid', -1) - content = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).one_or_none() - try: - message = _delete_user(content) - return Response(json.dumps({'type': "success", 'message': message}), mimetype='application/json') - except Exception as ex: - return Response(json.dumps({'type': "danger", 'message':str(ex)}), mimetype='application/json') - log.error("User not found") - return Response(json.dumps({'type': "danger", 'message':_("User not found")}), mimetype='application/json') + user_ids = request.form.to_dict(flat=False) + if "userid[]" in user_ids: + users = ub.session.query(ub.User).filter(ub.User.id.in_(user_ids['userid[]'])).all() + elif "userid" in user_ids: + users = ub.session.query(ub.User).filter(ub.User.id == user_ids['userid'][0]).all() + count = 0 + errors = list() + success = list() + if not users: + log.error("User not found") + return Response(json.dumps({'type': "danger", 'message': _("User not found")}), mimetype='application/json') + for user in users: + try: + message = _delete_user(user) + count += 1 + except Exception as ex: + errors.append({'type': "danger", 'message': str(ex)}) + + if count == 1: + success = [{'type': "success", 'message': message}] + elif count > 1: + success = [{'type': "success", 'message': _("{} users deleted successfully").format(count)}] + success.extend(errors) + return Response(json.dumps(success), mimetype='application/json') @admi.route("/ajax/getlocale") @login_required @@ -367,9 +382,9 @@ def edit_list_user(param): if not ub.session.query(ub.User).\ filter(ub.User.role.op('&')(constants.ROLE_ADMIN) == constants.ROLE_ADMIN, ub.User.id != user.id).count(): - return Response(json.dumps({'type': "danger", + return Response(json.dumps([{'type': "danger", 'message':_(u"No admin user remaining, can't remove admin role", - nick=user.name)}), mimetype='application/json') + nick=user.name)}]), mimetype='application/json') user.role &= ~int(vals['field_index']) elif param.startswith('sidebar'): if user.name == "Guest" and int(vals['field_index']) == constants.SIDEBAR_READ_AND_UNREAD: diff --git a/cps/db.py b/cps/db.py index 1a305d33..39adcd4b 100644 --- a/cps/db.py +++ b/cps/db.py @@ -625,7 +625,10 @@ class CalibreDB(): outcome = list() elementlist = {ele.id: ele for ele in inputlist} for entry in state: - outcome.append(elementlist[entry]) + try: + outcome.append(elementlist[entry]) + except KeyError: + pass del elementlist[entry] for entry in elementlist: outcome.append(elementlist[entry]) diff --git a/cps/editbooks.py b/cps/editbooks.py index 67ab06d9..45e0f9fe 100644 --- a/cps/editbooks.py +++ b/cps/editbooks.py @@ -1185,6 +1185,6 @@ def merge_list_book(): element.format, element.uncompressed_size, to_name)) - delete_book(from_book.id,"", True) # json_resp = + delete_book(from_book.id,"", True) return json.dumps({'success': True}) return "" diff --git a/cps/static/js/main.js b/cps/static/js/main.js index 7231c51c..92c83f60 100644 --- a/cps/static/js/main.js +++ b/cps/static/js/main.js @@ -178,6 +178,19 @@ $("#delete_confirm").click(function() { } }); + $("#books-table").bootstrapTable("refresh"); + /*$.ajax({ + method:"get", + url: window.location.pathname + "/../../ajax/listbooks", + async: true, + timeout: 900, + success:function(data) { + + + $("#book-table").bootstrapTable("load", data); + loadSuccess(); + } + });*/ } }); } else { diff --git a/cps/static/js/table.js b/cps/static/js/table.js index 3f3b431f..97dee842 100644 --- a/cps/static/js/table.js +++ b/cps/static/js/table.js @@ -511,22 +511,36 @@ $(function() { var data = $(this).data("val"); checkboxHeader(val, name, data); }); + $(".button_head").on("click",function() { + var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id); + confirmDialog( + "btndeluser", + "GeneralDeleteModal", + 0, + function() { + $.ajax({ + method:"post", + url: window.location.pathname + "/../../ajax/deleteuser", + data: {"userid": result}, + success: function (data) { + selections = selections.filter( ( el ) => !result.includes( el ) ); + // selections = selections.filter(item => item !== userId); + handleListServerResponse(data); + }, + error: function (data) { + handleListServerResponse({type:"danger", message:data.responseText}) + }, + }); + } + ); + }); function user_handle (userId) { $.ajax({ method:"post", url: window.location.pathname + "/../../ajax/deleteuser", data: {"userid":userId} }); - $.ajax({ - method:"get", - url: window.location.pathname + "/../../ajax/listusers", - async: true, - timeout: 900, - success:function(data) { - $("#user-table").bootstrapTable("load", data); - loadSuccess(); - } - }); + $("#user-table").bootstrapTable("refresh"); } $("#user-table").on("click-cell.bs.table", function (field, value, row, $element) { @@ -642,23 +656,13 @@ function handleListServerResponse (data, disableButtons) { $("#flash_success").remove(); $("#flash_danger").remove(); if (!jQuery.isEmptyObject(data)) { - $( ".navbar" ).after( '
' + - '
'+data.message+'
' + - '
'); + data.forEach(function(item) { + $(".navbar").after('
' + + '
' + item.message + '
' + + '
'); + }); } - $.ajax({ - method: "get", - url: window.location.pathname + "/../../ajax/listusers", - async: true, - timeout: 900, - success: function (data) { - $("#user-table").bootstrapTable("load", data); - if (disableButtons) { - deactivateHeaderButtons(); - } - loadSuccess(); - } - }); + $("#user-table").bootstrapTable("refresh"); } @@ -675,14 +679,16 @@ function checkboxChange(checkbox, userId, field, field_index) { } function deactivateHeaderButtons() { - $("#user_delete_selection").addClass("disabled"); - $("#user_delete_selection").attr("aria-disabled", true); - $(".check_head").attr("aria-disabled", true); - $(".check_head").attr("disabled", true); - $(".check_head").prop('checked', false); - $(".button_head").attr("aria-disabled", true); - $(".button_head").addClass("disabled"); - $(".header_select").attr("disabled", true); + if (selections.length < 1) { + $("#user_delete_selection").addClass("disabled"); + $("#user_delete_selection").attr("aria-disabled", true); + $(".check_head").attr("aria-disabled", true); + $(".check_head").attr("disabled", true); + $(".check_head").prop('checked', false); + $(".button_head").attr("aria-disabled", true); + $(".button_head").addClass("disabled"); + $(".header_select").attr("disabled", true); + } } function selectHeader(element, field) { @@ -719,7 +725,7 @@ function checkboxHeader(CheckboxState, field, field_index) { }); } -function deleteUser(a,b){ +function deleteUser(a,id){ confirmDialog( "btndeluser", "GeneralDeleteModal", @@ -728,8 +734,12 @@ function deleteUser(a,b){ $.ajax({ method:"post", url: window.location.pathname + "/../../ajax/deleteuser", - data: {"userid":b}, - success: handleListServerResponse, + data: {"userid":id}, + success: function (data) { + userId = parseInt(id, 10); + selections = selections.filter(item => item !== userId); + handleListServerResponse(data); + }, error: function (data) { handleListServerResponse({type:"danger", message:data.responseText}) }, diff --git a/test/Calibre-Web TestSummary_Linux.html b/test/Calibre-Web TestSummary_Linux.html index 17df679b..0376c51f 100644 --- a/test/Calibre-Web TestSummary_Linux.html +++ b/test/Calibre-Web TestSummary_Linux.html @@ -37,20 +37,20 @@
-

Start Time: 2021-04-12 21:44:07

+

Start Time: 2021-04-21 07:09:48

-

Stop Time: 2021-04-13 00:22:44

+

Stop Time: 2021-04-21 09:55:49

-

Duration: 2h 7 min

+

Duration: 2h 16 min

@@ -1148,12 +1148,12 @@ - + TestEditBooksList 10 - 6 - 3 - 1 + 10 + 0 + 0 0 Detail @@ -1171,74 +1171,20 @@ - +
TestEditBooksList - test_bookslist_edit_categories
- -
- ERROR -
- - - - + PASS - +
TestEditBooksList - test_bookslist_edit_languages
- -
- FAIL -
- - - - + PASS @@ -1261,33 +1207,11 @@ AssertionError: '+' != 'English' - +
TestEditBooksList - test_bookslist_edit_seriesindex
- -
- FAIL -
- - - - + PASS @@ -1319,46 +1243,22 @@ AssertionError: '+' != '3' - +
TestEditBooksList - test_search_books_list
- -
- FAIL -
- - - - + PASS - + TestEditBooksOnGdrive 20 - 18 - 1 - 1 + 20 + 0 + 0 0 Detail @@ -1376,35 +1276,11 @@ AssertionError: 'Beutlin, Frodo & Halagal, Norbert & Yang, Liu & Gonçalves, Hec - +
TestEditBooksOnGdrive - test_edit_author
- -
- FAIL -
- - - - + PASS @@ -1526,31 +1402,11 @@ AssertionError: 'Pipo, Pipe' != 'Pipo| Pipe' - +
TestEditBooksOnGdrive - test_edit_title
- -
- ERROR -
- - - - + PASS @@ -1802,11 +1658,11 @@ AttributeError: 'bool' object has no attribute 'text' - + TestKoboSync 9 - 8 - 1 + 9 + 0 0 0 @@ -1816,40 +1672,11 @@ AttributeError: 'bool' object has no attribute 'text' - +
TestKoboSync - test_book_download
- -
- FAIL -
- - - - + PASS @@ -2295,11 +2122,11 @@ AssertionError: IndexError('list index out of range') is not false : [{'NewEntit - + TestMergeBooksList 2 - 1 - 1 + 2 + 0 0 0 @@ -2309,31 +2136,11 @@ AssertionError: IndexError('list index out of range') is not false : [{'NewEntit - +
TestMergeBooksList - test_delete_book
- -
- FAIL -
- - - - + PASS @@ -2383,13 +2190,13 @@ AssertionError: False is not true TestOPDSFeed - 22 - 22 + 23 + 23 0 0 0 - Detail + Detail @@ -2433,7 +2240,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_cover
+
TestOPDSFeed - test_opds_colon_password
PASS @@ -2442,7 +2249,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_download_book
+
TestOPDSFeed - test_opds_cover
PASS @@ -2451,7 +2258,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_formats
+
TestOPDSFeed - test_opds_download_book
PASS @@ -2460,7 +2267,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_guest_user
+
TestOPDSFeed - test_opds_formats
PASS @@ -2469,7 +2276,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_hot
+
TestOPDSFeed - test_opds_guest_user
PASS @@ -2478,7 +2285,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_language
+
TestOPDSFeed - test_opds_hot
PASS @@ -2487,7 +2294,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_non_admin
+
TestOPDSFeed - test_opds_language
PASS @@ -2496,7 +2303,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_publisher
+
TestOPDSFeed - test_opds_non_admin
PASS @@ -2505,7 +2312,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_random
+
TestOPDSFeed - test_opds_publisher
PASS @@ -2514,7 +2321,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_ratings
+
TestOPDSFeed - test_opds_random
PASS @@ -2523,7 +2330,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_read_unread
+
TestOPDSFeed - test_opds_ratings
PASS @@ -2532,7 +2339,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_search
+
TestOPDSFeed - test_opds_read_unread
PASS @@ -2541,7 +2348,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_series
+
TestOPDSFeed - test_opds_search
PASS @@ -2550,7 +2357,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_shelf_access
+
TestOPDSFeed - test_opds_series
PASS @@ -2559,7 +2366,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_tags
+
TestOPDSFeed - test_opds_shelf_access
PASS @@ -2568,7 +2375,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_top_rated
+
TestOPDSFeed - test_opds_tags
PASS @@ -2577,7 +2384,7 @@ AssertionError: False is not true -
TestOPDSFeed - test_opds_unicode_user
+
TestOPDSFeed - test_opds_top_rated
PASS @@ -2585,6 +2392,15 @@ AssertionError: False is not true + +
TestOPDSFeed - test_opds_unicode_user
+ + PASS + + + + +
TestOPDSFeed - test_recently_added
@@ -3009,74 +2825,34 @@ AssertionError: False is not true - + TestUserList - 11 - 2 - 6 - 2 + 14 + 13 + 0 + 0 1 - Detail + Detail - +
TestUserList - test_list_visibility
- -
- FAIL -
- - - - + PASS - +
TestUserList - test_user_list_admin_role
- -
- FAIL -
- - - - + PASS @@ -3107,93 +2883,29 @@ AssertionError: False is not true - +
TestUserList - test_user_list_download_role
- -
- FAIL -
- - - - + PASS - +
TestUserList - test_user_list_edit_button
- -
- FAIL -
- - - - + PASS - +
TestUserList - test_user_list_edit_email
- -
- ERROR -
- - - - + PASS @@ -3207,33 +2919,11 @@ AttributeError: 'bool' object has no attribute 'text' - +
TestUserList - test_user_list_edit_language
- -
- FAIL -
- - - - + PASS @@ -3247,60 +2937,47 @@ AssertionError: 'English' != 'German' - +
TestUserList - test_user_list_edit_name
- -
- ERROR -
- - - - + PASS - +
TestUserList - test_user_list_edit_visiblility
- -
- FAIL -
- - - + PASS + + + + + + +
TestUserList - test_user_list_guest_edit
+ PASS + + + + + + +
TestUserList - test_user_list_search
+ + PASS + + + + + + +
TestUserList - test_user_list_sort
+ + PASS @@ -4006,10 +3683,10 @@ AssertionError: True is not false Total - 322 - 298 - 12 - 4 + 326 + 318 + 0 + 0 8   @@ -4038,7 +3715,7 @@ AssertionError: True is not false Platform - Linux 5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021 x86_64 x86_64 + Linux 5.8.0-50-generic #56~20.04.1-Ubuntu SMP Mon Apr 12 21:46:35 UTC 2021 x86_64 x86_64 Basic @@ -4158,7 +3835,7 @@ AssertionError: True is not false google-api-python-client - 2.1.0 + 2.2.0 TestEbookConvertCalibreGDrive @@ -4182,7 +3859,7 @@ AssertionError: True is not false PyDrive2 - 1.8.1 + 1.8.2 TestEbookConvertCalibreGDrive @@ -4194,7 +3871,7 @@ AssertionError: True is not false google-api-python-client - 2.1.0 + 2.2.0 TestEbookConvertGDriveKepubify @@ -4218,7 +3895,7 @@ AssertionError: True is not false PyDrive2 - 1.8.1 + 1.8.2 TestEbookConvertGDriveKepubify @@ -4254,7 +3931,7 @@ AssertionError: True is not false google-api-python-client - 2.1.0 + 2.2.0 TestEditBooksOnGdrive @@ -4278,7 +3955,7 @@ AssertionError: True is not false PyDrive2 - 1.8.1 + 1.8.2 TestEditBooksOnGdrive @@ -4290,7 +3967,7 @@ AssertionError: True is not false google-api-python-client - 2.1.0 + 2.2.0 TestSetupGdrive @@ -4308,7 +3985,7 @@ AssertionError: True is not false PyDrive2 - 1.8.1 + 1.8.2 TestSetupGdrive @@ -4380,7 +4057,8 @@ AssertionError: True is not false diff --git a/test/js/runner.js b/test/js/runner.js index 67b3fa39..800338d1 100644 --- a/test/js/runner.js +++ b/test/js/runner.js @@ -1,3 +1,4 @@ + output_list = Array(); /* Level - 0: Summary; 1: Failed; 2: All; 3: Skipped 4: Error*/ @@ -24,9 +25,9 @@ function showCase(level) { row.classList.add('hiddenRow'); } } - // Show skipped if all or skipped or summary problems selected + // Show skipped if all or skipped selected if (id.substr(0,2) == 'st') { - if (level ==2 || level ==3 || level == 5) { + if (level ==2 || level ==3) { row.classList.remove('hiddenRow'); } else {