Completed admin views
Corrected model method return values
This commit is contained in:
@ -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)
|
Reference in New Issue
Block a user