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: Use signals in lecture online and text unit #9658

Merged
merged 9 commits into from
Nov 7, 2024

Conversation

florian-glombik
Copy link
Contributor

@florian-glombik florian-glombik commented Nov 2, 2024

Checklist

General

Client

Motivation and Context

This PR introduces signals and fixes code smells in components used for editing and updating lectures. This is a preparation for Lectures: Add status bar to lecture creation and edit mode #9655 and aims to keep #9655 at a manageable size of changes.

Description

  • Introduced signals in online-unit-form.component (got rid of a method call in the template)
  • Introduced signals in text-unit-form.component (got rid of a method call in the template)

Steps for Testing

Prerequisites:

  • 1 Instructor
  1. Navigate to the Instructor lecture view (creating and editing)
  2. Click Units > Text to create a text lecture unit, verify the behavior is the same as on develop
  3. Navigate to the Instructor lecture view (creating and editing)
  4. Click Units > Online to create an online lecture unit, verify the behavior is the same as on develop
  5. Verify Editing the text / online Unit works as on develop
  6. Create a Lecture in the guided mode, where you add a Online Lecture Unit & Text Lecture Unit
  7. Verify Adding a Online lecture unit & Text Lecture Unit works
  8. Verify the cancel button works for the Online lecture unit & Text Lecture Unit

There are known issues with the guided mode that will not be addressed in this PR #9658 (review), see reasoning #9658 (comment)

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

Screenshots

lectureUnitRefactoring-9658

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Enhanced form validation logic across multiple components, ensuring stricter validation and improved user feedback.
    • Introduced a new method isFormValid() for determining form submission eligibility.
  • Bug Fixes

    • Updated method calls to ensure accurate form validity checks.
  • Refactor

    • Streamlined component structures by utilizing Angular's reactive programming features for better performance and readability.
    • Renamed properties for clarity and deprecated outdated ones.
    • Improved input handling in test setups to align with Angular's practices.
  • Documentation

    • Updated comments for clarity in the previousState method.

@florian-glombik florian-glombik requested a review from a team as a code owner November 2, 2024 23:29
@github-actions github-actions bot added the client Pull requests that update TypeScript code. (Added Automatically!) label Nov 2, 2024
Copy link

coderabbitai bot commented Nov 2, 2024

Walkthrough

The pull request introduces several updates across multiple components in an Angular application, focusing on enhancing form validation and state management. Key changes include the renaming of validation properties, the introduction of new input properties with required decorators, and the adoption of Angular's reactive programming features. The HTML templates for form components have been adjusted to utilize a new method for determining form validity. Additionally, modifications to access levels of properties in various components have been made to improve encapsulation.

Changes

File Change Summary
src/main/webapp/app/exercises/programming/manage/update/update-components/information/programming-exercise-information.component.ts - Updated method call from formValidSignal() to isFormValidSignal() in calculateFormValid.
- Defined several input properties with the required option.
- Introduced signals for state management and modified ngOnChanges to update exerciseTitle signal.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.html - Changed submit button's disabled attribute to use isFormValid() instead of isSubmitPossible.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts - Replaced constructor-based dependency injection with inject.
- Removed ngOnInit and initializeForm, directly instantiated FormGroup.
- Added statusChanges and isFormValid properties for form state management.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.html - Updated submit button's disabled attribute to use isFormValid() instead of isSubmitPossible.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts - Added imports for computed, inject, and toSignal.
- Directly initialized form property using FormBuilder.
- Introduced statusChanges and isFormValid properties.
src/main/webapp/app/lecture/lecture-update.component.ts - Changed documentationType from readonly to protected readonly.
- Updated several icon properties from public to protected.
- Added allowedFileExtensions and acceptedFileExtensionsFileBrowser as protected readonly.
src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts - Renamed formValidSignal to isFormValidSignal.
- Marked formValid and formValidChanges as deprecated.
- Updated calculateFormValid method to use the new signal property.

Possibly related PRs

Suggested labels

programming, modeling

Suggested reviewers

  • JohannesStoehr
  • krusche
  • SimonEntholzer
  • pzdr7

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.

@florian-glombik florian-glombik changed the title Development: Use signals in online unit form component Development: Use signals in lecture online unit form component Nov 2, 2024
@florian-glombik florian-glombik changed the title Development: Use signals in lecture online unit form component Development: Use signals in lecture online and text unit Nov 2, 2024
@florian-glombik florian-glombik added code quality refactoring lecture Pull requests that affect the corresponding module labels Nov 2, 2024
@github-actions github-actions bot removed the lecture Pull requests that affect the corresponding module label Nov 2, 2024
@florian-glombik florian-glombik temporarily deployed to artemis-test2.artemis.cit.tum.de November 3, 2024 00:09 — with GitHub Actions Inactive
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: 7

🧹 Outside diff range and nitpick comments (11)
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts (3)

50-59: Consider enhancing type safety for form controls

While the form initialization is clean, consider using typed form controls for better type safety and IDE support.

Here's how you could improve it:

interface OnlineUnitForm {
    name: FormControl<string | undefined>;
    description: FormControl<string | undefined>;
    releaseDate: FormControl<dayjs.Dayjs | undefined>;
    source: FormControl<string | undefined>;
    competencyLinks: FormControl<CompetencyLectureUnitLink[] | undefined>;
}

form = this.formBuilder.group<OnlineUnitForm>({
    name: this.formBuilder.control(undefined, [Validators.required, Validators.maxLength(255)]),
    description: this.formBuilder.control(undefined, [Validators.maxLength(1000)]),
    releaseDate: this.formBuilder.control(undefined),
    source: this.formBuilder.control(undefined, [Validators.required, this.urlValidator]),
    competencyLinks: this.formBuilder.control(undefined),
});

61-62: Consider adding initial value and error handling to signals

The signal implementation could be more robust with explicit initial values and error handling.

Here's an improved version:

private readonly statusChanges = toSignal(this.form.statusChanges, {
    initialValue: 'INVALID' as const,
    requireSync: true
});

protected readonly isFormValid = computed(() => {
    const status = this.statusChanges();
    return status === 'VALID' && this.form.dirty;
});

This ensures:

  • Type safety with as const
  • Explicit initial value
  • Form must be dirty to be considered valid

Line range hint 89-108: Prevent potential memory leaks in HTTP subscription

The HTTP subscription in onLinkChanged should be properly managed to prevent memory leaks.

Consider using the takeUntilDestroyed operator or implementing proper cleanup:

import { DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

export class OnlineUnitFormComponent implements OnChanges {
    private readonly destroyRef = inject(DestroyRef);

    onLinkChanged(): void {
        // ... existing code ...

        if (this.sourceControl?.valid) {
            this.onlineUnitService
                .getOnlineResource(this.sourceControl.value)
                .pipe(
                    takeUntilDestroyed(this.destroyRef),
                    map((response: HttpResponse<OnlineResourceDTO>) => response.body!)
                )
                .subscribe({
                    next: (onlineResource) => {
                        const updateForm = {
                            name: onlineResource.title || undefined,
                            description: onlineResource.description || undefined,
                        };
                        this.form.patchValue(updateForm);
                    },
                });
        }
    }
}
src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts (1)

32-39: Consider adding migration guidance for deprecated properties.

While the deprecation notices are helpful, consider adding migration examples in the JSDoc comments to guide developers on how to transition from the deprecated properties to the new signal-based approach.

Apply this enhancement to the deprecation notices:

    /**
-    * @deprecated Use {@link isFormValidSignal} instead.
+    * @deprecated Use {@link isFormValidSignal} instead.
+    * @example
+    * // Before
+    * this.formValid
+    * // After
+    * this.isFormValidSignal()
     */
    formValid: boolean;
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.html (1)

Signal implementation is partially complete but can be enhanced

The component already uses signals through:

  • toSignal() for form status changes
  • computed() for form validation state

However, the implementation could be improved by:

  1. Converting form control getters to signals using toSignal() for better reactivity
  2. Using effect() to handle side effects in onLinkChanged()
  3. Adding cleanup for the form status signal subscription

Example refactoring for the control getters:

nameControl = toSignal(this.form.get('name')!.valueChanges);
🔗 Analysis chain

Line range hint 2-78: Verify signal implementation in the component.

To ensure the PR's objective of introducing signals is fully met, please verify that:

  1. Form controls are exposed as signals in the component
  2. Form validation state is derived from these signals
  3. The component properly cleans up signal subscriptions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify signal implementation in the component

# Test: Check if signals are properly implemented in the component
ast-grep --pattern 'class OnlineUnitFormComponent {
  $$$
  signal<$_>($_) {
    $$$
  }
  $$$
}'

# Test: Check for proper signal cleanup
rg -A 5 'ngOnDestroy|effect' src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts

Length of output: 366


Script:

#!/bin/bash
# Let's try a different approach to check the component implementation

# First, let's check the content of the component file
cat src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts

# As a backup, let's also search for signal-related imports and usage
rg -l "@angular/core.*signal" src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/

# And check for FormControl-related code
rg "FormControl|form\." src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts

Length of output: 5045

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

30-33: LGTM! Well-structured file extension handling with clear separation of concerns.

The implementation cleanly separates human-readable and technical formats. The comments are helpful but could be even more descriptive.

Consider enhancing the comments to be more specific:

-    // A human-readable list of allowed file extensions
+    // Comma-separated list of allowed file extensions for display purposes (e.g., "pdf, txt, doc")
-    // The list of file extensions for the "accept" attribute of the file input field
+    // Formatted list of file extensions for HTML file input's "accept" attribute (e.g., ".pdf,.txt,.doc")
src/main/webapp/app/exercises/programming/manage/update/update-components/information/programming-exercise-information.component.ts (2)

Line range hint 164-171: LGTM! Consider refactoring for improved readability.

The validation logic is comprehensive and the rename to isFormValidSignal() improves clarity. However, the boolean expression could be more readable.

Consider breaking down the validation checks into a separate method:

-        this.formValid = Boolean(
-            this.exerciseTitleChannelComponent()?.titleChannelNameComponent?.isFormValidSignal() &&
-                this.getIsShortNameFieldValid() &&
-                isCheckoutSolutionRepositoryValid &&
-                isRecreateBuildPlansValid &&
-                isUpdateTemplateFilesValid &&
-                areAuxiliaryRepositoriesValid &&
-                areCheckoutPathsValid,
-        );
+        this.formValid = this.validateAllFormFields(
+            isCheckoutSolutionRepositoryValid,
+            isRecreateBuildPlansValid,
+            isUpdateTemplateFilesValid,
+            areAuxiliaryRepositoriesValid,
+            areCheckoutPathsValid,
+        );
+
+    private validateAllFormFields(
+        isCheckoutSolutionRepositoryValid: boolean,
+        isRecreateBuildPlansValid: boolean,
+        isUpdateTemplateFilesValid: boolean,
+        areAuxiliaryRepositoriesValid: boolean,
+        areCheckoutPathsValid: boolean,
+    ): boolean {
+        return Boolean(
+            this.exerciseTitleChannelComponent()?.titleChannelNameComponent?.isFormValidSignal() &&
+            this.getIsShortNameFieldValid() &&
+            isCheckoutSolutionRepositoryValid &&
+            isRecreateBuildPlansValid &&
+            isUpdateTemplateFilesValid &&
+            areAuxiliaryRepositoriesValid &&
+            areCheckoutPathsValid,
+        );
+    }

Line range hint 89-98: Consider improving subscription management.

While the current implementation handles cleanup, it could be enhanced using RxJS operators to prevent potential memory leaks.

Consider using the takeUntilDestroyed operator from @angular/core/rxjs-interop:

+import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

-    inputFieldSubscriptions: (Subscription | undefined)[] = [];
+    constructor() {
+        this.exerciseTitleChannelComponent()?.titleChannelNameComponent?.formValidChanges
+            .pipe(takeUntilDestroyed())
+            .subscribe(() => this.calculateFormValid());
+        
+        // Apply similar pattern to other subscriptions
+    }
-    ngOnDestroy(): void {
-        for (const subscription of this.inputFieldSubscriptions) {
-            subscription?.unsubscribe();
-        }
-    }
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts (3)

27-33: Maintain consistent ordering and grouping of @Input and @Output properties

To enhance code readability and maintainability, consider grouping all @Input properties together, followed by @Output properties, and ordering them consistently.

Apply this diff to reorder the properties:

 @Input() formData: TextUnitFormData;
 @Input() isEditMode = false;
+@Input() hasCancelButton: boolean;

 @Output() formSubmitted: EventEmitter<TextUnitFormData> = new EventEmitter<TextUnitFormData>();
+@Output() onCancel: EventEmitter<any> = new EventEmitter<any>();

This aligns with the project's convention of grouping inputs and outputs, enhancing code consistency across the application.


40-41: Align dependency injection methods for consistency

Currently, FormBuilder is injected using the inject() function, while Router and TranslateService are injected via the constructor. For consistency, consider using the same injection method for all dependencies.

Option 1: Use inject() for all services:

+private readonly router = inject(Router);
+private readonly translateService = inject(TranslateService);
+private readonly formBuilder = inject(FormBuilder);

-constructor(
-    private router: Router,
-    private translateService: TranslateService,
-) {}

Option 2: Inject FormBuilder via the constructor:

-private readonly formBuilder = inject(FormBuilder);

 constructor(
     private router: Router,
     private translateService: TranslateService,
+    private formBuilder: FormBuilder,
 ) {}

Consistent injection patterns improve code readability and reduce potential confusion.


42-46: Initialize form controls with default values appropriately

Initializing form controls with undefined as the default value is acceptable. However, consider whether default values are necessary or if they could be omitted to simplify the code.

For example:

 form: FormGroup = this.formBuilder.group({
-    name: [undefined as string | undefined, [Validators.required, Validators.maxLength(255)]],
+    name: ['', [Validators.required, Validators.maxLength(255)]],
-    releaseDate: [undefined as dayjs.Dayjs | undefined],
+    releaseDate: [null as dayjs.Dayjs | null],
-    competencyLinks: [undefined as CompetencyLectureUnitLink[] | undefined],
+    competencyLinks: [[] as CompetencyLectureUnitLink[]],
 });

This can help avoid potential issues with form controls expecting certain types.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 4954074 and ea2cbd6.

📒 Files selected for processing (7)
  • src/main/webapp/app/exercises/programming/manage/update/update-components/information/programming-exercise-information.component.ts (1 hunks)
  • src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.html (1 hunks)
  • src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts (2 hunks)
  • src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.html (1 hunks)
  • src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts (3 hunks)
  • src/main/webapp/app/lecture/lecture-update.component.ts (2 hunks)
  • src/main/webapp/app/shared/form/title-channel-name/title-channel-name.component.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
src/main/webapp/app/exercises/programming/manage/update/update-components/information/programming-exercise-information.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/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.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/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.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/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.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/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.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/lecture/lecture-update.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/shared/form/title-channel-name/title-channel-name.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

📓 Learnings (3)
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.html (1)
Learnt from: florian-glombik
PR: ls1intum/Artemis#9656
File: src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts:69-71
Timestamp: 2024-11-02T22:57:57.717Z
Learning: In the `src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts`, the `isFormValid` computed property intentionally uses a logical OR between `this.statusChanges() === 'VALID'` and `this.fileName()` to mirror the original `isSubmitPossible` getter, ensuring consistent form validation behavior.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.html (1)
Learnt from: florian-glombik
PR: ls1intum/Artemis#9656
File: src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts:69-71
Timestamp: 2024-11-02T22:57:57.717Z
Learning: In the `src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts`, the `isFormValid` computed property intentionally uses a logical OR between `this.statusChanges() === 'VALID'` and `this.fileName()` to mirror the original `isSubmitPossible` getter, ensuring consistent form validation behavior.
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts (1)
Learnt from: florian-glombik
PR: ls1intum/Artemis#9656
File: src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts:69-71
Timestamp: 2024-11-02T22:57:57.717Z
Learning: In the `src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/attachment-unit-form/attachment-unit-form.component.ts`, the `isFormValid` computed property intentionally uses a logical OR between `this.statusChanges() === 'VALID'` and `this.fileName()` to mirror the original `isSubmitPossible` getter, ensuring consistent form validation behavior.
🔇 Additional comments (10)
src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.html (1)

Line range hint 3-3: LGTM: Proper usage of new Angular control flow syntax.

The template correctly implements the new @if syntax instead of the older *ngIf, which aligns with the coding guidelines.

Also applies to: 8-15

src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.ts (1)

2-2: LGTM: Modern Angular features adoption

The addition of computed, inject, and toSignal imports aligns with modern Angular best practices and the PR's objective to introduce signals.

Also applies to: 10-10

src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/online-unit-form/online-unit-form.component.html (1)

Line range hint 2-2: Excellent use of new Angular syntax!

The template consistently uses the new @if syntax instead of *ngIf throughout the file, which aligns perfectly with the coding guidelines.

Also applies to: 10-10, 13-13, 16-16, 26-26, 33-33, 36-36, 46-46, 49-49, 79-79

src/main/webapp/app/lecture/lecture-update.component.ts (3)

24-29: LGTM! Property access modifiers enhance encapsulation.

The changes to make icon properties and documentationType protected readonly improve encapsulation while maintaining inheritance capability. This aligns with Angular's style guide and supports the PR's goal of template optimization.


89-90: LGTM! Improved documentation clarity.

The updated comments clearly explain the navigation behavior based on the lecture's state, which helps maintainability.


24-33: Verify template usage of the protected properties.

The properties have been made protected. Let's verify that all template references have been updated accordingly.

✅ Verification successful

Template references to protected properties are correctly used

The verification shows that all template references to the protected properties are valid and working as expected. The properties are accessed in the component templates where they are defined:

  • lecture-update.component.html correctly uses all the protected properties defined in its component
  • Other components (lecture-attachments.component, lecture-unit-management, etc.) that show similar property usage have their own component-level declarations

This confirms that making these properties protected in lecture-update.component.ts doesn't break any template references, as they are properly scoped and accessed within their respective components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check template usage of the protected properties
# Expected: No direct references to these properties in templates

# Search for template references to the protected properties
echo "Checking template references..."
rg -t html "documentationType|faQuestionCircle|faSave|faPuzzleProcess|faBan|faHandShakeAngle|allowedFileExtensions|acceptedFileExtensionsFileBrowser" "src/main/webapp/app/lecture"

Length of output: 3814

src/main/webapp/app/exercises/programming/manage/update/update-components/information/programming-exercise-information.component.ts (2)

Line range hint 39-42: Well-implemented reactive state management using signals!

The implementation follows Angular's best practices for reactive programming with signals. The state management is clean and efficient.

Also applies to: 52-55


Line range hint 45-52: Excellent use of required input decorators!

The implementation follows Angular's latest best practices for input properties, improving type safety and runtime validation.

src/main/webapp/app/lecture/lecture-unit/lecture-unit-management/text-unit-form/text-unit-form.component.ts (2)

1-1: Good adoption of Angular's inject and computed functions

The inclusion of inject and computed from @angular/core aligns with Angular's move towards more streamlined dependency injection and reactive programming patterns.


25-25: Consistent visibility modifier for template-bound properties

Defining faTimes as protected ensures it is accessible in the template while encapsulating it from external classes. This aligns with Angular's best practices for component property visibility.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 3, 2024
@florian-glombik
Copy link
Contributor Author

florian-glombik commented Nov 5, 2024

Thanks for testing and the detailed information! @BBesrour #9658 (review)
Regarding the Internal Server Error: It seems to occur if the competencies are not set.
The empty channel name: this happens because the lecture is saved as we need the lecture id to save attachments and units (was present before this PR)

As the issues do not seem to be introduced with this PR, I will not address them. I also do not think that creating issues makes much sense as #9655 aims at removing the guided mode in the near future anyways.

I will keep them in mind and make sure the same issues do not occur for the new "status bar" edit mode :)

Copy link

@Haoyuli2002 Haoyuli2002 left a comment

Choose a reason for hiding this comment

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

Screenshot 2024-11-05 at 13 04 18 Tested on TS3 as Instructor 17. I have create a text lecture unit and an online lecture unit. Then I editted these units and they are working as expected. I also created a Lecture in the guided mode, add the dates, an Online Lecture Unit and a Text Lecture Unit. This function works fine as well. The only small issue I noticed is that:
  • If I used the Markdown Language in the Text Unit, it will be displayed properly. But if I then clicked the "View Isolated", it will redirect me to a page where the Markdown Language got some problems.
  • You may check the screenshots below.
    Other than that, I think everything is working well!
Screenshot 2024-11-05 at 13 04 30 Screenshot 2024-11-05 at 13 04 14

@florian-glombik
Copy link
Contributor Author

#9658 (review) As far as I am aware this is the expected behavior for the isolated view

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, lgtm

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.

Tested on TS3, worked fine.

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.

Tested on TS3. Works as described

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!) code quality lecture Pull requests that affect the corresponding module ready for review ready to merge refactoring small tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.