mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 04:12:45 +00:00 
			
		
		
		
	Add a parallel package for query results.
This commit is contained in:
		
							
								
								
									
										5
									
								
								web/app/query_results/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								web/app/query_results/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
from flask import Blueprint
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
query_results = Blueprint('query_results', __name__)
 | 
			
		||||
from . import views  # noqa
 | 
			
		||||
							
								
								
									
										21
									
								
								web/app/query_results/forms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								web/app/query_results/forms.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
from flask_wtf import FlaskForm
 | 
			
		||||
from werkzeug.utils import secure_filename
 | 
			
		||||
from wtforms import FileField, StringField, SubmitField, ValidationError
 | 
			
		||||
from wtforms.validators import DataRequired, Length
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AddQueryResultForm(FlaskForm):
 | 
			
		||||
    '''
 | 
			
		||||
    Form used to import one result json file.
 | 
			
		||||
    '''
 | 
			
		||||
    description = StringField('Description',
 | 
			
		||||
                              validators=[DataRequired(), Length(1, 255)])
 | 
			
		||||
    file = FileField('File', validators=[DataRequired()])
 | 
			
		||||
    title = StringField('Title', validators=[DataRequired(), Length(1, 32)])
 | 
			
		||||
    submit = SubmitField()
 | 
			
		||||
 | 
			
		||||
    def validate_file(self, field):
 | 
			
		||||
        if not field.data.filename.lower().endswith('.json'):
 | 
			
		||||
            raise ValidationError('File does not have an approved extension: '
 | 
			
		||||
                                  '.json')
 | 
			
		||||
        field.data.filename = secure_filename(field.data.filename)
 | 
			
		||||
							
								
								
									
										13
									
								
								web/app/query_results/tasks.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/app/query_results/tasks.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
from .. import db
 | 
			
		||||
from ..decorators import background
 | 
			
		||||
from ..models import QueryResult
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@background
 | 
			
		||||
def delete_query_result(query_result_id, *args, **kwargs):
 | 
			
		||||
    with kwargs['app'].app_context():
 | 
			
		||||
        query_result = QueryResult.query.get(query_result_id)
 | 
			
		||||
        if query_result is None:
 | 
			
		||||
            raise Exception('QueryResult {} not found'.format(query_result_id))
 | 
			
		||||
        query_result.delete()
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
							
								
								
									
										144
									
								
								web/app/query_results/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								web/app/query_results/views.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
from . import query_results
 | 
			
		||||
from . import tasks
 | 
			
		||||
from .. import db
 | 
			
		||||
from ..corpora.forms import DisplayOptionsForm
 | 
			
		||||
from ..models import QueryResult
 | 
			
		||||
from .forms import AddQueryResultForm
 | 
			
		||||
from flask import (abort, current_app, flash, make_response, redirect,
 | 
			
		||||
                   render_template, request, send_from_directory, url_for)
 | 
			
		||||
from flask_login import current_user, login_required
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
from jsonschema import validate
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@query_results.route('/add', methods=['GET', 'POST'])
 | 
			
		||||
@login_required
 | 
			
		||||
def add_query_result():
 | 
			
		||||
    '''
 | 
			
		||||
    View to import a result as a json file.
 | 
			
		||||
    '''
 | 
			
		||||
    add_query_result_form = AddQueryResultForm(prefix='add-query-result-form')
 | 
			
		||||
    if add_query_result_form.is_submitted():
 | 
			
		||||
        if not add_query_result_form.validate():
 | 
			
		||||
            return make_response(add_query_result_form.errors, 400)
 | 
			
		||||
        query_result = QueryResult(
 | 
			
		||||
            creator=current_user,
 | 
			
		||||
            description=add_query_result_form.description.data,
 | 
			
		||||
            filename=add_query_result_form.file.data.filename,
 | 
			
		||||
            title=add_query_result_form.title.data
 | 
			
		||||
        )
 | 
			
		||||
        db.session.add(query_result)
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        # create paths to save the uploaded json file
 | 
			
		||||
        query_result_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
 | 
			
		||||
                                        str(current_user.id),
 | 
			
		||||
                                        'query_results',
 | 
			
		||||
                                        str(query_result.id))
 | 
			
		||||
        try:
 | 
			
		||||
            os.makedirs(query_result_dir)
 | 
			
		||||
        except Exception:
 | 
			
		||||
            db.session.delete(query_result)
 | 
			
		||||
            db.session.commit()
 | 
			
		||||
            flash('Internal Server Error', 'error')
 | 
			
		||||
            redirect_url = url_for('query_results.add_query_result')
 | 
			
		||||
            return make_response({'redirect_url': redirect_url}, 500)
 | 
			
		||||
        # save the uploaded file
 | 
			
		||||
        query_result_file_path = os.path.join(query_result_dir,
 | 
			
		||||
                                              query_result.filename)
 | 
			
		||||
        add_query_result_form.file.data.save(query_result_file_path)
 | 
			
		||||
        # parse json from file
 | 
			
		||||
        with open(query_result_file_path, 'r') as file:
 | 
			
		||||
            query_result_file_content = json.load(file)
 | 
			
		||||
        # parse json schema
 | 
			
		||||
        with open('app/static/json_schema/nopaque_cqi_py_results_schema.json', 'r') as file:  # noqa
 | 
			
		||||
            schema = json.load(file)
 | 
			
		||||
        try:
 | 
			
		||||
            # validate imported json file
 | 
			
		||||
            validate(instance=query_result_file_content, schema=schema)
 | 
			
		||||
        except Exception:
 | 
			
		||||
            tasks.delete_query_result(query_result.id)
 | 
			
		||||
            flash('Uploaded file is invalid', 'result')
 | 
			
		||||
            redirect_url = url_for('query_results.add_query_result')
 | 
			
		||||
            return make_response({'redirect_url': redirect_url}, 201)
 | 
			
		||||
        query_result_file_content.pop('matches')
 | 
			
		||||
        query_result_file_content.pop('cpos_lookup')
 | 
			
		||||
        query_result.query_metadata = query_result_file_content
 | 
			
		||||
        db.session.commit()
 | 
			
		||||
        flash('Query result added!', 'result')
 | 
			
		||||
        redirect_url = url_for('query_results.query_result',
 | 
			
		||||
                               query_result_id=query_result.id)
 | 
			
		||||
        return make_response({'redirect_url': redirect_url}, 201)
 | 
			
		||||
    return render_template('query_results/add_query_result.html.j2',
 | 
			
		||||
                           add_query_result_form=add_query_result_form,
 | 
			
		||||
                           title='Add query result')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@query_results.route('/<int:query_result_id>')
 | 
			
		||||
@login_required
 | 
			
		||||
def query_result(query_result_id):
 | 
			
		||||
    query_result = QueryResult.query.get_or_404(query_result_id)
 | 
			
		||||
    if not (query_result.creator == current_user
 | 
			
		||||
            or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    return render_template('query_results/query_result.html.j2',
 | 
			
		||||
                           query_result=query_result,
 | 
			
		||||
                           title='Query result')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@query_results.route('/<int:query_result_id>/inspect')
 | 
			
		||||
@login_required
 | 
			
		||||
def inspect_query_result(query_result_id):
 | 
			
		||||
    '''
 | 
			
		||||
    View to inspect one importe result file in a corpus analysis like interface
 | 
			
		||||
    '''
 | 
			
		||||
    query_result = QueryResult.query.get_or_404(query_result_id)
 | 
			
		||||
    if not (query_result.creator == current_user
 | 
			
		||||
            or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    display_options_form = DisplayOptionsForm(
 | 
			
		||||
        prefix='display-options-form',
 | 
			
		||||
        results_per_page=request.args.get('results_per_page', 30),
 | 
			
		||||
        result_context=request.args.get('context', 20)
 | 
			
		||||
    )
 | 
			
		||||
    query_result_file_path = os.path.join(
 | 
			
		||||
        current_app.config['NOPAQUE_STORAGE'],
 | 
			
		||||
        str(current_user.id),
 | 
			
		||||
        'query_results',
 | 
			
		||||
        str(query_result.id),
 | 
			
		||||
        query_result.filename
 | 
			
		||||
    )
 | 
			
		||||
    with open(query_result_file_path, 'r') as query_result_file:
 | 
			
		||||
        query_result_content = json.load(query_result_file)
 | 
			
		||||
    return render_template('query_results/inspect_query_result.html.j2',
 | 
			
		||||
                           display_options_form=display_options_form,
 | 
			
		||||
                           query_result_content=query_result_content,
 | 
			
		||||
                           title='Inspect query result')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@query_results.route('/<int:query_result_id>/delete')
 | 
			
		||||
@login_required
 | 
			
		||||
def delete_query_result(query_result_id):
 | 
			
		||||
    query_result = QueryResult.query.get_or_404(query_result_id)
 | 
			
		||||
    if not (query_result.creator == current_user
 | 
			
		||||
            or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    tasks.delete_result(query_result_id)
 | 
			
		||||
    flash('Query result deleted!', 'result')
 | 
			
		||||
    return redirect(url_for('main.dashboard'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@query_results.route('/<int:query_result_id>/download')
 | 
			
		||||
@login_required
 | 
			
		||||
def download_query_result(query_result_id):
 | 
			
		||||
    query_result = QueryResult.query.get_or_404(query_result_id)
 | 
			
		||||
    if not (query_result.creator == current_user
 | 
			
		||||
            or current_user.is_administrator()):
 | 
			
		||||
        abort(403)
 | 
			
		||||
    query_result_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
 | 
			
		||||
                                    str(current_user.id),
 | 
			
		||||
                                    'query_results',
 | 
			
		||||
                                    str(query_result.id))
 | 
			
		||||
    return send_from_directory(as_attachment=True,
 | 
			
		||||
                               directory=query_result_dir,
 | 
			
		||||
                               filename=query_result.filename)
 | 
			
		||||
		Reference in New Issue
	
	Block a user