diff --git a/ref-test/admin/models/tests.py b/ref-test/admin/models/tests.py index 2ba8573..6605ea8 100644 --- a/ref-test/admin/models/tests.py +++ b/ref-test/admin/models/tests.py @@ -14,7 +14,7 @@ class Test: self._id = _id self.start_date = start_date self.expiry_date = expiry_date - self.time_limit = None if time_limit == 'none' or time_limit == '' else int(time_limit) + self.time_limit = None if time_limit == 'none' or time_limit == '' or time_limit == None else int(time_limit) self.creator = creator self.dataset = dataset diff --git a/ref-test/admin/static/css/style.css b/ref-test/admin/static/css/style.css index d719dc2..6672d33 100644 --- a/ref-test/admin/static/css/style.css +++ b/ref-test/admin/static/css/style.css @@ -20,7 +20,7 @@ body { padding-bottom: 40px; } -.form-signin { +.form-display { width: 100%; max-width: 420px; padding: 15px; diff --git a/ref-test/admin/static/js/script.js b/ref-test/admin/static/js/script.js index ad4cd34..23cfe3c 100644 --- a/ref-test/admin/static/js/script.js +++ b/ref-test/admin/static/js/script.js @@ -13,392 +13,37 @@ for(let i = 0; i< dropdownItems.length; i++) { } } -// Form Processing Scripts -$('form[name=form-register]').submit(function(event) { +// General Post Method Form Processing Script +$('form.form-post').submit(function(event) { var $form = $(this); - var alert = document.getElementById('alert-box'); var data = $form.serialize(); - - alert.innerHTML = ''; + var url = $(this).attr('action'); + var rel_success = $(this).data('rel-success'); $.ajax({ - url: window.location.pathname, + url: url, type: 'POST', data: data, dataType: 'json', success: function(response) { - window.location.href = "/admin/login/"; + window.location.href = rel_success; }, error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-login]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = "/admin/dashboard/"; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-reset]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = "/admin/login/"; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-update-password]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - console.log(data) - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = "/admin/login/"; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-create-user]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.reload(); - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-delete-user]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = '/admin/settings/users/'; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-update-user]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = '/admin/settings/users'; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-update-account]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = '/admin/dashboard/'; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - - event.preventDefault(); -}); - -$('form[name=form-create-test]').submit(function(event) { - - var $form = $(this); - var alert = document.getElementById('alert-box'); - var data = $form.serialize(); - alert.innerHTML = ''; - - $.ajax({ - url: window.location.pathname, - type: 'POST', - data: data, - dataType: 'json', - success: function(response) { - window.location.href = '/admin/tests/'; - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } + error_response(response); } }); event.preventDefault(); }); +// Form Upload Questions - Special case, needs to handle files. $('form[name=form-upload-questions]').submit(function(event) { var $form = $(this); - var alert = document.getElementById('alert-box'); var data = new FormData($form[0]); var file = $('input[name=data_file]')[0].files[0] data.append('file', file) - alert.innerHTML = ''; $.ajax({ url: window.location.pathname, @@ -410,153 +55,84 @@ $('form[name=form-upload-questions]').submit(function(event) { window.location.reload(); }, error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } + error_response(response); } }); event.preventDefault(); }); - // Edit and Delete Test Button Handlers $('.delete-test').click(function(event) { - _id = $(this).data('_id') - + let _id = $(this).data('_id') $.ajax({ - url: `/admin/tests/delete/${_id}`, - type: 'GET', + url: `/admin/tests/delete/`, + type: 'POST', + data: JSON.stringify({'_id': _id}), + contentType: 'application/json', success: function(response) { window.location.href = '/admin/tests/'; }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } + error: function(response){ + error_response(response); + }, }); event.preventDefault(); }); -// Edit and Delete Dataset Button Handlers -$('.delete-question-dataset').click(function(event) { - - var alert = document.getElementById('alert-box'); - alert.innerHTML = ''; - - var filename = $(this).data('filename'); - var disabled = $(this).hasClass('disabled'); - - if ( !disabled ) { - $.ajax({ - url: `/admin/settings/questions/delete/${filename}`, - type: 'GET', - success: function(response) { - window.location.reload(); - }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } - }); - }; - event.preventDefault(); -}); - +// Edit Dataset Button Handlers $('.edit-question-dataset').click(function(event) { - var alert = document.getElementById('alert-box'); - alert.innerHTML = ''; - var filename = $(this).data('filename'); + var action = $(this).data('action'); var disabled = $(this).hasClass('disabled'); - if ( !disabled ) { + if ( !disabled ) { $.ajax({ - url: `/admin/settings/questions/default/${filename}`, - type: 'GET', + url: `/admin/settings/questions/${action}/`, + type: 'POST', + data: JSON.stringify({'filename': filename}), + contentType: 'application/json', success: function(response) { window.location.reload(); }, - error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } - } + error: function(response){ + error_response(response); + }, }); }; event.preventDefault(); }); +function error_response(response) { + + var alert = $("#alert-box"); + alert.html(''); + + if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { + alert.html(` + + `); + } else if (response.responseJSON.error instanceof Array) { + for (var i = 0; i < response.responseJSON.error.length; i ++) { + alert.html(` + + `); + } + } +} + // Dismiss Cookie Alert $('#dismiss-cookie-alert').click(function(event){ diff --git a/ref-test/admin/templates/admin/auth/account.html b/ref-test/admin/templates/admin/auth/account.html index 28ca8af..1043fc9 100644 --- a/ref-test/admin/templates/admin/auth/account.html +++ b/ref-test/admin/templates/admin/auth/account.html @@ -2,9 +2,9 @@ {% block content %}
-
+ {% include "admin/components/server-alerts.html" %} - +

Update Your Account

{{ form.hidden_tag() }}
Please confirm your current password before making any changes to your user account. diff --git a/ref-test/admin/templates/admin/auth/login.html b/ref-test/admin/templates/admin/auth/login.html index c78eb66..3572f4a 100644 --- a/ref-test/admin/templates/admin/auth/login.html +++ b/ref-test/admin/templates/admin/auth/login.html @@ -2,7 +2,7 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %}

Log In

{{ form.hidden_tag() }} diff --git a/ref-test/admin/templates/admin/auth/register.html b/ref-test/admin/templates/admin/auth/register.html index 9bdb4f5..c6fcb4e 100644 --- a/ref-test/admin/templates/admin/auth/register.html +++ b/ref-test/admin/templates/admin/auth/register.html @@ -10,9 +10,9 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %} - +

Register an Account

{{ form.hidden_tag() }}
{{ form.username(class_="form-control", autofocus=true, placeholder="Username") }} diff --git a/ref-test/admin/templates/admin/auth/reset.html b/ref-test/admin/templates/admin/auth/reset.html index 12bd644..96f3978 100644 --- a/ref-test/admin/templates/admin/auth/reset.html +++ b/ref-test/admin/templates/admin/auth/reset.html @@ -2,9 +2,9 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %} - +

Reset Password

{{ form.hidden_tag() }}
{{ form.username(class_="form-control", autofocus=true, placeholder="Enter Username") }} diff --git a/ref-test/admin/templates/admin/auth/update-password.html b/ref-test/admin/templates/admin/auth/update-password.html index 144ff31..7efc244 100644 --- a/ref-test/admin/templates/admin/auth/update-password.html +++ b/ref-test/admin/templates/admin/auth/update-password.html @@ -2,9 +2,9 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %} - +

Update Password

{{ form.hidden_tag() }}
{{ form.password(class_="form-control", placeholder="Password") }} diff --git a/ref-test/admin/templates/admin/settings/delete-user.html b/ref-test/admin/templates/admin/settings/delete-user.html index 1b56b93..ca766c7 100644 --- a/ref-test/admin/templates/admin/settings/delete-user.html +++ b/ref-test/admin/templates/admin/settings/delete-user.html @@ -2,9 +2,9 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %} - +

Delete User ‘{{ user.username }}’?

{{ form.hidden_tag() }}

This action cannot be undone. Deleting an account will mean {{ user.username }} will no longer be able to log in to the admin console.

Are you sure you want to proceed?

diff --git a/ref-test/admin/templates/admin/settings/questions.html b/ref-test/admin/templates/admin/settings/questions.html index 07e5c98..9493c8f 100644 --- a/ref-test/admin/templates/admin/settings/questions.html +++ b/ref-test/admin/templates/admin/settings/questions.html @@ -1,8 +1,8 @@ {% extends "admin/components/datatable.html" %} {% block title %} SKA Referee Test | Upload Questions {% endblock %} {% block content %} -

Manage Question Datasets

{% include "admin/components/client-alerts.html" %} +

Manage Question Datasets

{% if data %} @@ -56,14 +56,16 @@ href="#" class="btn btn-primary edit-question-dataset {% if element.filename == default %}disabled{% endif %}" data-filename="{{ element.filename }}" + data-action="default" title="Make Default" > @@ -80,8 +82,8 @@ {% endif %}
- - + +

Upload Question Dataset

{{ form.hidden_tag() }}
{{ form.data_file() }} diff --git a/ref-test/admin/templates/admin/settings/update-user.html b/ref-test/admin/templates/admin/settings/update-user.html index 0b3a6c1..06ec84a 100644 --- a/ref-test/admin/templates/admin/settings/update-user.html +++ b/ref-test/admin/templates/admin/settings/update-user.html @@ -2,9 +2,9 @@ {% block content %}
- + {% include "admin/components/server-alerts.html" %} - +

Update User ‘{{ user.username }}’

{{ form.hidden_tag() }}
{{ form.email(class_="form-control", placeholder="Email Address", value = user.email) }} diff --git a/ref-test/admin/templates/admin/settings/users.html b/ref-test/admin/templates/admin/settings/users.html index b41beb3..e770d71 100644 --- a/ref-test/admin/templates/admin/settings/users.html +++ b/ref-test/admin/templates/admin/settings/users.html @@ -71,8 +71,8 @@
- - + +

Create User

{{ form.hidden_tag() }}
{{ form.username(class_="form-control", placeholder="Enter Username") }} diff --git a/ref-test/admin/templates/admin/tests.html b/ref-test/admin/templates/admin/tests.html index d27a847..aeef8b4 100644 --- a/ref-test/admin/templates/admin/tests.html +++ b/ref-test/admin/templates/admin/tests.html @@ -43,18 +43,18 @@ {% if test.time_limit == None -%} None - {% elif test.time_limit == '60' -%} + {% elif test.time_limit == 60 -%} 1 hour - {% elif test.time_limit == '90' -%} + {% elif test.time_limit == 90 -%} 1 hour 30 min - {% elif test.time_limit == '120' -%} + {% elif test.time_limit == 120 -%} 2 hours {% else -%} {{ test.time_limit }} {% endif %} - {{ test.attempts|length }} + {{ test.entries|length }} - - + +

Create Exam

{{ form.hidden_tag() }}
{{ form.start_date(placeholder="Enter Start Date", class_ = "datepicker") }} diff --git a/ref-test/admin/views.py b/ref-test/admin/views.py index a50a126..af0cbd8 100644 --- a/ref-test/admin/views.py +++ b/ref-test/admin/views.py @@ -16,7 +16,7 @@ import secrets from main import mail from datetime import datetime, date, timedelta from .models.tests import Test -from common.data_tools import get_default_dataset, get_time_options +from common.data_tools import get_default_dataset, get_time_options, available_datasets views = Blueprint( 'admin_views', @@ -69,18 +69,6 @@ def disable_if_logged_in(function): return function(*args, **kwargs) return decorated_function -def available_datasets(): - files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json')) - default = get_default_dataset() - output = [] - for file in files: - filename = file.rsplit('/')[-1] - label = f'{filename[:-5]} (Default)' if filename == default else filename[:-5] - element = (filename, label) - output.append(element) - output.reverse() - return output - @views.route('/') @views.route('/home/') @views.route('/dashboard/') @@ -288,10 +276,11 @@ def questions(): errors = [*form.errors] return jsonify({ 'error': errors}), 400 -@views.route('/settings/questions/delete/') +@views.route('/settings/questions/delete/', methods=['POST']) @admin_account_required @login_required -def delete_questions(filename): +def delete_questions(): + filename = request.get_json()['filename'] data_files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json')) if any(filename in file for file in data_files): default = get_default_dataset() @@ -309,10 +298,11 @@ def delete_questions(filename): return jsonify({'success': f'Question dataset {filename} has been deleted.'}), 200 return abort(404) -@views.route('/settings/questions/default/') +@views.route('/settings/questions/default/', methods=['POST']) @admin_account_required @login_required -def make_default_questions(filename): +def make_default_questions(): + filename = request.get_json()['filename'] data_files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json')) default_file_path = os.path.join(app.config['DATA_FILE_DIRECTORY'], '.default.txt') if any(filename in file for file in data_files): @@ -369,7 +359,7 @@ def tests(filter=''): @views.route('/tests/create/', methods=['POST']) @admin_account_required @login_required -def _tests(): +def create_test(): from .models.forms import CreateTest form = CreateTest() form.dataset.choices = available_datasets() @@ -405,8 +395,15 @@ def _tests(): errors = [*form.expiry.errors, *form.time_limit.errors] return jsonify({ 'error': errors}), 400 -@views.route('/tests/delete/<_id>/') -def delete_test(_id): +@views.route('/tests/delete/', methods=['POST']) +def delete_test(): + _id = request.get_json()['_id'] if db.tests.find_one({'_id': _id}): return Test(_id = _id).delete() - return abort(404) \ No newline at end of file + return jsonify({'error': 'Could not find the corresponding test to delete.'}), 404 + +@views.route('/test//', methods=['GET','POST']) +def view_test(_id, filter=''): + test = db.tests.find_one({'_id':_id}) + if not test: + return abort(404) \ No newline at end of file diff --git a/ref-test/common/data_tools.py b/ref-test/common/data_tools.py index fdf2d71..8226c52 100644 --- a/ref-test/common/data_tools.py +++ b/ref-test/common/data_tools.py @@ -2,6 +2,7 @@ import os import pathlib from json import dump, loads from datetime import datetime, timedelta +from glob import glob from flask.json import jsonify from main import app @@ -24,6 +25,18 @@ def get_default_dataset(): default = default_file.read() return default +def available_datasets(): + files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json')) + default = get_default_dataset() + output = [] + for file in files: + filename = file.rsplit('/')[-1] + label = f'{filename[:-5]} (Default)' if filename == default else filename[:-5] + element = (filename, label) + output.append(element) + output.reverse() + return output + def check_json_format(file): if not '.' in file.filename: return False @@ -168,7 +181,6 @@ def evaluate_answers(dataset: dict, answers: dict): 'max': max } - def get_tags_list(dataset:dict): output = [] blocks = dataset['questions'] @@ -178,8 +190,7 @@ def get_tags_list(dataset:dict): if block['type'] == 'block': for question in block['questions']: output = list(set(output) | set(question['tags'])) - return output - + return output def get_time_options(): time_options = [ diff --git a/ref-test/quiz/static/js/quiz.js b/ref-test/quiz/static/js/quiz.js index 344d849..440c06c 100644 --- a/ref-test/quiz/static/js/quiz.js +++ b/ref-test/quiz/static/js/quiz.js @@ -28,16 +28,16 @@ $("#btn-toggle-navigator").click(function(event){ $(".navigator-text").fadeIn(); $(".review-text").fadeOut(); toggle_navigator = false; - $quiz_navigator.focus(); + $(window).scrollTop(0); } else { $quiz_navigator.fadeOut(); if (toggle_settings) { $quiz_settings.fadeIn(); - $quiz_settings.focus() + $(window).scrollTop(0); toggle_settings = false; } else { $quiz_render.fadeIn(); - $question_title.focus(); + $(window).scrollTop(0); } } event.preventDefault(); @@ -51,17 +51,17 @@ $("#btn-toggle-settings").click(function(event){ } $quiz_render.fadeOut(); $quiz_settings.fadeIn(); - $quiz_settings.focus() + $(window).scrollTop(0); toggle_settings = false; } else { $quiz_settings.fadeOut(); if (toggle_navigator) { $quiz_navigator.fadeIn(); toggle_navigator = false; - $quiz_navigator.focus(); + $(window).scrollTop(0); } else { $quiz_render.fadeIn(); - $question_title.focus(); + $(window).scrollTop(0); } } event.preventDefault(); @@ -71,7 +71,7 @@ $(".btn-quiz-return").click(function(event){ $quiz_navigator.fadeOut(); $quiz_settings.fadeOut(); $quiz_render.fadeIn(); - $question_title.focus(); + $(window).scrollTop(0); toggle_settings = false; toggle_navigator = false; event.preventDefault(); @@ -85,9 +85,10 @@ $("#navigator-container").on("click", ".q-navigator-button", function(event){ check_answered(); update_navigator(); current_question = parseInt($(this).attr("name")); + $quiz_navigator.fadeOut(); $quiz_render.fadeIn(); $question_title.focus(); - $quiz_navigator.fadeOut(); + $(window).scrollTop(0); toggle_navigator = false; toggle_settings = false; render_question(); @@ -164,25 +165,7 @@ $("#btn-start-quiz").click(function(event){ } }, error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } + error_response(response); } }); @@ -209,7 +192,7 @@ $("#q-review-answers").click(function(event){ $(".navigator-text").fadeOut(); $(".review-text").fadeIn(); toggle_navigator = false; - $quiz_navigator.focus(); + $(window).scrollTop(0); } else { $quiz_navigator.fadeOut(); if (toggle_settings) { @@ -238,25 +221,7 @@ $(".quiz-button-submit").click(function(event){ window.location.href = `/result/`; }, error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } + error_response(response); } }); @@ -392,6 +357,7 @@ function render_question() { } $question_options.html(options_output); $question_title.focus(); + $(window).scrollTop(0); } function check_answered() { diff --git a/ref-test/quiz/static/js/script.js b/ref-test/quiz/static/js/script.js index 691ecfc..09c7d0e 100644 --- a/ref-test/quiz/static/js/script.js +++ b/ref-test/quiz/static/js/script.js @@ -4,7 +4,7 @@ $(document).ready(function() { }); $('.test-code-input').keyup(function() { - var input = $(this).val().split("-").join("").split("—").join(""); // remove hyphens and mdashes + var input = $(this).val().split("-").join("").split("—").join(""); if (input.length > 0) { input = input.match(new RegExp('.{1,4}', 'g')).join("—"); } @@ -15,11 +15,8 @@ $(document).ready(function() { $('form[name=form-quiz-start]').submit(function(event) { var $form = $(this); - var alert = document.getElementById('alert-box'); var data = $form.serialize(); - alert.innerHTML = '' - $.ajax({ url: window.location.pathname, type: 'POST', @@ -31,31 +28,39 @@ $('form[name=form-quiz-start]').submit(function(event) { window.location.href = `/test/`; }, error: function(response) { - if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { - alert.innerHTML = alert.innerHTML + ` - - `; - } else if (response.responseJSON.error instanceof Array) { - for (var i = 0; i < response.responseJSON.error.length; i ++) { - alert.innerHTML = alert.innerHTML + ` - - `; - } - } + error_response(response); } }); event.preventDefault(); }); +function error_response(response) { + + var alert = $("#alert-box"); + alert.html(''); + + if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { + alert.html(` + + `); + } else if (response.responseJSON.error instanceof Array) { + for (var i = 0; i < response.responseJSON.error.length; i ++) { + alert.html(` + + `); + } + } +} + // Dismiss Cookie Alert $('#dismiss-cookie-alert').click(function(event){ diff --git a/ref-test/quiz/views.py b/ref-test/quiz/views.py index 24e789d..19bb9b4 100644 --- a/ref-test/quiz/views.py +++ b/ref-test/quiz/views.py @@ -59,10 +59,10 @@ def start(): test = db.tests.find_one({'test_code': test_code}) if not test: return jsonify({'error': 'The exam code you entered is invalid.'}), 400 - if test['expiry_date'] < datetime.utcnow(): - return jsonify({'error': f'The exam code you entered expired on {test["expiry_date"].strftime("%d %b %Y")}.'}), 400 + if test['expiry_date'] + timedelta(days=1) < datetime.utcnow(): + return jsonify({'error': f'The exam code you entered expired on {test["expiry_date"].strftime("%d %b %Y")} UTC.'}), 400 if test['start_date'] > datetime.utcnow(): - return jsonify({'error': f'The exam has not yet opened. Your exam code will be valid from {test["start_date"].strftime("%d %b %Y %H:%M")}.'}), 400 + return jsonify({'error': f'The exam has not yet opened. Your exam code will be valid from {test["start_date"].strftime("%d %b %Y %H:%M")} UTC.'}), 400 entry = { '_id': uuid4().hex, 'name': encrypt(name),