small fixes

This commit is contained in:
Ross
2024-12-30 11:31:05 +00:00
parent 2f6e3a8701
commit 7ebba5cdb2
7 changed files with 333 additions and 203 deletions
+1
View File
@@ -1,3 +1,4 @@
/* Set some default CSS */
html, html,
body, body,
div, div,
+1 -1
View File
@@ -1,4 +1,4 @@
/* Some fancy loading CSS */
.sk-cube-grid { .sk-cube-grid {
width: 60px; width: 60px;
height: 60px; height: 60px;
+1 -1
View File
@@ -2,7 +2,7 @@
@import "./base.css"; @import "./base.css";
@import "./loading.css"; @import "./loading.css";
@import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700"); @import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700");
/* Colourscheme from https://www.materialui.co/colors */ /* Colourscheme from https://www.materialui.co/colors (as per original) */
* { * {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
+270 -183
View File
@@ -1,210 +1,299 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" class="no-touch" lang="en"> <html
xmlns="http://www.w3.org/1999/xhtml"
<head> xml:lang="en"
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> class="no-touch"
<meta charset="UTF-8"> lang="en"
<meta name="viewport" >
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"> <head>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, width=device-width, height=device-height"> <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link type="text/css" rel="stylesheet" href="lib/jquery.modal.min.css"> <meta charset="UTF-8" />
<link type="text/css" rel="stylesheet" href="lib/cornerstone.min.css"> <meta
<link type="text/css" rel="stylesheet" href="css/main.css"> name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"
/>
<meta
name="viewport"
content="initial-scale=1.0, maximum-scale=1.0, width=device-width, height=device-height"
/>
<link type="text/css" rel="stylesheet" href="lib/jquery.modal.min.css" />
<link type="text/css" rel="stylesheet" href="lib/cornerstone.min.css" />
<link type="text/css" rel="stylesheet" href="css/main.css" />
<title>RTS</title> <title>RTS</title>
</head> </head>
<body> <body>
<div id="content"> <div id="content">
<div class="content-panel"> <div class="content-panel">
<div class="nav-bar"> <div class="nav-bar">
<button id="btn-review" class="navigation nav-right"><b></b></button> <button id="btn-review" class="navigation nav-right"><b></b></button>
<button id="btn-submit-nav" class="submit-button navigation nav-right"><b>submit</b></button> <button
<button id="btn-review-overlay" class="navigation nav-right" id="btn-submit-nav"
title="click to finish exam and review answers">review</button> class="submit-button navigation nav-right"
<button id="btn-fullscreen-overlay" class="navigation nav-right" >
title="click to toggle fullscreen">fullscreen</button> <b>submit</b>
<div class="app-name nav-left">RTS</div> </button>
<div id="timer" title="click to pause"></div> <button
<div class="exam-name" title="currently loaded packet"></div> id="btn-review-overlay"
<input type="button" class="navigation nav-left" value="previous" disabled="disabled"> class="navigation nav-right"
<input type="button" class="navigation nav-left" value="next"> title="click to finish exam and review answers"
</div> >
<div class="main-panel"> review
<div class="question-list-panel" style="display: block;"> </button>
</div> <button
<div class="exam-panel"> id="btn-fullscreen-overlay"
<div class="exam-content-panel"> class="navigation nav-right"
<div class="question"> title="click to toggle fullscreen"
<div class="title"><span style="font-weight:700;">1</span> </div> >
<div class="stem"> fullscreen
<div id="thumbnails"></div> </button>
</div> <div class="app-name nav-left">RTS</div>
<div class="thumbs"> <div id="timer" title="click to pause"></div>
</div> <div class="exam-name" title="currently loaded packet"></div>
</div> <input
<div class="answers"> type="button"
<div class="answer-title">Answer</div> class="navigation nav-left"
<div class="answer-panel"> value="previous"
</div> disabled="disabled"
</div> />
</div> <input type="button" class="navigation nav-left" value="next" />
</div>
</div>
<div class="logout-background">
<div class="logout-panel">
<div class="logout-title">Ready to logout?</div>
<div class="logout-text"></div>
<button class="navigation logout-cancel">continue exam</button>
<button class="navigation logout-okay">logout now</button>
</div>
</div>
<div id="options-panel" class="fullscreen-overlay">
<h1>RTS</h1>
<input type='button' id='btn-candidate-login' class="login-button" value='Enter candidate details' onclick='void(0)' ><span
id="candidate-details"></span>
<input type='button' id='btn-user-login' class="login-button" value='User log in'>
<!-- <a href="#" id="overlay-close" class="close"></a> -->
<div id="user" class="user-text"></div>
<div id="packets">
<p>Click buttons below to load an exam / packet</p>
<span class="exam-wrapper">
<h2>Exams:</h2>
<span id="exam-list"></span>
</span>
<span class="packet-wrapper">
<h2>Packets:</h2>
<span id="packet-list"></span>
</span>
</div>
<div id="options-link">
</div>
<div id="storage-details">
</div>
<div id="cache-details">
<details>
<summary></summary>
<ul>
</ul>
</details>
</div>
<details>
<summary>Options</summary>
<div id="database-buttons">
<input type='button' id='btn-delete-answer-databases' value='Delete local answers'>
<input type='button' id='btn-delete-cached-questions' value='Delete cached questions'>
<input type='button' id='btn-reset-local' value='Clear all local data'>
</div>
<div id="local-fileloader">
<form id="jsonFile" name="jsonFile" enctype="multipart/form-data" method="post">
<fieldset>
<h2>Load local question set</h2>
<input type='file' id='fileinput'>
<input type='button' id='btn-local-file-load' value='Load'>
</fieldset>
</form>
</div>
<p><button id='btn-view-local-answers'>View local saved answers</button></p>
</details>
</div>
<div id="review-overlay" class="fullscreen-overlay">
<a href="#" id="review-overlay-close" class="close"></a>
<div id="review-score"></div>
<div id="exam-stats">
<p>Performance breakdown:</p>
Unanswered questions: <span id="unanswered-number"></span><br />
Answered normal: <span id="normal-number"></span><br />
Answered abnormal: <span id="abnormal-number"></span><br />
<br />
Undercall: <span id="undercall-number"></span><br />
Overcall: <span id="overcall-number"></span><br />
Incorrect call: <span id="incorrectcall-number"></span><br />
</div>
<ul id='review-answer-list'></ul>
<table id='review-answer-table'></table>
</div>
</div> </div>
<div class="main-panel">
<div class="question-list-panel" style="display: block"></div>
<div class="exam-panel">
<div class="exam-content-panel">
<div class="question">
<div class="title"><span style="font-weight: 700">1</span></div>
<div class="stem">
<div id="thumbnails"></div>
</div>
<div class="thumbs"></div>
</div>
<div class="answers">
<div class="answer-title">Answer</div>
<div class="answer-panel"></div>
</div>
</div>
</div>
</div>
<div class="logout-background">
<div class="logout-panel">
<div class="logout-title">Ready to logout?</div>
<div class="logout-text"></div>
<button class="navigation logout-cancel">continue exam</button>
<button class="navigation logout-okay">logout now</button>
</div>
</div>
<div id="options-panel" class="fullscreen-overlay">
<h1>RTS</h1>
<span id="user-details">
<input
type="button"
id="btn-candidate-login"
class="login-button"
value="Enter candidate details"
onclick="void(0)"
/><span id="candidate-details"></span>
<input
type="button"
id="btn-user-login"
class="login-button"
value="User log in"
/>
<!-- <a href="#" id="overlay-close" class="close"></a> -->
<div id="user" class="user-text"></div>
</span>
<div id="packets">
<p>Click buttons below to load an exam / packet</p>
<span class="exam-wrapper">
<h2>Exams:</h2>
<span id="exam-list"></span>
</span>
<span class="packet-wrapper">
<h2>Packets:</h2>
<span id="packet-list"></span>
</span>
</div>
<div id="options-link"></div>
<div id="storage-details"></div>
<div id="cache-details">
<details>
<summary></summary>
<ul></ul>
</details>
</div>
<details>
<summary>Options</summary>
<div id="database-buttons">
<input
type="button"
id="btn-delete-answer-databases"
value="Delete local answers"
/>
<input
type="button"
id="btn-delete-cached-questions"
value="Delete cached questions"
/>
<input
type="button"
id="btn-reset-local"
value="Clear all local data"
/>
</div>
<div id="local-fileloader">
<form
id="jsonFile"
name="jsonFile"
enctype="multipart/form-data"
method="post"
>
<fieldset>
<h2>Load local question set</h2>
<input type="file" id="fileinput" />
<input type="button" id="btn-local-file-load" value="Load" />
</fieldset>
</form>
</div>
<p>
<button id="btn-view-local-answers">
View local saved answers
</button>
</p>
</details>
</div>
<div id="review-overlay" class="fullscreen-overlay">
<a href="#" id="review-overlay-close" class="close"></a>
<div id="review-score"></div>
<div id="exam-stats">
<p>Performance breakdown:</p>
Unanswered questions: <span id="unanswered-number"></span><br />
Answered normal: <span id="normal-number"></span><br />
Answered abnormal: <span id="abnormal-number"></span><br />
<br />
Undercall: <span id="undercall-number"></span><br />
Overcall: <span id="overcall-number"></span><br />
Incorrect call: <span id="incorrectcall-number"></span><br />
</div>
<ul id="review-answer-list"></ul>
<table id="review-answer-table"></table>
</div>
</div>
</div> </div>
<div id="finish-dialog" class="dialog modal"> <div id="finish-dialog" class="dialog modal">
<h3 class="dialog-title">Finish exam and review?</h3> <h3 class="dialog-title">Finish exam and review?</h3>
<div class="dialog-text"> <div class="dialog-text">
<button id="finish-exam" class="navigation dialog-yes">Finish and review</button> <button id="finish-exam" class="navigation dialog-yes">
<button id="finish-cancel" class="navigation dialog-cancel">Continue exam</button> Finish and review
</div> </button>
<button id="finish-cancel" class="navigation dialog-cancel">
Continue exam
</button>
</div>
</div> </div>
<div id="start-dialog" class="dialog modal"> <div id="start-dialog" class="dialog modal">
<h3 class="dialog-title">Start <span class="exam-name"></span></h3> <h3 class="dialog-title">Start <span class="exam-name"></span></h3>
<div class="packet-database-options"> <div class="packet-database-options">
<input type='button' id='btn-delete-current' value='Reset current packet answers'><br /> <input
<input type='button' id='btn-delete-current-saved-answers' value='Reset current packet saved answers'> type="button"
</div> id="btn-delete-current"
<div class="dialog-text"> value="Reset current packet answers"
Click to start exam. /><br />
<p>You will have <input type='number' size=2 class='exam-time'></input> minutes.</p> <input
</div> type="button"
<div id="exam-candidate-number" class="dialog-text hidden"> id="btn-delete-current-saved-answers"
Check your below candidate number / user is correct. value="Reset current packet saved answers"
<input type='text' size=10 id='candidate-number2' disabled></input> />
</div> </div>
<button class="start-packet-button navigation dialog-yes">Start</button> <div class="dialog-text">
Click to start exam.
<p>
You will have
<input type="number" size="2" class="exam-time" /> minutes.
</p>
</div>
<div id="exam-candidate-number" class="dialog-text hidden">
Check your below candidate number / user is correct.
<input type="text" size="10" id="candidate-number2" disabled />
</div>
<button class="start-packet-button navigation dialog-yes">Start</button>
</div> </div>
<div id="time-up-dialog" class="dialog modal"> <div id="time-up-dialog" class="dialog modal">
<h3 class="dialog-title">Time ended</h3> <h3 class="dialog-title">Time ended</h3>
<div class="dialog-text"> <div class="dialog-text">
Allocated time has ended. You can review or continue. Allocated time has ended. You can review or continue.
</div> </div>
<button id="btn-time-up-review" class="navigation dialog-review">Review</button> <button id="btn-time-up-review" class="navigation dialog-review">
<button id="time-up-continue-button" class="navigation dialog-yes">Continue</button> Review
<button id="dialog-submit-button" class="submit-button navigation dialog-review hidden"><b>submit</b></button> </button>
<button id="time-up-continue-button" class="navigation dialog-yes">
Continue
</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 noclose"> <div id="login-dialog" class="dialog modal noclose">
<h3 class="dialog-title">Enter Details</h3> <h3 class="dialog-title">Enter Details</h3>
<div class="dialog-text"> <div class="dialog-text">
Candidate number: <input type="number" id="candidate-number" name="candidate" required size="10"><br /> Candidate number:
Passcode: <input type="text" id="passcode" name="passcode" required size="10"><br /> <input
</div> type="number"
<button id="btn-login" class="navigation dialog-yes">Login</button> id="candidate-number"
name="candidate"
required
size="10"
/><br />
Passcode:
<input
type="text"
id="passcode"
name="passcode"
required
size="10"
/><br />
</div>
<button id="btn-login" class="navigation dialog-yes">Login</button>
</div> </div>
<div id="loading" class="fullscreen-overlay"> <div id="loading" class="fullscreen-overlay">
<div class="progress-block"> <div class="progress-block">
<div id="progress"> <div id="progress"></div>
</div> <div class="sk-cube-grid full">
<div class="sk-cube-grid full"> <div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube1"></div> <div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube2"></div> <div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube3"></div> <div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube4"></div> <div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube5"></div> <div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube6"></div> <div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube7"></div> <div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube8"></div> <div class="sk-cube sk-cube9"></div>
<div class="sk-cube sk-cube9"></div>
</div>
</div> </div>
</div>
</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 class="lds-ripple">
<div></div> <div></div>
<div></div> <div></div>
</div>
</div> </div>
</div>
</div> </div>
<div id="pause" class="fullscreen-overlay"> <div id="pause" class="fullscreen-overlay"></div>
</div>
<div id="packet-history" class="fullscreen-overlay"> <div id="packet-history" class="fullscreen-overlay"></div>
</div>
<div id="database-error" class="fullscreen-overlay"> <div id="database-error" class="fullscreen-overlay"></div>
</div>
<script src="lib/loglevel.min.js"></script> <script src="lib/loglevel.min.js"></script>
<script src="lib/uuidv4.min.js" type="module"></script> <script src="lib/uuidv4.min.js" type="module"></script>
@@ -226,8 +315,6 @@
<script src="js/main.js" defer="defer" type="module"></script> <script src="js/main.js" defer="defer" type="module"></script>
<script src="lib/notify.min.js" type="text/javascript"></script> <script src="lib/notify.min.js" type="text/javascript"></script>
<script> <script></script>
</script> </body>
</body>
</html> </html>
+8 -7
View File
@@ -3,7 +3,7 @@ import * as config from "./config.js";
/** /**
* Submits answers * Submits answers
*/ */
export function submitAnswers(exam_details, db, config) { export function submitAnswers(exam_details, db, URLS) {
getJsonAnswers(exam_details, db) getJsonAnswers(exam_details, db)
.then((a) => { .then((a) => {
let json = { let json = {
@@ -12,7 +12,7 @@ export function submitAnswers(exam_details, db, config) {
start_time: exam_details.start_time, start_time: exam_details.start_time,
answers: JSON.stringify(a), answers: JSON.stringify(a),
}; };
postAnswers(json, config, exam_details); postAnswers(json, URLS, exam_details);
}) })
.catch((e) => { .catch((e) => {
console.debug(e) console.debug(e)
@@ -44,11 +44,12 @@ export function getJsonAnswers(exam_details, db) {
* Posts answers to url * Posts answers to url
* @param {*} ans - json representation of answers * @param {*} ans - json representation of answers
*/ */
export function postAnswers(ans, config, exam_details) { export function postAnswers(ans, URLS, exam_details) {
$("#progress").html("Submitting answers..."); $("#progress").html("Submitting answers...");
console.debug("postAnswers", ans, config, exam_details) console.debug("postAnswers", ans, URLS, exam_details)
console.debug("posturl", URLS.exam_submit_url)
$.post(config.exam_submit_url, ans, null, "json") $.post(URLS.exam_submit_url, ans, null, "json")
.done((data) => { .done((data) => {
console.debug("returned data", data); console.debug("returned data", data);
if (data.success) { if (data.success) {
@@ -61,8 +62,8 @@ export function postAnswers(ans, config, exam_details) {
if (ret) { if (ret) {
$(document).trigger("saveSessionEvent", [true]); $(document).trigger("saveSessionEvent", [true]);
if (config.exam_results_url != "") { if (URLS.exam_results_url != "") {
let url = config.exam_results_url; let url = URLS.exam_results_url;
if (exam_details.cid != "") { if (exam_details.cid != "") {
url = url + exam_details.cid; url = url + exam_details.cid;
+49 -10
View File
@@ -6,10 +6,25 @@ import * as config from "./config.js";
// const { v4: uuidv4 } = require('uuid'); // const { v4: uuidv4 } = require('uuid');
log.setDefaultLevel("warn") log.setDefaultLevel("warn")
log.setDefaultLevel("debug")
let URLS = {}; let URLS = {};
let standalone = false;
if (config.standalone != "" && config.standalone != undefined) {
standalone = config.standalone
}
let allow_users = false;
if (config.allow_users != "" && config.allow_users != undefined) {
allow_users = config.allow_users
}
// Generate urls base on base_url // Generate urls base on base_url
if (config.base_url != "" && config.base_url != undefined) { if (config.base_url != "" && config.base_url != undefined) {
URLS.base_url = config.base_url; URLS.base_url = config.base_url;
@@ -25,7 +40,7 @@ if (config.base_url != "" && config.base_url != undefined) {
// Override individual urls // Override individual urls
let urls_to_check = ["exam_query_url", "exam_submit_url", let urls_to_check = ["exam_query_url", "exam_submit_url",
"exam_results_url", "question_feedback_url", "exam_results_url", "question_feedback_url",
"quetion_answer_submit_url", "login_url", "logout_url"] "question_answer_submit_url", "login_url", "logout_url"]
for (let url of urls_to_check) { for (let url of urls_to_check) {
if (config[url] != "" && config[url] != undefined) { if (config[url] != "" && config[url] != undefined) {
@@ -33,6 +48,7 @@ for (let url of urls_to_check) {
} }
} }
log.debug("URLS")
log.debug(URLS) log.debug(URLS)
@@ -47,7 +63,7 @@ let exam_details = {
start_time: null, start_time: null,
}; };
let packet_list = []; //let packet_list = [];
let packet_name = null; let packet_name = null;
let questions = null; let questions = null;
let questions_correct = {}; let questions_correct = {};
@@ -113,6 +129,10 @@ question_db.version(1).stores({
retrievePacketList(); retrievePacketList();
if (!allow_users) {
$("#user-details").hide()
}
try { try {
refreshDatabaseSettings(); refreshDatabaseSettings();
} }
@@ -198,7 +218,7 @@ async function retrievePacketList() {
url = `${URLS.exam_query_url}/${global_cid}/${global_passcode}`; url = `${URLS.exam_query_url}/${global_cid}/${global_passcode}`;
} }
} }
log.debug(`url: {url}`) log.debug(`url: ${url}`)
} catch (e) { } catch (e) {
log.debug("Unable to set exam query url", e) log.debug("Unable to set exam query url", e)
log.debug("this will default to packets/packets.json") log.debug("this will default to packets/packets.json")
@@ -525,8 +545,12 @@ async function loadExamList(data) {
*/ */
// TODO: remove (data formats should be switched to the exam format) // TODO: remove (data formats should be switched to the exam format)
async function loadPacketList(data) { async function loadPacketList(data) {
// NOTE: currently the packet id is not available prior ot downloading the packet
// this severly limits what we can do with it (but to require would limit the utility)
log.debug(`loadPacketList`);
log.debug("Loading saved sessions")
let sessions = await db.session.toArray().catch(function(error) { let sessions = await db.session.toArray().catch(function(error) {
console.debug("Error loading session", error); log.debug(`Error loading session ${error}`);
$("#database-error").text( $("#database-error").text(
"Error loading the database, schema has probably changed and needs updating. You will probably need to delete the local database." "Error loading the database, schema has probably changed and needs updating. You will probably need to delete the local database."
); );
@@ -539,12 +563,15 @@ async function loadPacketList(data) {
$("#database-error").append(delete_button); $("#database-error").append(delete_button);
$("#database-error").show(); $("#database-error").show();
}); });
log.debug(sessions)
// db.session // db.session
// .where("packet") // .where("packet")
// .equals() // .equals()
let packets_started = []; let packets_started = [];
let packets_completed = []; let packets_completed = [];
log.debug("Check status of saved packets")
sessions.forEach((s) => { sessions.forEach((s) => {
log.debug(`checking status of`, s)
if (s.status == "active") { if (s.status == "active") {
packets_started.push(s.packet); packets_started.push(s.packet);
} else { } else {
@@ -552,17 +579,29 @@ async function loadPacketList(data) {
} }
}); });
log.debug("Packets started")
log.debug(packets_started)
log.debug("Packets completed")
log.debug(packets_completed)
let packet_list = [];
if (data != null) { if (data != null) {
packet_list = data.packets; packet_list = data.packets;
} else {
log.debug("data == null")
} }
log.debug(packet_list)
$("#packet-list").empty(); $("#packet-list").empty();
if (packet_json_id == undefined) { //if (packet_json_id == undefined) {
$("#options-panel").show(); // $("#options-panel").show();
return // return
} //}
//console.debug(packet_list)
packet_list.forEach(function(packet) { packet_list.forEach(function(packet) {
// Seperate packet types // Seperate packet types
let list; let list;
@@ -1774,7 +1813,7 @@ $("#btn-local-file-load").click(function(evt) {
}); });
$(".submit-button").click(function(evt) { $(".submit-button").click(function(evt) {
interact.submitAnswers(exam_details, db, config); interact.submitAnswers(exam_details, db, URLS);
}); });
$("#btn-review").click(function(evt) { $("#btn-review").click(function(evt) {
+2
View File
@@ -279,6 +279,8 @@ export function debugCornerstone() {
/** /**
* Registers the selected dicom tool * Registers the selected dicom tool
*
* This also allows selecting of window levels
*/ */
export function changeControlSelection() { export function changeControlSelection() {
// We also duplicate the sel that are available // We also duplicate the sel that are available