mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 04:12:45 +00:00 
			
		
		
		
	Rework corpora package
This commit is contained in:
		
							
								
								
									
										8
									
								
								app/corpora/files/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/corpora/files/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
from flask import Blueprint
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEMPLATE_FOLDER = 'corpora/files'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bp = Blueprint('files', __name__)
 | 
			
		||||
from . import routes, json_routes
 | 
			
		||||
							
								
								
									
										54
									
								
								app/corpora/files/forms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/corpora/files/forms.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
from flask_wtf import FlaskForm
 | 
			
		||||
from flask_wtf.file import FileField, FileRequired
 | 
			
		||||
from wtforms import (
 | 
			
		||||
    StringField,
 | 
			
		||||
    SubmitField,
 | 
			
		||||
    ValidationError,
 | 
			
		||||
    IntegerField
 | 
			
		||||
)
 | 
			
		||||
from wtforms.validators import InputRequired, Length
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CorpusFileBaseForm(FlaskForm):
 | 
			
		||||
    author = StringField(
 | 
			
		||||
        'Author',
 | 
			
		||||
        validators=[InputRequired(), Length(max=255)]
 | 
			
		||||
    )
 | 
			
		||||
    publishing_year = IntegerField(
 | 
			
		||||
        'Publishing year',
 | 
			
		||||
        validators=[InputRequired()]
 | 
			
		||||
    )
 | 
			
		||||
    title = StringField(
 | 
			
		||||
        'Title',
 | 
			
		||||
        validators=[InputRequired(), Length(max=255)]
 | 
			
		||||
    )
 | 
			
		||||
    address = StringField('Adress', validators=[Length(max=255)])
 | 
			
		||||
    booktitle = StringField('Booktitle', validators=[Length(max=255)])
 | 
			
		||||
    chapter = StringField('Chapter', validators=[Length(max=255)])
 | 
			
		||||
    editor = StringField('Editor', validators=[Length(max=255)])
 | 
			
		||||
    institution = StringField('Institution', validators=[Length(max=255)])
 | 
			
		||||
    journal = StringField('Journal', validators=[Length(max=255)])
 | 
			
		||||
    pages = StringField('Pages', validators=[Length(max=255)])
 | 
			
		||||
    publisher = StringField('Publisher', validators=[Length(max=255)])
 | 
			
		||||
    school = StringField('School', validators=[Length(max=255)])
 | 
			
		||||
    submit = SubmitField()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CreateCorpusFileForm(CorpusFileBaseForm):
 | 
			
		||||
    vrt = FileField('File', validators=[FileRequired()])
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        if 'prefix' not in kwargs:
 | 
			
		||||
            kwargs['prefix'] = 'create-corpus-file-form'
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def validate_vrt(self, field):
 | 
			
		||||
        if not field.data.filename.lower().endswith('.vrt'):
 | 
			
		||||
            raise ValidationError('VRT files only!')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UpdateCorpusFileForm(CorpusFileBaseForm):
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        if 'prefix' not in kwargs:
 | 
			
		||||
            kwargs['prefix'] = 'update-corpus-file-form'
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
							
								
								
									
										42
									
								
								app/corpora/files/json_routes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/corpora/files/json_routes.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
from flask import current_app, jsonify
 | 
			
		||||
from flask_login import login_required
 | 
			
		||||
from threading import Thread
 | 
			
		||||
from app import db
 | 
			
		||||
from app.decorators import content_negotiation
 | 
			
		||||
from app.models import CorpusFile
 | 
			
		||||
from ..decorators import corpus_follower_permission_required
 | 
			
		||||
from . import bp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
# IMPORTANT NOTE: These routes are prefixed by the blueprint                 #
 | 
			
		||||
#                 Prefix: <hashid:corpus_id>/files                           #
 | 
			
		||||
#                 This implies that the corpus_id is always in the kwargs of #
 | 
			
		||||
#                 a route that is registered to this blueprint.              #
 | 
			
		||||
##############################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_file_id>', methods=['DELETE'])
 | 
			
		||||
@login_required
 | 
			
		||||
@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()
 | 
			
		||||
    response_data = {
 | 
			
		||||
        'message': f'Corpus File "{corpus_file.title}" marked for deletion',
 | 
			
		||||
        'category': 'corpus'
 | 
			
		||||
    }
 | 
			
		||||
    response = jsonify(response_data)
 | 
			
		||||
    response.status_code = 202
 | 
			
		||||
    return response
 | 
			
		||||
							
								
								
									
										101
									
								
								app/corpora/files/routes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								app/corpora/files/routes.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
from flask import (
 | 
			
		||||
    abort,
 | 
			
		||||
    flash,
 | 
			
		||||
    Markup,
 | 
			
		||||
    redirect,
 | 
			
		||||
    render_template,
 | 
			
		||||
    send_from_directory
 | 
			
		||||
)
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
import os
 | 
			
		||||
from app import db
 | 
			
		||||
from app.models import Corpus, CorpusFile, CorpusStatus
 | 
			
		||||
from ..decorators import corpus_follower_permission_required
 | 
			
		||||
from . import bp, TEMPLATE_FOLDER
 | 
			
		||||
from .forms import CreateCorpusFileForm, UpdateCorpusFileForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##############################################################################
 | 
			
		||||
# IMPORTANT NOTE: These routes are prefixed by the blueprint                 #
 | 
			
		||||
#                 Prefix: <hashid:corpus_id>/files                           #
 | 
			
		||||
#                 This implies that the corpus_id is always in the kwargs of #
 | 
			
		||||
#                 a route that is registered to this blueprint.              #
 | 
			
		||||
##############################################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/create', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('ADD_CORPUS_FILE')
 | 
			
		||||
def create_corpus_file(corpus_id):
 | 
			
		||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
			
		||||
    form = CreateCorpusFileForm()
 | 
			
		||||
    if form.is_submitted():
 | 
			
		||||
        if not form.validate():
 | 
			
		||||
            response = {'errors': form.errors}
 | 
			
		||||
            return response, 400
 | 
			
		||||
        try:
 | 
			
		||||
            corpus_file = CorpusFile.create(
 | 
			
		||||
                form.vrt.data,
 | 
			
		||||
                address=form.address.data,
 | 
			
		||||
                author=form.author.data,
 | 
			
		||||
                booktitle=form.booktitle.data,
 | 
			
		||||
                chapter=form.chapter.data,
 | 
			
		||||
                editor=form.editor.data,
 | 
			
		||||
                institution=form.institution.data,
 | 
			
		||||
                journal=form.journal.data,
 | 
			
		||||
                pages=form.pages.data,
 | 
			
		||||
                publisher=form.publisher.data,
 | 
			
		||||
                publishing_year=form.publishing_year.data,
 | 
			
		||||
                school=form.school.data,
 | 
			
		||||
                title=form.title.data,
 | 
			
		||||
                mimetype='application/vrt+xml',
 | 
			
		||||
                corpus=corpus
 | 
			
		||||
            )
 | 
			
		||||
        except (AttributeError, OSError):
 | 
			
		||||
            abort(500)
 | 
			
		||||
        corpus.status = CorpusStatus.UNPREPARED
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        flash(f'Corpus File "{corpus_file.filename}" added', category='corpus')
 | 
			
		||||
        return '', 201, {'Location': corpus.url}
 | 
			
		||||
    return render_template(
 | 
			
		||||
        f'{TEMPLATE_FOLDER}/create_corpus_file.html.j2',
 | 
			
		||||
        corpus=corpus,
 | 
			
		||||
        form=form,
 | 
			
		||||
        title='Add corpus file'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_file_id>', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
@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())
 | 
			
		||||
    if form.validate_on_submit():
 | 
			
		||||
        form.populate_obj(corpus_file)
 | 
			
		||||
        if db.session.is_modified(corpus_file):
 | 
			
		||||
            corpus_file.corpus.status = CorpusStatus.UNPREPARED
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
            flash(f'Corpus file "{corpus_file.filename}" updated', category='corpus')
 | 
			
		||||
        return redirect(corpus_file.corpus.url)
 | 
			
		||||
    return render_template(
 | 
			
		||||
        f'{TEMPLATE_FOLDER}/corpus_file.html.j2',
 | 
			
		||||
        corpus=corpus_file.corpus,
 | 
			
		||||
        corpus_file=corpus_file,
 | 
			
		||||
        form=form,
 | 
			
		||||
        title='Edit corpus file'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.route('/<hashid:corpus_file_id>/download')
 | 
			
		||||
@login_required
 | 
			
		||||
@corpus_follower_permission_required('VIEW')
 | 
			
		||||
def download_corpus_file(corpus_id, corpus_file_id):
 | 
			
		||||
    corpus_file = CorpusFile.query.filter_by(corpus_id=corpus_id, id=corpus_file_id).first_or_404()
 | 
			
		||||
    return send_from_directory(
 | 
			
		||||
        os.path.dirname(corpus_file.path),
 | 
			
		||||
        os.path.basename(corpus_file.path),
 | 
			
		||||
        as_attachment=True,
 | 
			
		||||
        attachment_filename=corpus_file.filename,
 | 
			
		||||
        mimetype=corpus_file.mimetype
 | 
			
		||||
    )
 | 
			
		||||
		Reference in New Issue
	
	Block a user