Skip to content

Conversation

marlonnienaber
Copy link
Contributor

@marlonnienaber marlonnienaber commented Aug 31, 2025

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding and design guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

The old tutorial group detail page has room for improvement when it comes to UI/UX.

Description

In this PR we refactor the tutorial group detail page that can be accessed through the course overview (not the management page). I built a new version of the page. I fetch the data via a new DTO endpoint (the call of the old page loaded a lot of unnecessary data). The new endpoint (part of TutorialGroupResource )calls a method in TutorialGroupService. While implementing this method some architecture tests started to fail because it is a very large Service and with the new method some threshold regarding Service complexity and size were exceeded. So I looked at the Service and decided one way to improve the complexity a little is to remove the AuthorizationCheckService dependency. I hence moved all authorization related logic into the Resource layer (I personally think that is cleaner anyways).

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Tutor
  • 1 Student
  • a course with a tutorial group configuration that enables communication for tutorial groups (see second screenshot if you don't know where to configure this)
  1. Create a Tutorial Group with the tutor and register the student
  2. Configure it with only the required fields
  3. Go to the new tutorial group detail page and verify that the page displays the information you configured correctly:
  • next to the title you should find buttons that lead to the tutor chat and to the group chat. Verify that they work
  • in the cards some fields should be shown with a "-" since you did not configure all fields for the group.
  • all created sessions should be displayed (try both the all sessions and future sessions option for displaying them)
  • a disclaimer should be displayed in the attendance card that no data are available
  1. As the instructor edit the group and add the missing fields that you did not configure in the beginning
  2. As the tutor cancel a session, reschedule one and change the location of a third. Also add an attendacne count to some of the sessions.
  3. Verify as student that the status of the modified session updates in the new tutorial group detail page. Also verify that the average attendance is now displayed in the attendance card.
  4. As the tutor reconfigure the group such that there are no upcoming sessions (change the groups period such that it has already ended)
  5. Verify as a student that the next session card in the new tutorial group detail page now displays that there is no upcoming session.

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
course-tutorial-group-detail-container.component.ts 90.32%
course-tutorial-group-detail-session-status-chip.component.ts 100%
course-tutorial-group-detail-session-status-indicator.component.ts 100%
course-tutorial-group-detail.component.ts 92.53%
tutorial-groups.service.ts 87.5%

Server

Class/File Line Coverage Confirmation (assert/expect)
TutorialGroupResource.java 93%
TutorialGroupService.java 93%

Screenshots

image image

Summary by CodeRabbit

  • New Features

    • Detailed Tutorial Group view: tutor card, general info, attendance chart, next-session with per-field change indicators, session list with filters, status chips/indicator, loading state, and tutor-chat/group-channel links; client and API support with timezone-aware details and chat creation/navigation.
  • Improvements

    • Weekday translations unified under global.*, expanded tutorial-group i18n.
    • Profile picture color fallback improved.
    • Removed utilization text from tutorial-group sidebar cards.
  • Tests

    • Added/updated unit and integration tests for the detail view, timezone handling, and messaging.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Aug 31, 2025
@github-actions github-actions bot added client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module tutorialgroup Pull requests that affect the corresponding module labels Aug 31, 2025
@github-actions github-actions bot added the server Pull requests that update Java code. (Added Automatically!) label Sep 3, 2025
@github-actions github-actions bot added the communication Pull requests that affect the corresponding module label Sep 12, 2025
@marlonnienaber marlonnienaber changed the title Chore/student tutorial group session refactoring Tutorial groups: Refactor student tutorial group detail page Sep 13, 2025
@github-actions github-actions bot added the tests label Sep 14, 2025
Copy link
Contributor

@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

♻️ Duplicate comments (3)
src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts (2)

53-78: Reuse the spy variable instead of creating a duplicate spy.

Line 54 calls jest.spyOn(CourseModel, 'isMessagingEnabled') again, creating a second spy on the same method. This overrides the spy from beforeEach and can lead to test pollution.

Based on learnings

Apply this diff:

     it('should display no conversation links if messaging disabled', () => {
-        jest.spyOn(CourseModel, 'isMessagingEnabled').mockReturnValue(false);
+        isMessagingEnabledSpy.mockReturnValue(false);
         const raw: RawTutorialGroupDetailGroupDTO = {

24-51: Declare a reusable spy variable for isMessagingEnabled to prevent spy conflicts.

The test creates a spy for CourseModel.isMessagingEnabled in beforeEach (line 48) but doesn't store it in a variable. Later, line 54 creates a duplicate spy, which can cause test pollution and unpredictable behavior.

Based on learnings

Apply this diff to declare and reuse a single spy:

 describe('NewTutorialGroupDetail', () => {
     let component: CourseTutorialGroupDetailComponent;
     let fixture: ComponentFixture<CourseTutorialGroupDetailComponent>;
+    let isMessagingEnabledSpy: jest.SpyInstance;

     const mockTranslateService = new MockTranslateService();
     mockTranslateService.use('en');
     const mockAccountService = new MockAccountService();
     mockAccountService.userIdentity = new User(undefined, 'artemis_admin');

     beforeEach(async () => {
         await TestBed.configureTestingModule({
             imports: [CourseTutorialGroupDetailComponent],
             providers: [
                 { provide: TranslateService, useValue: mockTranslateService },
                 { provide: AccountService, useValue: mockAccountService },
                 { provide: OneToOneChatService, useValue: MockService(OneToOneChatService) },
                 { provide: AlertService, useValue: MockService(AlertService) },
                 { provide: Router, useValue: MockService(Router) },
             ],
             declarations: [MockDirective(TranslateDirective), MockDirective(RouterLink)],
         }).compileComponents();

         fixture = TestBed.createComponent(CourseTutorialGroupDetailComponent);
         component = fixture.componentInstance;

-        jest.spyOn(CourseModel, 'isMessagingEnabled').mockReturnValue(true);
+        isMessagingEnabledSpy = jest.spyOn(CourseModel, 'isMessagingEnabled').mockReturnValue(true);

         fixture.componentRef.setInput('course', { id: 1 } as Course);
     });
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java (1)

642-669: Guard schedule time parsing against null values.

Lines 658-660 parse scheduleStartTime() and scheduleEndTime() without null checks. The repository query uses a LEFT JOIN on schedule, so these fields can be null even when scheduleDayOfWeek() is non-null. LocalTime.parse(null) will throw a NullPointerException.

Apply this fix to guard against null values:

-        if (rawGroupDTOs.scheduleDayOfWeek() != null) {
+        if (rawGroupDTOs.scheduleDayOfWeek() != null
+                && rawGroupDTOs.scheduleStartTime() != null
+                && rawGroupDTOs.scheduleEndTime() != null) {
             int scheduleDayOfWeek = rawGroupDTOs.scheduleDayOfWeek();
             LocalTime scheduleStart = LocalTime.parse(rawGroupDTOs.scheduleStartTime());
             LocalTime scheduleEnd = LocalTime.parse(rawGroupDTOs.scheduleEndTime());
             String scheduleLocation = rawGroupDTOs.scheduleLocation();
             sessionDTOs = rawSessionDTOs.stream()
                     .map(data -> TutorialGroupDetailSessionDTO.from(data, scheduleDayOfWeek, scheduleStart, scheduleEnd, scheduleLocation, courseTimeZone)).toList();
         }
         else {
             sessionDTOs = rawSessionDTOs.stream().map(TutorialGroupDetailSessionDTO::from).toList();
         }

This ensures all three time-related fields are non-null before parsing, preventing NPE when schedule data is incomplete.

🧹 Nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailSessionDTO.java (1)

1-1: Consider moving DTO to a dedicated package.

Per coding guidelines, DTOs should follow single responsibility and be organized appropriately. This record is placed in the util package, but DTOs are typically placed in a dto or web.dto package for better organization and separation of concerns.

If the project convention is to place DTOs in a dedicated package (e.g., de.tum.cit.aet.artemis.tutorialgroup.dto or de.tum.cit.aet.artemis.tutorialgroup.web.dto), consider moving this record there for consistency. If util is the established convention for "raw" DTOs used in repository projections, this is acceptable.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 335d1df and 46b1e7e.

📒 Files selected for processing (7)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailSessionDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupResource.java (9 hunks)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupSessionResource.java (10 hunks)
  • src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail-container/course-tutorial-group-detail-container.component.spec.ts (1 hunks)
  • src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail-container/course-tutorial-group-detail-container.component.spec.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupResource.java
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupSessionResource.java
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailSessionDTO.java
src/main/webapp/**/*.ts

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts
🧠 Learnings (8)
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: JohannesStoehr
PR: ls1intum/Artemis#8679
File: src/main/java/de/tum/in/www1/artemis/web/rest/tutorialgroups/TutorialGroupSessionResource.java:37-37
Timestamp: 2024-06-10T19:44:09.116Z
Learning: The DTOs `CompetencyProgressForLearningPathDTO`, `ProgrammingExerciseResetOptionsDTO`, and `CourseWithIdDTO` do not contain nullable values or `Optional` types, making the `JsonInclude` annotation unnecessary for them.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: florian-glombik
PR: ls1intum/Artemis#8597
File: src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts:8-8
Timestamp: 2024-06-10T19:44:09.116Z
Learning: DTOs are typically defined in the `src/main/webapp/app/entities` folder on the client side in the Artemis project.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
📚 Learning: 2025-09-10T16:35:23.211Z
Learnt from: SamuelRoettgermann
PR: ls1intum/Artemis#11111
File: src/main/java/de/tum/cit/aet/artemis/exam/domain/room/ExamRoom.java:69-75
Timestamp: 2025-09-10T16:35:23.211Z
Learning: Artemis convention: The term “DTO” is used broadly (includes DAOs/value objects), not strictly client-transport models. Avoid assuming dto.* packages are always API-facing.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
📚 Learning: 2024-10-08T15:35:42.972Z
Learnt from: Strohgelaender
PR: ls1intum/Artemis#8574
File: src/main/java/de/tum/in/www1/artemis/service/tutorialgroups/TutorialGroupService.java:0-0
Timestamp: 2024-10-08T15:35:42.972Z
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`.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupResource.java
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java
📚 Learning: 2025-09-18T22:22:54.269Z
Learnt from: marlonnienaber
PR: ls1intum/Artemis#11350
File: src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java:0-0
Timestamp: 2025-09-18T22:22:54.269Z
Learning: In the tutorial group domain, TutorialGroup entities are guaranteed to have a non-null teachingAssistant due to database constraints. This means teachingAssistantLogin() will always return a non-null value, and null checks are not necessary when using this field in repository calls or other operations.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java
📚 Learning: 2025-09-18T20:55:38.115Z
Learnt from: marlonnienaber
PR: ls1intum/Artemis#11350
File: src/main/java/de/tum/cit/aet/artemis/tutorialgroup/repository/TutorialGroupRepository.java:145-168
Timestamp: 2025-09-18T20:55:38.115Z
Learning: In tutorial groups, every TutorialGroup is guaranteed to have a teachingAssistant (non-null constraint), so teaching assistant associations don't require LEFT JOINs in JPQL queries. Only optional associations like tutorialGroupSchedule and tutorialGroupChannel need LEFT JOINs.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: JohannesStoehr
PR: ls1intum/Artemis#0
File: :0-0
Timestamp: 2024-06-10T19:44:09.116Z
Learning: Admins are included in the `isAtLeastTutor` check, and unauthenticated users cannot access the `CourseTutorialGroupsComponent`.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java
📚 Learning: 2025-09-01T13:47:02.624Z
Learnt from: Michael-Breu-UIbk
PR: ls1intum/Artemis#10989
File: src/main/webapp/app/programming/manage/detail/programming-exercise-detail.component.with-sharing.spec.ts:167-169
Timestamp: 2025-09-01T13:47:02.624Z
Learning: In Jest tests, prefer using jest.spyOn() over direct method assignment for mocking service methods, as spies are automatically restored by Jest's cleanup mechanisms (jest.restoreAllMocks()), while direct assignment bypasses this system and can lead to test pollution where mocked methods affect subsequent tests.

Applied to files:

  • src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts
🧬 Code graph analysis (6)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java (1)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (1)
  • RawTutorialGroupDetailGroupDTO (79-92)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupResource.java (5)
src/main/webapp/app/core/course/shared/entities/course.model.ts (1)
  • Course (59-181)
src/main/webapp/app/core/user/user.model.ts (1)
  • User (5-65)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (1)
  • TutorialGroupDetailGroupDTO (37-77)
src/main/webapp/app/tutorialgroup/shared/service/tutorial-groups.service.ts (3)
  • getOneOfCourse (41-45)
  • getTutorialGroupDetailGroupDTO (47-51)
  • exportTutorialGroupsToCSV (184-186)
src/main/webapp/app/core/auth/account.service.ts (2)
  • isAdmin (228-230)
  • isAtLeastInstructorInCourse (200-202)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupSessionResource.java (5)
src/main/webapp/app/core/course/shared/entities/course.model.ts (1)
  • Course (59-181)
src/main/webapp/app/core/user/user.model.ts (1)
  • User (5-65)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (1)
  • TutorialGroup (10-35)
src/main/webapp/app/tutorialgroup/shared/service/tutorial-group-session.service.ts (1)
  • getOneOfTutorialGroup (27-31)
src/main/webapp/app/core/auth/account.service.ts (2)
  • isAdmin (228-230)
  • isAtLeastInstructorInCourse (200-202)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java (3)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (3)
  • TutorialGroup (10-35)
  • TutorialGroupDetailGroupDTO (37-77)
  • RawTutorialGroupDetailGroupDTO (79-92)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group-session.model.ts (3)
  • TutorialGroupSession (12-23)
  • TutorialGroupDetailSessionDTO (25-36)
  • RawTutorialGroupDetailSessionDTO (38-47)
src/main/webapp/app/tutorialgroup/shared/service/tutorial-groups.service.ts (3)
  • getOneOfCourse (41-45)
  • getTutorialGroupDetailGroupDTO (47-51)
  • exportTutorialGroupsToCSV (184-186)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailSessionDTO.java (1)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group-session.model.ts (1)
  • RawTutorialGroupDetailSessionDTO (38-47)
src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts (5)
src/test/javascript/spec/helpers/mocks/service/mock-account.service.ts (1)
  • MockAccountService (7-45)
src/main/webapp/app/core/user/user.model.ts (1)
  • User (5-65)
src/main/webapp/app/core/course/shared/entities/course.model.ts (1)
  • Course (59-181)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (2)
  • RawTutorialGroupDetailGroupDTO (79-92)
  • TutorialGroupDetailGroupDTO (37-77)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group-session.model.ts (1)
  • RawTutorialGroupDetailSessionDTO (38-47)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: server-tests
  • GitHub Check: client-tests-selected
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Analyse
🔇 Additional comments (27)
src/main/webapp/app/tutorialgroup/overview/course-tutorial-group-detail/course-tutorial-group-detail.component.spec.ts (2)

12-13: Import issue resolved.

The missing RawTutorialGroupDetailSessionDTO import flagged in previous reviews is now present on line 13.


80-1144: Comprehensive test coverage with good edge case handling.

The test suite thoroughly covers:

  • Messaging enablement and conversation link visibility
  • Computed properties (language, capacity, mode, campus, nextSession, average attendance)
  • Pie chart data and color calculations across all attendance ranges
  • UI disclaimer display for missing data
  • Edge cases (no capacity, no attendance, no sessions, no future sessions)

The tests follow Angular best practices with input-driven testing and consistent assertion patterns.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailSessionDTO.java (2)

12-14: Review @JsonInclude(NON_EMPTY) semantics with nullable field.

The class-level @JsonInclude(JsonInclude.Include.NON_EMPTY) annotation excludes "empty" values (null, empty collections, empty strings, etc.). However, attendanceCount is @Nullable Integer which will be excluded when null. Verify this is the intended behavior:

  • If attendanceCount == null should be explicitly serialized as null in JSON (to distinguish "no data" from "0 attendees"), use @JsonInclude(JsonInclude.Include.ALWAYS) on that field specifically
  • If excluding null attendanceCount from JSON is correct (client treats absence as "no data"), the current annotation is fine

Based on the PR objectives mentioning "data economy" and the field being marked @Nullable, the current approach likely matches intent. However, confirm the frontend correctly handles the absence of this field versus an explicit null or 0 value.


1-15: Incorrect mismatch concern – no change needed
The frontend’s RawTutorialGroupDetailSessionDTO interface represents the JSON‐serialized TutorialGroupDetailSessionDTO (record in de.tum.cit.aet.artemis.tutorialgroup.dto), not the internal RawTutorialGroupDetailSessionDTO in util. Their shapes align correctly: the JSON DTO supplies the boolean flags and optional attendanceCount that the TS model expects.

Likely an incorrect or invalid review comment.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupSessionResource.java (9)

90-103: LGTM: Constructor injection follows guidelines.

The addition of CourseRepository and UserRepository via constructor injection aligns with the coding guideline to use constructor injection for DI.


114-126: LGTM: Authorization now uses session's course.

The endpoint correctly derives the course from session.getTutorialGroup().getCourse() and uses it for the instructor check, eliminating the previous authorization gap.


176-181: LGTM: Helper method reduces duplication.

The new helper method encapsulates the common pattern of fetching user context and computing admin/instructor status, following DRY principles.


147-149: LGTM: Authorization refactored correctly.

The update method now uses the helper and calls the appropriate throwing authorization check method.


199-203: LGTM: Consistent authorization pattern.

The updateAttendanceCount method follows the same authorization pattern as update.


223-227: LGTM: Delete authorization uses correct method.

The deleteSession method now calls checkIfUserIsAllowedToDeleteTutorialGroupElseThrow, which is semantically appropriate for deletion operations.


246-251: LGTM: Create authorization follows pattern.

The create method correctly fetches the tutorial group and performs authorization checks before creating the session.


296-300: LGTM: Cancel authorization consistent.

The cancel method uses the same authorization pattern as other session-modifying operations.


326-330: LGTM: Activate authorization consistent.

The activate method follows the same authorization pattern as other session modification endpoints.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/web/TutorialGroupResource.java (7)

655-664: LGTM: Helper methods reduce duplication.

The two helper methods isAdminOrInstructorOfCourse and getUserAndCheckWhetherTheyAreAllowedToChangeRegistration encapsulate common authorization patterns and follow DRY principles.


187-196: LGTM: Authorization context passed correctly.

The getAllForCourse method now computes and passes the isAdminOrInstructor flag to the service layer.


205-214: LGTM: Annotation and authorization updated correctly.

The getOneOfCourse method now uses EnforceAtLeastStudentInCourse and passes the isAdminOrInstructor context to the service.


450-460: LGTM: Authorization refactored to use helper.

The deregisterStudent method now uses the helper to fetch user and validate authorization, reducing code duplication.


472-486: LGTM: Consistent authorization pattern.

The registerStudent method follows the same refactored authorization pattern as deregisterStudent.


592-612: LGTM: Export method updated with authorization context.

The exportTutorialGroupsToCSV method now computes and passes the isAdminOrInstructor flag to the service layer.


216-238: Membership validation confirmed tutorialGroupService.getTutorialGroupDetailGroupDTO delegates to tutorialGroupRepository.getTutorialGroupDetailData(tutorialGroupId, courseId), enforcing the tutorial group belongs to the course by filtering on both IDs and throwing EntityNotFoundException otherwise.

src/main/java/de/tum/cit/aet/artemis/tutorialgroup/service/TutorialGroupService.java (7)

90-102: LGTM: Constructor injection follows guidelines.

The addition of OneToOneChatRepository via constructor injection is correct and supports the new tutorial-group detail DTO functionality.


598-610: LGTM: Signature updated with authorization context.

The findAllForCourse method now accepts and uses the isAdminOrInstructor flag, eliminating the dependency on AuthorizationCheckService in the service layer.


621-631: LGTM: Consistent signature update.

The getOneOfCourse method follows the same pattern as findAllForCourse.


671-690: LGTM: Clear authorization helper method.

The userHasManagingRightsForTutorialGroup method provides a clear, reusable authorization check and correctly handles lazy-loaded teaching assistant associations.


692-731: LGTM: Throwing authorization methods follow consistent pattern.

The three authorization check methods (checkIfUserIsAllowedToChangeRegistrationsOfTutorialGroupElseThrow, checkIfUserIsAllowedToDeleteTutorialGroupElseThrow, checkIfUserIsAllowedToModifySessionsOfTutorialGroupElseThrow) follow a consistent pattern, use clear naming (per past review feedback), and have proper @NotNull annotations.


739-776: LGTM: Export method signature updated consistently.

The exportTutorialGroupsToCSV method signature now accepts the isAdminOrInstructor flag and passes it through to findAllForCourse, maintaining consistency with other service methods.


564-588: LGTM: User lookup refactored to repository methods.

The tryToFindMatchingUsers method now uses dedicated repository methods, improving clarity and leveraging database-level filtering. Based on learnings.

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 30, 2025
@marlonnienaber
Copy link
Contributor Author

@tobias-lippert see slack chat with @rabeatwork. Lets go with the headings as is for now and generally improve heading use in a follow up.

@ls1intum ls1intum deleted a comment from github-actions bot Sep 30, 2025
Copy link
Contributor

@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

♻️ Duplicate comments (1)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java (1)

9-13: Don't drop isOnline=false from serialization

@JsonInclude(Include.NON_EMPTY) suppresses Boolean.FALSE, so offline groups lose the isOnline flag entirely and the student UI can no longer distinguish “on-site” from “missing data”. Switch to Include.NON_NULL (or drop the annotation) so legitimate false values are sent.

-@JsonInclude(Include.NON_EMPTY)
+@JsonInclude(Include.NON_NULL)
 public record RawTutorialGroupDetailGroupDTO(...)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4b86f2 and 5691517.

📒 Files selected for processing (2)
  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java (1 hunks)
  • supporting_scripts/code-coverage/module-coverage-client/check-client-module-coverage.mjs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
🧠 Learnings (3)
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: JohannesStoehr
PR: ls1intum/Artemis#8679
File: src/main/java/de/tum/in/www1/artemis/web/rest/tutorialgroups/TutorialGroupSessionResource.java:37-37
Timestamp: 2024-06-10T19:44:09.116Z
Learning: The DTOs `CompetencyProgressForLearningPathDTO`, `ProgrammingExerciseResetOptionsDTO`, and `CourseWithIdDTO` do not contain nullable values or `Optional` types, making the `JsonInclude` annotation unnecessary for them.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: florian-glombik
PR: ls1intum/Artemis#8597
File: src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts:8-8
Timestamp: 2024-06-10T19:44:09.116Z
Learning: DTOs are typically defined in the `src/main/webapp/app/entities` folder on the client side in the Artemis project.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
📚 Learning: 2025-09-10T16:35:23.211Z
Learnt from: SamuelRoettgermann
PR: ls1intum/Artemis#11111
File: src/main/java/de/tum/cit/aet/artemis/exam/domain/room/ExamRoom.java:69-75
Timestamp: 2025-09-10T16:35:23.211Z
Learning: Artemis convention: The term “DTO” is used broadly (includes DAOs/value objects), not strictly client-transport models. Avoid assuming dto.* packages are always API-facing.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java
🧬 Code graph analysis (1)
src/main/java/de/tum/cit/aet/artemis/tutorialgroup/util/RawTutorialGroupDetailGroupDTO.java (1)
src/main/webapp/app/tutorialgroup/shared/entities/tutorial-group.model.ts (1)
  • RawTutorialGroupDetailGroupDTO (79-92)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-tests
  • GitHub Check: server-style
  • GitHub Check: client-style
  • GitHub Check: server-tests
  • GitHub Check: client-tests-selected
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse

@ls1intum ls1intum deleted a comment from github-actions bot Sep 30, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran201 passed3 skipped1 failed1h 8m 39s 69ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseManagement.spec.ts
ts.Quiz Exercise Management › Quiz Exercise Creation › Creates a Quiz with Drag and Drop❌ failure2m 3s 968ms

@ls1intum ls1intum deleted a comment from github-actions bot Oct 1, 2025
Copy link
Contributor

@KonstiAnon KonstiAnon left a comment

Choose a reason for hiding this comment

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

Still not 100% happy regarding the is... functions that don't return a boolean, but nothing severe

Copy link
Contributor

@SamuelRoettgermann SamuelRoettgermann left a comment

Choose a reason for hiding this comment

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

Re-tested on TS4.

Lgtm; I never said it before, but I especially like that the Attendance value can display values above 100% (the Utilization bar in the Manage View can't do that).

Fun fact, the attendance value text can leak into the Attendance circle, but that is such an unrealistic scenario that I think it's fine either way.
image

Copy link
Contributor

@tobias-lippert tobias-lippert left a comment

Choose a reason for hiding this comment

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

Reapprove code

Copy link
Contributor

@MoritzSpengler MoritzSpengler left a comment

Choose a reason for hiding this comment

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

Re-tested on TS4. Detail page looks good. I did not find any problems, thanks for implementing my prior requests.

@marlonnienaber
Copy link
Contributor Author

marlonnienaber commented Oct 3, 2025

Re-tested on TS4.

Lgtm; I never said it before, but I especially like that the Attendance value can display values above 100% (the Utilization bar in the Manage View can't do that).

Fun fact, the attendance value text can leak into the Attendance circle, but that is such an unrealistic scenario that I think it's fine either way.

Seems like the inputs in the management view are not validated correctly. Such inputs should not be possible. Out of scope for this PR though.

@krusche krusche changed the title Tutorial groups: Refactor student tutorial group detail page Tutorial groups: Improve student tutorial group detail page Oct 3, 2025
@krusche krusche added this to the 8.4.1 milestone Oct 3, 2025
@krusche krusche merged commit db5bd19 into develop Oct 3, 2025
52 of 59 checks passed
@github-project-automation github-project-automation bot moved this from Ready For Review to Merged in Artemis Development Oct 3, 2025
@krusche krusche deleted the chore/student-tutorial-group-session-refactoring branch October 3, 2025 17:11
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 ready to merge server Pull requests that update Java code. (Added Automatically!) tests tutorialgroup Pull requests that affect the corresponding module
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

9 participants