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: Migrate client code for conversation detail tabs #9973

Merged
merged 4 commits into from
Dec 14, 2024

Conversation

asliayk
Copy link
Contributor

@asliayk asliayk commented Dec 9, 2024

Checklist

General

Client

Motivation and Context

For the client migration, following files need to be updated:

-- File Path Standalone Signals Inject
20 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.html
21 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts
22 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.html
23 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts
24 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.html
25 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts
26 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.html
27 /overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts

Description

ConversationSettingsComponent, ConversationMembersComponent, ConversationMemberRowComponent, and ConversationInfoComponent have been updated to use inject and signals.

Known Issue: These components have been migrated to use inject and signals, but they haven't been converted to standalone yet, as it would impact other components. This will be addressed in a follow-up PR.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Course with Communication enabled
  1. Log in to Artemis
  2. Navigate to Communication section of a course
  3. Open the settings of a random channel by clicking the three-dot menu option.
  4. Test all functionalities across the three tabs (info, members, settings) and ensure everything works as expected.

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

Class/File Line Coverage Confirmation (assert/expect)
conversation-info.component.ts 90.09% ✅ ❌
conversation-member-row.component.ts 83.91% ✅ ❌
conversation-members.component.ts 93.18% ✅ ❌
conversation-settings.component.ts 88.37% ✅ ❌

Summary by CodeRabbit

  • New Features

    • Enhanced input handling in several components, transitioning to a more reactive programming model.
    • Added new methods for retrieving conversation creator and improved property access in templates.
  • Bug Fixes

    • Improved handling of optional chaining for safer property access in conversation-related components.
  • Tests

    • Updated test setups to align with new input/output handling and reactive properties.
    • Adjusted test cases to ensure proper state management using Angular's dependency injection context.

@asliayk asliayk added tests client Pull requests that update TypeScript code. (Added Automatically!) chore labels Dec 9, 2024
@asliayk asliayk self-assigned this Dec 9, 2024
@asliayk asliayk requested a review from a team as a code owner December 9, 2024 12:17
Copy link

coderabbitai bot commented Dec 9, 2024

Walkthrough

The pull request introduces several modifications across multiple components in the Angular application. Key changes include renaming input properties to align with new naming conventions, transitioning from traditional decorators to function-based input and output handling, and adopting a reactive programming model using signals. The updates affect how properties are accessed and initialized, ensuring that components use function calls instead of direct property access. The overall structure and logic of the components remain intact, focusing on enhancing code maintainability and consistency.

Changes

File Path Change Summary
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.html Updated input property from activeConversation to activeConversationInput for jhi-conversation-members component.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.html Changed access of activeConversation and course from properties to function calls. Introduced optional chaining for activeConversation?.creator.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts Updated input properties to use input and output decorators. Removed constructor in favor of inject function for dependency injection. Added getCreator method.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.html Modified access to activeConversation, course, and conversationMember to use function calls instead of properties.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts Refactored input and output properties to use input and output functions. Simplified constructor using inject for services.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.html Updated conditional checks for course and activeConversation to call them as functions.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts Transitioned to using input and output functions for properties. Changed activeConversation to a signal for reactive updates.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.html Updated checks for activeConversation and course to use function calls instead of direct property access.
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts Changed input and output properties to use new function-based syntax. Refactored constructor to utilize inject.
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts Renamed activeConversation to activeConversationInput in ConversationMembersStubComponent.
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts Added import for input and updated property initialization to use input<>() for activeConversation and course.
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts Added imports for input and runInInjectionContext. Updated property initialization to use input function.
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts Added imports for input and signal. Updated initialization of activeConversation and course to use signal<>() and input<>().
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts Added imports for input and runInInjectionContext. Updated property initialization to use input function for course and activeConversation.

Possibly related PRs

Suggested labels

refactoring, ready to merge, small, component:Communication

Suggested reviewers

  • HawKhiem
  • florian-glombik
  • sachmii
  • JohannesWt
  • Malekos74
  • az108

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

🧹 Outside diff range and nitpick comments (15)
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts (1)

125-129: Improve type safety in conversation manipulation.

The current implementation uses type casting which could be made more type-safe using type guards.

 runInInjectionContext(fixture.debugElement.injector, () => {
     const activeConversation = component.activeConversation();
-    (activeConversation as ChannelDTO).isArchived = true;
-    component.activeConversation = input<ConversationDTO>(activeConversation as ConversationDTO);
+    if (isChannelDTO(activeConversation)) {
+        activeConversation.isArchived = true;
+        component.activeConversation = input<ConversationDTO>(activeConversation);
+    }
 });
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (4)

44-47: Make injected services readonly.

To prevent accidental reassignment of injected services, consider making them readonly.

-    private modalService = inject(NgbModal);
-    private channelService = inject(ChannelService);
-    private groupChatService = inject(GroupChatService);
-    private alertService = inject(AlertService);
+    private readonly modalService = inject(NgbModal);
+    private readonly channelService = inject(ChannelService);
+    private readonly groupChatService = inject(GroupChatService);
+    private readonly alertService = inject(AlertService);

Line range hint 58-74: Improve error handling and null checks in conversation management.

The current implementation has several potential issues:

  1. Unsafe null assertions
  2. No error handling for the group chat service call
  3. Duplicate subscription logic
     leaveConversation($event: MouseEvent) {
         $event.stopPropagation();
-        if (isGroupChatDTO(this.activeConversation()!)) {
+        const conversation = this.activeConversation();
+        const courseId = this.course()?.id;
+        
+        if (!conversation || !courseId) {
+            this.alertService.error('artemisApp.conversation.errors.invalidState');
+            return;
+        }
+
+        if (isGroupChatDTO(conversation)) {
             this.groupChatService
-                .removeUsersFromGroupChat(this.course()!.id!, this.activeConversation()?.id!)
-                .pipe(takeUntil(this.ngUnsubscribe))
+                .removeUsersFromGroupChat(courseId, conversation.id)
+                .pipe(
+                    takeUntil(this.ngUnsubscribe),
+                    catchError((error: HttpErrorResponse) => {
+                        onError(this.alertService, error);
+                        return EMPTY;
+                    })
+                )
                 .subscribe(() => {
                     this.conversationLeave.emit();
                 });
             return;
-        } else if (isChannelDTO(this.activeConversation()!)) {
+        } else if (isChannelDTO(conversation)) {
             this.channelService
-                .deregisterUsersFromChannel(this.course()!.id!, this.activeConversation()?.id!)
-                .pipe(takeUntil(this.ngUnsubscribe))
+                .deregisterUsersFromChannel(courseId, conversation.id)
+                .pipe(
+                    takeUntil(this.ngUnsubscribe),
+                    catchError((error: HttpErrorResponse) => {
+                        onError(this.alertService, error);
+                        return EMPTY;
+                    })
+                )
                 .subscribe(() => {
                     this.conversationLeave.emit();
                 });
             return;
         }
-        throw new Error('The conversation type is not supported');
+        this.alertService.error('artemisApp.conversation.errors.unsupportedType');
     }

Line range hint 84-161: Extract duplicate modal logic into a reusable method.

The modal setup logic is duplicated between openArchivalModal and openUnArchivalModal.

+    private openConfirmationModal(
+        channel: ChannelDTO,
+        keys: {
+            titleKey: string;
+            questionKey: string;
+            descriptionKey: string;
+            confirmButtonKey: string;
+        },
+        onConfirm: () => void
+    ) {
+        const translationParams = { channelName: channel.name };
+        const modalRef: NgbModalRef = this.modalService.open(
+            GenericConfirmationDialogComponent,
+            defaultSecondLayerDialogOptions
+        );
+        
+        modalRef.componentInstance.translationParameters = translationParams;
+        modalRef.componentInstance.translationKeys = keys;
+        modalRef.componentInstance.canBeUndone = true;
+        modalRef.componentInstance.initialize();
+
+        from(modalRef.result)
+            .pipe(
+                catchError(() => EMPTY),
+                takeUntil(this.ngUnsubscribe)
+            )
+            .subscribe(() => onConfirm());
+    }

     openArchivalModal(event: MouseEvent) {
-        const channel = getAsChannelDTO(this.activeConversation()!);
+        const channel = getAsChannelDTO(this.activeConversation());
         if (!channel) {
             return;
         }
+        event.stopPropagation();
 
-        const keys = {
+        this.openConfirmationModal(
+            channel,
+            {
                 titleKey: 'artemisApp.dialogs.archiveChannel.title',
                 questionKey: 'artemisApp.dialogs.archiveChannel.question',
                 descriptionKey: 'artemisApp.dialogs.archiveChannel.description',
                 confirmButtonKey: 'artemisApp.dialogs.archiveChannel.confirmButton',
-        };
-
-        const translationParams = {
-            channelName: channel.name,
-        };
-
-        event.stopPropagation();
-        const modalRef: NgbModalRef = this.modalService.open(GenericConfirmationDialogComponent, defaultSecondLayerDialogOptions);
-        modalRef.componentInstance.translationParameters = translationParams;
-        modalRef.componentInstance.translationKeys = keys;
-        modalRef.componentInstance.canBeUndone = true;
-        modalRef.componentInstance.initialize();
-
-        from(modalRef.result)
-            .pipe(
-                catchError(() => EMPTY),
-                takeUntil(this.ngUnsubscribe),
-            )
-            .subscribe(() => {
+            },
+            () => {
                 this.channelService.archive(this.course()?.id!, channel.id!).subscribe({
                     next: () => {
                         this.channelArchivalChange.emit();
                     },
                     error: (errorResponse: HttpErrorResponse) => onError(this.alertService, errorResponse),
                 });
-            });
+            }
+        );
     }

Line range hint 165-179: Improve error handling in channel deletion.

The current implementation could benefit from more specific error handling and user feedback.

     deleteChannel() {
-        const channel = getAsChannelDTO(this.activeConversation()!);
+        const channel = getAsChannelDTO(this.activeConversation());
+        const courseId = this.course()?.id;
+
-        if (!channel) {
+        if (!channel || !courseId) {
+            this.alertService.error('artemisApp.channel.errors.invalidState');
             return;
         }
+
         this.channelService
-            .delete(this.course()?.id!, channel.id!)
-            .pipe(takeUntil(this.ngUnsubscribe))
+            .delete(courseId, channel.id)
+            .pipe(
+                takeUntil(this.ngUnsubscribe),
+                catchError((error: HttpErrorResponse) => {
+                    const errorMessage = error.status === 403 
+                        ? 'artemisApp.channel.errors.notAuthorized'
+                        : 'artemisApp.channel.errors.deleteFailed';
+                    this.dialogErrorSource.next(errorMessage);
+                    return EMPTY;
+                })
+            )
             .subscribe({
                 next: () => {
                     this.dialogErrorSource.next('');
                     this.channelDeleted.emit();
-                },
-                error: (errorResponse: HttpErrorResponse) => this.dialogErrorSource.next(errorResponse.message),
+                }
             });
     }
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts (2)

33-34: Consider renaming activeConversationInput for consistency.

The input property activeConversationInput could be renamed to activeConversation to maintain consistency and improve readability, as the input function already indicates that it's an input property.

Apply this diff to rename the input property:

 course = input<Course>();
-activeConversationInput = input<ConversationDTO>();
+activeConversation = input<ConversationDTO>();
 activeConversation = signal<ConversationDTO | null>(null);

 // In ngOnInit
-const inputValue = this.activeConversationInput();
+const inputValue = this.activeConversation();

62-62: Remove redundant public modifier.

In TypeScript classes, properties are public by default. The public keyword on conversationService is redundant and can be omitted for brevity.

Apply this diff to remove the redundant public keyword:

-public conversationService = inject(ConversationService);
+conversationService = inject(ConversationService);
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.html (1)

65-65: Consider standardizing input property names for consistency.

The input property for jhi-conversation-members has been renamed to activeConversationInput. To maintain consistency across components, consider using activeConversation as the input property name unless there is a specific reason for the distinction.

Apply this diff to rename the input property:

-<jhi-conversation-members [course]="course" [activeConversationInput]="activeConversation" (changesPerformed)="changesWerePerformed = true" />
+<jhi-conversation-members [course]="course" [activeConversation]="activeConversation" (changesPerformed)="changesWerePerformed = true" />

Ensure that the ConversationMembersComponent is updated accordingly to accept activeConversation as the input.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.html (1)

58-59: Consider performance optimization for frequent function calls.

The template bindings activeConversation() and course() will be called during every change detection cycle. Consider caching these values in local variables if they don't change frequently within the component.

- [activeConversation]="activeConversation()!"
- [course]="course()"
+ [activeConversation]="cachedActiveConversation"
+ [course]="cachedCourse"

Add to the component class:

private cachedActiveConversation = computed(() => this.activeConversation());
private cachedCourse = computed(() => this.course());
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.html (2)

85-93: Simplify nested conditionals and null checks.

The current implementation has multiple nested null checks and function calls which could be simplified.

- @if (activeConversation()?.creator) {
-   <li>
-     {{ 'artemisApp.dialogs.conversationDetail.infoTab.createdBy' | artemisTranslate }}:
-     {{ getCreator() ? getUserLabel(getCreator()!) : '' }}
-   </li>
- }
+ @if (getCreator(); as creator) {
+   <li>
+     {{ 'artemisApp.dialogs.conversationDetail.infoTab.createdBy' | artemisTranslate }}:
+     {{ getUserLabel(creator) }}
+   </li>
+ }

93-93: Simplify date display logic.

The date display logic could be simplified by using the non-null assertion more effectively.

- {{ activeConversation()!.creationDate ? (activeConversation()!.creationDate | artemisDate) : '' }}
+ {{ activeConversation()!.creationDate | artemisDate }}
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts (1)

Line range hint 109-127: Enhance test specificity per coding guidelines.

The test expectations could be more specific according to the coding guidelines.

- expect(component.changesWerePerformed).toBeFalse();
+ expect(component.changesWerePerformed).toBeExactlyFalse();

- expect(closeSpy).toHaveBeenCalledOnce();
+ expect(closeSpy).toHaveBeenCalledExactlyOnceWith();
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts (2)

Line range hint 230-236: Consider using a type discriminator for conversation types.

The conversation type checking could be improved using a type discriminator pattern.

Consider this pattern:

type ConversationType = 'channel' | 'groupChat';
interface BaseConversation {
    type: ConversationType;
}

// Then use type predicates
function isChannel(conversation: BaseConversation): conversation is ChannelDTO {
    return conversation.type === 'channel';
}

Line range hint 242-251: Consider using an enum for user roles.

The user authority logic could be more maintainable using an enum for roles.

Consider this pattern:

enum UserRole {
    INSTRUCTOR = 'instructor',
    TUTOR = 'tutor',
    STUDENT = 'student'
}

interface UserAuthority {
    role: UserRole;
    icon: IconProp;
    tooltipKey: string;
}
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts (1)

162-166: Consider extracting test setup logic.

The test setup logic for modifying component properties could be extracted into a helper method for better reusability.

Consider this pattern:

function updateComponentMember(fixture: ComponentFixture<ConversationMemberRowComponent>, updates: Partial<ConversationUserDTO>) {
    runInInjectionContext(fixture.debugElement.injector, () => {
        const member = { ...fixture.componentInstance.conversationMember(), ...updates };
        fixture.componentInstance.conversationMember = input<ConversationUserDTO>(member);
    });
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 390d00c and 5123fee.

📒 Files selected for processing (14)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.html (1 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.html (4 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts (9 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.html (2 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts (11 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.html (3 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts (7 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.html (1 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (8 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts (1 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts (2 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts (3 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts (4 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.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/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.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}}

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.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}}

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.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/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.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/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.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/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.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}}

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.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/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.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}}

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.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}}

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.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-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.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-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.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-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.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

🪛 GitHub Check: client-style
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts

[warning] 176-176:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 194-194:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts

[warning] 126-126:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 126-126:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 146-146:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 146-146:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 177-177:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 177-177:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 177-177:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 196-196:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

🔇 Additional comments (15)
src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts (1)

Line range hint 55-174: Test suite structure and coverage look good!

The test suite:

  • Properly tests permissions and conditional rendering
  • Correctly mocks services and handles async operations
  • Uses specific expectations and proper test isolation
  • Follows jest and NgMocks best practices
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (1)

1-1: LGTM! Component follows Angular style guidelines.

The migration to the new input/output syntax is implemented correctly.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts (2)

31-34: Consistent use of input and signal functions.

Great job transitioning to the new input and signal APIs for defining inputs and reactive properties. This enhances readability and aligns with Angular's recommendations.


182-190: Avoid mutating state directly within signals.

While updating the activeConversation signal, ensure that you are not mutating the existing state. Returning a new object is good practice. Verify that current is not mutated elsewhere in the code.

Run the following script to check for any direct mutations of current:

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.html (2)

1-1: Proper use of the new @if syntax with function calls.

Good job updating the conditional to use @if (activeConversation() && course()), aligning with the new Angular syntax and reactive programming model.


18-18: Consistent null checking with optional chaining.

Using conversationMember()?.isStudent ensures that you safely access isStudent even if conversationMember() returns null or undefined. Good practice!

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.html (1)

1-1: Updated conditional check with function calls.

The conditional now correctly uses @if (activeConversation() && course()), reflecting the reactive approach and aligning with the new Angular syntax.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.html (1)

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

The conversion from *ngIf to @if follows the new Angular syntax guidelines.

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/conversation-detail-dialog.component.spec.ts (1)

28-28: LGTM! Property rename aligns with component changes.

The input property rename from activeConversation to activeConversationInput is consistent with the component changes.

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.spec.ts (1)

78-82: LGTM: Proper initialization of signals and inputs

The component initialization correctly uses TestBed.runInInjectionContext to set up the signals and inputs, following Angular's latest practices.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts (2)

47-49: LGTM: Clean implementation of inputs and outputs

The component properly implements required and optional inputs using the new Angular syntax.


51-54: LGTM: Modern dependency injection

Clean implementation of dependency injection using the new inject function.

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.spec.ts (1)

52-56: LGTM: Proper test setup with new input system

The component initialization correctly uses TestBed.runInInjectionContext to set up the inputs, following Angular's latest practices.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts (1)

33-36: LGTM: Input/Output declarations follow the new Angular syntax.

The component correctly uses the new input/output syntax with signals, which is the recommended approach in modern Angular.

src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.spec.ts (1)

89-94: LGTM: Proper setup of input signals in tests.

The test correctly uses runInInjectionContext to set up input signals, following Angular's best practices.

coderabbitai[bot]
coderabbitai bot previously approved these changes Dec 9, 2024
…igration' into chore/conversation-detail-tabs-migration
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: 0

🧹 Outside diff range and nitpick comments (2)
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts (1)

43-45: Consider using type guard instead of type casting

The type casting in getCreator method could be made safer by using a type guard function.

-return this.activeConversation()?.creator as ConversationUserDTO | null;
+return this.activeConversation()?.creator && isConversationUserDTO(this.activeConversation()?.creator) 
+  ? this.activeConversation()?.creator 
+  : null;
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (1)

Line range hint 62-174: Add comprehensive null checking for service calls

Multiple service calls use unsafe non-null assertions with optional chaining, which could lead to runtime errors.

Apply this pattern across all service methods:

leaveConversation($event: MouseEvent) {
    $event.stopPropagation();
-    if (isGroupChatDTO(this.activeConversation()!)) {
+    const conversation = this.activeConversation();
+    const courseId = this.course()?.id;
+    if (!conversation || !courseId) {
+        return;
+    }
+    if (isGroupChatDTO(conversation)) {
        this.groupChatService
-            .removeUsersFromGroupChat(this.course()!.id!, this.activeConversation()?.id!)
+            .removeUsersFromGroupChat(courseId, conversation.id)
            .pipe(takeUntil(this.ngUnsubscribe))
            .subscribe(() => {
                this.conversationLeave.emit();
            });
        return;
    }

Similar pattern should be applied to:

  • openArchivalModal
  • openUnArchivalModal
  • deleteChannel
🧰 Tools
🪛 GitHub Check: client-style

[warning] 64-64:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 72-72:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5123fee and 087351f.

📒 Files selected for processing (5)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts (9 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts (11 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts (7 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (8 hunks)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/test/javascript/spec/component/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.spec.ts
  • src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-member-row/conversation-member-row.component.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.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-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.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-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.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

🪛 GitHub Check: client-style
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts

[warning] 118-118:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 119-119:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts

[warning] 64-64:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 72-72:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 117-117:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 157-157:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 174-174:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

🔇 Additional comments (14)
src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-info/conversation-info.component.ts (6)

1-1: LGTM! Imports are properly updated for signals migration

The imports have been correctly updated to include the necessary Angular features (inject, input, output) for the migration to signals, and the ConversationUserDTO model has been properly imported.

Also applies to: 22-22


47-49: LGTM! Properties correctly migrated to new input/output API

The migration from decorators to the new input/output API is correctly implemented, maintaining the required/optional status of inputs.


51-54: LGTM! Services properly injected using modern DI pattern

The migration from constructor injection to the inject() function follows Angular's modern dependency injection patterns.


172-175: LGTM! Proper null checks added for courseId

The addition of null checks for courseId improves safety by preventing undefined behavior.

Also applies to: 195-198


220-221: LGTM! Type references properly added for template type checking

The addition of protected readonly type references enables proper type checking in templates when using strict mode.


180-180: ⚠️ Potential issue

Address remaining non-null assertions

There are still unsafe non-null assertions on channel.id! and groupChat.id! that should be handled similarly to the courseId check.

Apply this pattern to both update methods:

private updateChannel<K extends keyof ChannelDTO>(channel: ChannelDTO, propertyName: K, updateValue: ChannelDTO[K]) {
    const courseId = this.course()?.id;
    if (!courseId) {
        return;
    }
+   if (!channel.id) {
+       this.alertService.error('artemisApp.conversation.error.channelNotFound');
+       return;
+   }
    const updateDTO = new ChannelDTO();
    updateDTO[propertyName] = updateValue;
-   this.channelService.update(courseId, channel.id!, updateDTO)
+   this.channelService.update(courseId, channel.id, updateDTO)

Also applies to: 202-202

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-settings/conversation-settings.component.ts (4)

1-1: LGTM: Imports updated correctly for new Angular syntax

The imports have been properly updated to include the new input/output and inject functions from @angular/core.


27-32: Consider implementing cleanup for outputs

While the migration to function-based inputs/outputs is correct, ensure proper cleanup of output subscriptions to prevent memory leaks.


44-47: LGTM: Clean dependency injection implementation

The migration to the new inject() syntax is well-implemented, making the code more maintainable and cleaner than constructor-based DI.


50-57: 🛠️ Refactor suggestion

Replace non-null assertion with safe navigation

While the early return for conversation is good, there's still an unsafe non-null assertion when checking canDeleteChannel.

-        this.canDeleteChannel = this.conversationAsChannel ? canDeleteChannel(this.course()!, this.conversationAsChannel) : false;
+        const course = this.course();
+        this.canDeleteChannel = course && this.conversationAsChannel ? canDeleteChannel(course, this.conversationAsChannel) : false;

Likely invalid or redundant comment.

src/main/webapp/app/overview/course-conversations/dialogs/conversation-detail-dialog/tabs/conversation-members/conversation-members.component.ts (4)

62-65: LGTM!

The usage of the inject function for dependency injection aligns with the updated Angular patterns and enhances code readability.


146-149: LGTM!

Initializing the activeConversation signal with the input value ensures reactive updates and state consistency.


186-194: LGTM!

Updating the activeConversation signal to reflect the new numberOfMembers maintains consistency across the component when members change.


118-119: ⚠️ Potential issue

Avoid using non-null assertions after optional chaining

Using non-null assertions ! immediately after optional chaining ?. can lead to runtime errors if the value is null or undefined. Since the if condition already ensures that this.course()?.id and this.activeConversation()?.id are truthy, you can safely access id without optional chaining or non-null assertions.

Apply this diff to correct the issue:

return this.conversationService.searchMembersOfConversation(
-    this.course()?.id!,
-    this.activeConversation()?.id!,
+    this.course().id,
+    this.activeConversation().id,
     this.searchTerm,
     this.page - 1,
     this.itemsPerPage,
     Number(this.selectedFilter),
);
🧰 Tools
🪛 GitHub Check: client-style

[warning] 118-118:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong


[warning] 119-119:
Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong

Copy link
Contributor

@iyannsch iyannsch left a comment

Choose a reason for hiding this comment

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

Changes LGTM

Copy link
Contributor

@raffifasaro raffifasaro left a comment

Choose a reason for hiding this comment

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

Code lgtm

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 TS2. I tested the followings:
✅ Edit the name of a channel
✅ Edit the topic of a channel
✅ Edit the description of a channel (although I'm not really sure how the change is reflected)
✅ Searching for members
✅ Archiving channels

Everything works fine. One thing I noticed was the change for the name of the channel was only updated after I close the edit popup, even after clicking on save, the change is not reflected imediately.

image

After closing the pop up for editing, the change is updated

image

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 TS6, everything works just fine as before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
chore client Pull requests that update TypeScript code. (Added Automatically!) ready to merge tests
Projects
Status: Merged
Development

Successfully merging this pull request may close these issues.

7 participants