2020-07-03 12:41:57 +00:00
|
|
|
from . import results
|
2020-07-07 13:08:15 +00:00
|
|
|
from . import tasks
|
|
|
|
from .. import db
|
2020-07-03 12:41:57 +00:00
|
|
|
from ..corpora.forms import DisplayOptionsForm
|
2020-07-07 13:08:15 +00:00
|
|
|
from ..models import Result, ResultFile, User
|
|
|
|
from .forms import ImportResultsForm
|
|
|
|
from datetime import datetime
|
|
|
|
from flask import (abort, render_template, current_app, request, redirect,
|
2020-07-08 14:03:44 +00:00
|
|
|
flash, url_for, make_response, send_from_directory)
|
2020-07-07 13:08:15 +00:00
|
|
|
from flask_login import current_user, login_required
|
2020-07-03 12:41:57 +00:00
|
|
|
import json
|
|
|
|
import os
|
2020-07-08 13:24:18 +00:00
|
|
|
from .. import logger
|
2020-07-09 13:41:25 +00:00
|
|
|
from jsonschema import validate
|
2020-07-03 12:41:57 +00:00
|
|
|
|
|
|
|
|
2020-07-07 13:08:15 +00:00
|
|
|
@results.route('/import_results', methods=['GET', 'POST'])
|
|
|
|
@login_required
|
|
|
|
def import_results():
|
|
|
|
'''
|
|
|
|
View to import one json result file. Uses the ImportReultFileForm.
|
|
|
|
'''
|
|
|
|
import_results_form = ImportResultsForm(prefix='add-result-file-form')
|
|
|
|
if import_results_form.is_submitted():
|
|
|
|
if not import_results_form.validate():
|
|
|
|
return make_response(import_results_form.errors, 400)
|
|
|
|
# Save the file
|
|
|
|
# result creation only happens on file save to avoid creating a result
|
|
|
|
# object in the db everytime by just visiting the import_results page
|
|
|
|
result = Result(user_id=current_user.id)
|
|
|
|
db.session.add(result)
|
|
|
|
db.session.commit()
|
|
|
|
if not (result.creator == current_user
|
|
|
|
or current_user.is_administrator()):
|
|
|
|
abort(403)
|
2020-07-09 13:41:25 +00:00
|
|
|
# create paths to save the uploaded json file
|
2020-07-07 13:08:15 +00:00
|
|
|
dir = os.path.join(str(result.user_id),
|
|
|
|
'results',
|
|
|
|
'corpus_analysis_results',
|
|
|
|
str(result.id))
|
|
|
|
abs_dir = os.path.join(current_app.config['NOPAQUE_STORAGE'], dir)
|
|
|
|
abs_file_path = os.path.join(abs_dir,
|
|
|
|
import_results_form.file.data.filename)
|
|
|
|
os.makedirs(abs_dir)
|
2020-07-09 13:41:25 +00:00
|
|
|
# save the json file
|
2020-07-07 13:08:15 +00:00
|
|
|
import_results_form.file.data.save(abs_file_path)
|
2020-07-09 13:41:25 +00:00
|
|
|
# Create ResultFile db entry
|
|
|
|
result_file = ResultFile(result_id=result.id,
|
|
|
|
dir=dir,
|
|
|
|
filename=import_results_form.file.data.filename) # noqa
|
2020-07-07 13:08:15 +00:00
|
|
|
db.session.add(result_file)
|
|
|
|
db.session.commit()
|
2020-07-09 13:41:25 +00:00
|
|
|
# reads uploaded json file
|
|
|
|
with open(abs_file_path, 'r') as f:
|
|
|
|
corpus_metadata = json.load(f)
|
|
|
|
try:
|
|
|
|
# open json schema to validate against it
|
|
|
|
with open('app/static/json_schema/nopaque_cqi_py_results_schema.json', # noqa
|
|
|
|
'r') as s:
|
|
|
|
schema = json.load(s)
|
|
|
|
# validate if imported json is actually a json result file
|
|
|
|
validate(instance=corpus_metadata, schema=schema)
|
|
|
|
# if validated continue
|
|
|
|
# delete matches and cpos_lookup from read json file
|
|
|
|
del corpus_metadata['matches']
|
|
|
|
del corpus_metadata['cpos_lookup']
|
|
|
|
# save metadate directly as json into one field
|
|
|
|
result.corpus_metadata = corpus_metadata
|
|
|
|
flash('Result file added!', 'result')
|
|
|
|
db.session.commit()
|
|
|
|
return make_response(
|
|
|
|
{'redirect_url': url_for('results.results_overview')},
|
|
|
|
201)
|
|
|
|
except Exception as e:
|
|
|
|
# this runs if validation fails
|
|
|
|
flash('Uploaded file was not a valid result JSON!', 'result')
|
|
|
|
# deletes before created Result and ResultFile db entries
|
|
|
|
tasks.delete_result(result.id)
|
|
|
|
return make_response(
|
|
|
|
{'redirect_url': url_for('results.import_results')},
|
|
|
|
201)
|
2020-07-07 13:08:15 +00:00
|
|
|
return render_template('results/import_results.html.j2',
|
|
|
|
import_results_form=import_results_form,
|
|
|
|
title='Add corpus file')
|
|
|
|
|
|
|
|
|
|
|
|
@results.route('/')
|
|
|
|
@login_required
|
|
|
|
def results_overview():
|
|
|
|
'''
|
|
|
|
Shows an overview of imported results.
|
|
|
|
'''
|
|
|
|
# get all results of current user
|
|
|
|
results = User.query.get(current_user.id).results
|
2020-07-08 14:03:44 +00:00
|
|
|
|
2020-07-07 13:08:15 +00:00
|
|
|
def __p_time(time_str):
|
|
|
|
# helper to convert the datetime into a nice readable string
|
|
|
|
return datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S.%f')
|
2020-07-08 14:03:44 +00:00
|
|
|
|
2020-07-07 13:08:15 +00:00
|
|
|
# convert results into a list of dicts to add the measier to list.js in
|
|
|
|
# the template
|
|
|
|
results = [dict(query=r.corpus_metadata['query'],
|
|
|
|
match_count=r.corpus_metadata['match_count'],
|
|
|
|
corpus_name=r.corpus_metadata['corpus_name'],
|
|
|
|
corpus_creation_date=__p_time(r.corpus_metadata['corpus_creation_date']), # noqa
|
|
|
|
corpus_analysis_date=__p_time(r.corpus_metadata['corpus_analysis_date']), # noqa
|
|
|
|
corpus_type=r.corpus_metadata['corpus_type'],
|
2020-07-08 14:03:44 +00:00
|
|
|
file_id=r.file[0].id,
|
2020-07-07 13:08:15 +00:00
|
|
|
id=r.id)
|
|
|
|
for r in results]
|
|
|
|
return render_template('results/results.html.j2',
|
|
|
|
title='Imported Results',
|
|
|
|
# table=table,
|
|
|
|
results=results)
|
|
|
|
|
|
|
|
|
2020-07-03 12:41:57 +00:00
|
|
|
@results.route('/<int:result_id>/details')
|
|
|
|
@login_required
|
|
|
|
def result_details(result_id):
|
|
|
|
'''
|
|
|
|
View to show metadate and details about on imported result file.
|
|
|
|
'''
|
|
|
|
result = Result.query.get_or_404(result_id)
|
|
|
|
if not (result.creator == current_user or current_user.is_administrator()):
|
|
|
|
abort(403)
|
|
|
|
return render_template('results/result_details.html.j2',
|
|
|
|
result=result,
|
|
|
|
title='Result Details')
|
|
|
|
|
|
|
|
|
|
|
|
@results.route('/<int:result_id>/inspect')
|
|
|
|
@login_required
|
|
|
|
def result_inspect(result_id):
|
|
|
|
'''
|
|
|
|
View to inspect one importe result file in a corpus analysis like interface
|
|
|
|
'''
|
|
|
|
display_options_form = DisplayOptionsForm(
|
|
|
|
prefix='display-options-form',
|
|
|
|
result_context=request.args.get('context', 20),
|
|
|
|
results_per_page=request.args.get('results_per_page', 30))
|
|
|
|
result = Result.query.get_or_404(result_id)
|
|
|
|
result_file_path = os.path.join(current_app.config['NOPAQUE_STORAGE'],
|
|
|
|
result.file[0].dir,
|
|
|
|
result.file[0].filename)
|
|
|
|
with open(result_file_path, 'r') as result_json:
|
|
|
|
result_json = json.load(result_json)
|
|
|
|
if not (result.creator == current_user or current_user.is_administrator()):
|
|
|
|
abort(403)
|
|
|
|
return render_template('results/result_inspect.html.j2',
|
|
|
|
display_options_form=display_options_form,
|
|
|
|
result=result,
|
|
|
|
result_json=result_json,
|
|
|
|
title='Result Insepct')
|
2020-07-07 13:08:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
@results.route('/<int:result_id>/delete')
|
|
|
|
@login_required
|
|
|
|
def result_delete(result_id):
|
|
|
|
result = Result.query.get_or_404(result_id)
|
|
|
|
if not result.id == result_id:
|
|
|
|
abort(404)
|
|
|
|
if not (result.creator == current_user
|
|
|
|
or current_user.is_administrator()):
|
|
|
|
abort(403)
|
|
|
|
tasks.delete_result(result_id)
|
|
|
|
flash('Result deleted!')
|
|
|
|
return redirect(url_for('results.results_overview'))
|
2020-07-08 14:03:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
@results.route('/<int:result_id>/file/<int:result_file_id>/download')
|
|
|
|
@login_required
|
|
|
|
def result_download(result_id, result_file_id):
|
|
|
|
result_file = ResultFile.query.get_or_404(result_file_id)
|
|
|
|
if not result_file.result_id == result_id:
|
|
|
|
abort(404)
|
|
|
|
if not (result_file.result.creator == current_user
|
|
|
|
or current_user.is_administrator()):
|
|
|
|
abort(403)
|
|
|
|
dir = os.path.join(current_app.config['NOPAQUE_STORAGE'],
|
|
|
|
result_file.dir)
|
|
|
|
return send_from_directory(as_attachment=True,
|
|
|
|
directory=dir,
|
|
|
|
filename=result_file.filename)
|