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

Development: Introduce tutorialgroup module API #10266

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from

Conversation

ole-ve
Copy link
Contributor

@ole-ve ole-ve commented Feb 4, 2025

Checklist

General

Server

  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I documented the Java code using JavaDoc style.

Motivation and Context

As part of the server modularization, we "facade" the service/repository declaration and method calls to module-external classes via a module API provided by the respective module.

Description

  1. Open management view of an existing course
  2. Edit the course settings and set the timezone (if not already done)
  3. Go to management view and select "Tutorials"
  4. Click the button "Create configuration" and enter some arbitrary time-range
  5. Tick "Use Artemis managed Tutorial Group Channels" and select Public for visiblity
  6. Submit via "Continue to Tutorial Group Management"
  7. Create a new tutorial group with arbitrary values
  8. Go to Communication and join the channel ("Browse Channels"). See that there is a tutorial group channel(s). Create posts and check that they are persisted after reload
  9. Change the time zone of the course and verify that the date/period of the tutorial group changes
  10. Delete the tutorial group

Out of scope: Adding a PROFILE_TUTORIALGROUP (or similar) to disable the module on server start. This requires a lot of frontend changes and testing.

Steps for Testing

Can only be test on TS3

Basically try to test all the functionality of tutorialgroup.

  1. Log in to Artemis
  2. Create a tutorial group
  3. Test your way around

Exam Mode Testing

  • does not apply, no tutorial groups for exams -

Review Progress

Performance Review

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Introduced new API endpoints that streamline tutorial group communications, notifications, channel management, and registrations.
  • Refactor
    • Transitioned core tutorial group functionalities to more flexible, modular API integrations, enhancing robustness and error handling.
  • Tests
    • Added architectural tests to validate the new tutorial group module integrations.
  • Style
    • Enhanced date handling capabilities in the tutorial group configuration and schedule forms by integrating ArtemisDatePipe.

These updates improve the reliability and flexibility of tutorial group features, ensuring smoother user interactions without altering visible behavior.

@ole-ve ole-ve self-assigned this Feb 4, 2025
@ole-ve ole-ve requested a review from a team as a code owner February 4, 2025 21:39
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module tutorialgroup Pull requests that affect the corresponding module labels Feb 4, 2025
Copy link

coderabbitai bot commented Feb 4, 2025

Walkthrough

The changes across multiple modules focus on replacing direct repository and service dependencies with Optional API interfaces. Existing classes in the communication, notification, core, and web layers have been updated to conditionally interact with these new APIs. Additionally, several new API classes have been introduced to encapsulate tutorial group functionalities such as communication details, channel management, notifications, and registrations. A new architecture test for the tutorial group module has also been added.

Changes

File(s) Change Summary
.../communication/service/conversation/ConversationDTOService.java
.../communication/service/notifications/TutorialGroupNotificationService.java
.../communication/web/NotificationResource.java
.../communication/web/conversation/ChannelResource.java
.../core/service/CourseService.java
.../core/web/CourseResource.java
Replaced direct repository and service dependencies with Optional API interfaces. Constructor parameters and method calls were updated to conditionally invoke API methods (e.g., getTutorialGroupCommunicationDetails, findAllForNotifications, onTimeZoneUpdate, etc.), enhancing safety with Optional checks and improved error handling.
.../tutorialgroup/api/AbstractTutorialGroupApi.java
.../tutorialgroup/api/TutorialGroupApi.java
.../tutorialgroup/api/TutorialGroupChannelManagementApi.java
.../tutorialgroup/api/TutorialGroupNotificationApi.java
.../tutorialgroup/api/TutorialGroupRegistrationApi.java
.../tutorialgroup/api/TutorialGroupCommunicationApi.java
Introduced new API classes to encapsulate tutorial group functionalities. These classes extend a new abstract base (AbstractTutorialGroupApi) and expose methods for operations such as retrieving communication details, managing channels, handling notifications, and processing registrations.
.../tutorialgroup/architecture/TutorialGroupApiArchitectureTest.java Added a new architecture test class extending the abstract module access test to verify module-level dependency boundaries for the tutorial group package.

Sequence Diagram(s)

sequenceDiagram
    participant Service as ConversationDTOService
    participant API as TutorialGroupCommunicationApi
    participant DTO as ChannelDTO

    Service->>API: Check if Optional API is present
    alt API Present
        Service->>API: getTutorialGroupCommunicationDetails(channelId)
        API-->>Service: Return (tutorialGroupId, tutorialGroupTitle)
        Service->>DTO: Set tutorialGroupId and tutorialGroupTitle
    else API Absent
        Service->>DTO: Set tutorialGroup details to defaults
    end
Loading
sequenceDiagram
    participant NR as NotificationResource
    participant TGA as TutorialGroupApi
    participant User as CurrentUser

    NR->>User: Retrieve currentUser info
    alt TutorialGroupApi Present
        NR->>TGA: findAllForNotifications(currentUser)
        TGA-->>NR: Return tutorialGroupIds (set)
    else API Absent
        NR-->>NR: Initialize empty tutorialGroupIds set
    end
    NR->>User: Process notifications with retrieved group IDs
Loading

Suggested labels

ready to merge

Suggested reviewers

  • JohannesStoehr
  • BBesrour
  • MaximilianAnzinger
  • pzdr7
  • HawKhiem
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (10)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupNotificationApi.java (1)

11-13: Consider using @service instead of @controller.

Since this class is not handling web requests but rather providing a service facade for tutorial group notifications, @Service would be more appropriate than @Controller.

 @Profile(PROFILE_CORE)
-@Controller
+@Service
 public class TutorialGroupNotificationApi extends AbstractTutorialGroupApi {
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupRegistrationApi.java (2)

15-17: Consider using @Service instead of @Controller.

This class appears to be a service facade rather than a REST controller as it doesn't handle HTTP requests directly. Using @Service would better reflect its role in the architecture.

 @Profile(PROFILE_CORE)
-@Controller
+@Service
 public class TutorialGroupRegistrationApi extends AbstractTutorialGroupApi {

19-23: Add null check for injected dependency.

While Spring handles dependency injection, it's a good practice to add explicit null checks to fail fast and provide clear error messages.

 public TutorialGroupRegistrationApi(TutorialGroupRegistrationRepository tutorialGroupRegistrationRepository) {
+    if (tutorialGroupRegistrationRepository == null) {
+        throw new IllegalArgumentException("TutorialGroupRegistrationRepository must not be null");
+    }
     this.tutorialGroupRegistrationRepository = tutorialGroupRegistrationRepository;
 }
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (1)

99-100: Consider handling invalid registrations.

While this maps each registration to its student, consider skipping entries with null or invalid students to avoid potential NPEs or incomplete data.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1)

30-48: Add JavaDoc documentation for public methods.

Each public method should be documented with JavaDoc to describe its purpose, parameters, return values, and any exceptions it may throw.

Apply this diff to add JavaDoc:

+    /**
+     * Find all tutorial group IDs associated with notifications for a user.
+     * @param user The user to find notifications for
+     * @return Set of tutorial group IDs
+     */
     public Set<Long> findAllForNotifications(User user) {
         return tutorialGroupService.findAllForNotifications(user);
     }

+    /**
+     * Count tutorial groups associated with a course.
+     * @param course The course to count tutorial groups for
+     * @return Number of tutorial groups
+     */
     public Long countByCourse(Course course) {
         return tutorialGroupRepository.countByCourse(course);
     }

+    /**
+     * Find all tutorial groups for a course.
+     * @param courseId ID of the course
+     * @return Set of tutorial groups
+     */
     public Set<TutorialGroup> findAllByCourseId(Long courseId) {
         return tutorialGroupRepository.findAllByCourseId(courseId);
     }

+    /**
+     * Delete a tutorial group by its ID.
+     * @param id ID of the tutorial group to delete
+     */
     public void deleteById(Long id) {
         tutorialGroupRepository.deleteById(id);
     }

+    /**
+     * Find a tutorial group by its channel ID.
+     * @param channelId ID of the channel
+     * @return Optional containing the tutorial group if found
+     */
     public Optional<TutorialGroup> findByTutorialGroupChannelId(Long channelId) {
         return tutorialGroupRepository.findByTutorialGroupChannelId(channelId);
     }
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupChannelManagementApi.java (1)

30-40: Add JavaDoc documentation for public methods.

Each public method should be documented with JavaDoc to describe its purpose, parameters, and return values.

Apply this diff to add JavaDoc:

+    /**
+     * Get the tutorial group associated with a channel.
+     * @param channel The channel to find the tutorial group for
+     * @return Optional containing the tutorial group if found
+     */
     public Optional<TutorialGroup> getTutorialGroupBelongingToChannel(Channel channel) {
         return tutorialGroupChannelManagementService.getTutorialGroupBelongingToChannel(channel);
     }

+    /**
+     * Delete the channel associated with a tutorial group.
+     * @param tutorialGroup The tutorial group whose channel should be deleted
+     */
     public void deleteTutorialGroupChannel(TutorialGroup tutorialGroup) {
         tutorialGroupChannelManagementService.deleteTutorialGroupChannel(tutorialGroup);
     }

+    /**
+     * Handle timezone updates for a course.
+     * @param course The course whose timezone has been updated
+     */
     public void onTimeZoneUpdate(Course course) {
         tutorialGroupsConfigurationService.onTimeZoneUpdate(course);
     }
src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java (2)

138-144: Consider extracting tutorial group mapping logic to a private method.

The tutorial group mapping logic is duplicated in both convertChannelToDTO methods. Consider extracting it to a private method to improve code reusability and maintainability.

+private void setTutorialGroupInfo(ChannelDTO channelDTO, Channel channel) {
+    if (tutorialGroupApi.isPresent()) {
+        var tutorialGroup = tutorialGroupApi.get().findByTutorialGroupChannelId(channel.getId());
+        tutorialGroup.ifPresent(tg -> {
+            channelDTO.setTutorialGroupId(tg.getId());
+            channelDTO.setTutorialGroupTitle(tg.getTitle());
+        });
+    }
+}

 public ChannelDTO convertChannelToDTO(User requestingUser, Channel channel) {
     // ... existing code ...
-    if (tutorialGroupApi.isPresent()) {
-        var tutorialGroup = tutorialGroupApi.get().findByTutorialGroupChannelId(channel.getId());
-        tutorialGroup.ifPresent(tg -> {
-            channelDTO.setTutorialGroupId(tg.getId());
-            channelDTO.setTutorialGroupTitle(tg.getTitle());
-        });
-    }
+    setTutorialGroupInfo(channelDTO, channel);
     return channelDTO;
 }

168-174: Duplicate code: Use the extracted method here as well.

This is the same tutorial group mapping logic as in the other method. Use the extracted method here.

-if (tutorialGroupApi.isPresent()) {
-    var tutorialGroup = tutorialGroupApi.get().findByTutorialGroupChannelId(channel.getId());
-    tutorialGroup.ifPresent(tg -> {
-        channelDTO.setTutorialGroupId(tg.getId());
-        channelDTO.setTutorialGroupTitle(tg.getTitle());
-    });
-}
+setTutorialGroupInfo(channelDTO, channel);
src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (1)

288-290: Consider improving error message clarity.

The error message could be more descriptive about why the channel cannot be deleted. Consider mentioning that tutorial group channels must be managed through the tutorial group interface.

-throw new BadRequestAlertException("The channel belongs to tutorial group " + tutorialGroup.getTitle(), CHANNEL_ENTITY_NAME, "channel.tutorialGroup.mismatch");
+throw new BadRequestAlertException("Cannot delete channel: It belongs to tutorial group '" + tutorialGroup.getTitle() + "'. Tutorial group channels must be managed through the tutorial group interface.", CHANNEL_ENTITY_NAME, "channel.tutorialGroup.mismatch");
src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (1)

350-352: Consider extracting time zone update logic to a private method.

The time zone update logic could be extracted to a private method to improve readability and maintainability.

+private void handleTimeZoneUpdate(Course course) {
+    if (tutorialGroupChannelManagementApi.isPresent()) {
+        tutorialGroupChannelManagementApi.get().onTimeZoneUpdate(course);
+    }
+}

-if (timeZoneChanged && tutorialGroupChannelManagementApi.isPresent()) {
-    tutorialGroupChannelManagementApi.get().onTimeZoneUpdate(result);
+if (timeZoneChanged) {
+    handleTimeZoneUpdate(result);
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b015d33 and a3fb3dc.

📒 Files selected for processing (13)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/NotificationResource.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/exception/ApiNotPresentException.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/AbstractTutorialGroupApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupChannelManagementApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupNotificationApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupRegistrationApi.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/tutorialgroup/architecture/TutorialGroupApiArchitectureTest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/AbstractTutorialGroupApi.java
🧰 Additional context used
📓 Path-based instructions (12)
src/test/java/de/tum/cit/aet/artemis/tutorialgroup/architecture/TutorialGroupApiArchitectureTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupChannelManagementApi.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/exception/ApiNotPresentException.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupRegistrationApi.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/web/NotificationResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupNotificationApi.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

📓 Learnings (3)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupRegistrationApi.java (1)
Learnt from: Strohgelaender
PR: ls1intum/Artemis#8574
File: src/main/java/de/tum/in/www1/artemis/service/tutorialgroups/TutorialGroupService.java:0-0
Timestamp: 2024-11-12T12:51:58.050Z
Learning: The `tryToFindMatchingUsers` method in `TutorialGroupService.java` has been updated to skip registrations without a student, enhancing the method's robustness. This change was implemented in commit `bef30f9751de0913143e8cb28cc0088264052261`.
src/main/java/de/tum/cit/aet/artemis/communication/web/NotificationResource.java (1)
Learnt from: Strohgelaender
PR: ls1intum/Artemis#8574
File: src/main/java/de/tum/in/www1/artemis/service/tutorialgroups/TutorialGroupService.java:0-0
Timestamp: 2024-11-12T12:51:58.050Z
Learning: The `tryToFindMatchingUsers` method in `TutorialGroupService.java` has been updated to skip registrations without a student, enhancing the method's robustness. This change was implemented in commit `bef30f9751de0913143e8cb28cc0088264052261`.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (1)
Learnt from: Strohgelaender
PR: ls1intum/Artemis#8574
File: src/main/java/de/tum/in/www1/artemis/service/tutorialgroups/TutorialGroupService.java:0-0
Timestamp: 2024-11-12T12:51:58.050Z
Learning: The `tryToFindMatchingUsers` method in `TutorialGroupService.java` has been updated to skip registrations without a student, enhancing the method's robustness. This change was implemented in commit `bef30f9751de0913143e8cb28cc0088264052261`.
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Call Build Workflow / Build and Push Docker Image
  • GitHub Check: Call Build Workflow / Build .war artifact
  • GitHub Check: client-tests
  • GitHub Check: client-style
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: Analyse
🔇 Additional comments (29)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupNotificationApi.java (2)

1-10: LGTM! Package structure and imports are well-organized.

The package structure follows Java naming conventions, and imports are specific without using wildcard imports.


15-19: LGTM! Field declaration and constructor follow best practices.

The code follows best practices by:

  • Using constructor injection
  • Making the field private and final
  • Following the principle of least access
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupRegistrationApi.java (1)

1-14: LGTM!

Package declaration and imports are well-organized, following Java naming conventions and avoiding star imports.

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (5)

8-8: Nice introduction of Optional APIs and custom exception.

Using Optional to represent potentially unavailable functionality and throwing ApiNotPresentException when absent is a clean approach to modular disablement.

Also applies to: 20-22


31-31: Fields align well with the new API-based design.

Declaring Optional fields for tutorialGroupNotificationApi and tutorialGroupRegistrationApi ensures graceful handling of disabled modules without polluting code with null checks.

Also applies to: 33-33


41-45: Injection of Optionals in the constructor is consistent.

This constructor neatly enforces the presence of either a valid API or throws an exception when it’s missing. All good here.


72-73: Safe fallback with orElseThrow.

Efficiently terminates the flow if the notification API is unavailable. Ensure upstream callers are prepared to handle ApiNotPresentException.


95-95: Same pattern for the registration API.

Consistently applying the same fallback strategy for the registration API provides uniform handling. No issues noted.

src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (5)

86-86: Addition of ApiNotPresentException and optional tutorial group APIs.

Imports are well-structured and reflect the new API-based approach for tutorial groups. This is consistent with the modular design shift.

Also applies to: 119-121


135-135: Optional fields align with the disablement mechanism.

These field declarations neatly accommodate conditional availability of tutorial group functionalities, maintaining clean boundaries.

Also applies to: 199-199, 211-211


234-234: Constructor injection of Optionals is coherent and maintainable.

You've properly assigned the optional API fields within the constructor. This design fosters clarity regarding module presence.

Also applies to: 236-236, 269-269, 275-275, 276-276


372-377: Handling absent TutorialGroupApi during course retrieval.

Falling back to zero tutorial groups if the API is missing is a simple, user-friendly fallback. This approach cleanly avoids error cascades.


546-546: Tutorial group deletion flow respects new modular APIs.

Fetching the API with orElseThrow ensures the module is enabled before proceeding, and conditionally deletes channels and notifications to maintain data consistency.

Also applies to: 548-548, 551-552

src/test/java/de/tum/cit/aet/artemis/tutorialgroup/architecture/TutorialGroupApiArchitectureTest.java (2)

1-5: New architecture test introduced.

Extending the AbstractModuleAccessArchitectureTest for the tutorial group module is a solid approach to verify module boundaries and usage.


7-10: Module package resolved for tutorial group.

Overriding getModulePackage helps ensure the architecture tests specifically target the tutorialgroup package.

src/main/java/de/tum/cit/aet/artemis/core/exception/ApiNotPresentException.java (1)

6-18: LGTM! Well-structured exception class with clear error messaging.

The implementation follows best practices with proper JavaDoc documentation and a clear, informative error message format.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1)

25-28: LGTM! Constructor injection is properly implemented.

The constructor follows Spring best practices for dependency injection.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupChannelManagementApi.java (1)

24-28: LGTM! Constructor injection is properly implemented.

The constructor follows Spring best practices for dependency injection.

src/main/java/de/tum/cit/aet/artemis/communication/web/NotificationResource.java (2)

57-65: LGTM! Optional dependency is properly handled.

The constructor injection and field declaration follow Spring best practices.


82-88: LGTM! Proper handling of optional API presence.

The code correctly handles the case when the tutorial group API is not present by falling back to an empty set.

src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java (3)

34-34: LGTM!

Clean import of the new API interface.


46-46: LGTM!

Field declaration correctly uses Optional wrapper for the API dependency, following the module API pattern.


50-51: LGTM!

Constructor properly handles the Optional API dependency injection.

Also applies to: 55-55

src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (3)

57-57: LGTM!

Clean import of the new API interface.


80-80: LGTM!

Field declaration correctly uses Optional wrapper for the API dependency, following the module API pattern.


86-89: LGTM!

Constructor properly handles the Optional API dependency injection.

Also applies to: 98-98

src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (3)

125-125: LGTM!

Clean import of the new API interface.


170-170: LGTM!

Field declaration correctly uses Optional wrapper for the API dependency, following the module API pattern.


193-197: LGTM!

Constructor properly handles the Optional API dependency injection.

Also applies to: 214-214

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 4, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (2)

22-29: Consider adding @Autowired annotation for clarity.

While constructor injection works without @Autowired in Spring, adding it makes the dependency injection more explicit. Also, the @Lazy annotation suggests a circular dependency that might need attention.

-    public TutorialGroupApi(TutorialGroupRepository tutorialGroupRepository, @Lazy TutorialGroupService tutorialGroupService) {
+    @Autowired
+    public TutorialGroupApi(TutorialGroupRepository tutorialGroupRepository, @Lazy TutorialGroupService tutorialGroupService) {

31-49: Consider adding transaction boundaries.

The methods that modify data (e.g., deleteById) should be wrapped in transactions to ensure data consistency.

+    @Transactional
     public void deleteById(Long id) {
         tutorialGroupRepository.deleteById(id);
     }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3fb3dc and b7c7724.

📒 Files selected for processing (1)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`src/main/java/**/*.java`: naming:CamelCase; principles:{sin...

src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (1)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1)

1-20: LGTM! Well-structured class with proper annotations and imports.

The class follows Java naming conventions, uses specific imports, and is properly annotated for Spring framework integration.

@ls1intum ls1intum deleted a comment from coderabbitai bot Feb 7, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b7c7724 and 57fde8d.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupCommunicationApi.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupApi.java
  • src/main/java/de/tum/cit/aet/artemis/communication/service/conversation/ConversationDTOService.java
🧰 Additional context used
📓 Path-based instructions (1)
`src/main/java/**/*.java`: naming:CamelCase; principles:{sin...

src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupCommunicationApi.java
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Call Build Workflow / Build .war artifact
  • GitHub Check: Call Build Workflow / Build and Push Docker Image
  • GitHub Check: client-tests
  • GitHub Check: client-style
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: Analyse
  • GitHub Check: Mend Security Check
🔇 Additional comments (3)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupCommunicationApi.java (3)

1-14: LGTM! Well-organized imports and package structure.

The imports are specific and well-organized, following Java best practices.


19-23: LGTM! Clean dependency injection implementation.

Good use of constructor injection and final field, following Spring best practices.


15-17: Consider using @Component instead of @Controller.

Since this class acts as a facade for repository access rather than handling HTTP requests directly, @Component might be more appropriate than @Controller.

Please verify if this class needs to handle web requests. If not, consider changing the annotation:

-@Controller
+@Component
✅ Verification successful

I'm going to verify if this class is handling web requests by checking for any mapping annotations within it. We'll execute a shell script to search for common Spring HTTP mapping annotations (such as @RequestMapping, @GetMapping, @PostMapping, etc.) in the file.


🏁 Script executed:

#!/bin/bash
# Search for Spring web mapping annotations in the file to determine if it's used for handling HTTP requests
rg -n "@(RequestMapping|GetMapping|PostMapping|PutMapping|DeleteMapping)" src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupCommunicationApi.java

Length of output: 165


I'll generate a new script to display the first 100 lines of the file. This will let us manually inspect whether any HTTP request mapping annotations (such as @RequestMapping or @GetMapping) are present in any method declarations that might have been overlooked.


🏁 Script executed:

#!/bin/bash
head -n 100 src/main/java/de/tum/cit/aet/artemis/tutorialgroup/api/TutorialGroupCommunicationApi.java

Length of output: 1254


Annotation Choice Verification

The file doesn't contain any HTTP endpoint mapping annotations. Its sole public method doesn’t handle HTTP requests, confirming that the class is acting as a facade for repository access rather than exposing web endpoints. Based on this, replacing @controller with @component (or another appropriate stereotype) is advisable.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 7, 2025
HanyangXu0508
HanyangXu0508 previously approved these changes Feb 7, 2025
Copy link

@HanyangXu0508 HanyangXu0508 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested on server3 and worked as expected.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (1)

445-445: Consider implementing a limit for bulk deregistration.

The TODO comment suggests implementing a limit on the number of users that can be deregistered at once. This could help prevent potential performance issues or abuse.

Would you like me to help implement this feature by suggesting a solution that includes:

  • A configurable maximum limit
  • Batch processing for large deregistrations
  • Error handling for requests exceeding the limit
src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (1)

193-200: Consider using the builder pattern to improve constructor readability.

The constructor has many parameters (20+) which makes it hard to maintain and use. Consider refactoring to use the builder pattern or breaking down the class into smaller components to reduce the number of dependencies.

Example builder pattern implementation:

public class CourseResource {
    private CourseResource(CourseResourceBuilder builder) {
        this.userRepository = builder.userRepository;
        this.courseService = builder.courseService;
        // ... other assignments
    }

    public static class CourseResourceBuilder {
        private UserRepository userRepository;
        private CourseService courseService;
        // ... other fields

        public CourseResourceBuilder userRepository(UserRepository userRepository) {
            this.userRepository = userRepository;
            return this;
        }

        public CourseResourceBuilder courseService(CourseService courseService) {
            this.courseService = courseService;
            return this;
        }

        // ... other builder methods

        public CourseResource build() {
            return new CourseResource(this);
        }
    }
}
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1)

547-555: Consider enhancing error handling in deleteTutorialGroupsOfCourse.

While the implementation is functionally correct, there are a few improvements that could be made:

  1. The error handling could be more granular for each API operation
  2. The operations could benefit from being transactional

Consider this enhanced implementation:

 private void deleteTutorialGroupsOfCourse(Course course) {
-    var api = tutorialGroupApi.orElseThrow(() -> new ApiNotPresentException(TutorialGroupApi.class, PROFILE_CORE));
-    var tutorialGroups = api.findAllByCourseId(course.getId());
-    // we first need to delete notifications and channels, only then we can delete the tutorial group
-    tutorialGroups.forEach(tutorialGroup -> {
-        tutorialGroupNotificationApi.ifPresent(notApi -> notApi.deleteAllByTutorialGroupId(tutorialGroup.getId()));
-        tutorialGroupChannelManagementApi.ifPresent(manApi -> manApi.deleteTutorialGroupChannel(tutorialGroup));
-        api.deleteById(tutorialGroup.getId());
-    });
+    var api = tutorialGroupApi.orElseThrow(() -> new ApiNotPresentException(TutorialGroupApi.class, PROFILE_CORE));
+    var tutorialGroups = api.findAllByCourseId(course.getId());
+    // we first need to delete notifications and channels, only then we can delete the tutorial group
+    tutorialGroups.forEach(tutorialGroup -> {
+        try {
+            tutorialGroupNotificationApi.ifPresent(notApi -> {
+                try {
+                    notApi.deleteAllByTutorialGroupId(tutorialGroup.getId());
+                } catch (Exception e) {
+                    log.error("Failed to delete notifications for tutorial group {}: {}", tutorialGroup.getId(), e.getMessage());
+                }
+            });
+            tutorialGroupChannelManagementApi.ifPresent(manApi -> {
+                try {
+                    manApi.deleteTutorialGroupChannel(tutorialGroup);
+                } catch (Exception e) {
+                    log.error("Failed to delete channel for tutorial group {}: {}", tutorialGroup.getId(), e.getMessage());
+                }
+            });
+            api.deleteById(tutorialGroup.getId());
+        } catch (Exception e) {
+            log.error("Failed to delete tutorial group {}: {}", tutorialGroup.getId(), e.getMessage());
+        }
+    });
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0de1c9c and 9e9b8d5.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (5 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`src/main/java/**/*.java`: naming:CamelCase; principles:{sin...

src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

  • src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java
  • src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Call Build Workflow / Build and Push Docker Image
  • GitHub Check: Call Build Workflow / Build .war artifact
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: Analyse
🔇 Additional comments (10)
src/main/java/de/tum/cit/aet/artemis/communication/web/conversation/ChannelResource.java (2)

81-81: LGTM! Good use of dependency inversion.

The change from direct service dependency to an optional API interface improves modularity and follows the dependency inversion principle.

Also applies to: 90-90, 99-99


289-291: LGTM! Improved null safety with Optional.

The use of flatMap provides better null safety and follows functional programming practices. The error message is clear and informative.

src/main/java/de/tum/cit/aet/artemis/core/web/CourseResource.java (4)

125-125: LGTM!

The import is correctly placed and follows Java best practices by avoiding wildcard imports.


170-170: LGTM!

The field declaration follows best practices:

  • Appropriate use of Optional for optional dependency
  • Proper encapsulation with private modifier
  • Immutability with final modifier
  • Clear and descriptive naming

214-214: LGTM!

The field assignment is correctly placed and follows the established pattern.


350-352: LGTM!

The time zone update handling is well-implemented:

  • Proper null safety using Optional
  • Efficient conditional execution only when time zone changes
  • Clean and readable code structure
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (4)

86-86: LGTM! Clean import organization.

The new imports for tutorial group APIs and exception handling are well-organized and follow the package structure.

Also applies to: 119-121


135-135: LGTM! Proper field declarations.

The new Optional API fields are correctly declared as final and follow the established pattern of using Optional for modular APIs.

Also applies to: 199-199, 211-211


234-234: LGTM! Constructor injection follows best practices.

The constructor properly injects the new Optional API dependencies, maintaining the pattern of constructor-based dependency injection.

Also applies to: 236-236, 269-269, 275-276


372-377: LGTM! Proper null safety with Optional API.

The code correctly handles the Optional API presence check for counting tutorial groups, providing a safe fallback to 0 when the API is not present.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 18, 2025
@ole-ve
Copy link
Contributor Author

ole-ve commented Feb 18, 2025

Requires #10359 to be merged as currently, one cannot create new tutorial group configurations.

@github-actions github-actions bot added the client Pull requests that update TypeScript code. (Added Automatically!) label Feb 18, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts (3)

15-17: LGTM! Consider optimizing imports organization.

The addition of Artemis pipes and their configuration in the component decorator is correct. The pipes are properly imported and configured in both providers and imports arrays.

Consider organizing imports by grouping them into these categories (separated by blank lines):

  1. Angular core imports
  2. Angular form imports
  3. Third-party library imports
  4. Application-specific imports
 import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, inject } from '@angular/core';
 import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
+
 import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons';
 import { NgbDateParserFormatter, NgbTimeAdapter, NgbTimepicker } from '@ng-bootstrap/ng-bootstrap';
-import { weekDays } from 'app/course/tutorial-groups/shared/weekdays';
 import { Course } from 'app/entities/course.model';
 import * as _ from 'lodash-es';
 import dayjs from 'dayjs/esm';
+
+import { weekDays } from 'app/course/tutorial-groups/shared/weekdays';
 import { dayOfWeekZeroSundayToZeroMonday } from 'app/utils/date.utils';

Also applies to: 32-34


107-117: Enhance type safety in form initialization.

While the form initialization and validation are correct, the form lacks proper type safety. Consider using strongly typed form controls.

-        this.formGroup = this.fb.group(
+        this.formGroup = this.fb.group<{
+            dayOfWeek: FormControl<number>;
+            startTime: FormControl<string>;
+            endTime: FormControl<string>;
+            repetitionFrequency: FormControl<number>;
+            period: FormControl<Date[]>;
+            location: FormControl<string>;
+        }>(
             {
                 dayOfWeek: [1, Validators.required],
                 startTime: ['13:00:00', [Validators.required]],

78-99: Improve session creation logic for better maintainability.

The createdSessions getter handles multiple responsibilities and could benefit from being broken down into smaller, more focused methods. Additionally, consider adding error handling for edge cases.

Consider refactoring like this:

-    get createdSessions() {
+    private findFirstDayOfWeek(start: dayjs.Dayjs, targetDayOfWeek: number): dayjs.Dayjs {
+        while (dayOfWeekZeroSundayToZeroMonday(start.day()) + 1 !== targetDayOfWeek) {
+            start = start.add(1, 'day');
+        }
+        return start;
+    }
+
+    private generateSessions(start: dayjs.Dayjs, end: dayjs.Dayjs, repetitionFrequency: number): dayjs.Dayjs[] {
+        const sessions: dayjs.Dayjs[] = [];
+        while (start.isBefore(end) || start.isSame(end)) {
+            sessions.push(start);
+            start = start.add(repetitionFrequency, 'week');
+        }
+        return sessions;
+    }
+
+    get createdSessions() {
         const sessions: dayjs.Dayjs[] = [];
 
         if (this.formGroup.valid) {
             const { dayOfWeek, repetitionFrequency, period } = this.formGroup.value;
-            let start = dayjs(period[0]);
+            if (!period?.[0] || !period?.[1]) {
+                return sessions;
+            }
+
+            let start = dayjs(period[0]);
             const end = dayjs(period[1]);
 
-            // find the first day of the week
-            while (dayOfWeekZeroSundayToZeroMonday(start.day()) + 1 !== dayOfWeek) {
-                start = start.add(1, 'day');
+            if (!start.isValid() || !end.isValid()) {
+                return sessions;
             }
 
-            // add sessions
-            while (start.isBefore(end) || start.isSame(end)) {
-                sessions.push(start);
-                start = start.add(repetitionFrequency, 'week');
-            }
+            start = this.findFirstDayOfWeek(start, dayOfWeek);
+            return this.generateSessions(start, end, repetitionFrequency);
         }
 
         return sessions;
     }
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (1)

98-98: Address the TODO comment about registration type adaptation.

The comment indicates future work needed to adapt the registration type handling.

Would you like me to help create an issue to track this enhancement for future implementation?

src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (2)

135-211: Consider breaking down the service class to reduce dependencies.

The class has a high number of dependencies (30+), which could indicate it's handling too many responsibilities. Consider:

  • Splitting into smaller, focused services
  • Creating separate services for tutorial group, exam, and exercise management

372-377: Consider simplifying the tutorial group count logic.

The conditional count logic could be more concise using Optional's map and orElse:

-if (tutorialGroupApi.isPresent()) {
-    course.setNumberOfTutorialGroups(tutorialGroupApi.get().countByCourse(course));
-}
-else {
-    course.setNumberOfTutorialGroups(0L);
-}
+course.setNumberOfTutorialGroups(tutorialGroupApi.map(api -> api.countByCourse(course)).orElse(0L));
src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts (1)

21-24: Consider memory optimization with OnPush strategy.

The component uses ChangeDetectionStrategy.OnPush, which is good for performance. To fully leverage this:

  1. Ensure all inputs are immutable
  2. Use async pipe for observables
  3. Use pure pipes for transformations
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e9b8d5 and f019f44.

📒 Files selected for processing (4)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (9 hunks)
  • src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts (2 hunks)
  • src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`src/main/webapp/**/*.ts`: angular_style:https://angular.io/...

src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

  • src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts
  • src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups/crud/tutorial-group-form/schedule-form/schedule-form.component.ts
`src/main/java/**/*.java`: naming:CamelCase; principles:{sin...

src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Call Build Workflow / Build and Push Docker Image
  • GitHub Check: Call Build Workflow / Build .war artifact
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: client-tests-selected
  • GitHub Check: client-style
  • GitHub Check: server-style
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: Analyse
🔇 Additional comments (6)
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/TutorialGroupNotificationService.java (3)

31-49: Well-structured dependency injection with Optional APIs!

The refactoring from direct repository dependencies to Optional APIs is well-implemented:

  • Uses constructor injection (recommended practice)
  • Supports modular architecture through API interfaces
  • Enables conditional functionality through Optional wrapper

71-76: Clean implementation of API usage in saveAndSend!

The method properly handles the API dependency:

  • Checks for API presence with orElseThrow
  • Maintains clean separation of concerns
  • Preserves existing notification functionality

94-105: Well-implemented user notification logic with API integration!

The findUsersToNotify method effectively:

  • Handles API absence through orElseThrow
  • Maintains existing filtering logic
  • Uses streams effectively for user collection
src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (2)

546-555: Well-structured tutorial group deletion with API integration!

The method properly:

  • Handles API absence through orElseThrow
  • Deletes related notifications and channels first
  • Maintains proper deletion order

547-547: Consistent error handling with ApiNotPresentException!

The error handling is well-implemented:

  • Uses consistent pattern across methods
  • Provides clear error messages with API class and profile information
src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.ts (1)

9-9:

❓ Verification inconclusive

Verify the usage of ArtemisDatePipe.

The ArtemisDatePipe is imported and provided but doesn't appear to be used in the component. If it's intended for use in the template, ensure it's being utilized effectively. Otherwise, consider removing it to maintain clean dependencies.

Also applies to: 23-23


🏁 Script executed:

#!/bin/bash
# Check if ArtemisDatePipe is used in the template
rg "artemisDate" "src/main/webapp/app/course/tutorial-groups/tutorial-groups-management/tutorial-groups-configuration/crud/tutorial-groups-configuration-form/tutorial-groups-configuration-form.component.html"

Length of output: 436


Action Required: Confirm Whether ArtemisDatePipe Is Actually Utilized in the Component

  • The ArtemisDatePipe is imported (line 9) and added to the providers (line 23) of the component, yet there’s no evidence that it’s being used.
  • The initial search in an expected external HTML template returned an error (file not found). This suggests one of two scenarios:
    • The component uses an inline template instead of an external file.
    • The pipe is not used at all.
  • Next Steps:
    • Manually verify if the component defines an inline template (check for a template: property in the .component.ts file) and confirm whether the pipe is invoked using Angular’s pipe syntax (e.g., | artemisDate) within that template.
    • If no usage is found, please remove the ArtemisDatePipe from both the imports and providers to keep dependencies clean.
  • Also, note that employing the OnPush change detection strategy is a good practice for optimizing performance and memory usage.

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de February 18, 2025 16:54 Inactive
Copy link

@simonbohnen simonbohnen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on TS3, works 👌🏼

Copy link
Contributor

@SimonEntholzer SimonEntholzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tutorial groups work correctly on Ts3

Copy link
Contributor

@coolchock coolchock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code LGTM 👍 also tested on ts3 during testing session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client Pull requests that update TypeScript code. (Added Automatically!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests tutorialgroup Pull requests that affect the corresponding module
Projects
Status: Ready For Review
Status: Todo
Development

Successfully merging this pull request may close these issues.

6 participants