Merge branch 'master' of ssh://161.35.163.87:/home/django/rts

This commit is contained in:
Ross
2022-01-03 15:34:47 +00:00
6 changed files with 961 additions and 580 deletions
+2 -1
View File
@@ -3,5 +3,6 @@
"javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false,
"javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": false, "javascript.format.insertSpaceAfterKeywordsInControlFlowStatements": false,
"javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
"javascript.format.enable": false "javascript.format.enable": false,
"liveServer.settings.port": 5502
} }
+69 -15
View File
@@ -1,18 +1,67 @@
html, body, div, span, applet, object, iframe, html,
h1, h2, h3, h4, h5, h6, p, blockquote, pre, body,
a, abbr, acronym, address, big, cite, code, div,
del, dfn, em, font, img, ins, kbd, q, s, samp, span,
small, strike, strong, sub, sup, tt, var, applet,
dl, dt, dd, ol, ul, li, object,
fieldset, form, label, legend, iframe,
table, caption, tbody, tfoot, thead, tr, th, td { h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
font,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td {
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 0; border: 0;
outline: 0; outline: 0;
font-weight: inherit; font-weight: inherit;
font-style: inherit; font-style: inherit;
font-size: 100%;
font-family: inherit; font-family: inherit;
vertical-align: baseline; vertical-align: baseline;
} }
@@ -27,7 +76,8 @@ body {
background: white; background: white;
} }
ol, ul { ol,
ul {
list-style: none; list-style: none;
} }
@@ -36,17 +86,21 @@ table {
border-spacing: 0; border-spacing: 0;
} }
caption, th, td { caption,
th,
td {
text-align: left; text-align: left;
font-weight: normal; font-weight: normal;
} }
blockquote:before, blockquote:after, blockquote:before,
q:before, q:after { blockquote:after,
q:before,
q:after {
content: ""; content: "";
} }
blockquote, q { blockquote,
q {
quotes: """"; quotes: """";
} }
+110 -19
View File
@@ -17,7 +17,6 @@
appearance: none; appearance: none;
font-family: "Noto Sans", sans-serif !important; font-family: "Noto Sans", sans-serif !important;
font-weight: 400; font-weight: 400;
font-size: 1.6rem;
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
line-height: 1.5; line-height: 1.5;
} }
@@ -49,7 +48,12 @@ html {
font-size: 62.5%; font-size: 62.5%;
} }
html, body, input:not([type=text]), button, select, option { html,
body,
input:not([type=text]),
button,
select,
option {
user-select: none; user-select: none;
-moz-user-select: none; -moz-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
@@ -57,11 +61,18 @@ html, body, input:not([type=text]), button, select, option {
-o-user-select: none; -o-user-select: none;
} }
html, body, input, button, select, option, textarea { html,
body,
input,
button,
select,
option,
textarea {
vertical-align: top; vertical-align: top;
margin: 0; margin: 0;
padding: 0; padding: 0;
color: black; /*#1d3850;*/ color: black;
/*#1d3850;*/
/*font-family: 'Noto Sans', sans-serif;*/ /*font-family: 'Noto Sans', sans-serif;*/
overflow: hidden; overflow: hidden;
} }
@@ -72,7 +83,11 @@ body {
font-weight: 400; font-weight: 400;
} }
input, button, select, option, textarea { input,
button,
select,
option,
textarea {
background-color: white; background-color: white;
font-size: 100%; font-size: 100%;
padding: 0.4rem 0.8rem; padding: 0.4rem 0.8rem;
@@ -652,7 +667,8 @@ img {
opacity: 1; opacity: 1;
} }
.close:before, .close:after { .close:before,
.close:after {
position: absolute; position: absolute;
left: 15px; left: 15px;
content: ' '; content: ' ';
@@ -816,6 +832,23 @@ select option:disabled {
padding-top: 20px; padding-top: 20px;
} }
.login-button {
display: inline-block;
padding: 0.35em 1.2em;
border: 0.1em solid purple;
margin: 0 0.3em 0.3em 0;
border-radius: 0.12em;
box-sizing: border-box;
text-decoration: none;
font-family: 'Roboto', sans-serif;
font-weight: 300;
color: rgb(201, 0, 201);
text-align: center;
transition: all 0.2s;
background-color: black;
}
.packet-button { .packet-button {
display: inline-block; display: inline-block;
padding: 0.35em 1.2em; padding: 0.35em 1.2em;
@@ -901,49 +934,77 @@ select option:disabled {
-webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out; animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
} }
.sk-cube-grid .sk-cube1 { .sk-cube-grid .sk-cube1 {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; } animation-delay: 0.2s;
}
.sk-cube-grid .sk-cube2 { .sk-cube-grid .sk-cube2 {
-webkit-animation-delay: 0.3s; -webkit-animation-delay: 0.3s;
animation-delay: 0.3s; } animation-delay: 0.3s;
}
.sk-cube-grid .sk-cube3 { .sk-cube-grid .sk-cube3 {
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; } animation-delay: 0.4s;
}
.sk-cube-grid .sk-cube4 { .sk-cube-grid .sk-cube4 {
-webkit-animation-delay: 0.1s; -webkit-animation-delay: 0.1s;
animation-delay: 0.1s; } animation-delay: 0.1s;
}
.sk-cube-grid .sk-cube5 { .sk-cube-grid .sk-cube5 {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; } animation-delay: 0.2s;
}
.sk-cube-grid .sk-cube6 { .sk-cube-grid .sk-cube6 {
-webkit-animation-delay: 0.3s; -webkit-animation-delay: 0.3s;
animation-delay: 0.3s; } animation-delay: 0.3s;
}
.sk-cube-grid .sk-cube7 { .sk-cube-grid .sk-cube7 {
-webkit-animation-delay: 0s; -webkit-animation-delay: 0s;
animation-delay: 0s; } animation-delay: 0s;
}
.sk-cube-grid .sk-cube8 { .sk-cube-grid .sk-cube8 {
-webkit-animation-delay: 0.1s; -webkit-animation-delay: 0.1s;
animation-delay: 0.1s; } animation-delay: 0.1s;
}
.sk-cube-grid .sk-cube9 { .sk-cube-grid .sk-cube9 {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; } animation-delay: 0.2s;
}
@-webkit-keyframes sk-cubeGridScaleDelay { @-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
0%,
70%,
100% {
-webkit-transform: scale3D(1, 1, 1); -webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1); transform: scale3D(1, 1, 1);
} 35% { }
35% {
-webkit-transform: scale3D(0, 0, 1); -webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1);
} }
} }
@keyframes sk-cubeGridScaleDelay { @keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
0%,
70%,
100% {
-webkit-transform: scale3D(1, 1, 1); -webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1); transform: scale3D(1, 1, 1);
} 35% { }
35% {
-webkit-transform: scale3D(0, 0, 1); -webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1);
} }
@@ -1053,6 +1114,7 @@ display: block
width: 80px; width: 80px;
height: 80px; height: 80px;
} }
.lds-ripple div { .lds-ripple div {
position: absolute; position: absolute;
border: 4px solid #4527A0; border: 4px solid #4527A0;
@@ -1060,9 +1122,11 @@ display: block
border-radius: 50%; border-radius: 50%;
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
} }
.lds-ripple div:nth-child(2) { .lds-ripple div:nth-child(2) {
animation-delay: -0.5s; animation-delay: -0.5s;
} }
@keyframes lds-ripple { @keyframes lds-ripple {
0% { 0% {
top: 36px; top: 36px;
@@ -1071,6 +1135,7 @@ display: block
height: 0; height: 0;
opacity: 1; opacity: 1;
} }
100% { 100% {
top: 0px; top: 0px;
left: 0px; left: 0px;
@@ -1096,3 +1161,29 @@ display: block
.cache-out-of-date { .cache-out-of-date {
color: red; color: red;
} }
.user-text {
color: darkslateblue;
}
.inactive::before {
content: "inactive";
transform: rotate(45deg);
color: red;
font-size: 1rem;
font-weight: 900;
border: 0.25rem solid red;
display: inline-block;
/* padding: 0.25rem 1rem; */
text-transform: uppercase;
border-radius: 1rem;
font-family: 'Courier';
/* mix-blend-mode: multiply; */
opacity: 30%;
margin-left: -2em;
position: absolute;
}
.invalid-login {
color: red;
}
+25 -10
View File
@@ -19,8 +19,8 @@
<div class="nav-bar"> <div class="nav-bar">
<button id="review-button" class="navigation nav-right"><b></b></button> <button id="review-button" class="navigation nav-right"><b></b></button>
<button id="nav-submit-button" class="submit-button navigation nav-right"><b>submit</b></button> <button id="nav-submit-button" class="submit-button navigation nav-right"><b>submit</b></button>
<button id="options-button" class="navigation nav-right" <!--<button id="options-button" class="navigation nav-right"
title="click to load new packet or manage saved answers">options</button> title="click to load new packet or manage saved answers">options</button>-->
<button id="review-overlay-button" class="navigation nav-right" <button id="review-overlay-button" class="navigation nav-right"
title="click to finish exam and review answers">review</button> title="click to finish exam and review answers">review</button>
<button id="fullscreen-overlay-button" class="navigation nav-right" <button id="fullscreen-overlay-button" class="navigation nav-right"
@@ -63,9 +63,20 @@
</div> </div>
<div id="options-panel" class="fullscreen-overlay"> <div id="options-panel" class="fullscreen-overlay">
<h1>RTS</h1> <h1>RTS</h1>
<input type='button' id='btn-candidate-login' class="login-button" value='Enter candidate details'><span
id="candidate-details"></span>
<!-- <a href="#" id="overlay-close" class="close"></a> --> <!-- <a href="#" id="overlay-close" class="close"></a> -->
<div id="user" class="user-text"></div>
<div id="packets"> <div id="packets">
<p>Available Packets (click to load):</p> <p>Click buttons below to load an exam / packet</p>
<span class="exam-wrapper hidden">
<h2>Available Exams:</h2>
<span id="exam-list">
</span>
</span>
<h2>Available Packets:</h2>
<span id="packet-list"> <span id="packet-list">
</span> </span>
</div> </div>
@@ -137,7 +148,7 @@
</div> </div>
<div id="exam-candidate-number" class="dialog-text hidden"> <div id="exam-candidate-number" class="dialog-text hidden">
Check your below candidate number is correct. Check your below candidate number is correct.
<input type='number' size=10 id='candidate-number2'></input> <input type='number' size=10 id='candidate-number2' disabled></input>
</div> </div>
<button class="start-packet-button navigation dialog-yes">Start</button> <button class="start-packet-button navigation dialog-yes">Start</button>
</div> </div>
@@ -152,12 +163,13 @@
<button id="dialog-submit-button" class="submit-button navigation dialog-review hidden"><b>submit</b></button> <button id="dialog-submit-button" class="submit-button navigation dialog-review hidden"><b>submit</b></button>
</div> </div>
<div id="login-dialog" class="dialog modal"> <div id="login-dialog" class="dialog modal noclose">
<h3 class="dialog-title">Select exam</h3> <h3 class="dialog-title">Enter Details</h3>
<div class="dialog-text"> <div class="dialog-text">
Candidate number: <input type="text" id="candidate-number" name="candidate" required size="10"> Candidate number: <input type="number" id="candidate-number" name="candidate" required size="10"><br />
Passcode: <input type="text" id="passcode" name="passcode" required size="10"><br />
</div> </div>
<button id="start-exam-button" class="navigation dialog-yes">Start</button> <button id="login-button" class="navigation dialog-yes">Login</button>
</div> </div>
<div id="loading" class="fullscreen-overlay"> <div id="loading" class="fullscreen-overlay">
@@ -179,7 +191,10 @@
</div> </div>
<div id="question-loading" class="fullscreen-overlay-transparent"> <div id="question-loading" class="fullscreen-overlay-transparent">
<div class="progress-block"> <div class="progress-block">
<div class="lds-ripple"><div></div><div></div></div> <div class="lds-ripple">
<div></div>
<div></div>
</div>
</div> </div>
</div> </div>
@@ -202,7 +217,7 @@
<script src="lib/dicomParser.min.js"></script> <script src="lib/dicomParser.min.js"></script>
<script src="lib/cornerstoneMath.min.js"></script> <script src="lib/cornerstoneMath.min.js"></script>
<!-- <script src="lib/cornerstoneTools.min.js"></script> --> <!-- <script src="lib/cornerstoneTools.min.js"></script> -->
<script src="https://www.unpkg.com/cornerstone-tools@5.1.3/dist/cornerstoneTools.js"></script> <script src="https://www.unpkg.com/cornerstone-tools@5.2.0/dist/cornerstoneTools.js"></script>
<script src="lib/cornerstoneWebImageLoader.min.js"></script> <script src="lib/cornerstoneWebImageLoader.min.js"></script>
<script src="lib/cornerstoneWADOImageLoader.js"></script> <script src="lib/cornerstoneWADOImageLoader.js"></script>
<script src="lib/cornerstone-base64-image-loader.umd.js"></script> <script src="lib/cornerstone-base64-image-loader.umd.js"></script>
+12 -6
View File
@@ -8,6 +8,8 @@ export function submitAnswers(exam_details, db, config) {
.then((a) => { .then((a) => {
let json = { let json = {
eid: exam_details.eid, eid: exam_details.eid,
cid: exam_details.cid,
start_time: exam_details.start_time,
answers: JSON.stringify(a), answers: JSON.stringify(a),
}; };
postAnswers(json, config, exam_details); postAnswers(json, config, exam_details);
@@ -70,8 +72,7 @@ export function postAnswers(ans, config, exam_details) {
); );
} }
$("#options-panel").show(); $("#options-panel").show();
} else { } else {}
}
} else { } else {
alert(`${data.question_count} answers sucessfully submitted.`); alert(`${data.question_count} answers sucessfully submitted.`);
} }
@@ -146,9 +147,6 @@ export function getQuestion(url, question_number, question_total) {
dataType: "json", dataType: "json",
url: url, url: url,
progress: function(e) { progress: function(e) {
$("#progress").html(
`Downloading question [${question_number}/${question_total}]<br/>This file is compressed (no size available)`
);
if (e.lengthComputable) { if (e.lengthComputable) {
var completedPercentage = Math.round((e.loaded * 100) / e.total); var completedPercentage = Math.round((e.loaded * 100) / e.total);
@@ -157,6 +155,10 @@ export function getQuestion(url, question_number, question_total) {
e.total e.total
)}` )}`
); );
} else {
$("#progress").html(
`Downloading question [${question_number}/${question_total}]<br/>This file is compressed (downloaded ${helper.humanFileSize(e.loaded)})`
);
} }
}, },
error: (jqXHR, textStatus, errorThrown) => { error: (jqXHR, textStatus, errorThrown) => {
@@ -174,7 +176,11 @@ console.log("post", type, qid, answer, e)
return $.ajax({ return $.ajax({
type: "POST", type: "POST",
url: config.question_answer_submit_url, url: config.question_answer_submit_url,
data: JSON.stringify({ qid: `${type}/${qid}`, answer: answer, status: 2 }), data: JSON.stringify({
qid: `${type}/${qid}`,
answer: answer,
status: 2
}),
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
+333 -119
View File
@@ -9,9 +9,11 @@ let exam_details = {
aid: null, aid: null,
cid: "", cid: "",
eid: 5678, eid: 5678,
passcode: "",
exam_mode: false, exam_mode: false,
number_of_questions: null, number_of_questions: null,
question_order: [], question_order: [],
start_time: null,
}; };
let packet_list = []; let packet_list = [];
@@ -27,12 +29,17 @@ let date_started = null;
let score = 0; let score = 0;
let packet_json_id = null; let packet_json_id = null;
let global_cid = null;
let global_passcode = null;
let allow_self_marking = true; let allow_self_marking = true;
let timer = null; let timer = null;
let use_local_question_cache = false; let use_local_question_cache = false;
cornerstone.imageCache.setMaximumSizeBytes(5128800); cornerstone.imageCache.setMaximumSizeBytes(5128800);
// Set up cornerstone (the dicom viewer) // Set up cornerstone (the dicom viewer)
@@ -59,11 +66,10 @@ cornerstoneTools.init();
// Set up database // Set up database
const db = new Dexie("answers_database"); const db = new Dexie("answers_database");
db.version(1).stores({ db.version(1).stores({
answers: "[aid+cid+eid+qid+qidn], [aid+cid+eid], qid, ans", answers: "[aid+cid+eid+qid+qidn], [aid+cid+eid], qid, ans, eid",
flags: "[aid+cid+eid+qid+qidn], [aid+cid+eid], qid", flags: "[aid+cid+eid+qid+qidn], [aid+cid+eid], qid",
user_answers: "[qid+type+ans], [qid+type]", user_answers: "[qid+type+ans], [qid+type]",
session: session: "[eid+aid], eid, packet, aid, status, date, score, max_score, exam_time, time_left, question_order, questions_answered, total_questions",
"[packet+aid], packet, aid, status, date, score, max_score, exam_time, time_left, question_order, questions_answered, total_questions",
}); });
const question_db = new Dexie("question_database"); const question_db = new Dexie("question_database");
@@ -72,6 +78,11 @@ question_db.version(1).stores({
saved_exams: "&eid, type, exam_mode, name, order, time, exam_json_id", saved_exams: "&eid, type, exam_mode, name, order, time, exam_json_id",
}); });
const user_db = new Dexie("user_database");
user_db.version(1).stores({
user: "cid, passcode",
});
retrievePacketList(); retrievePacketList();
refreshDatabaseSettings(); refreshDatabaseSettings();
@@ -83,14 +94,76 @@ refreshDatabaseSettings();
* *
* if exam_query_url is defined in config.js this will be used in preference * if exam_query_url is defined in config.js this will be used in preference
*/ */
function retrievePacketList() { async function retrievePacketList() {
let url = "packets/packets.json"; let url = "packets/packets.json";
//console.log(config.exam_query_url); //console.log(config.exam_query_url);
let users = await user_db.user.toArray();
console.log(users)
if (users.length > 0) {
global_cid = users[0].cid;
global_passcode = users[0].passcode;
$(".exam-wrapper").toggle();
let logout = $("<span>[x]</span>")
logout.click(() => {
user_db.user.clear().then(() => {
window.location = window.location.pathname;
return;
});
})
if (config.exam_results_url != "" && config.exam_results_url != undefined) {
let url = `${config.exam_results_url}${global_cid}/${global_passcode}`;
$("#options-link")
.empty()
.append(
`<a href="${url}" target="_blank"><div class="packet-button">Results and answers</div></a>`
);
}
$("#candidate-details").append(`Current: CID ${global_cid} / Passcode ${global_passcode} `).append(logout);
} else {
let items = window.location.search.substr(1).split("&");
if (items.length == 2) {
let cid = "";
let passcode = "";
for (let index = 0; index < items.length; index++) {
const item = items[index];
let s = item.split("=");
if (s[0] == "cid") {
cid = s[1];
}
if (s[0] == "passcode") {
passcode = s[1];
}
};
console.log(cid, passcode)
user_db.user.add({
cid: cid,
passcode: passcode
})
location.reload();
}
}
try { try {
if (config.exam_query_url != undefined) { if (config.exam_query_url != undefined) {
if (global_cid == null) {
url = config.exam_query_url; url = config.exam_query_url;
} else {
url = `${config.exam_query_url}/${global_cid}/${global_passcode}`;
}
} }
} catch (e) { } catch (e) {
// //
@@ -107,6 +180,14 @@ function retrievePacketList() {
loadPacketList(data); loadPacketList(data);
} }
}, },
error: function(httpObj, textStatus) {
console.log(httpObj);
if (httpObj.status == 401 || httpObj.status == 404) {
$.notify("Unable to login", "error");
$("#options-panel").show();
$("#candidate-details").addClass("invalid-login");
}
},
}) })
.done(function() {}) .done(function() {})
.fail(function() { .fail(function() {
@@ -118,7 +199,7 @@ function retrievePacketList() {
} }
}).fail(function(jqXHR, textStatus, errorThrown) { }).fail(function(jqXHR, textStatus, errorThrown) {
console.log("No packet list available"); console.log("No packet list available");
showLoginDialog(); //showLoginDialog();
}); });
}) })
.always(function() {}); .always(function() {});
@@ -146,6 +227,13 @@ async function loadExamList(data) {
$("#database-error").show(); $("#database-error").show();
}); });
//Display user info if it exists
if (data.hasOwnProperty("user") && data.user) {
$("#user").append(`User: ${data.user}`);
$(".exam-wrapper").show();
}
let exams_started = []; let exams_started = [];
let exams_completed = []; let exams_completed = [];
sessions.forEach((s) => { sessions.forEach((s) => {
@@ -164,7 +252,9 @@ async function loadExamList(data) {
let exam_generated_map = {}; let exam_generated_map = {};
$("#packet-list").empty(); $("#packet-list").empty();
//exam_list.sort((a, b) => (a.name > b.name) ? 1 : -1).forEach(function (exam) { //exam_list.sort((a, b) => (a.name > b.name) ? 1 : -1).forEach(function (exam) {
exam_list.forEach(function (exam) { for (let index = 0; index < exam_list.length; index++) {
const exam = exam_list[index];
console.log(exam)
let name = exam["name"]; let name = exam["name"];
let url = exam["url"]; let url = exam["url"];
let eid = exam["eid"]; let eid = exam["eid"];
@@ -185,20 +275,29 @@ async function loadExamList(data) {
c = " session-completed"; c = " session-completed";
} }
if (!exam.exam_active) {
c = c + " inactive";
}
let target_list = "packet-list";
if (exam.exam_mode) {
target_list = "exam-list";
}
let list; let list;
if (exam.type != undefined) { if (exam.type != undefined) {
if ($(`#packet-list .${exam.type}`).length) { if ($(`.${target_list}.${exam.type}`).length) {
list = $(`#packet-list .${exam.type}`); list = $(`.${target_list}.${exam.type}`);
} else { } else {
list = $("#packet-list").append( list = $(`<div class='${target_list} ${exam.type}'><span class='packet-list-title'>${exam.type}</span><br/></div>`);
`<div class='packet-list ${exam.type}'><span class='packet-list-title'>${exam.type}</span><br/></div>` $(`#${target_list}`).append(list);
);
} }
} else { } else {
list = $("#packet-list"); list = $("#packet-list");
} }
list.append( $(list).append(
$( $(
`<div class='packet-button${c}' data-eid='${eid}' title='Load packet'></div>` `<div class='packet-button${c}' data-eid='${eid}' title='Load packet'></div>`
) )
@@ -207,17 +306,9 @@ async function loadExamList(data) {
loadPacketFromAjax(url, eid, exam_json_id); loadPacketFromAjax(url, eid, exam_json_id);
}) })
); );
});
if (config.exam_results_url != "" && config.exam_results_url != undefined) {
let url = config.exam_results_url;
$("#options-link")
.empty()
.append(
`<a href="${url}" target="_blank"><div class="packet-button">Results and answers</div></a>`
);
} }
// Check the database for exams that have been saved // Check the database for exams that have been saved
question_db.saved_exams.toArray().then((saved_exams) => { question_db.saved_exams.toArray().then((saved_exams) => {
if (saved_exams.length < 1) { if (saved_exams.length < 1) {
@@ -226,7 +317,7 @@ async function loadExamList(data) {
$("#cache-details summary").append("<span>Cached exams / questions:</span>"); $("#cache-details summary").append("<span>Cached exams / questions:</span>");
} }
console.log("Loop through saved exams"); console.log("Loop through saved exams");
saved_exams.forEach((saved_exam, n) => { saved_exams.forEach(async (saved_exam, n) => {
console.log("Check", saved_exam); console.log("Check", saved_exam);
$("#cache-details ul").append( $("#cache-details ul").append(
`<li class="cache-item" data-eid=${saved_exam.eid}>Exam: ${saved_exam.exam_name} [${saved_exam.eid}]: ${saved_exam.exam_json_id}` `<li class="cache-item" data-eid=${saved_exam.eid}>Exam: ${saved_exam.exam_name} [${saved_exam.eid}]: ${saved_exam.exam_json_id}`
@@ -240,6 +331,7 @@ async function loadExamList(data) {
if (saved_exam.exam_json_id != exam_json_id) { if (saved_exam.exam_json_id != exam_json_id) {
console.log("id mismath", saved_exam.exam_json_id, exam_json_id); console.log("id mismath", saved_exam.exam_json_id, exam_json_id);
question_db.saved_exams.where("eid").equals(saved_exam.eid).delete(); question_db.saved_exams.where("eid").equals(saved_exam.eid).delete();
db.answers.where("eid").equals(saved_exam.eid).delete();
console.log("HOL"); console.log("HOL");
$(`li.cache-item[data-eid="${saved_exam.eid}"]`) $(`li.cache-item[data-eid="${saved_exam.eid}"]`)
@@ -259,15 +351,20 @@ async function loadExamList(data) {
`<li class="cache-item" data-qid=${q}>Question (${saved_exam.exam_type}): ${q} [New JSON id: ${new_question_json_id}]` `<li class="cache-item" data-qid=${q}>Question (${saved_exam.exam_type}): ${q} [New JSON id: ${new_question_json_id}]`
); );
// If a single question is out of date we invalidate the lot... // If a single question is out of date we invalidate the lot...
const q_object = { qid: String(q), type: saved_exam.exam_type }; const q_object = {
console.log("q_object", q_object); qid: String(q),
question_db.question_data type: saved_exam.exam_type
.get(q_object) };
.then((d) => { console.log(q_object);
console.log("saved question data", d)
// d is undefined if the question is not saved let save_question_data = await question_db.question_data.get(q_object);
try {
console.log("saved question data", save_question_data, new_question_json_id)
// saved_question_data is undefined if the question is not saved
// we should really just requeue the required question for dowload... // we should really just requeue the required question for dowload...
if (d == undefined || d.data.question_json_id != new_question_json_id) { if (save_question_data == undefined || save_question_data.data.question_json_id != new_question_json_id) {
console.log(`INVALIDATE eid: ${saved_exam.eid}, q ${q}`);
$(`li.cache-item[data-eid="${saved_exam.eid}"]`).addClass( $(`li.cache-item[data-eid="${saved_exam.eid}"]`).addClass(
"cache-out-of-date" "cache-out-of-date"
); );
@@ -278,15 +375,19 @@ async function loadExamList(data) {
"out-of-date" "out-of-date"
); );
// Invalidate associated exam
question_db.saved_exams.where("eid").equals(saved_exam.eid).delete();
// Invalidate and any associated answers
db.answers.where("eid").equals(saved_exam.eid).delete();
//question_db.saved_exams.where("eid").equals(saved_exam.eid).delete(); //question_db.saved_exams.where("eid").equals(saved_exam.eid).delete();
question_db.question_data question_db.question_data
.where(["qid", "type"]) .where(["qid", "type"])
.equals([String(q), saved_exam.exam_type]) .equals([String(q), saved_exam.exam_type])
.delete(); .delete();
} }
d = null; } catch (e) {
})
.catch((e) => {
console.log("Error loading qusetion data", q_object); console.log("Error loading qusetion data", q_object);
console.log(e); console.log(e);
console.log("1234", saved_exam.eid); console.log("1234", saved_exam.eid);
@@ -306,7 +407,7 @@ async function loadExamList(data) {
.where(["qid", "type"]) .where(["qid", "type"])
.equals([String(q), saved_exam.exam_type]) .equals([String(q), saved_exam.exam_type])
.delete(); .delete();
}); }
} }
} }
}); });
@@ -315,29 +416,29 @@ async function loadExamList(data) {
// Sort different lists // Sort different lists
$(".packet-list.rapid div") $(".packet-list.rapid div")
.sort(function(a, b) { .sort(function(a, b) {
return a.dataset.eid > b.dataset.eid return a.dataset.eid > b.dataset.eid ?
? 1 1 :
: a.dataset.eid < b.dataset.eid a.dataset.eid < b.dataset.eid ?
? -1 -1 :
: 0; 0;
}) })
.appendTo(".packet-list.rapid"); .appendTo(".packet-list.rapid");
$(".packet-list.anatomy div") $(".packet-list.anatomy div")
.sort(function(a, b) { .sort(function(a, b) {
return a.dataset.eid > b.dataset.eid return a.dataset.eid > b.dataset.eid ?
? 1 1 :
: a.dataset.eid < b.dataset.eid a.dataset.eid < b.dataset.eid ?
? -1 -1 :
: 0; 0;
}) })
.appendTo(".packet-list.anatomy"); .appendTo(".packet-list.anatomy");
$(".packet-list.long div") $(".packet-list.long div")
.sort(function(a, b) { .sort(function(a, b) {
return a.dataset.eid > b.dataset.eid return a.dataset.eid > b.dataset.eid ?
? 1 1 :
: a.dataset.eid < b.dataset.eid a.dataset.eid < b.dataset.eid ?
? -1 -1 :
: 0; 0;
}) })
.appendTo(".packet-list.long"); .appendTo(".packet-list.long");
@@ -383,6 +484,12 @@ async function loadPacketList(data) {
} }
$("#packet-list").empty(); $("#packet-list").empty();
if (packet_json_id == undefined) {
$("#options-panel").show();
return
}
//console.log(packet_list)
packet_list.forEach(function(packet) { packet_list.forEach(function(packet) {
// Seperate packet types // Seperate packet types
let list; let list;
@@ -435,8 +542,7 @@ function loadPacketFromAjax(path, eid, exam_json_id) {
question_db.saved_exams question_db.saved_exams
.get(eid) .get(eid)
.then((exam) => { .then((exam) => {
if (exam == undefined || (exam["exam_json_id"] != exam_json_id)) if (exam == undefined || (exam["exam_json_id"] != exam_json_id)) {
{
console.log("AjaxRequestPacket:", eid); console.log("AjaxRequestPacket:", eid);
ajaxRequestionPacket(true); ajaxRequestionPacket(true);
} else { } else {
@@ -507,6 +613,8 @@ function setUpPacket(data, path) {
if (data.hasOwnProperty("eid")) { if (data.hasOwnProperty("eid")) {
exam_details.eid = data.eid; exam_details.eid = data.eid;
} else {
exam_details.eid = packet_name
} }
if (data.hasOwnProperty("exam_type")) { if (data.hasOwnProperty("exam_type")) {
@@ -568,7 +676,9 @@ function setUpPacket(data, path) {
if (!use_local_question_cache) { if (!use_local_question_cache) {
// Save the details to the question database // Save the details to the question database
var clone_data = Object.assign({}, data, { questions: "cached" }); var clone_data = Object.assign({}, data, {
questions: "cached"
});
console.log(clone_data) console.log(clone_data)
//clone_data["cached_questions"] = Object.keys(data["questions"]); //clone_data["cached_questions"] = Object.keys(data["questions"]);
question_db.saved_exams.put(clone_data); question_db.saved_exams.put(clone_data);
@@ -602,7 +712,10 @@ function setUpPacket(data, path) {
question_number++; question_number++;
n = String(n); n = String(n);
let obj = { qid: n, type: question_type }; let obj = {
qid: n,
type: question_type
};
let question_in_db = await question_db.question_data.get(obj); let question_in_db = await question_db.question_data.get(obj);
// If the question is in the db we can load // If the question is in the db we can load
@@ -631,8 +744,7 @@ function setUpPacket(data, path) {
if ( if (
question_json.hasOwnProperty("images_json") && question_json.hasOwnProperty("images_json") &&
question_json["images_json"] question_json["images_json"]
) { ) {}
}
//requests.push(request) //requests.push(request)
//request_numbers.push(n) //request_numbers.push(n)
@@ -669,8 +781,8 @@ function loadSession() {
db.session db.session
// .where("status") // .where("status")
// .equals("active") // .equals("active")
.where("[packet+aid]") .where("[eid+aid]")
.between([packet_name, Dexie.minKey], [packet_name, Dexie.maxKey]) .between([exam_details.eid, Dexie.minKey], [exam_details.eid, Dexie.maxKey])
.toArray() .toArray()
.then((sessions) => { .then((sessions) => {
//console.log("sessions", sessions); //console.log("sessions", sessions);
@@ -714,9 +826,15 @@ function loadSession() {
if (sessions[i].status == "active") { if (sessions[i].status == "active") {
text = text + `\r${i}: ${formatted_date} [In progress]`; text = text + `\r${i}: ${formatted_date} [In progress]`;
} else { } else {
if (!exam_details.exam_mode) {
text = text =
text + text +
`\r${i}: ${formatted_date} [Complete - score ${sessions[i].score}/${sessions[i].max_score}]`; `\r${i}: ${formatted_date} [Complete - score ${sessions[i].score}/${sessions[i].max_score}]`;
} else {
text =
text +
`\r${i}: ${formatted_date} [Complete]`;
}
} }
} }
@@ -780,8 +898,7 @@ function setUpQuestions(load_previous) {
} }
// Set an order for the questions // Set an order for the questions
if (!load_previous) { if (!load_previous) {}
}
} }
exam_details.number_of_questions = exam_details.question_order.length; exam_details.number_of_questions = exam_details.question_order.length;
review_mode = false; review_mode = false;
@@ -817,11 +934,14 @@ function setUpQuestions(load_previous) {
if (exam_details.exam_mode) { if (exam_details.exam_mode) {
// NOTE: changing the CID when restoring a session will not affect the time left // NOTE: changing the CID when restoring a session will not affect the time left
$("#candidate-number2") //$("#candidate-number2")
.val(exam_details.cid) // .val(exam_details.cid)
.change(() => { // .change(() => {
exam_details.cid = parseInt($("#candidate-number2").val()); // exam_details.cid = parseInt($("#candidate-number2").val());
}); // });
exam_details.cid = global_cid;
$("#candidate-number2").val(global_cid)
exam_details.passcode = global_passcode;
$("#start-dialog").addClass("no-close"); $("#start-dialog").addClass("no-close");
$("#start-dialog .exam-time").prop("disabled", "true"); $("#start-dialog .exam-time").prop("disabled", "true");
@@ -852,6 +972,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
const aid = exam_details.aid; const aid = exam_details.aid;
const cid = exam_details.cid; const cid = exam_details.cid;
const eid = exam_details.eid; const eid = exam_details.eid;
const passcode = exam_details.passcode;
n = parseInt(n); n = parseInt(n);
//console.log("loading question (n)", n); //console.log("loading question (n)", n);
@@ -867,7 +988,10 @@ async function loadQuestion(n, section = 1, force_reload = false) {
const qid = exam_details.question_order[n]; const qid = exam_details.question_order[n];
console.log("qid", qid) console.log("qid", qid)
let q = { qid: String(qid), type: question_type }; let q = {
qid: String(qid),
type: question_type
};
console.log(q) console.log(q)
console.log(question_db.question_data) console.log(question_db.question_data)
@@ -1064,6 +1188,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
eid: eid, eid: eid,
qid: qid, qid: qid,
qidn: "1", qidn: "1",
passcode: passcode,
ans: evt.target.value, ans: evt.target.value,
}; };
@@ -1091,6 +1216,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
eid: eid, eid: eid,
qid: qid, qid: qid,
qidn: "2", qidn: "2",
passcode: passcode,
ans: evt.target.value, ans: evt.target.value,
}; };
// db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value}); // db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value});
@@ -1110,7 +1236,14 @@ async function loadQuestion(n, section = 1, force_reload = false) {
// they have been loaded (should probably use then or after) // they have been loaded (should probably use then or after)
db.answers db.answers
.get({ aid: aid, cid: cid, eid: eid, qid: qid, qidn: "1" }) .get({
aid: aid,
cid: cid,
eid: eid,
qid: qid,
passcode: passcode,
qidn: "1"
})
.then(function(answer) { .then(function(answer) {
if (answer != undefined) { if (answer != undefined) {
$("#rapid-option option:contains(" + answer.ans + ")").prop( $("#rapid-option option:contains(" + answer.ans + ")").prop(
@@ -1130,7 +1263,14 @@ async function loadQuestion(n, section = 1, force_reload = false) {
}) })
.then( .then(
db.answers db.answers
.get({ aid: aid, cid: cid, eid: eid, qid: qid, qidn: "2" }) .get({
aid: aid,
cid: cid,
eid: eid,
qid: qid,
qidn: "2",
passcode: passcode,
})
.then(function(answer) { .then(function(answer) {
if (answer != undefined) { if (answer != undefined) {
$(".long-answer").text(answer.ans); $(".long-answer").text(answer.ans);
@@ -1177,9 +1317,9 @@ async function loadQuestion(n, section = 1, force_reload = false) {
eid: eid, eid: eid,
qid: qid, qid: qid,
qidn: "1", qidn: "1",
passcode: passcode,
ans: evt.target.value, ans: evt.target.value,
}; };
// db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value});
db.answers.put(answer); db.answers.put(answer);
$( $(
@@ -1192,7 +1332,13 @@ async function loadQuestion(n, section = 1, force_reload = false) {
}); });
db.answers db.answers
.get({ aid: aid, cid: cid, eid: eid, qid: qid, qidn: "1" }) .get({
aid: aid,
cid: cid,
eid: eid,
qid: qid,
qidn: "1"
})
.then(function(answer) { .then(function(answer) {
if (answer != undefined) { if (answer != undefined) {
$(".long-answer").text(answer.ans); $(".long-answer").text(answer.ans);
@@ -1261,13 +1407,13 @@ async function loadQuestion(n, section = 1, force_reload = false) {
).removeClass("question-saved-localdb"); ).removeClass("question-saved-localdb");
return; return;
} }
// db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value});
const answer = { const answer = {
aid: aid, aid: aid,
cid: cid, cid: cid,
eid: eid, eid: eid,
qid: qid, qid: qid,
qidn: qidn, qidn: qidn,
passcode: passcode,
ans: evt.target.value, ans: evt.target.value,
}; };
@@ -1412,7 +1558,11 @@ function rebuildQuestionListPanel() {
const eid = exam_details.eid; const eid = exam_details.eid;
db.answers db.answers
.where({ aid: aid, cid: cid, eid: eid }) .where({
aid: aid,
cid: cid,
eid: eid
})
.toArray() .toArray()
.then(function(answers) { .then(function(answers) {
// Reset all classes (of question-list-item s) // Reset all classes (of question-list-item s)
@@ -1431,7 +1581,11 @@ function rebuildQuestionListPanel() {
}); });
db.flags db.flags
.where({ aid: aid, cid: cid, eid: eid }) .where({
aid: aid,
cid: cid,
eid: eid
})
.toArray() .toArray()
.then(function(answers) { .then(function(answers) {
answers.forEach(function(answer, n) { answers.forEach(function(answer, n) {
@@ -1645,7 +1799,11 @@ function reviewQuestions() {
loadQuestion(0, 0, true); loadQuestion(0, 0, true);
db.answers db.answers
.where({ aid: aid, cid: cid, eid: eid }) .where({
aid: aid,
cid: cid,
eid: eid
})
.toArray() .toArray()
.then(function(answers) { .then(function(answers) {
let current_answers = {}; let current_answers = {};
@@ -1666,7 +1824,10 @@ function reviewQuestions() {
let overcall_number = 0; let overcall_number = 0;
let incorrectcall_number = 0; let incorrectcall_number = 0;
exam_details.question_order.forEach(async function(qid, n) { exam_details.question_order.forEach(async function(qid, n) {
const q_object = { qid: String(qid), type: question_type }; const q_object = {
qid: String(qid),
type: question_type
};
let question = await question_db.question_data.get(q_object); let question = await question_db.question_data.get(q_object);
question = question.data; question = question.data;
if (question_type == "long") { if (question_type == "long") {
@@ -1735,11 +1896,11 @@ function reviewQuestions() {
// TOOD fix // TOOD fix
$("#review-answer-table tr") $("#review-answer-table tr")
.sort(function(a, b) { .sort(function(a, b) {
return a.dataset.qid > b.dataset.qid return a.dataset.qid > b.dataset.qid ?
? 1 1 :
: a.dataset.qid < b.dataset.qid a.dataset.qid < b.dataset.qid ?
? -1 -1 :
: 0; 0;
}) })
.appendTo("#review-answer-table"); .appendTo("#review-answer-table");
return; return;
@@ -1761,8 +1922,16 @@ function reviewQuestions() {
$("#review-overlay").hide(); $("#review-overlay").hide();
}); });
console.log(db.user_answers)
console.log({
type: question_type,
qid: qid
})
db.user_answers db.user_answers
.where({ type: question_type, qid: qid }) .where({
type: question_type,
qid: qid
})
.toArray() .toArray()
.then(function(answers) { .then(function(answers) {
// Merge the question answers with the user saved answers // Merge the question answers with the user saved answers
@@ -1811,25 +1980,26 @@ function reviewQuestions() {
) { ) {
if (normal) { if (normal) {
el.html( el.html(
"<span class='" + `<span class='${c}'>Answer: ${user_answer} (Normal)</span>`
c +
"'>Answer: " +
user_answer +
" (Normal)</span>"
); );
} else { } else {
el.html( el.html(
"<span class='" + `<span class='${c}'>Answer: ${user_answer} (Abnormal: ${question_answers.join(', ')})</span>`
c +
"'>Answer: " +
user_answer +
" (Abnormal: " +
question_answers.join(", ") +
")</span>"
); );
} }
} }
function setAnatomyReviewAnswer(
el,
c,
user_answer,
question_answers
) {
el.html(
`<span class='${c}'>Answer: ${user_answer} (Correct answers: ${question_answers.join(', ')})</span>`
)
}
if (question_type == "rapid") { if (question_type == "rapid") {
// First check normal vs abnormal // First check normal vs abnormal
if (question["normal"] == true) { if (question["normal"] == true) {
@@ -1877,8 +2047,7 @@ function reviewQuestions() {
); );
questions_correct[qid] = false; questions_correct[qid] = false;
if (section_1_answer == "Not Answered") { if (section_1_answer == "Not Answered") {} else if (section_1_answer == "Normal") {
} else if (section_1_answer == "Normal") {
undercall_number++; undercall_number++;
} else { } else {
// Incorrect calls could be correct if // Incorrect calls could be correct if
@@ -1898,20 +2067,18 @@ function reviewQuestions() {
// Anatomy answers are either correct or incorrect // Anatomy answers are either correct or incorrect
if (answerInArray(question_answers, section_1_answer)) { if (answerInArray(question_answers, section_1_answer)) {
correct_count++; correct_count++;
setReviewAnswer( setAnatomyReviewAnswer(
el, el,
"correct", "correct",
section_1_answer, section_1_answer,
false,
question_answers question_answers
); );
questions_correct[qid] = true; questions_correct[qid] = true;
} else { } else {
setReviewAnswer( setAnatomyReviewAnswer(
el, el,
"incorrect", "incorrect",
section_1_answer, section_1_answer,
false,
question_answers question_answers
); );
questions_correct[qid] = false; questions_correct[qid] = false;
@@ -1949,11 +2116,11 @@ function reviewQuestions() {
$("#review-answer-list li") $("#review-answer-list li")
.sort(function(a, b) { .sort(function(a, b) {
return a.dataset.qid > b.dataset.qid return a.dataset.qid > b.dataset.qid ?
? 1 1 :
: a.dataset.qid < b.dataset.qid a.dataset.qid < b.dataset.qid ?
? -1 -1 :
: 0; 0;
}) })
.appendTo("#review-answer-list"); .appendTo("#review-answer-list");
}); });
@@ -2025,7 +2192,10 @@ function markAnswer(qid, current_question, n) {
// Load user saved answers // Load user saved answers
db.user_answers db.user_answers
.where({ type: type, qid: qid }) .where({
type: type,
qid: qid
})
.toArray() .toArray()
.then(function(saved_user_answers) { .then(function(saved_user_answers) {
// check if given answer matches a user saved answer // check if given answer matches a user saved answer
@@ -2192,7 +2362,13 @@ function addFlagEvents() {
el.toggleClass("flag flag-selected"); el.toggleClass("flag flag-selected");
const flag_db_data = { aid: aid, cid: cid, eid: eid, qid: qid, qidn: qidn }; const flag_db_data = {
aid: aid,
cid: cid,
eid: eid,
qid: qid,
qidn: qidn
};
if (el.hasClass("flag")) { if (el.hasClass("flag")) {
$("#question-list-item-" + nqid + "-" + qidn + " span").css( $("#question-list-item-" + nqid + "-" + qidn + " span").css(
@@ -2218,7 +2394,13 @@ function loadFlagsFromDb(qid, n) {
const cid = exam_details.cid; const cid = exam_details.cid;
const eid = exam_details.eid; const eid = exam_details.eid;
db.flags db.flags
.get({ aid: aid, cid: cid, eid: eid, qid: qid, qidn: n }) .get({
aid: aid,
cid: cid,
eid: eid,
qid: qid,
qidn: n
})
.then(function(answer) { .then(function(answer) {
if (answer != undefined) { if (answer != undefined) {
$("button.flag, button.flag-selected") $("button.flag, button.flag-selected")
@@ -2235,18 +2417,41 @@ function showLoginDialog() {
$("#login-dialog").modal(); $("#login-dialog").modal();
} }
$("#start-exam-button").click(function (evt) { $("#btn-candidate-login").click(function(evt) {
exam_details.cid = parseInt($("#candidate-number").val()); $("#login-dialog").modal({
escapeClose: false,
clickClose: false,
showClose: false
});
$("#options-panel").toggle();
$(".exam-wrapper").toggle();
});
$("#login-button").click(function(evt) {
global_cid = parseInt($("#candidate-number").val());
global_passcode = $("#passcode").val();
user_db.user.clear().then(() => {
user_db.user.add({
cid: global_cid,
passcode: global_passcode
})
location.reload();
});
$.modal.close(); $.modal.close();
}); });
$(".start-packet-button").click(function(evt) { $(".start-packet-button").click(function(evt) {
if (exam_details.exam_mode) { // No longer needed as candidates log in...
if (!Number.isInteger(parseInt($("#candidate-number2").val()))) { //if (exam_details.exam_mode) {
alert("Please enter a valid candidate number."); // if (!Number.isInteger(parseInt($("#candidate-number2").val()))) {
return; // alert("Please enter a valid candidate number.");
} // return;
} // }
//}
exam_details.start_time = new Date().getTime() / 1000;
if (timer != null) { if (timer != null) {
timer.stop(); timer.stop();
@@ -2255,7 +2460,12 @@ $(".start-packet-button").click(function (evt) {
timer = new easytimer.Timer(); timer = new easytimer.Timer();
//exam_time = 2; //exam_time = 2;
timer.start({ countdown: true, startValues: { seconds: exam_time } }); timer.start({
countdown: true,
startValues: {
seconds: exam_time
}
});
timer.addEventListener("secondsUpdated", function(e) { timer.addEventListener("secondsUpdated", function(e) {
$("#timer").html("Time left: " + timer.getTimeValues().toString()); $("#timer").html("Time left: " + timer.getTimeValues().toString());
}); });
@@ -2338,8 +2548,7 @@ $("#btn-delete-answer-databases").click(function (evt) {
.finally(() => { .finally(() => {
// Do what should be done next... // Do what should be done next...
}); });
} else { } else {}
}
}); });
$("#btn-delete-cached-questions").click(function(evt) { $("#btn-delete-cached-questions").click(function(evt) {
var r = confirm("Delete cached questions?"); var r = confirm("Delete cached questions?");
@@ -2361,8 +2570,7 @@ $("#btn-delete-cached-questions").click(function (evt) {
.finally(() => { .finally(() => {
// Do what should be done next... // Do what should be done next...
}); });
} else { } else {}
}
}); });
$("#btn-delete-current").click(function(evt) { $("#btn-delete-current").click(function(evt) {
@@ -2450,8 +2658,10 @@ function saveSession(start_review) {
time_values.seconds; time_values.seconds;
db.session.put({ db.session.put({
packet: packet_name, packet: packet_name,
eid: exam_details.eid,
aid: exam_details.aid, aid: exam_details.aid,
cid: exam_details.cid, cid: exam_details.cid,
passcode: exam_details.passcode,
status: status, status: status,
date: date_started, date: date_started,
score: score, score: score,
@@ -2485,6 +2695,10 @@ $(document).on("saveSessionEvent", {}, (evt, review) => {
saveSession(review); saveSession(review);
}); });
$(document).contextmenu(() => {
return false;
})
// Helper to compare dates // Helper to compare dates
function compareDates(d1, d2) { function compareDates(d1, d2) {
console.log("compare", d1, d2); console.log("compare", d1, d2);