Skip to content

Conversation

@krusche
Copy link
Member

@krusche krusche commented Apr 18, 2025

We want to deprecate simple lecture attachments in the future and guide instructors to use attachment units, because they offer much more functionality, e.g.:

  • Referencing attachments in single (PDF) slides in the communication channels
  • Adding attachments to Iris (for improved answers when asking questins)
  • Completing the unit after reading the attachment (by students)
  • Referencing the unit in competencies

This PR is a first step and removes adding simple lecture attachments. Instead, the UI forwards instructors to the creation of attachment units. Old simple lecture attachments are still accessible for instructors and students. Instructors can edit and delete them, but cannot create new ones.

In addition, this PR significantly improves the performance in a few places, in particular for courses with multiple lectures, attachment units and slides. I created DTOs and improve database calls to minimize data transfer between server and database and between server and client for the lectures-with-slides REST call.

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 authorities to all new routes and checked the course groups for displaying navigation elements (links, buttons).
  • I documented the TypeScript code using JSDoc style.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Create a lecture, navigate to attachments and click on the new Add button to add a few attachment units (e.g. lecture slides as PDF)
  2. Load the lectures in course management and make sure it's fast even with multiple lectures with many slides
  3. Go to the communication section and make sure (e.g. by looking into the network tab in the browser development tools) that the REST Call lectures-with-slides is super fast
  4. Reference lectures, whole attachment units, and single slides in a channel in communication and make sure this works without any issues (incl. preview and/or clicking on the link)

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

No real changes. I remove functionality and made other functionality faster.

Screenshots

New button:
image

Adding slides in a channel
image

Fast REST call despite its size and data:
image

Realized with a custom DTO
image

Summary by CodeRabbit

  • New Features

    • Introduced new data transfer objects (DTOs) for lectures, attachments, and slides, improving the structure and filtering of lecture-related data in API responses.
    • Added an efficient method to retrieve visible slides for multiple attachment units.
  • Bug Fixes

    • Improved Angular change detection by updating tracking expressions in templates for course lists and reaction metadata.
  • Refactor

    • Replaced direct entity-based lecture API responses with filtered DTO-based responses for better control and data visibility.
    • Updated dependency injection in several Angular components and pipes to use the inject() function.
    • Simplified and clarified filtering logic for lecture content visibility.
  • Chores

    • Removed the ability to create new attachments through the UI and corresponding backend endpoints.
    • Deleted unused or obsolete methods and tests related to attachment creation and lecture details with slides.
    • Adjusted test setups and removed tests for deprecated features.
    • Updated localization for the "Add Attachment" action to clarify its new behavior.
    • Removed "view" button for attachments and replaced the "Add Attachment" button with a navigation link in the UI.

@krusche krusche added this to the 8.0.0 milestone Apr 18, 2025
@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Apr 18, 2025
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) documentation core Pull requests that affect the corresponding module lecture Pull requests that affect the corresponding module labels Apr 18, 2025
@github-actions github-actions bot added communication Pull requests that affect the corresponding module tutorialgroup Pull requests that affect the corresponding module labels Apr 18, 2025
@github-actions github-actions bot added the programming Pull requests that affect the corresponding module label Apr 18, 2025
@krusche krusche marked this pull request as ready for review April 18, 2025 21:00
@krusche krusche requested review from a team as code owners April 18, 2025 21:00
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 18, 2025

Walkthrough

This set of changes removes the ability to create attachments directly via file upload in the lecture management system. The backend endpoint and service methods for creating attachments with files are deleted, and the corresponding UI elements and logic for adding new attachments are removed or replaced with navigation to a different creation route. The lecture and slide retrieval logic is refactored to use DTOs for controlled data exposure, with filtering for visible slides and attachment units. Related test cases for attachment creation and lecture slide retrieval are removed or updated. Additionally, some dependency injection patterns are modernized, and translation strings are updated for clarity.

Changes

File(s) / Path(s) Change Summary
src/main/webapp/app/lecture/manage/services/attachment.service.ts,
src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.ts,
src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.html,
src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentResource.java,
src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java
Removed all logic, UI, and backend endpoints for creating attachments via file upload; deleted related methods and tests; replaced "Add Attachment" button with a navigation link to attachment unit creation.
src/main/webapp/app/lecture/manage/services/attachment.service.spec.ts,
src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.spec.ts
Removed or updated tests related to attachment creation and view button availability; retained only update and delete related tests.
src/main/webapp/app/lecture/manage/services/lecture.service.ts,
src/main/webapp/app/lecture/manage/services/lecture.service.spec.ts,
src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java,
src/test/java/de/tum/cit/aet/artemis/lecture/LectureIntegrationTest.java
Removed endpoint and service method for fetching lecture details with slides; refactored lecture-with-slides endpoint to use DTOs, filter for visibility, and aggregate slides efficiently; updated or removed related tests.
src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java,
src/main/java/de/tum/cit/aet/artemis/lecture/dto/SlideDTO.java
Added SlideDTO record; introduced efficient query to fetch visible slides by attachment unit IDs; refactored unhide operation to use JPQL update.
src/main/java/de/tum/cit/aet/artemis/lecture/repository/LectureRepository.java Removed queries and methods for fetching lectures with slides; adjusted remaining queries for explicit joins.
src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java,
src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureTranscription.java
Removed bidirectional relationship between lecture units and lecture transcriptions to avoid eager loading issues; cleaned up related annotations and comments.
src/main/java/de/tum/cit/aet/artemis/lecture/service/LectureService.java Removed method for filtering hidden slides from attachment units.
src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureTranscriptionResource.java Changed deletion logic for lecture transcriptions to use repository query rather than direct field access; fixed minor Javadoc.
src/main/webapp/app/lecture/manage/lecture/lecture.component.ts,
src/main/webapp/app/lecture/manage/lecture/lecture.component.spec.ts
Updated to use new lecture fetching method without slides; adjusted imports to use absolute paths.
src/main/webapp/app/lecture/overview/course-lectures/lecture-unit/lecture-unit.component.ts,
src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.ts
Refactored to use Angular's inject() function for dependency injection; updated method signature in pipe to add optional parameter.
src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.html,
src/main/webapp/app/core/course/shared/course-sidebar/course-sidebar.component.html
Changed Angular template tracking expressions to use unique keys/IDs for improved rendering.
src/main/webapp/app/core/user/settings/user-settings-container/user-settings-container.component.spec.ts,
src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.spec.ts
Refactored tests to use Angular's TestBed and improved dependency injection patterns.
src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java Added a new static method for SHA-256 hashing of strings.
jest.config.js Slightly reduced global coverage thresholds for statements and branches.
docs/admin/accessRights.rst,
docs/dev/guidelines/client-design.rst
Updated documentation to reflect removal of attachment creation and changes in Angular dependency injection patterns.
src/main/webapp/i18n/en/global.json,
src/main/webapp/i18n/de/global.json
Updated translation strings for "Add attachment" to clarify that it's now "Add attachment as lecture unit."

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant Backend
    participant DB

    User->>UI: Navigate to lecture attachments
    UI->>Backend: GET /lectures-with-slides
    Backend->>DB: Query lectures, attachments, attachment units
    Backend->>DB: Query visible slides for attachment units
    Backend->>UI: Return List<LectureDTO> (with filtered, visible slides)
    UI->>User: Display lectures, attachments, and slides

    User->>UI: Click "Add attachment as lecture unit"
    UI->>UI: Navigate to /unit-management/attachment-units/create
Loading

Possibly related PRs

  • ls1intum/Artemis#10487: The main PR removes the lectureTranscription field and its getter/setter from the LectureUnit class, while the retrieved PR adds the lectureTranscription field and its getter/setter to the same class, indicating that these changes are directly related but inverse modifications to the same code element.

Suggested labels

feature, database

Suggested reviewers

  • florian-glombik
  • ole-ve

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a00c1b5 and 2a19e64.

📒 Files selected for processing (2)
  • jest.config.js (1 hunks)
  • src/main/webapp/app/lecture/manage/lecture-update/lecture-update.component.html (0 hunks)
💤 Files with no reviewable changes (1)
  • src/main/webapp/app/lecture/manage/lecture-update/lecture-update.component.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • jest.config.js
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-tests-selected
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: Analyse

🪧 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.
  • @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
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

🔭 Outside diff range comments (1)
src/main/java/de/tum/cit/aet/artemis/lecture/repository/LectureRepository.java (1)

46-54: ⚠️ Potential issue

lu.attachment breaks the JPA type‑system – use TREAT and DISTINCT

lecture.lectureUnits is a polymorphic association of the abstract type LectureUnit.
Dereferencing lu.attachment is illegal JPA because that attribute exists only on AttachmentUnit.
Hibernate will accept it in lenient mode but other providers – or future Hibernate versions with strict compliance enabled – will throw IllegalArgumentException: could not resolve property: attachment.

In addition, the extra joins introduce row duplication; relying on Set<Lecture> to de‑duplicate happens in Java rather than SQL and wastes memory.

-SELECT lecture
+SELECT DISTINCT lecture
 ...
-    LEFT JOIN FETCH lecture.lectureUnits lu
-    LEFT JOIN FETCH lu.attachment
+    LEFT JOIN FETCH lecture.lectureUnits lu
+    LEFT JOIN FETCH TREAT(lu AS de.tum.cit.aet.artemis.lecture.domain.AttachmentUnit).attachment

This keeps the query portable and reduces the result set size.

🧹 Nitpick comments (4)
jest.config.js (1)

94-95: Verify coverage threshold adjustments
The statements threshold has been lowered to 88.96% (from 88.98%) and branches to 75.15% (from 75.18%) to account for removed tests. Please confirm these new values accurately reflect current coverage reports and remain aligned with the TODO note on line 93 about eventually reaching 90%.

src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java (1)

27-35: Well-implemented SHA-256 hashing method.

The implementation is clean, with proper exception handling and documentation. The method follows good practices by using a standardized character encoding and leveraging the MessageDigest API correctly.

Minor inconsistency in error message wording:

-            throw new IllegalStateException("Failed to hash token", e);
+            throw new IllegalStateException("Failed to hash secret", e);

The parameter is named "secret" but the error message refers to "token".

src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java (1)

114-116: Consider documenting / mitigating eager loading via @OneToOne instead of omitting the association altogether

The comment explains why LectureTranscription is left out, but losing the navigation property forces every consumer to reach into the repository layer whenever they need the transcription.
With Hibernate 6 you can keep the property if you:

  1. Declare it with @OneToOne(fetch = FetchType.LAZY, optional = true) and
  2. Enable byte‑code enhancement (already used in Artemis for other lazy @OneToOnes).

This preserves the domain model without incurring unnecessary queries.

src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (1)

260-267: AttachmentUnitDTO.from leaks mutable state via a shared ArrayList

slides is created with new ArrayList<>() and then exposed directly. Callers can mutate it inadvertently, breaking immutability expectations of a record.
Return List.of() and let the assembly code replace the list when necessary:

-return new AttachmentUnitDTO(attachmentUnit.getId(), attachmentUnit.getName(), new ArrayList<>(), …
+return new AttachmentUnitDTO(attachmentUnit.getId(), attachmentUnit.getName(), new ArrayList<>(), …)  // <- if you keep it

or

return new AttachmentUnitDTO(
        attachmentUnit.getId(),
        attachmentUnit.getName(),
        Collections.emptyList(),
        AttachmentDTO.from(attachmentUnit.getAttachment()),
        attachmentUnit.getReleaseDate(),
        "attachment");
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 96a2285 and 00d2161.

📒 Files selected for processing (32)
  • docs/admin/accessRights.rst (0 hunks)
  • docs/dev/guidelines/client-design.rst (1 hunks)
  • jest.config.js (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureTranscription.java (0 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/dto/SlideDTO.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/LectureRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/LectureService.java (0 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentResource.java (0 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (8 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureTranscriptionResource.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java (1 hunks)
  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.html (1 hunks)
  • src/main/webapp/app/core/course/shared/course-sidebar/course-sidebar.component.html (1 hunks)
  • src/main/webapp/app/core/user/settings/user-settings-container/user-settings-container.component.spec.ts (2 hunks)
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.html (1 hunks)
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.spec.ts (0 hunks)
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.ts (2 hunks)
  • src/main/webapp/app/lecture/manage/lecture/lecture.component.spec.ts (2 hunks)
  • src/main/webapp/app/lecture/manage/lecture/lecture.component.ts (2 hunks)
  • src/main/webapp/app/lecture/manage/services/attachment.service.spec.ts (0 hunks)
  • src/main/webapp/app/lecture/manage/services/attachment.service.ts (0 hunks)
  • src/main/webapp/app/lecture/manage/services/lecture.service.spec.ts (0 hunks)
  • src/main/webapp/app/lecture/manage/services/lecture.service.ts (0 hunks)
  • src/main/webapp/app/lecture/overview/course-lectures/lecture-unit/lecture-unit.component.ts (2 hunks)
  • src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.spec.ts (5 hunks)
  • src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.ts (2 hunks)
  • src/main/webapp/i18n/de/global.json (1 hunks)
  • src/main/webapp/i18n/en/global.json (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java (0 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/LectureIntegrationTest.java (0 hunks)
💤 Files with no reviewable changes (11)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureTranscription.java
  • src/main/webapp/app/lecture/manage/services/lecture.service.spec.ts
  • src/main/webapp/app/lecture/manage/services/lecture.service.ts
  • src/main/webapp/app/lecture/manage/services/attachment.service.ts
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/LectureService.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentResource.java
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentResourceIntegrationTest.java
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.spec.ts
  • docs/admin/accessRights.rst
  • src/test/java/de/tum/cit/aet/artemis/lecture/LectureIntegrationTest.java
  • src/main/webapp/app/lecture/manage/services/attachment.service.spec.ts
🧰 Additional context used
📓 Path-based instructions (4)
`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:PascalC...

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/core/user/settings/user-settings-container/user-settings-container.component.spec.ts
  • src/main/webapp/app/lecture/overview/course-lectures/lecture-unit/lecture-unit.component.ts
  • src/main/webapp/app/lecture/manage/lecture/lecture.component.ts
  • src/main/webapp/app/lecture/manage/lecture/lecture.component.spec.ts
  • src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.spec.ts
  • src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.ts
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.ts
`src/main/webapp/**/*.html`: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

src/main/webapp/**/*.html: @if and @for are new and valid Angular syntax replacing *ngIf and *ngFor. They should always be used over the old style.

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.html
  • src/main/webapp/app/core/course/shared/course-sidebar/course-sidebar.component.html
  • src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.html
`src/main/webapp/i18n/de/**/*.json`: German language translations should be informal (dutzen) and should never be formal (sietzen). So the user should always be addressed with "du/...

src/main/webapp/i18n/de/**/*.json: German language translations should be informal (dutzen) and should never be formal (sietzen). So the user should always be addressed with "du/dein" and never with "sie/ihr".

  • src/main/webapp/i18n/de/global.json
`src/main/java/**/*.java`: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,de...

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/lecture/web/LectureTranscriptionResource.java
  • src/main/java/de/tum/cit/aet/artemis/programming/service/localvc/ssh/HashUtils.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/dto/SlideDTO.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/LectureRepository.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java
🧬 Code Graph Analysis (2)
src/main/webapp/app/core/user/settings/user-settings-container/user-settings-container.component.spec.ts (1)
src/test/javascript/spec/helpers/mocks/service/mock-profile.service.ts (1)
  • MockProfileService (4-22)
src/main/java/de/tum/cit/aet/artemis/lecture/dto/SlideDTO.java (1)
src/main/webapp/app/lecture/shared/entities/lecture-unit/slide.model.ts (1)
  • Slide (4-10)
🔇 Additional comments (23)
src/main/webapp/app/core/user/settings/user-settings-container/user-settings-container.component.spec.ts (1)

3-3: Proper test setup with ProfileService provider.

The addition of ProfileService and its mock implementation to the test setup ensures consistent service provisioning, aligning with the PR's enhanced dependency injection patterns.

Also applies to: 5-5, 33-33

src/main/webapp/app/core/course/shared/course-sidebar/course-sidebar.component.html (1)

17-17: Good adoption of tracking by unique ID for performance optimization.

Using track courseItem.id is a performance best practice for Angular's change detection as it allows more efficient DOM updates by tracking stable identifiers rather than object identity.

src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.html (1)

52-52: Good adoption of key-based tracking for performance optimization.

Using track reactionMetaData.key ensures efficient DOM updates by tracking stable identifiers rather than object references, which is important for the keyvalue pipe output.

src/main/webapp/app/lecture/overview/course-lectures/lecture-unit/lecture-unit.component.ts (1)

1-1: Good modernization to standalone injection pattern.

The change to use Angular's standalone inject() function instead of constructor-based dependency injection aligns with modern Angular practices and the project's coding standards.

Also applies to: 21-21

docs/dev/guidelines/client-design.rst (1)

212-212: Documentation accurately updated to reflect modern injection pattern.

The example code now correctly demonstrates the preferred Angular dependency injection pattern using the standalone inject() function instead of constructor injection, maintaining consistency with the actual implementation.

src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.spec.ts (3)

1-24: Good modernization of test setup using TestBed.

The test setup has been improved to use Angular's TestBed for proper dependency injection rather than manual mocking. This approach better mirrors real application behavior and makes the tests more maintainable.


32-33: Good adoption of Jest spies for cleaner testing.

Using jest.spyOn provides better verification capabilities for method calls compared to direct mock implementations, making the test more robust and easier to maintain.

Also applies to: 46-47, 61-62, 76-77


51-52: Properly updated method call verification to use spies.

The assertions now correctly verify the calls to the translated service using the spy, which is more maintainable and provides clearer failure messages when tests fail.

Also applies to: 66-67, 81-82

src/main/webapp/app/tutorialgroup/shared/pipe/meeting-pattern.pipe.ts (2)

1-1: Good modernization of dependency injection.

Replacing constructor-based injection with Angular's standalone inject() function follows modern Angular practices and simplifies the code. This change aligns with Angular's push toward functional programming patterns.

Also applies to: 17-17


22-22: Well-implemented feature extension with backward compatibility.

The addition of the optional includeRepetitionFrequency parameter with:

  • Proper JSDoc documentation
  • Default value preserving backward compatibility
  • Clean conditional implementation

This change provides flexibility while maintaining existing functionality for callers.

Also applies to: 25-25, 31-31

src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java (2)

70-77: Good refactoring of unhideSlide with direct JPQL

The refactoring from an entity-based approach to a direct JPQL update query with @Modifying and @Transactional annotations is a good performance improvement that avoids unnecessary entity loading and reduces database overhead.


79-85: Well-designed query for optimized slide retrieval

This new query method efficiently retrieves only visible slides as DTOs for the specified attachment units, filtering based on the hidden status. The use of DTOs and specific field selection aligns perfectly with the PR objective to improve performance for courses with multiple lectures and slides.

src/main/webapp/i18n/en/global.json (1)

248-248: Updated text clarifies the preferred attachment creation method

The text change from "Add attachment" to "Add attachment as lecture unit" effectively communicates to users that attachments should now be created as lecture units, aligning with the PR objective to deprecate simple lecture attachments.

src/main/webapp/i18n/de/global.json (1)

248-248: Correctly updated German translation using informal language

The German translation has been properly updated to "Anhang als Vorlesungseinheit hinzufügen" and correctly uses the informal form ("dutzen") as required by the coding guidelines. This maintains consistency with the English version and communicates the same information about creating attachments as lecture units.

src/main/webapp/app/lecture/manage/lecture/lecture.component.spec.ts (2)

132-139: Updated method name in test mock

The mock provider now uses findAllByCourseId instead of findAllByCourseIdWithSlides, correctly reflecting the service method changes as part of the DTO-based optimization.


172-173: Updated spy to match new method name

The test now correctly spies on findAllByCourseId instead of findAllByCourseIdWithSlides, maintaining test validity after the service refactoring to use DTOs for improved performance.

src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureTranscriptionResource.java (2)

98-99: Optimized transcription replacement logic.

Excellent approach to finding and deleting existing transcriptions by lectureUnitId before creating a new one. This change properly handles the removal of the direct bidirectional entity references between LectureUnit and LectureTranscription, shifting to a repository-based approach.


109-109: Fixed Javadoc URL path format.

The corrected URL path format in the Javadoc improves documentation accuracy.

src/main/java/de/tum/cit/aet/artemis/lecture/dto/SlideDTO.java (1)

1-16: Well-designed DTO for performance optimization.

This SlideDTO record follows best practices for DTOs:

  • Uses Java record for immutability and compact syntax
  • Includes JsonInclude annotation to optimize serialization
  • Provides a clear static factory method for entity conversion
  • Contains only necessary data fields without exposing entities
  • Properly extracts nested entity IDs (attachmentUnitId)

The introduction of this DTO aligns perfectly with the PR objective of optimizing performance for courses with multiple lectures, attachment units, and slides by reducing data transfer between server and client.

src/main/webapp/app/lecture/manage/lecture/lecture.component.ts (2)

20-21: Improved import paths for consistency.

Good refactoring of imports from relative to absolute paths starting with 'app/shared/...'. This change makes imports more consistent and follows Angular style guidelines.

Also applies to: 24-26, 28-28


184-184: Updated service method to align with backend changes.

The update from findAllByCourseIdWithSlides to findAllByCourseId correctly aligns with the backend refactoring where slide data is now handled with DTOs for better performance. This change supports the PR objective of optimizing database calls and reducing data transfer.

src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.html (1)

198-203: Redirect to attachment units creation instead of direct attachment creation.

This UI change correctly implements the PR's core objective of deprecating simple lecture attachments in favor of attachment units. By replacing the "Add Attachment" button with a router link to the attachment units creation page, the UI now guides instructors toward the preferred approach that offers enhanced functionality.

src/main/webapp/app/lecture/manage/lecture-attachments/lecture-attachments.component.ts (1)

7-23: Imports look consistent with the new “update‑only” flow

Obsolete symbols related to creating / viewing attachments (e.g. faEye, AttachmentType) have been removed and the remaining imports compile fine. No further action required.

Also applies to: 44-44

@github-project-automation github-project-automation bot moved this from Work In Progress to Ready For Review in Artemis Development Apr 18, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran196 passed3 skipped2 failed52m 49s 689ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure28s 610ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure1m 44s 992ms

Copy link
Contributor

@eceeeren eceeeren left a comment

Choose a reason for hiding this comment

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

Tested locally, all of the functionalities for Attachments and Attachment Units seem to work corrrectly. I only found an issue with referencing a slide when some pages are hidden.

ahmetsenturk
ahmetsenturk previously approved these changes Apr 18, 2025
Copy link
Contributor

@ahmetsenturk ahmetsenturk left a comment

Choose a reason for hiding this comment

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

Tested locally, all functionalities work as described - the requests are pretty fast, and the references in the communication section work out as well (clicking on units automatically redirects to the attachment - pptx automatically downloads pdf opens the file in another tab) 👍

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 19, 2025
@krusche
Copy link
Member Author

krusche commented Apr 19, 2025

I tested this locally, seems good. Performance LGTM. I added a few inline comments.

Additionally, I suggest that we remove the Attachments section in the Wizard, as its kinda redundant with the units rendered directly below:

CleanShot 2025-04-18 at 23 40 33

Thanks for the feedback. I agree that we should remove it here

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 19, 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: 0

♻️ Duplicate comments (1)
src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (1)

225-226: 🛠️ Refactor suggestion

Handle empty attachment unit sets to avoid dialect-specific SQL issues.

When calling slideRepository.findVisibleSlidesByAttachmentUnits() with an empty set, some databases might produce syntax errors with queries like IN ().

-Set<SlideDTO> slides = slideRepository.findVisibleSlidesByAttachmentUnits(attachmentUnitIds);
+Set<SlideDTO> slides = attachmentUnitIds.isEmpty()
+        ? Set.of()
+        : slideRepository.findVisibleSlidesByAttachmentUnits(attachmentUnitIds);
🧹 Nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (1)

229-240: Consider adding null checks for data structure access.

When accessing the map with slidesByAttachmentUnitId.get(attachmentUnitDTO.id), you're correctly checking for null, but consider using getOrDefault for more concise code.

-List<SlideDTO> slidesForAttachmentUnit = slidesByAttachmentUnitId.get(attachmentUnitDTO.id);
-if (slidesForAttachmentUnit != null) {
-    // remove unnecessary fields from the slide DTOs
-    var finalSlides = slidesForAttachmentUnit.stream()
-        .map(slideDTO -> new SlideDTO(slideDTO.id(), slideDTO.slideNumber(), null, null))
-        .sorted(Comparator.comparingInt(SlideDTO::slideNumber)).toList();
-    attachmentUnitDTO.slides.addAll(finalSlides);
-}
+List<SlideDTO> slidesForAttachmentUnit = slidesByAttachmentUnitId.getOrDefault(attachmentUnitDTO.id, List.of());
+if (!slidesForAttachmentUnit.isEmpty()) {
+    // remove unnecessary fields from the slide DTOs
+    var finalSlides = slidesForAttachmentUnit.stream()
+        .map(slideDTO -> new SlideDTO(slideDTO.id(), slideDTO.slideNumber(), null, null))
+        .sorted(Comparator.comparingInt(SlideDTO::slideNumber)).toList();
+    attachmentUnitDTO.slides.addAll(finalSlides);
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 45ff162 and a00c1b5.

📒 Files selected for processing (3)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java (2 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/de/tum/cit/aet/artemis/lecture/domain/LectureUnit.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/repository/SlideRepository.java
🧰 Additional context used
📓 Path-based instructions (1)
`src/main/java/**/*.java`: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,de...

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/lecture/web/LectureResource.java
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: client-tests
  • GitHub Check: client-tests-selected
  • GitHub Check: server-tests
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: Analyse
🔇 Additional comments (6)
src/main/java/de/tum/cit/aet/artemis/lecture/web/LectureResource.java (6)

53-53: Good security enhancement with permission annotation.

The shift to using @EnforceAtLeastStudentInCourse is appropriate and aligns with modern authorization patterns, making security enforcement more declarative.


81-81: Good dependency management with constructor injection.

Adding the SlideRepository dependency through constructor injection is a clean pattern that maintains proper dependency inversion. The use of constructor injection instead of field injection follows best practices.

Also applies to: 108-119


216-246: Performance and data transfer optimization looks good.

The implementation efficiently retrieves only necessary data with several notable optimizations:

  1. Proper filtering of visible lectures for students
  2. Separate loading of slides to avoid large data exchanges
  3. Grouping slides by attachment unit for efficient organization
  4. Stripping unnecessary fields from DTOs
  5. Good performance logging to track execution time

249-267: Good DTO design with Java records.

The use of Java records for DTOs is an excellent choice that:

  1. Reduces boilerplate code
  2. Provides immutability
  3. Has controlled serialization with @JsonInclude(JsonInclude.Include.NON_EMPTY)
  4. Clear transformation logic with static factory methods
  5. Proper filtering for student visibility

268-283: DTO hierarchy maintains single responsibility.

Both AttachmentDTO and AttachmentUnitDTO follow single responsibility principle, each representing a distinct domain concept with appropriate transformations.


416-422: Modern Java switch expression is a great improvement.

The refactoring to use the switch expression instead of multiple if-else statements improves readability and reduces the potential for bugs by enforcing exhaustive pattern matching.

@krusche
Copy link
Member Author

krusche commented Apr 19, 2025

Thanks everyone for testing and revieweing

@helios-aet helios-aet bot temporarily deployed to artemis-test2.artemis.cit.tum.de April 19, 2025 06:55 Inactive
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report201 ran197 passed3 skipped1 failed47m 32s 369ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/course/CourseMessages.spec.ts
ts.Course messages › Channel messages › Write/edit/delete message in channel › Student should be able to edit message in channel❌ failure26s 227ms

@krusche krusche merged commit 8e6f67d into develop Apr 19, 2025
32 of 37 checks passed
@krusche krusche deleted the feature/prefer-attachment-units branch April 19, 2025 07:05
@github-project-automation github-project-automation bot moved this from Ready For Review to Merged in Artemis Development Apr 19, 2025
@github-project-automation github-project-automation bot moved this from Todo to Done in Communication Webclient Apr 19, 2025
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 documentation lecture Pull requests that affect the corresponding module programming Pull requests that affect the corresponding module ready for review server Pull requests that update Java code. (Added Automatically!) tests tutorialgroup Pull requests that affect the corresponding module

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants