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

Development: Refactor competencies management page to signals #9629

Conversation

JohannesWt
Copy link
Contributor

@JohannesWt JohannesWt commented Oct 29, 2024

Checklist

General

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 client coding and design guidelines.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I documented the TypeScript code using JSDoc style.

Motivation and Context

According to the new client coding guidelines Artemis should move to using signals step by step. This PR refactors the competency management page to using signals.

Description

This PR changes the current competency management page to use signals. Visually nothing changed.

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Log in to Artemis
  2. Navigate to course competency management
  3. verify that a competency and prerequisite can be created and that they are shown in the table
  4. verify that a competency/prerequiste can be deleted
  5. verify that the generate competencies button is visible (on TS3 as Iris is required)

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.







Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
competency-management.component.ts 92.04% ✅ ❌

Screenshots

unchanged

Summary by CodeRabbit

  • New Features

    • Enhanced reactivity in the Competency Management component, improving data handling and state management.
    • Updated loading indicators and competency retrieval methods for better user experience.
    • Improved structure for handling competencies in the Competency Management Table component.
  • Bug Fixes

    • Improved error handling and alert notifications for data fetching issues.
  • Tests

    • Refined test suite for better coverage and reliability, including new tests for loading states and error handling.

@JohannesWt JohannesWt self-assigned this Oct 29, 2024
@github-actions github-actions bot added tests client Pull requests that update TypeScript code. (Added Automatically!) labels Oct 29, 2024
@JohannesWt JohannesWt changed the title Adaptive Learning: Refactor competencies management page to signals Adaptive learning: Refactor competencies management page to signals Oct 29, 2024
@JohannesWt JohannesWt temporarily deployed to artemis-test3.artemis.cit.tum.de October 29, 2024 15:26 — with GitHub Actions Inactive
@JohannesWt JohannesWt marked this pull request as ready for review October 29, 2024 17:10
@JohannesWt JohannesWt requested a review from a team as a code owner October 29, 2024 17:10
Copy link

coderabbitai bot commented Oct 29, 2024

Walkthrough

This pull request introduces updates to the CompetencyManagementComponent by converting property accesses to function calls in both the HTML and TypeScript files. It enhances the component's reactivity by utilizing Angular's reactive programming features, including the introduction of reactive signals for state management. The OnDestroy lifecycle hook has been removed, simplifying the component's lifecycle management. Additionally, the test suite has been refactored to improve dependency management and robustness, incorporating mock services and new tests for loading states and error handling.

Changes

File Change Summary
src/main/webapp/app/course/competencies/competency-management/competency-management.component.html Converted property accesses to function calls for irisCompetencyGenerationEnabled, courseId, isLoading, courseCompetencies, and standardizedCompetenciesEnabled.
src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts Updated component to use reactive signals for state management, removed OnDestroy, and refactored methods for loading data.
src/test/javascript/spec/component/competencies/competency-management/competency-management.component.spec.ts Enhanced test suite with mock services, refactored beforeEach, and added new tests for loading state and error handling.
src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts Changed allCompetencies to a model-based required type and updated the updateDataAfterImportAll method to use a method call for state management.

Possibly related PRs

Suggested labels

server, enhancement, ready to merge, component:AdaptiveLearning

Suggested reviewers

  • JohannesStoehr
  • MaximilianAnzinger
  • pzdr7
  • florian-glombik
  • sarpsahinalp
  • Jan-Thurner

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6109663 and 8c840fb.

📒 Files selected for processing (1)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.html (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.html

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 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

@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

🧹 Outside diff range and nitpick comments (3)
src/main/webapp/app/course/competencies/competency-management/competency-management.component.html (1)

42-43: LGTM! Proper signal-based input bindings for prerequisites table.

All input properties correctly use function calls for signal-based reactivity.

Consider extracting the common table configuration into a reusable interface or type to reduce duplication:

interface CompetencyTableConfig {
  courseId: () => number;
  courseCompetencies: () => CourseCompetency[];
  competencyType: CourseCompetencyType;
  standardizedCompetenciesEnabled: () => boolean;
}

Then in the template, you could use a structural directive or component property to render tables based on configurations:

readonly tableConfigs: CompetencyTableConfig[] = [
  {
    courseId: this.courseId,
    courseCompetencies: this.competencies,
    competencyType: CourseCompetencyType.COMPETENCY,
    standardizedCompetenciesEnabled: this.standardizedCompetenciesEnabled
  },
  {
    courseId: this.courseId,
    courseCompetencies: this.prerequisites,
    competencyType: CourseCompetencyType.PREREQUISITE,
    standardizedCompetenciesEnabled: this.standardizedCompetenciesEnabled
  }
];

Also applies to: 45-45

src/test/javascript/spec/component/competencies/competency-management/competency-management.component.spec.ts (1)

176-194: Enhance error handling tests with message verification

While the error handling tests are good, they could be more specific by verifying the error message content:

 it('should show alert when loading iris settings fails', async () => {
     const errorSpy = jest.spyOn(alertService, 'error');
-    getIrisSettingsSpy.mockRejectedValueOnce({});
+    const errorMessage = 'Failed to load IRIS settings';
+    getIrisSettingsSpy.mockRejectedValueOnce(new Error(errorMessage));

     fixture.detectChanges();
     await fixture.whenStable();

-    expect(errorSpy).toHaveBeenCalledOnce();
+    expect(errorSpy).toHaveBeenCalledExactlyOnceWith('artemis.competencyManagement.error.loadIrisSettings');
 });
src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts (1)

117-118: Avoid unnecessary wrapping of values in new signals

Creating new signals with signal<number>(this.courseId()) when passing data to child components may be redundant since courseId is already a signal. Passing the existing signal or the value directly can simplify the code and avoid unnecessary nesting.

Adjust the code as follows:

-modalRef.componentInstance.courseId = signal<number>(this.courseId());
+modalRef.componentInstance.courseId = this.courseId;

-modalRef.componentInstance.courseCompetencies = signal<CourseCompetency[]>(this.courseCompetencies());
+modalRef.componentInstance.courseCompetencies = this.courseCompetencies;

This ensures that the child components receive the current signals without creating additional layers.

Also applies to: 129-129

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 7503f9c and 47cd904.

📒 Files selected for processing (3)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.html (2 hunks)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts (7 hunks)
  • src/test/javascript/spec/component/competencies/competency-management/competency-management.component.spec.ts (6 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/main/webapp/app/course/competencies/competency-management/competency-management.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/app/course/competencies/competency-management/competency-management.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/test/javascript/spec/component/competencies/competency-management/competency-management.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}}

🔇 Additional comments (6)
src/main/webapp/app/course/competencies/competency-management/competency-management.component.html (3)

11-12: LGTM! Proper usage of new Angular control flow syntax.

The @if directive is correctly used here, replacing the older *ngIf syntax as per guidelines. The function calls indicate proper signal usage.


27-33: LGTM! Proper loading state handling with accessibility support.

The loading spinner is correctly implemented with:

  • New @if syntax
  • Proper ARIA attributes for accessibility
  • Signal-based loading state

35-36: LGTM! Proper signal-based input bindings for competency table.

All input properties correctly use function calls for signal-based reactivity.

Also applies to: 38-38

src/test/javascript/spec/component/competencies/competency-management/competency-management.component.spec.ts (3)

34-35: LGTM: Proper mock service imports

The imports follow the best practices by using specific mock services instead of full module imports.


95-130: LGTM: Well-structured test setup

The test setup follows best practices with:

  • Proper service injection
  • Well-configured spies
  • Clear test data structure

228-239: LGTM: Well-structured modal test

The test properly verifies the modal interaction and competency updates using signals. The assertions follow the coding guidelines for checking array length.

Copy link

@Cathy0123456789 Cathy0123456789 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. Creating, editing and deleting competencies / prerequisites still works, as well as linking and unlinking lecture units. Also the "Generate Competencies" button is shown.

flbrgit
flbrgit previously approved these changes Oct 29, 2024
Copy link

@flbrgit flbrgit 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. Functionality works as described and the button to generate competencies is also shown. Linking to units, deleting and creating as well as editing works without noticable bugs

ItsaaaMeMario
ItsaaaMeMario previously approved these changes Oct 29, 2024
Copy link

@ItsaaaMeMario ItsaaaMeMario left a comment

Choose a reason for hiding this comment

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

I tested on TS3 with artemis_test_user_20, I was flawlessly able to create/delete/edit prerequisites/competencies. The "generate Competencies" button is also visible.

JohannesStoehr
JohannesStoehr previously approved these changes Oct 29, 2024
Copy link
Contributor

@JohannesStoehr JohannesStoehr left a comment

Choose a reason for hiding this comment

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

Code looks good apart from one small issue:

HawKhiem
HawKhiem previously approved these changes Oct 29, 2024
Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Competencies and prerequesites can be added and deleted as described. The generate competencies button is also visible. But when I click on it it takes really long to load

image

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

🧹 Outside diff range and nitpick comments (3)
src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts (2)

Line range hint 25-45: Consider splitting component responsibilities

The component handles both competencies and prerequisites through a shared service pattern. Consider splitting these into separate components for better maintainability and single responsibility principle.

This would improve:

  • Code maintainability
  • Testing isolation
  • Reusability

Line range hint 104-115: Improve error handling in deleteCompetency

The error handling could be more informative and consistent with the rest of the application.

Consider using the AlertService for error handling:

 deleteCompetency(competencyId: number) {
     this.service.delete(competencyId, this.courseId).subscribe({
         next: () => {
-            this.dialogErrorSource.next('');
             this.competencyDeleted.next(competencyId);
+            this.alertService.success('artemisApp.competency.deleted');
         },
-        error: (error: HttpErrorResponse) => this.dialogErrorSource.next(error.message),
+        error: (error: HttpErrorResponse) => onError(this.alertService, error),
     });
 }
src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts (1)

117-118: Share existing signals with modal components

Creating new signals with initial values for modal components could lead to synchronization issues if the underlying data changes. Instead, share the existing signals:

-modalRef.componentInstance.courseId = signal<number>(this.courseId());
-modalRef.componentInstance.courseCompetencies = signal<CourseCompetency[]>(this.courseCompetencies());
+modalRef.componentInstance.courseId = this.courseId;
+modalRef.componentInstance.courseCompetencies = this.courseCompetencies;

Also applies to: 129-129

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5030bec and 6109663.

📒 Files selected for processing (3)
  • src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts (3 hunks)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.html (2 hunks)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/course/competencies/competency-management/competency-management.component.html
🧰 Additional context used
📓 Path-based instructions (2)
src/main/webapp/app/course/competencies/competency-management/competency-management-table.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/course/competencies/competency-management/competency-management.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

🔇 Additional comments (2)
src/main/webapp/app/course/competencies/competency-management/competency-management-table.component.ts (1)

25-25: Verify signal usage across related components

The change to model.required for allCompetencies is good, but we should ensure consistent usage across related components.

✅ Verification successful

Signal usage is consistent across related components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other usages of allCompetencies to ensure consistent signal usage
rg -t ts "allCompetencies\s*=" "src/main/webapp/app/course/competencies/"

Length of output: 236

src/main/webapp/app/course/competencies/competency-management/competency-management.component.ts (1)

157-158: 🛠️ Refactor suggestion

Improve type safety in updateDataAfterImportAll

The non-null assertion on dto.competency assumes the property will always be defined. Consider using proper type guards or filtering:

-const importedCourseCompetencies = res.map((dto) => dto.competency!);
+const importedCourseCompetencies = res
+    .map((dto) => dto.competency)
+    .filter((competency): competency is CourseCompetency => !!competency);
this.courseCompetencies.update((courseCompetencies) => 
    courseCompetencies.concat(importedCourseCompetencies)
);

Likely invalid or redundant comment.

Copy link
Contributor

@az108 az108 left a comment

Choose a reason for hiding this comment

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

reapprove merge

Copy link

@sachmii sachmii left a comment

Choose a reason for hiding this comment

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

reapprove

Copy link
Contributor

@JohannesStoehr JohannesStoehr left a comment

Choose a reason for hiding this comment

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

Reapprove

Copy link
Contributor

@EneaGore EneaGore left a comment

Choose a reason for hiding this comment

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

reapprove

Copy link
Contributor

@MaximilianAnzinger MaximilianAnzinger left a comment

Choose a reason for hiding this comment

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

Maintainer approved

@JohannesWt JohannesWt added maintainer-approved The feature maintainer has approved the PR and removed ready for review labels Nov 13, 2024
@krusche krusche changed the title Adaptive learning: Refactor competencies management page to signals Development: Refactor competencies management page to signals Nov 13, 2024
@krusche krusche added this to the 7.7.1 milestone Nov 13, 2024
@krusche krusche merged commit 383945a into develop Nov 13, 2024
48 of 54 checks passed
@krusche krusche deleted the feature/competencies/refactor-competencies-management-page-to-signals branch November 13, 2024 14:53
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!) maintainer-approved The feature maintainer has approved the PR refactoring small tests
Projects
Status: Merged
Status: Done
Development

Successfully merging this pull request may close these issues.