1
0
mirror of https://github.com/janeczku/calibre-web.git synced 2024-11-28 08:58:41 +02:00

Bulk User management

This commit is contained in:
Ozzie Isaacs 2021-02-13 13:17:02 +01:00
parent c810c5275a
commit 0992bafe30
5 changed files with 226 additions and 69 deletions

View File

@ -35,6 +35,7 @@ from flask import Blueprint, flash, redirect, url_for, abort, request, make_resp
from flask_login import login_required, current_user, logout_user, confirm_login
from flask_babel import gettext as _
from sqlalchemy import and_
from sqlalchemy.orm.attributes import flag_modified
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
from sqlalchemy.sql.expression import func, or_
@ -225,11 +226,12 @@ def edit_user_table():
return render_title_template("user_table.html",
users=allUser.all(),
visiblility=visibility,
all_roles = constants.ALL_ROLES,
all_roles=constants.ALL_ROLES,
sidebar_settings=constants.sidebar_settings,
title=_(u"Edit Users"),
page="usertable")
@admi.route("/axjax/listusers")
@admi.route("/ajax/listusers")
@login_required
@admin_required
def list_users():
@ -242,8 +244,11 @@ def list_users():
all_user = all_user.filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS)
total_count = all_user.count()
if search:
users = all_user.filter().offset(off).limit(limit).all()
filtered_count = users.length()
users = all_user.filter(or_(func.lower(ub.User.nickname).ilike("%" + search + "%"),
func.lower(ub.User.kindle_mail).ilike("%" + search + "%"),
func.lower(ub.User.email).ilike("%" + search + "%")))\
.offset(off).limit(limit).all()
filtered_count = len(users)
else:
users = all_user.offset(off).limit(limit).all()
filtered_count = total_count
@ -255,6 +260,14 @@ def list_users():
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response
@admi.route("/ajax/deleteuser")
@login_required
@admin_required
def delete_user():
# ToDo User delete check also not last one
pass
return
@admi.route("/axjax/editlistusers/<param>", methods=['POST'])
@login_required
@ -285,6 +298,24 @@ def edit_list_user(param):
return ""
@admi.route("/ajax/user_table_settings", methods=['POST'])
@login_required
@admin_required
def update_table_settings():
# ToDo: Save table settings
current_user.view_settings['useredit'] = json.loads(request.data)
try:
try:
flag_modified(current_user, "view_settings")
except AttributeError:
pass
ub.session.commit()
except (InvalidRequestError, OperationalError):
log.error("Invalid request received: %r ", request, )
return "Invalid request", 400
return ""
@admi.route("/admin/viewconfig", methods=["POST"])
@login_required
@admin_required

View File

@ -88,6 +88,26 @@ SIDEBAR_ARCHIVED = 1 << 15
SIDEBAR_DOWNLOAD = 1 << 16
SIDEBAR_LIST = 1 << 17
sidebar_settings = {
"detail_random": DETAIL_RANDOM,
"sidebar_language": SIDEBAR_LANGUAGE,
"sidebar_series": SIDEBAR_SERIES,
"sidebar_category": SIDEBAR_CATEGORY,
"sidebar_random": SIDEBAR_RANDOM,
"sidebar_author": SIDEBAR_AUTHOR,
"sidebar_best_rated": SIDEBAR_BEST_RATED,
"sidebar_read_and_unread": SIDEBAR_READ_AND_UNREAD,
"sidebar_recent": SIDEBAR_RECENT,
"sidebar_sorted": SIDEBAR_SORTED,
"sidebar_publisher": SIDEBAR_PUBLISHER,
"sidebar_rating": SIDEBAR_RATING,
"sidebar_format": SIDEBAR_FORMAT,
"sidebar_archived": SIDEBAR_ARCHIVED,
"sidebar_download": SIDEBAR_DOWNLOAD,
"sidebar_list": SIDEBAR_LIST,
}
ADMIN_USER_ROLES = sum(r for r in ALL_ROLES.values()) & ~ROLE_ANONYMOUS
ADMIN_USER_SIDEBAR = (SIDEBAR_LIST << 1) - 1

View File

@ -116,7 +116,7 @@ $(function() {
search: true,
showColumns: true,
searchAlign: "left",
showSearchButton : false,
showSearchButton : true,
searchOnEnterKey: true,
checkboxHeader: false,
maintainMetaData: true,
@ -377,15 +377,24 @@ $(function() {
search: true,
showColumns: true,
searchAlign: "left",
showSearchButton : false,
showSearchButton : true,
searchOnEnterKey: true,
checkboxHeader: false,
checkboxHeader: true,
maintainMetaData: true,
responseHandler: responseHandler,
columns: user_column,
formatNoMatches: function () {
return "";
},
onPostBody () {
// var elements = ;
// Remove all checkboxes from Headers for showing the texts in the column selector
$('.columns [data-field]').each(function(){
var elText = $(this).next().text();
$(this).next().empty();
$(this).next().text(elText);
});
},
// eslint-disable-next-line no-unused-vars
/*onEditableSave: function (field, row, oldvalue, $el) {
if (field === "title" || field === "authors") {
@ -411,22 +420,47 @@ $(function() {
var hidden = $("#user-table").bootstrapTable("getHiddenColumns");
var st = "";
visible.forEach(function(item) {
st += "\"" + item.field + "\":\"" + "true" + "\",";
st += "\"" + item.name + "\":\"" + "true" + "\",";
});
hidden.forEach(function(item) {
st += "\"" + item.field + "\":\"" + "false" + "\",";
st += "\"" + item.name + "\":\"" + "false" + "\",";
});
st = st.slice(0, -1);
/*$.ajax({
$.ajax({
method:"post",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: window.location.pathname + "/../../ajax/table_settings",
url: window.location.pathname + "/../../ajax/user_table_settings",
data: "{" + st + "}",
});*/
});
},
});
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);
}
});
}
$("#user-table").on("click-cell.bs.table", function (field, value, row, $element) {
if (value === "denied_column_value") {
ConfirmDialog("btndeluser", $element.id, user_handle);
}
});
/*$("#user-table").on("check.bs.table check-all.bs.table uncheck.bs.table uncheck-all.bs.table",
function (e, rowsAfter, rowsBefore) {
@ -474,7 +508,7 @@ function EbookActions (value, row) {
/* Function for deleting books */
function UserActions (value, row) {
return [
"<div class=\"user-remove\" data-toggle=\"modal\" data-target=\"#GeneralDeleteModal\" data-ajax=\"1\" data-delete-id=\"" + row.id + "\" title=\"Remove\">",
"<div class=\"user-remove\" data-target=\"#GeneralDeleteModal\" title=\"Remove\">",
"<i class=\"glyphicon glyphicon-trash\"></i>",
"</div>"
].join("");
@ -507,3 +541,8 @@ function checkboxChange(checkbox, index){
reinit: false
});
}
function checkboxHeader(element) {
console.log("hallo");
}

View File

@ -1,7 +1,8 @@
{% extends "layout.html" %}
{% macro user_table_row(parameter, edit_text, show_text, validate) -%}
<th data-field="{{ parameter }}" id="{{ parameter }}" data-sortable="true"
data-visible = "{{visiblility.get(parameter)}}"
data-name="{{ parameter }}"
data-visible="{{visiblility.get(parameter)}}"
data-editable-type="text"
data-editable-url="{{ url_for('admin.edit_list_user', param=parameter)}}"
data-editable-title="{{ edit_text }}"
@ -16,28 +17,44 @@
{% endblock %}
{% block body %}
<h2 class="{{page}}">{{_(title)}}</h2>
<table>
</table>
<table id="user-table" class="table table-no-bordered table-striped"
data-url="{{url_for('admin.list_users')}}">
<thead>
<tr>
<th data-buttontext="{{_('Edit User')}}" data-formatter="singleUserFormatter"></th>
<th data-field="state" data-checkbox="true" data-sortable="true"></th>
<th data-field="id" id="id" data-visible="false" data-switchable="false"></th>
<th data-name="edit" data-buttontext="{{_('Edit User')}}" data-visible="{{visiblility.get('edit')}}" data-formatter="singleUserFormatter">{{_('Edit')}}</th>
<th data-name="state" data-field="state" data-checkbox="true" data-visible="{{visiblility.get('state')}}" data-sortable="true"></th>
<th data-name="id" data-field="id" id="id" data-visible="false" data-switchable="false"></th>
{{ user_table_row('nickname', _('Enter Username'), _('Username'), true) }}
{{ user_table_row('email', _('Enter E-mail Address'), _('E-mail Address'), true) }}
{{ user_table_row('kindle_mail', _('Enter Kindle E-mail Address'), _('Kindle E-mail'), true) }}
<th data-field="role" data-column="{{all_roles.admin_role}}" data-formatter="checkboxFormatter">{{_('Admin')}}</th>
<th data-field="role" data-column="{{all_roles.download_role}}" data-formatter="checkboxFormatter">{{_('Upload')}}</th>
<th data-field="role" data-column="{{all_roles.upload_role}}" data-formatter="checkboxFormatter">{{_('Download')}}</th>
<th data-field="role" data-column="{{all_roles.edit_role}}" data-formatter="checkboxFormatter">{{_('Edit')}}</th>
<th data-field="role" data-column="{{all_roles.passwd_role}}" data-formatter="checkboxFormatter">{{_('Change Password')}}</th>
<th data-field="role" data-column="{{all_roles.edit_shelf_role}}" data-formatter="checkboxFormatter">{{_('Edit Public Shelfs')}}</th>
<th data-field="role" data-column="{{all_roles.delete_role}}" data-formatter="checkboxFormatter">{{_('Delete')}}</th>
<th data-field="role" data-column="{{all_roles.viewer_role}}" data-formatter="checkboxFormatter">{{_('View')}}</th>
<th data-name="admin_role" data-field="role" data-visible="{{visiblility.get('admin_role')}}" data-column="{{all_roles.admin_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Admin')}}</th>
<th data-name="download_role" data-field="role" data-visible="{{visiblility.get('download_role')}}" data-column="{{all_roles.download_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Upload')}}</th>
<th data-name="upload_role" data-field="role" data-visible="{{visiblility.get('upload_role')}}" data-column="{{all_roles.upload_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Download')}}</th>
<th data-name="edit_role" data-field="role" data-visible="{{visiblility.get('edit_role')}}" data-column="{{all_roles.edit_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Edit')}}</th>
<th data-name="passwd_role" data-field="role" data-visible="{{visiblility.get('passwd_role')}}" data-column="{{all_roles.passwd_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Change Password')}}</th>
<th data-name="edit_shelf_role" data-field="role" data-visible="{{visiblility.get('edit_shelf_role')}}" data-column="{{all_roles.edit_shelf_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Edit Public Shelfs')}}</th>
<th data-name="delete_role" data-field="role" data-visible="{{visiblility.get('delete_role')}}" data-column="{{all_roles.delete_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('Delete')}}</th>
<th data-name="viewer_role" data-field="role" data-visible="{{visiblility.get('viewer_role')}}" data-column="{{all_roles.viewer_role}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chkhead" onchange="checkboxHeader(this)"><br>{{_('View')}}</th>
{{ user_table_row('denied_tags', _("Enter Users's Locale"), _("Users's Locale"), true) }}
{{ user_table_row('allowed_tags', _("Enter Users's Locale"), _("Users's Locale"), true) }}
{{ user_table_row('allowed_column_value', _("Enter Users's Locale"), _("Users's Locale"), true) }}
{{ user_table_row('denied_column_value', _("Enter Users's Locale"), _("Users's Locale"), true) }}
<th data-name="detail_random" data-field="sidebar_view" data-visible="{{visiblility.get('detail_random')}}" data-column="{{sidebar_settings.detail_random}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show Random Books in Detail View')}}</th>
<th data-name="sidebar_language" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_language')}}" data-column="{{sidebar_settings.sidebar_language}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show language selection')}}</th>
<th data-name="sidebar_series" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_series')}}" data-column="{{sidebar_settings.sidebar_series}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show series selection')}}</th>
<th data-name="sidebar_category" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_category')}}" data-column="{{sidebar_settings.sidebar_category}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{ _('Show category selection')}}</th>
<th data-name="sidebar_random" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_random')}}" data-column="{{sidebar_settings.sidebar_random}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{ _('Show random books')}}</th>
<th data-name="sidebar_author" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_author')}}" data-column="{{sidebar_settings.sidebar_author}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show author selection')}}</th>
<th data-name="sidebar_best_rated" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_best_rated')}}" data-column="{{sidebar_settings.sidebar_best_rated}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show Top Rated Books')}}</th>
<th data-name="sidebar_read_and_unread" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_read_and_unread')}}" data-column="{{sidebar_settings.sidebar_read_and_unread}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show random books')}}</th>
<th data-name="sidebar_publisher" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_publisher')}}" data-column="{{sidebar_settings.sidebar_publisher}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show publisher selection')}}</th>
<th data-name="sidebar_rating" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_rating')}}" data-column="{{sidebar_settings.sidebar_rating}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show ratings selection')}}</th>
<th data-name="sidebar_format" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_format')}}" data-column="{{sidebar_settings.sidebar_format}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show file formats selection')}}</th>
<th data-name="sidebar_archived" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_archived')}}" data-column="{{sidebar_settings.sidebar_archived}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show archived books')}}</th>
<th data-name="sidebar_download" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_download')}}" data-column="{{sidebar_settings.sidebar_download}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show Downloaded Books')}}</th>
<th data-name="sidebar_list" data-field="sidebar_view" data-visible="{{visiblility.get('sidebar_list')}}" data-column="{{sidebar_settings.sidebar_list}}" data-formatter="checkboxFormatter"><input type="checkbox" class="chk" ><br>{{_('Show Books List')}}</th>
<th data-align="right" data-formatter="UserActions" data-switchable="false">{{_('Delete User')}}</th>
</tr>
</thead>

View File

@ -37,14 +37,14 @@
<div class="row">
<div class="col-xs-6 col-md-6 col-sm-offset-3" style="margin-top:50px;">
<p class='text-justify attribute'><strong>Start Time: </strong>2021-02-08 20:40:55</p>
<p class='text-justify attribute'><strong>Start Time: </strong>2021-02-09 20:40:28</p>
</div>
</div>
<div class="row">
<div class="col-xs-6 col-md-6 col-sm-offset-3">
<p class='text-justify attribute'><strong>Stop Time: </strong>2021-02-08 23:09:33</p>
<p class='text-justify attribute'><strong>Stop Time: </strong>2021-02-09 23:08:52</p>
</div>
</div>
@ -1595,12 +1595,12 @@
<tr id="su" class="errorClass">
<tr id="su" class="passClass">
<td>TestKoboSync</td>
<td class="text-center">9</td>
<td class="text-center">8</td>
<td class="text-center">9</td>
<td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center">1</td>
<td class="text-center">0</td>
<td class="text-center">
<a onclick="showClassDetail('c18', 9)">Detail</a>
@ -1609,31 +1609,11 @@
<tr id="et18.1" class="none bg-info">
<tr id='pt18.1' class='hiddenRow bg-success'>
<td>
<div class='testcase'>TestKoboSync - test_book_download</div>
</td>
<td colspan='6'>
<div class="text-center">
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et18.1')">ERROR</a>
</div>
<!--css div popup start-->
<div id="div_et18.1" class="popup_window test_output" style="display:none;">
<div class='close_button pull-right'>
<button type="button" class="close" aria-label="Close" onfocus='this.blur();'
onclick='document.getElementById('div_et18.1').style.display='none'"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="text-left pull-left">
<pre class="text-left">Traceback (most recent call last):
File "/home/ozzie/Development/calibre-web-test/test/test_kobo_sync.py", line 593, in test_book_download
print(data[0]['NewEntitlement']['BookMetadata']['DownloadUrls'][1]['Url'])
IndexError: list index out of range</pre>
</div>
<div class="clearfix"></div>
</div>
<!--css div popup end-->
</td>
<td colspan='6' align='center'>PASS</td>
</tr>
@ -2376,11 +2356,11 @@ IndexError: list index out of range</pre>
<tr id="su" class="passClass">
<tr id="su" class="failClass">
<td>TestRegister</td>
<td class="text-center">8</td>
<td class="text-center">8</td>
<td class="text-center">0</td>
<td class="text-center">7</td>
<td class="text-center">1</td>
<td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center">
@ -2453,11 +2433,31 @@ IndexError: list index out of range</pre>
<tr id='pt25.8' class='hiddenRow bg-success'>
<tr id="ft25.8" class="none bg-danger">
<td>
<div class='testcase'>TestRegister - test_user_change_password</div>
</td>
<td colspan='6' align='center'>PASS</td>
<td colspan='6'>
<div class="text-center">
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft25.8')">FAIL</a>
</div>
<!--css div popup start-->
<div id="div_ft25.8" class="popup_window test_output" style="display:none;">
<div class='close_button pull-right'>
<button type="button" class="close" aria-label="Close" onfocus='this.blur();'
onclick='document.getElementById('div_ft25.8').style.display='none'"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="text-left pull-left">
<pre class="text-left">Traceback (most recent call last):
File "/home/ozzie/Development/calibre-web-test/test/test_register.py", line 185, in test_user_change_password
self.assertTrue(self.edit_user(u'upasswd', { 'resend_password':1}))
AssertionError: False is not true</pre>
</div>
<div class="clearfix"></div>
</div>
<!--css div popup end-->
</td>
</tr>
@ -2594,12 +2594,12 @@ IndexError: list index out of range</pre>
<tr id="su" class="skipClass">
<tr id="su" class="errorClass">
<td>TestUpdater</td>
<td class="text-center">8</td>
<td class="text-center">7</td>
<td class="text-center">0</td>
<td class="text-center">0</td>
<td class="text-center">5</td>
<td class="text-center">1</td>
<td class="text-center">1</td>
<td class="text-center">1</td>
<td class="text-center">
<a onclick="showClassDetail('c27', 8)">Detail</a>
@ -2653,11 +2653,31 @@ IndexError: list index out of range</pre>
<tr id='pt27.6' class='hiddenRow bg-success'>
<tr id="ft27.6" class="none bg-danger">
<td>
<div class='testcase'>TestUpdater - test_perform_update_stable_errors</div>
</td>
<td colspan='6' align='center'>PASS</td>
<td colspan='6'>
<div class="text-center">
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_ft27.6')">FAIL</a>
</div>
<!--css div popup start-->
<div id="div_ft27.6" class="popup_window test_output" style="display:none;">
<div class='close_button pull-right'>
<button type="button" class="close" aria-label="Close" onfocus='this.blur();'
onclick='document.getElementById('div_ft27.6').style.display='none'"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="text-left pull-left">
<pre class="text-left">Traceback (most recent call last):
File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 312, in test_perform_update_stable_errors
self.assertTrue('HTTP Error' in self.check_element_on_page((By.ID, "DialogContent")).text)
AssertionError: False is not true</pre>
</div>
<div class="clearfix"></div>
</div>
<!--css div popup end-->
</td>
</tr>
@ -2688,11 +2708,41 @@ IndexError: list index out of range</pre>
<tr id='pt27.8' class='hiddenRow bg-success'>
<tr id="et27.8" class="none bg-info">
<td>
<div class='testcase'>TestUpdater - test_reconnect_database</div>
</td>
<td colspan='6' align='center'>PASS</td>
<td colspan='6'>
<div class="text-center">
<a class="popup_link text-center" onfocus='blur()' onclick="showTestDetail('div_et27.8')">ERROR</a>
</div>
<!--css div popup start-->
<div id="div_et27.8" class="popup_window test_output" style="display:none;">
<div class='close_button pull-right'>
<button type="button" class="close" aria-label="Close" onfocus='this.blur();'
onclick='document.getElementById('div_et27.8').style.display='none'"><span
aria-hidden="true">&times;</span></button>
</div>
<div class="text-left pull-left">
<pre class="text-left">Traceback (most recent call last):
File "/home/ozzie/Development/calibre-web-test/test/test_updater.py", line 371, in test_reconnect_database
self.reconnect_database()
File "/home/ozzie/Development/calibre-web-test/test/helper_ui.py", line 359, in reconnect_database
self.driver.find_element_by_id('restart_database').click()
File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 80, in click
self._execute(Command.CLICK_ELEMENT)
File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
return self._parent.execute(command, params)
File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
self.error_handler.check_response(response)
File "/home/ozzie/Development/calibre-web-test/venv/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementClickInterceptedException: Message: Element <div id="restart_database" class="btn btn-default"> is not clickable at point (553,718) because another element <div id="StatusDialog" class="modal fade in"> obscures it</pre>
</div>
<div class="clearfix"></div>
</div>
<!--css div popup end-->
</td>
</tr>
@ -3399,8 +3449,8 @@ IndexError: list index out of range</pre>
<tr id='total_row' class="text-center bg-grey">
<td>Total</td>
<td>299</td>
<td>291</td>
<td>0</td>
<td>289</td>
<td>2</td>
<td>1</td>
<td>7</td>
<td>&nbsp;</td>
@ -3430,7 +3480,7 @@ IndexError: list index out of range</pre>
<tr>
<th>Platform</th>
<td>Linux 5.8.0-41-generic #46~20.04.1-Ubuntu SMP Mon Jan 18 17:52:23 UTC 2021 x86_64 x86_64</td>
<td>Linux 5.8.0-43-generic #49~20.04.1-Ubuntu SMP Fri Feb 5 09:57:56 UTC 2021 x86_64 x86_64</td>
<td>Basic</td>
</tr>
@ -3766,7 +3816,7 @@ IndexError: list index out of range</pre>
</div>
<script>
drawCircle(291, 0, 1, 7);
drawCircle(289, 2, 1, 7);
</script>
</div>