Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

General: Implement Course Archive to see old courses from previous semesters #9343

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

Conversation

edkaya
Copy link
Contributor

@edkaya edkaya commented Sep 20, 2024

Checklist

General

Server

  • I strictly followed the server coding and design guidelines.
  • 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 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

Students often want access to old or completed courses on Artemis from previous semesters in which they were enrolled. While they can technically access these courses if they remember the course link, relying on memory and attempting to access the course via the link is not practical. This PR closes #9129.

Description

  • Added new component course archive to present all previous courses in which students were enrolled, grouped by semesters, which can be collapsed by clicking on the respective accordion groups.
  • Added new course card header component, derived from the new course card design. (We are currently using the same code/styling for new course cards, therefore this component will be reused in the course cards files after we succesfully merge the new course cards)
  • Added a get request to fetch necessary courses on demand
  • Added "Looking for old courses? Click here" label to get access for the course archive page.
  • Added Search and Sort Functionality

Steps for Testing

Prerequisites:

  • 1 Admin (if you want to create your own course, if its the case, please dont forget to assign a semester, start and end date to the course (end date should be older than the current time), otherwise the page does not display the old course)
  • 1 Student
  • Some courses with a defined start/end date and an assigned semester. The student account must be also enrolled in the courses.

(I already created some old courses on TS3, and test users 1-5 are enrolled in these courses. Other test users are not enrolled. You can test that only users 1-5 can see these additional tests courses, where other test users can not. )

  1. Log in to Artemis
  2. Navigate to Course Overview Page
  3. Scroll down, see "Looking for old courses? Click here" label and click on it
  4. Verify that the page looks good
  5. Verify that you can see the old courses, grouped by the semesters
  6. Verify that you can search for courses via search bar
  7. Verify that sort functionality works as expected (sorting semesters)
  8. Verify that you can navigate to the course by clicking on the course card headers

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Class/File Line Coverage Confirmation (assert/expect)
course-archive.component.ts 96.96%

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Screenshots

Group 156

Screenshot 2024-09-20 at 15 38 21 Screenshot 2024-09-20 at 15 38 32

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a new DTO structure for course archiving, enhancing data representation.
    • Introduced a method to retrieve archived courses, improving access to course data.
    • Implemented methods for managing semester collapse states in local storage.
  • User Interface Improvements

    • Enhanced layout for displaying archived courses with sorting and search functionalities.
    • Added new prompts and messages to guide users in accessing archived courses.
  • Localization Enhancements

    • Introduced German and English translations for new archive-related terms and messages, improving accessibility for users.
  • Bug Fixes

    • Improved state management for course overviews and semester visibility.
  • Tests

    • Enhanced testing capabilities for course archiving functionality, ensuring correct behavior for various user scenarios.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 4017d0e and 4251db5.

📒 Files selected for processing (5)
  • src/main/webapp/app/overview/course-archive/course-archive.component.ts (1 hunks)
  • src/main/webapp/app/overview/course-overview.component.ts (2 hunks)
  • src/main/webapp/app/overview/courses.module.ts (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java (1 hunks)
  • src/test/javascript/spec/component/course/course-overview.component.spec.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • src/test/javascript/spec/component/course/course-overview.component.spec.ts
🧰 Additional context used
📓 Path-based instructions (4)
src/main/webapp/app/overview/course-archive/course-archive.component.ts (1)

Pattern 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/overview/course-overview.component.ts (1)

Pattern 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/overview/courses.module.ts (1)

Pattern 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/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java (1)

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

🪛 Biome
src/main/webapp/app/overview/course-archive/course-archive.component.ts

[error] 142-142: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)


[error] 142-142: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)

🔇 Additional comments (18)
src/main/webapp/app/overview/courses.module.ts (1)

Line range hint 1-46: Summary: Minor adjustments needed for course archive implementation

The changes in this file contribute to the implementation of the course archive feature mentioned in the PR objectives. The addition of SearchFilterComponent aligns with the search functionality requirement for the course archive.

However, there are two minor issues that need to be addressed:

  1. Moving SearchFilterComponent to the correct array (declarations instead of imports).
  2. Reverting the declarations array to a multi-line format for better readability.

Once these adjustments are made, the module will be properly set up to support the new course archive feature, including the search functionality.

src/test/java/de/tum/cit/aet/artemis/programming/CourseGitlabJenkinsIntegrationTest.java (2)

1070-1074: LGTM! Well-structured test for an important edge case.

This test method is well-implemented and follows the established patterns in the file. It correctly uses the @WithMockUser annotation to simulate a student user and delegates the testing logic to the courseTestService. Testing the scenario for an unenrolled student is an important edge case to cover.


1063-1074: Great addition of test cases for course archive functionality!

These new test methods enhance the test coverage for the course archive feature, including an important edge case for unenrolled students. The implementation is consistent with the existing code structure and testing patterns in this file.

src/main/webapp/app/overview/course-archive/course-archive.component.ts (15)

1-14: Well-Organized Imports and Dependency Injection

The imports are well-organized, grouping Angular core modules, third-party libraries, and application-specific modules effectively. The use of the modern inject() function for dependency injection enhances code readability and aligns with Angular best practices.


15-21: Correct Component Configuration with Standalone Component

The @Component decorator is correctly configured. Setting standalone: true modernizes the component, and the necessary modules are imported explicitly. This approach promotes encapsulation and reusability.


22-35: Proper Declaration and Initialization of Class Properties

Class properties are appropriately declared and initialized, ensuring that they are ready for use within the component. The initialization of arrays and objects prevents potential undefined errors during runtime. The use of readonly for icon declarations enhances code safety by preventing unintended mutations.


43-46: Effective Initialization in ngOnInit Lifecycle Hook

The ngOnInit() method effectively initializes the component by loading archived courses and enabling the course overview background. This ensures that the component is ready for user interaction upon rendering.


51-63: Efficient Data Loading in loadArchivedCourses Method

The loadArchivedCourses() method efficiently fetches archived courses, handles the response correctly, and processes the data by sorting and mapping it into semesters. Error handling is appropriately managed using the onError utility.


65-75: Accurate Mapping of Courses into Semesters

The mapCoursesIntoSemesters() method accurately organizes courses by their respective semesters and initializes the collapse states. This enhances the user's ability to navigate through archived courses effectively.


77-80: Proper Cleanup in ngOnDestroy Lifecycle Hook

The ngOnDestroy() method unsubscribes from subscriptions and disables the course overview background, ensuring that resources are released appropriately and preventing potential memory leaks.


82-89: Responsive Search Functionality in setSearchValue Method

The setSearchValue() method effectively updates the search text and adjusts the display of semesters based on the search input, enhancing the user experience through responsive filtering.


91-96: Intuitive Sorting Mechanism in onSort Method

The onSort() method provides an intuitive mechanism for users to sort semesters in ascending or descending order, improving the navigability of the course archive.


97-105: Dynamic Expansion and Collapse Based on Search Input

The expandOrCollapseBasedOnSearchValue() method dynamically adjusts the visibility of semesters based on whether courses match the search criteria, enhancing usability by showing relevant content.


107-111: Consistent Retrieval of Collapse States

The getCollapseStateForSemesters() method retrieves the collapse states for semesters consistently, ensuring that the user interface reflects the user's previous interactions and preferences.


113-116: Toggle Functionality for Semester Visibility

The toggleCollapseState() method allows users to expand or collapse semesters interactively, providing control over the displayed content.


118-120: Efficient Course Search Within Semesters

The isCourseFoundInSemester() method efficiently determines if a course matching the search text exists within a semester, aiding in the accurate display of search results.


122-124: Proper Sorting of Courses by Title

The sortCoursesByTitle() method correctly sorts courses alphabetically by their titles, improving the organization and findability of courses within semesters.


126-157: Robust Sorting Logic for Semesters

The getUniqueSemesterNamesSorted() method implements a robust sorting algorithm to order semesters logically, accounting for both the year and semester type (WS or SS). This ensures that semesters are presented in a meaningful sequence.

🧰 Tools
🪛 Biome

[error] 142-142: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)


[error] 142-142: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)

coderabbitai[bot]
coderabbitai bot previously approved these changes Oct 12, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 4251db5 and bc137e7.

📒 Files selected for processing (2)
  • src/main/webapp/app/overview/course-archive/course-archive.component.html (1 hunks)
  • src/test/javascript/spec/component/course/course-archive.component.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/main/webapp/app/overview/course-archive/course-archive.component.html (1)

Pattern 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/test/javascript/spec/component/course/course-archive.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

📓 Learnings (1)
src/test/javascript/spec/component/course/course-archive.component.spec.ts (1)
Learnt from: pzdr7
PR: ls1intum/Artemis#9463
File: src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts:50-55
Timestamp: 2024-10-13T12:03:02.430Z
Learning: In `src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts`, when a function is called multiple times in a test, use `toHaveBeenCalledTimes` and `toHaveBeenNthCalledWith` assertions instead of `toHaveBeenCalledExactlyOnceWith`.
🔇 Additional comments (7)
src/main/webapp/app/overview/course-archive/course-archive.component.html (1)

1-70: Well-structured Implementation of Course Archive Component

The template is well-organized and effectively utilizes the new @if and @for Angular directives as per the coding guidelines. The code is clean, readable, and follows best practices. Great job!

src/test/javascript/spec/component/course/course-archive.component.spec.ts (6)

198-205: 🧹 Nitpick (assertive)

Remove unnecessary use of fakeAsync and tick()

In this test, there are no asynchronous operations that require fakeAsync or tick(). Simplifying the test improves readability without affecting functionality.

Apply this diff to simplify the test:

-it('should toggle sort order and update the icon accordingly', fakeAsync(() => {
+it('should toggle sort order and update the icon accordingly', () => {
     // ...
     fixture.detectChanges();
-    tick();

     // ...
 }));

Likely invalid or redundant comment.


129-135: 🧹 Nitpick (assertive)

Prefer .toEqual() over .toStrictEqual() for object comparison

Using .toStrictEqual() enforces strict equality, which can make tests brittle if objects have additional properties or different prototypes. .toEqual() performs a deep equality check and is more appropriate here.

Apply this diff to adjust the assertions:

 expect(component.coursesBySemester).toStrictEqual({
+expect(component.coursesBySemester).toEqual({
     // ...
 });

 expect(component.semesterCollapsed).toStrictEqual({
+expect(component.semesterCollapsed).toEqual({
     // ...
 });

 expect(component.fullFormOfSemesterStrings).toStrictEqual({
+expect(component.fullFormOfSemesterStrings).toEqual({
     // ...
 });

Likely invalid or redundant comment.


70-70: 🧹 Nitpick (assertive)

Unnecessary call to component.ngOnDestroy() in afterEach

Calling component.ngOnDestroy() in the afterEach block is unnecessary because the Angular testing environment automatically handles component destruction after each test. Removing this call simplifies the test code without affecting functionality.

Apply this diff to remove the unnecessary call:

 afterEach(() => {
-    component.ngOnDestroy();
     jest.restoreAllMocks();
 });

Likely invalid or redundant comment.


102-102: 🧹 Nitpick (assertive)

Prefer .toEqual() over .toStrictEqual() for array comparison

Using .toStrictEqual() for array comparison can be unnecessarily strict and may cause tests to fail if there are prototype differences. .toEqual() is sufficient for comparing arrays deeply.

Apply this diff to adjust the assertion:

 expect(component.courses).toStrictEqual(emptyCourses);
+expect(component.courses).toEqual(emptyCourses);

Likely invalid or redundant comment.


218-218: 🧹 Nitpick (assertive)

Specify the number of times onSort is called

Instead of checking if onSort was called, assert that it was called exactly once to make the test more precise.

Apply this diff to clarify the expectation:

-expect(onSortSpy).toHaveBeenCalled();
+expect(onSortSpy).toHaveBeenCalledTimes(1);

Likely invalid or redundant comment.


184-185: 🧹 Nitpick (assertive)

Avoid spying on internal component methods

Spying on expandOrCollapseBasedOnSearchValue, an internal method, couples your test to implementation details, making it fragile. Instead, assert the observable outcomes to ensure the component behaves as expected.

Consider removing the spy and verifying the expected state:

-const expandOrCollapseBasedOnSearchValueSpy = jest.spyOn(component, 'expandOrCollapseBasedOnSearchValue');
 component.setSearchValue('iPraktikum');

-expect(expandOrCollapseBasedOnSearchValueSpy).toHaveBeenCalledOnce();
+expect(component.searchValue).toBe('iPraktikum');
+expect(component.semesterCollapsed['WS21/22']).toBeFalse();
+// Add assertions for other semesters as needed

Likely invalid or redundant comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between bc137e7 and 6d9f82c.

📒 Files selected for processing (3)
  • src/main/webapp/app/overview/course-archive/course-archive.component.ts (1 hunks)
  • src/main/webapp/app/overview/courses.component.html (2 hunks)
  • src/test/javascript/spec/component/course/course.component.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/main/webapp/app/overview/course-archive/course-archive.component.ts (1)

Pattern 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/overview/courses.component.html (1)

Pattern 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/test/javascript/spec/component/course/course.component.spec.ts (1)

Pattern src/test/javascript/spec/**/*.ts: jest: true; mock: NgMocks; bad_practices: avoid_full_module_import; perf_improvements: mock_irrelevant_deps; service_testing: mock_http_for_logic; no_schema: avoid_NO_ERRORS_SCHEMA; expectation_specificity: true; solutions: {boolean: toBeTrue/False, reference: toBe, existence: toBeNull/NotNull, undefined: toBeUndefined, class_obj: toContainEntries/toEqual, spy_calls: {not_called: not.toHaveBeenCalled, once: toHaveBeenCalledOnce, with_value: toHaveBeenCalledWith|toHaveBeenCalledExactlyOnceWith}}

🪛 Biome
src/main/webapp/app/overview/course-archive/course-archive.component.ts

[error] 134-134: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)


[error] 134-134: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)

🔇 Additional comments (5)
src/main/webapp/app/overview/courses.component.html (2)

27-27: LGTM: Added id for testing purposes.

The addition of the id="test-sort" attribute to the sort link is appropriate. This change likely facilitates easier targeting of the element for testing purposes, which is a good practice for improving testability.


65-71: 🧹 Nitpick (assertive)

LGTM! Consider improving HTML structure for better semantics.

The implementation successfully adds the course archive feature as described in the PR objectives. It correctly uses the @if directive and jhiTranslate for internationalization, addressing previous review comments.

However, the HTML structure could be improved for better semantics and consistency with the rest of the file. Consider the following changes:

 @if (coursesLoaded) {
-    <div class="d-flex justify-content-center mt-3">
-        <div jhiTranslate="artemisApp.studentDashboard.archive.oldCourses"></div>
-        <div>&nbsp;</div>
-        <a [routerLink]="['/courses/archive']" jhiTranslate="artemisApp.studentDashboard.archive.here"></a>
+    <div class="text-center mt-3">
+        <span jhiTranslate="artemisApp.studentDashboard.archive.oldCourses"></span>
+        <a [routerLink]="['/courses/archive']" class="ms-1" jhiTranslate="artemisApp.studentDashboard.archive.here"></a>
     </div>
 }

These changes:

  1. Replace d-flex justify-content-center with text-center for simpler centering.
  2. Use a <span> instead of a <div> for inline text.
  3. Remove the unnecessary <div>&nbsp;</div> and add ms-1 class to the link for spacing.
  4. Maintain the use of jhiTranslate and the correct routing.

This structure is more semantic and consistent with modern HTML practices while maintaining the intended functionality.

Likely invalid or redundant comment.

src/test/javascript/spec/component/course/course.component.spec.ts (1)

Line range hint 1-298: Overall assessment: Good additions with minor improvements needed.

The new test cases for search functionality and sorting behavior enhance the coverage of the CoursesComponent. They focus on important aspects of the component's functionality. While there are minor issues in the implementation of these tests, they can be easily addressed with the suggested changes. Once these improvements are made, the test suite will provide more robust coverage of the component's behavior.

src/main/webapp/app/overview/course-archive/course-archive.component.ts (2)

28-28: ⚠️ Potential issue

Initialize 'semesters' to avoid potential undefined issues

The semesters array is declared but not initialized. Initializing it to an empty array ensures that it doesn't cause undefined errors when accessed before being populated.

Apply this diff to initialize semesters:

-    semesters: string[];
+    semesters: string[] = [];

Likely invalid or redundant comment.


31-31: ⚠️ Potential issue

Correct the type of 'coursesBySemester' to match assigned data

The coursesBySemester property is typed as { [key: string]: Course[] }, but it is assigned arrays of CourseForArchiveDTO[]. To ensure type safety and prevent potential runtime errors, update the type to match the assigned data.

Apply this diff to fix the type:

-    coursesBySemester: { [key: string]: Course[] } = {};
+    coursesBySemester: { [key: string]: CourseForArchiveDTO[] } = {};

Likely invalid or redundant comment.

Copy link
Contributor

@SimonEntholzer SimonEntholzer left a comment

Choose a reason for hiding this comment

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

tested again on Ts4, reapprove

Copy link
Contributor

@coolchock coolchock left a comment

Choose a reason for hiding this comment

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

re-approve after merge conflicts were resolved

Copy link
Member

@BBesrour BBesrour left a comment

Choose a reason for hiding this comment

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

re-approve after fixing coverage

Copy link

@anian03 anian03 left a comment

Choose a reason for hiding this comment

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

Re-approve, tested on TS3

Copy link

⚠️ Unable to deploy to test servers ⚠️

Testserver "artemis-test3.artemis.cit.tum.de" is already in use by PR #9456.

@github-actions github-actions bot added the deployment-error Added by deployment workflows if an error occured label Oct 16, 2024
@rabeatwork rabeatwork removed the deployment-error Added by deployment workflows if an error occured label Oct 16, 2024
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!) core 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
Projects
Status: Developer Approved
Development

Successfully merging this pull request may close these issues.

Students show be able to see completed / inactive course
9 participants