Skip to content

Conversation

@Senan04
Copy link

@Senan04 Senan04 commented Nov 11, 2025

Checklist

General

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the client coding guidelines.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.

Motivation and Context

This change is required because when a user forwards a message to another user with whom they have no prior direct message conversation, the newly created DM chat is not immediately displayed in the left-hand navigation sidebar. This resulted in a poor user experience, forcing users to manually refresh the page or course to see the new conversation tab.
Fixes #11513

Description

I have added a Method reloadSidebar to CourseSidebarService that gets called by forwardPost in PostingReactionsbarComponent when the forwarded Message was succesfully created by the metisService. CourseConversationsComponent gets notified via its event subscription so the data gets refreshed and the sidebar updated accordingly.

Steps for Testing

Prerequisites:

  • 2 Students
  • 1 Course with communication functionality enabled
  1. Log in to Artemis as Student A.
  2. Navigate to any course where communication is enabled.
  3. Open the chat panel (e.g., the general channel or any other group channel).
  4. Select any existing message within the channel.
  5. Click the "Forward" option.
  6. Select Student B as the recipient for the forwarded message. Important: Ensure that Student A and Student B have no existing Direct Message conversation prior to this test.
  7. Verify the result: The newly created Direct Message conversation with Student B appears immediately in the sidebar list of Direct Messages without the need for a manual page refresh.

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Summary by CodeRabbit

  • New Features

    • Sidebar now automatically refreshes after forwarding posts, keeping conversation data synchronized.
  • Tests

    • Added test coverage for sidebar reload events and post-forwarding actions.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Nov 11, 2025
@github-actions github-actions bot added client Pull requests that update TypeScript code. (Added Automatically!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module labels Nov 11, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran200 passed3 skipped2 failed1h 14m 29s 489ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseDropLocation.spec.ts
ts.Quiz Exercise Drop Location Spec › DnD Quiz drop locations › Checks drop locations❌ failure2m 3s 923ms
e2e/exam/test-exam/TestExamParticipation.spec.ts
ts.Test exam participation › Early Hand-in › Using exercise overview to navigate within exam❌ failure3m 38s 243ms

@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran200 passed3 skipped2 failed1h 14m 27s 385ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseDropLocation.spec.ts
ts.Quiz Exercise Drop Location Spec › DnD Quiz drop locations › Checks drop locations❌ failure2m 3s 837ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 36s 164ms

@Senan04 Senan04 changed the title Communication : Fix open a new direct chat immediately after forwarding a message to a new user Communication: Fix open a new direct chat immediately after forwarding a message to a new user Nov 18, 2025
@Senan04 Senan04 changed the title Communication: Fix open a new direct chat immediately after forwarding a message to a new user Communication: Fix open a new direct chat immediately after forwarding a message to a new user Nov 18, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran201 passed3 skipped1 failed1h 12m 22s 166ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 36s 557ms

@helios-aet helios-aet bot temporarily deployed to artemis-test4.artemis.cit.tum.de November 19, 2025 07:24 Inactive
@Senan04 Senan04 marked this pull request as ready for review November 20, 2025 16:18
@Senan04 Senan04 requested review from a team and krusche as code owners November 20, 2025 16:18
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

Walkthrough

A new sidebar reload mechanism is implemented in CourseSidebarService with an EventEmitter. When message forwarding completes in PostingReactionsBar, reloadSidebar() is called, triggering an event that CourseConversations component listens to, refreshing sidebar data via prepareSidebarData().

Changes

Cohort / File(s) Change Summary
Sidebar Reload Event Service
src/main/webapp/app/core/course/overview/services/course-sidebar.service.ts, src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts
Added public reloadSidebar$ EventEmitter and reloadSidebar() method to service. Introduced test case verifying event emission and subscription.
Message Forwarding Integration
src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.ts, src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
Injected CourseSidebarService and integrated it into forwardPost flow. Added complete callback that invokes reloadSidebar() after forwarding finishes. Extended test suite with spy assertion.
Sidebar UI Refresh
src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.ts, src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
Subscribed to courseSidebarService.reloadSidebar$ in ngOnInit to trigger prepareSidebarData() on reload events. Added cleanup in ngOnDestroy. Added test verifying event-driven sidebar data refresh.

Sequence Diagram

sequenceDiagram
    actor User
    participant PBComp as PostingReactionsBar
    participant Service as CourseSidebarService
    participant CCComp as CourseConversations

    User->>PBComp: Forward message
    PBComp->>PBComp: createForwardedMessages()
    PBComp->>Service: reloadSidebar()
    Service->>Service: reloadSidebar$.emit()
    Service-->>CCComp: reloadSidebar$ event
    CCComp->>CCComp: prepareSidebarData()
    CCComp-->>User: Sidebar updated
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Multiple affected files with coordinated changes across service, message-forwarding, and sidebar-refresh layers
  • Straightforward observable/event-emitter pattern applied consistently
  • Test coverage added for new event emission and subscription flows
  • Attention areas:
    • Verify subscription cleanup in ngOnDestroy prevents memory leaks
    • Confirm prepareSidebarData() idempotency and performance impact when called frequently
    • Check that the complete callback in forwardPost doesn't interfere with existing error handling or retry logic

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: fixing sidebar updates when forwarding messages to users with no prior conversation.
Linked Issues check ✅ Passed All coding requirements from issue #11513 are met: reloadSidebar method added to CourseSidebarService, PostingReactionsBarComponent triggers reload after forward completion, and CourseConversationsComponent refreshes sidebar data on reload event.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the sidebar refresh issue; no unrelated modifications to other features or systems were introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bugfix/communication/refresh-conversations-on-forward

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@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

🧹 Nitpick comments (4)
src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.ts (1)

165-165: Sidebar reload subscription is correct; optional consistency refactor

Subscribing to courseSidebarService.reloadSidebar$ and calling prepareSidebarData() (with proper unsubscribe in ngOnDestroy) cleanly wires the new reload behavior into the component and fulfills the bugfix objective.

If you want to align with the rest of the component’s Rx usage, you could alternatively expose reloadSidebar$ as an Observable<void> and subscribe via pipe(takeUntil(this.ngUnsubscribe)) instead of maintaining a separate Subscription field. Not required for this PR.

Also applies to: 258-260, 383-383, 504-513

src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.ts (1)

34-35: Sidebar reload hook after forwarding is correct; minor optimization possible

Injecting CourseSidebarService and calling reloadSidebar() in the createForwardedMessages completion handler is a good way to ensure the new DM appears immediately in the sidebar.

Note that when a post is forwarded to multiple conversations, forwardPost will trigger a full sidebar reload once per conversation. If this ever becomes a hot path, you could wrap the forwards in a single aggregation (e.g. forkJoin or a counter) and call reloadSidebar() only once after all forwards complete.

Also applies to: 151-151, 586-592

src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts (1)

363-370: Reload integration test is valid; could be tightened if desired

Spying on prepareSidebarData and asserting it is called after courseSidebarService.reloadSidebar() verifies the new subscription works as intended.

If you ever want more precision, you could call fixture.detectChanges() first and then prepareSidebarDataSpy.mockClear() before triggering reloadSidebar() to assert only the reload emission, but the current test is already acceptable.

src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts (1)

47-47: Sidebar reload behavior after forwarding is well-covered in tests

Mocking CourseSidebarService via MockProvider, spying on reloadSidebar, and asserting it is called when forwardPost completes gives good coverage of the new behavior.

Given createForwardedMessagesSpy is stubbed with of(null), you could drop fakeAsync/tick() in the last test, but it’s not required for correctness.

Also applies to: 55-57, 94-95, 102-104, 730-742

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c038ff and 64dea2b.

📒 Files selected for processing (6)
  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts (3 hunks)
  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.ts (3 hunks)
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts (1 hunks)
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.ts (3 hunks)
  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts (1 hunks)
  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/**/*.ts

⚙️ CodeRabbit configuration file

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

Files:

  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.ts
  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.ts
  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts
🧠 Learnings (7)
📚 Learning: 2025-09-01T10:20:40.706Z
Learnt from: Michael-Breu-UIbk
Repo: ls1intum/Artemis PR: 10989
File: src/main/webapp/app/programming/manage/detail/programming-exercise-detail.component.with-sharing.spec.ts:132-149
Timestamp: 2025-09-01T10:20:40.706Z
Learning: In the Artemis codebase, Angular component test files for ProgrammingExerciseDetailComponent follow a pattern where the component is imported but not explicitly declared in TestBed.configureTestingModule(), yet TestBed.createComponent() still works successfully. This pattern is consistently used across test files like programming-exercise-detail.component.spec.ts and programming-exercise-detail.component.with-sharing.spec.ts.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
📚 Learning: 2024-10-10T11:42:23.069Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9443
File: src/test/javascript/spec/component/hestia/git-diff-report/git-diff-modal.component.spec.ts:55-60
Timestamp: 2024-10-10T11:42:23.069Z
Learning: In `git-diff-report-modal.component.spec.ts`, using `fakeAsync` and `tick` does not work for handling asynchronous operations in the tests; alternative methods are needed.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
📚 Learning: 2024-10-20T22:00:52.335Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9505
File: src/test/javascript/spec/integration/code-editor/code-editor-container.integration.spec.ts:179-181
Timestamp: 2024-10-20T22:00:52.335Z
Learning: In `src/test/javascript/spec/integration/code-editor/code-editor-container.integration.spec.ts`, `ResizeObserver` is mocked within the `beforeEach` block.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts
📚 Learning: 2024-10-13T12:03:02.430Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9463
File: src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts:50-55
Timestamp: 2024-10-13T12:03:02.430Z
Learning: In `src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts`, when a function is called multiple times in a test, use `toHaveBeenCalledTimes` and `toHaveBeenNthCalledWith` assertions instead of `toHaveBeenCalledExactlyOnceWith`.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts
📚 Learning: 2025-08-21T17:30:20.530Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11297
File: src/main/webapp/app/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.spec.ts:34-34
Timestamp: 2025-08-21T17:30:20.530Z
Learning: FitTextDirective in src/main/webapp/app/quiz/shared/fit-text/fit-text.directive.ts is a standalone directive marked with standalone: true, so it should be imported in TestBed imports array, not declarations array.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
📚 Learning: 2025-05-31T23:25:34.020Z
Learnt from: eylulnc
Repo: ls1intum/Artemis PR: 10944
File: src/main/webapp/app/communication/message/message-reply-inline-input/message-reply-inline-input.component.spec.ts:177-190
Timestamp: 2025-05-31T23:25:34.020Z
Learning: In MessageReplyInlineInputComponent tests, the manual call to component['loadDraft']() after ngOnInit() is necessary because ngOnInit() starts an async loadCurrentUser() operation that only calls loadDraft() after the account identity is resolved. The manual call ensures the draft loading logic is tested directly, bypassing async timing dependencies.

Applied to files:

  • src/main/webapp/app/communication/posting-reactions-bar/posting-reactions-bar.component.spec.ts
  • src/main/webapp/app/communication/shared/course-conversations/course-conversations.component.spec.ts
📚 Learning: 2025-09-01T13:47:02.624Z
Learnt from: Michael-Breu-UIbk
Repo: ls1intum/Artemis PR: 10989
File: src/main/webapp/app/programming/manage/detail/programming-exercise-detail.component.with-sharing.spec.ts:167-169
Timestamp: 2025-09-01T13:47:02.624Z
Learning: In Jest tests, prefer using jest.spyOn() over direct method assignment for mocking service methods, as spies are automatically restored by Jest's cleanup mechanisms (jest.restoreAllMocks()), while direct assignment bypasses this system and can lead to test pollution where mocked methods affect subsequent tests.

Applied to files:

  • src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (2)
src/main/webapp/app/core/course/overview/services/course-sidebar.service.ts (1)

10-11: Reload event API fits existing sidebar service pattern

reloadSidebar$ and reloadSidebar() mirror the existing close/open/toggle event emitters, keeping the API uniform and easy to consume from components and tests.

Also applies to: 24-26

src/main/webapp/app/core/course/overview/services/course-sidebar.service.spec.ts (1)

35-39: Tests adequately cover the new reloadSidebar event

The added specs correctly assert that reloadSidebar() emits on reloadSidebar$ and that subscribers receive the event, in line with the existing close/open/toggle tests and Jest spying practices.

Also applies to: 45-46, 50-50, 55-56, 60-60

@helios-aet helios-aet bot temporarily deployed to artemis-test4.artemis.cit.tum.de November 21, 2025 13:09 Inactive
Copy link
Contributor

@toukhi toukhi 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 TS4 and works as described

Copy link
Contributor

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

Code looks good 👍

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!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module ready for review

Projects

Status: Work In Progress

Development

Successfully merging this pull request may close these issues.

Fix: Forwarding a message to a user with no prior conversation doesn't open chat tab

4 participants