Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/uis/screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface UIExamModeElements {
examStartText: HTMLSpanElement;
examEndText: HTMLSpanElement;
examStartButton: HTMLButtonElement;
examStartTimer: HTMLParagraphElement;
}

export abstract class UIScreen {
Expand Down
48 changes: 46 additions & 2 deletions client/uis/screens/examscreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export class ExamModeUI extends UIScreen {
private _examMode: boolean = false;
private _examIds: number[] = [];
private _loginScreen: LoginScreenUI;
private _examStartButtonEnableInterval: ReturnType<typeof setInterval> | null = null;
private _examStartTime = new Date("2099-01-01T00:00:00Z"); // Set to a future date so that the button is disabled by default
protected _events: AuthenticatorEvents = {
authenticationStart: () => {
this._disableForm();
Expand Down Expand Up @@ -43,6 +45,7 @@ export class ExamModeUI extends UIScreen {
examStartText: document.getElementById('exam-mode-start') as HTMLSpanElement,
examEndText: document.getElementById('exam-mode-end') as HTMLSpanElement,
examStartButton: document.getElementById('exam-mode-start-button') as HTMLButtonElement,
examStartTimer: document.getElementById('exam-mode-start-timer') as HTMLParagraphElement,
} as UIExamModeElements;

this._initForm();
Expand Down Expand Up @@ -100,6 +103,16 @@ export class ExamModeUI extends UIScreen {
});
}

private _clearExamStartTimer(): void {
const form = this._form as UIExamModeElements;
if (this._examStartButtonEnableInterval) {
clearTimeout(this._examStartButtonEnableInterval);
this._examStartButtonEnableInterval = null;
}
form.examStartTimer.innerText = "Click the arrow below to start your exam.";
this._enableOrDisableSubmitButton();
}

private _populateData(examsToPopulate: ExamForHost[]): void {
const form = this._form as UIExamModeElements;

Expand All @@ -108,6 +121,9 @@ export class ExamModeUI extends UIScreen {
form.examProjectsText.innerText = '';
form.examStartText.innerText = 'unknown';
form.examEndText.innerText = 'unknown';
// Clear the timeout for the exam start button and disable it
this._examStartTime = new Date("2099-01-01T00:00:00Z");
this._clearExamStartTimer();
}
else {
// Find all exams in the data.json file that match the ids in the exams variable
Expand Down Expand Up @@ -144,14 +160,42 @@ export class ExamModeUI extends UIScreen {
form.examProjectsText.innerText = projectsText;
form.examStartText.innerText = earliestExam.toLocaleTimeString("en-NL", { hour: '2-digit', minute: '2-digit' });
form.examEndText.innerText = latestExam.toLocaleTimeString("en-NL", { hour: '2-digit', minute: '2-digit' });

// Enable or disable the exam start button based on the current time
this._clearExamStartTimer();
this._examStartTime = earliestExam;
this._enableOrDisableSubmitButton();
if (this._examStartTime.getTime() > Date.now()) {
this._examStartButtonEnableInterval = setInterval(() => {
const timeLeft = Math.floor((this._examStartTime.getTime() - Date.now()) / 1000);
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
const formattedTime = `${(minutes > 0 ? `${minutes} minutes and ` : '')} ${seconds} seconds`;
form.examStartTimer.innerText = `You may start your exam in ${formattedTime}.`;

if (this._examStartTime.getTime() <= Date.now()) {
// Clear the timer and enable the button
this._clearExamStartTimer();
return;
}
}, 1000);
}
}
}

// Returns true if the exam-start button is disabled, false otherwise
protected _enableOrDisableSubmitButton(): boolean {
const form = this._form as UIExamModeElements;
form.examStartButton.disabled = false; // Always enable the button
return false;
const buttonDisabled = this._examStartTime.getTime() > Date.now(); // Disable the button if the exam start time is in the future
form.examStartButton.disabled = buttonDisabled;
if (!buttonDisabled) {
form.examStartTimer.innerText = "Click the arrow below to start your exam.";
const focusInput = this._getInputToFocusOn();
if (focusInput) {
focusInput.focus();
}
}
return buttonDisabled;
}

protected _wigglePasswordInput(clearInput: boolean = true): void {
Expand Down
2 changes: 1 addition & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h4 id="active-user-session-login-name">username</h4>
<h3>This computer is reserved for an exam between <span id="exam-mode-start">...</span> and <span id="exam-mode-end">...</span>.</h3>
<p><span id="exam-mode-projects"></span></p>
<br>
<p>Click the arrow below to start your exam.</p>
<p id="exam-mode-start-timer">Click the arrow below to start your exam.</p>
<button type="submit" id="exam-mode-start-button" title="Start your exam">&#10149;</button>
</form>

Expand Down