Added config option for shelf sync behavior

This commit is contained in:
Ozzie Isaacs 2021-05-15 10:45:51 +02:00
parent b3648187ff
commit d95838309e
9 changed files with 67 additions and 26 deletions

View File

@ -236,7 +236,7 @@ def edit_user_table():
custom_values = [] custom_values = []
if not config.config_anonbrowse: if not config.config_anonbrowse:
allUser = allUser.filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS) allUser = allUser.filter(ub.User.role.op('&')(constants.ROLE_ANONYMOUS) != constants.ROLE_ANONYMOUS)
kobo_support = feature_support['kobo'] and config.config_kobo_sync
return render_title_template("user_table.html", return render_title_template("user_table.html",
users=allUser.all(), users=allUser.all(),
tags=tags, tags=tags,
@ -245,6 +245,7 @@ def edit_user_table():
languages=languages, languages=languages,
visiblility=visibility, visiblility=visibility,
all_roles=constants.ALL_ROLES, all_roles=constants.ALL_ROLES,
kobo_support=kobo_support,
sidebar_settings=constants.sidebar_settings, sidebar_settings=constants.sidebar_settings,
title=_(u"Edit Users"), title=_(u"Edit Users"),
page="usertable") page="usertable")
@ -391,6 +392,8 @@ def edit_list_user(param):
user.name = check_username(vals['value']) user.name = check_username(vals['value'])
elif param =='email': elif param =='email':
user.email = check_email(vals['value']) user.email = check_email(vals['value'])
elif param =='kobo_only_shelves_sync':
user.kobo_only_shelves_sync = int(vals['value'] == 'true')
elif param == 'kindle_mail': elif param == 'kindle_mail':
user.kindle_mail = valid_email(vals['value']) if vals['value'] else "" user.kindle_mail = valid_email(vals['value']) if vals['value'] else ""
elif param.endswith('role'): elif param.endswith('role'):
@ -558,6 +561,8 @@ def load_dialogtexts(element_id):
texts["main"] = _('Are you sure you want to change the selected restrictions for the selected user(s)?') texts["main"] = _('Are you sure you want to change the selected restrictions for the selected user(s)?')
elif element_id == "sidebar_view": elif element_id == "sidebar_view":
texts["main"] = _('Are you sure you want to change the selected visibility restrictions for the selected user(s)?') texts["main"] = _('Are you sure you want to change the selected visibility restrictions for the selected user(s)?')
elif element_id == "kobo_only_shelves_sync":
texts["main"] = _('Are you sure you want to change shelf sync behavior for the selected user(s)?')
return json.dumps(texts) return json.dumps(texts)
@ -1314,6 +1319,7 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
content.denied_tags = config.config_denied_tags content.denied_tags = config.config_denied_tags
content.allowed_column_value = config.config_allowed_column_value content.allowed_column_value = config.config_allowed_column_value
content.denied_column_value = config.config_denied_column_value content.denied_column_value = config.config_denied_column_value
content.kobo_only_shelves_sync = 0 # No default value for kobo sync shelf setting
ub.session.add(content) ub.session.add(content)
ub.session.commit() ub.session.commit()
flash(_(u"User '%(user)s' created", user=content.name), category="success") flash(_(u"User '%(user)s' created", user=content.name), category="success")
@ -1381,6 +1387,8 @@ def _handle_edit_user(to_save, content, languages, translations, kobo_support):
else: else:
content.sidebar_view &= ~constants.DETAIL_RANDOM content.sidebar_view &= ~constants.DETAIL_RANDOM
content.kobo_only_shelves_sync = int(to_save.get("kobo_only_shelves_sync") == "on") or 0
if to_save.get("default_language"): if to_save.get("default_language"):
content.default_language = to_save["default_language"] content.default_language = to_save["default_language"]
if to_save.get("locale"): if to_save.get("locale"):

View File

@ -152,8 +152,8 @@ def HandleSyncRequest():
# in case of external changes (e.g: adding a book through Calibre). # in case of external changes (e.g: adding a book through Calibre).
calibre_db.reconnect_db(config, ub.app_DB_path) calibre_db.reconnect_db(config, ub.app_DB_path)
only_kobo_shelves = calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id)\ only_kobo_shelves = current_user.kobo_only_shelves_sync
.filter(ub.Shelf.kobo_sync).count() > 0 # calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id).filter(ub.Shelf.kobo_sync).count() > 0
if only_kobo_shelves: if only_kobo_shelves:
changed_entries = ( changed_entries = (

View File

@ -240,8 +240,8 @@ def edit_shelf(shelf_id):
# if shelf ID is set, we are editing a shelf # if shelf ID is set, we are editing a shelf
def create_edit_shelf(shelf, title, page, shelf_id=False): def create_edit_shelf(shelf, title, page, shelf_id=False):
sync_all_books = calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id)\ sync_only_selected_shelves = current_user.kobo_only_shelves_sync
.filter(ub.Shelf.kobo_sync).count() # calibre_db.session.query(ub.Shelf).filter(ub.Shelf.user_id == current_user.id).filter(ub.Shelf.kobo_sync).count()
if request.method == "POST": if request.method == "POST":
to_save = request.form.to_dict() to_save = request.form.to_dict()
shelf.is_public = 1 if to_save.get("is_public") else 0 shelf.is_public = 1 if to_save.get("is_public") else 0
@ -277,7 +277,7 @@ def create_edit_shelf(shelf, title, page, shelf_id=False):
title=title, title=title,
page=page, page=page,
kobo_sync_enabled=config.config_kobo_sync, kobo_sync_enabled=config.config_kobo_sync,
sync_all_books=sync_all_books) sync_only_selected_shelves=sync_only_selected_shelves)
def check_shelf_is_unique(shelf, to_save, shelf_id=False): def check_shelf_is_unique(shelf, to_save, shelf_id=False):

View File

@ -580,12 +580,19 @@ function singleUserFormatter(value, row) {
return '<a class="btn btn-default" onclick="storeLocation()" href="' + window.location.pathname + '/../../admin/user/' + row.id + '">' + this.buttontext + '</a>' return '<a class="btn btn-default" onclick="storeLocation()" href="' + window.location.pathname + '/../../admin/user/' + row.id + '">' + this.buttontext + '</a>'
} }
function checkboxFormatter(value, row, index){ function checkboxFormatter(value, row){
if(value & this.column) if(value & this.column)
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" checked onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">'; return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" checked onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
else else
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">'; return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', ' + this.column + ')">';
} }
function singlecheckboxFormatter(value, row){
if(value)
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" checked onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', 0)">';
else
return '<input type="checkbox" class="chk" data-pk="' + row.id + '" data-name="' + this.field + '" onchange="checkboxChange(this, ' + row.id + ', \'' + this.name + '\', 0)">';
}
/* Do some hiding disabling after user list is loaded */ /* Do some hiding disabling after user list is loaded */
function loadSuccess() { function loadSuccess() {

View File

@ -14,14 +14,10 @@
</label> </label>
</div> </div>
{% endif %} {% endif %}
{% if kobo_sync_enabled %} {% if kobo_sync_enabled and sync_only_selected_shelves %}
<div class="checkbox"> <div class="checkbox">
<label> <label> <input type="checkbox" name="kobo_sync" {% if shelf.kobo_sync == 1 %}checked{% endif %}>
<input type="checkbox" name="kobo_sync" {{ _('Sync this shelf with Kobo device') }}
{% if shelf.kobo_sync == 1 %}checked{% endif %}>
{% if shelf.kobo_sync == 1 and sync_all_books == 1 %}{{ _('Sync with Kobo device - If this option is turned off, all books and shelves will be synced with Kobo') }}
{% elif sync_all_books == 0 and shelf.kobo_sync == 0 %}{{ _('Only sync books from selected shelves to Kobo instead of all books and shelves') }}
{% else %}{{ _('Sync with Kobo device') }}{% endif %}
</label> </label>
</div> </div>
{% endif %} {% endif %}

View File

@ -66,7 +66,6 @@
<div class="btn btn-danger" id="config_delete_kobo_token" data-value="{{ content.id }}" data-remote="false" {% if not content.remote_auth_token.first() %} style="display: none;" {% endif %}>{{_('Delete')}}</div> <div class="btn btn-danger" id="config_delete_kobo_token" data-value="{{ content.id }}" data-remote="false" {% if not content.remote_auth_token.first() %} style="display: none;" {% endif %}>{{_('Delete')}}</div>
</div> </div>
{% endif %} {% endif %}
</div>
<div class="col-sm-6"> <div class="col-sm-6">
{% for element in sidebar %} {% for element in sidebar %}
{% if element['config_show'] %} {% if element['config_show'] %}
@ -125,6 +124,12 @@
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if kobo_support and not content.role_anonymous() %}
<div class="form-group">
<input type="checkbox" name="kobo_only_shelves_sync" id="kobo_only_shelves_sync" {% if content.kobo_only_shelves_sync %}checked{% endif %}>
<label for="kobo_only_shelves_sync">{{_('Sync only books in selected shelves with Kobo')}}</label>
</div>
{% endif %}
</div> </div>
<div class="col-sm-12"> <div class="col-sm-12">
<div id="user_submit" class="btn btn-default">{{_('Save')}}</div> <div id="user_submit" class="btn btn-default">{{_('Save')}}</div>

View File

@ -32,6 +32,21 @@
</th> </th>
{%- endmacro %} {%- endmacro %}
{% macro user_single_checkbox_row(parameter, show_text) -%}
<th data-name="{{parameter}}" data-field="{{parameter}}"
data-formatter="singlecheckboxFormatter">
<div class="form-check">
<div>
<input type="radio" class="check_head" data-set="false" data-val="0" name="{{parameter}}" id="false_{{parameter}}" data-name="{{parameter}}" disabled>{{_('Deny')}}
</div>
<div>
<input type="radio" class="check_head" data-set="true" data-val="1" name="{{parameter}}" data-name="{{parameter}}" disabled>{{_('Allow')}}
</div>
</div>
{{show_text}}
</th>
{%- endmacro %}
{% macro user_checkbox_row(parameter, array_field, show_text, element, value) -%} {% macro user_checkbox_row(parameter, array_field, show_text, element, value) -%}
<th data-name="{{array_field}}" data-field="{{parameter}}" <th data-name="{{array_field}}" data-field="{{parameter}}"
data-visible="{{element.get(array_field)}}" data-visible="{{element.get(array_field)}}"
@ -39,14 +54,10 @@
data-formatter="checkboxFormatter"> data-formatter="checkboxFormatter">
<div class="form-check"> <div class="form-check">
<div> <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')}}
<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> </div>
<div> <div>
<input type="radio" class="check_head" data-set="true" data-val="{{value.get(array_field)}}" name="options_{{array_field}}" data-name="{{parameter}}" disabled>{{_('Allow')}}
<input type="radio" class="check_head" data-set="true" data-val={{value.get(array_field)}} name="options_{{array_field}}" data-name="{{parameter}}" disabled>{{_('Allow')}}
</div> </div>
</div> </div>
{{show_text}} {{show_text}}
@ -134,7 +145,10 @@
{{ user_checkbox_row("role", "viewer_role", _('View'), visiblility, all_roles)}} {{ user_checkbox_row("role", "viewer_role", _('View'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_role", _('Edit'), visiblility, all_roles)}} {{ user_checkbox_row("role", "edit_role", _('Edit'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "delete_role", _('Delete'), visiblility, all_roles)}} {{ user_checkbox_row("role", "delete_role", _('Delete'), visiblility, all_roles)}}
{{ user_checkbox_row("role", "edit_shelf_role", _('Edit Public Shelfs'), visiblility, all_roles)}} {{ user_checkbox_row("role", "edit_shelf_role", _('Edit Public Shelves'), visiblility, all_roles)}}
{% if kobo_support %}
{{ user_single_checkbox_row("kobo_only_shelves_sync", _('Sync Selected Shelves with Kobo'))}}
{% endif %}
{{ user_checkbox_row("sidebar_view", "detail_random", _('Show Random Books in Detail View'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "detail_random", _('Show Random Books in Detail View'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_language", _('Show language selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_language", _('Show language selection'), visiblility, sidebar_settings)}}
{{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show read/unread selection'), visiblility, sidebar_settings)}} {{ user_checkbox_row("sidebar_view", "sidebar_read_and_unread", _('Show read/unread selection'), visiblility, sidebar_settings)}}

View File

@ -188,7 +188,7 @@ class User(UserBase, Base):
allowed_column_value = Column(String, default="") allowed_column_value = Column(String, default="")
remote_auth_token = relationship('RemoteAuthToken', backref='user', lazy='dynamic') remote_auth_token = relationship('RemoteAuthToken', backref='user', lazy='dynamic')
view_settings = Column(JSON, default={}) view_settings = Column(JSON, default={})
kobo_only_shelves_sync = Column(Integer, default=1)
if oauth_support: if oauth_support:
@ -229,6 +229,7 @@ class Anonymous(AnonymousUserMixin, UserBase):
self.denied_column_value = data.denied_column_value self.denied_column_value = data.denied_column_value
self.allowed_column_value = data.allowed_column_value self.allowed_column_value = data.allowed_column_value
self.view_settings = data.view_settings self.view_settings = data.view_settings
self.kobo_only_shelves_sync = data.kobo_only_shelves_sync
def role_admin(self): def role_admin(self):
@ -603,6 +604,13 @@ def migrate_Database(session):
with engine.connect() as conn: with engine.connect() as conn:
conn.execute("ALTER TABLE user ADD column `view_settings` VARCHAR(10) DEFAULT '{}'") conn.execute("ALTER TABLE user ADD column `view_settings` VARCHAR(10) DEFAULT '{}'")
session.commit() session.commit()
try:
session.query(exists().where(User.kobo_only_shelves_sync)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
conn.execute("ALTER TABLE user ADD column `kobo_only_shelves_sync` SMALLINT DEFAULT 0")
session.commit()
try: try:
# check if name is in User table instead of nickname # check if name is in User table instead of nickname
session.query(exists().where(User.name)).scalar() session.query(exists().where(User.name)).scalar()
@ -623,14 +631,15 @@ def migrate_Database(session):
"denied_column_value VARCHAR," "denied_column_value VARCHAR,"
"allowed_column_value VARCHAR," "allowed_column_value VARCHAR,"
"view_settings JSON," "view_settings JSON,"
"kobo_only_shelves_sync SMALLINT,"
"UNIQUE (name)," "UNIQUE (name),"
"UNIQUE (email))")) "UNIQUE (email))"))
conn.execute(text("INSERT INTO user_id(id, name, email, role, password, kindle_mail,locale," conn.execute(text("INSERT INTO user_id(id, name, email, role, password, kindle_mail,locale,"
"sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, " "sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, "
"allowed_column_value, view_settings)" "allowed_column_value, view_settings, kobo_only_shelves_sync)"
"SELECT id, nickname, email, role, password, kindle_mail, locale," "SELECT id, nickname, email, role, password, kindle_mail, locale,"
"sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, " "sidebar_view, default_language, denied_tags, allowed_tags, denied_column_value, "
"allowed_column_value, view_settings FROM user")) "allowed_column_value, view_settings, kobo_only_shelves_sync FROM user"))
# delete old user table and rename new user_id table to user: # delete old user table and rename new user_id table to user:
conn.execute(text("DROP TABLE user")) conn.execute(text("DROP TABLE user"))
conn.execute(text("ALTER TABLE user_id RENAME TO user")) conn.execute(text("ALTER TABLE user_id RENAME TO user"))

View File

@ -1593,6 +1593,8 @@ def change_profile(kobo_support, local_oauth_check, oauth_status, translations,
current_user.default_language = to_save["default_language"] current_user.default_language = to_save["default_language"]
if to_save.get("locale"): if to_save.get("locale"):
current_user.locale = to_save["locale"] current_user.locale = to_save["locale"]
current_user.kobo_only_shelves_sync = int(to_save.get("kobo_only_shelves_sync") == "on") or 0
except Exception as ex: except Exception as ex:
flash(str(ex), category="error") flash(str(ex), category="error")
return render_title_template("user_edit.html", content=current_user, return render_title_template("user_edit.html", content=current_user,