mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Hide Community Update code
This commit is contained in:
		@@ -12,65 +12,65 @@ from ..decorators import corpus_follower_permission_required
 | 
			
		||||
from . import bp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
 | 
			
		||||
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def create_corpus_followers(corpus_id):
 | 
			
		||||
    usernames = request.json
 | 
			
		||||
    if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    for username in usernames:
 | 
			
		||||
        user = User.query.filter_by(username=username, is_public=True).first_or_404()
 | 
			
		||||
        user.follow_corpus(corpus)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'Users are now following "{corpus.title}"',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 200
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
 | 
			
		||||
# @corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
# @content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
# def create_corpus_followers(corpus_id):
 | 
			
		||||
#     usernames = request.json
 | 
			
		||||
#     if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
#     for username in usernames:
 | 
			
		||||
#         user = User.query.filter_by(username=username, is_public=True).first_or_404()
 | 
			
		||||
#         user.follow_corpus(corpus)
 | 
			
		||||
#     db.session.commit()
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': f'Users are now following "{corpus.title}"',
 | 
			
		||||
#         'category': 'corpus'
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
 | 
			
		||||
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def update_corpus_follower_role(corpus_id, follower_id):
 | 
			
		||||
    role_name = request.json
 | 
			
		||||
    if not isinstance(role_name, str):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
 | 
			
		||||
    if cfr is None:
 | 
			
		||||
        abort(400)
 | 
			
		||||
    cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
    cfa.role = cfr
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 200
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
 | 
			
		||||
# @corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
# @content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
# def update_corpus_follower_role(corpus_id, follower_id):
 | 
			
		||||
#     role_name = request.json
 | 
			
		||||
#     if not isinstance(role_name, str):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
 | 
			
		||||
#     if cfr is None:
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
#     cfa.role = cfr
 | 
			
		||||
#     db.session.commit()
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
 | 
			
		||||
#         'category': 'corpus'
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
 | 
			
		||||
def delete_corpus_follower(corpus_id, follower_id):
 | 
			
		||||
    cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
    if not (
 | 
			
		||||
        current_user.id == follower_id
 | 
			
		||||
        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 current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    if current_user.id == follower_id:
 | 
			
		||||
        flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
 | 
			
		||||
        response = make_response()
 | 
			
		||||
        response.status_code = 204
 | 
			
		||||
    else:
 | 
			
		||||
        response_data = {
 | 
			
		||||
            'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
 | 
			
		||||
            'category': 'corpus'
 | 
			
		||||
        }
 | 
			
		||||
        response = jsonify(response_data)
 | 
			
		||||
        response.status_code = 200
 | 
			
		||||
    cfa.follower.unfollow_corpus(cfa.corpus)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    return response
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
 | 
			
		||||
# def delete_corpus_follower(corpus_id, follower_id):
 | 
			
		||||
#     cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
#     if not (
 | 
			
		||||
#         current_user.id == follower_id
 | 
			
		||||
#         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 current_user.is_administrator()):
 | 
			
		||||
#         abort(403)
 | 
			
		||||
#     if current_user.id == follower_id:
 | 
			
		||||
#         flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
 | 
			
		||||
#         response = make_response()
 | 
			
		||||
#         response.status_code = 204
 | 
			
		||||
#     else:
 | 
			
		||||
#         response_data = {
 | 
			
		||||
#             'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
 | 
			
		||||
#             'category': 'corpus'
 | 
			
		||||
#         }
 | 
			
		||||
#         response = jsonify(response_data)
 | 
			
		||||
#         response.status_code = 200
 | 
			
		||||
#     cfa.follower.unfollow_corpus(cfa.corpus)
 | 
			
		||||
#     db.session.commit()
 | 
			
		||||
#     return response
 | 
			
		||||
 
 | 
			
		||||
@@ -57,55 +57,55 @@ def build_corpus(corpus_id):
 | 
			
		||||
    return response_data, 202
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/generate-share-link', methods=['POST'])
 | 
			
		||||
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def generate_corpus_share_link(corpus_id):
 | 
			
		||||
    data = request.json
 | 
			
		||||
    if not isinstance(data, dict):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    expiration = data.get('expiration')
 | 
			
		||||
    if not isinstance(expiration, str):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    role_name = data.get('role')
 | 
			
		||||
    if not isinstance(role_name, str):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    expiration_date = datetime.strptime(expiration, '%b %d, %Y')
 | 
			
		||||
    cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
 | 
			
		||||
    if cfr is None:
 | 
			
		||||
        abort(400)
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    token = current_user.generate_follow_corpus_token(corpus.hashid, role_name, expiration_date)
 | 
			
		||||
    corpus_share_link = url_for(
 | 
			
		||||
        'corpora.follow_corpus',
 | 
			
		||||
        corpus_id=corpus_id,
 | 
			
		||||
        token=token,
 | 
			
		||||
        _external=True
 | 
			
		||||
    )
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': 'Corpus share link generated',
 | 
			
		||||
        'category': 'corpus',
 | 
			
		||||
        'corpusShareLink': corpus_share_link
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 200
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/generate-share-link', methods=['POST'])
 | 
			
		||||
# @corpus_follower_permission_required('MANAGE_FOLLOWERS')
 | 
			
		||||
# @content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
# def generate_corpus_share_link(corpus_id):
 | 
			
		||||
#     data = request.json
 | 
			
		||||
#     if not isinstance(data, dict):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     expiration = data.get('expiration')
 | 
			
		||||
#     if not isinstance(expiration, str):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     role_name = data.get('role')
 | 
			
		||||
#     if not isinstance(role_name, str):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     expiration_date = datetime.strptime(expiration, '%b %d, %Y')
 | 
			
		||||
#     cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
 | 
			
		||||
#     if cfr is None:
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
#     token = current_user.generate_follow_corpus_token(corpus.hashid, role_name, expiration_date)
 | 
			
		||||
#     corpus_share_link = url_for(
 | 
			
		||||
#         'corpora.follow_corpus',
 | 
			
		||||
#         corpus_id=corpus_id,
 | 
			
		||||
#         token=token,
 | 
			
		||||
#         _external=True
 | 
			
		||||
#     )
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': 'Corpus share link generated',
 | 
			
		||||
#         'category': 'corpus',
 | 
			
		||||
#         'corpusShareLink': corpus_share_link
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 200
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/is_public', methods=['PUT'])
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def update_corpus_is_public(corpus_id):
 | 
			
		||||
    is_public = request.json
 | 
			
		||||
    if not isinstance(is_public, bool):
 | 
			
		||||
        abort(400)
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    corpus.is_public = is_public
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': (
 | 
			
		||||
            f'Corpus "{corpus.title}" is now'
 | 
			
		||||
            f' {"public" if is_public else "private"}'
 | 
			
		||||
        ),
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 200
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/is_public', methods=['PUT'])
 | 
			
		||||
# @corpus_owner_or_admin_required
 | 
			
		||||
# @content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
# def update_corpus_is_public(corpus_id):
 | 
			
		||||
#     is_public = request.json
 | 
			
		||||
#     if not isinstance(is_public, bool):
 | 
			
		||||
#         abort(400)
 | 
			
		||||
#     corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
#     corpus.is_public = is_public
 | 
			
		||||
#     db.session.commit()
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': (
 | 
			
		||||
#             f'Corpus "{corpus.title}" is now'
 | 
			
		||||
#             f' {"public" if is_public else "private"}'
 | 
			
		||||
#         ),
 | 
			
		||||
#         'category': 'corpus'
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 200
 | 
			
		||||
 
 | 
			
		||||
@@ -71,16 +71,17 @@ def corpus(corpus_id):
 | 
			
		||||
            users = users
 | 
			
		||||
        )
 | 
			
		||||
    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()
 | 
			
		||||
        return render_template(
 | 
			
		||||
            'corpora/public_corpus.html.j2',
 | 
			
		||||
            title=corpus.title,
 | 
			
		||||
            corpus=corpus,
 | 
			
		||||
            cfrs=cfrs,
 | 
			
		||||
            cfr=cfr,
 | 
			
		||||
            cfas=cfas,
 | 
			
		||||
            users = users
 | 
			
		||||
        )
 | 
			
		||||
        abort(404)
 | 
			
		||||
        # cfas = CorpusFollowerAssociation.query.filter(Corpus.id == corpus_id, CorpusFollowerAssociation.follower_id != corpus.user.id).all()
 | 
			
		||||
        # return render_template(
 | 
			
		||||
        #     'corpora/public_corpus.html.j2',
 | 
			
		||||
        #     title=corpus.title,
 | 
			
		||||
        #     corpus=corpus,
 | 
			
		||||
        #     cfrs=cfrs,
 | 
			
		||||
        #     cfr=cfr,
 | 
			
		||||
        #     cfas=cfas,
 | 
			
		||||
        #     users = users
 | 
			
		||||
        # )
 | 
			
		||||
    abort(403)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -97,14 +98,14 @@ def analysis(corpus_id):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/follow/<token>')
 | 
			
		||||
def follow_corpus(corpus_id, token):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    if current_user.follow_corpus_by_token(token):
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        flash(f'You are following "{corpus.title}" now', category='corpus')
 | 
			
		||||
        return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
 | 
			
		||||
    abort(403)
 | 
			
		||||
# @bp.route('/<hashid:corpus_id>/follow/<token>')
 | 
			
		||||
# def follow_corpus(corpus_id, token):
 | 
			
		||||
#     corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
#     if current_user.follow_corpus_by_token(token):
 | 
			
		||||
#         db.session.commit()
 | 
			
		||||
#         flash(f'You are following "{corpus.title}" now', category='corpus')
 | 
			
		||||
#         return redirect(url_for('corpora.corpus', corpus_id=corpus_id))
 | 
			
		||||
#     abort(403)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/import', methods=['GET', 'POST'])
 | 
			
		||||
 
 | 
			
		||||
@@ -78,15 +78,15 @@ def terms_of_use():
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/social-area')
 | 
			
		||||
@register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area')
 | 
			
		||||
@login_required
 | 
			
		||||
def social_area():
 | 
			
		||||
    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()
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'main/social_area.html.j2',
 | 
			
		||||
        title='Social Area',
 | 
			
		||||
        corpora=corpora,
 | 
			
		||||
        users=users
 | 
			
		||||
    )
 | 
			
		||||
# @bp.route('/social-area')
 | 
			
		||||
# @register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area')
 | 
			
		||||
# @login_required
 | 
			
		||||
# def social_area():
 | 
			
		||||
#     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()
 | 
			
		||||
#     return render_template(
 | 
			
		||||
#         'main/social_area.html.j2',
 | 
			
		||||
#         title='Social Area',
 | 
			
		||||
#         corpora=corpora,
 | 
			
		||||
#         users=users
 | 
			
		||||
#     )
 | 
			
		||||
 
 | 
			
		||||
@@ -853,7 +853,7 @@ class User(HashidMixin, UserMixin, db.Model):
 | 
			
		||||
        json_serializeable = {
 | 
			
		||||
            'id': self.hashid,
 | 
			
		||||
            '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,
 | 
			
		||||
            'last_seen': (
 | 
			
		||||
                None if self.last_seen is None
 | 
			
		||||
 
 | 
			
		||||
@@ -225,15 +225,16 @@ class CorpusList extends ResourceList {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      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(
 | 
			
		||||
          `
 | 
			
		||||
            <div class="modal">
 | 
			
		||||
              <div class="modal-content">
 | 
			
		||||
                <h4>Confirm Corpus deletion</h4>
 | 
			
		||||
                <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>
 | 
			
		||||
                <p>Do you really want to unfollow this Corpora?</p>
 | 
			
		||||
                  <ul id="selected-unfollow-items-list"></ul>
 | 
			
		||||
                <ul id="selected-deletion-items-list"></ul>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="modal-footer">
 | 
			
		||||
                <a class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
@@ -244,16 +245,16 @@ class CorpusList extends ResourceList {
 | 
			
		||||
        );
 | 
			
		||||
        document.querySelector('#modals').appendChild(modalElement);
 | 
			
		||||
        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 => {
 | 
			
		||||
          let listItem = this.listjs.get('id', selectedItemId)[0].elm;
 | 
			
		||||
          let values = this.listjs.get('id', listItem.dataset.id)[0].values();
 | 
			
		||||
          let itemElement = Utils.HTMLToElement(`<li> - ${values.title}</li>`);
 | 
			
		||||
          if (!values['is-owner']) { 
 | 
			
		||||
            itemUnfollowList.appendChild(itemElement);
 | 
			
		||||
          } else {
 | 
			
		||||
            itemDeletionList.appendChild(itemElement);
 | 
			
		||||
          }
 | 
			
		||||
          // if (!values['is-owner']) { 
 | 
			
		||||
          //   itemUnfollowList.appendChild(itemElement);
 | 
			
		||||
          // } else {
 | 
			
		||||
          itemDeletionList.appendChild(itemElement);
 | 
			
		||||
          // }
 | 
			
		||||
        });
 | 
			
		||||
        let modal = M.Modal.init(
 | 
			
		||||
          modalElement,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,12 @@
 | 
			
		||||
    <div class="user-view" style="padding-top: 3px;">
 | 
			
		||||
      <div class="background primary-color"></div>
 | 
			
		||||
      <div class="row">
 | 
			
		||||
        <div class="col s4">
 | 
			
		||||
        {# <div class="col s4">
 | 
			
		||||
          <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;">
 | 
			
		||||
          </a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col s8">
 | 
			
		||||
        </div> #}
 | 
			
		||||
        <div class="col s12">
 | 
			
		||||
          <span class="white-text name">{{ current_user.username }}</span>
 | 
			
		||||
          <span class="white-text email">{{ current_user.email }}</span>
 | 
			
		||||
        </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;">
 | 
			
		||||
    <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><div class="divider"></div></li>
 | 
			
		||||
  {# <li><div class="divider"></div></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>
 | 
			
		||||
    <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>
 | 
			
		||||
  </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
  </li>
 | 
			
		||||
  </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">
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
  <div class="row">
 | 
			
		||||
    <div class="col s12 l2">
 | 
			
		||||
      <p> </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 class="col s12 l10">
 | 
			
		||||
      <h1 id="title">{{ title }}</h1>
 | 
			
		||||
 
 | 
			
		||||
@@ -65,14 +65,14 @@
 | 
			
		||||
            <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>
 | 
			
		||||
            </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>
 | 
			
		||||
            </div>
 | 
			
		||||
            </div> #}
 | 
			
		||||
            <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>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
          {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
			
		||||
          {# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
			
		||||
          <span class="card-title">Social</span>
 | 
			
		||||
          <div class="row">
 | 
			
		||||
            <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>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
          {% endif %}
 | 
			
		||||
          {% endif %} #}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
			
		||||
    {# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
			
		||||
    <div class="col s12">
 | 
			
		||||
      <div class="card">
 | 
			
		||||
        <div class="card-content">
 | 
			
		||||
@@ -111,7 +111,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    {% endif %} #}
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -121,7 +121,7 @@
 | 
			
		||||
{{ super() }}
 | 
			
		||||
 | 
			
		||||
{% 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">
 | 
			
		||||
    <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>
 | 
			
		||||
@@ -138,7 +138,7 @@
 | 
			
		||||
  <div class="modal-footer">
 | 
			
		||||
    <a class="modal-close waves-effect waves-green btn-flat">Close</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
</div> #}
 | 
			
		||||
 | 
			
		||||
<div class="modal" id="delete-modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
@@ -152,7 +152,7 @@
 | 
			
		||||
</div>
 | 
			
		||||
{% 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-content">
 | 
			
		||||
    <h4>Invite a nopaque user by username</h4>
 | 
			
		||||
@@ -230,7 +230,7 @@
 | 
			
		||||
    <a class="modal-close waves-effect waves-green btn-flat">Close</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endif %} #}
 | 
			
		||||
 | 
			
		||||
{% endblock modals %}
 | 
			
		||||
 | 
			
		||||
@@ -239,7 +239,7 @@
 | 
			
		||||
<script>
 | 
			
		||||
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"]');
 | 
			
		||||
  unfollowRequestElement.addEventListener('click', () => {
 | 
			
		||||
    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();
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endif %} #}
 | 
			
		||||
 | 
			
		||||
{% if current_user == corpus.user or current_user.is_administrator() %}
 | 
			
		||||
// #region Publishing
 | 
			
		||||
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
 | 
			
		||||
{# let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
 | 
			
		||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
 | 
			
		||||
  let newIsPublic = publishingModalIsPublicSwitchElement.checked;
 | 
			
		||||
  Requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic)
 | 
			
		||||
    .catch((response) => {
 | 
			
		||||
      publishingModalIsPublicSwitchElement.checked = !newIsPublic;
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
}); #}
 | 
			
		||||
// #endregion Publishing
 | 
			
		||||
 | 
			
		||||
// #region Delete
 | 
			
		||||
@@ -274,7 +274,7 @@ deleteModalDeleteButtonElement.addEventListener('click', (event) => {
 | 
			
		||||
 | 
			
		||||
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
			
		||||
// #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 inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
 | 
			
		||||
let users = {
 | 
			
		||||
@@ -376,7 +376,7 @@ shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
 | 
			
		||||
      () => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
 | 
			
		||||
    );
 | 
			
		||||
  
 | 
			
		||||
});
 | 
			
		||||
}); #}
 | 
			
		||||
// #endregion Share link
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
      <h1 id="title">{{ title }}</h1>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="col s12 l4">
 | 
			
		||||
    {# <div class="col s12 l4">
 | 
			
		||||
      <h4>Profile Settings</h4>
 | 
			
		||||
      <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. 
 | 
			
		||||
@@ -112,7 +112,7 @@
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="col s12"></div>
 | 
			
		||||
    <div class="col s12"></div> #}
 | 
			
		||||
 | 
			
		||||
    <div class="col s12 l4">
 | 
			
		||||
      <h4>General Settings</h4>
 | 
			
		||||
@@ -181,7 +181,7 @@
 | 
			
		||||
 | 
			
		||||
{% block modals %}
 | 
			
		||||
{{ super() }}
 | 
			
		||||
<div class="modal" id="delete-avatar-modal">
 | 
			
		||||
{# <div class="modal" id="delete-avatar-modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
    <h4>Confirm Avatar deletion</h4>
 | 
			
		||||
    <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 red waves-effect waves-light" id="delete-avatar">Delete</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
</div> #}
 | 
			
		||||
 | 
			
		||||
<div class="modal" id="delete-user-modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
@@ -212,7 +212,7 @@
 | 
			
		||||
{% block scripts %}
 | 
			
		||||
{{ super() }}
 | 
			
		||||
<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');
 | 
			
		||||
 | 
			
		||||
avatarUploadElement.addEventListener('change', () => {
 | 
			
		||||
@@ -227,7 +227,7 @@ document.querySelector('#delete-avatar').addEventListener('click', () => {
 | 
			
		||||
        avatarPreviewElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }};
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
}); #}
 | 
			
		||||
 | 
			
		||||
document.querySelector('#delete-user').addEventListener('click', (event) => {
 | 
			
		||||
  Requests.users.entity.delete({{ user.hashid|tojson }})
 | 
			
		||||
@@ -251,7 +251,7 @@ for (let collapsibleElement of document.querySelectorAll('.collapsible.no-autoin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// #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');
 | 
			
		||||
profileIsPublicSwitchElement.addEventListener('change', (event) => {
 | 
			
		||||
  let newEnabled = profileIsPublicSwitchElement.checked;
 | 
			
		||||
@@ -276,7 +276,7 @@ for (let profilePrivacySettingCheckboxElement of profilePrivacySettingCheckboxEl
 | 
			
		||||
        profilePrivacySettingCheckboxElement.checked = !newEnabled;
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
} #}
 | 
			
		||||
// #endregion Profile Privacy settings
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock scripts %}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,54 +7,54 @@ from app.models import Avatar, User
 | 
			
		||||
from . import bp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:user_id>', methods=['DELETE'])
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def delete_user(user_id):
 | 
			
		||||
    def _delete_user(app, user_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
            user = User.query.get(user_id)
 | 
			
		||||
            user.delete()
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
# @bp.route('/<hashid:user_id>', methods=['DELETE'])
 | 
			
		||||
# @content_negotiation(produces='application/json')
 | 
			
		||||
# def delete_user(user_id):
 | 
			
		||||
#     def _delete_user(app, user_id):
 | 
			
		||||
#         with app.app_context():
 | 
			
		||||
#             user = User.query.get(user_id)
 | 
			
		||||
#             user.delete()
 | 
			
		||||
#             db.session.commit()
 | 
			
		||||
 | 
			
		||||
    user = User.query.get_or_404(user_id)
 | 
			
		||||
    if not (user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_delete_user,
 | 
			
		||||
        args=(current_app._get_current_object(), user.id)
 | 
			
		||||
    )
 | 
			
		||||
    if user == current_user:
 | 
			
		||||
        logout_user()
 | 
			
		||||
    thread.start()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'User "{user.username}" marked for deletion'
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 202
 | 
			
		||||
#     user = User.query.get_or_404(user_id)
 | 
			
		||||
#     if not (user == current_user or current_user.is_administrator()):
 | 
			
		||||
#         abort(403)
 | 
			
		||||
#     thread = Thread(
 | 
			
		||||
#         target=_delete_user,
 | 
			
		||||
#         args=(current_app._get_current_object(), user.id)
 | 
			
		||||
#     )
 | 
			
		||||
#     if user == current_user:
 | 
			
		||||
#         logout_user()
 | 
			
		||||
#     thread.start()
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': f'User "{user.username}" marked for deletion'
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 202
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:user_id>/avatar', methods=['DELETE'])
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def delete_user_avatar(user_id):
 | 
			
		||||
    def _delete_avatar(app, avatar_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
            avatar = Avatar.query.get(avatar_id)
 | 
			
		||||
            avatar.delete()
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
# @bp.route('/<hashid:user_id>/avatar', methods=['DELETE'])
 | 
			
		||||
# @content_negotiation(produces='application/json')
 | 
			
		||||
# def delete_user_avatar(user_id):
 | 
			
		||||
#     def _delete_avatar(app, avatar_id):
 | 
			
		||||
#         with app.app_context():
 | 
			
		||||
#             avatar = Avatar.query.get(avatar_id)
 | 
			
		||||
#             avatar.delete()
 | 
			
		||||
#             db.session.commit()
 | 
			
		||||
 | 
			
		||||
    user = User.query.get_or_404(user_id)
 | 
			
		||||
    if user.avatar is None:
 | 
			
		||||
        abort(404)
 | 
			
		||||
    if not (user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_delete_avatar,
 | 
			
		||||
        args=(current_app._get_current_object(), user.avatar.id)
 | 
			
		||||
    )
 | 
			
		||||
    thread.start()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'Avatar marked for deletion'
 | 
			
		||||
    }
 | 
			
		||||
    return response_data, 202
 | 
			
		||||
#     user = User.query.get_or_404(user_id)
 | 
			
		||||
#     if user.avatar is None:
 | 
			
		||||
#         abort(404)
 | 
			
		||||
#     if not (user == current_user or current_user.is_administrator()):
 | 
			
		||||
#         abort(403)
 | 
			
		||||
#     thread = Thread(
 | 
			
		||||
#         target=_delete_avatar,
 | 
			
		||||
#         args=(current_app._get_current_object(), user.avatar.id)
 | 
			
		||||
#     )
 | 
			
		||||
#     thread.start()
 | 
			
		||||
#     response_data = {
 | 
			
		||||
#         'message': f'Avatar marked for deletion'
 | 
			
		||||
#     }
 | 
			
		||||
#     return response_data, 202
 | 
			
		||||
 | 
			
		||||
@bp.route('/accept-terms-of-use', methods=['POST'])
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
 
 | 
			
		||||
@@ -13,36 +13,36 @@ from . import bp
 | 
			
		||||
from .utils import user_dynamic_list_constructor as user_dlc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('')
 | 
			
		||||
@register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users')
 | 
			
		||||
def users():
 | 
			
		||||
    return redirect(url_for('main.social_area', _anchor='users'))
 | 
			
		||||
# @bp.route('')
 | 
			
		||||
# @register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users')
 | 
			
		||||
# def users():
 | 
			
		||||
#     return redirect(url_for('main.social_area', _anchor='users'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:user_id>')
 | 
			
		||||
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
 | 
			
		||||
def user(user_id):
 | 
			
		||||
    user = User.query.get_or_404(user_id)
 | 
			
		||||
    if not (user.is_public or user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'users/user.html.j2',
 | 
			
		||||
        title=user.username,
 | 
			
		||||
        user=user
 | 
			
		||||
    )
 | 
			
		||||
# @bp.route('/<hashid:user_id>')
 | 
			
		||||
# @register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
 | 
			
		||||
# def user(user_id):
 | 
			
		||||
#     user = User.query.get_or_404(user_id)
 | 
			
		||||
#     if not (user.is_public or user == current_user or current_user.is_administrator()):
 | 
			
		||||
#         abort(403)
 | 
			
		||||
#     return render_template(
 | 
			
		||||
#         'users/user.html.j2',
 | 
			
		||||
#         title=user.username,
 | 
			
		||||
#         user=user
 | 
			
		||||
#     )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:user_id>/avatar')
 | 
			
		||||
def user_avatar(user_id):
 | 
			
		||||
    user = User.query.get_or_404(user_id)
 | 
			
		||||
    if not (user.is_public or user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    if user.avatar is None:
 | 
			
		||||
        return redirect(url_for('static', filename='images/user_avatar.png'))
 | 
			
		||||
    return send_from_directory(
 | 
			
		||||
        os.path.dirname(user.avatar.path),
 | 
			
		||||
        os.path.basename(user.avatar.path),
 | 
			
		||||
        as_attachment=True,
 | 
			
		||||
        attachment_filename=user.avatar.filename,
 | 
			
		||||
        mimetype=user.avatar.mimetype
 | 
			
		||||
    )
 | 
			
		||||
# @bp.route('/<hashid:user_id>/avatar')
 | 
			
		||||
# def user_avatar(user_id):
 | 
			
		||||
#     user = User.query.get_or_404(user_id)
 | 
			
		||||
#     if not (user.is_public or user == current_user or current_user.is_administrator()):
 | 
			
		||||
#         abort(403)
 | 
			
		||||
#     if user.avatar is None:
 | 
			
		||||
#         return redirect(url_for('static', filename='images/user_avatar.png'))
 | 
			
		||||
#     return send_from_directory(
 | 
			
		||||
#         os.path.dirname(user.avatar.path),
 | 
			
		||||
#         os.path.basename(user.avatar.path),
 | 
			
		||||
#         as_attachment=True,
 | 
			
		||||
#         attachment_filename=user.avatar.filename,
 | 
			
		||||
#         mimetype=user.avatar.mimetype
 | 
			
		||||
#     )
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user