Finished delete and data table fiew for tests

This commit is contained in:
Vivek Santayana 2021-11-25 20:12:50 +00:00
parent f68571900e
commit bf18944761
8 changed files with 303 additions and 125 deletions

View File

@ -1,6 +1,6 @@
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, DateField, SelectField from wtforms import StringField, PasswordField, BooleanField, DateField, SelectField
from wtforms.validators import InputRequired, Email, Length, EqualTo, Optional, ValidationError from wtforms.validators import InputRequired, Email, Length, EqualTo, Optional
from datetime import date, timedelta from datetime import date, timedelta
class LoginForm(FlaskForm): class LoginForm(FlaskForm):
@ -45,11 +45,12 @@ class UpdateAccountForm(FlaskForm):
password_reenter = PasswordField('Re-Enter New Password', validators=[EqualTo('password', message='Passwords do not match.')]) password_reenter = PasswordField('Re-Enter New Password', validators=[EqualTo('password', message='Passwords do not match.')])
class CreateTest(FlaskForm): class CreateTest(FlaskForm):
start_date = DateField('Start Date', format="%Y-%m-%d", validators=[InputRequired()], default = date.today() )
time_options = [ time_options = [
('none', 'None'), ('none', 'None'),
('60', '1 hour'), ('60', '1 hour'),
('90', '1 hour 30 minutes'), ('90', '1 hour 30 minutes'),
('120', '2 hours') ('120', '2 hours')
] ]
expiry = DateField('Expiry Date', format="%Y-%m-%d", validators=[InputRequired()], default = date.today() + timedelta(days=1) ) expiry_date = DateField('Expiry Date', format="%Y-%m-%d", validators=[InputRequired()], default = date.today() + timedelta(days=1) )
time_limit = SelectField('Time Limit', choices=time_options) time_limit = SelectField('Time Limit', choices=time_options)

View File

@ -2,22 +2,25 @@ import secrets
from datetime import datetime from datetime import datetime
from uuid import uuid4 from uuid import uuid4
from flask import flash, jsonify from flask import flash, jsonify
import secrets
from main import db from main import db
from security import encrypt, decrypt from security import encrypt
class Test: class Test:
def __init__(self, _id=None, expiry=None, time_limit=None, creator=None): def __init__(self, _id=None, start_date=None, expiry_date=None, time_limit=None, creator=None):
self._id = _id self._id = _id
self.expiry = expiry self.start_date = start_date
self.expiry_date = expiry_date
self.time_limit = None if time_limit == 'none' or time_limit == '' else time_limit self.time_limit = None if time_limit == 'none' or time_limit == '' else time_limit
self.creator = creator self.creator = creator
def create(self): def create(self):
test = { test = {
'_id': self._id, '_id': self._id,
'date': datetime.today(), 'date_created': datetime.today(),
'expiry': self.expiry, 'start_date': self.start_date,
'expiry_date': self.expiry_date,
'time_limit': self.time_limit, 'time_limit': self.time_limit,
'creator': encrypt(self.creator), 'creator': encrypt(self.creator),
'test_code': secrets.token_hex(6).upper() 'test_code': secrets.token_hex(6).upper()
@ -27,19 +30,66 @@ class Test:
return jsonify({'success': test}), 200 return jsonify({'success': test}), 200
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400 return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
def add_user_code(self, user_code, time_adjustment): def add_time_adjustment(self, time_adjustment):
code = { code = {
'_id': uuid4().hex, '_id': uuid4().hex,
'user_code': user_code, 'user_code': secrets.token_hex(2).upper(),
'time_adjustment': time_adjustment 'time_adjustment': time_adjustment
} }
if db.tests.find_one_and_update({'_id': self._id}, {'$push': {'time_adjustments': code}},upsert=False): if db.tests.find_one_and_update({'_id': self._id}, {'$push': {'time_adjustments': code}},upsert=False):
return jsonify({'success': code}) return jsonify({'success': code})
else: return jsonify({'error': 'Failed to add the time adjustment. An error occurred.'}), 400
return jsonify({'error': 'An error occurred.'}), 400
def remove_time_adjustment(self, _id):
if db.tests.find_one_and_update({'_id': self._id}, {'$pull': {'time_adjustments': {'_id': _id} }}):
message = 'Time adjustment has been deleted.'
flash(message, 'success')
return jsonify({'success': message})
return jsonify({'error': 'Failed to delete the time adjustment. An error occurred.'}), 400
def render_test_code(self, test_code): def render_test_code(self, test_code):
return ''.join([test_code[:4], test_code[4:8], test_code[8:]]) return ''.join([test_code[:4], test_code[4:8], test_code[8:]])
def parse_test_code(self, test_code): def parse_test_code(self, test_code):
return test_code.replace('', '') return test_code.replace('', '')
def delete(self):
if db.tests.delete_one({'_id': self._id}):
message = 'Deleted exam.'
flash(message, 'alert')
return jsonify({'success': message}), 200
return jsonify({'error': f'Could not create exam. An error occurred.'}), 400
def update(self):
test = {}
updated = []
if not self.start_date == '' and self.start_date is not None:
test['start_date'] = self.start_date
updated.append('start date')
if not self.expiry_date == '' and self.expiry_date is not None:
test['expiry_date'] = self.expiry_date
updated.append('expiry date')
if not self.time_limit == '' and self.time_limit is not None:
test['time_limit'] = self.time_limit
updated.append('time limit')
output = ''
if len(updated) == 0:
flash(f'There were no changes requested for your account.', 'alert'), 200
return jsonify({'success': 'There were no changes requested for your account.'}), 200
elif len(updated) == 1:
output = updated[0]
elif len(updated) == 2:
output = ' and '.join(updated)
elif len(updated) > 2:
output = updated[0]
for index in range(1,len(updated)):
if index < len(updated) - 2:
output = ', '.join([output, updated[index]])
elif index == len(updated) - 2:
output = ', and '.join([output, updated[index]])
else:
output = ''.join([output, updated[index]])
db.tests.find_one_and_update({'_id': self._id}, {'$set': test})
_output = f'The {output} of the test {"has" if len(updated) == 1 else "have"} been updated.'
flash(_output)
return jsonify({'success': _output}), 200

View File

@ -138,6 +138,19 @@ table.dataTable {
.user-row-actions { .user-row-actions {
text-align: center; text-align: center;
white-space: nowrap;
}
.test-row-actions {
text-align: center;
white-space: nowrap;
}
.dataTables_wrapper .dt-buttons {
left: 50%;
transform: translateX(-50%);
float:none;
text-align:center;
} }
.user-row-actions button { .user-row-actions button {
@ -197,6 +210,10 @@ table.dataTable {
z-index: -1; z-index: -1;
} }
.button-icon {
font-size: 20px;
}
/* Fallback for Edge /* Fallback for Edge
-------------------------------------------------- */ -------------------------------------------------- */
@supports (-ms-ime-align: auto) { @supports (-ms-ime-align: auto) {

View File

@ -350,12 +350,49 @@ $('form[name=form-update-account]').submit(function(event) {
event.preventDefault(); event.preventDefault();
}); });
$('.delete-test').click(function(event) {
_id = $(this).data('_id')
$.ajax({
url: `/admin/tests/delete/${_id}`,
type: 'GET',
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 + `
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
${response.responseJSON.error}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
} else if (response.responseJSON.error instanceof Array) {
for (var i = 0; i < response.responseJSON.error.length; i ++) {
alert.innerHTML = alert.innerHTML + `
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
${response.responseJSON.error[i]}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
`;
}
}
}
});
event.preventDefault();
});
// Edit and Delete Test Button Handlers
$('form[name=form-create-test]').submit(function(event) { $('form[name=form-create-test]').submit(function(event) {
var $form = $(this); var $form = $(this);
var alert = document.getElementById('alert-box'); var alert = document.getElementById('alert-box');
var data = $form.serialize(); var data = $form.serialize();
console.log(data)
alert.innerHTML = '' alert.innerHTML = ''
$.ajax({ $.ajax({
@ -364,10 +401,9 @@ $('form[name=form-create-test]').submit(function(event) {
data: data, data: data,
dataType: 'json', dataType: 'json',
success: function(response) { success: function(response) {
window.location.reload(); window.location.href = '/admin/tests/';
}, },
error: function(response) { error: function(response) {
console.log(response.responseJSON)
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) { if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
alert.innerHTML = alert.innerHTML + ` alert.innerHTML = alert.innerHTML + `
<div class="alert alert-danger alert-dismissible fade show" role="alert"> <div class="alert alert-danger alert-dismissible fade show" role="alert">
@ -396,8 +432,6 @@ $('form[name=form-create-test]').submit(function(event) {
// Dismiss Cookie Alert // Dismiss Cookie Alert
$('#dismiss-cookie-alert').click(function(event){ $('#dismiss-cookie-alert').click(function(event){
console.log('Foo')
$.ajax({ $.ajax({
url: '/cookies/', url: '/cookies/',
type: 'GET', type: 'GET',

View File

@ -0,0 +1,23 @@
<div class="navbar navbar-expand-sm navbar-light bg-light">
<div class="container-fluid">
<div class="expand navbar-expand justify-content-center" id="navbar_secondary">
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_views.tests', filter='active') }}">Active</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_views.tests', filter='scheduled') }}">Scheduled</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_views.tests', filter='expired') }}">Expired</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_views.tests', filter='all') }}">All</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_views.tests', filter='create') }}">Create</a>
</li>
</ul>
</div>
</div>
</div>

View File

@ -2,7 +2,6 @@
{% block title %} SKA Referee Test | Manage Users {% endblock %} {% block title %} SKA Referee Test | Manage Users {% endblock %}
{% block content %} {% block content %}
<h1>Manage Users</h1> <h1>Manage Users</h1>
<table id="user-table" class="table table-striped" style="width:100%"> <table id="user-table" class="table table-striped" style="width:100%">
<thead> <thead>
<tr> <tr>
@ -50,9 +49,7 @@
class="btn btn-primary" class="btn btn-primary"
title="Update User" title="Update User"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-lines-fill" viewBox="0 0 16 16"> <i class="bi bi-person-lines-fill button-icon"></i>
<path d="M6 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-5 6s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zM11 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zm.5 2.5a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1h-4zm2 3a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1h-2zm0 3a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1h-2z"/>
</svg>
</a> </a>
<a <a
href=" href="
@ -66,16 +63,13 @@
title="Delete User" title="Delete User"
{% if user._id == get_id_from_cookie() %} onclick="return false" {% endif %} {% if user._id == get_id_from_cookie() %} onclick="return false" {% endif %}
> >
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-x-fill" viewBox="0 0 16 16"> <i class="bi bi-person-x-fill button-icon"></i>
<path fill-rule="evenodd" d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm6.146-2.854a.5.5 0 0 1 .708 0L14 6.293l1.146-1.147a.5.5 0 0 1 .708.708L14.707 7l1.147 1.146a.5.5 0 0 1-.708.708L14 7.707l-1.146 1.147a.5.5 0 0 1-.708-.708L13.293 7l-1.147-1.146a.5.5 0 0 1 0-.708z"></path>
</svg>
</button> </button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<div class="form-container"> <div class="form-container">
<form name="form-create-user" class="form-signin"> <form name="form-create-user" class="form-signin">
<h2 class="form-signin-heading">Create User</h2> <h2 class="form-signin-heading">Create User</h2>
@ -100,10 +94,7 @@
<div class="row"> <div class="row">
<div class="col text-center"> <div class="col text-center">
<button title="Create User" class="btn btn-md btn-success btn-block" type="submit"> <button title="Create User" class="btn btn-md btn-success btn-block" type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-plus-fill" viewBox="0 0 20 20"> <i class="bi bi-person-plus-fill button-icon"></i>
<path d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
<path fill-rule="evenodd" d="M13.5 5a.5.5 0 0 1 .5.5V7h1.5a.5.5 0 0 1 0 1H14v1.5a.5.5 0 0 1-1 0V8h-1.5a.5.5 0 0 1 0-1H13V5.5a.5.5 0 0 1 .5-.5z"/>
</svg>
Create User Create User
</button> </button>
</div> </div>

View File

@ -2,12 +2,11 @@
{% block title %} SKA Referee Test | Manage Exams {% endblock %} {% block title %} SKA Referee Test | Manage Exams {% endblock %}
{% block content %} {% block content %}
<h1>Manage Exams</h1> <h1>Manage Exams</h1>
{% if active_tests %} {% include "admin/components/secondary-navs/tests.html" %}
<h2>{{ display_title }}</h2>
{% if tests %}
<table id="active-test-table" class="table table-striped" style="width:100%"> <table id="active-test-table" class="table table-striped" style="width:100%">
<thead> <thead>
<caption>
Active Tests
</caption>
<tr> <tr>
<th data-priority="1"> <th data-priority="1">
Start Date Start Date
@ -22,7 +21,7 @@
Time Limit Time Limit
</th> </th>
<th data-priority="4"> <th data-priority="4">
Results Entries
</th> </th>
<th data-priority="1"> <th data-priority="1">
Actions Actions
@ -30,16 +29,16 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for test in active_tests %} {% for test in tests %}
<tr class="user-table-row"> <tr class="user-table-row">
<td> <td>
{{ test.date.strftime('%d %b %Y') }} {{ test.start_date.strftime('%d %b %Y') }}
</td> </td>
<td> <td>
{{ '—'.join([test.test_code[:4], test.test_code[4:8], test.test_code[8:]]) }} {{ '—'.join([test.test_code[:4], test.test_code[4:8], test.test_code[8:]]) }}
</td> </td>
<td> <td>
{{ test.expiry }} {{ test.expiry_date.strftime('%d %b %Y') }}
</td> </td>
<td> <td>
{% if test.time_limit == None -%} {% if test.time_limit == None -%}
@ -55,61 +54,37 @@
{% endif %} {% endif %}
</td> </td>
<td> <td>
{{ test.creator }} {{ test.attempts|length }}
</td> </td>
<td class="test-row-actions"> <td class="test-row-actions">
<a <a
href="#" href="#"
class="btn btn-primary" class="btn btn-primary edit-test"
data-_id="{{test._id}}"
title="Edit Exam" title="Edit Exam"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-lines-fill" viewBox="0 0 16 16"> <i class="bi bi-file-earmark-text-fill button-icon"></i>
<path d="M6 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-5 6s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zM11 3.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5zm.5 2.5a.5.5 0 0 0 0 1h4a.5.5 0 0 0 0-1h-4zm2 3a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1h-2zm0 3a.5.5 0 0 0 0 1h2a.5.5 0 0 0 0-1h-2z"/>
</svg>
</a> </a>
<a <a
href="#" href="#"
class="btn btn-danger" class="btn btn-danger delete-test"
data-_id="{{test._id}}"
title="Delete Exam" title="Delete Exam"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-x-fill" viewBox="0 0 16 16"> <i class="bi bi-file-earmark-excel-fill button-icon"></i>
<path fill-rule="evenodd" d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm6.146-2.854a.5.5 0 0 1 .708 0L14 6.293l1.146-1.147a.5.5 0 0 1 .708.708L14.707 7l1.147 1.146a.5.5 0 0 1-.708.708L14 7.707l-1.146 1.147a.5.5 0 0 1-.708-.708L13.293 7l-1.147-1.146a.5.5 0 0 1 0-.708z"></path>
</svg>
</button> </button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% else %} {% elif not filter == 'create' %}
<div class="alert alert-primary alert-db-empty"> <div class="alert alert-primary alert-db-empty">
<i class="bi bi-info-circle-fill" aria-title="Alert" title="Alert"></i> <i class="bi bi-info-circle-fill" aria-title="Alert" title="Alert"></i>
There are no active exams. Use the form below to create an exam. {{ error_none }}
</div> </div>
{% endif %} {% endif %}
{% if form %}
{% block custom_data_script %}
<script>
$(document).ready(function() {
$('#active-test-table').DataTable({
'columnDefs': [
{'sortable': false, 'targets': [1,3,5]},
{'searchable': false, 'targets': [3,5]}
],
'order': [[0, 'desc'], [2, 'asc']],
'buttons': [
'copy', 'excel', 'pdf'
],
'responsive': 'true',
'colReorder': 'true',
'fixedHeader': 'true'
});
} );
$('#test-table').show();
$(window).trigger('resize');
</script>
{% endblock %}
<div class="form-container"> <div class="form-container">
<form name="form-create-test" class="form-signin"> <form name="form-create-test" class="form-signin">
<h2 class="form-signin-heading">Create Exam</h2> <h2 class="form-signin-heading">Create Exam</h2>
@ -131,10 +106,7 @@
<div class="row"> <div class="row">
<div class="col text-center"> <div class="col text-center">
<button title="Create Exam" class="btn btn-md btn-success btn-block" type="submit"> <button title="Create Exam" class="btn btn-md btn-success btn-block" type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-person-plus-fill" viewBox="0 0 20 20"> <i class="bi bi-file-earmark-plus-fill button-icon"></i>
<path d="M1 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
<path fill-rule="evenodd" d="M13.5 5a.5.5 0 0 1 .5.5V7h1.5a.5.5 0 0 1 0 1H14v1.5a.5.5 0 0 1-1 0V8h-1.5a.5.5 0 0 1 0-1H13V5.5a.5.5 0 0 1 .5-.5z"/>
</svg>
Create Exam Create Exam
</button> </button>
</div> </div>
@ -142,4 +114,47 @@
</div> </div>
</form> </form>
</div> </div>
{% endif %}
{% endblock %} {% endblock %}
{% if tests %}
{% block custom_data_script %}
<script>
$(document).ready(function() {
$('#active-test-table').DataTable({
'columnDefs': [
{'sortable': false, 'targets': [1,3,5]},
{'searchable': false, 'targets': [3,5]}
],
'order': [[0, 'desc'], [2, 'asc']],
dom: 'lfBrtip',
'buttons': [
{
extend: 'print',
exportOptions: {
columns: [0, 1, 2, 3]
}
},
{
extend: 'excel',
exportOptions: {
columns: [0, 1, 2, 3]
}
},
{
extend: 'pdf',
exportOptions: {
columns: [0, 1, 2, 3]
}
},
],
'responsive': 'true',
'colReorder': 'true',
'fixedHeader': 'true',
});
// $('.buttons-pdf').html('<span class="glyphicon glyphicon-file" data-toggle="tooltip" title="Export To Excel"/>') -->
} );
$('#test-table').show();
$(window).trigger('resize');
</script>
{% endblock %}
{% endif %}

View File

@ -243,27 +243,68 @@ def questions():
def upload_questions(): def upload_questions():
return render_template('/admin/settings/upload-questions.html') return render_template('/admin/settings/upload-questions.html')
@views.route('/tests/', methods=['GET','POST']) @views.route('/tests/<filter>/', methods=['GET'])
@views.route('/tests/', methods=['GET'])
@admin_account_required @admin_account_required
@login_required @login_required
def tests(): def tests(filter=''):
if filter not in ['', 'create', 'active', 'scheduled', 'expired', 'all']:
return abort(404)
if filter == 'create':
from .forms import CreateTest
form = CreateTest()
form.time_limit.default='none'
form.process()
display_title = ''
error_none = ''
return render_template('/admin/tests.html', form = form, display_title=display_title, error_none=error_none, filter=filter)
_tests = db.tests.find({})
if filter == 'active' or filter == '':
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', tests = tests, display_title=display_title, error_none=error_none, filter=filter)
@views.route('/tests/create/', methods=['POST'])
@admin_account_required
@login_required
def _tests():
from .forms import CreateTest from .forms import CreateTest
form = CreateTest() form = CreateTest()
form.time_limit.default='none' form.time_limit.default='none'
form.process() form.process()
if request.method == 'GET':
tests = decrypt_find(db.tests, {})
return render_template('/admin/tests.html', tests = tests, form = form)
if request.method == 'POST':
if form.validate_on_submit(): if form.validate_on_submit():
expiry = request.form.get('expiry') start_date = request.form.get('start_date')
if datetime.strptime(expiry, '%Y-%m-%d').date() < date.today(): start_date = datetime.strptime(start_date, '%Y-%m-%d')
return jsonify({'error': 'The expiry date cannot be in the past.'}), 400 expiry_date = request.form.get('expiry_date')
expiry_date = datetime.strptime(expiry_date, '%Y-%m-%d')
errors = []
if start_date.date() < date.today():
errors.append('The start date cannot be in the past.')
if expiry_date.date() < date.today():
errors.append('The expiry date cannot be in the past.')
if expiry_date < start_date:
errors.append('The expiry date cannot be before the start date.')
if errors:
return jsonify({'error': errors}), 400
creator_id = get_id_from_cookie() creator_id = get_id_from_cookie()
creator = decrypt_find_one(db.users, { '_id': creator_id } )['username'] creator = decrypt_find_one(db.users, { '_id': creator_id } )['username']
test = Test( test = Test(
_id = uuid4().hex, _id = uuid4().hex,
expiry = expiry, start_date = start_date,
expiry_date = expiry_date,
time_limit = request.form.get('time_limit'), time_limit = request.form.get('time_limit'),
creator = creator creator = creator
) )
@ -272,3 +313,9 @@ def tests():
else: else:
errors = [*form.expiry.errors, *form.time_limit.errors] errors = [*form.expiry.errors, *form.time_limit.errors]
return jsonify({ 'error': errors}), 400 return jsonify({ 'error': errors}), 400
@views.route('/tests/delete/<_id>/')
def delete_test(_id):
if db.tests.find_one({'_id': _id}):
return Test(_id = _id).delete()
return abort(404)