Skip to content

Commit

Permalink
Exam mode: Do not display working time differences for tests exams
Browse files Browse the repository at this point in the history
  • Loading branch information
krusche committed Dec 15, 2024
1 parent 1f0f75b commit b21a9c4
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 71 deletions.
6 changes: 3 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ module.exports = {
coverageThreshold: {
global: {
// TODO: in the future, the following values should increase to at least 90%
statements: 87.67,
statements: 87.69,
branches: 73.79,
functions: 82.27,
lines: 87.72,
functions: 82.28,
lines: 87.74,
},
},
coverageReporters: ['clover', 'json', 'lcov', 'text-summary'],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<div class="d-flex pb-3 border-bottom">
<div class="d-flex flex-column justify-content-center">
@if (!isTestRun) {
<h4 class="mb-0" jhiTranslate="artemisApp.studentExamDetail.studentExam" [translateValues]="{ examTitle: studentExam.exam!.title! }">
Student exam ({{ studentExam.exam!.title! }})
@if (isTestExam) {
<h4 class="mb-0" jhiTranslate="artemisApp.studentExamDetail.studentTestExam" [translateValues]="{ examTitle: studentExam.exam!.title! }">
Student test exam ({{ studentExam.exam!.title! }})
</h4>
} @else {
} @else if (isTestRun) {
<h4 class="mb-0" jhiTranslate="artemisApp.studentExamDetail.testRun" [translateValues]="{ examTitle: studentExam.exam!.title! }">
Test Run ({{ studentExam.exam!.title! }})
</h4>
} @else {
<h4 class="mb-0" jhiTranslate="artemisApp.studentExamDetail.studentExam" [translateValues]="{ examTitle: studentExam.exam!.title! }">
Student exam ({{ studentExam.exam!.title! }})
</h4>
}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ export class StudentExamDetailComponent implements OnInit, OnDestroy {
.subscribe(([data, params, url]) => {
this.examId = params.examId;
this.courseId = params.courseId;
this.setStudentExamWithGrade(data.studentExam);
this.isTestExam = data.studentExam.exam?.testExam;
const studentExamWithGrade = data.studentExam as StudentExamWithGradeDTO;
this.setStudentExamWithGrade(studentExamWithGrade);
this.isTestExam = studentExamWithGrade.studentExam?.exam?.testExam || false;
this.isTestRun = url[1]?.toString() === 'test-runs';
});
}
Expand Down Expand Up @@ -215,7 +216,7 @@ export class StudentExamDetailComponent implements OnInit, OnDestroy {
this.isSaving = false;
},
error: () => {
this.alertService.error('artemisApp.studentExamDetail.togglefailed');
this.alertService.error('artemisApp.studentExamDetail.toggleFailed');
this.isSaving = false;
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<span>
{{ studentExam.workingTime! | artemisDurationFromSeconds }}
@if (!isTestRun && percentDifference !== 0) {
@if (!isTestRun && !isTestExam && percentDifference !== 0) {
({{ percentDifference > 0 ? '+' : '' }}{{ percentDifference }}&thinsp;%)
}
</span>
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ export class StudentExamWorkingTimeComponent implements OnInit {

percentDifference = 0;
isTestRun = false;
isTestExam = false;

ngOnInit() {
if (this.studentExam.exam && this.studentExam.workingTime) {
this.isTestRun = this.studentExam.testRun ?? false;
this.isTestExam = this.studentExam.exam?.testExam ?? false;
if (this.studentExam.exam && this.studentExam.workingTime && !this.isTestRun && !this.isTestExam) {
this.percentDifference = getRelativeWorkingTimeExtension(this.studentExam.exam, this.studentExam.workingTime);
}
this.isTestRun = this.studentExam.testRun ?? false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export class ConversationMembersComponent implements OnInit, OnDestroy {

private readonly search$ = new Subject<SearchQuery>();

course = input<Course>();
activeConversationInput = input<ConversationDTO>();
activeConversation = signal<ConversationDTO | null>(null);
course = input.required<Course>();
activeConversationInput = input.required<ConversationDTO>();
activeConversation = signal<ConversationDTO | undefined>(undefined);
changesPerformed = output<void>();

canAddUsersToConversation = canAddUsersToConversation;
Expand Down Expand Up @@ -115,8 +115,8 @@ export class ConversationMembersComponent implements OnInit, OnDestroy {
switchMap(() => {
if (this.course()?.id && this.activeConversation()?.id) {
return this.conversationService.searchMembersOfConversation(
this.course()?.id!,
this.activeConversation()?.id!,
this.course().id!,
this.activeConversation()!.id!,
this.searchTerm,
this.page - 1,
this.itemsPerPage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import { catchError } from 'rxjs/operators';
export class ConversationSettingsComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject<void>();

activeConversation = input<ConversationDTO>();
course = input<Course>();
activeConversation = input.required<ConversationDTO>();
course = input.required<Course>();

channelArchivalChange = output<void>();
channelDeleted = output<void>();
Expand Down Expand Up @@ -54,22 +54,22 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
this.canLeaveConversation = canLeaveConversation(conversation);
this.conversationAsChannel = getAsChannelDTO(conversation);
this.canChangeChannelArchivalState = this.conversationAsChannel ? canChangeChannelArchivalState(this.conversationAsChannel) : false;
this.canDeleteChannel = this.conversationAsChannel ? canDeleteChannel(this.course()!, this.conversationAsChannel) : false;
this.canDeleteChannel = this.conversationAsChannel ? canDeleteChannel(this.course(), this.conversationAsChannel) : false;
}

leaveConversation($event: MouseEvent) {
$event.stopPropagation();
if (isGroupChatDTO(this.activeConversation()!)) {
this.groupChatService
.removeUsersFromGroupChat(this.course()!.id!, this.activeConversation()?.id!)
.removeUsersFromGroupChat(this.course().id!, this.activeConversation().id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {
this.conversationLeave.emit();
});
return;
} else if (isChannelDTO(this.activeConversation()!)) {
this.channelService
.deregisterUsersFromChannel(this.course()!.id!, this.activeConversation()?.id!)
.deregisterUsersFromChannel(this.course().id!, this.activeConversation().id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe(() => {
this.conversationLeave.emit();
Expand Down Expand Up @@ -97,30 +97,16 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
confirmButtonKey: 'artemisApp.dialogs.archiveChannel.confirmButton',
};

const translationParams = {
channelName: channel.name,
};
const modalRef = this.createModal(channel, event, keys);

event.stopPropagation();
const modalRef: NgbModalRef = this.modalService.open(GenericConfirmationDialogComponent, defaultSecondLayerDialogOptions);
modalRef.componentInstance.translationParameters = translationParams;
modalRef.componentInstance.translationKeys = keys;
modalRef.componentInstance.canBeUndone = true;
modalRef.componentInstance.initialize();

from(modalRef.result)
.pipe(
catchError(() => EMPTY),
takeUntil(this.ngUnsubscribe),
)
.subscribe(() => {
this.channelService.archive(this.course()?.id!, channel.id!).subscribe({
next: () => {
this.channelArchivalChange.emit();
},
error: (errorResponse: HttpErrorResponse) => onError(this.alertService, errorResponse),
});
this.openModal(modalRef, () => {
this.channelService.archive(this.course().id!, channel.id!).subscribe({
next: () => {
this.channelArchivalChange.emit();
},
error: (errorResponse: HttpErrorResponse) => onError(this.alertService, errorResponse),
});
});
}

openUnArchivalModal(event: MouseEvent) {
Expand All @@ -135,34 +121,38 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
descriptionKey: 'artemisApp.dialogs.unArchiveChannel.description',
confirmButtonKey: 'artemisApp.dialogs.unArchiveChannel.confirmButton',
};
const modalRef = this.createModal(channel, event, keys);

const translationParams = {
channelName: channel.name,
};

event.stopPropagation();
const modalRef: NgbModalRef = this.modalService.open(GenericConfirmationDialogComponent, defaultSecondLayerDialogOptions);
modalRef.componentInstance.translationParameters = translationParams;
modalRef.componentInstance.translationKeys = keys;
modalRef.componentInstance.canBeUndone = true;
modalRef.componentInstance.initialize();
this.openModal(modalRef, () => {
this.channelService
.unarchive(this.course().id!, channel.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: () => {
this.channelArchivalChange.emit();
},
error: (errorResponse: HttpErrorResponse) => onError(this.alertService, errorResponse),
});
});
}

private openModal(modalRef: NgbModalRef, unArchiveObservable: () => void) {
from(modalRef.result)
.pipe(
catchError(() => EMPTY),
takeUntil(this.ngUnsubscribe),
)
.subscribe(() => {
this.channelService
.unarchive(this.course()?.id!, channel.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: () => {
this.channelArchivalChange.emit();
},
error: (errorResponse: HttpErrorResponse) => onError(this.alertService, errorResponse),
});
});
.subscribe(unArchiveObservable);
}

private createModal(channel: ChannelDTO, event: MouseEvent, keys: { titleKey: string; questionKey: string; descriptionKey: string; confirmButtonKey: string }): NgbModalRef {
event.stopPropagation();
const modalRef: NgbModalRef = this.modalService.open(GenericConfirmationDialogComponent, defaultSecondLayerDialogOptions);
modalRef.componentInstance.translationParameters = { channelName: channel.name };
modalRef.componentInstance.translationKeys = keys;
modalRef.componentInstance.canBeUndone = true;
modalRef.componentInstance.initialize();
return modalRef;
}

deleteChannel() {
Expand All @@ -171,7 +161,7 @@ export class ConversationSettingsComponent implements OnInit, OnDestroy {
return;
}
this.channelService
.delete(this.course()?.id!, channel.id!)
.delete(this.course().id!, channel.id!)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe({
next: () => {
Expand Down
5 changes: 3 additions & 2 deletions src/main/webapp/i18n/de/exam.json
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,8 @@
}
},
"studentExamDetail": {
"studentExam": "Klausur ({{ examTitle }})",
"studentExam": "Studierenden Klausur ({{ examTitle }})",
"studentTestExam": "Studierenden Test Klausur ({{ examTitle }})",
"testRun": "Testlauf ({{ examTitle }})",
"exercises": "Aufgaben",
"overview": "Übersicht",
Expand All @@ -800,7 +801,7 @@
"endOfIndividualWorkingTime": "Ende der individuellen Bearbeitungszeit:",
"disabledChangeSubmissionStateButtonExplanation": "Der Abgabestatus kann erst nach Ende der Bearbeitungszeit und Ablauf der Karenzzeit geändert werden.",
"toggleSuccessful": "Der Abgabestatus wurde erfolgreich geändert.",
"togglefailed": "Der Abgabestatus konnte nicht geändert werden!",
"toggleFailed": "Der Abgabestatus konnte nicht geändert werden!",
"hasComplaint": "Beschwerde existiert",
"noSessions": "Keine Sitzungen"
},
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/i18n/en/exam.json
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@
},
"studentExamDetail": {
"studentExam": "Student exam ({{ examTitle }})",
"studentTestExam": "Student test exam ({{ examTitle }})",
"testRun": "Test Run ({{ examTitle }})",
"exercises": "Exercises",
"overview": "Overview",
Expand All @@ -800,7 +801,7 @@
"endOfIndividualWorkingTime": "End of individual working time:",
"disabledChangeSubmissionStateButtonExplanation": "Cannot be changed before the end of the working time and the respective grace period.",
"toggleSuccessful": "The submitted status was changed successfully.",
"togglefailed": "The submitted status could not be changed!",
"toggleFailed": "The submitted status could not be changed!",
"hasComplaint": "Has Complaint",
"noSessions": "No Sessions"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ examples.forEach((activeConversation) => {
fixture = TestBed.createComponent(ConversationMembersComponent);
TestBed.runInInjectionContext(() => {
component = fixture.componentInstance;
component.activeConversation = signal<ConversationDTO>(activeConversation);
component.activeConversationInput = input<ConversationDTO>(activeConversation);
component.course = input<Course>(course);
component.activeConversation = signal<ConversationDTO>(activeConversation);
});
component.canAddUsersToConversation = canAddUsersToConversation;
});
Expand Down

0 comments on commit b21a9c4

Please sign in to comment.