mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	More restructuring
This commit is contained in:
		@@ -16,6 +16,7 @@ from threading import Thread
 | 
			
		||||
import os
 | 
			
		||||
from .decorators import corpus_follower_permission_required, corpus_owner_or_admin_required
 | 
			
		||||
from app import db, hashids
 | 
			
		||||
from app.decorators import content_negotiation
 | 
			
		||||
from app.models import (
 | 
			
		||||
    Corpus,
 | 
			
		||||
    CorpusFile,
 | 
			
		||||
@@ -32,93 +33,6 @@ from .forms import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/is_public', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
def update_corpus_is_public(corpus_id):
 | 
			
		||||
    is_public = request.json
 | 
			
		||||
    if not isinstance(is_public, bool):
 | 
			
		||||
        response = jsonify('The request body must be a boolean')
 | 
			
		||||
        response.status_code = 400
 | 
			
		||||
        abort(response)
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    corpus.is_public = is_public
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    return '', 204
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/add', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
def add_corpus_followers(corpus_id):
 | 
			
		||||
    usernames = request.json
 | 
			
		||||
    if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
 | 
			
		||||
        response = jsonify('The request body must be a list of strings')
 | 
			
		||||
        response.status_code = 400
 | 
			
		||||
        abort(response)
 | 
			
		||||
    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()
 | 
			
		||||
    return '', 204
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/follow/<token>')
 | 
			
		||||
@login_required
 | 
			
		||||
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>/followers/<hashid:follower_id>/unfollow', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
def unfollow_corpus(corpus_id, follower_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    follower = User.query.get_or_404(follower_id)
 | 
			
		||||
    if not (corpus.user == current_user or follower == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    if not follower.is_following_corpus(corpus):
 | 
			
		||||
        abort(409)  # 'User is not following the corpus'
 | 
			
		||||
    follower.unfollow_corpus(corpus)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    flash(f'{follower.username} is not following {corpus.title} anymore', category='corpus')
 | 
			
		||||
    return '', 204
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['POST'])
 | 
			
		||||
@corpus_follower_permission_required('UPDATE_FOLLOWER')
 | 
			
		||||
def add_permission(corpus_id, follower_id):
 | 
			
		||||
    corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
    if not (corpus_follower_association.corpus.user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    role_name = request.json.get('role')
 | 
			
		||||
    if role_name is None:
 | 
			
		||||
        abort(400)
 | 
			
		||||
    corpus_follower_role = CorpusFollowerRole.query.filter_by(name=role_name).first_or_404()
 | 
			
		||||
    corpus_follower_association.role = corpus_follower_role
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    return '', 204
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/public')
 | 
			
		||||
@login_required
 | 
			
		||||
def public_corpora():
 | 
			
		||||
    corpora = [
 | 
			
		||||
        c.to_json_serializeable()
 | 
			
		||||
        for c in Corpus.query.filter(Corpus.is_public == True).all()
 | 
			
		||||
    ]
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'corpora/public_corpora.html.j2',
 | 
			
		||||
        corpora=corpora,
 | 
			
		||||
        title='Corpora'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/create', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
def create_corpus():
 | 
			
		||||
@@ -145,6 +59,24 @@ def create_corpus():
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/public')
 | 
			
		||||
@login_required
 | 
			
		||||
def public_corpora():
 | 
			
		||||
    corpora = [
 | 
			
		||||
        c.to_json_serializeable()
 | 
			
		||||
        for c in Corpus.query.filter(Corpus.is_public == True).all()
 | 
			
		||||
    ]
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'corpora/public_corpora.html.j2',
 | 
			
		||||
        corpora=corpora,
 | 
			
		||||
        title='Corpora'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
# Corpus                                                                     #
 | 
			
		||||
##############################################################################
 | 
			
		||||
#region corpus
 | 
			
		||||
@bp.route('/<hashid:corpus_id>')
 | 
			
		||||
@login_required
 | 
			
		||||
def corpus(corpus_id):
 | 
			
		||||
@@ -172,6 +104,18 @@ def corpus(corpus_id):
 | 
			
		||||
    abort(403)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/analyse')
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('VIEW')
 | 
			
		||||
def analyse_corpus(corpus_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'corpora/analyse_corpus.html.j2',
 | 
			
		||||
        corpus=corpus,
 | 
			
		||||
        title=f'Analyse Corpus {corpus.title}'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/generate-corpus-share-link', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('GENERATE_SHARE_LINK')
 | 
			
		||||
@@ -186,9 +130,34 @@ def generate_corpus_share_link(corpus_id):
 | 
			
		||||
    return link
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/follow/<token>')
 | 
			
		||||
@login_required
 | 
			
		||||
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'])
 | 
			
		||||
@login_required
 | 
			
		||||
def import_corpus():
 | 
			
		||||
    abort(503)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/export')
 | 
			
		||||
@login_required
 | 
			
		||||
def export_corpus(corpus_id):
 | 
			
		||||
    abort(503)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#region json-routes
 | 
			
		||||
@bp.route('/<hashid:corpus_id>', methods=['DELETE'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def delete_corpus(corpus_id):
 | 
			
		||||
    def _delete_corpus(app, corpus_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
@@ -199,27 +168,22 @@ def delete_corpus(corpus_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_delete_corpus,
 | 
			
		||||
        args=(current_app._get_current_object(), corpus_id)
 | 
			
		||||
        args=(current_app._get_current_object(), corpus.id)
 | 
			
		||||
    )
 | 
			
		||||
    thread.start()
 | 
			
		||||
    return {}, 202
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/analyse')
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('VIEW')
 | 
			
		||||
def analyse_corpus(corpus_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    return render_template(
 | 
			
		||||
        'corpora/analyse_corpus.html.j2',
 | 
			
		||||
        corpus=corpus,
 | 
			
		||||
        title=f'Analyse Corpus {corpus.title}'
 | 
			
		||||
    )
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'Corpus "{corpus.title}" marked for deletion',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(response_data)
 | 
			
		||||
    response.status_code = 200
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/build', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def build_corpus(corpus_id):
 | 
			
		||||
    def _build_corpus(app, corpus_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
@@ -230,18 +194,51 @@ def build_corpus(corpus_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    if not (corpus.user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    # Check if the corpus has corpus files
 | 
			
		||||
    if not corpus.files.all():
 | 
			
		||||
        response = {'errors': {'message': 'Corpus file(s) required'}}
 | 
			
		||||
        return response, 409
 | 
			
		||||
    if len(corpus.files.all()) == 0:
 | 
			
		||||
        abort(409)
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_build_corpus,
 | 
			
		||||
        args=(current_app._get_current_object(), corpus_id)
 | 
			
		||||
    )
 | 
			
		||||
    thread.start()
 | 
			
		||||
    return {}, 202
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'Corpus "{corpus.title}" marked for building',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(response_data)
 | 
			
		||||
    response.status_code = 202
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/is_public', methods=['PUT'])
 | 
			
		||||
@login_required
 | 
			
		||||
@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'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(response_data)
 | 
			
		||||
    response.status_code = 200
 | 
			
		||||
    return response
 | 
			
		||||
#endregion json-routes
 | 
			
		||||
#endregion corpus
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
# Corpus/Files                                                               #
 | 
			
		||||
##############################################################################
 | 
			
		||||
#region files
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/files/create', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('ADD_CORPUS_FILE')
 | 
			
		||||
@@ -292,7 +289,7 @@ def create_corpus_file(corpus_id):
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('ADD_CORPUS_FILE', 'UPDATE_CORPUS_FILE', 'REMOVE_CORPUS_FILE')
 | 
			
		||||
@corpus_follower_permission_required('UPDATE_CORPUS_FILE')
 | 
			
		||||
def corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    corpus_file = CorpusFile.query.filter_by(corpus_id = corpus_id, id=corpus_file_id).first_or_404()
 | 
			
		||||
    form = UpdateCorpusFileForm(data=corpus_file.to_json_serializeable())
 | 
			
		||||
@@ -313,27 +310,6 @@ def corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['DELETE'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('REMOVE_CORPUS_FILE')
 | 
			
		||||
def delete_corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    def _delete_corpus_file(app, corpus_file_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
            corpus_file = CorpusFile.query.get(corpus_file_id)
 | 
			
		||||
            corpus_file.delete()
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
 | 
			
		||||
    corpus_file = CorpusFile.query.filter_by(corpus_id = corpus_id, id=corpus_file_id).first_or_404()
 | 
			
		||||
    if not (corpus_file.corpus.user == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_delete_corpus_file,
 | 
			
		||||
        args=(current_app._get_current_object(), corpus_file_id)
 | 
			
		||||
    )
 | 
			
		||||
    thread.start()
 | 
			
		||||
    return {}, 202
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>/download')
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('VIEW')
 | 
			
		||||
@@ -350,13 +326,95 @@ def download_corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/import', methods=['GET', 'POST'])
 | 
			
		||||
#region json-routes
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['DELETE'])
 | 
			
		||||
@login_required
 | 
			
		||||
def import_corpus():
 | 
			
		||||
    abort(503)
 | 
			
		||||
@corpus_follower_permission_required('REMOVE_CORPUS_FILE')
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def delete_corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    def _delete_corpus_file(app, corpus_file_id):
 | 
			
		||||
        with app.app_context():
 | 
			
		||||
            corpus_file = CorpusFile.query.get(corpus_file_id)
 | 
			
		||||
            corpus_file.delete()
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
 | 
			
		||||
    corpus_file = CorpusFile.query.filter_by(corpus_id=corpus_id, id=corpus_file_id).first_or_404()
 | 
			
		||||
    thread = Thread(
 | 
			
		||||
        target=_delete_corpus_file,
 | 
			
		||||
        args=(current_app._get_current_object(), corpus_file.id)
 | 
			
		||||
    )
 | 
			
		||||
    thread.start()
 | 
			
		||||
    return {}, 202
 | 
			
		||||
#endregion json-routes
 | 
			
		||||
#endregion files
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
# Corpus/Followers                                                           #
 | 
			
		||||
##############################################################################
 | 
			
		||||
#region followers
 | 
			
		||||
#region json-routes
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def add_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()
 | 
			
		||||
    resonse_data = {
 | 
			
		||||
        'message': f'Users are now following "{corpus.title}"',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(resonse_data)
 | 
			
		||||
    response.status_code = 200
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/export')
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
 | 
			
		||||
@login_required
 | 
			
		||||
def export_corpus(corpus_id):
 | 
			
		||||
    abort(503)
 | 
			
		||||
@content_negotiation(produces='application/json')
 | 
			
		||||
def unfollow_corpus(corpus_id, follower_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    follower = User.query.get_or_404(follower_id)
 | 
			
		||||
    if not (corpus.user == current_user or follower == current_user or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    if not follower.is_following_corpus(corpus):
 | 
			
		||||
        abort(409)  # 'User is not following the corpus'
 | 
			
		||||
    follower.unfollow_corpus(corpus)
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': \
 | 
			
		||||
            f'"{follower.username}" is not following "{corpus.title}" anymore',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(response_data)
 | 
			
		||||
    response.status_code = 200
 | 
			
		||||
    return response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_owner_or_admin_required
 | 
			
		||||
@content_negotiation(consumes='application/json', produces='application/json')
 | 
			
		||||
def add_permission(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_or_404()
 | 
			
		||||
    cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
			
		||||
    cfa.role = cfr
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    resonse_data = {
 | 
			
		||||
        'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(resonse_data)
 | 
			
		||||
    response.status_code = 200
 | 
			
		||||
    return response
 | 
			
		||||
#endregion json-routes
 | 
			
		||||
#endregion followers
 | 
			
		||||
 
 | 
			
		||||
@@ -1,51 +0,0 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
* Contributions                                                              *
 | 
			
		||||
* Fetch requests for /contributions routes                                   *
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
Requests.contributions = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.ent = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.ent.delete = (spacyNlpPipelineModelId) => {
 | 
			
		||||
  let input = `/contributions/spacy-nlp-pipeline-models/${spacyNlpPipelineModelId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE'
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.ent.isPublic = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.ent.isPublic.update = (spacyNlpPipelineModelId, value) => {
 | 
			
		||||
  let input = `/contributions/spacy-nlp-pipeline-models/${spacyNlpPipelineModelId}/is_public`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.ent = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.ent.delete = (tesseractOcrPipelineModelId) => {
 | 
			
		||||
  let input = `/contributions/tesseract-ocr-pipeline-models/${tesseractOcrPipelineModelId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE'
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.ent.isPublic = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.ent.isPublic.update = (tesseractOcrPipelineModelId, value) => {
 | 
			
		||||
  let input = `/contributions/tesseract-ocr-pipeline-models/${tesseractOcrPipelineModelId}/is_public`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										0
									
								
								app/static/js/Requests/Corpora.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/static/js/Requests/Corpora.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										5
									
								
								app/static/js/Requests/contributions/contributions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/static/js/Requests/contributions/contributions.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
* Contributions                                                              *
 | 
			
		||||
* Fetch requests for /contributions routes                                   *
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
Requests.contributions = {};
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
* SpaCy NLP Pipeline Models                                                  *
 | 
			
		||||
* Fetch requests for /contributions/spacy-nlp-pipeline-models routes         *
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.entity = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.entity.delete = (spacyNlpPipelineModelId) => {
 | 
			
		||||
  let input = `/contributions/spacy-nlp-pipeline-models/${spacyNlpPipelineModelId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE'
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.entity.isPublic = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.spacy_nlp_pipeline_models.entity.isPublic.update = (spacyNlpPipelineModelId, value) => {
 | 
			
		||||
  let input = `/contributions/spacy-nlp-pipeline-models/${spacyNlpPipelineModelId}/is_public`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
* Tesseract OCR Pipeline Models                                              *
 | 
			
		||||
* Fetch requests for /contributions/tesseract-ocr-pipeline-models routes     *
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.entity = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.entity.delete = (tesseractOcrPipelineModelId) => {
 | 
			
		||||
  let input = `/contributions/tesseract-ocr-pipeline-models/${tesseractOcrPipelineModelId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE'
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.entity.isPublic = {};
 | 
			
		||||
 | 
			
		||||
Requests.contributions.tesseract_ocr_pipeline_models.entity.isPublic.update = (tesseractOcrPipelineModelId, value) => {
 | 
			
		||||
  let input = `/contributions/tesseract-ocr-pipeline-models/${tesseractOcrPipelineModelId}/is_public`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										78
									
								
								app/static/js/Requests/corpora/corpora.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								app/static/js/Requests/corpora/corpora.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
* Corpora                                                                    *
 | 
			
		||||
* Fetch requests for /corpora routes                                         *
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
Requests.corpora = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.delete = (corpusId) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE'
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.build = (corpusId) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/build`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.isPublic = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.isPublic.update = (corpusId, value) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/is_public`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.files = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.files.ent = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.files.ent.delete = (corpusId, corpusFileId) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/files/${corpusFileId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE',
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers.add = (corpusId, usernames) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/followers`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    body: JSON.stringify(usernames)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers.ent = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers.ent.delete = (corpusId, followerId) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/followers/${followerId}`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'DELETE',
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers.ent.role = {};
 | 
			
		||||
 | 
			
		||||
Requests.corpora.ent.followers.ent.role.update = (corpusId, followerId, value) => {
 | 
			
		||||
  let input = `/corpora/${corpusId}/followers/${followerId}/role`;
 | 
			
		||||
  let init = {
 | 
			
		||||
    method: 'PUT',
 | 
			
		||||
    body: JSON.stringify(value)
 | 
			
		||||
  };
 | 
			
		||||
  return Requests.JSONfetch(input, init);
 | 
			
		||||
};
 | 
			
		||||
@@ -120,7 +120,7 @@ class SpaCyNLPPipelineModelList extends ResourceList {
 | 
			
		||||
    switch (listAction) {
 | 
			
		||||
      case 'toggle-is-public': {
 | 
			
		||||
        let newIsPublicValue = listActionElement.checked;
 | 
			
		||||
        Requests.contributions.spacy_nlp_pipeline_models.ent.isPublic.update(itemId, newIsPublicValue)
 | 
			
		||||
        Requests.contributions.spacy_nlp_pipeline_models.entity.isPublic.update(itemId, newIsPublicValue)
 | 
			
		||||
          .catch((response) => {
 | 
			
		||||
            listActionElement.checked = !newIsPublicValue;
 | 
			
		||||
          });
 | 
			
		||||
@@ -141,7 +141,37 @@ class SpaCyNLPPipelineModelList extends ResourceList {
 | 
			
		||||
    let listAction = listActionElement === null ? 'view' : listActionElement.dataset.listAction;
 | 
			
		||||
    switch (listAction) {
 | 
			
		||||
      case 'delete-request': {
 | 
			
		||||
        Requests.contributions.spacy_nlp_pipeline_models.ent.delete(itemId);
 | 
			
		||||
        let values = this.listjs.get('id', itemId)[0].values();
 | 
			
		||||
        let modalElement = Utils.HTMLToElement(
 | 
			
		||||
          `
 | 
			
		||||
            <div class="modal">
 | 
			
		||||
              <div class="modal-content">
 | 
			
		||||
                <h4>Confirm SpaCy NLP Pipeline Model deletion</h4>
 | 
			
		||||
                <p>Do you really want to delete the SpaCy NLP Pipeline Model <b>${values.title}</b>? All files will be permanently deleted!</p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="modal-footer">
 | 
			
		||||
                <a class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          `
 | 
			
		||||
        );
 | 
			
		||||
        document.querySelector('#modals').appendChild(modalElement);
 | 
			
		||||
        let modal = M.Modal.init(
 | 
			
		||||
          modalElement,
 | 
			
		||||
          {
 | 
			
		||||
            dismissible: false,
 | 
			
		||||
            onCloseEnd: () => {
 | 
			
		||||
              modal.destroy();
 | 
			
		||||
              modalElement.remove();
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        );
 | 
			
		||||
        let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
 | 
			
		||||
        confirmElement.addEventListener('click', (event) => {
 | 
			
		||||
          Requests.contributions.spacy_nlp_pipeline_models.entity.delete(itemId);
 | 
			
		||||
        });
 | 
			
		||||
        modal.open();
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'view': {
 | 
			
		||||
 
 | 
			
		||||
@@ -129,7 +129,7 @@ class TesseractOCRPipelineModelList extends ResourceList {
 | 
			
		||||
    switch (listAction) {
 | 
			
		||||
      case 'toggle-is-public': {
 | 
			
		||||
        let newIsPublicValue = listActionElement.checked;
 | 
			
		||||
        Requests.contributions.tesseract_ocr_pipeline_models.ent.isPublic.update(itemId, newIsPublicValue)
 | 
			
		||||
        Requests.contributions.tesseract_ocr_pipeline_models.entity.isPublic.update(itemId, newIsPublicValue)
 | 
			
		||||
          .catch((response) => {
 | 
			
		||||
            listActionElement.checked = !newIsPublicValue;
 | 
			
		||||
          });
 | 
			
		||||
@@ -155,7 +155,37 @@ class TesseractOCRPipelineModelList extends ResourceList {
 | 
			
		||||
    let listAction = listActionElement === null ? 'view' : listActionElement.dataset.listAction;
 | 
			
		||||
    switch (listAction) {
 | 
			
		||||
      case 'delete-request': {
 | 
			
		||||
        Requests.contributions.tesseract_ocr_pipeline_models.ent.delete(itemId);
 | 
			
		||||
        let values = this.listjs.get('id', itemId)[0].values();
 | 
			
		||||
        let modalElement = Utils.HTMLToElement(
 | 
			
		||||
          `
 | 
			
		||||
            <div class="modal">
 | 
			
		||||
              <div class="modal-content">
 | 
			
		||||
                <h4>Confirm Tesseract OCR Pipeline Model deletion</h4>
 | 
			
		||||
                <p>Do you really want to delete the Tesseract OCR Pipeline Model <b>${values.title}</b>? All files will be permanently deleted!</p>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="modal-footer">
 | 
			
		||||
                <a class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
                <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          `
 | 
			
		||||
        );
 | 
			
		||||
        document.querySelector('#modals').appendChild(modalElement);
 | 
			
		||||
        let modal = M.Modal.init(
 | 
			
		||||
          modalElement,
 | 
			
		||||
          {
 | 
			
		||||
            dismissible: false,
 | 
			
		||||
            onCloseEnd: () => {
 | 
			
		||||
              modal.destroy();
 | 
			
		||||
              modalElement.remove();
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        );
 | 
			
		||||
        let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
 | 
			
		||||
        confirmElement.addEventListener('click', (event) => {
 | 
			
		||||
          Requests.contributions.tesseract_ocr_pipeline_models.entity.delete(itemId);
 | 
			
		||||
        });
 | 
			
		||||
        modal.open();
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'view': {
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,10 @@
 | 
			
		||||
  filters='rjsmin',
 | 
			
		||||
  output='gen/Requests.%(version)s.js',
 | 
			
		||||
  'js/Requests/Requests.js',
 | 
			
		||||
  'js/Requests/Contributions.js'
 | 
			
		||||
  'js/Requests/contributions/contributions.js',
 | 
			
		||||
  'js/Requests/contributions/spacy_nlp_pipeline_models.js',
 | 
			
		||||
  'js/Requests/contributions/tesseract_ocr_pipeline_models.js',
 | 
			
		||||
  'js/Requests/Corpora.js'
 | 
			
		||||
%}
 | 
			
		||||
<script src="{{ ASSET_URL }}"></script>
 | 
			
		||||
{%- endassets %}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
 | 
			
		||||
    <div class="col s4">
 | 
			
		||||
      <div class="card extension-selector hoverable service-color" data-service="spacy-nlp-pipeline">
 | 
			
		||||
      <a href="{{ url_for('.spacy_nlp_pipeline_models.spacy_nlp_pipeline_models') }}" style="position: absolute; width: 100%; height: 100%;"></a>
 | 
			
		||||
        <a href="{{ url_for('.spacy_nlp_pipeline_models.spacy_nlp_pipeline_models') }}" style="position: absolute; width: 100%; height: 100%;"></a>
 | 
			
		||||
        <div class="card-content">
 | 
			
		||||
          <span class="card-title"><i class="nopaque-icons service-icons" data-service="spacy-nlp-pipeline"></i>SpaCy NLP Pipeline Models</span>
 | 
			
		||||
          <p>Here you can see and edit the models that you have created. You can also create new models.</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,7 @@
 | 
			
		||||
              <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 class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
 | 
			
		||||
              <a class="action-button btn red waves-effect waves-light" data-action="delete-request" 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>
 | 
			
		||||
          <span class="card-title">Social</span>
 | 
			
		||||
@@ -131,6 +131,17 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="modal" id="delete-modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
    <h4>Confirm Corpus deletion</h4>
 | 
			
		||||
    <p>Do you really want to delete the Corpus <b>{{ corpus.title }}</b>? All files will be permanently deleted!</p>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="modal-footer">
 | 
			
		||||
    <a class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
			
		||||
    <a class="btn modal-close red waves-effect waves-light" id="delete-modal-delete-button">Delete</a>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="modal no-autoinit" id="invite-user-modal">
 | 
			
		||||
  <div class="modal-content">
 | 
			
		||||
    <h4>Invite a nopaque user by username</h4>
 | 
			
		||||
@@ -215,13 +226,21 @@
 | 
			
		||||
  let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
 | 
			
		||||
  publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
 | 
			
		||||
    let newIsPublic = publishingModalIsPublicSwitchElement.checked;
 | 
			
		||||
    Utils.updateCorpusIsPublicRequest(corpusId, newIsPublic)
 | 
			
		||||
    Requests.corpora.corpus.isPublic.update(corpusId, newIsPublic)
 | 
			
		||||
      .catch((response) => {
 | 
			
		||||
        publishingModalIsPublicSwitchElement.checked = !newIsPublic;
 | 
			
		||||
      });
 | 
			
		||||
  });
 | 
			
		||||
  // #endregion publishing_modal_js
 | 
			
		||||
 | 
			
		||||
  // #region delete_modal_js
 | 
			
		||||
  let deleteModalDeleteButtonElement = document.querySelector('#delete-modal-delete-button');
 | 
			
		||||
  deleteModalDeleteButtonElement.addEventListener('click', (event) => {
 | 
			
		||||
    Requests.corpora.corpus.delete(corpusId)
 | 
			
		||||
      .then((response) => {window.location.href = '/dashboard';});
 | 
			
		||||
  });
 | 
			
		||||
  // #endregion delete_modal_js
 | 
			
		||||
 | 
			
		||||
  // #region invite_user_modal_js
 | 
			
		||||
  let inviteUserModalElement = document.querySelector('#invite-user-modal');
 | 
			
		||||
  let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user