From 3b30ed8b0b39917c85e541536dc259f1d240a706 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Tue, 8 Oct 2024 20:42:24 +0200 Subject: [PATCH 01/18] add save exercise button --- .../exam-participation.component.html | 6 ++- .../text/text-exam-submission.component.html | 43 +++++++++++++------ .../text/text-exam-submission.component.ts | 21 +++++++-- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.html b/src/main/webapp/app/exam/participate/exam-participation.component.html index 391c435fee09..99504a088dd7 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.html +++ b/src/main/webapp/app/exam/participate/exam-participation.component.html @@ -68,7 +68,11 @@ /> } @case (TEXT) { - + } @case (MODELING) { diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index 653d0f6b0ad5..ebd593943f27 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -1,17 +1,36 @@ @if (exercise) { -

- - {{ exercise.exerciseGroup?.title }} - - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} +
+

+ + {{ exercise.exerciseGroup?.title }} + + +  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { + , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } -

+ + } +

+ + +
diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index 3a493af08507..8c45deb0f7bc 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { TextEditorService } from 'app/exercises/text/participate/text-editor.service'; import { Subject } from 'rxjs'; import { TextSubmission } from 'app/entities/text/text-submission.model'; @@ -6,10 +6,11 @@ import { StringCountService } from 'app/exercises/text/participate/string-count. import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; import { ExamSubmissionComponent } from 'app/exam/participate/exercises/exam-submission.component'; import { Submission } from 'app/entities/submission.model'; -import { faListAlt } from '@fortawesome/free-regular-svg-icons'; +import { faCheck, faFloppyDisk, faListAlt } from '@fortawesome/free-solid-svg-icons'; import { MAX_SUBMISSION_TEXT_LENGTH } from 'app/shared/constants/input.constants'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; +import { ExamParticipationService } from '../../exam-participation.service'; @Component({ selector: 'jhi-text-editor-exam', @@ -26,6 +27,8 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme @Input() exercise: Exercise; + @Output() saveCurrentExercise = new EventEmitter(); + readonly IncludedInOverallScore = IncludedInOverallScore; readonly maxCharacterCount = MAX_SUBMISSION_TEXT_LENGTH; @@ -33,13 +36,17 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme answer: string; problemStatementHtml: string; private textEditorInput = new Subject(); + submission?: Submission; // Icons - farListAlt = faListAlt; + readonly farListAlt = faListAlt; + readonly faFloppyDisk = faFloppyDisk; + readonly faCheck = faCheck; constructor( private textService: TextEditorService, private stringCountService: StringCountService, + private examParticipationService: ExamParticipationService, changeDetectorReference: ChangeDetectorRef, ) { super(changeDetectorReference); @@ -49,6 +56,7 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme // show submission answers in UI this.problemStatementHtml = htmlForMarkdown(this.exercise?.problemStatement); this.updateViewFromSubmission(); + this.submission = ExamParticipationService.getSubmissionForExercise(this.exercise); } getExerciseId(): number | undefined { @@ -121,4 +129,11 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme this.submissionVersion = submissionVersion; this.updateViewFromSubmissionVersion(); } + + onSave() { + if (this.submission) { + this.submission.submitted = true; + } + this.saveCurrentExercise.emit(); + } } From ab40f4d64196af53b5d8963cd183969db26cf613 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Wed, 9 Oct 2024 19:43:06 +0200 Subject: [PATCH 02/18] Add save button component --- .../exam-participation.component.html | 7 ++++- .../exam-submission-components.module.ts | 2 ++ .../exercise-save-button.component.html | 6 ++++ .../exercise-save-button.component.scss | 3 ++ .../exercise-save-button.component.ts | 29 +++++++++++++++++++ .../modeling-exam-submission.component.html | 27 +++++++++-------- .../modeling-exam-submission.component.ts | 8 ++++- .../quiz/quiz-exam-submission.component.html | 25 +++++++++------- .../quiz/quiz-exam-submission.component.ts | 8 ++++- .../text/text-exam-submission.component.html | 18 +----------- .../text/text-exam-submission.component.ts | 9 ++---- 11 files changed, 92 insertions(+), 50 deletions(-) create mode 100644 src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html create mode 100644 src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.scss create mode 100644 src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.html b/src/main/webapp/app/exam/participate/exam-participation.component.html index 99504a088dd7..a62faf6b3892 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.html +++ b/src/main/webapp/app/exam/participate/exam-participation.component.html @@ -59,6 +59,7 @@ } @case (FILEUPLOAD) { @@ -75,7 +76,11 @@ /> } @case (MODELING) { - + } @case (PROGRAMMING) { + + + {{ submission?.submitted && submission?.isSynced ? 'Exercise Saved' : 'Save Exercise' }} + + diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.scss b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.scss new file mode 100644 index 000000000000..0b4d4eb0b98c --- /dev/null +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.scss @@ -0,0 +1,3 @@ +.saved { + --fa-secondary-opacity: 1; +} diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts new file mode 100644 index 000000000000..e2619dc2c912 --- /dev/null +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -0,0 +1,29 @@ +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { faFloppyDisk, faListAlt } from '@fortawesome/free-solid-svg-icons'; +import { facSaveSuccess } from '../../../../../content/icons/icons'; +import { Submission } from 'app/entities/submission.model'; + +@Component({ + selector: 'jhi-exercise-save-button', + templateUrl: './exercise-save-button.component.html', + styleUrls: ['./exercise-save-button.component.scss'], + standalone: true, + imports: [FaIconComponent], +}) +export class ExerciseSaveButtonComponent { + @Input() submission?: Submission; + @Output() save = new EventEmitter(); + + //Icons + readonly faFloppyDisk = faFloppyDisk; + readonly faListAlt = faListAlt; + readonly facSaveSuccess = facSaveSuccess; + + onSave() { + if (this.submission) { + this.submission.submitted = true; + } + this.save.emit(); + } +} diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html index 273a1acbb8e5..7271aca5b570 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html @@ -1,17 +1,20 @@ @if (exercise) { -

- - {{ exercise.exerciseGroup?.title }} - - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} +
+

+ + {{ exercise.exerciseGroup?.title }} + + +  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { + , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } -

+ + } +

+ +
diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index 60957411fcf8..66e74ed29b0a 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; import { UMLModel } from '@ls1intum/apollon'; import dayjs from 'dayjs/esm'; import { ModelingSubmission } from 'app/entities/modeling-submission.model'; @@ -34,6 +34,8 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp exercise: ModelingExercise; umlModel: UMLModel; // input model for Apollon+ + @Output() saveCurrentExercise = new EventEmitter(); + explanationText: string; // current explanation text readonly IncludedInOverallScore = IncludedInOverallScore; @@ -154,4 +156,8 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp this.changeDetectorReference.detectChanges(); } } + + notifyTriggerSave() { + this.saveCurrentExercise.emit(); + } } diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html index ace69b781b7e..a097a94b0816 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html @@ -1,14 +1,17 @@ -

- - {{ quizConfiguration.exerciseGroup?.title }} - - ({{ quizConfiguration.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}) - @if (quizConfiguration.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } - -

+
+

+ + {{ quizConfiguration.exerciseGroup?.title }} + + ({{ quizConfiguration.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}) + @if (quizConfiguration.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + } + +

+ +

diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts index f967003238ba..6a76be30e718 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, Input, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, QueryList, ViewChildren } from '@angular/core'; import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; import { AbstractQuizSubmission } from 'app/entities/quiz/abstract-quiz-exam-submission.model'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; @@ -53,6 +53,8 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme @Input() examTimeline = false; @Input() quizConfiguration: QuizConfiguration; + @Output() saveCurrentExercise = new EventEmitter(); + selectedAnswerOptions = new Map(); dragAndDropMappings = new Map(); shortAnswerSubmittedTexts = new Map(); @@ -285,4 +287,8 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme this.submissionVersion = submissionVersion; this.updateViewFromSubmissionVersion(); } + + notifyTriggerSave() { + this.saveCurrentExercise.emit(); + } } diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index ebd593943f27..58fa238a5615 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -13,23 +13,7 @@

[includedInOverallScore]="exercise.includedInOverallScore" /> }

- - +

diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index 8c45deb0f7bc..d652cb16da9f 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -6,7 +6,7 @@ import { StringCountService } from 'app/exercises/text/participate/string-count. import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; import { ExamSubmissionComponent } from 'app/exam/participate/exercises/exam-submission.component'; import { Submission } from 'app/entities/submission.model'; -import { faCheck, faFloppyDisk, faListAlt } from '@fortawesome/free-solid-svg-icons'; +import { faListAlt } from '@fortawesome/free-solid-svg-icons'; import { MAX_SUBMISSION_TEXT_LENGTH } from 'app/shared/constants/input.constants'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; @@ -40,8 +40,6 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme // Icons readonly farListAlt = faListAlt; - readonly faFloppyDisk = faFloppyDisk; - readonly faCheck = faCheck; constructor( private textService: TextEditorService, @@ -130,10 +128,7 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme this.updateViewFromSubmissionVersion(); } - onSave() { - if (this.submission) { - this.submission.submitted = true; - } + notifyTriggerSave() { this.saveCurrentExercise.emit(); } } From 4020da76a5c80c4a6767536b1be7216f2a083bab Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Wed, 9 Oct 2024 19:47:37 +0200 Subject: [PATCH 03/18] Remove unused icon --- .../exercise-save-button/exercise-save-button.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index e2619dc2c912..832c6118647c 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; -import { faFloppyDisk, faListAlt } from '@fortawesome/free-solid-svg-icons'; +import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons'; import { facSaveSuccess } from '../../../../../content/icons/icons'; import { Submission } from 'app/entities/submission.model'; @@ -17,7 +17,6 @@ export class ExerciseSaveButtonComponent { //Icons readonly faFloppyDisk = faFloppyDisk; - readonly faListAlt = faListAlt; readonly facSaveSuccess = facSaveSuccess; onSave() { From 81c10f254a09e6877016a7359e0f0f5bb493878c Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 10 Oct 2024 02:31:58 +0200 Subject: [PATCH 04/18] force sync in modeling exercise --- .../exercise-save-button/exercise-save-button.component.ts | 3 --- .../exercises/modeling/modeling-exam-submission.component.ts | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index 832c6118647c..84e9310acd69 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -20,9 +20,6 @@ export class ExerciseSaveButtonComponent { readonly facSaveSuccess = facSaveSuccess; onSave() { - if (this.submission) { - this.submission.submitted = true; - } this.save.emit(); } } diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index 66e74ed29b0a..2e1914b17697 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -158,6 +158,7 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp } notifyTriggerSave() { + this.studentSubmission.isSynced = true; this.saveCurrentExercise.emit(); } } From e4ba7658d9ca3f4384f6485194e90bd2df855eee Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Tue, 15 Oct 2024 16:30:00 +0200 Subject: [PATCH 05/18] use new input output signals --- .../exercise-save-button.component.html | 6 +++--- .../exercise-save-button.component.ts | 10 +++++----- .../modeling/modeling-exam-submission.component.ts | 5 ++--- .../exercises/quiz/quiz-exam-submission.component.ts | 4 ++-- .../exercises/text/text-exam-submission.component.ts | 4 ++-- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html index 0da019ef6afb..53a5972269c7 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html @@ -1,6 +1,6 @@ - diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index 84e9310acd69..c465e2f404a3 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { Component, input, output } from '@angular/core'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons'; import { facSaveSuccess } from '../../../../../content/icons/icons'; @@ -12,12 +12,12 @@ import { Submission } from 'app/entities/submission.model'; imports: [FaIconComponent], }) export class ExerciseSaveButtonComponent { - @Input() submission?: Submission; - @Output() save = new EventEmitter(); + submission = input(); + save = output(); //Icons - readonly faFloppyDisk = faFloppyDisk; - readonly facSaveSuccess = facSaveSuccess; + protected readonly faFloppyDisk = faFloppyDisk; + protected readonly facSaveSuccess = facSaveSuccess; onSave() { this.save.emit(); diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index 2e1914b17697..403c82f00f42 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild, output } from '@angular/core'; import { UMLModel } from '@ls1intum/apollon'; import dayjs from 'dayjs/esm'; import { ModelingSubmission } from 'app/entities/modeling-submission.model'; @@ -34,7 +34,7 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp exercise: ModelingExercise; umlModel: UMLModel; // input model for Apollon+ - @Output() saveCurrentExercise = new EventEmitter(); + saveCurrentExercise = output(); explanationText: string; // current explanation text @@ -158,7 +158,6 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp } notifyTriggerSave() { - this.studentSubmission.isSynced = true; this.saveCurrentExercise.emit(); } } diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts index 6a76be30e718..30186e5c8272 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, QueryList, ViewChildren } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnInit, QueryList, ViewChildren, output } from '@angular/core'; import { Exercise, ExerciseType, IncludedInOverallScore } from 'app/entities/exercise.model'; import { AbstractQuizSubmission } from 'app/entities/quiz/abstract-quiz-exam-submission.model'; import { AnswerOption } from 'app/entities/quiz/answer-option.model'; @@ -53,7 +53,7 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme @Input() examTimeline = false; @Input() quizConfiguration: QuizConfiguration; - @Output() saveCurrentExercise = new EventEmitter(); + saveCurrentExercise = output(); selectedAnswerOptions = new Map(); dragAndDropMappings = new Map(); diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index d652cb16da9f..27c386838bbe 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnInit, output } from '@angular/core'; import { TextEditorService } from 'app/exercises/text/participate/text-editor.service'; import { Subject } from 'rxjs'; import { TextSubmission } from 'app/entities/text/text-submission.model'; @@ -27,7 +27,7 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme @Input() exercise: Exercise; - @Output() saveCurrentExercise = new EventEmitter(); + saveCurrentExercise = output(); readonly IncludedInOverallScore = IncludedInOverallScore; readonly maxCharacterCount = MAX_SUBMISSION_TEXT_LENGTH; From 76398236ef1d45993106fe43581cd4bd1da4cc45 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Wed, 23 Oct 2024 16:06:33 +0200 Subject: [PATCH 06/18] Add sync input, add comments --- .../exam/participate/exam-participation.component.html | 1 + .../exercise-save-button.component.ts | 7 +++---- .../modeling/modeling-exam-submission.component.ts | 8 +++++++- .../exercises/quiz/quiz-exam-submission.component.ts | 3 +++ .../exercises/text/text-exam-submission.component.ts | 3 +++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.html b/src/main/webapp/app/exam/participate/exam-participation.component.html index a62faf6b3892..3beb602b88b3 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.html +++ b/src/main/webapp/app/exam/participate/exam-participation.component.html @@ -79,6 +79,7 @@ } diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index c465e2f404a3..6c8311173c73 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -12,13 +12,12 @@ import { Submission } from 'app/entities/submission.model'; imports: [FaIconComponent], }) export class ExerciseSaveButtonComponent { - submission = input(); - save = output(); - - //Icons protected readonly faFloppyDisk = faFloppyDisk; protected readonly facSaveSuccess = facSaveSuccess; + submission = input(); + save = output(); + onSave() { this.save.emit(); } diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index 403c82f00f42..fca9a9e74baf 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild, output } from '@angular/core'; +import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, ViewChild, input, output } from '@angular/core'; import { UMLModel } from '@ls1intum/apollon'; import dayjs from 'dayjs/esm'; import { ModelingSubmission } from 'app/entities/modeling-submission.model'; @@ -34,6 +34,9 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp exercise: ModelingExercise; umlModel: UMLModel; // input model for Apollon+ + // explicitly needed to track if submission.isSynced is changed, otherwise component + // does not update the state due to onPush strategy + isSubmissionSynced = input(); saveCurrentExercise = output(); explanationText: string; // current explanation text @@ -157,6 +160,9 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp } } + /** + * Trigger save action in exam participation component + */ notifyTriggerSave() { this.saveCurrentExercise.emit(); } diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts index 30186e5c8272..26aa88a762d5 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.ts @@ -288,6 +288,9 @@ export class QuizExamSubmissionComponent extends ExamSubmissionComponent impleme this.updateViewFromSubmissionVersion(); } + /** + * Trigger save action in exam participation component + */ notifyTriggerSave() { this.saveCurrentExercise.emit(); } diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index 27c386838bbe..9d6ded4726e5 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -128,6 +128,9 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme this.updateViewFromSubmissionVersion(); } + /** + * Trigger save action in exam participation component + */ notifyTriggerSave() { this.saveCurrentExercise.emit(); } From a3ccb125427fc52571cfa735fb8185fd74662e34 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Wed, 23 Oct 2024 18:24:30 +0200 Subject: [PATCH 07/18] Add button to tests --- .../exercises/text/text-exam-submission.component.ts | 4 ---- .../exercises/modeling-exam-submission.component.spec.ts | 2 ++ .../exercises/quiz-exam-submission.component.spec.ts | 2 ++ .../exercises/text-exam-submission.component.spec.ts | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index 9d6ded4726e5..308649636e39 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -10,7 +10,6 @@ import { faListAlt } from '@fortawesome/free-solid-svg-icons'; import { MAX_SUBMISSION_TEXT_LENGTH } from 'app/shared/constants/input.constants'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { htmlForMarkdown } from 'app/shared/util/markdown.conversion.util'; -import { ExamParticipationService } from '../../exam-participation.service'; @Component({ selector: 'jhi-text-editor-exam', @@ -36,7 +35,6 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme answer: string; problemStatementHtml: string; private textEditorInput = new Subject(); - submission?: Submission; // Icons readonly farListAlt = faListAlt; @@ -44,7 +42,6 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme constructor( private textService: TextEditorService, private stringCountService: StringCountService, - private examParticipationService: ExamParticipationService, changeDetectorReference: ChangeDetectorRef, ) { super(changeDetectorReference); @@ -54,7 +51,6 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme // show submission answers in UI this.problemStatementHtml = htmlForMarkdown(this.exercise?.problemStatement); this.updateViewFromSubmission(); - this.submission = ExamParticipationService.getSubmissionForExercise(this.exercise); } getExerciseId(): number | undefined { diff --git a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts index 60731362866e..2b5af18600a6 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts @@ -17,6 +17,7 @@ import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-hea import { ExamExerciseUpdateHighlighterComponent } from 'app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; import { NgbTooltipMocksModule } from '../../../../helpers/mocks/directive/ngbTooltipMocks.module'; import { SubmissionVersion } from 'app/entities/submission-version.model'; +import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; describe('ModelingExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -49,6 +50,7 @@ describe('ModelingExamSubmissionComponent', () => { MockPipe(HtmlForMarkdownPipe, (markdown) => markdown as SafeHtml), MockComponent(IncludedInScoreBadgeComponent), MockComponent(ExamExerciseUpdateHighlighterComponent), + MockComponent(ExerciseSaveButtonComponent), ], providers: [MockProvider(ChangeDetectorRef)], }) diff --git a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts index c83015c99c75..6801cce7067a 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts @@ -25,6 +25,7 @@ import { ModelingSubmission } from 'app/entities/modeling-submission.model'; import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { Course } from 'app/entities/course.model'; import { provideRouter } from '@angular/router'; +import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; describe('QuizExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -55,6 +56,7 @@ describe('QuizExamSubmissionComponent', () => { MockComponent(MultipleChoiceQuestionComponent), MockComponent(DragAndDropQuestionComponent), MockComponent(ShortAnswerQuestionComponent), + MockComponent(ExerciseSaveButtonComponent), ], providers: [provideRouter([]), MockProvider(ArtemisQuizService)], }) diff --git a/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts index 176692131b10..7ad01b0bd71b 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts @@ -17,6 +17,7 @@ import { ArtemisTestModule } from '../../../../test.module'; import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; import dayjs from 'dayjs/esm'; import { TranslateDirective } from 'app/shared/language/translate.directive'; +import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; describe('TextExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -39,6 +40,7 @@ describe('TextExamSubmissionComponent', () => { MockComponent(IncludedInScoreBadgeComponent), MockComponent(ExamExerciseUpdateHighlighterComponent), MockComponent(ResizeableContainerComponent), + MockComponent(ExerciseSaveButtonComponent), MockDirective(TranslateDirective), ], providers: [MockProvider(TextEditorService), MockProvider(ArtemisMarkdownService)], From 6346a13697c79b5b3110780b51258c047b281209 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 24 Oct 2024 02:50:48 +0200 Subject: [PATCH 08/18] Fix e2e exam test --- src/test/playwright/e2e/exam/ExamDateVerification.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts b/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts index 48d80de67065..7bd52b266ca7 100644 --- a/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts +++ b/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts @@ -92,7 +92,7 @@ test.describe('Exam date verification', () => { await examNavigation.openOrSaveExerciseByTitle(exercise.exerciseGroup!.title!); await page.hover('.fa-save-success'); - await expect(page.getByText('Exercise saved')).toBeVisible(); + await expect(page.getByText('Exercise saved', { exact: true })).toBeVisible(); }); test('Exam ends after end time', async ({ page, login, examAPIRequests, exerciseAPIRequests, examStartEnd, examNavigation, textExerciseEditor, examParticipation }) => { From e081979996006335044c3c018ae8316c6bf33721 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 24 Oct 2024 03:15:26 +0200 Subject: [PATCH 09/18] Add translation to the button, remove margins --- .../exercise-save-button.component.html | 6 ++++-- .../exercise-save-button/exercise-save-button.component.ts | 3 ++- .../modeling/modeling-exam-submission.component.html | 2 +- .../exercises/quiz/quiz-exam-submission.component.html | 2 +- .../exercises/text/text-exam-submission.component.html | 2 +- src/main/webapp/i18n/de/exam.json | 4 +++- src/main/webapp/i18n/en/exam.json | 4 +++- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html index 53a5972269c7..8ec143ed83ee 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.html @@ -1,6 +1,8 @@ diff --git a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts index 6c8311173c73..01e627a6941f 100644 --- a/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component.ts @@ -3,13 +3,14 @@ import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons'; import { facSaveSuccess } from '../../../../../content/icons/icons'; import { Submission } from 'app/entities/submission.model'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-exercise-save-button', templateUrl: './exercise-save-button.component.html', styleUrls: ['./exercise-save-button.component.scss'], standalone: true, - imports: [FaIconComponent], + imports: [FaIconComponent, TranslateDirective], }) export class ExerciseSaveButtonComponent { protected readonly faFloppyDisk = faFloppyDisk; diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html index 811cc4c00ad4..5a1a9ac894c3 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html @@ -1,6 +1,6 @@ @if (exercise) {
-

+

{{ exercise.exerciseGroup?.title }} diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html index a097a94b0816..3cc63e8f99fa 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html @@ -1,5 +1,5 @@
-

+

{{ quizConfiguration.exerciseGroup?.title }} diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index 49d4e9ad88a0..62568880d38c 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -1,6 +1,6 @@ @if (exercise) {
-

+

{{ exercise.exerciseGroup?.title }} diff --git a/src/main/webapp/i18n/de/exam.json b/src/main/webapp/i18n/de/exam.json index bea5f259ab2a..ea6f80fbbb6a 100644 --- a/src/main/webapp/i18n/de/exam.json +++ b/src/main/webapp/i18n/de/exam.json @@ -336,7 +336,9 @@ "noActionRequired": "Artemis erfordert keine weitere Aktion, das Fenster kann geschlossen werden.", "followExamProtocol": "Halte dich an die Klausuranweisungen deiner Lehrenden.", "button": "Zusammenfassung der Klausur anzeigen{{ countdown }}" - } + }, + "saveExercise": "Aufgabe speichern", + "exerciseSaved": "Aufgabe gespeichert" }, "exerciseGroup": { "created": "Neue Aufgabengruppe erstellt", diff --git a/src/main/webapp/i18n/en/exam.json b/src/main/webapp/i18n/en/exam.json index cb75f38dece0..2925d7904cfa 100644 --- a/src/main/webapp/i18n/en/exam.json +++ b/src/main/webapp/i18n/en/exam.json @@ -337,7 +337,9 @@ "noActionRequired": "Artemis does not require any further action and this window can be closed.", "followExamProtocol": "Be sure to follow your instructor's exam protocol.", "button": "Show exam summary{{countdown}}" - } + }, + "saveExercise": "Save Exercise", + "exerciseSaved": "Exercise Saved" }, "exerciseGroup": { "created": "New exercise group created", From 07f3af65f4c12d6765527df2228e0e54fde35120 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 24 Oct 2024 03:20:08 +0200 Subject: [PATCH 10/18] Use upper case --- src/main/webapp/i18n/de/exam.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/i18n/de/exam.json b/src/main/webapp/i18n/de/exam.json index ea6f80fbbb6a..e6c95fd28256 100644 --- a/src/main/webapp/i18n/de/exam.json +++ b/src/main/webapp/i18n/de/exam.json @@ -337,8 +337,8 @@ "followExamProtocol": "Halte dich an die Klausuranweisungen deiner Lehrenden.", "button": "Zusammenfassung der Klausur anzeigen{{ countdown }}" }, - "saveExercise": "Aufgabe speichern", - "exerciseSaved": "Aufgabe gespeichert" + "saveExercise": "Aufgabe Speichern", + "exerciseSaved": "Aufgabe Gespeichert" }, "exerciseGroup": { "created": "Neue Aufgabengruppe erstellt", From 8bf0bb7666e855fbc6b191910dc52be5389e8bd5 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 24 Oct 2024 14:38:11 +0200 Subject: [PATCH 11/18] avoid non-null assertions, make icons protected --- .../exam-participation.component.html | 72 ++++++++++--------- .../modeling-exam-submission.component.html | 2 +- .../modeling-exam-submission.component.ts | 2 +- .../text/text-exam-submission.component.html | 2 +- .../text/text-exam-submission.component.ts | 2 +- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.html b/src/main/webapp/app/exam/participate/exam-participation.component.html index 3beb602b88b3..109383351e90 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.html +++ b/src/main/webapp/app/exam/participate/exam-participation.component.html @@ -54,41 +54,43 @@ @if (exercise && exercise.studentParticipations && exercise.studentParticipations[0]) { @if (pageComponentVisited[i]) {
- @switch (exercise.type) { - @case (QUIZ) { - - } - @case (FILEUPLOAD) { - - } - @case (TEXT) { - - } - @case (MODELING) { - - } - @case (PROGRAMMING) { - + @if (exercise.studentParticipations[0] && exercise.studentParticipations[0].submissions) { + @switch (exercise.type) { + @case (QUIZ) { + + } + @case (FILEUPLOAD) { + + } + @case (TEXT) { + + } + @case (MODELING) { + + } + @case (PROGRAMMING) { + + } } }
diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html index 5a1a9ac894c3..a484609de631 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html @@ -41,7 +41,7 @@

-   +   diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts index fca9a9e74baf..d16f4d56ff6d 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.ts @@ -44,7 +44,7 @@ export class ModelingExamSubmissionComponent extends ExamSubmissionComponent imp readonly IncludedInOverallScore = IncludedInOverallScore; // Icons - farListAlt = faListAlt; + protected readonly faListAlt = faListAlt; constructor(changeDetectorReference: ChangeDetectorRef) { super(changeDetectorReference); diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index 62568880d38c..2d733c7c4403 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -43,7 +43,7 @@

-   +   diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts index 308649636e39..cb2dc3c0fd51 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.ts @@ -37,7 +37,7 @@ export class TextExamSubmissionComponent extends ExamSubmissionComponent impleme private textEditorInput = new Subject(); // Icons - readonly farListAlt = faListAlt; + protected readonly faListAlt = faListAlt; constructor( private textService: TextEditorService, From 49a4628860271d3bea99e34f4ed131be76bfe05c Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Thu, 24 Oct 2024 14:45:35 +0200 Subject: [PATCH 12/18] split if statements --- .../exam-participation.component.html | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exam-participation.component.html b/src/main/webapp/app/exam/participate/exam-participation.component.html index 109383351e90..e90b28528020 100644 --- a/src/main/webapp/app/exam/participate/exam-participation.component.html +++ b/src/main/webapp/app/exam/participate/exam-participation.component.html @@ -54,29 +54,35 @@ @if (exercise && exercise.studentParticipations && exercise.studentParticipations[0]) { @if (pageComponentVisited[i]) {
- @if (exercise.studentParticipations[0] && exercise.studentParticipations[0].submissions) { - @switch (exercise.type) { - @case (QUIZ) { + @switch (exercise.type) { + @case (QUIZ) { + @if (exercise.studentParticipations[0].submissions) { } - @case (FILEUPLOAD) { + } + @case (FILEUPLOAD) { + @if (exercise.studentParticipations[0].submissions) { } - @case (TEXT) { + } + @case (TEXT) { + @if (exercise.studentParticipations[0].submissions) { } - @case (MODELING) { + } + @case (MODELING) { + @if (exercise.studentParticipations[0].submissions) { } - @case (PROGRAMMING) { - - } + } + @case (PROGRAMMING) { + } }
From 1f76446804cc48b0cf8040ee07180467f849d768 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Fri, 25 Oct 2024 14:29:37 +0200 Subject: [PATCH 13/18] Integrate feedback --- .../file-upload-exam-submission.component.html | 16 ++++++++-------- .../modeling-exam-submission.component.html | 16 ++++++++-------- .../programming-exam-submission.component.html | 16 ++++++++-------- .../quiz/quiz-exam-submission.component.html | 10 ++++------ .../text/text-exam-submission.component.html | 16 ++++++++-------- src/main/webapp/i18n/de/exam.json | 8 ++++---- src/main/webapp/i18n/en/exam.json | 8 ++++---- 7 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html index be860bc79852..e85e710164e9 100644 --- a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html @@ -3,14 +3,14 @@

{{ exercise.exerciseGroup?.title }} - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} - }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } + + + @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + }


diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html index a484609de631..d1e89ff3f1ea 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html @@ -4,14 +4,14 @@

{{ exercise.exerciseGroup?.title }} - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} - }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } + + + @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + }

diff --git a/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.html index 2bb8078c07ce..35129261f2ec 100644 --- a/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/programming/programming-exam-submission.component.html @@ -2,14 +2,14 @@

{{ exercise.exerciseGroup?.title }} - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} - }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } + + + @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + }


diff --git a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html index 3cc63e8f99fa..3bbe2afbdfe3 100644 --- a/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/quiz/quiz-exam-submission.component.html @@ -3,12 +3,10 @@

{{ quizConfiguration.exerciseGroup?.title }} - ({{ quizConfiguration.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}) - @if (quizConfiguration.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } - + + @if (quizConfiguration.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + }

diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index 2d733c7c4403..4087130be3ea 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -4,14 +4,14 @@

{{ exercise.exerciseGroup?.title }} - -  ({{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}@if (exercise.bonusPoints) { - , {{ exercise.bonusPoints }} {{ 'artemisApp.examParticipation.bonus' | artemisTranslate }} - }) @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { - - } + + + @if (exercise.includedInOverallScore !== IncludedInOverallScore.INCLUDED_COMPLETELY) { + + }

diff --git a/src/main/webapp/i18n/de/exam.json b/src/main/webapp/i18n/de/exam.json index ec0e7c1ebbf8..34cea3d9900d 100644 --- a/src/main/webapp/i18n/de/exam.json +++ b/src/main/webapp/i18n/de/exam.json @@ -314,8 +314,8 @@ "preparingParticipation": "Aufgabe wird vorbereitet. Dies kann ein paar Sekunden dauern.", "generateParticipationFailed": "Das Vorbereiten der Aufgabe ist fehlgeschlagen.", "generateParticipationRetry": "Erneut versuchen", - "points": "Punkte", - "bonus": "Bonuspunkte", + "points": "({{ points }} Punkte)", + "bonus": "({{ points }} Punkte, {{ bonusPoints }} Bonuspunkte)", "synced": "Aufgabe gespeichert", "notSynced": "Aufgabe nicht gespeichert", "notStarted": "Aufgabe nicht gestartet", @@ -339,8 +339,8 @@ "followExamProtocol": "Halte dich an die Klausuranweisungen deiner Lehrenden.", "button": "Zusammenfassung der Klausur anzeigen{{ countdown }}" }, - "saveExercise": "Aufgabe Speichern", - "exerciseSaved": "Aufgabe Gespeichert" + "saveExercise": "Aufgabe speichern", + "exerciseSaved": "Aufgabe gespeichert" }, "exerciseGroup": { "created": "Neue Aufgabengruppe erstellt", diff --git a/src/main/webapp/i18n/en/exam.json b/src/main/webapp/i18n/en/exam.json index 46b96252d0e3..374506d757af 100644 --- a/src/main/webapp/i18n/en/exam.json +++ b/src/main/webapp/i18n/en/exam.json @@ -314,8 +314,8 @@ "preparingParticipation": "Preparing exercise. This may take a few seconds.", "generateParticipationFailed": "The preparation of the exercise failed.", "generateParticipationRetry": "Retry", - "points": "Points", - "bonus": "Bonus Points", + "points": "({{ points }} Points)", + "bonus": "({{ points }} Points, {{ bonusPoints }} Bonus Points)", "synced": "Exercise saved", "notSynced": "Exercise not saved", "notStarted": "Exercise not started", @@ -339,8 +339,8 @@ "followExamProtocol": "Be sure to follow your instructor's exam protocol.", "button": "Show exam summary{{countdown}}" }, - "saveExercise": "Save Exercise", - "exerciseSaved": "Exercise Saved" + "saveExercise": "Save exercise", + "exerciseSaved": "Exercise saved" }, "exerciseGroup": { "created": "New exercise group created", From 3c762562088a07cb26b8399dc6292c953cae4b5d Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Fri, 25 Oct 2024 16:30:18 +0200 Subject: [PATCH 14/18] Fix client tests --- ...e-upload-exam-submission.component.spec.ts | 22 ++++++++++++++----- ...modeling-exam-submission.component.spec.ts | 18 ++++++++++----- .../quiz-exam-submission.component.spec.ts | 4 +++- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts index 9c10ec5ca996..90a35bd8a76b 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts @@ -6,7 +6,7 @@ import { Course } from 'app/entities/course.model'; import { FullscreenComponent } from 'app/shared/fullscreen/fullscreen.component'; import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; -import { MockComponent, MockPipe, MockProvider } from 'ng-mocks'; +import { MockComponent, MockDirective, MockPipe, MockProvider } from 'ng-mocks'; import { MockTranslateService, TranslatePipeMock } from '../../../../helpers/mocks/service/mock-translate.service'; import { ArtemisTestModule } from '../../../../test.module'; import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; @@ -22,6 +22,7 @@ import { FileUploadSubmissionService } from 'app/exercises/file-upload/participa import { HttpResponse } from '@angular/common/http'; import { of } from 'rxjs'; import { ExamExerciseUpdateHighlighterComponent } from 'app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; +import { TranslateDirective } from '../../../../../../../main/webapp/app/shared/language/translate.directive'; describe('FileUploadExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -52,10 +53,11 @@ describe('FileUploadExamSubmissionComponent', () => { FileUploadExamSubmissionComponent, FullscreenComponent, ResizeableContainerComponent, - TranslatePipeMock, MockPipe(HtmlForMarkdownPipe, (markdown) => markdown as SafeHtml), + TranslatePipeMock, MockComponent(IncludedInScoreBadgeComponent), MockComponent(ExamExerciseUpdateHighlighterComponent), + MockDirective(TranslateDirective), ], providers: [MockProvider(ChangeDetectorRef), { provide: TranslateService, useClass: MockTranslateService }], }) @@ -78,6 +80,7 @@ describe('FileUploadExamSubmissionComponent', () => { }); it('should show static text in header', () => { + comp.examTimeline = false; fixture.detectChanges(); const el = fixture.debugElement.query((de) => de.nativeElement.textContent === 'artemisApp.exam.yourSolution'); expect(el).not.toBeNull(); @@ -87,8 +90,12 @@ describe('FileUploadExamSubmissionComponent', () => { const maxScore = 30; comp.exercise.maxPoints = maxScore; fixture.detectChanges(); - const el = fixture.debugElement.query((de) => de.nativeElement.textContent.includes(`(${maxScore} artemisApp.examParticipation.points)`)); + const el = fixture.debugElement.query(By.directive(TranslateDirective)); expect(el).not.toBeNull(); + + const directiveInstance = el.injector.get(TranslateDirective); + expect(directiveInstance.jhiTranslate).toBe('artemisApp.examParticipation.points'); + expect(directiveInstance.translateValues).toEqual({ points: maxScore, bonusPoints: 0 }); }); it('should show exercise bonus score if any', () => { @@ -97,11 +104,14 @@ describe('FileUploadExamSubmissionComponent', () => { const bonusPoints = 55; comp.exercise.bonusPoints = bonusPoints; fixture.detectChanges(); - const el = fixture.debugElement.query((de) => - de.nativeElement.textContent.includes(`(${maxScore} artemisApp.examParticipation.points, ${bonusPoints} artemisApp.examParticipation.bonus)`), - ); + const el = fixture.debugElement.query(By.directive(TranslateDirective)); expect(el).not.toBeNull(); + + const directiveInstance = el.injector.get(TranslateDirective); + expect(directiveInstance.jhiTranslate).toBe('artemisApp.examParticipation.bonus'); + expect(directiveInstance.translateValues).toEqual({ points: maxScore, bonusPoints: bonusPoints }); }); + it('should show problem statement if there is any', () => { fixture.detectChanges(); const el = fixture.debugElement.query((de) => de.nativeElement.textContent === mockExercise.problemStatement); diff --git a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts index 2b5af18600a6..00bf29cf60e3 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts @@ -10,7 +10,7 @@ import { ModelingEditorComponent } from 'app/exercises/modeling/shared/modeling- import { FullscreenComponent } from 'app/shared/fullscreen/fullscreen.component'; import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; import { ResizeableContainerComponent } from 'app/shared/resizeable-container/resizeable-container.component'; -import { MockComponent, MockPipe, MockProvider } from 'ng-mocks'; +import { MockComponent, MockDirective, MockPipe, MockProvider } from 'ng-mocks'; import { TranslatePipeMock } from '../../../../helpers/mocks/service/mock-translate.service'; import { ArtemisTestModule } from '../../../../test.module'; import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; @@ -18,6 +18,7 @@ import { ExamExerciseUpdateHighlighterComponent } from 'app/exam/participate/exe import { NgbTooltipMocksModule } from '../../../../helpers/mocks/directive/ngbTooltipMocks.module'; import { SubmissionVersion } from 'app/entities/submission-version.model'; import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; +import { TranslateDirective } from '../../../../../../../main/webapp/app/shared/language/translate.directive'; describe('ModelingExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -51,6 +52,7 @@ describe('ModelingExamSubmissionComponent', () => { MockComponent(IncludedInScoreBadgeComponent), MockComponent(ExamExerciseUpdateHighlighterComponent), MockComponent(ExerciseSaveButtonComponent), + MockDirective(TranslateDirective), ], providers: [MockProvider(ChangeDetectorRef)], }) @@ -80,8 +82,12 @@ describe('ModelingExamSubmissionComponent', () => { const maxScore = 30; comp.exercise.maxPoints = maxScore; fixture.detectChanges(); - const el = fixture.debugElement.query((de) => de.nativeElement.textContent.includes(`(${maxScore} artemisApp.examParticipation.points)`)); + const el = fixture.debugElement.query(By.directive(TranslateDirective)); expect(el).not.toBeNull(); + + const directiveInstance = el.injector.get(TranslateDirective); + expect(directiveInstance.jhiTranslate).toBe('artemisApp.examParticipation.points'); + expect(directiveInstance.translateValues).toEqual({ points: maxScore, bonusPoints: 0 }); }); it('should show exercise bonus score if any', () => { @@ -90,10 +96,12 @@ describe('ModelingExamSubmissionComponent', () => { const bonusPoints = 55; comp.exercise.bonusPoints = bonusPoints; fixture.detectChanges(); - const el = fixture.debugElement.query((de) => - de.nativeElement.textContent.includes(`(${maxScore} artemisApp.examParticipation.points, ${bonusPoints} artemisApp.examParticipation.bonus)`), - ); + const el = fixture.debugElement.query(By.directive(TranslateDirective)); expect(el).not.toBeNull(); + + const directiveInstance = el.injector.get(TranslateDirective); + expect(directiveInstance.jhiTranslate).toBe('artemisApp.examParticipation.bonus'); + expect(directiveInstance.translateValues).toEqual({ points: maxScore, bonusPoints: bonusPoints }); }); it('should show modeling editor with correct props when there is submission and exercise', () => { diff --git a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts index 6801cce7067a..ac8c219a3743 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts @@ -15,7 +15,7 @@ import { QuizExamSubmissionComponent } from 'app/exam/participate/exercises/quiz import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; import { ArtemisQuizService } from 'app/shared/quiz/quiz.service'; -import { MockComponent, MockPipe, MockProvider } from 'ng-mocks'; +import { MockComponent, MockDirective, MockPipe, MockProvider } from 'ng-mocks'; import { MultipleChoiceQuestionComponent } from 'app/exercises/quiz/shared/questions/multiple-choice-question/multiple-choice-question.component'; import { DragAndDropQuestionComponent } from 'app/exercises/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component'; import { ShortAnswerQuestionComponent } from 'app/exercises/quiz/shared/questions/short-answer-question/short-answer-question.component'; @@ -26,6 +26,7 @@ import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model'; import { Course } from 'app/entities/course.model'; import { provideRouter } from '@angular/router'; import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; +import { TranslateDirective } from '../../../../../../../main/webapp/app/shared/language/translate.directive'; describe('QuizExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -57,6 +58,7 @@ describe('QuizExamSubmissionComponent', () => { MockComponent(DragAndDropQuestionComponent), MockComponent(ShortAnswerQuestionComponent), MockComponent(ExerciseSaveButtonComponent), + MockDirective(TranslateDirective), ], providers: [provideRouter([]), MockProvider(ArtemisQuizService)], }) From 29f82032b69536ddc81d25c2dadad02189e5f095 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Fri, 25 Oct 2024 17:36:50 +0200 Subject: [PATCH 15/18] Fix e2e test --- .../exam-result-summary-exercise-card-header.component.html | 4 ++-- src/test/playwright/e2e/exam/ExamDateVerification.spec.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html index 74dfce8f5638..4c9d11e7aab6 100644 --- a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html +++ b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html @@ -11,7 +11,7 @@
@if (resultsPublished && exerciseInfo?.achievedPoints !== undefined) {
- [{{ exerciseInfo?.achievedPoints }} / {{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}] + [{{ exerciseInfo?.achievedPoints }} / {{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.exercisePoints' | artemisTranslate }}]
@if (exerciseInfo?.resultIconClass) { @@ -22,7 +22,7 @@
} @else { - [{{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.points' | artemisTranslate }}] + [{{ exercise.maxPoints }} {{ 'artemisApp.examParticipation.exercisePoints' | artemisTranslate }}] }
diff --git a/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts b/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts index 7bd52b266ca7..40981da6f03f 100644 --- a/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts +++ b/src/test/playwright/e2e/exam/ExamDateVerification.spec.ts @@ -92,7 +92,8 @@ test.describe('Exam date verification', () => { await examNavigation.openOrSaveExerciseByTitle(exercise.exerciseGroup!.title!); await page.hover('.fa-save-success'); - await expect(page.getByText('Exercise saved', { exact: true })).toBeVisible(); + // nth(0) is the button, nth(1) is the ngtooltip, which is tested + await expect(page.getByText('Exercise saved').nth(1)).toBeVisible(); }); test('Exam ends after end time', async ({ page, login, examAPIRequests, exerciseAPIRequests, examStartEnd, examNavigation, textExerciseEditor, examParticipation }) => { From 44221f99a9e937bd662c9ee590c624d26e75e32c Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Fri, 25 Oct 2024 19:23:05 +0200 Subject: [PATCH 16/18] increase coverage --- .../exercise-save-button.component.spec.ts | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts diff --git a/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts new file mode 100644 index 000000000000..b379634317b3 --- /dev/null +++ b/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts @@ -0,0 +1,95 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateService } from '@ngx-translate/core'; +import { input } from '@angular/core'; +import { MockPipe } from 'ng-mocks'; +import { MockTranslateService } from '../../../../helpers/mocks/service/mock-translate.service'; +import { ArtemisTestModule } from '../../../../test.module'; +import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; +import { By } from '@angular/platform-browser'; +import { ExerciseSaveButtonComponent } from '../../../../../../../main/webapp/app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; +import { Submission } from '../../../../../../../main/webapp/app/entities/submission.model'; +import { facSaveSuccess } from '../../../../../../../main/webapp/content/icons/icons'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons'; + +describe('ExerciseSaveButtonComponent', () => { + let component: ExerciseSaveButtonComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ArtemisTestModule], + declarations: [ExerciseSaveButtonComponent, MockPipe(ArtemisTranslatePipe)], + providers: [{ provide: TranslateService, useClass: MockTranslateService }], + }) + .compileComponents() + .then(() => { + fixture = TestBed.createComponent(ExerciseSaveButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('should disable the button if submission is synced', () => { + TestBed.runInInjectionContext(() => { + component.submission = input({ isSynced: true, submitted: false } as Submission); + }); + + fixture.detectChanges(); + + const button = fixture.debugElement.query(By.css('#save-exam')); + expect(button.nativeElement.disabled).toBeTrue(); + }); + + it('should enable the button if submission is not synced', () => { + TestBed.runInInjectionContext(() => { + component.submission = input({ isSynced: false, submitted: false } as Submission); + }); + fixture.detectChanges(); + + const button = fixture.debugElement.query(By.css('#save-exam')); + expect(button.nativeElement.disabled).toBeFalse(); + }); + + it('should display facSaveSuccess icon if submission is synced and submitted', () => { + TestBed.runInInjectionContext(() => { + component.submission = input({ isSynced: true, submitted: true } as Submission); + }); + fixture.detectChanges(); + + const icon = fixture.debugElement.query(By.directive(FaIconComponent)); + expect(icon.componentInstance.icon).toBe(facSaveSuccess); + }); + + it('should display faFloppyDisk icon if submission is not synced and submitted', () => { + TestBed.runInInjectionContext(() => { + component.submission = input({ isSynced: false, submitted: false } as Submission); + }); + fixture.detectChanges(); + + const icon = fixture.debugElement.query(By.directive(FaIconComponent)); + expect(icon.componentInstance.icon).toBe(faFloppyDisk); + }); + + it('should emit call onSave when the button is clicked and submission is not synced', () => { + TestBed.runInInjectionContext(() => { + component.submission = input({ isSynced: false, submitted: false } as Submission); + }); + fixture.detectChanges(); + + const onSaveSpy = jest.spyOn(component, 'onSave'); + + const button = fixture.debugElement.query(By.css('#save-exam')); + button.nativeElement.click(); + + expect(onSaveSpy).toHaveBeenCalled(); + }); +}); From 672260615aefc6f7ac0dad96cab692f72504bca2 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Sat, 26 Oct 2024 18:20:17 +0200 Subject: [PATCH 17/18] increase test coverage --- .../exercise-save-button.component.spec.ts | 2 +- .../quiz-exam-submission.component.spec.ts | 18 ++++++++++++++++++ .../text-exam-submission.component.spec.ts | 11 +++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts index b379634317b3..c99743924bb6 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/exercise-save-button.component.spec.ts @@ -79,7 +79,7 @@ describe('ExerciseSaveButtonComponent', () => { expect(icon.componentInstance.icon).toBe(faFloppyDisk); }); - it('should emit call onSave when the button is clicked and submission is not synced', () => { + it('should call onSave when the button is clicked and submission is not synced', () => { TestBed.runInInjectionContext(() => { component.submission = input({ isSynced: false, submitted: false } as Submission); }); diff --git a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts index ac8c219a3743..e3e9c1a94556 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/quiz-exam-submission.component.spec.ts @@ -27,6 +27,7 @@ import { Course } from 'app/entities/course.model'; import { provideRouter } from '@angular/router'; import { ExerciseSaveButtonComponent } from 'app/exam/participate/exercises/exercise-save-button/exercise-save-button.component'; import { TranslateDirective } from '../../../../../../../main/webapp/app/shared/language/translate.directive'; +import { By } from '@angular/platform-browser'; describe('QuizExamSubmissionComponent', () => { let fixture: ComponentFixture; @@ -215,4 +216,21 @@ describe('QuizExamSubmissionComponent', () => { expect(component.dragAndDropMappings.size).toBe(1); expect(component.shortAnswerSubmittedTexts.size).toBe(0); }); + + it('should call triggerSave if save exercise button is clicked', () => { + const submissionVersion = { + content: + '[ {\r\n "quizQuestion" : {\r\n "type" : "drag-and-drop",\r\n "id" : 2,\r\n "title" : "dnd image",\r\n "text" : "Enter your long question if needed",\r\n "hint" : "Add a hint here (visible during the quiz via ?-Button)",\r\n "points" : 1,\r\n "scoringType" : "PROPORTIONAL_WITH_PENALTY",\r\n "randomizeOrder" : true,\r\n "invalid" : false,\r\n "backgroundFilePath" : "/api/files/drag-and-drop/backgrounds/14/DragAndDropBackground_2023-07-08T19-35-26-953_a3265da6.jpg",\r\n "dropLocations" : [ {\r\n "id" : 12,\r\n "posX" : 45.0,\r\n "posY" : 120.0,\r\n "width" : 62.0,\r\n "height" : 52.0,\r\n "invalid" : false\r\n } ],\r\n "dragItems" : [ {\r\n "id" : 11,\r\n "pictureFilePath" : "/api/files/drag-and-drop/drag-items/11/DragItem_2023-07-08T19-35-26-956_2ffe94ba.jpg",\r\n "invalid" : false\r\n } ]\r\n },\r\n "mappings" : [ {\r\n "invalid" : false,\r\n "dragItem" : {\r\n "id" : 11,\r\n "pictureFilePath" : "/api/files/drag-and-drop/drag-items/11/DragItem_2023-07-08T19-35-26-956_2ffe94ba.jpg",\r\n "invalid" : false\r\n },\r\n "dropLocation" : {\r\n "id" : 12,\r\n "posX" : 45.0,\r\n "posY" : 120.0,\r\n "width" : 62.0,\r\n "height" : 52.0,\r\n "invalid" : false\r\n }\r\n } ]\r\n} ]', + } as unknown as SubmissionVersion; + component.studentSubmission = new ModelingSubmission(); + component.exercise = new QuizExercise(new Course(), undefined); + component.exercise.quizQuestions = [dragAndDropQuestion]; + component.quizConfiguration = { quizQuestions: [dragAndDropQuestion] }; + component.setSubmissionVersion(submissionVersion); + fixture.detectChanges(); + const saveExerciseSpy = jest.spyOn(component, 'notifyTriggerSave'); + const saveButton = fixture.debugElement.query(By.directive(ExerciseSaveButtonComponent)); + saveButton.triggerEventHandler('save', null); + expect(saveExerciseSpy).toHaveBeenCalledOnce(); + }); }); diff --git a/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts index 7ad01b0bd71b..a0850296fc26 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/text-exam-submission.component.spec.ts @@ -142,4 +142,15 @@ describe('TextExamSubmissionComponent', () => { expect(component.answer).toBe('submission version'); expect(component.submissionVersion).toBe(submissionVersion); }); + + it('should call triggerSave if save exercise button is clicked', () => { + component.exercise = exercise; + textSubmission.text = 'Hello World'; + component.studentSubmission = textSubmission; + fixture.detectChanges(); + const saveExerciseSpy = jest.spyOn(component, 'notifyTriggerSave'); + const saveButton = fixture.debugElement.query(By.directive(ExerciseSaveButtonComponent)); + saveButton.triggerEventHandler('save', null); + expect(saveExerciseSpy).toHaveBeenCalledOnce(); + }); }); From f588a0016b18e966580e056d1ca0280bedc89380 Mon Sep 17 00:00:00 2001 From: EgeDoguKaya Date: Sat, 26 Oct 2024 18:23:31 +0200 Subject: [PATCH 18/18] add triggersave test to modeling test --- .../exercises/modeling-exam-submission.component.spec.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts index 00bf29cf60e3..5b2845a76b22 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts @@ -104,6 +104,14 @@ describe('ModelingExamSubmissionComponent', () => { expect(directiveInstance.translateValues).toEqual({ points: maxScore, bonusPoints: bonusPoints }); }); + it('should call triggerSave if save exercise button is clicked', () => { + fixture.detectChanges(); + const saveExerciseSpy = jest.spyOn(comp, 'notifyTriggerSave'); + const saveButton = fixture.debugElement.query(By.directive(ExerciseSaveButtonComponent)); + saveButton.triggerEventHandler('save', null); + expect(saveExerciseSpy).toHaveBeenCalledOnce(); + }); + it('should show modeling editor with correct props when there is submission and exercise', () => { fixture.detectChanges(); const modelingEditor = fixture.debugElement.query(By.directive(ModelingEditorComponent));