Skip to content

Commit

Permalink
feat: prevent uploading files until scorm passed
Browse files Browse the repository at this point in the history
  • Loading branch information
satikaj committed Jun 15, 2024
1 parent 3b75765 commit ec86e4e
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 44 deletions.
1 change: 1 addition & 0 deletions src/app/api/models/task-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class TaskDefinition extends Entity {
scormEnabled: boolean;
hasScormData: boolean;
scormAllowReview: boolean;
scormBypassTest: boolean;
scormTimeDelayEnabled: boolean;
scormAttemptLimit: number = 0;
hasTaskAssessmentResources: boolean;
Expand Down
24 changes: 20 additions & 4 deletions src/app/api/models/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,22 @@ export class Task extends Entity {
}

public get scormEnabled(): boolean {
return (
this.definition.scormEnabled && this.definition.hasScormData
);
return this.definition.scormEnabled && this.definition.hasScormData;
}

public get scormPassed(): boolean {
if (this.latestCompletedTestAttempt) {
return this.latestCompletedTestAttempt.successStatus;
}
return false;
}

public get isReadyForUpload(): boolean {
return !this.scormEnabled || this.definition.scormBypassTest || this.scormPassed;
}

public get latestCompletedTestAttempt(): TestAttempt {
return this.testAttemptCache.currentValues.find((attempt) => attempt.terminated);
}

public submissionUrl(asAttachment: boolean = false): string {
Expand Down Expand Up @@ -669,12 +682,15 @@ export class Task extends Entity {

public triggerTransition(status: TaskStatusEnum): void {
if (this.status === status) return;
const alerts: AlertService = AppInjector.get(AlertService);

const requiresFileUpload =
['ready_for_feedback', 'need_help'].includes(status) && this.requiresFileUpload();

if (requiresFileUpload) {
if (requiresFileUpload && this.isReadyForUpload) {
this.presentTaskSubmissionModal(status);
} else if (requiresFileUpload && !this.isReadyForUpload) {
alerts.error('Complete Knowledge Check first to submit files', 6000);
} else {
this.updateTaskStatus(status);
}
Expand Down
1 change: 1 addition & 0 deletions src/app/api/services/task-definition.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export class TaskDefinitionService extends CachedEntityService<TaskDefinition> {
'scormEnabled',
'hasScormData',
'scormAllowReview',
'scormBypassTest',
'scormTimeDelayEnabled',
'scormAttemptLimit',
'isGraded',
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/services/test-attempt.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {HttpClient} from '@angular/common/http';
@Injectable()
export class TestAttemptService extends CachedEntityService<TestAttempt> {
protected readonly endpointFormat =
'/projects/:project_id:/task_def_id/:task_def_id:/test_attempts';
'projects/:project_id:/task_def_id/:task_def_id:/test_attempts';
protected readonly latestCompletedEndpoint =
this.endpointFormat + '/latest?completed=:completed:';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
@if (isPassed) {
<mat-card appearance="outlined" [hidden]="!task.scormEnabled">
@if (latestCompletedAttempt.scoreScaled === 1) {
@if (this.task.latestCompletedTestAttempt.scoreScaled === 1) {
<mat-card-header class="bg-green-600 text-white">
<mat-card-title class="flex items-center mb-4"
><mat-icon class="font-extrabold">check</mat-icon>
<span class="ml-4">Knowledge Check Passed</span></mat-card-title
>
</mat-card-header>
}
@if (latestCompletedAttempt.scoreScaled !== 1) {
@if (this.task.latestCompletedTestAttempt.scoreScaled !== 1) {
<mat-card-header class="bg-green-500 text-white">
<mat-card-title class="flex items-center mb-4"
><mat-icon class="font-extrabold">check</mat-icon>
Expand Down Expand Up @@ -73,7 +73,10 @@
<button
mat-stroked-button
(click)="reviewLatestCompletedAttempt()"
[hidden]="(!user.isStaff && !task.definition.scormAllowReview) || !latestCompletedAttempt"
[hidden]="
(!user.isStaff && !task.definition.scormAllowReview) ||
!this.task.latestCompletedTestAttempt
"
>
Review last attempt
</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,63 +1,45 @@
import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import {
Task,
TestAttempt,
TestAttemptService,
User,
UserService,
} from 'src/app/api/models/doubtfire-model';
import {Component, Input, OnChanges, SimpleChanges} from '@angular/core';
import {Task, User, UserService} from 'src/app/api/models/doubtfire-model';
import {ScormExtensionModalService} from 'src/app/common/modals/scorm-extension-modal/scorm-extension-modal.service';

@Component({
selector: 'f-task-scorm-card',
templateUrl: './task-scorm-card.component.html',
styleUrls: ['./task-scorm-card.component.scss'],
})
export class TaskScormCardComponent implements OnInit, OnChanges {
export class TaskScormCardComponent implements OnChanges {
@Input() task: Task;
attemptsLeft: number;
isPassed: boolean;
latestCompletedAttempt: TestAttempt;
user: User;

constructor(
private extensions: ScormExtensionModalService,
private testAttemptService: TestAttemptService,
private userService: UserService,
) {
this.user = this.userService.currentUser;
}

ngOnInit() {
this.refreshAttemptData();
}

ngOnChanges(changes: SimpleChanges) {
if (changes.task && changes.task.currentValue) {
this.refreshAttemptData();
}
}

refreshAttemptData(): void {
this.attemptsLeft = undefined;
this.isPassed = undefined;
this.latestCompletedAttempt = undefined;
if (changes.task && changes.task.currentValue && changes.task.currentValue.scormEnabled) {
this.attemptsLeft = undefined;
this.isPassed = undefined;

this.getAttemptsLeft();
this.testAttemptService.getLatestCompletedAttempt(this.task).subscribe((attempt) => {
this.latestCompletedAttempt = attempt;
this.isPassed = attempt.successStatus;
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.task?.fetchTestAttempts().subscribe((_) => {
this.getAttemptsLeft();
if (this.task.latestCompletedTestAttempt) this.isPassed = this.task.scormPassed;
});
}
}

getAttemptsLeft(): void {
if (this.task.definition.scormAttemptLimit != 0) {
this.task.fetchTestAttempts().subscribe((attempts) => {
let count = attempts.length;
if (count > 0 && attempts[0].terminated === false) count--;
this.attemptsLeft =
this.task.definition.scormAttemptLimit + this.task.scormExtensions - count;
});
const attempts = this.task.testAttemptCache.currentValues;
let count = attempts.length;
if (count > 0 && attempts[0].terminated === false) count--;
this.attemptsLeft =
this.task.definition.scormAttemptLimit + this.task.scormExtensions - count;
}
}

Expand All @@ -70,7 +52,7 @@ export class TaskScormCardComponent implements OnInit, OnChanges {

reviewLatestCompletedAttempt(): void {
window.open(
`#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.latestCompletedAttempt.id}`,
`#/task_def_id/${this.task.taskDefId}/scorm-player/review/${this.task.latestCompletedTestAttempt.id}`,
'_blank',
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
<mat-checkbox matInput required [(ngModel)]="taskDefinition.scormAllowReview">
Allow students to review completed test attempt
</mat-checkbox>
<mat-checkbox matInput required [(ngModel)]="taskDefinition.scormBypassTest">
Allow file upload regardless of test pass status
</mat-checkbox>
</div>
<mat-form-field appearance="outline" class="basis-1/2">
<mat-label>Attempt limit</mat-label>
Expand Down

0 comments on commit ec86e4e

Please sign in to comment.