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

Communication: Allow user to forward messages #9794

Open
wants to merge 118 commits into
base: develop
Choose a base branch
from

Conversation

asliayk
Copy link
Contributor

@asliayk asliayk commented Nov 16, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I added pre-authorization annotations according to the guidelines and checked the course groups for all new REST Calls (security).

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding and design guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Jest) related to the features (with a high test coverage), while following the test guidelines.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

Currently user cannot forward messages to other channels/direct-group chats.

(Closes #9066)

Description

The forward message feature has been added. Users can now navigate to the forward message dialog by clicking on the forward message option. They can select a random number of destinations and add content to the forwarded message (similar to Slack).

forwarded_message table has been added to the database with the following fields:

  • id: id of forwarded message
  • source_id: the id of the original message
  • source_type: the type of the original message (post or answer)
  • destination_post_id: the id of the destination post (the id of newly created post with the forwarded message)
  • destination_answer_id: the id of the destination answer post (the id of newly created answer post with the forwarded message)

post and answer_post table have been updated with a new column named has_forwarded_messages.

Known Issue for a followup PR:
The server-side changes for forwarding multiple messages within a single message and forwarding a message as a reply to another message (inside an AnswerPost) are already in place, but the client-side implementation is not ready yet. To achieve this, a unique message link needs to be generated for each post/answer post, similar to the "Copy Link" feature in Slack. This will be completed in a follow-up PR.

Steps for Testing

Prerequisites:

  • 1 Instructor/Student
  • 1 Course with Communication enabled
  1. Log in to Artemis.
  2. Navigate to the Communication section of a course.
  3. Select a random message to forward or create a new one. Click on the forward message option (available on its hover bar or in the dropdown menu when opened via right-click).
  4. Add some content to the forwarded message and select random destinations to forward the message.
  5. Go to the destination channels/user chats and observe the forwarded messages.

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

Performance Review

  • I (as a reviewer) confirm that the client changes (in particular related to REST calls and UI responsiveness) are implemented with a very good performance even for very large courses with more than 2000 students.
  • I (as a reviewer) confirm that the server changes (in particular related to database calls) are implemented with a very good performance even for very large courses with more than 2000 students.

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Performance Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Confirmation (assert/expect)
answer-post.model.ts 100%
forwarded-message.model.ts 91.66% ✅ ❌
post.model.ts 100%
posting.model.ts 86.36% ✅ ❌
course-conversations.component.ts 91.27% ✅ ❌
forward-message-dialog.component.ts 95.79% ✅ ❌
conversation-messages.component.ts 95.53% ✅ ❌
answer-post.service.ts 100%
answer-post.component.ts 93.75% ✅ ❌
forwarded-message.service.ts 100%
forwarded-message.component.ts 90% ✅ ❌
metis-conversation.service.ts 83.47% ✅ ❌
metis.service.ts 88.43% ✅ ❌
post.service.ts 80% ✅ ❌
post.component.ts 97.1% ✅ ❌
answer-post-reactions-bar.component.ts 92.3% ✅ ❌
post-reactions-bar.component.ts 94.44% ✅ ❌
posting-reactions-bar.directive.ts 63.93% ✅ ❌
posting-thread.component.ts 100%
posting.directive.ts 93.82% ✅ ❌
profile-picture.component.ts 100%

Server

Class/File Line Coverage Confirmation (assert/expect)
AnswerPost.java 90% ✅ ❌
ForwardedMessage.java 42% ✅ ❌
Post.java 95% ✅ ❌
ForwardedMessageDTO.java 100%
ForwardedMessagesGroupDTO.java 100%
ForwardedMessageRepository.java not found (added)
AnswerMessageService.java 88% ✅ ❌
ConversationMessagingService.java 92% ✅ ❌
AnswerMessageResource.java 90% ✅ ❌
ConversationMessageResource.java 88% ✅ ❌
ForwardedMessageResource.java 94% ✅ ❌

Screenshots

forwarded message view
image

forward message dialog
image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added functionality to forward messages, including a new modal dialog for selecting channels and chats.
    • Introduced methods to retrieve messages by their IDs and manage forwarded messages.
    • Enhanced the Post and AnswerPost classes to track forwarded messages.
    • Added a new component for displaying forwarded messages.
    • Implemented a new method for batch retrieval of answer messages by their IDs.
    • Added new endpoints for retrieving answer posts and source posts by their IDs.
    • Introduced a new DTO for grouping forwarded messages.
    • Added new buttons for forwarding messages in various components.
    • Enhanced the ConversationMessagesComponent to handle forwarded messages and navigation.
    • Added new methods in MetisConversationService for creating group and direct conversations.
  • Bug Fixes

    • Improved error handling in message retrieval and forwarding functionalities.
  • Documentation

    • Updated UI elements and added tooltips for new features.
  • Style

    • Introduced new styles for the forward message dialog and related components.
  • Tests

    • Added tests for new functionalities related to message forwarding.
    • Enhanced test coverage for components managing forwarded messages.
  • Chores

    • Updated internationalization files to include translations for the forward message feature.

asliayk and others added 30 commits October 10, 2024 20:48
…e-message-view' into feature/communication/consecutive-message-view
…-view

# Conflicts:
#	src/main/webapp/app/overview/course-conversations/layout/conversation-messages/conversation-messages.component.ts
#	src/main/webapp/app/shared/metis/answer-post/answer-post.component.scss
coderabbitai[bot]
coderabbitai bot previously approved these changes Jan 16, 2025
@asliayk
Copy link
Contributor Author

asliayk commented Jan 17, 2025

after resolving merge conflicts and newly added client tests, this PR is ready for review again :)

here are the performance test results:

image

This Locust script tests the forward message workflow under load. Each user:

  1. Logs in briefly
  2. Fetches messages from a conversation and randomly picks one
  3. Creates a new post and forwards the selected message

These steps mimic typical user activity, allowing us to see how the system handles multiple forwarding actions simultaneously. From the attached results, we can observe stable response times and low error rates, indicating that the application can effectively manage concurrent forwarding requests without significant performance issues.

Copy link
Contributor

@FelberMartin FelberMartin left a comment

Choose a reason for hiding this comment

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

Just tested it on TS3, works mostly as expected from a technical side. I have two remarks:

  1. In dark mode, the forward autocompletion hint row highlighting is quite bright, and makes it hard to read the row that the user currently is hovering over
  2. When searching for users, it looks like we currently only search by loginName. This leads to confusion when I already see the "Test User 12" in the list when typing "test", but then the user disappears again when I type "test user" into the search field. Would it be possible to search users by their full name?
20250117-1421-36.5808733.mp4

@asliayk
Copy link
Contributor Author

asliayk commented Jan 17, 2025

Just tested it on TS3, works mostly as expected from a technical side. I have two remarks:

  1. In dark mode, the forward autocompletion hint row highlighting is quite bright, and makes it hard to read the row that the user currently is hovering over
  2. When searching for users, it looks like we currently only search by loginName. This leads to confusion when I already see the "Test User 12" in the list when typing "test", but then the user disappears again when I type "test user" into the search field. Would it be possible to search users by their full name?

20250117-1421-36.5808733.mp4

The second issue you mentioned has already been noted. However, I used the preexisting endpoint for user selection, which is also used in the "Create Direct Chat" and "Group Chat" options. In those options, users cannot search by name either; they can only search using the login name. While this is an issue that needs to be addressed, it is not directly related to this PR.

I’m not entirely sure which specific color you are referring to in the first issue. I tried to align it with the existing input sections to make it consistent.

@FelberMartin
Copy link
Contributor

FelberMartin commented Jan 17, 2025

The second issue you mentioned has already been noted. However, I used the preexisting endpoint for user selection, which is also used in the "Create Direct Chat" and "Group Chat" options. In those options, users cannot search by name either; they can only search using the login name. While this is an issue that needs to be addressed, it is not directly related to this PR.

Ah I remember having the same problem on the Android app 😅. However I just checked for creating a DM chat, and there searching by username seems to work. Maybe there is already a fix in place?

image


I’m not entirely sure which specific color you are referring to in the first issue. I tried to align it with the existing input sections to make it consistent.

The color I am refering to, is the bright white of the row item backgrounds, that highlights the list item that the mouse hovers over (see screenshot below). I am not sure what other inputs use this color for highlighting as well, but eg also the selection for the DM chat creation uses a much more pleasant color imo (see blue highlighted row in screenshot above).

image

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.component.ts (3)

5-11: Consolidate monaco-editor action imports.

Consider consolidating the monaco-editor action imports for better maintainability.

Apply this diff:

-import { BoldAction } from 'app/shared/monaco-editor/model/actions/bold.action';
-import { ItalicAction } from 'app/shared/monaco-editor/model/actions/italic.action';
-import { UnderlineAction } from 'app/shared/monaco-editor/model/actions/underline.action';
-import { QuoteAction } from 'app/shared/monaco-editor/model/actions/quote.action';
-import { CodeAction } from 'app/shared/monaco-editor/model/actions/code.action';
-import { CodeBlockAction } from 'app/shared/monaco-editor/model/actions/code-block.action';
-import { UrlAction } from 'app/shared/monaco-editor/model/actions/url.action';
+import {
+    BoldAction,
+    ItalicAction,
+    UnderlineAction,
+    QuoteAction,
+    CodeAction,
+    CodeBlockAction,
+    UrlAction,
+} from 'app/shared/monaco-editor/model/actions';

41-43: Simplify signal type declarations.

The union with empty array is unnecessary as the type already includes empty arrays.

Apply this diff:

-    channels = signal<ChannelDTO[] | []>([]);
-    users = signal<UserPublicInfoDTO[] | []>([]);
-    postToForward = signal<Post | undefined>(undefined);
+    channels = signal<ChannelDTO[]>([]);
+    users = signal<UserPublicInfoDTO[]>([]);
+    postToForward = signal<Post | undefined>(undefined);

169-191: Add selection limits for channels and users.

Implement maximum selection limits to prevent performance issues and improve user experience.

Apply this diff:

+    private readonly MAX_SELECTIONS = 10;
+
     selectOption(option: CombinedOption): void {
+        if (this.selectedChannels.length + this.selectedUsers.length >= this.MAX_SELECTIONS) {
+            // Optionally show error message to user
+            return;
+        }
+
         if (option.type === 'channel') {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bff0273 and 960873a.

⛔ Files ignored due to path filters (1)
  • src/main/resources/config/liquibase/master.xml is excluded by !**/*.xml
📒 Files selected for processing (2)
  • src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.component.scss (1 hunks)
  • src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.component.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.component.scss
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.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

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: client-tests-selected
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: Build and Push Docker Image
  • GitHub Check: Analyse
  • GitHub Check: Build .war artifact
🔇 Additional comments (4)
src/main/webapp/app/overview/course-conversations/dialogs/forward-message-dialog/forward-message-dialog.component.ts (4)

33-39: Convert to standalone component.

As suggested in the past review, this component should be converted to a standalone component for better modularity and tree-shaking.

Apply this diff:

 @Component({
     selector: 'jhi-forward-message-dialog',
     templateUrl: './forward-message-dialog.component.html',
     styleUrls: ['./forward-message-dialog.component.scss'],
+    standalone: true,
     imports: [ArtemisTranslatePipe, ProfilePictureComponent, NgClass, PostingContentComponent, MarkdownEditorMonacoComponent, ArtemisSharedModule],
     providers: [MetisService, LinkPreviewService, LinkifyService],
 })

54-55: Use viewChild with signal syntax.

As suggested in the past review, use the signal syntax for viewChild declarations.

Apply this diff:

-    searchInput = viewChild<ElementRef>('searchInput');
-    messageContent = viewChild<ElementRef>('messageContent');
+    searchInput = viewChild.required<ElementRef>('searchInput');
+    messageContent = viewChild.required<ElementRef>('messageContent');

111-113: Add content validation in updateField.

The method should validate the content before updating.

Apply this diff:

 updateField(content: string): void {
+    if (!content || !content.trim()) {
+        return;
+    }
     this.newPost.content = content;
 }

209-216: Add validation in send method.

The send method should validate selections and content before closing the modal.

Apply this diff:

 send(): void {
+    if (!this.hasSelections()) {
+        // Optionally show error message to user
+        return;
+    }
+
+    if (!this.newPost.content?.trim()) {
+        // Optionally show error message to user
+        return;
+    }
+
     const selectedItems = {
         channels: this.selectedChannels,
         users: this.selectedUsers,
         messageContent: this.newPost.content,
     };
     this.activeModal.close(selectedItems);
 }

@asliayk
Copy link
Contributor Author

asliayk commented Jan 17, 2025

The second issue you mentioned has already been noted. However, I used the preexisting endpoint for user selection, which is also used in the "Create Direct Chat" and "Group Chat" options. In those options, users cannot search by name either; they can only search using the login name. While this is an issue that needs to be addressed, it is not directly related to this PR.

Ah I remember having the same problem on the Android app 😅. However I just checked for creating a DM chat, and there searching by username seems to work. Maybe there is already a fix in place?

image

I’m not entirely sure which specific color you are referring to in the first issue. I tried to align it with the existing input sections to make it consistent.

The color I am refering to, is the bright white of the row item backgrounds, that highlights the list item that the mouse hovers over (see screenshot below). I am not sure what other inputs use this color for highlighting as well, but eg also the selection for the DM chat creation uses a much more pleasant color imo (see blue highlighted row in screenshot above).

image

ah I see the color issue now, thank you for noticing this. I think I have solved it now.

However, the user selection does not work for me with usernames on TS3 for direct chat user selection. In my PR, I kept the user selection logic unchanged, as it is in the current implementation. Since the existing logic already has this issue, it also affects this PR. Therefore, I think this issue is unrelated to this PR and should be addressed in a separate PR.

Screen.Recording.2025-01-17.at.17.08.02.mov

Copy link
Contributor

@FelberMartin FelberMartin left a comment

Choose a reason for hiding this comment

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

The highlight color is much better now, thanks for adjusting!

Regarding the search by username issue, I accidentality tested the user search in the DM dialog on TS2, but you are right, on TS3 that searching by username does not work there.

Good to merge from my side :D

Copy link
Contributor

@cremertim cremertim left a comment

Choose a reason for hiding this comment

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

Code seems good to me, just 1 remark in the translations

"addMessage": "Eine Nachricht hinzufügen",
"searchBar": "Nach Name oder Kanal suchen",
"viewConversation": "Unterhaltung anzeigen",
"forwardedFrom": "Forwarded from",
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you intentionally using a english string? Should be "forwardedFrom": "Weitergeleitet von",

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

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 component:Communication database Pull requests that update the database. (Added Automatically!). Require a CRITICAL deployment. feature ready for review server Pull requests that update Java code. (Added Automatically!) tests
Projects
Status: Ready For Review
Status: In Progress
Development

Successfully merging this pull request may close these issues.

Communication: Forward Messages Feature