Hide Community Update code

This commit is contained in:
Inga Kirschnick 2023-06-07 15:13:47 +02:00
parent 15e7fa6dd3
commit b8bcb159a2
12 changed files with 252 additions and 250 deletions

View File

@ -12,65 +12,65 @@ from ..decorators import corpus_follower_permission_required
from . import bp from . import bp
@bp.route('/<hashid:corpus_id>/followers', methods=['POST']) # @bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
@corpus_follower_permission_required('MANAGE_FOLLOWERS') # @corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json') # @content_negotiation(consumes='application/json', produces='application/json')
def create_corpus_followers(corpus_id): # def create_corpus_followers(corpus_id):
usernames = request.json # usernames = request.json
if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)): # if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
abort(400) # abort(400)
corpus = Corpus.query.get_or_404(corpus_id) # corpus = Corpus.query.get_or_404(corpus_id)
for username in usernames: # for username in usernames:
user = User.query.filter_by(username=username, is_public=True).first_or_404() # user = User.query.filter_by(username=username, is_public=True).first_or_404()
user.follow_corpus(corpus) # user.follow_corpus(corpus)
db.session.commit() # db.session.commit()
response_data = { # response_data = {
'message': f'Users are now following "{corpus.title}"', # 'message': f'Users are now following "{corpus.title}"',
'category': 'corpus' # 'category': 'corpus'
} # }
return response_data, 200 # return response_data, 200
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT']) # @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
@corpus_follower_permission_required('MANAGE_FOLLOWERS') # @corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json') # @content_negotiation(consumes='application/json', produces='application/json')
def update_corpus_follower_role(corpus_id, follower_id): # def update_corpus_follower_role(corpus_id, follower_id):
role_name = request.json # role_name = request.json
if not isinstance(role_name, str): # if not isinstance(role_name, str):
abort(400) # abort(400)
cfr = CorpusFollowerRole.query.filter_by(name=role_name).first() # cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
if cfr is None: # if cfr is None:
abort(400) # abort(400)
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404() # cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
cfa.role = cfr # cfa.role = cfr
db.session.commit() # db.session.commit()
response_data = { # response_data = {
'message': f'User "{cfa.follower.username}" is now {cfa.role.name}', # 'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
'category': 'corpus' # 'category': 'corpus'
} # }
return response_data, 200 # return response_data, 200
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE']) # @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
def delete_corpus_follower(corpus_id, follower_id): # def delete_corpus_follower(corpus_id, follower_id):
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404() # cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
if not ( # if not (
current_user.id == follower_id # current_user.id == follower_id
or current_user == cfa.corpus.user # or current_user == cfa.corpus.user
or CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS') # or CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS')
or current_user.is_administrator()): # or current_user.is_administrator()):
abort(403) # abort(403)
if current_user.id == follower_id: # if current_user.id == follower_id:
flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus') # flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
response = make_response() # response = make_response()
response.status_code = 204 # response.status_code = 204
else: # else:
response_data = { # response_data = {
'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore', # 'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
'category': 'corpus' # 'category': 'corpus'
} # }
response = jsonify(response_data) # response = jsonify(response_data)
response.status_code = 200 # response.status_code = 200
cfa.follower.unfollow_corpus(cfa.corpus) # cfa.follower.unfollow_corpus(cfa.corpus)
db.session.commit() # db.session.commit()
return response # return response

View File

@ -57,55 +57,55 @@ def build_corpus(corpus_id):
return response_data, 202 return response_data, 202
@bp.route('/<hashid:corpus_id>/generate-share-link', methods=['POST']) # @bp.route('/<hashid:corpus_id>/generate-share-link', methods=['POST'])
@corpus_follower_permission_required('MANAGE_FOLLOWERS') # @corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json') # @content_negotiation(consumes='application/json', produces='application/json')
def generate_corpus_share_link(corpus_id): # def generate_corpus_share_link(corpus_id):
data = request.json # data = request.json
if not isinstance(data, dict): # if not isinstance(data, dict):
abort(400) # abort(400)
expiration = data.get('expiration') # expiration = data.get('expiration')
if not isinstance(expiration, str): # if not isinstance(expiration, str):
abort(400) # abort(400)
role_name = data.get('role') # role_name = data.get('role')
if not isinstance(role_name, str): # if not isinstance(role_name, str):
abort(400) # abort(400)
expiration_date = datetime.strptime(expiration, '%b %d, %Y') # expiration_date = datetime.strptime(expiration, '%b %d, %Y')
cfr = CorpusFollowerRole.query.filter_by(name=role_name).first() # cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
if cfr is None: # if cfr is None:
abort(400) # abort(400)
corpus = Corpus.query.get_or_404(corpus_id) # corpus = Corpus.query.get_or_404(corpus_id)
token = current_user.generate_follow_corpus_token(corpus.hashid, role_name, expiration_date) # token = current_user.generate_follow_corpus_token(corpus.hashid, role_name, expiration_date)
corpus_share_link = url_for( # corpus_share_link = url_for(
'corpora.follow_corpus', # 'corpora.follow_corpus',
corpus_id=corpus_id, # corpus_id=corpus_id,
token=token, # token=token,
_external=True # _external=True
) # )
response_data = { # response_data = {
'message': 'Corpus share link generated', # 'message': 'Corpus share link generated',
'category': 'corpus', # 'category': 'corpus',
'corpusShareLink': corpus_share_link # 'corpusShareLink': corpus_share_link
} # }
return response_data, 200 # return response_data, 200
@bp.route('/<hashid:corpus_id>/is_public', methods=['PUT']) # @bp.route('/<hashid:corpus_id>/is_public', methods=['PUT'])
@corpus_owner_or_admin_required # @corpus_owner_or_admin_required
@content_negotiation(consumes='application/json', produces='application/json') # @content_negotiation(consumes='application/json', produces='application/json')
def update_corpus_is_public(corpus_id): # def update_corpus_is_public(corpus_id):
is_public = request.json # is_public = request.json
if not isinstance(is_public, bool): # if not isinstance(is_public, bool):
abort(400) # abort(400)
corpus = Corpus.query.get_or_404(corpus_id) # corpus = Corpus.query.get_or_404(corpus_id)
corpus.is_public = is_public # corpus.is_public = is_public
db.session.commit() # db.session.commit()
response_data = { # response_data = {
'message': ( # 'message': (
f'Corpus "{corpus.title}" is now' # f'Corpus "{corpus.title}" is now'
f' {"public" if is_public else "private"}' # f' {"public" if is_public else "private"}'
), # ),
'category': 'corpus' # 'category': 'corpus'
} # }
return response_data, 200 # return response_data, 200

View File

@ -71,16 +71,17 @@ def corpus(corpus_id):
users = users users = users
) )
if (current_user.is_following_corpus(corpus) or corpus.is_public): if (current_user.is_following_corpus(corpus) or corpus.is_public):
cfas = CorpusFollowerAssociation.query.filter(Corpus.id == corpus_id, CorpusFollowerAssociation.follower_id != corpus.user.id).all() abort(404)
return render_template( # cfas = CorpusFollowerAssociation.query.filter(Corpus.id == corpus_id, CorpusFollowerAssociation.follower_id != corpus.user.id).all()
'corpora/public_corpus.html.j2', # return render_template(
title=corpus.title, # 'corpora/public_corpus.html.j2',
corpus=corpus, # title=corpus.title,
cfrs=cfrs, # corpus=corpus,
cfr=cfr, # cfrs=cfrs,
cfas=cfas, # cfr=cfr,
users = users # cfas=cfas,
) # users = users
# )
abort(403) abort(403)
@ -97,14 +98,14 @@ def analysis(corpus_id):
) )
@bp.route('/<hashid:corpus_id>/follow/<token>') # @bp.route('/<hashid:corpus_id>/follow/<token>')
def follow_corpus(corpus_id, token): # def follow_corpus(corpus_id, token):
corpus = Corpus.query.get_or_404(corpus_id) # corpus = Corpus.query.get_or_404(corpus_id)
if current_user.follow_corpus_by_token(token): # if current_user.follow_corpus_by_token(token):
db.session.commit() # db.session.commit()
flash(f'You are following "{corpus.title}" now', category='corpus') # flash(f'You are following "{corpus.title}" now', category='corpus')
return redirect(url_for('corpora.corpus', corpus_id=corpus_id)) # return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
abort(403) # abort(403)
@bp.route('/import', methods=['GET', 'POST']) @bp.route('/import', methods=['GET', 'POST'])

View File

@ -78,15 +78,15 @@ def terms_of_use():
) )
@bp.route('/social-area') # @bp.route('/social-area')
@register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area') # @register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area')
@login_required # @login_required
def social_area(): # def social_area():
corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all() # corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
users = User.query.filter(User.is_public == True, User.id != current_user.id).all() # users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
return render_template( # return render_template(
'main/social_area.html.j2', # 'main/social_area.html.j2',
title='Social Area', # title='Social Area',
corpora=corpora, # corpora=corpora,
users=users # users=users
) # )

View File

@ -853,7 +853,7 @@ class User(HashidMixin, UserMixin, db.Model):
json_serializeable = { json_serializeable = {
'id': self.hashid, 'id': self.hashid,
'confirmed': self.confirmed, 'confirmed': self.confirmed,
'avatar': url_for('users.user_avatar', user_id=self.id), # 'avatar': url_for('users.user_avatar', user_id=self.id),
'email': self.email, 'email': self.email,
'last_seen': ( 'last_seen': (
None if self.last_seen is None None if self.last_seen is None

View File

@ -225,6 +225,9 @@ class CorpusList extends ResourceList {
break; break;
} }
case 'delete': { case 'delete': {
// Saved for future use:
// <p class="hide">Do you really want to unfollow this Corpora?</p>
// <ul id="selected-unfollow-items-list"></ul>
let modalElement = Utils.HTMLToElement( let modalElement = Utils.HTMLToElement(
` `
<div class="modal"> <div class="modal">
@ -232,8 +235,6 @@ class CorpusList extends ResourceList {
<h4>Confirm Corpus deletion</h4> <h4>Confirm Corpus deletion</h4>
<p>Do you really want to delete this Corpora? <i>All corpora will be permanently deleted!</i></p> <p>Do you really want to delete this Corpora? <i>All corpora will be permanently deleted!</i></p>
<ul id="selected-deletion-items-list"></ul> <ul id="selected-deletion-items-list"></ul>
<p>Do you really want to unfollow this Corpora?</p>
<ul id="selected-unfollow-items-list"></ul>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a class="btn modal-close waves-effect waves-light">Cancel</a> <a class="btn modal-close waves-effect waves-light">Cancel</a>
@ -244,16 +245,16 @@ class CorpusList extends ResourceList {
); );
document.querySelector('#modals').appendChild(modalElement); document.querySelector('#modals').appendChild(modalElement);
let itemDeletionList = document.querySelector('#selected-deletion-items-list'); let itemDeletionList = document.querySelector('#selected-deletion-items-list');
let itemUnfollowList = document.querySelector('#selected-unfollow-items-list'); // let itemUnfollowList = document.querySelector('#selected-unfollow-items-list');
this.selectedItemIds.forEach(selectedItemId => { this.selectedItemIds.forEach(selectedItemId => {
let listItem = this.listjs.get('id', selectedItemId)[0].elm; let listItem = this.listjs.get('id', selectedItemId)[0].elm;
let values = this.listjs.get('id', listItem.dataset.id)[0].values(); let values = this.listjs.get('id', listItem.dataset.id)[0].values();
let itemElement = Utils.HTMLToElement(`<li> - ${values.title}</li>`); let itemElement = Utils.HTMLToElement(`<li> - ${values.title}</li>`);
if (!values['is-owner']) { // if (!values['is-owner']) {
itemUnfollowList.appendChild(itemElement); // itemUnfollowList.appendChild(itemElement);
} else { // } else {
itemDeletionList.appendChild(itemElement); itemDeletionList.appendChild(itemElement);
} // }
}); });
let modal = M.Modal.init( let modal = M.Modal.init(
modalElement, modalElement,

View File

@ -3,12 +3,12 @@
<div class="user-view" style="padding-top: 3px;"> <div class="user-view" style="padding-top: 3px;">
<div class="background primary-color"></div> <div class="background primary-color"></div>
<div class="row"> <div class="row">
<div class="col s4"> {# <div class="col s4">
<a href="{{ url_for('users.user', user_id=current_user.id) }}"> <a href="{{ url_for('users.user', user_id=current_user.id) }}">
<img src="{{ url_for('users.user_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 13px; margin-left:-15px;"> <img src="{{ url_for('users.user_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 13px; margin-left:-15px;">
</a> </a>
</div> </div> #}
<div class="col s8"> <div class="col s12">
<span class="white-text name">{{ current_user.username }}</span> <span class="white-text name">{{ current_user.username }}</span>
<span class="white-text email">{{ current_user.email }}</span> <span class="white-text email">{{ current_user.email }}</span>
</div> </div>
@ -58,7 +58,7 @@
<li class="service-color service-color-border border-darken" data-service="corpus-analysis" style="border-left: 10px solid; margin-top: 5px;"> <li class="service-color service-color-border border-darken" data-service="corpus-analysis" style="border-left: 10px solid; margin-top: 5px;">
<a class="waves-effect" href="{{ url_for('services.corpus_analysis') }}"><i class="nopaque-icons service-icons" data-service="corpus-analysis"></i>Corpus Analysis</a> <a class="waves-effect" href="{{ url_for('services.corpus_analysis') }}"><i class="nopaque-icons service-icons" data-service="corpus-analysis"></i>Corpus Analysis</a>
</li> </li>
<li><div class="divider"></div></li> {# <li><div class="divider"></div></li>
<li> <li>
<a class="waves-effect" class="waves-effect" href="{{ url_for('main.social_area') }}"><i class="material-icons">rocket_launch</i>Social Area</a> <a class="waves-effect" class="waves-effect" href="{{ url_for('main.social_area') }}"><i class="material-icons">rocket_launch</i>Social Area</a>
<ul> <ul>
@ -69,7 +69,7 @@
<a class="waves-effect" href="{{ url_for('main.social_area', _anchor='public-corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>Public Corpora</a> <a class="waves-effect" href="{{ url_for('main.social_area', _anchor='public-corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>Public Corpora</a>
</li> </li>
</ul> </ul>
</li> </li> #}
<li class="hide-on-large-only"><div class="divider"></div></li> <li class="hide-on-large-only"><div class="divider"></div></li>
<li class="hide-on-large-only"><a class="subheader">Account</a></li> <li class="hide-on-large-only"><a class="subheader">Account</a></li>
<li class="hide-on-large-only"> <li class="hide-on-large-only">

View File

@ -5,7 +5,7 @@
<div class="row"> <div class="row">
<div class="col s12 l2"> <div class="col s12 l2">
<p>&nbsp;</p> <p>&nbsp;</p>
<img src="{{ url_for('users.user_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img"> {# <img src="{{ url_for('users.user_avatar', user_id=user.id) }}" alt="user-image" class="circle responsive-img"> #}
</div> </div>
<div class="col s12 l10"> <div class="col s12 l10">
<h1 id="title">{{ title }}</h1> <h1 id="title">{{ title }}</h1>

View File

@ -65,14 +65,14 @@
<div class="col s12 l6" style="padding: 0 2.5px;"> <div class="col s12 l6" style="padding: 0 2.5px;">
<a class="action-button btn disabled waves-effect waves-light" data-action="analyze" href="{{ url_for('corpora.analysis', corpus_id=corpus.id) }}" style="width: 100%;"><i class="material-icons left">search</i>Analyze</a> <a class="action-button btn disabled waves-effect waves-light" data-action="analyze" href="{{ url_for('corpora.analysis', corpus_id=corpus.id) }}" style="width: 100%;"><i class="material-icons left">search</i>Analyze</a>
</div> </div>
<div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;"> {# <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
<a class="btn waves-effect waves-light modal-trigger" href="#publishing-modal" style="width: 100%;"><i class="material-icons left">publish</i>Publishing</a> <a class="btn waves-effect waves-light modal-trigger" href="#publishing-modal" style="width: 100%;"><i class="material-icons left">publish</i>Publishing</a>
</div> </div> #}
<div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;"> <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
<a class="btn red waves-effect waves-light modal-trigger" href="#delete-modal" style="width: 100%;"><i class="material-icons left">delete</i>Delete</a> <a class="btn red waves-effect waves-light modal-trigger" href="#delete-modal" style="width: 100%;"><i class="material-icons left">delete</i>Delete</a>
</div> </div>
</div> </div>
{% if cfr.has_permission('MANAGE_FOLLOWERS') %} {# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
<span class="card-title">Social</span> <span class="card-title">Social</span>
<div class="row"> <div class="row">
<div class="col s12 l6" style="padding: 0 2.5px;"> <div class="col s12 l6" style="padding: 0 2.5px;">
@ -82,7 +82,7 @@
<a class="btn waves-effect waves-light modal-trigger" href="#share-link-modal" style="width: 100%;"><i class="material-icons left">link</i>Share link</a> <a class="btn waves-effect waves-light modal-trigger" href="#share-link-modal" style="width: 100%;"><i class="material-icons left">link</i>Share link</a>
</div> </div>
</div> </div>
{% endif %} {% endif %} #}
</div> </div>
</div> </div>
</div> </div>
@ -102,7 +102,7 @@
</div> </div>
</div> </div>
{% if cfr.has_permission('MANAGE_FOLLOWERS') %} {# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
<div class="col s12"> <div class="col s12">
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
@ -111,7 +111,7 @@
</div> </div>
</div> </div>
</div> </div>
{% endif %} {% endif %} #}
</div> </div>
</div> </div>
@ -121,7 +121,7 @@
{{ super() }} {{ super() }}
{% if current_user == corpus.user or current_user.is_administrator() %} {% if current_user == corpus.user or current_user.is_administrator() %}
<div class="modal" id="publishing-modal"> {# <div class="modal" id="publishing-modal">
<div class="modal-content"> <div class="modal-content">
<h4>Change your Corpus publishing status</h4> <h4>Change your Corpus publishing status</h4>
<p><i>Other users can only see the meta data of your corpus. The files of the corpus remain private and can only be viewed via a share link.</i></p> <p><i>Other users can only see the meta data of your corpus. The files of the corpus remain private and can only be viewed via a share link.</i></p>
@ -138,7 +138,7 @@
<div class="modal-footer"> <div class="modal-footer">
<a class="modal-close waves-effect waves-green btn-flat">Close</a> <a class="modal-close waves-effect waves-green btn-flat">Close</a>
</div> </div>
</div> </div> #}
<div class="modal" id="delete-modal"> <div class="modal" id="delete-modal">
<div class="modal-content"> <div class="modal-content">
@ -152,7 +152,7 @@
</div> </div>
{% endif %} {% endif %}
{% if cfr.has_permission('MANAGE_FOLLOWERS') %} {# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
<div class="modal no-autoinit" id="invite-user-modal"> <div class="modal no-autoinit" id="invite-user-modal">
<div class="modal-content"> <div class="modal-content">
<h4>Invite a nopaque user by username</h4> <h4>Invite a nopaque user by username</h4>
@ -230,7 +230,7 @@
<a class="modal-close waves-effect waves-green btn-flat">Close</a> <a class="modal-close waves-effect waves-green btn-flat">Close</a>
</div> </div>
</div> </div>
{% endif %} {% endif %} #}
{% endblock modals %} {% endblock modals %}
@ -239,7 +239,7 @@
<script> <script>
let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display')); let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));
{% if current_user.is_following_corpus(corpus) %} {# {% if current_user.is_following_corpus(corpus) %}
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]'); let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
unfollowRequestElement.addEventListener('click', () => { unfollowRequestElement.addEventListener('click', () => {
Requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ current_user.hashid|tojson }}) Requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ current_user.hashid|tojson }})
@ -247,18 +247,18 @@ let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'))
window.location.reload(); window.location.reload();
}); });
}); });
{% endif %} {% endif %} #}
{% if current_user == corpus.user or current_user.is_administrator() %} {% if current_user == corpus.user or current_user.is_administrator() %}
// #region Publishing // #region Publishing
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch'); {# let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => { publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
let newIsPublic = publishingModalIsPublicSwitchElement.checked; let newIsPublic = publishingModalIsPublicSwitchElement.checked;
Requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic) Requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic)
.catch((response) => { .catch((response) => {
publishingModalIsPublicSwitchElement.checked = !newIsPublic; publishingModalIsPublicSwitchElement.checked = !newIsPublic;
}); });
}); }); #}
// #endregion Publishing // #endregion Publishing
// #region Delete // #region Delete
@ -274,7 +274,7 @@ deleteModalDeleteButtonElement.addEventListener('click', (event) => {
{% if cfr.has_permission('MANAGE_FOLLOWERS') %} {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
// #region Invite user // #region Invite user
let inviteUserModalElement = document.querySelector('#invite-user-modal'); {# let inviteUserModalElement = document.querySelector('#invite-user-modal');
let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search'); let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button'); let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
let users = { let users = {
@ -376,7 +376,7 @@ shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
() => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');} () => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
); );
}); }); #}
// #endregion Share link // #endregion Share link
{% endif %} {% endif %}

View File

@ -8,7 +8,7 @@
<h1 id="title">{{ title }}</h1> <h1 id="title">{{ title }}</h1>
</div> </div>
<div class="col s12 l4"> {# <div class="col s12 l4">
<h4>Profile Settings</h4> <h4>Profile Settings</h4>
<p>You can edit your public profile here and share it with other nopaque users. <p>You can edit your public profile here and share it with other nopaque users.
Tell others about your (scientific) background so they can relate and network with you. Tell others about your (scientific) background so they can relate and network with you.
@ -112,7 +112,7 @@
</ul> </ul>
</div> </div>
<div class="col s12"></div> <div class="col s12"></div> #}
<div class="col s12 l4"> <div class="col s12 l4">
<h4>General Settings</h4> <h4>General Settings</h4>
@ -181,7 +181,7 @@
{% block modals %} {% block modals %}
{{ super() }} {{ super() }}
<div class="modal" id="delete-avatar-modal"> {# <div class="modal" id="delete-avatar-modal">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm Avatar deletion</h4> <h4>Confirm Avatar deletion</h4>
<p>Do you really want to delete <b>{{ user.username }}</b>s avatar?</p> <p>Do you really want to delete <b>{{ user.username }}</b>s avatar?</p>
@ -190,7 +190,7 @@
<a class="btn modal-close waves-effect waves-light">Cancel</a> <a class="btn modal-close waves-effect waves-light">Cancel</a>
<a class="btn modal-close red waves-effect waves-light" id="delete-avatar">Delete</a> <a class="btn modal-close red waves-effect waves-light" id="delete-avatar">Delete</a>
</div> </div>
</div> </div> #}
<div class="modal" id="delete-user-modal"> <div class="modal" id="delete-user-modal">
<div class="modal-content"> <div class="modal-content">
@ -212,7 +212,7 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script> <script>
let avatarPreviewElement = document.querySelector('#update-avatar-form-avatar-preview'); {# let avatarPreviewElement = document.querySelector('#update-avatar-form-avatar-preview');
let avatarUploadElement = document.querySelector('#update-avatar-form-avatar'); let avatarUploadElement = document.querySelector('#update-avatar-form-avatar');
avatarUploadElement.addEventListener('change', () => { avatarUploadElement.addEventListener('change', () => {
@ -227,7 +227,7 @@ document.querySelector('#delete-avatar').addEventListener('click', () => {
avatarPreviewElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }}; avatarPreviewElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }};
} }
); );
}); }); #}
document.querySelector('#delete-user').addEventListener('click', (event) => { document.querySelector('#delete-user').addEventListener('click', (event) => {
Requests.users.entity.delete({{ user.hashid|tojson }}) Requests.users.entity.delete({{ user.hashid|tojson }})
@ -251,7 +251,7 @@ for (let collapsibleElement of document.querySelectorAll('.collapsible.no-autoin
} }
// #region Profile Privacy settings // #region Profile Privacy settings
let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch'); {# let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch');
let profilePrivacySettingCheckboxElements = document.querySelectorAll('.profile-privacy-setting-checkbox'); let profilePrivacySettingCheckboxElements = document.querySelectorAll('.profile-privacy-setting-checkbox');
profileIsPublicSwitchElement.addEventListener('change', (event) => { profileIsPublicSwitchElement.addEventListener('change', (event) => {
let newEnabled = profileIsPublicSwitchElement.checked; let newEnabled = profileIsPublicSwitchElement.checked;
@ -276,7 +276,7 @@ for (let profilePrivacySettingCheckboxElement of profilePrivacySettingCheckboxEl
profilePrivacySettingCheckboxElement.checked = !newEnabled; profilePrivacySettingCheckboxElement.checked = !newEnabled;
}); });
}); });
} } #}
// #endregion Profile Privacy settings // #endregion Profile Privacy settings
</script> </script>
{% endblock scripts %} {% endblock scripts %}

View File

@ -7,54 +7,54 @@ from app.models import Avatar, User
from . import bp from . import bp
@bp.route('/<hashid:user_id>', methods=['DELETE']) # @bp.route('/<hashid:user_id>', methods=['DELETE'])
@content_negotiation(produces='application/json') # @content_negotiation(produces='application/json')
def delete_user(user_id): # def delete_user(user_id):
def _delete_user(app, user_id): # def _delete_user(app, user_id):
with app.app_context(): # with app.app_context():
user = User.query.get(user_id) # user = User.query.get(user_id)
user.delete() # user.delete()
db.session.commit() # db.session.commit()
user = User.query.get_or_404(user_id) # user = User.query.get_or_404(user_id)
if not (user == current_user or current_user.is_administrator()): # if not (user == current_user or current_user.is_administrator()):
abort(403) # abort(403)
thread = Thread( # thread = Thread(
target=_delete_user, # target=_delete_user,
args=(current_app._get_current_object(), user.id) # args=(current_app._get_current_object(), user.id)
) # )
if user == current_user: # if user == current_user:
logout_user() # logout_user()
thread.start() # thread.start()
response_data = { # response_data = {
'message': f'User "{user.username}" marked for deletion' # 'message': f'User "{user.username}" marked for deletion'
} # }
return response_data, 202 # return response_data, 202
@bp.route('/<hashid:user_id>/avatar', methods=['DELETE']) # @bp.route('/<hashid:user_id>/avatar', methods=['DELETE'])
@content_negotiation(produces='application/json') # @content_negotiation(produces='application/json')
def delete_user_avatar(user_id): # def delete_user_avatar(user_id):
def _delete_avatar(app, avatar_id): # def _delete_avatar(app, avatar_id):
with app.app_context(): # with app.app_context():
avatar = Avatar.query.get(avatar_id) # avatar = Avatar.query.get(avatar_id)
avatar.delete() # avatar.delete()
db.session.commit() # db.session.commit()
user = User.query.get_or_404(user_id) # user = User.query.get_or_404(user_id)
if user.avatar is None: # if user.avatar is None:
abort(404) # abort(404)
if not (user == current_user or current_user.is_administrator()): # if not (user == current_user or current_user.is_administrator()):
abort(403) # abort(403)
thread = Thread( # thread = Thread(
target=_delete_avatar, # target=_delete_avatar,
args=(current_app._get_current_object(), user.avatar.id) # args=(current_app._get_current_object(), user.avatar.id)
) # )
thread.start() # thread.start()
response_data = { # response_data = {
'message': f'Avatar marked for deletion' # 'message': f'Avatar marked for deletion'
} # }
return response_data, 202 # return response_data, 202
@bp.route('/accept-terms-of-use', methods=['POST']) @bp.route('/accept-terms-of-use', methods=['POST'])
@content_negotiation(produces='application/json') @content_negotiation(produces='application/json')

View File

@ -13,36 +13,36 @@ from . import bp
from .utils import user_dynamic_list_constructor as user_dlc from .utils import user_dynamic_list_constructor as user_dlc
@bp.route('') # @bp.route('')
@register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users') # @register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users')
def users(): # def users():
return redirect(url_for('main.social_area', _anchor='users')) # return redirect(url_for('main.social_area', _anchor='users'))
@bp.route('/<hashid:user_id>') # @bp.route('/<hashid:user_id>')
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc) # @register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
def user(user_id): # def user(user_id):
user = User.query.get_or_404(user_id) # user = User.query.get_or_404(user_id)
if not (user.is_public or user == current_user or current_user.is_administrator()): # if not (user.is_public or user == current_user or current_user.is_administrator()):
abort(403) # abort(403)
return render_template( # return render_template(
'users/user.html.j2', # 'users/user.html.j2',
title=user.username, # title=user.username,
user=user # user=user
) # )
@bp.route('/<hashid:user_id>/avatar') # @bp.route('/<hashid:user_id>/avatar')
def user_avatar(user_id): # def user_avatar(user_id):
user = User.query.get_or_404(user_id) # user = User.query.get_or_404(user_id)
if not (user.is_public or user == current_user or current_user.is_administrator()): # if not (user.is_public or user == current_user or current_user.is_administrator()):
abort(403) # abort(403)
if user.avatar is None: # if user.avatar is None:
return redirect(url_for('static', filename='images/user_avatar.png')) # return redirect(url_for('static', filename='images/user_avatar.png'))
return send_from_directory( # return send_from_directory(
os.path.dirname(user.avatar.path), # os.path.dirname(user.avatar.path),
os.path.basename(user.avatar.path), # os.path.basename(user.avatar.path),
as_attachment=True, # as_attachment=True,
attachment_filename=user.avatar.filename, # attachment_filename=user.avatar.filename,
mimetype=user.avatar.mimetype # mimetype=user.avatar.mimetype
) # )