Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exam mode: Fix missing repository lock notifications #7297

Merged
merged 29 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
61396cf
`Exam mode`: Fix missing repository lock notifications
Strohgelaender Sep 29, 2023
68224e5
Merge branch 'develop' of https://github.com/ls1intum/Artemis into bu…
Strohgelaender Sep 29, 2023
60f43df
add own notification type for repository lock status updates
Strohgelaender Sep 29, 2023
f3d9ef1
Merge branch 'develop' of https://github.com/ls1intum/Artemis into bu…
Strohgelaender Sep 29, 2023
6db368e
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Oct 4, 2023
c66e0f1
Merge branch 'bugifx/exam-update-notification' of https://github.com/…
Strohgelaender Oct 8, 2023
962507c
Merge branch 'develop' of https://github.com/ls1intum/Artemis into bu…
Strohgelaender Oct 8, 2023
3339d84
add second notification type for build run updates
Strohgelaender Oct 8, 2023
ca17f2b
improve notification translations
Strohgelaender Oct 8, 2023
7a15ff0
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Oct 10, 2023
3a41fe3
Merge branch 'develop' of https://github.com/ls1intum/Artemis into bu…
Strohgelaender Oct 17, 2023
dbba38f
revert client changes
Strohgelaender Oct 17, 2023
be7dea4
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Oct 19, 2023
01f25f1
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Oct 21, 2023
3bff779
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Oct 24, 2023
2fb335b
merge
Strohgelaender Oct 29, 2023
ac22b53
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 4, 2023
f0e6357
merge
Strohgelaender Nov 5, 2023
fae248b
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 10, 2023
dca59b6
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 11, 2023
9b87555
Apply suggestions from code review
Strohgelaender Nov 13, 2023
adb82df
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 13, 2023
42dfee7
merge
Strohgelaender Nov 20, 2023
fb38131
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 21, 2023
5836763
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 24, 2023
741ebbe
fix notification capitalization
Strohgelaender Nov 24, 2023
47a5e2b
revert unintentional style change
Strohgelaender Nov 24, 2023
f57f554
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 27, 2023
12e2b18
Merge branch 'develop' into bugifx/exam-update-notification
Strohgelaender Nov 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public enum NotificationType {
TUTORIAL_GROUP_REGISTRATION_STUDENT, TUTORIAL_GROUP_DEREGISTRATION_STUDENT, TUTORIAL_GROUP_REGISTRATION_TUTOR, TUTORIAL_GROUP_MULTIPLE_REGISTRATION_TUTOR,
TUTORIAL_GROUP_DEREGISTRATION_TUTOR, TUTORIAL_GROUP_DELETED, TUTORIAL_GROUP_UPDATED, TUTORIAL_GROUP_ASSIGNED, TUTORIAL_GROUP_UNASSIGNED, CONVERSATION_NEW_MESSAGE,
CONVERSATION_NEW_REPLY_MESSAGE, CONVERSATION_USER_MENTIONED, CONVERSATION_CREATE_ONE_TO_ONE_CHAT, CONVERSATION_CREATE_GROUP_CHAT, CONVERSATION_ADD_USER_GROUP_CHAT,
CONVERSATION_ADD_USER_CHANNEL, CONVERSATION_REMOVE_USER_GROUP_CHAT, CONVERSATION_REMOVE_USER_CHANNEL, CONVERSATION_DELETE_CHANNEL, DATA_EXPORT_CREATED, DATA_EXPORT_FAILED
CONVERSATION_ADD_USER_CHANNEL, CONVERSATION_REMOVE_USER_GROUP_CHAT, CONVERSATION_REMOVE_USER_CHANNEL, CONVERSATION_DELETE_CHANNEL, DATA_EXPORT_CREATED, DATA_EXPORT_FAILED,
PROGRAMMING_REPOSITORY_LOCKS, PROGRAMMING_BUILD_RUN_UPDATE
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,66 +93,66 @@ public static GroupNotification createNotification(Exercise exercise, User autho
String title;
String text;
boolean textIsPlaceholder;
String[] placeholderValues;
String[] placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
NotificationPriority priority = MEDIUM;

switch (notificationType) {
case EXERCISE_RELEASED -> {
title = NotificationConstants.EXERCISE_RELEASED_TITLE;
text = NotificationConstants.EXERCISE_RELEASED_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
case EXERCISE_PRACTICE -> {
title = NotificationConstants.EXERCISE_PRACTICE_TITLE;
text = NotificationConstants.EXERCISE_PRACTICE_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
case QUIZ_EXERCISE_STARTED -> {
title = NotificationConstants.QUIZ_EXERCISE_STARTED_TITLE;
text = NotificationConstants.QUIZ_EXERCISE_STARTED_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
case EXERCISE_UPDATED -> {
if (exercise.isExamExercise()) {
title = NotificationConstants.LIVE_EXAM_EXERCISE_UPDATE_NOTIFICATION_TITLE;
text = NotificationConstants.LIVE_EXAM_EXERCISE_UPDATE_NOTIFICATION_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
else {
title = NotificationConstants.EXERCISE_UPDATED_TITLE;
text = NotificationConstants.EXERCISE_UPDATED_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
textIsPlaceholder = true;
}
case PROGRAMMING_TEST_CASES_CHANGED -> {
title = NotificationConstants.PROGRAMMING_TEST_CASES_CHANGED_TITLE;
text = NotificationConstants.PROGRAMMING_TEST_CASES_CHANGED_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
case NEW_MANUAL_FEEDBACK_REQUEST -> {
title = NotificationConstants.NEW_MANUAL_FEEDBACK_REQUEST_TITLE;
text = NotificationConstants.NEW_MANUAL_FEEDBACK_REQUEST_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
}
case DUPLICATE_TEST_CASE -> {
title = NotificationConstants.DUPLICATE_TEST_CASE_TITLE;
text = notificationText;
textIsPlaceholder = false;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle() };
priority = HIGH;
}
case PROGRAMMING_REPOSITORY_LOCKS -> {
title = NotificationConstants.PROGRAMMING_REPOSITORY_LOCKS_TITLE;
text = notificationText;
textIsPlaceholder = false;
}
case PROGRAMMING_BUILD_RUN_UPDATE -> {
title = NotificationConstants.PROGRAMMING_BUILD_RUN_UPDATE_TITLE;
text = notificationText;
textIsPlaceholder = false;
}
case ILLEGAL_SUBMISSION -> {
title = NotificationConstants.ILLEGAL_SUBMISSION_TITLE;
text = NotificationConstants.ILLEGAL_SUBMISSION_TEXT;
textIsPlaceholder = true;
placeholderValues = new String[] { exercise.getCourseViaExerciseGroupOrCourseMember().getTitle(), exercise.getTitle() };
priority = HIGH;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ public class NotificationConstants {

public static final String NEW_MANUAL_FEEDBACK_REQUEST_TITLE = "artemisApp.groupNotification.title.newManualFeedbackRequest";

public static final String PROGRAMMING_REPOSITORY_LOCKS_TITLE = "artemisApp.groupNotification.title.repositoryLocks";

public static final String PROGRAMMING_BUILD_RUN_UPDATE_TITLE = "artemisApp.groupNotification.title.buildRun";

public static final String NEW_PLAGIARISM_CASE_STUDENT_TITLE = "artemisApp.singleUserNotification.title.newPlagiarismCaseStudent";

public static final String NEW_CPC_PLAGIARISM_CASE_STUDENT_TITLE = "artemisApp.singleUserNotification.title.newPlagiarismCaseStudentSignificantSimilarity";
Expand Down Expand Up @@ -242,7 +246,8 @@ public class NotificationConstants {
.put(CONVERSATION_CREATE_GROUP_CHAT, CONVERSATION_CREATE_GROUP_CHAT_TITLE).put(CONVERSATION_ADD_USER_CHANNEL, CONVERSATION_ADD_USER_CHANNEL_TITLE)
.put(CONVERSATION_ADD_USER_GROUP_CHAT, CONVERSATION_ADD_USER_GROUP_CHAT_TITLE).put(CONVERSATION_REMOVE_USER_GROUP_CHAT, CONVERSATION_REMOVE_USER_GROUP_CHAT_TITLE)
.put(CONVERSATION_REMOVE_USER_CHANNEL, CONVERSATION_REMOVE_USER_CHANNEL_TITLE).put(CONVERSATION_DELETE_CHANNEL, CONVERSATION_DELETE_CHANNEL_TITLE)
.put(DATA_EXPORT_CREATED, DATA_EXPORT_CREATED_TITLE).put(DATA_EXPORT_FAILED, DATA_EXPORT_FAILED_TITLE).build();
.put(DATA_EXPORT_CREATED, DATA_EXPORT_CREATED_TITLE).put(DATA_EXPORT_FAILED, DATA_EXPORT_FAILED_TITLE)
.put(PROGRAMMING_REPOSITORY_LOCKS, PROGRAMMING_REPOSITORY_LOCKS_TITLE).put(PROGRAMMING_BUILD_RUN_UPDATE, PROGRAMMING_BUILD_RUN_UPDATE_TITLE).build();

/**
* Finds the corresponding NotificationType for the provided notification title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ private void notifyGroupsWithNotificationType(GroupNotificationType[] groups, No
case EXAM_ARCHIVE_STARTED, EXAM_ARCHIVE_FINISHED, EXAM_ARCHIVE_FAILED ->
createNotification((Exam) notificationSubject, author, group, notificationType, (List<String>) typeSpecificInformation);
// Critical Types
case DUPLICATE_TEST_CASE, ILLEGAL_SUBMISSION ->
case DUPLICATE_TEST_CASE, ILLEGAL_SUBMISSION, PROGRAMMING_REPOSITORY_LOCKS, PROGRAMMING_BUILD_RUN_UPDATE ->
createNotification((Exercise) notificationSubject, author, group, notificationType, (String) typeSpecificInformation);
// Additional Types
case PROGRAMMING_TEST_CASES_CHANGED, NEW_MANUAL_FEEDBACK_REQUEST ->
Expand Down Expand Up @@ -200,6 +200,27 @@ public void notifyEditorAndInstructorGroupsAboutChangedTestCasesForProgrammingEx
notifyGroupsWithNotificationType(new GroupNotificationType[] { EDITOR, INSTRUCTOR }, PROGRAMMING_TEST_CASES_CHANGED, exercise, null, null);
}

/**
* Notify editor and instructor groups about a finished repository permission change and the amount of failed updated.
*
* @param exercise the exercise where the repository permissions got updated
* @param notificationText the notification text containing the amount of failed operations.
*/
public void notifyEditorAndInstructorGroupsAboutRepositoryLocks(ProgrammingExercise exercise, String notificationText) {
notifyGroupsWithNotificationType(new GroupNotificationType[] { EDITOR, INSTRUCTOR }, PROGRAMMING_REPOSITORY_LOCKS, exercise, notificationText, null);
}

/**
* Notify editor and instructor groups about started or completed build runs for all participants of an exercise.
*
*
* @param exercise the exercise where the builds status changed
* @param notificationText the notification text
*/
public void notifyEditorAndInstructorGroupsAboutBuildRunUpdate(ProgrammingExercise exercise, String notificationText) {
notifyGroupsWithNotificationType(new GroupNotificationType[] { EDITOR, INSTRUCTOR }, PROGRAMMING_BUILD_RUN_UPDATE, exercise, notificationText, null);
}

/**
* Notify all groups about a new post in an exercise.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public ProgrammingMessagingService(GroupNotificationService groupNotificationSer

public void notifyInstructorAboutStartedExerciseBuildRun(ProgrammingExercise programmingExercise) {
websocketMessagingService.sendMessage(getProgrammingExerciseAllExerciseBuildsTriggeredTopic(programmingExercise.getId()), BuildRunState.RUNNING);
// Send a notification to the client to inform the instructor about the test case update.
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(programmingExercise, BUILD_RUN_STARTED_FOR_PROGRAMMING_EXERCISE);
// Send a notification to the client to inform the instructor about started builds.
groupNotificationService.notifyEditorAndInstructorGroupsAboutBuildRunUpdate(programmingExercise, BUILD_RUN_STARTED_FOR_PROGRAMMING_EXERCISE);
}

public void notifyInstructorAboutCompletedExerciseBuildRun(ProgrammingExercise programmingExercise) {
websocketMessagingService.sendMessage(getProgrammingExerciseAllExerciseBuildsTriggeredTopic(programmingExercise.getId()), BuildRunState.COMPLETED);
// Send a notification to the client to inform the instructor about the test case update.
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(programmingExercise, BUILD_RUN_COMPLETE_FOR_PROGRAMMING_EXERCISE);
// Send a notification to the client to inform the instructor about the completed builds.
groupNotificationService.notifyEditorAndInstructorGroupsAboutBuildRunUpdate(programmingExercise, BUILD_RUN_COMPLETE_FOR_PROGRAMMING_EXERCISE);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -625,13 +625,14 @@ private void stashStudentChangesAndNotifyInstructor(ProgrammingExercise exercise
Predicate<ProgrammingExerciseStudentParticipation> condition) {
Long programmingExerciseId = exercise.getId();

String notificationText;
if (numberOfFailedLockOperations > 0) {
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(exercise,
Constants.PROGRAMMING_EXERCISE_FAILED_LOCK_OPERATIONS_NOTIFICATION + numberOfFailedLockOperations);
notificationText = Constants.PROGRAMMING_EXERCISE_FAILED_LOCK_OPERATIONS_NOTIFICATION + numberOfFailedLockOperations;
}
else {
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(exercise, Constants.PROGRAMMING_EXERCISE_SUCCESSFUL_LOCK_OPERATION_NOTIFICATION);
notificationText = Constants.PROGRAMMING_EXERCISE_SUCCESSFUL_LOCK_OPERATION_NOTIFICATION;
}
groupNotificationService.notifyEditorAndInstructorGroupsAboutRepositoryLocks(exercise, notificationText);

// Stash the not submitted/committed changes for exercises with manual assessment and with online editor enabled
// This is necessary for students who have used the online editor, to ensure that only submitted/committed changes are displayed during manual assessment
Expand All @@ -641,14 +642,14 @@ private void stashStudentChangesAndNotifyInstructor(ProgrammingExercise exercise
var failedStashOperations = stashChangesInAllStudentRepositories(programmingExerciseId, condition);
failedStashOperations.thenAccept(failures -> {
long numberOfFailedStashOperations = failures.size();
String notificationText;
String stashNotificationText;
if (numberOfFailedStashOperations > 0) {
notificationText = Constants.PROGRAMMING_EXERCISE_FAILED_STASH_OPERATIONS_NOTIFICATION + numberOfFailedStashOperations;
stashNotificationText = Constants.PROGRAMMING_EXERCISE_FAILED_STASH_OPERATIONS_NOTIFICATION + numberOfFailedStashOperations;
}
else {
notificationText = Constants.PROGRAMMING_EXERCISE_SUCCESSFUL_STASH_OPERATION_NOTIFICATION;
stashNotificationText = Constants.PROGRAMMING_EXERCISE_SUCCESSFUL_STASH_OPERATION_NOTIFICATION;
}
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(exercise, notificationText);
groupNotificationService.notifyEditorAndInstructorGroupsAboutRepositoryLocks(exercise, stashNotificationText);
});
}
}
Expand Down Expand Up @@ -711,7 +712,7 @@ public Runnable runUnlockOperation(ProgrammingExercise exercise, Consumer<Progra
else {
notificationText = Constants.PROGRAMMING_EXERCISE_SUCCESSFUL_UNLOCK_OPERATION_NOTIFICATION;
}
groupNotificationService.notifyEditorAndInstructorGroupAboutExerciseUpdate(exercise, notificationText);
groupNotificationService.notifyEditorAndInstructorGroupsAboutRepositoryLocks(exercise, notificationText);

// Schedule the lock operations here, this is also done here because the working times might change often before the exam start
// Note: this only makes sense before the due date of a course exercise or before the end date of an exam, because for individual dates in the past
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ export class CategoryIssuesChartComponent implements OnChanges {
this.category.state === StaticCodeAnalysisCategoryState.Inactive
? '#ddd'
: numStudents === 0 || this.category.state !== StaticCodeAnalysisCategoryState.Graded
? '#28a745'
: numIssues > maxGradedIssues
? '#dc3545'
: '#ffc107',
? '#28a745'
: numIssues > maxGradedIssues
? '#dc3545'
: '#ffc107',
tooltip: `${numStudents} student${numStudents !== 1 ? 's' : ''} ${numStudents !== 1 ? 'have' : 'has'} ${numIssues} issue${numIssues !== 1 ? 's' : ''}.`,
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ <h5 jhiTranslate="artemisApp.exercise.export.options"></h5>
value.results?.[correctionRound].assessmentType === AssessmentType.AUTOMATIC
? 'assess'
: value.results?.[correctionRound]?.completionDate
? 'open'
: 'continue') | artemisTranslate: { correctionRound: correctionRound + 1 }
? 'open'
: 'continue') | artemisTranslate: { correctionRound: correctionRound + 1 }
}}
</ng-container>
<ng-template #complaint>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@
(gradedParticipation?.initializationState === InitializationState.INITIALIZED || (beforeDueDate && !hasRatedGradedResult)
? editorLabel
: hasRatedGradedResult
? 'viewResults'
: 'viewSubmissions') | artemisTranslate
? 'viewResults'
: 'viewSubmissions') | artemisTranslate
"
[outlined]="(!beforeDueDate || hasRatedGradedResult) && gradedParticipation?.initializationState === InitializationState.FINISHED"
[buttonLoading]="!!exercise.loading"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ export class UsersImportDialogComponent implements OnDestroy {
return !this.hasImported
? 0
: this.examUserMode
? this.examUsersToImport.length - this.numberOfUsersNotImported
: this.usersToImport.length - this.numberOfUsersNotImported;
? this.examUsersToImport.length - this.numberOfUsersNotImported
: this.usersToImport.length - this.numberOfUsersNotImported;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/webapp/i18n/de/notification.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
"programmingTestCasesChanged": "Testfälle für Programmieraufgaben geändert",
"newManualFeedbackRequest": "Eine neue Anfrage zu manuellem Feedback wurde eingereicht",
"duplicateTestCase": "Doppelte Testfälle wurden gefunden.",
"repositoryLocks": "Repository-Berechtigungen aktualisiert",
"buildRun": "Neubewertung der Einreichungen",
"illegalSubmission": "Unzulässige Einreichung eines Studenten",
"newExercisePost": "Neuer Aufgabenbeitrag",
"newLecturePost": "Neuer Vorlesungsbeitrag",
Expand Down
4 changes: 3 additions & 1 deletion src/main/webapp/i18n/en/notification.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@
"exerciseReleased": "Exercise released",
"exercisePractice": "Exercise open for practice",
"quizExerciseStarted": "Quiz started",
"liveExamExerciseUpdate": "Live Exam Exercise Update",
"liveExamExerciseUpdate": "Live exam exercise update",
"exerciseUpdated": "Exercise updated",
"programmingTestCasesChanged": "Test cases for programming exercise changed",
"newManualFeedbackRequest": "A new manual feedback request has been submitted",
"duplicateTestCase": "Duplicate test case was found.",
"repositoryLocks": "Repository permissions changed",
"buildRun": "Build run update",
"illegalSubmission": "Illegal submission of a student.",
"newExercisePost": "New exercise post",
"newLecturePost": "New lecture post",
Expand Down
Loading