Skip to content

Lectures: Merge attachment and video unit #10575

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

Merged
merged 200 commits into from
May 25, 2025

Conversation

sebastianloose
Copy link
Contributor

@sebastianloose sebastianloose commented Mar 24, 2025

Checklist

General

Server

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

Motivation and Context

To enable the linking of attachments to lecture transcriptions, the video unit and attachment unit have been merged into a single attachment-video unit. In the future, this unit can be sent to Pyris to simultaneously ingest transcriptions and slides. This integration is essential for providing Iris with the best context when answering questions about specific lecture topics.

Description

  • Video unit was deleted
  • attachment video unit now contains a video source and can display a video player
  • an attachment video unit must either contain an attachment, a video source or both
  • attachment video unit release date and name are no longer saved in the attachment but in the unit itself
  • already existing video units will be converted to attachment video units without an attachment

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Lecture
  1. Log in to Artemis
  2. Go to a lecture
  3. Create a new File/Video Unit
  4. Enter a name and upload an attachment and save the new unit
  5. Try to edit the newly created unit and save it
  6. Create a new File/Video Unit
  7. Enter a name and specify a video source and save the new unit
  8. Try also to edit this Unit
  9. Create a new File/Video Unit
  10. Enter a name, a video source and upload a file and save the new unit
  11. Also try to edit this unit
  12. If you inserted a valid video source you should also be able to watch the video when clicking on a unit with video

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

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Screenshots

grafik
grafik

Summary by CodeRabbit

  • New Features

    • Unified attachment and video lecture units into a single "Attachment Video Unit" type supporting file uploads and embeddable video URLs.
    • Enhanced forms with validation and automatic transformation for embeddable video URLs including YouTube and TUM-Live.
    • Updated lecture unit management, slide splitting, and ingestion processes for video attachment units.
  • Refactor

    • Replaced all "Attachment Unit" and "Video Unit" entities, services, forms, components, routes, API endpoints, and translations with "Attachment Video Unit" counterparts.
    • Removed legacy video unit-specific code, forms, resources, and tests.
    • Updated internal and external references, including file paths, repository interfaces, and authorization checks, to use the new entity.
  • Bug Fixes

    • Improved validation and error handling for video URLs and file uploads.
    • Fixed slide handling and file operations consistency under the unified unit type.
  • Documentation

    • Updated UI labels, tooltips, help texts, and breadcrumbs to reflect the "Attachment Video Unit" concept.
  • Tests

    • Replaced and extended test coverage to focus on "Attachment Video Unit" features, removing tests for separate attachment and video units.

@helios-aet helios-aet bot temporarily deployed to artemis-test3.artemis.cit.tum.de May 24, 2025 18:54 Inactive
coderabbitai[bot]
coderabbitai bot previously approved these changes May 24, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed1s 965ms
TestResultTime ⏱
No test annotations available

@helios-aet helios-aet bot temporarily deployed to artemis-test2.artemis.cit.tum.de May 24, 2025 20:17 Inactive
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report201 ran198 passed3 skipped0 failed50m 9s 434ms
TestResultTime ⏱
No test annotations available

@helios-aet helios-aet bot temporarily deployed to artemis-test9.artemis.cit.tum.de May 25, 2025 15:50 Inactive
@helios-aet helios-aet bot temporarily deployed to artemis-test4.artemis.cit.tum.de May 25, 2025 15:52 Inactive
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 (3)
src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (3)

33-35: Add @transactional annotation for data consistency.

Methods like createAttachmentVideoUnit, updateAttachmentVideoUnit, and handleStudentVersionFile perform operations across multiple repositories and the file system. Without transactional boundaries, runtime exceptions could leave the system in an inconsistent state.

The coding guidelines mention "avoid_transactions" but this appears to refer to avoiding unnecessary transactions. For operations that modify multiple data sources, transactions are essential for consistency.

 @Profile(PROFILE_CORE)
 @Service
+@Transactional
 public class AttachmentVideoUnitService {

103-156: 🛠️ Refactor suggestion

Refactor large method to improve maintainability.

The updateAttachmentVideoUnit method is 54 lines long and handles multiple responsibilities: metadata updates, competency link management, attachment creation/updates, file handling, and external API calls. This violates the "small_methods" principle from the coding guidelines.

Consider extracting the attachment handling logic into separate private methods:

 public AttachmentVideoUnit updateAttachmentVideoUnit(AttachmentVideoUnit existingAttachmentVideoUnit, AttachmentVideoUnit updateUnit, Attachment updateAttachment,
         MultipartFile updateFile, boolean keepFilename, List<HiddenPageInfoDTO> hiddenPages, List<SlideOrderDTO> pageOrder) {
     Set<CompetencyLectureUnitLink> existingCompetencyLinks = new HashSet<>(existingAttachmentVideoUnit.getCompetencyLinks());
     
-    existingAttachmentVideoUnit.setDescription(updateUnit.getDescription());
-    existingAttachmentVideoUnit.setName(updateUnit.getName());
-    existingAttachmentVideoUnit.setReleaseDate(updateUnit.getReleaseDate());
-    existingAttachmentVideoUnit.setCompetencyLinks(updateUnit.getCompetencyLinks());
-    existingAttachmentVideoUnit.setVideoSource(updateUnit.getVideoSource());
+    updateUnitMetadata(existingAttachmentVideoUnit, updateUnit);
     
-    Attachment existingAttachment = existingAttachmentVideoUnit.getAttachment();
-    
-    if (existingAttachment == null && updateAttachment != null) {
-        createAttachment(updateAttachment, existingAttachmentVideoUnit, updateFile, keepFilename);
-    }
+    handleAttachmentUpdate(existingAttachmentVideoUnit, updateAttachment, updateFile, keepFilename, hiddenPages, pageOrder);
     
     AttachmentVideoUnit savedAttachmentVideoUnit = lectureUnitService.saveWithCompetencyLinks(existingAttachmentVideoUnit, attachmentVideoUnitRepository::saveAndFlush);
     
-    // Set the original competencies back to the attachment video unit so that the competencyProgressService can determine which competencies changed
-    existingAttachmentVideoUnit.setCompetencyLinks(existingCompetencyLinks);
-    competencyProgressApi.ifPresent(api -> api.updateProgressForUpdatedLearningObjectAsync(existingAttachmentVideoUnit, Optional.of(updateUnit)));
+    updateCompetencyProgress(existingAttachmentVideoUnit, existingCompetencyLinks, updateUnit);
+    notifyExternalServices(savedAttachmentVideoUnit);
     
     return savedAttachmentVideoUnit;
 }

196-203: 🛠️ Refactor suggestion

Enhance file validation for security.

The handleFile method only checks if the file is not null and not empty, but doesn't validate file types, sizes, or other security constraints. This could pose security risks with malicious file uploads.

Consider adding comprehensive file validation:

 private void handleFile(MultipartFile file, Attachment attachment, boolean keepFilename, Long attachmentVideoUnitId) {
     if (file != null && !file.isEmpty()) {
+        validateFile(file);
         Path basePath = FilePathConverter.getAttachmentVideoUnitFileSystemPath().resolve(attachmentVideoUnitId.toString());
         Path savePath = fileService.saveFile(file, basePath, FilePathType.ATTACHMENT_UNIT, keepFilename);
         attachment.setLink(FilePathConverter.externalUriForFileSystemPath(savePath, FilePathType.ATTACHMENT_UNIT, attachmentVideoUnitId).toString());
         attachment.setUploadDate(ZonedDateTime.now());
     }
 }
+
+private void validateFile(MultipartFile file) {
+    // Validate file type, size, and other security constraints
+    String contentType = file.getContentType();
+    long size = file.getSize();
+    // Add validation logic here
+}
🧹 Nitpick comments (2)
src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (2)

104-104: Simplify method signature.

The method signature has 7 parameters, which makes it complex and hard to use. Consider creating a parameter object or DTO to encapsulate the update data.

public class AttachmentVideoUnitUpdateRequest {
    private AttachmentVideoUnit updateUnit;
    private Attachment updateAttachment;
    private MultipartFile updateFile;
    private boolean keepFilename;
    private List<HiddenPageInfoDTO> hiddenPages;
    private List<SlideOrderDTO> pageOrder;
    // constructors, getters, setters
}

public AttachmentVideoUnit updateAttachmentVideoUnit(AttachmentVideoUnit existingAttachmentVideoUnit, 
                                                   AttachmentVideoUnitUpdateRequest request) {
    // method implementation
}

250-253: Review the client preparation method.

The prepareAttachmentVideoUnitForClient method sets collections to null, which might cause issues if the client code expects empty collections instead of null values. Consider setting empty collections or documenting this behavior clearly.

 public void prepareAttachmentVideoUnitForClient(AttachmentVideoUnit attachmentVideoUnit) {
-    attachmentVideoUnit.getLecture().setLectureUnits(null);
-    attachmentVideoUnit.getLecture().setAttachments(null);
+    attachmentVideoUnit.getLecture().setLectureUnits(Collections.emptyList());
+    attachmentVideoUnit.getLecture().setAttachments(Collections.emptyList());
 }

Alternatively, add clear documentation about why null is preferred over empty collections.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fb53573 and c16d085.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (9)
  • gradle/jacoco.gradle (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideSplitterService.java (11 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentVideoUnitResource.java (6 hunks)
  • src/main/webapp/app/communication/posting-content/posting-content-part/posting-content-part.component.spec.ts (3 hunks)
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.spec.ts (23 hunks)
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.ts (18 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentVideoUnitIntegrationTest.java (14 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideSplitterServiceTest.java (35 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • gradle/jacoco.gradle
  • src/main/webapp/app/communication/posting-content/posting-content-part/posting-content-part.component.spec.ts
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.spec.ts
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentVideoUnitIntegrationTest.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/SlideSplitterService.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentVideoUnitResource.java
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.ts
  • src/test/java/de/tum/cit/aet/artemis/lecture/service/SlideSplitterServiceTest.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/service/AttachmentVideoUnitService.java
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • 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: server-tests
  • GitHub Check: client-tests
  • GitHub Check: Analyse

coderabbitai[bot]
coderabbitai bot previously approved these changes May 25, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed2s 55ms
TestResultTime ⏱
No test annotations available

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 (3)
src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (3)

33-35: Add @transactional annotation for data consistency

The service methods perform database operations and file system modifications that should be transactional to prevent inconsistent state on exceptions.


103-157: Break down this complex method into smaller focused methods

This method is too large (55+ lines) and handles multiple responsibilities, violating the "small_methods" principle from coding guidelines. Consider extracting attachment handling, file processing, and slide splitting into separate private methods.


197-204: Add comprehensive file validation for security

The method only checks for file emptiness but lacks file type validation, size limits, and other security measures to prevent malicious uploads.

🧹 Nitpick comments (1)
src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (1)

103-104: Consider reducing parameter count with DTOs

The method has 7 parameters, which makes it difficult to use and maintain. Consider grouping related parameters into DTOs (e.g., UpdateAttachmentVideoUnitRequest).

+public class UpdateAttachmentVideoUnitRequest {
+    private final AttachmentVideoUnit updateUnit;
+    private final Attachment updateAttachment;
+    private final MultipartFile updateFile;
+    private final boolean keepFilename;
+    private final List<HiddenPageInfoDTO> hiddenPages;
+    private final List<SlideOrderDTO> pageOrder;
+    // constructor and getters
+}

-public AttachmentVideoUnit updateAttachmentVideoUnit(AttachmentVideoUnit existingAttachmentVideoUnit, AttachmentVideoUnit updateUnit, Attachment updateAttachment,
-        MultipartFile updateFile, boolean keepFilename, List<HiddenPageInfoDTO> hiddenPages, List<SlideOrderDTO> pageOrder) {
+public AttachmentVideoUnit updateAttachmentVideoUnit(AttachmentVideoUnit existingAttachmentVideoUnit, UpdateAttachmentVideoUnitRequest request) {
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c16d085 and 14d47ee.

📒 Files selected for processing (5)
  • jest.config.js (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentVideoUnitResource.java (6 hunks)
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.spec.ts (23 hunks)
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentVideoUnitIntegrationTest.java (14 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • jest.config.js
  • src/main/webapp/app/lecture/manage/pdf-preview/pdf-preview.component.spec.ts
  • src/test/java/de/tum/cit/aet/artemis/lecture/AttachmentVideoUnitIntegrationTest.java
  • src/main/java/de/tum/cit/aet/artemis/lecture/web/AttachmentVideoUnitResource.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/service/AttachmentVideoUnitService.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 (3)
src/main/java/de/tum/cit/aet/artemis/lecture/service/AttachmentVideoUnitService.java (3)

73-89: Well-structured creation method

The method follows good practices by handling the persistence order correctly and integrating with external services appropriately.


159-169: Well-structured helper method

The createAttachment method follows single responsibility principle and handles the attachment creation workflow cleanly.


214-231: Good file cleanup implementation

The handleStudentVersionFile method properly handles cleanup of old files before saving new ones, demonstrating good resource management practices.

Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅SkippedFailedTime ⏱
End-to-End (E2E) Test Report1 ran1 passed0 skipped0 failed2s 43ms
TestResultTime ⏱
No test annotations available

@helios-aet helios-aet bot temporarily deployed to artemis-test2.artemis.cit.tum.de May 25, 2025 17:38 Inactive
Copy link
Member

@bassner bassner left a comment

Choose a reason for hiding this comment

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

Tested lecture functionalities on TS2 ✅

@bassner bassner merged commit a50be98 into develop May 25, 2025
27 of 32 checks passed
@bassner bassner deleted the feature/lectures/combine-video-unit-and-attachment-unit branch May 25, 2025 18:06
@github-project-automation github-project-automation bot moved this from Todo to Done in Communication Webclient May 25, 2025
@github-project-automation github-project-automation bot moved this from Ready For Review to Merged in Artemis Development May 25, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jun 30, 2025
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
atlas Pull requests that affect the corresponding module 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 database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. iris Pull requests that affect the corresponding module lecture Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests
Projects
Archived in project
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants