Streamlined post form handlers for admin console
This commit is contained in:
parent
3f5d0feedb
commit
6a4fe535e1
@ -14,7 +14,7 @@ class Test:
|
|||||||
self._id = _id
|
self._id = _id
|
||||||
self.start_date = start_date
|
self.start_date = start_date
|
||||||
self.expiry_date = expiry_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.creator = creator
|
||||||
self.dataset = dataset
|
self.dataset = dataset
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ body {
|
|||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-signin {
|
.form-display {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
@ -13,392 +13,37 @@ for(let i = 0; i< dropdownItems.length; i++) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form Processing Scripts
|
// General Post Method Form Processing Script
|
||||||
$('form[name=form-register]').submit(function(event) {
|
$('form.form-post').submit(function(event) {
|
||||||
|
|
||||||
var $form = $(this);
|
var $form = $(this);
|
||||||
var alert = document.getElementById('alert-box');
|
|
||||||
var data = $form.serialize();
|
var data = $form.serialize();
|
||||||
|
var url = $(this).attr('action');
|
||||||
alert.innerHTML = '';
|
var rel_success = $(this).data('rel-success');
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: window.location.pathname,
|
url: url,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: data,
|
data: data,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
window.location.href = "/admin/login/";
|
window.location.href = rel_success;
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('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 + `
|
|
||||||
<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();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Form Upload Questions - Special case, needs to handle files.
|
||||||
$('form[name=form-upload-questions]').submit(function(event) {
|
$('form[name=form-upload-questions]').submit(function(event) {
|
||||||
|
|
||||||
var $form = $(this);
|
var $form = $(this);
|
||||||
var alert = document.getElementById('alert-box');
|
|
||||||
var data = new FormData($form[0]);
|
var data = new FormData($form[0]);
|
||||||
var file = $('input[name=data_file]')[0].files[0]
|
var file = $('input[name=data_file]')[0].files[0]
|
||||||
data.append('file', file)
|
data.append('file', file)
|
||||||
alert.innerHTML = '';
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: window.location.pathname,
|
url: window.location.pathname,
|
||||||
@ -410,153 +55,84 @@ $('form[name=form-upload-questions]').submit(function(event) {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Edit and Delete Test Button Handlers
|
// Edit and Delete Test Button Handlers
|
||||||
$('.delete-test').click(function(event) {
|
$('.delete-test').click(function(event) {
|
||||||
|
|
||||||
_id = $(this).data('_id')
|
let _id = $(this).data('_id')
|
||||||
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: `/admin/tests/delete/${_id}`,
|
url: `/admin/tests/delete/`,
|
||||||
type: 'GET',
|
type: 'POST',
|
||||||
|
data: JSON.stringify({'_id': _id}),
|
||||||
|
contentType: 'application/json',
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
window.location.href = '/admin/tests/';
|
window.location.href = '/admin/tests/';
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response){
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Edit and Delete Dataset Button Handlers
|
// Edit 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 + `
|
|
||||||
<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-question-dataset').click(function(event) {
|
$('.edit-question-dataset').click(function(event) {
|
||||||
|
|
||||||
var alert = document.getElementById('alert-box');
|
|
||||||
alert.innerHTML = '';
|
|
||||||
|
|
||||||
var filename = $(this).data('filename');
|
var filename = $(this).data('filename');
|
||||||
|
var action = $(this).data('action');
|
||||||
var disabled = $(this).hasClass('disabled');
|
var disabled = $(this).hasClass('disabled');
|
||||||
|
|
||||||
if ( !disabled ) {
|
if ( !disabled ) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: `/admin/settings/questions/default/${filename}`,
|
url: `/admin/settings/questions/${action}/`,
|
||||||
type: 'GET',
|
type: 'POST',
|
||||||
|
data: JSON.stringify({'filename': filename}),
|
||||||
|
contentType: 'application/json',
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response){
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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();
|
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(`
|
||||||
|
<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.html(`
|
||||||
|
<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>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dismiss Cookie Alert
|
// Dismiss Cookie Alert
|
||||||
$('#dismiss-cookie-alert').click(function(event){
|
$('#dismiss-cookie-alert').click(function(event){
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-update-account" class="form-signin">
|
<form name="form-update-account" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_views.home') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Update Your Account</h2>
|
<h2 class="form-heading">Update Your Account</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
Please confirm <strong>your current password</strong> before making any changes to your user account.
|
Please confirm <strong>your current password</strong> before making any changes to your user account.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-login" class="form-signin">
|
<form name="form-login" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_views.home') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form">Log In</h2>
|
<h2 class="form">Log In</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-register" action="" method="" class="form-signin">
|
<form name="form-register" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_auth.login') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Register an Account</h2>
|
<h2 class="form-heading">Register an Account</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
{{ form.username(class_="form-control", autofocus=true, placeholder="Username") }}
|
{{ form.username(class_="form-control", autofocus=true, placeholder="Username") }}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-reset" class="form-signin">
|
<form name="form-reset" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_auth.login') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Reset Password</h2>
|
<h2 class="form-heading">Reset Password</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
{{ form.username(class_="form-control", autofocus=true, placeholder="Enter Username") }}
|
{{ form.username(class_="form-control", autofocus=true, placeholder="Enter Username") }}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-update-password" class="form-signin">
|
<form name="form-update-password" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_auth.login') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Update Password</h2>
|
<h2 class="form-heading">Update Password</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
{{ form.password(class_="form-control", placeholder="Password") }}
|
{{ form.password(class_="form-control", placeholder="Password") }}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-delete-user" class="form-signin">
|
<form name="form-delete-user" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_views.users') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Delete User ‘{{ user.username }}’?</h2>
|
<h2 class="form-heading">Delete User ‘{{ user.username }}’?</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<p>This action cannot be undone. Deleting an account will mean {{ user.username }} will no longer be able to log in to the admin console.</p>
|
<p>This action cannot be undone. Deleting an account will mean {{ user.username }} will no longer be able to log in to the admin console.</p>
|
||||||
<p>Are you sure you want to proceed?</p>
|
<p>Are you sure you want to proceed?</p>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
{% extends "admin/components/datatable.html" %}
|
{% extends "admin/components/datatable.html" %}
|
||||||
{% block title %} SKA Referee Test | Upload Questions {% endblock %}
|
{% block title %} SKA Referee Test | Upload Questions {% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Manage Question Datasets</h1>
|
|
||||||
{% include "admin/components/client-alerts.html" %}
|
{% include "admin/components/client-alerts.html" %}
|
||||||
|
<h1>Manage Question Datasets</h1>
|
||||||
{% if data %}
|
{% if data %}
|
||||||
<table id="question-datasets-table" class="table table-striped" style="width:100%">
|
<table id="question-datasets-table" class="table table-striped" style="width:100%">
|
||||||
<thead>
|
<thead>
|
||||||
@ -56,14 +56,16 @@
|
|||||||
href="#"
|
href="#"
|
||||||
class="btn btn-primary edit-question-dataset {% if element.filename == default %}disabled{% endif %}"
|
class="btn btn-primary edit-question-dataset {% if element.filename == default %}disabled{% endif %}"
|
||||||
data-filename="{{ element.filename }}"
|
data-filename="{{ element.filename }}"
|
||||||
|
data-action="default"
|
||||||
title="Make Default"
|
title="Make Default"
|
||||||
>
|
>
|
||||||
<i class="bi bi-file-earmark-text-fill button-icon"></i>
|
<i class="bi bi-file-earmark-text-fill button-icon"></i>
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
class="btn btn-danger delete-question-dataset {% if element.filename == default %}disabled{% endif %}"
|
class="btn btn-danger edit-question-dataset {% if element.filename == default %}disabled{% endif %}"
|
||||||
data-filename="{{ element.filename }}"
|
data-filename="{{ element.filename }}"
|
||||||
|
data-action="delete"
|
||||||
title="Delete Dataset"
|
title="Delete Dataset"
|
||||||
>
|
>
|
||||||
<i class="bi bi-file-earmark-excel-fill button-icon"></i>
|
<i class="bi bi-file-earmark-excel-fill button-icon"></i>
|
||||||
@ -80,8 +82,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-upload-questions" method="post" action="#" class="form-signin" enctype="multipart/form-data">
|
<form name="form-upload-questions" class="form-display" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="" enctype="multipart/form-data">
|
||||||
<h2 class="form-signin-heading">Upload Question Dataset</h2>
|
<h2 class="form-heading">Upload Question Dataset</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-upload">
|
<div class="form-upload">
|
||||||
{{ form.data_file() }}
|
{{ form.data_file() }}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-update-user" class="form-signin">
|
<form name="form-update-user" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="{{ url_for('admin_views.users') }}">
|
||||||
{% include "admin/components/server-alerts.html" %}
|
{% include "admin/components/server-alerts.html" %}
|
||||||
<h2 class="form-signin-heading">Update User ‘{{ user.username }}’</h2>
|
<h2 class="form-heading">Update User ‘{{ user.username }}’</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
{{ form.email(class_="form-control", placeholder="Email Address", value = user.email) }}
|
{{ form.email(class_="form-control", placeholder="Email Address", value = user.email) }}
|
||||||
|
@ -71,8 +71,8 @@
|
|||||||
</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-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="">
|
||||||
<h2 class="form-signin-heading">Create User</h2>
|
<h2 class="form-heading">Create User</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-label-group">
|
<div class="form-label-group">
|
||||||
{{ form.username(class_="form-control", placeholder="Enter Username") }}
|
{{ form.username(class_="form-control", placeholder="Enter Username") }}
|
||||||
|
@ -43,18 +43,18 @@
|
|||||||
<td>
|
<td>
|
||||||
{% if test.time_limit == None -%}
|
{% if test.time_limit == None -%}
|
||||||
None
|
None
|
||||||
{% elif test.time_limit == '60' -%}
|
{% elif test.time_limit == 60 -%}
|
||||||
1 hour
|
1 hour
|
||||||
{% elif test.time_limit == '90' -%}
|
{% elif test.time_limit == 90 -%}
|
||||||
1 hour 30 min
|
1 hour 30 min
|
||||||
{% elif test.time_limit == '120' -%}
|
{% elif test.time_limit == 120 -%}
|
||||||
2 hours
|
2 hours
|
||||||
{% else -%}
|
{% else -%}
|
||||||
{{ test.time_limit }}
|
{{ test.time_limit }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ test.attempts|length }}
|
{{ test.entries|length }}
|
||||||
</td>
|
</td>
|
||||||
<td class="row-actions">
|
<td class="row-actions">
|
||||||
<a
|
<a
|
||||||
@ -86,8 +86,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if form %}
|
{% if form %}
|
||||||
<div class="form-container">
|
<div class="form-container">
|
||||||
<form name="form-create-test" class="form-signin">
|
<form name="form-create-test" class="form-display form-post" action="{{ url_for(request.endpoint, **request.view_args) }}" data-rel-success="/admin/tests/">
|
||||||
<h2 class="form-signin-heading">Create Exam</h2>
|
<h2 class="form-heading">Create Exam</h2>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<div class="form-date-input">
|
<div class="form-date-input">
|
||||||
{{ form.start_date(placeholder="Enter Start Date", class_ = "datepicker") }}
|
{{ form.start_date(placeholder="Enter Start Date", class_ = "datepicker") }}
|
||||||
|
@ -16,7 +16,7 @@ import secrets
|
|||||||
from main import mail
|
from main import mail
|
||||||
from datetime import datetime, date, timedelta
|
from datetime import datetime, date, timedelta
|
||||||
from .models.tests import Test
|
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(
|
views = Blueprint(
|
||||||
'admin_views',
|
'admin_views',
|
||||||
@ -69,18 +69,6 @@ def disable_if_logged_in(function):
|
|||||||
return function(*args, **kwargs)
|
return function(*args, **kwargs)
|
||||||
return decorated_function
|
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('/')
|
||||||
@views.route('/home/')
|
@views.route('/home/')
|
||||||
@views.route('/dashboard/')
|
@views.route('/dashboard/')
|
||||||
@ -288,10 +276,11 @@ def questions():
|
|||||||
errors = [*form.errors]
|
errors = [*form.errors]
|
||||||
return jsonify({ 'error': errors}), 400
|
return jsonify({ 'error': errors}), 400
|
||||||
|
|
||||||
@views.route('/settings/questions/delete/<filename>')
|
@views.route('/settings/questions/delete/', methods=['POST'])
|
||||||
@admin_account_required
|
@admin_account_required
|
||||||
@login_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'))
|
data_files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json'))
|
||||||
if any(filename in file for file in data_files):
|
if any(filename in file for file in data_files):
|
||||||
default = get_default_dataset()
|
default = get_default_dataset()
|
||||||
@ -309,10 +298,11 @@ def delete_questions(filename):
|
|||||||
return jsonify({'success': f'Question dataset {filename} has been deleted.'}), 200
|
return jsonify({'success': f'Question dataset {filename} has been deleted.'}), 200
|
||||||
return abort(404)
|
return abort(404)
|
||||||
|
|
||||||
@views.route('/settings/questions/default/<filename>')
|
@views.route('/settings/questions/default/', methods=['POST'])
|
||||||
@admin_account_required
|
@admin_account_required
|
||||||
@login_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'))
|
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')
|
default_file_path = os.path.join(app.config['DATA_FILE_DIRECTORY'], '.default.txt')
|
||||||
if any(filename in file for file in data_files):
|
if any(filename in file for file in data_files):
|
||||||
@ -369,7 +359,7 @@ def tests(filter=''):
|
|||||||
@views.route('/tests/create/', methods=['POST'])
|
@views.route('/tests/create/', methods=['POST'])
|
||||||
@admin_account_required
|
@admin_account_required
|
||||||
@login_required
|
@login_required
|
||||||
def _tests():
|
def create_test():
|
||||||
from .models.forms import CreateTest
|
from .models.forms import CreateTest
|
||||||
form = CreateTest()
|
form = CreateTest()
|
||||||
form.dataset.choices = available_datasets()
|
form.dataset.choices = available_datasets()
|
||||||
@ -405,8 +395,15 @@ def _tests():
|
|||||||
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>/')
|
@views.route('/tests/delete/', methods=['POST'])
|
||||||
def delete_test(_id):
|
def delete_test():
|
||||||
|
_id = request.get_json()['_id']
|
||||||
if db.tests.find_one({'_id': _id}):
|
if db.tests.find_one({'_id': _id}):
|
||||||
return Test(_id = _id).delete()
|
return Test(_id = _id).delete()
|
||||||
return abort(404)
|
return jsonify({'error': 'Could not find the corresponding test to delete.'}), 404
|
||||||
|
|
||||||
|
@views.route('/test/<id>/', methods=['GET','POST'])
|
||||||
|
def view_test(_id, filter=''):
|
||||||
|
test = db.tests.find_one({'_id':_id})
|
||||||
|
if not test:
|
||||||
|
return abort(404)
|
@ -2,6 +2,7 @@ import os
|
|||||||
import pathlib
|
import pathlib
|
||||||
from json import dump, loads
|
from json import dump, loads
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
from flask.json import jsonify
|
from flask.json import jsonify
|
||||||
from main import app
|
from main import app
|
||||||
@ -24,6 +25,18 @@ def get_default_dataset():
|
|||||||
default = default_file.read()
|
default = default_file.read()
|
||||||
return default
|
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):
|
def check_json_format(file):
|
||||||
if not '.' in file.filename:
|
if not '.' in file.filename:
|
||||||
return False
|
return False
|
||||||
@ -168,7 +181,6 @@ def evaluate_answers(dataset: dict, answers: dict):
|
|||||||
'max': max
|
'max': max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_tags_list(dataset:dict):
|
def get_tags_list(dataset:dict):
|
||||||
output = []
|
output = []
|
||||||
blocks = dataset['questions']
|
blocks = dataset['questions']
|
||||||
@ -178,8 +190,7 @@ def get_tags_list(dataset:dict):
|
|||||||
if block['type'] == 'block':
|
if block['type'] == 'block':
|
||||||
for question in block['questions']:
|
for question in block['questions']:
|
||||||
output = list(set(output) | set(question['tags']))
|
output = list(set(output) | set(question['tags']))
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def get_time_options():
|
def get_time_options():
|
||||||
time_options = [
|
time_options = [
|
||||||
|
@ -28,16 +28,16 @@ $("#btn-toggle-navigator").click(function(event){
|
|||||||
$(".navigator-text").fadeIn();
|
$(".navigator-text").fadeIn();
|
||||||
$(".review-text").fadeOut();
|
$(".review-text").fadeOut();
|
||||||
toggle_navigator = false;
|
toggle_navigator = false;
|
||||||
$quiz_navigator.focus();
|
$(window).scrollTop(0);
|
||||||
} else {
|
} else {
|
||||||
$quiz_navigator.fadeOut();
|
$quiz_navigator.fadeOut();
|
||||||
if (toggle_settings) {
|
if (toggle_settings) {
|
||||||
$quiz_settings.fadeIn();
|
$quiz_settings.fadeIn();
|
||||||
$quiz_settings.focus()
|
$(window).scrollTop(0);
|
||||||
toggle_settings = false;
|
toggle_settings = false;
|
||||||
} else {
|
} else {
|
||||||
$quiz_render.fadeIn();
|
$quiz_render.fadeIn();
|
||||||
$question_title.focus();
|
$(window).scrollTop(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -51,17 +51,17 @@ $("#btn-toggle-settings").click(function(event){
|
|||||||
}
|
}
|
||||||
$quiz_render.fadeOut();
|
$quiz_render.fadeOut();
|
||||||
$quiz_settings.fadeIn();
|
$quiz_settings.fadeIn();
|
||||||
$quiz_settings.focus()
|
$(window).scrollTop(0);
|
||||||
toggle_settings = false;
|
toggle_settings = false;
|
||||||
} else {
|
} else {
|
||||||
$quiz_settings.fadeOut();
|
$quiz_settings.fadeOut();
|
||||||
if (toggle_navigator) {
|
if (toggle_navigator) {
|
||||||
$quiz_navigator.fadeIn();
|
$quiz_navigator.fadeIn();
|
||||||
toggle_navigator = false;
|
toggle_navigator = false;
|
||||||
$quiz_navigator.focus();
|
$(window).scrollTop(0);
|
||||||
} else {
|
} else {
|
||||||
$quiz_render.fadeIn();
|
$quiz_render.fadeIn();
|
||||||
$question_title.focus();
|
$(window).scrollTop(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -71,7 +71,7 @@ $(".btn-quiz-return").click(function(event){
|
|||||||
$quiz_navigator.fadeOut();
|
$quiz_navigator.fadeOut();
|
||||||
$quiz_settings.fadeOut();
|
$quiz_settings.fadeOut();
|
||||||
$quiz_render.fadeIn();
|
$quiz_render.fadeIn();
|
||||||
$question_title.focus();
|
$(window).scrollTop(0);
|
||||||
toggle_settings = false;
|
toggle_settings = false;
|
||||||
toggle_navigator = false;
|
toggle_navigator = false;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -85,9 +85,10 @@ $("#navigator-container").on("click", ".q-navigator-button", function(event){
|
|||||||
check_answered();
|
check_answered();
|
||||||
update_navigator();
|
update_navigator();
|
||||||
current_question = parseInt($(this).attr("name"));
|
current_question = parseInt($(this).attr("name"));
|
||||||
|
$quiz_navigator.fadeOut();
|
||||||
$quiz_render.fadeIn();
|
$quiz_render.fadeIn();
|
||||||
$question_title.focus();
|
$question_title.focus();
|
||||||
$quiz_navigator.fadeOut();
|
$(window).scrollTop(0);
|
||||||
toggle_navigator = false;
|
toggle_navigator = false;
|
||||||
toggle_settings = false;
|
toggle_settings = false;
|
||||||
render_question();
|
render_question();
|
||||||
@ -164,25 +165,7 @@ $("#btn-start-quiz").click(function(event){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -209,7 +192,7 @@ $("#q-review-answers").click(function(event){
|
|||||||
$(".navigator-text").fadeOut();
|
$(".navigator-text").fadeOut();
|
||||||
$(".review-text").fadeIn();
|
$(".review-text").fadeIn();
|
||||||
toggle_navigator = false;
|
toggle_navigator = false;
|
||||||
$quiz_navigator.focus();
|
$(window).scrollTop(0);
|
||||||
} else {
|
} else {
|
||||||
$quiz_navigator.fadeOut();
|
$quiz_navigator.fadeOut();
|
||||||
if (toggle_settings) {
|
if (toggle_settings) {
|
||||||
@ -238,25 +221,7 @@ $(".quiz-button-submit").click(function(event){
|
|||||||
window.location.href = `/result/`;
|
window.location.href = `/result/`;
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -392,6 +357,7 @@ function render_question() {
|
|||||||
}
|
}
|
||||||
$question_options.html(options_output);
|
$question_options.html(options_output);
|
||||||
$question_title.focus();
|
$question_title.focus();
|
||||||
|
$(window).scrollTop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_answered() {
|
function check_answered() {
|
||||||
|
@ -4,7 +4,7 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('.test-code-input').keyup(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) {
|
if (input.length > 0) {
|
||||||
input = input.match(new RegExp('.{1,4}', 'g')).join("—");
|
input = input.match(new RegExp('.{1,4}', 'g')).join("—");
|
||||||
}
|
}
|
||||||
@ -15,11 +15,8 @@ $(document).ready(function() {
|
|||||||
$('form[name=form-quiz-start]').submit(function(event) {
|
$('form[name=form-quiz-start]').submit(function(event) {
|
||||||
|
|
||||||
var $form = $(this);
|
var $form = $(this);
|
||||||
var alert = document.getElementById('alert-box');
|
|
||||||
var data = $form.serialize();
|
var data = $form.serialize();
|
||||||
|
|
||||||
alert.innerHTML = ''
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: window.location.pathname,
|
url: window.location.pathname,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
@ -31,31 +28,39 @@ $('form[name=form-quiz-start]').submit(function(event) {
|
|||||||
window.location.href = `/test/`;
|
window.location.href = `/test/`;
|
||||||
},
|
},
|
||||||
error: function(response) {
|
error: function(response) {
|
||||||
if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
|
error_response(response);
|
||||||
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();
|
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(`
|
||||||
|
<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.html(`
|
||||||
|
<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>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dismiss Cookie Alert
|
// Dismiss Cookie Alert
|
||||||
$('#dismiss-cookie-alert').click(function(event){
|
$('#dismiss-cookie-alert').click(function(event){
|
||||||
|
|
||||||
|
@ -59,10 +59,10 @@ def start():
|
|||||||
test = db.tests.find_one({'test_code': test_code})
|
test = db.tests.find_one({'test_code': test_code})
|
||||||
if not test:
|
if not test:
|
||||||
return jsonify({'error': 'The exam code you entered is invalid.'}), 400
|
return jsonify({'error': 'The exam code you entered is invalid.'}), 400
|
||||||
if test['expiry_date'] < datetime.utcnow():
|
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")}.'}), 400
|
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():
|
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 = {
|
entry = {
|
||||||
'_id': uuid4().hex,
|
'_id': uuid4().hex,
|
||||||
'name': encrypt(name),
|
'name': encrypt(name),
|
||||||
|
Loading…
Reference in New Issue
Block a user