Completed admin views

Corrected model method return values
This commit is contained in:
2022-06-15 11:23:38 +01:00
parent 126bf9203c
commit a1bee61679
6 changed files with 226 additions and 43 deletions

View File

@ -1,12 +1,16 @@
from ..forms.admin import CreateUser, DeleteUser, Login, Register, ResetPassword, UpdatePassword, UpdateUser, UploadData
from ..models import Dataset, User
from ..forms.admin import AddTimeAdjustment, CreateTest, CreateUser, DeleteUser, Login, Register, ResetPassword, UpdatePassword, UpdateUser, UploadData
from ..models import Dataset, Entry, Test, User
from ..tools.auth import disable_if_logged_in, require_account_creation
from ..tools.forms import get_dataset_choices, get_time_options
from ..tools.data import check_is_json, validate_json
from ..tools.test import get_correct_answers
from flask import Blueprint, flash, jsonify, render_template, redirect, request, session
from flask.helpers import url_for
from flask import Blueprint, jsonify, render_template, redirect, request, session
from flask.helpers import flash, url_for
from flask_login import current_user, login_required
from datetime import date, datetime
from json import loads
import secrets
admin = Blueprint(
@ -21,7 +25,17 @@ admin = Blueprint(
@admin.route('/dashboard/')
@login_required
def _home():
return 'Home Page' # TODO Dashboard
tests = Test.query.all()
results = Entry.query.all()
current_tests = [ test for test in tests if test['expiry_date'].date() >= datetime.now().date() and test['start_date'].date() <= date.today() ]
current_tests.sort(key= lambda x: x['expiry_date'], reverse=True)
upcoming_tests = [ test for test in tests if test['start_date'].date() > datetime.now().date()]
upcoming_tests.sort(key= lambda x: x['start_date'])
recent_results = [result for result in results if not result['status'] == 'started' ]
recent_results.sort(key= lambda x: x['end_time'], reverse=True)
for result in recent_results:
result['percent'] = round(100*result['result']['score']/result['result']['max'])
return render_template('/admin/index.html', current_tests = current_tests, upcomimg_tests = upcoming_tests, recent_results = recent_results)
@admin.route('/settings/')
@login_required
@ -216,14 +230,159 @@ def _quesitons():
@admin.route('/settings/questions/edit/', methods=['POST'])
@login_required
def _delete_questions():
def _edit_questions():
id = request.get_json()['id']
action = request.get_json()['action']
if action not in ['defailt', 'delete']: return jsonify({'error': 'Invalid action.'}), 400
dataset = Dataset.query.filter_by(id=id).first()
if action == 'delete': success, message = dataset.delete()
elif action == 'default': success, message = dataset.make_default()
if success: return jsonify({'success': message}), 200
return jsonify({'error': message}), 400
# TODO Test views
# TODO Result views
@admin.route('/tests/<string:filter>/', methods=['GET'])
@admin.route('/tests/', methods=['GET'])
@login_required
def _tests(filter:str=None):
datasets = Dataset.query.all()
tests = None
_tests = Test.query.all()
form = None
if not datasets:
flash('There are no available question datasets. Please upload a question dataset in order to set up an exam.', 'error')
return redirect(url_for('admin._questions'))
if filter not in [None, '', 'create','active','scheduled','expired','all']: return redirect(url_for('admin._tests'))
if filter == 'create':
form = CreateTest()
form.time_limit.choices = get_time_options()
form.dataset.choices = get_dataset_choices
form.time_limit.default='none'
form.process()
display_title = ''
error_none = ''
if filter in [None, '', 'active']:
tests = [ test for test in _tests if test['expiry_date'].date() >= date.today() and test['start_date'].date() <= date.today() ]
display_title = 'Active Exams'
error_none = 'There are no exams that are currently active. You can create one using the Creat Exam form.'
if filter == 'expired':
tests = [ test for test in _tests if test['expiry_date'].date() < date.today() ]
display_title = 'Expired Exams'
error_none = 'There are no expired exams. Exams will appear in this category after their expiration date has passed.'
if filter == 'scheduled':
tests = [ test for test in _tests if test['start_date'].date() > date.today()]
display_title = 'Scheduled Exams'
error_none = 'There are no scheduled exams pending. You can schedule an exam for the future using the Create Exam form.'
if filter == 'all':
tests = _tests
display_title = 'All Exams'
error_none = 'There are no exams set up. You can create one using the Create Exam form.'
return render_template('/admin/tests.html', form = form, tests=tests, display_title=display_title, error_none=error_none, filter=filter)
@admin.route('/tests/create/', methods=['POST'])
@login_required
def _create_test():
form = CreateTest()
form.dataset.choices = get_dataset_choices()
form.time_limit.choices = get_time_options()
if form.validate_on_submit():
new_test = Test()
new_test.start_date = request.form.get('start_date')
new_test.start_date = datetime.strptime(new_test.start_date, '%Y-%m-%d')
new_test.end_date = request.form.get('expiry_date')
new_test.end_date = datetime.strptime(new_test.end_date, '%Y-%m-%d')
dataset = request.form.get('dataset')
new_test.dataset = Dataset.query.filter_by(id=dataset)
success, message = new_test.create()
if success:
flash(message=message, category='success')
return jsonify({'success': message}), 200
return jsonify({'error': message}), 400
else:
errors = [*form.start_date.errors, *form.expiry_date.errors, *form.time_limit.errors]
return jsonify({ 'error': errors}), 400
@admin.route('/tests/edit/', methods=['POST'])
@login_required
def _edit_test():
id = request.get_json()['id']
action = request.get_json()['action']
if action not in ['start', 'delete', 'end']: return jsonify({'error': 'Invalid action.'}), 400
test = Test.query.filter_by(id=id).first()
if not test: return jsonify({'error': 'Could not find the corresponding test to delete.'}), 404
if action == 'delete': success, message = test.delete()
if action == 'start': success, message = test.start()
if action == 'end': success, message = test.end()
if success:
flash(message=message, category='success')
return jsonify({'success': message}), 200
return jsonify({'error': message}), 400
@admin.route('/test/<string:id>/', methods=['GET','POST'])
@login_required
def _view_test(id:str=None):
form = AddTimeAdjustment()
test = Test.query.filter_by(id=id).first()
if request.method == 'POST':
if not test: return jsonify({'error': 'Invalid test ID.'}), 404
if form.validate_on_submit():
time = int(request.form.get('time'))
success, message = test.add_adjustment(time)
if success: return jsonify({'success': message}), 200
return jsonify({'error': message}), 400
return jsonify({'error': form.time.errors }), 400
if not test:
flash('Invalid test ID.', 'error')
return redirect(url_for('admin._tests'))
return render_template('/admin/test.html', test = test, form = form)
@admin.route('/test/<string:id>/delete-adjustment/', methods=['POST'])
@login_required
def _delete_adjustment(id:str=None):
test = Test.query.filter_by(id=id).first()
if not test: return jsonify({'error': 'Invalid test ID.'}), 404
user_code = request.get_json()['user_code'].lower()
success, message = test.remove_adjustment(user_code)
if success: return jsonify({'success': message}), 200
return jsonify({'error': message}), 400
@admin.route('/results/')
@login_required
def _view_entries():
entries = Entry.query.all()
return render_template('/admin/results.html', entries = entries)
@admin.route('/results/<string:id>/', methods = ['GET', 'POST'])
@login_required
def _view_entry(id:str=None):
entry = Entry.query.filter_by(id=id)
if request.method == 'POST':
if not entry: return jsonify({'error': 'Invalid entry ID.'}), 404
action = request.get_json()['action']
if action not in ['validate', 'delete']: return jsonify({'error': 'Invalid action.'}), 400
if action == 'validate':
success, message = entry.validate()
if action == 'delete':
success, message = entry.delete()
if success:
flash(message, 'success')
return jsonify({'success': message}), 200
return jsonify({'error': message}),400
if not entry:
flash('Invalid entry ID.', 'error')
return redirect(url_for('admin._view_entries'))
test = entry['test']
dataset = test['dataset']
dataset_path = dataset.get_file()
with open(dataset_path, 'r') as _dataset:
data = loads(_dataset.read())
correct = get_correct_answers(dataset=data)
return render_template('/admin/result-detail.html', entry = entry, correct = correct)
@admin.route('/certificate/',methods=['POST'])
@login_required
def _generate_certificate():
from main import db
id = request.get_json()['id']
entry = Entry.query.filter_by(id=id).first()
if not entry: return jsonify({'error': 'Invalid entry ID.'}), 404
return render_template('/admin/components/certificate.html', entry = entry)