Update mass edit
Refactored delete User function Updated testresults
This commit is contained in:
+14
-9
@@ -40,7 +40,7 @@ from flask_babel import gettext as _
|
||||
from flask_babel import get_locale, format_time, format_datetime, format_timedelta
|
||||
from sqlalchemy import and_
|
||||
from sqlalchemy.orm.attributes import flag_modified
|
||||
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError
|
||||
from sqlalchemy.exc import IntegrityError, OperationalError, InvalidRequestError, ArgumentError
|
||||
from sqlalchemy.sql.expression import func, or_, text
|
||||
|
||||
from . import constants, logger, helper, services, cli_param
|
||||
@@ -386,13 +386,12 @@ def list_users():
|
||||
@user_login_required
|
||||
@admin_required
|
||||
def delete_user():
|
||||
user_ids = request.form.to_dict(flat=False)
|
||||
users = None
|
||||
user_ids = request.get_json().get("userid")
|
||||
message = ""
|
||||
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()
|
||||
try:
|
||||
users = ub.session.query(ub.User).filter(ub.User.id.in_(user_ids)).all()
|
||||
except (ArgumentError):
|
||||
users = None
|
||||
count = 0
|
||||
errors = list()
|
||||
success = list()
|
||||
@@ -408,10 +407,10 @@ def delete_user():
|
||||
errors.append({'type': "danger", 'message': str(ex)})
|
||||
|
||||
if count == 1:
|
||||
log.info("User {} deleted".format(user_ids))
|
||||
log.info("User {} deleted".format(user_ids[0]))
|
||||
success = [{'type': "success", 'message': message}]
|
||||
elif count > 1:
|
||||
log.info("Users {} deleted".format(user_ids))
|
||||
log.info("Users {} deleted".format(", ".join([str(user_id) for user_id in user_ids])))
|
||||
success = [{'type': "success", 'message': _("{} users deleted successfully").format(count)}]
|
||||
success.extend(errors)
|
||||
return make_response(jsonify(success))
|
||||
@@ -618,6 +617,8 @@ def load_dialogtexts(element_id):
|
||||
texts["main"] = _('Do you really want to delete this domain?')
|
||||
elif element_id == "btndeluser":
|
||||
texts["main"] = _('Do you really want to delete this user?')
|
||||
elif element_id == "btndelbook":
|
||||
texts["main"] = _('Do you really want to delete this book?')
|
||||
elif element_id == "delete_shelf":
|
||||
texts["main"] = _('Are you sure you want to delete this shelf?')
|
||||
elif element_id == "select_locale":
|
||||
@@ -626,6 +627,10 @@ def load_dialogtexts(element_id):
|
||||
texts["main"] = _('Are you sure you want to change visible book languages for selected user(s)?')
|
||||
elif element_id == "role":
|
||||
texts["main"] = _('Are you sure you want to change the selected role for the selected user(s)?')
|
||||
elif element_id == "archive_books":
|
||||
texts["main"] = _('Are you sure you want to change the archive status for the selected book(s)?')
|
||||
elif element_id == "read_books":
|
||||
texts["main"] = _('Are you sure you want to change the read status for the selected book(s)?')
|
||||
elif element_id == "restrictions":
|
||||
texts["main"] = _('Are you sure you want to change the selected restrictions for the selected user(s)?')
|
||||
elif element_id == "sidebar_view":
|
||||
|
||||
+217
-204
@@ -73,17 +73,18 @@ def edit_required(f):
|
||||
return inner
|
||||
|
||||
|
||||
@editbook.route("/ajax/delete/<int:book_id>", methods=["POST"])
|
||||
@editbook.route("/ajax/deletebook", methods=["POST"])
|
||||
@user_login_required
|
||||
def delete_book_from_details(book_id):
|
||||
return delete_book_from_table(book_id, "", True) # , mimetype='application/json')
|
||||
def delete_books_ajax():
|
||||
book_ids = request.get_json().get("bookid")
|
||||
return check_delete_book(book_ids, "", True)
|
||||
|
||||
|
||||
@editbook.route("/delete/<int:book_id>", defaults={'book_format': ""}, methods=["POST"])
|
||||
@editbook.route("/delete/<int:book_id>/<string:book_format>", methods=["POST"])
|
||||
@user_login_required
|
||||
def delete_book_ajax(book_id, book_format):
|
||||
return delete_book_from_table(book_id, book_format, False, request.form.to_dict().get('location', ""))
|
||||
def delete_book(book_id, book_format):
|
||||
return check_delete_book(book_id, book_format, False, request.form.to_dict().get('location', ""))
|
||||
|
||||
|
||||
@editbook.route("/admin/book/<int:book_id>", methods=['GET'])
|
||||
@@ -213,7 +214,7 @@ def table_get_custom_enum(c_id):
|
||||
@login_required_if_no_ano
|
||||
@edit_required
|
||||
def edit_list_book(param):
|
||||
vals = request.form.to_dict()
|
||||
vals = request.get_json() # form.to_dict(flat=False)
|
||||
return edit_book_param(param, vals)
|
||||
|
||||
@editbook.route("/ajax/editselectedbooks", methods=['POST'])
|
||||
@@ -233,42 +234,39 @@ def edit_selected_books():
|
||||
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 ""
|
||||
vals = {
|
||||
"pk": selections,
|
||||
"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})
|
||||
|
||||
# Separated from /editbooks so that /editselectedbooks can also use this
|
||||
#
|
||||
@@ -284,94 +282,96 @@ def edit_selected_books():
|
||||
@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 = ""
|
||||
ret = ""
|
||||
try:
|
||||
if param == 'series_index':
|
||||
edit_book_series_index(vals['value'], book)
|
||||
ret = make_response(jsonify(success=True, newValue=book.series_index))
|
||||
elif param == 'tags':
|
||||
edit_book_tags(vals['value'], book)
|
||||
ret = make_response(jsonify(success=True, newValue=', '.join([tag.name for tag in book.tags])))
|
||||
elif param == 'series':
|
||||
edit_book_series(vals['value'], book)
|
||||
ret = make_response(jsonify(success=True, newValue=', '.join([serie.name for serie in book.series])))
|
||||
elif param == 'publishers':
|
||||
edit_book_publisher(vals['value'], book)
|
||||
ret = make_response(jsonify(success=True,
|
||||
newValue=', '.join([publisher.name for publisher in book.publishers])))
|
||||
elif param == 'languages':
|
||||
invalid = list()
|
||||
edit_book_languages(vals['value'], book, invalid=invalid)
|
||||
if invalid:
|
||||
ret = make_response(jsonify(success=False,
|
||||
msg='Invalid languages in request: {}'.format(','.join(invalid))))
|
||||
else:
|
||||
lang_names = list()
|
||||
for lang in book.languages:
|
||||
lang_names.append(isoLanguages.get_language_name(get_locale(), lang.lang_code))
|
||||
ret = make_response(jsonify(success=True, newValue=', '.join(lang_names)))
|
||||
elif param == 'author_sort':
|
||||
book.author_sort = vals['value']
|
||||
ret = make_response(jsonify(success=True, newValue=book.author_sort))
|
||||
elif param == 'title':
|
||||
sort_param = book.sort
|
||||
if handle_title_on_edit(book, vals.get('value', "")):
|
||||
rename_error = helper.update_dir_structure(book.id, config.get_book_path())
|
||||
if not rename_error:
|
||||
ret = make_response(jsonify(success=True, newValue=book.title))
|
||||
elements = vals.get('pk',[])
|
||||
ret = {}
|
||||
for elem in elements:
|
||||
book = calibre_db.get_book(elem)
|
||||
calibre_db.create_functions(config)
|
||||
sort_param = ""
|
||||
try:
|
||||
if param == 'series_index':
|
||||
edit_book_series_index(vals['value'], book)
|
||||
ret = jsonify(success=True, newValue=book.series_index)
|
||||
elif param == 'tags':
|
||||
edit_book_tags(vals['value'], book)
|
||||
ret = jsonify(success=True, newValue=', '.join([tag.name for tag in book.tags]))
|
||||
elif param == 'series':
|
||||
edit_book_series(vals['value'], book)
|
||||
ret = jsonify(success=True, newValue=', '.join([serie.name for serie in book.series]))
|
||||
elif param == 'publishers':
|
||||
edit_book_publisher(vals['value'], book)
|
||||
ret = jsonify(success=True,
|
||||
newValue=', '.join([publisher.name for publisher in book.publishers]))
|
||||
elif param == 'languages':
|
||||
invalid = list()
|
||||
edit_book_languages(vals['value'], book, invalid=invalid)
|
||||
if invalid:
|
||||
ret = jsonify(success=False, msg='Invalid languages in request: {}'.format(','.join(invalid)))
|
||||
else:
|
||||
ret = make_response(jsonify(success=False, msg=rename_error))
|
||||
elif param == 'sort':
|
||||
book.sort = vals['value']
|
||||
ret = make_response(jsonify(success=True,newValue=book.sort))
|
||||
elif param == 'comments':
|
||||
edit_book_comments(vals['value'], book)
|
||||
ret = make_response(jsonify(success=True, newValue=book.comments[0].text))
|
||||
elif param == 'authors':
|
||||
input_authors, __ = handle_author_on_edit(book, vals['value'], vals.get('checkA', None) == "true")
|
||||
rename_error = helper.update_dir_structure(book.id, config.get_book_path(), input_authors[0])
|
||||
if not rename_error:
|
||||
ret = make_response(jsonify(
|
||||
success=True,
|
||||
newValue=' & '.join([author.replace('|', ',') for author in input_authors])))
|
||||
lang_names = list()
|
||||
for lang in book.languages:
|
||||
lang_names.append(isoLanguages.get_language_name(get_locale(), lang.lang_code))
|
||||
ret = jsonify(success=True, newValue=', '.join(lang_names))
|
||||
elif param == 'author_sort':
|
||||
book.author_sort = vals['value']
|
||||
ret = jsonify(success=True, newValue=book.author_sort)
|
||||
elif param == 'title':
|
||||
sort_param = book.sort
|
||||
if handle_title_on_edit(book, vals.get('value', "")):
|
||||
rename_error = helper.update_dir_structure(book.id, config.get_book_path())
|
||||
if not rename_error:
|
||||
ret = jsonify(success=True, newValue=book.title)
|
||||
else:
|
||||
ret = jsonify(success=False, msg=rename_error)
|
||||
elif param == 'sort':
|
||||
book.sort = vals['value']
|
||||
ret = jsonify(success=True,newValue=book.sort)
|
||||
elif param == 'comments':
|
||||
edit_book_comments(vals['value'], book)
|
||||
ret = jsonify(success=True, newValue=book.comments[0].text)
|
||||
elif param == 'authors':
|
||||
input_authors, __ = handle_author_on_edit(book, vals['value'], vals.get('checkA', None) == True)
|
||||
rename_error = helper.update_dir_structure(book.id, config.get_book_path(), input_authors[0])
|
||||
if not rename_error:
|
||||
ret = jsonify(
|
||||
success=True,
|
||||
newValue=' & '.join([author.replace('|', ',') for author in input_authors]))
|
||||
else:
|
||||
ret = jsonify(success=False, msg=rename_error)
|
||||
elif param == 'is_archived':
|
||||
is_archived = change_archived_books(book.id, vals['value'] == "True",
|
||||
message="Book {} archive bit set to: {}".format(book.id,
|
||||
vals['value']))
|
||||
if is_archived:
|
||||
kobo_sync_status.remove_synced_book(book.id)
|
||||
continue
|
||||
elif param == 'read_status':
|
||||
error = helper.edit_book_read_status(book.id, vals['value'] == "True")
|
||||
if error:
|
||||
return error, 400
|
||||
continue
|
||||
elif param.startswith("custom_column_"):
|
||||
new_val = dict()
|
||||
new_val[param] = vals['value']
|
||||
edit_single_cc_data(book.id, book, param[14:], new_val)
|
||||
# ToDo: Very hacky find better solution
|
||||
if vals['value'] in ["True", "False"]:
|
||||
ret = {}
|
||||
else:
|
||||
ret = jsonify(success=True, newValue=vals['value'])
|
||||
else:
|
||||
ret = make_response(jsonify(success=False, msg=rename_error))
|
||||
elif param == 'is_archived':
|
||||
is_archived = change_archived_books(book.id, vals['value'] == "True",
|
||||
message="Book {} archive bit set to: {}".format(book.id, vals['value']))
|
||||
if is_archived:
|
||||
kobo_sync_status.remove_synced_book(book.id)
|
||||
return ""
|
||||
elif param == 'read_status':
|
||||
ret = helper.edit_book_read_status(book.id, vals['value'] == "True")
|
||||
if ret:
|
||||
return ret, 400
|
||||
elif param.startswith("custom_column_"):
|
||||
new_val = dict()
|
||||
new_val[param] = vals['value']
|
||||
edit_single_cc_data(book.id, book, param[14:], new_val)
|
||||
# ToDo: Very hacky find better solution
|
||||
if vals['value'] in ["True", "False"]:
|
||||
ret = ""
|
||||
else:
|
||||
ret = make_response(jsonify(success=True, newValue=vals['value']))
|
||||
else:
|
||||
return _("Parameter not found"), 400
|
||||
book.last_modified = datetime.now(timezone.utc)
|
||||
return _("Parameter not found"), 400
|
||||
book.last_modified = datetime.now(timezone.utc)
|
||||
|
||||
calibre_db.session.commit()
|
||||
# revert change for sort if automatic fields link is deactivated
|
||||
if param == 'title' and vals.get('checkT') == "false":
|
||||
book.sort = sort_param
|
||||
calibre_db.session.commit()
|
||||
except (OperationalError, IntegrityError, StaleDataError) as e:
|
||||
calibre_db.session.rollback()
|
||||
log.error_or_exception("Database error: {}".format(e))
|
||||
ret = make_response(jsonify(success=False,
|
||||
msg='Database error: {}'.format(e.orig if hasattr(e, "orig") else e)))
|
||||
# revert change for sort if automatic fields link is deactivated
|
||||
if param == 'title' and vals.get('checkT') == False:
|
||||
book.sort = sort_param
|
||||
calibre_db.session.commit()
|
||||
except (OperationalError, IntegrityError, StaleDataError, AttributeError) as e:
|
||||
calibre_db.session.rollback()
|
||||
log.error_or_exception("Database error: {}".format(e))
|
||||
ret = jsonify(success=False, msg='Database error: {}'.format(e.orig if hasattr(e, "orig") else e))
|
||||
return ret
|
||||
|
||||
|
||||
@@ -433,16 +433,6 @@ def archive_selected_books():
|
||||
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
|
||||
@@ -498,7 +488,7 @@ def merge_list_book():
|
||||
element.format,
|
||||
element.uncompressed_size,
|
||||
to_name))
|
||||
delete_book_from_table(from_book.id, "", True)
|
||||
check_delete_book([from_book.id], "", True)
|
||||
return make_response(jsonify(success=True))
|
||||
return ""
|
||||
|
||||
@@ -968,86 +958,109 @@ 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, location=""):
|
||||
def render_delete_book_result(book_format, book_id, location=""):
|
||||
if book_format:
|
||||
if json_response:
|
||||
return jsonify([warning, {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "success",
|
||||
"format": book_format,
|
||||
"message": _('Book Format Successfully Deleted')}])
|
||||
else:
|
||||
flash(_('Book Format Successfully Deleted'), category="success")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
flash(_('Book Format Successfully Deleted'), category="success")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
else:
|
||||
if json_response:
|
||||
return jsonify([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(get_redirect_location(location, "web.index"))
|
||||
flash(_('Book Successfully Deleted'), category="success")
|
||||
return redirect(get_redirect_location(location, "web.index"))
|
||||
|
||||
|
||||
def delete_book_from_table(book_id, book_format, json_response, location=""):
|
||||
warning = {}
|
||||
def check_delete_book(book_id, book_format, json_response, location=""):
|
||||
if current_user.role_delete_books():
|
||||
book = calibre_db.get_book(book_id)
|
||||
if book:
|
||||
try:
|
||||
result, error = helper.delete_book(book, config.get_book_path(), book_format=book_format.upper())
|
||||
if not result:
|
||||
if json_response:
|
||||
return jsonify([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": error}])
|
||||
else:
|
||||
flash(error, category="error")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
if error:
|
||||
if json_response:
|
||||
warning = {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "warning",
|
||||
"format": "",
|
||||
"message": error}
|
||||
else:
|
||||
flash(error, category="warning")
|
||||
if not book_format:
|
||||
delete_whole_book(book_id, book)
|
||||
else:
|
||||
calibre_db.session.query(db.Data).filter(db.Data.book == book.id).\
|
||||
filter(db.Data.format == book_format).delete()
|
||||
if book_format.upper() in ['KEPUB', 'EPUB', 'EPUB3']:
|
||||
kobo_sync_status.remove_synced_book(book.id, True)
|
||||
calibre_db.session.commit()
|
||||
except Exception as ex:
|
||||
log.error_or_exception(ex)
|
||||
calibre_db.session.rollback()
|
||||
if json_response:
|
||||
return jsonify([{"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": ex}])
|
||||
else:
|
||||
flash(str(ex), category="error")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
|
||||
if json_response:
|
||||
# if json response is set, it's possible to delete more than one book, but never a format is deleted
|
||||
res = list()
|
||||
for b in book_id:
|
||||
ret = delete_book_from_table(b)
|
||||
if ret:
|
||||
res.extend([ret])
|
||||
if len(res) == 0:
|
||||
return [{"location": get_redirect_location(location, "web.index"),
|
||||
"type": "success",
|
||||
"format": "",
|
||||
"message": _('Book Successfully Deleted')}]
|
||||
return jsonify(res)
|
||||
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, location)
|
||||
return delete_book_from_UI(book_id, book_format, location)
|
||||
message = _("You are missing permissions to delete books")
|
||||
if json_response:
|
||||
return jsonify({"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": message})
|
||||
try:
|
||||
return jsonify({"location": url_for("edit-book.show_edit_book", book_id=int(book_id)),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": message})
|
||||
except TypeError as e:
|
||||
return jsonify({"location": url_for("web.index"), "type": "danger", "format": "",
|
||||
"message": str(e)})
|
||||
else:
|
||||
flash(message, category="error")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
|
||||
|
||||
def delete_book_from_UI(book_id, book_format, location=""):
|
||||
book = calibre_db.get_book(book_id)
|
||||
if book:
|
||||
try:
|
||||
result, error = helper.delete_book(book, config.get_book_path(), book_format=book_format.upper())
|
||||
if not result:
|
||||
flash(error, category="error")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
if error:
|
||||
flash(error, category="warning")
|
||||
if not book_format:
|
||||
delete_whole_book(book_id, book)
|
||||
else:
|
||||
calibre_db.session.query(db.Data).filter(db.Data.book == book.id). \
|
||||
filter(db.Data.format == book_format).delete()
|
||||
if book_format.upper() in ['KEPUB', 'EPUB', 'EPUB3']:
|
||||
kobo_sync_status.remove_synced_book(book.id, True)
|
||||
calibre_db.session.commit()
|
||||
except Exception as ex:
|
||||
log.error_or_exception(ex)
|
||||
calibre_db.session.rollback()
|
||||
flash(str(ex), category="error")
|
||||
return redirect(url_for('edit-book.show_edit_book', book_id=book_id))
|
||||
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, book_id, location)
|
||||
|
||||
|
||||
def delete_book_from_table(book_id):
|
||||
book = calibre_db.get_book(book_id)
|
||||
if book:
|
||||
try:
|
||||
result, error = helper.delete_book(book, config.get_book_path(), book_format="")
|
||||
if not result:
|
||||
return {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": error}
|
||||
delete_whole_book(book_id, book)
|
||||
calibre_db.session.commit()
|
||||
if error:
|
||||
return {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "warning",
|
||||
"format": "",
|
||||
"message": error}
|
||||
except Exception as ex:
|
||||
log.error_or_exception(ex)
|
||||
calibre_db.session.rollback()
|
||||
return {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": ex}
|
||||
else:
|
||||
# book not found
|
||||
log.error('Book with id "%s" could not be deleted: not found', book_id)
|
||||
return {"location": url_for("edit-book.show_edit_book", book_id=book_id),
|
||||
"type": "danger",
|
||||
"format": "",
|
||||
"message": _('Book with id "{}" could not be deleted: not found'.format(book_id))}
|
||||
|
||||
|
||||
def render_edit_book(book_id):
|
||||
cc = calibre_db.session.query(db.CustomColumns).filter(db.CustomColumns.datatype.notin_(db.cc_exceptions)).all()
|
||||
book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
|
||||
|
||||
+8
-10
@@ -307,18 +307,16 @@ def edit_book_read_status(book_id, read_status=None):
|
||||
if not config.config_read_column:
|
||||
book = ub.session.query(ub.ReadBook).filter(and_(ub.ReadBook.user_id == int(current_user.id),
|
||||
ub.ReadBook.book_id == book_id)).first()
|
||||
if book:
|
||||
if read_status is None:
|
||||
if book.read_status == ub.ReadBook.STATUS_FINISHED:
|
||||
book.read_status = ub.ReadBook.STATUS_UNREAD
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED if read_status == True else ub.ReadBook.STATUS_UNREAD
|
||||
else:
|
||||
if not book:
|
||||
read_book = ub.ReadBook(user_id=current_user.id, book_id=book_id)
|
||||
read_book.read_status = ub.ReadBook.STATUS_FINISHED
|
||||
book = read_book
|
||||
if read_status is None:
|
||||
if book.read_status == ub.ReadBook.STATUS_FINISHED:
|
||||
book.read_status = ub.ReadBook.STATUS_UNREAD
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED
|
||||
else:
|
||||
book.read_status = ub.ReadBook.STATUS_FINISHED if read_status == True else ub.ReadBook.STATUS_UNREAD
|
||||
if not book.kobo_reading_state:
|
||||
kobo_reading_state = ub.KoboReadingState(user_id=current_user.id, book_id=book_id)
|
||||
kobo_reading_state.current_bookmark = ub.KoboBookmark()
|
||||
|
||||
@@ -56,7 +56,7 @@ def remove_synced_book(book_id, all=False, session=None):
|
||||
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 and (state == True or state == None):
|
||||
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 != None else not archived_book.is_archived
|
||||
|
||||
@@ -229,10 +229,12 @@ $("#delete_confirm").click(function(event) {
|
||||
postButton(event, getPath() + "/delete/" + deleteId + "/" + bookFormat);
|
||||
} else {
|
||||
if (ajaxResponse) {
|
||||
path = getPath() + "/ajax/delete/" + deleteId;
|
||||
$.ajax({
|
||||
method:"post",
|
||||
url: path,
|
||||
url: getPath() + "/ajax/deletebook",
|
||||
method: "post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({"bookid": [deleteId]}),
|
||||
timeout: 900,
|
||||
success:function(data) {
|
||||
data.forEach(function(item) {
|
||||
|
||||
+155
-55
@@ -119,18 +119,17 @@ $(function() {
|
||||
$("#edit_selected_books").attr("aria-disabled", true);
|
||||
}
|
||||
if (selections.length < 1) {
|
||||
$("#delete_selection").addClass("disabled");
|
||||
$("#delete_selection").attr("aria-disabled", true);
|
||||
// $("#book_delete_selection").addClass("disabled");
|
||||
// $("#book_delete_selection").attr("aria-disabled", true);
|
||||
$("#table_xchange").addClass("disabled");
|
||||
$("#table_xchange").attr("aria-disabled", true);
|
||||
} else {
|
||||
$("#delete_selection").removeClass("disabled");
|
||||
$("#delete_selection").attr("aria-disabled", false);
|
||||
// $("#book_delete_selection").removeClass("disabled");
|
||||
// $("#book_delete_selection").attr("aria-disabled", false);
|
||||
$("#table_xchange").removeClass("disabled");
|
||||
$("#table_xchange").attr("aria-disabled", false);
|
||||
|
||||
}
|
||||
|
||||
handle_header_buttons();
|
||||
});
|
||||
|
||||
// Small block to initialize the state of the author/title sort inputs in metadata form
|
||||
@@ -153,7 +152,7 @@ $(function() {
|
||||
})
|
||||
/////
|
||||
|
||||
$("#delete_selection").click(function() {
|
||||
$("#book_delete_selection").click(function () {
|
||||
$("#books-table").bootstrapTable("uncheckAll");
|
||||
});
|
||||
|
||||
@@ -162,7 +161,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/mergebooks",
|
||||
url: getPath() + "/ajax/mergebooks",
|
||||
data: JSON.stringify({"Merge_books":selections}),
|
||||
success: function success() {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -181,7 +180,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/simulatemerge",
|
||||
url: getPath() + "/ajax/simulatemerge",
|
||||
data: JSON.stringify({"Merge_books":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#merge_from').empty();
|
||||
@@ -207,7 +206,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/editselectedbooks",
|
||||
url: getPath() + "/ajax/editselectedbooks",
|
||||
data: JSON.stringify({
|
||||
"selections": selections,
|
||||
"title": $("#title_input").val(),
|
||||
@@ -250,7 +249,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
url: getPath() + "/ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-archive-selected-books').empty();
|
||||
@@ -262,12 +261,12 @@ $(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#archive_selected_confirm', function(event) {
|
||||
/*$(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",
|
||||
url: getPath() + "/ajax/archiveselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "archive": true}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -286,7 +285,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
url: getPath() + "/ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-unarchive-selected-books').empty();
|
||||
@@ -303,7 +302,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/archiveselectedbooks",
|
||||
url: getPath() + "/ajax/archiveselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "archive": false}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -322,7 +321,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
url: getPath() + "/ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-delete-selected-books').empty();
|
||||
@@ -339,7 +338,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/deleteselectedbooks",
|
||||
url: getPath() + "/ajax/deleteselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -358,7 +357,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
url: getPath() + "/ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-read-selected-books').empty();
|
||||
@@ -375,7 +374,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/readselectedbooks",
|
||||
url: getPath() + "/ajax/readselectedbooks",
|
||||
data: JSON.stringify({"selections":selections, "markAsRead": true}),
|
||||
success: function success(booTitles) {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -394,7 +393,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/displayselectedbooks",
|
||||
url: getPath() + "/ajax/displayselectedbooks",
|
||||
data: JSON.stringify({"selections":selections}),
|
||||
success: function success(booTitles) {
|
||||
$('#display-unread-selected-books').empty();
|
||||
@@ -411,21 +410,21 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/readselectedbooks",
|
||||
url: getPath() + "/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",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/xchange",
|
||||
url: getPath() + "/ajax/xchange",
|
||||
data: JSON.stringify({"xchange":selections}),
|
||||
success: function success() {
|
||||
$("#books-table").bootstrapTable("refresh");
|
||||
@@ -442,6 +441,10 @@ $(function() {
|
||||
editable: {
|
||||
mode: "inline",
|
||||
emptytext: "<span class='glyphicon glyphicon-plus'></span>",
|
||||
ajaxOptions: {
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
},
|
||||
success: function (response, __) {
|
||||
if (!response.success) return response.msg;
|
||||
return {newValue: response.newValue};
|
||||
@@ -449,7 +452,8 @@ $(function() {
|
||||
params: function (params) {
|
||||
params.checkA = $('#autoupdate_authorsort').prop('checked');
|
||||
params.checkT = $('#autoupdate_titlesort').prop('checked');
|
||||
return params
|
||||
params.pk = [params.pk];
|
||||
return JSON.stringify(params);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -483,7 +487,7 @@ $(function() {
|
||||
searchAlign: "left",
|
||||
showSearchButton : true,
|
||||
searchOnEnterKey: true,
|
||||
checkboxHeader: false,
|
||||
checkboxHeader: true,
|
||||
maintainMetaData: true,
|
||||
responseHandler: responseHandler,
|
||||
columns: column,
|
||||
@@ -497,7 +501,7 @@ $(function() {
|
||||
$.ajax({
|
||||
method:"get",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/sort_value/" + field + "/" + row.id,
|
||||
url: getPath() + "/ajax/sort_value/" + field + "/" + row.id,
|
||||
success: function success(data) {
|
||||
var key = Object.keys(data)[0];
|
||||
$("#books-table").bootstrapTable("updateCellByUniqueId", {
|
||||
@@ -509,6 +513,66 @@ $(function() {
|
||||
});
|
||||
}
|
||||
},
|
||||
onPostBody () {
|
||||
// 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();
|
||||
var index = elText.lastIndexOf('\n', elText.length - 2);
|
||||
if ( index > -1) {
|
||||
elText = elText.substr(index);
|
||||
}
|
||||
$(this).next().text(elText);
|
||||
});
|
||||
},
|
||||
onPostHeader() {
|
||||
$(".form-check").each(function () {
|
||||
var item = $(this).parent();
|
||||
var parent = item.parent().parent();
|
||||
if (parent.prop('nodeName') === "TH") {
|
||||
item.prependTo(parent);
|
||||
}
|
||||
});
|
||||
|
||||
if ($(".button_head").length) {
|
||||
if (!$._data($(".button_head").get(0), "events")) {
|
||||
$(".button_head").on("click", function () {
|
||||
var result = $('#books-table').bootstrapTable('getSelections').map(a => a.id);
|
||||
confirmDialog(
|
||||
"btndelbook",
|
||||
"GeneralDeleteModal",
|
||||
0,
|
||||
function () {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: getPath() + "/ajax/deletebook",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({"bookid": result}),
|
||||
success: function (data) {
|
||||
selections = selections.filter((el) => !result.includes(el));
|
||||
handleListServerResponse(data);
|
||||
},
|
||||
error: function (data) {
|
||||
handleListServerResponse([{type: "danger", message: data.responseText}])
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
if ($(".check_head").length) {
|
||||
if (!$._data($(".check_head").get(0), "events")) {
|
||||
$(".check_head").on("change", function () {
|
||||
var val = $(this).data("set");
|
||||
var name = $(this).data("name");
|
||||
var data = $(this).data("val");
|
||||
bookCheckboxHeader(val, name, data);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
onColumnSwitch: function (field, checked) {
|
||||
var visible = $("#books-table").bootstrapTable("getVisibleColumns");
|
||||
@@ -525,10 +589,16 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../ajax/table_settings",
|
||||
url: getPath() + "/ajax/table_settings",
|
||||
data: "{" + st + "}",
|
||||
});
|
||||
handle_header_buttons();
|
||||
},
|
||||
onLoadSuccess: function() {
|
||||
$("input:radio.check_head:checked").each(function () {
|
||||
$(this).prop('checked', false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#domain_allow_submit").click(function(event) {
|
||||
@@ -537,7 +607,7 @@ $(function() {
|
||||
$(this).closest("form").submit();
|
||||
$.ajax ({
|
||||
method:"get",
|
||||
url: window.location.pathname + "/../../ajax/domainlist/1",
|
||||
url: getPath() + "/ajax/domainlist/1",
|
||||
async: true,
|
||||
timeout: 900,
|
||||
success:function(data) {
|
||||
@@ -558,7 +628,7 @@ $(function() {
|
||||
$(this).closest("form").submit();
|
||||
$.ajax ({
|
||||
method:"get",
|
||||
url: window.location.pathname + "/../../ajax/domainlist/0",
|
||||
url: getPath() + "/ajax/domainlist/0",
|
||||
async: true,
|
||||
timeout: 900,
|
||||
success:function(data) {
|
||||
@@ -576,12 +646,12 @@ $(function() {
|
||||
function domainHandle(domainId) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
url: window.location.pathname + "/../../ajax/deletedomain",
|
||||
url: getPath() + "/ajax/deletedomain",
|
||||
data: {"domainid":domainId}
|
||||
});
|
||||
$.ajax({
|
||||
method:"get",
|
||||
url: window.location.pathname + "/../../ajax/domainlist/1",
|
||||
url: getPath() + "/ajax/domainlist/1",
|
||||
async: true,
|
||||
timeout: 900,
|
||||
success:function(data) {
|
||||
@@ -590,7 +660,7 @@ $(function() {
|
||||
});
|
||||
$.ajax({
|
||||
method:"get",
|
||||
url: window.location.pathname + "/../../ajax/domainlist/0",
|
||||
url: getPath() + "/ajax/domainlist/0",
|
||||
async: true,
|
||||
timeout: 900,
|
||||
success:function(data) {
|
||||
@@ -826,7 +896,7 @@ $(function() {
|
||||
method:"post",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
url: window.location.pathname + "/../../ajax/user_table_settings",
|
||||
url: getPath() + "/ajax/user_table_settings",
|
||||
data: "{" + st + "}",
|
||||
});
|
||||
handle_header_buttons();
|
||||
@@ -852,8 +922,8 @@ $(function() {
|
||||
|
||||
function handle_header_buttons () {
|
||||
if (selections.length < 1) {
|
||||
$("#user_delete_selection").addClass("disabled");
|
||||
$("#user_delete_selection").attr("aria-disabled", true);
|
||||
$(".mass_selection").addClass("disabled");
|
||||
$(".mass_selection").attr("aria-disabled", true);
|
||||
$(".check_head").attr("aria-disabled", true);
|
||||
$(".check_head").attr("disabled", true);
|
||||
$(".check_head").prop('checked', false);
|
||||
@@ -865,8 +935,8 @@ function handle_header_buttons () {
|
||||
$(".multi_selector").attr("disabled", true);
|
||||
$(".header_select").attr("disabled", true);
|
||||
} else {
|
||||
$("#user_delete_selection").removeClass("disabled");
|
||||
$("#user_delete_selection").attr("aria-disabled", false);
|
||||
$(".mass_selection").removeClass("disabled");
|
||||
$(".mass_selection").attr("aria-disabled", false);
|
||||
$(".check_head").attr("aria-disabled", false);
|
||||
$(".check_head").removeAttr("disabled");
|
||||
$(".button_head").attr("aria-disabled", false);
|
||||
@@ -875,8 +945,10 @@ function handle_header_buttons () {
|
||||
$(".multi_head").removeClass("hidden");
|
||||
$(".multi_selector").attr("aria-disabled", false);
|
||||
$(".multi_selector").removeAttr("disabled");
|
||||
$('.multi_selector').selectpicker('refresh');
|
||||
$(".header_select").removeAttr("disabled");
|
||||
if (typeof $.fn.selectpicker === "function") {
|
||||
$('.multi_selector').selectpicker('refresh');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,7 +1075,7 @@ function loadSuccess() {
|
||||
$("input[data-name='passwd_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||
$("input[data-name='edit_shelf_role'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||
$("input[data-name='sidebar_read_and_unread'][data-pk='"+guest.data("pk")+"']").prop("disabled", true);
|
||||
$(".user-remove[data-pk='"+guest.data("pk")+"']").hide();
|
||||
$(".user-remove[data-pk='" + guest.data("pk") + "']").hide();
|
||||
}
|
||||
|
||||
function move_header_elements() {
|
||||
@@ -1045,7 +1117,7 @@ function move_header_elements() {
|
||||
function () {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||
url: getPath() + "/ajax/editlistusers/" + field,
|
||||
data: {"pk": result, "value": values, "action": val},
|
||||
success: function (data) {
|
||||
handleListServerResponse(data);
|
||||
@@ -1059,7 +1131,6 @@ function move_header_elements() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$("#user_delete_selection").click(function () {
|
||||
$("#user-table").bootstrapTable("uncheckAll");
|
||||
});
|
||||
@@ -1090,8 +1161,10 @@ function move_header_elements() {
|
||||
function () {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: window.location.pathname + "/../../ajax/deleteuser",
|
||||
data: {"userid": result},
|
||||
url: getPath() + "/ajax/deleteuser",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({"userid": result}),
|
||||
success: function (data) {
|
||||
selections = selections.filter((el) => !result.includes(el));
|
||||
handleListServerResponse(data);
|
||||
@@ -1117,7 +1190,7 @@ function handleListServerResponse (data) {
|
||||
'</div>');
|
||||
});
|
||||
}
|
||||
$("#user-table").bootstrapTable("refresh");
|
||||
$(".table.table-striped").bootstrapTable("refresh");
|
||||
}
|
||||
|
||||
function checkboxChange(checkbox, userId, field, field_index) {
|
||||
@@ -1132,20 +1205,21 @@ function checkboxChange(checkbox, userId, field, field_index) {
|
||||
});
|
||||
}
|
||||
|
||||
function BookCheckboxChange(checkbox, userId, field) {
|
||||
function BookCheckboxChange(checkbox, bookId, field) {
|
||||
var value = checkbox.checked ? "True" : "False";
|
||||
var element = checkbox;
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: getPath() + "/ajax/editbooks/" + field,
|
||||
data: {"pk": userId, "value": value},
|
||||
data: JSON.stringify({"pk": [bookId], "value": value}),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
error: function(data) {
|
||||
element.checked = !element.checked;
|
||||
handleListServerResponse([{type:"danger", message:data.responseText}])
|
||||
},
|
||||
success: handleListServerResponse
|
||||
});
|
||||
console.log("test");
|
||||
}
|
||||
|
||||
function selectHeader(element, field) {
|
||||
@@ -1154,7 +1228,7 @@ function selectHeader(element, field) {
|
||||
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||
url: getPath() + "/ajax/editlistusers/" + field,
|
||||
data: {"pk": result, "value": element.value},
|
||||
error: function (data) {
|
||||
handleListServerResponse([{type:"danger", message:data.responseText}])
|
||||
@@ -1167,12 +1241,35 @@ function selectHeader(element, field) {
|
||||
}
|
||||
}
|
||||
|
||||
function bookCheckboxHeader(CheckboxState, text, field_index) {
|
||||
confirmDialog(text, "GeneralChangeModal", 0, function() {
|
||||
var result = $('#books-table').bootstrapTable('getSelections').map(a => a.id);
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: getPath() + "/ajax/editbooks/" + field_index,
|
||||
data: JSON.stringify({"pk": result, "field_index": field_index, "value": CheckboxState}),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
error: function (data) {
|
||||
handleListServerResponse([{type:"danger", message:data.responseText}])
|
||||
},
|
||||
success: function (data) {
|
||||
handleListServerResponse (data, true)
|
||||
},
|
||||
});
|
||||
},function() {
|
||||
$("input:radio.check_head:checked").each(function() {
|
||||
$(this).prop('checked', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkboxHeader(CheckboxState, field, field_index) {
|
||||
confirmDialog(field, "GeneralChangeModal", 0, function() {
|
||||
var result = $('#user-table').bootstrapTable('getSelections').map(a => a.id);
|
||||
$.ajax({
|
||||
method: "post",
|
||||
url: window.location.pathname + "/../../ajax/editlistusers/" + field,
|
||||
url: getPath() + "/ajax/editlistusers/" + field,
|
||||
data: {"pk": result, "field_index": field_index, "value": CheckboxState},
|
||||
error: function (data) {
|
||||
handleListServerResponse([{type:"danger", message:data.responseText}])
|
||||
@@ -1188,7 +1285,7 @@ function checkboxHeader(CheckboxState, field, field_index) {
|
||||
});
|
||||
}
|
||||
|
||||
function deleteUser(a,id){
|
||||
function deleteUser(a, id){
|
||||
confirmDialog(
|
||||
"btndeluser",
|
||||
"GeneralDeleteModal",
|
||||
@@ -1196,8 +1293,10 @@ function deleteUser(a,id){
|
||||
function() {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
url: window.location.pathname + "/../../ajax/deleteuser",
|
||||
data: {"userid":id},
|
||||
url: getPath() + "/ajax/deleteuser",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({"userid": [id]}),
|
||||
success: function (data) {
|
||||
userId = parseInt(id, 10);
|
||||
selections = selections.filter(item => item !== userId);
|
||||
@@ -1224,8 +1323,10 @@ function storeLocation() {
|
||||
function user_handle (userId) {
|
||||
$.ajax({
|
||||
method:"post",
|
||||
url: window.location.pathname + "/../../ajax/deleteuser",
|
||||
data: {"userid":userId}
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
data: JSON.stringify({"userid": [userId]}),
|
||||
url: getPath() + "/ajax/deleteuser",
|
||||
});
|
||||
$("#user-table").bootstrapTable("refresh");
|
||||
}
|
||||
@@ -1233,6 +1334,5 @@ function user_handle (userId) {
|
||||
function shorten_html(value, response) {
|
||||
if(value) {
|
||||
$(this).html("[...]");
|
||||
// value.split('\n').slice(0, 2).join("") +
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,27 +15,28 @@
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro book_checkbox_row(parameter, show_text, sort) -%}
|
||||
<th data-name="{{parameter}}" data-field="{{parameter}}" data-switchable="false"
|
||||
<th data-name="{{parameter}}" data-field="{{parameter}}"
|
||||
{% 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 class="form-check">
|
||||
<div>
|
||||
<input type="radio" class="check_head" data-set="True" data-val="{{ parameter }}" name="options_archive_selected_books" id="false_archive_selected_books" data-name="archive_books" disabled>{{_('Archive selected books')}}
|
||||
</div>
|
||||
<br>
|
||||
<div class="btn btn-default disabled" id="unarchive_selected_books" aria-disabled="true">
|
||||
{{_('Unarchive selected books')}}
|
||||
<div>
|
||||
<input type="radio" class="check_head" data-set="False" data-val="{{ parameter }}" name="options_unarchive_selected_books" data-name="archive_books" disabled>{{_('Unarchive selected books')}}
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
{% elif parameter == "read_status" %}
|
||||
<div class="btn btn-default disabled" id="read_selected_books" aria-disabled="true">
|
||||
{{_('Mark selected books as read')}}
|
||||
<div class="form-check">
|
||||
<div>
|
||||
<input type="radio" class="check_head" data-set="True" data-val="{{ parameter }}" name="options_read_selected_books" id="false_read_selected_books" data-name="read_books" disabled>{{_('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>
|
||||
<div>
|
||||
<input type="radio" class="check_head" data-set="False" data-val="{{ parameter }}" name="options_unread_selected_books" data-name="read_books" disabled>{{_('Mark selected books as unread')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{show_text}}
|
||||
</th>
|
||||
@@ -55,7 +56,7 @@
|
||||
<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">
|
||||
<div class="btn btn-default disabled mass_selection" id="book_delete_selection" aria-disabled="true">
|
||||
{{_('Clear selections')}}
|
||||
</div>
|
||||
<div class="btn btn-default disabled" id="edit_selected_books" aria-disabled="true">
|
||||
@@ -82,7 +83,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
{% if current_user.role_edit() %}
|
||||
<th data-field="state" data-checkbox="true" data-sortable="true"></th>
|
||||
<th data-field="state" data-checkbox="true" data-visible="true" data-sortable="true"></th>
|
||||
{% endif %}
|
||||
<th data-field="id" id="id" data-visible="false" data-switchable="false"></th>
|
||||
{{ text_table_row('title', _('Enter Title'),_('Title'), true, true) }}
|
||||
@@ -123,9 +124,9 @@
|
||||
{% 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">
|
||||
<div><div class="btn btn-default button_head disabled" aria-disabled="true">
|
||||
{{_('Delete selected books')}}
|
||||
</div>
|
||||
</div></div>
|
||||
<br>
|
||||
{{_('Delete')}}
|
||||
</th>
|
||||
@@ -137,6 +138,8 @@
|
||||
{% endblock %}
|
||||
{% block modal %}
|
||||
{{ delete_book(current_user.role_delete_books()) }}
|
||||
{{ delete_confirm_modal() }}
|
||||
{{ change_confirm_modal() }}
|
||||
{% if current_user.role_edit() %}
|
||||
<div class="modal fade" id="mergeModal" role="dialog" aria-labelledby="metaMergeLabel">
|
||||
<div class="modal-dialog">
|
||||
@@ -162,7 +165,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="delete_selected_modal" role="dialog" aria-labelledby="metaDeleteSelectedLabel">
|
||||
<!--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">
|
||||
@@ -180,7 +183,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<div class="modal fade" id="archive_selected_modal" role="dialog" aria-labelledby="metaArchiveSelectedLabel">
|
||||
<div class="modal-dialog">
|
||||
@@ -265,7 +268,7 @@
|
||||
<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">
|
||||
<div class="modal-header bg-info text-center">
|
||||
<span>{{_('Edit Metadata')}}</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
data-visible="{{element.get(array_field)}}"
|
||||
data-column="{{value.get(array_field)}}"
|
||||
data-formatter="checkboxFormatter">
|
||||
<div class="form-check">
|
||||
<div class="form-check">
|
||||
<div>
|
||||
<input type="radio" class="check_head" data-set="false" data-val="{{value.get(array_field)}}" name="options_{{array_field}}" id="false_{{array_field}}" data-name="{{parameter}}" disabled>{{_('Deny')}}
|
||||
</div>
|
||||
@@ -121,7 +121,7 @@
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<div class="col-xs-12 col-sm-12">
|
||||
<div class="row">
|
||||
<div class="btn btn-default disabled" id="user_delete_selection" aria-disabled="true">{{_('Remove Selections')}}</div>
|
||||
<div class="btn btn-default disabled mass_selection" id="user_delete_selection" aria-disabled="true">{{_('Clear selections')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<table id="user-table" class="table table-no-bordered table-striped"
|
||||
|
||||
Reference in New Issue
Block a user