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 66 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 to the course, 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 97.91%

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Screenshots

Group 146

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

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a dedicated course archive component for viewing archived courses organized by semester.
    • Added a new method for retrieving archived courses based on user access rights.
    • Enhanced navigation with a new archive section in the application’s navbar.
  • User Interface Improvements

    • Implemented a structured layout for displaying archived courses with sorting and search functionalities.
    • Added informative tooltips and messages to guide users in accessing archived courses.
  • Localization

    • Added German and English translations for course archiving features, including messages and tooltips.
  • Bug Fixes

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

    • Established comprehensive unit tests for the Course Archive component to validate functionality and user interactions.

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 21, 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: 4

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 16bf752 and 2d54c39.

Files selected for processing (1)
  • src/test/javascript/spec/component/course/course-archive.component.spec.ts (1 hunks)
Additional context used
Path-based instructions (1)
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}}

coderabbitai[bot]
coderabbitai bot previously approved these changes Sep 21, 2024
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.

I just tested it on TS3 and noticed that the course images reload quite often. For example, when collapsing a semester in the archive and then opening it again, all course images appear to be loaded again from scratch. Same thing with search, if I remove parts of the search string, any courses that appear will reload their image.
Is it possible to cache these images?

Copy link
Contributor

@janthoXO janthoXO left a comment

Choose a reason for hiding this comment

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

looks good in general, i would just move the server side query more into the db.

And maybe one UI change: currently the current semester is also displayed in the archive. does this make sense?
because those courses are already visible on the main course overview.
but I have no strong opinion on that so ill leave that open for discussion

src/main/webapp/i18n/en/student-dashboard.json Outdated Show resolved Hide resolved
SimonEntholzer
SimonEntholzer previously approved these changes Sep 22, 2024
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.

Works on TS3 👍

coolchock
coolchock previously approved these changes Sep 22, 2024
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.

tested in the testing session on ts3, works as expected. Course archive shows old courses, sorting and filtering is possible.

BBesrour
BBesrour previously approved these changes Sep 22, 2024
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.

tested on ts3, works as expected

Copy link
Contributor

@sarpsahinalp sarpsahinalp left a comment

Choose a reason for hiding this comment

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

Some small remarks

@edkaya
Copy link
Contributor Author

edkaya commented Sep 23, 2024

I just tested it on TS3 and noticed that the course images reload quite often. For example, when collapsing a semester in the archive and then opening it again, all course images appear to be loaded again from scratch. Same thing with search, if I remove parts of the search string, any courses that appear will reload their image. Is it possible to cache these images?

We actually use caching strategy for course card icons to load them and cache them in the local storage. For the current local storage, the maxCacheCount is 30, which means that 30 images (or entries) can be stored in localStorage. So in the test servers, there is way more than 30 icons on that page, leading to not to cache all icons. However, I will have a detailed look in a follow up, because this will be the case for course overview as well.

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: 8

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between 2d54c39 and 1884775.

Files selected for processing (6)
  • src/main/java/de/tum/cit/aet/artemis/core/repository/CourseRepository.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/CourseService.java (1 hunks)
  • src/main/webapp/app/overview/course-archive/course-archive.component.ts (1 hunks)
  • src/main/webapp/app/overview/courses.component.html (1 hunks)
  • src/main/webapp/i18n/de/student-dashboard.json (1 hunks)
  • src/main/webapp/i18n/en/student-dashboard.json (1 hunks)
Additional context used
Path-based instructions (5)
src/main/java/de/tum/cit/aet/artemis/core/repository/CourseRepository.java (1)

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

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

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

src/main/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/main/webapp/i18n/de/student-dashboard.json (1)

Pattern 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".

Additional comments not posted (1)
src/main/webapp/i18n/en/student-dashboard.json (1)

15-18: Consider refining the archive text structure for better internationalization

The addition of the "archive" object aligns well with the PR objective of implementing a course archive feature. However, there are two points to consider:

  1. Splitting the sentence into two parts ("oldCourses" and "here") might create challenges for translators in other languages where word order or sentence structure differs significantly from English.

  2. The "here" string is very generic and could potentially be reused in other contexts throughout the application.

Consider the following suggestions:

  1. Combine the two strings into a single entry with a placeholder:

    "archive": {
      "oldCoursesLink": "Looking for old courses? Click {0}"
    }

    This approach allows for more flexibility in translation while maintaining the clickable nature of the text.

  2. Move the "here" string to a more shared location in the i18n structure, as it could be reused in various contexts. This aligns with the previous reviewer's comment about moving shared words to a common location.

To check if "here" is used in other contexts, you can run:

This will help determine if creating a shared location for the "here" string would be beneficial.

Comment on lines +62 to +68
@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>
}
Copy link

Choose a reason for hiding this comment

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

LGTM! Minor suggestion for consistency.

The new code block successfully implements the course archive feature as described in the PR objectives. It correctly uses the @if directive and jhiTranslate for internationalization.

For consistency with the rest of the file, consider using a more semantic HTML structure:

 @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>
 }

This change:

  1. Uses text-center instead of d-flex justify-content-center for centering.
  2. Replaces the non-semantic <div> elements with a <span> and removes the empty space <div>.
  3. Adds a small margin (ms-1) to the link for proper spacing.
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@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>
}
@if (coursesLoaded) {
<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>
}

Comment on lines +15 to +18
"archive": {
"oldCourses": "Suchst du nach alten Kursen? Klicke",
"here": "hier"
},
Copy link

Choose a reason for hiding this comment

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

Combine "oldCourses" and "here" entries for a complete sentence.

The current implementation splits the sentence into two parts, which may cause issues in some UI contexts. Consider combining them into a single, complete sentence.

Apply this change to create a complete sentence in a single entry:

 "archive": {
-    "oldCourses": "Suchst du nach alten Kursen? Klicke",
-    "here": "hier"
+    "oldCourses": "Suchst du nach alten Kursen? Klicke hier"
 },

This change ensures that the translation is complete and can be used flexibly in different UI contexts.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"archive": {
"oldCourses": "Suchst du nach alten Kursen? Klicke",
"here": "hier"
},
"archive": {
"oldCourses": "Suchst du nach alten Kursen? Klicke hier"
},

Comment on lines +545 to +556
@Query("""
SELECT DISTINCT c
FROM Course c
JOIN UserGroup ug ON c.studentGroupName = ug.group
OR c.teachingAssistantGroupName = ug.group
OR c.editorGroupName = ug.group
OR c.instructorGroupName = ug.group
WHERE (ug.userId = :userId OR :isAdmin = TRUE)
AND c.semester IS NOT NULL
""")
List<Course> findCoursesForUserRolesWithNonNullSemester(@Param("userId") Long userId, @Param("isAdmin") boolean isAdmin);

Copy link

Choose a reason for hiding this comment

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

LGTM! Consider adding a brief Javadoc comment.

The new method findCoursesForUserRolesWithNonNullSemester is well-implemented and follows good practices:

  • Clear method name and appropriate return type
  • Proper use of @query and @param annotations
  • Efficient JOIN operation to check user roles
  • Correct filtering for non-null semesters

Consider adding a brief Javadoc comment to explain the method's purpose, parameters, and return value. This would enhance code documentation and make it easier for other developers to understand and use the method. For example:

/**
 * Finds courses for a user based on their roles and admin status, excluding courses without a semester.
 *
 * @param userId The ID of the user
 * @param isAdmin Whether the user is an admin
 * @return A list of courses the user has access to with non-null semesters
 */
@Query(...)
List<Course> findCoursesForUserRolesWithNonNullSemester(@Param("userId") Long userId, @Param("isAdmin") boolean isAdmin);

Comment on lines +655 to +667
/**
* Fetches all courses, filters out courses that the user does not have
* access to based on their role, and excludes any courses that do not
* belong to a specific semester.
*
* @return A list of courses for the course archive
*/
public List<Course> getAllCoursesForCourseArchive() {
var user = userRepository.getUserWithGroupsAndAuthorities();
boolean isAdmin = authCheckService.isAdmin(user);
return courseRepository.findCoursesForUserRolesWithNonNullSemester(user.getId(), isAdmin);
}

Copy link

Choose a reason for hiding this comment

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

LGTM! Consider adding a brief Javadoc comment.

The implementation of getAllCoursesForCourseArchive() looks good and aligns well with the PR objectives. It correctly filters courses based on user roles and ensures only courses with non-null semesters are included.

Consider adding a brief Javadoc comment to explain the purpose of this method and its return value. This would improve code documentation and make it easier for other developers to understand the method's functionality.

+    /**
+     * Retrieves all courses for the course archive feature.
+     * Filters courses based on user roles and includes only courses with non-null semesters.
+     *
+     * @return A list of courses suitable for the course archive
+     */
     public List<Course> getAllCoursesForCourseArchive() {
         var user = userRepository.getUserWithGroupsAndAuthorities();
         boolean isAdmin = authCheckService.isAdmin(user);
         return courseRepository.findCoursesForUserRolesWithNonNullSemester(user.getId(), isAdmin);
     }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Fetches all courses, filters out courses that the user does not have
* access to based on their role, and excludes any courses that do not
* belong to a specific semester.
*
* @return A list of courses for the course archive
*/
public List<Course> getAllCoursesForCourseArchive() {
var user = userRepository.getUserWithGroupsAndAuthorities();
boolean isAdmin = authCheckService.isAdmin(user);
return courseRepository.findCoursesForUserRolesWithNonNullSemester(user.getId(), isAdmin);
}
/**
* Retrieves all courses for the course archive feature.
* Filters courses based on user roles and includes only courses with non-null semesters.
*
* @return A list of courses suitable for the course archive
*/
public List<Course> getAllCoursesForCourseArchive() {
var user = userRepository.getUserWithGroupsAndAuthorities();
boolean isAdmin = authCheckService.isAdmin(user);
return courseRepository.findCoursesForUserRolesWithNonNullSemester(user.getId(), isAdmin);
}

Comment on lines +43 to +44
private alertService: AlertService,
) {}
Copy link

Choose a reason for hiding this comment

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

Adjust constructor formatting to adhere to coding guidelines

Remove the trailing comma after the last parameter and place the opening brace { on the same line as the closing parenthesis ) in the constructor to comply with the open_braces_same_line coding guideline.

Apply this diff to fix the formatting:

 constructor(
     private courseService: CourseManagementService,
-    private alertService: AlertService,
-) {}
+    private alertService: AlertService) {}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private alertService: AlertService,
) {}
private courseService: CourseManagementService,
private alertService: AlertService) {}

Comment on lines +75 to +81
for (const semester of this.semesters) {
this.semesterCollapsed[semester] = isCollapsed;
this.coursesBySemester[semester] = this.courses.filter((course) => course.semester === semester);
this.fullFormOfSemesterStrings[semester] = semester.startsWith('WS') ? 'artemisApp.course.archive.winterSemester' : 'artemisApp.course.archive.summerSemester';
isCollapsed = true;
}
}
Copy link

Choose a reason for hiding this comment

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

Clarify the logic for collapsing semesters

The current logic in mapCoursesIntoSemesters() sets isCollapsed to false for the first semester and true for subsequent semesters. Consider adding a comment to explain this behavior for better code readability.

Add a comment to clarify the logic:

             let isCollapsed = false;
+            // The first semester is expanded by default; subsequent semesters are collapsed
             for (const semester of this.semesters) {
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const semester of this.semesters) {
this.semesterCollapsed[semester] = isCollapsed;
this.coursesBySemester[semester] = this.courses.filter((course) => course.semester === semester);
this.fullFormOfSemesterStrings[semester] = semester.startsWith('WS') ? 'artemisApp.course.archive.winterSemester' : 'artemisApp.course.archive.summerSemester';
isCollapsed = true;
}
}
let isCollapsed = false;
// The first semester is expanded by default; subsequent semesters are collapsed
for (const semester of this.semesters) {
this.semesterCollapsed[semester] = isCollapsed;
this.coursesBySemester[semester] = this.courses.filter((course) => course.semester === semester);
this.fullFormOfSemesterStrings[semester] = semester.startsWith('WS') ? 'artemisApp.course.archive.winterSemester' : 'artemisApp.course.archive.summerSemester';
isCollapsed = true;
}
}

Comment on lines +41 to +44
constructor(
private courseService: CourseManagementService,
private alertService: AlertService,
) {}
Copy link

Choose a reason for hiding this comment

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

Remove unused import and align imports with Angular style guide

Ensure that all imported modules and components are used within the component. Also, follow the Angular style guide for organizing imports.

Review and remove any unused imports, and organize them according to the Angular style guide:

 import { Component, OnDestroy, OnInit } from '@angular/core';
 import { Course } from 'app/entities/course.model';
 import { CourseManagementService } from '../../course/manage/course-management.service';
 import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
 import { AlertService } from 'app/core/util/alert.service';
 import { onError } from 'app/shared/util/global.utils';
 import { Subscription } from 'rxjs';
 import { faAngleDown, faAngleUp, faArrowDownAZ, faArrowUpAZ, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
 import { sortCourses } from 'app/shared/util/course.util';
 import { SizeProp } from '@fortawesome/fontawesome-svg-core';
-import { ArtemisSharedModule } from 'app/shared/shared.module';
-import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module';
-import { CourseCardHeaderComponent } from '../course-card-header/course-card-header.component';

If ArtemisSharedModule, ArtemisSharedComponentModule, and CourseCardHeaderComponent are not used in the component's class or template, consider removing them from both the import statements and the imports array in the @Component decorator.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
constructor(
private courseService: CourseManagementService,
private alertService: AlertService,
) {}
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Course } from 'app/entities/course.model';
import { CourseManagementService } from '../../course/manage/course-management.service';
import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import { AlertService } from 'app/core/util/alert.service';
import { onError } from 'app/shared/util/global.utils';
import { Subscription } from 'rxjs';
import { faAngleDown, faAngleUp, faArrowDownAZ, faArrowUpAZ, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
import { sortCourses } from 'app/shared/util/course.util';
import { SizeProp } from '@fortawesome/fontawesome-svg-core';
constructor(
private courseService: CourseManagementService,
private alertService: AlertService,
) {}

Comment on lines +84 to +86
this.archiveCourseSubscription.unsubscribe();
this.courseService.disableCourseOverviewBackground();
}
Copy link

Choose a reason for hiding this comment

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

Add null check before unsubscribing to prevent potential errors

In the ngOnDestroy() method, it's good practice to check if archiveCourseSubscription exists before calling unsubscribe() to prevent potential runtime errors if the subscription was not established.

Apply this diff to add a null check:

 ngOnDestroy(): void {
-    this.archiveCourseSubscription.unsubscribe();
+    if (this.archiveCourseSubscription) {
+        this.archiveCourseSubscription.unsubscribe();
+    }
     this.courseService.disableCourseOverviewBackground();
 }
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.archiveCourseSubscription.unsubscribe();
this.courseService.disableCourseOverviewBackground();
}
ngOnDestroy(): void {
if (this.archiveCourseSubscription) {
this.archiveCourseSubscription.unsubscribe();
}
this.courseService.disableCourseOverviewBackground();
}

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!) ready for review server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

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