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: Group consecutive messages #9456

Merged
merged 46 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b09c320
consecutive message view with new reaction bar added
asliayk Oct 10, 2024
fedc900
renamed file
asliayk Oct 10, 2024
1113a4b
tests updated
asliayk Oct 10, 2024
df6a1fc
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 10, 2024
8a48723
tests updated
asliayk Oct 11, 2024
613e8d8
tests updated & refactor
asliayk Oct 11, 2024
72fefe2
minor fix
asliayk Oct 11, 2024
313dfef
refactored reaction bar style
asliayk Oct 12, 2024
252cedf
refactored reaction bar style
asliayk Oct 12, 2024
8f264b4
updated resolve button
asliayk Oct 12, 2024
a53c7ba
updated reaction bar style
asliayk Oct 12, 2024
f152661
Merge branch 'develop' into feature/communication/consecutive-message…
yassinsws Oct 13, 2024
e3c5384
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 17, 2024
9725c07
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 21, 2024
6794ca1
added dropdown
asliayk Oct 21, 2024
c9e7e6e
Merge remote-tracking branch 'origin/feature/communication/consecutiv…
asliayk Oct 21, 2024
8726cee
reply view added
asliayk Oct 21, 2024
f6d149c
adjusted timeframe to 5 minutes
asliayk Oct 21, 2024
bfec85d
added dropdown to posting directive
asliayk Oct 21, 2024
0cc49d9
updated strings
asliayk Oct 21, 2024
29a25c5
refactor code, fix pin/unpin string
asliayk Oct 22, 2024
2f73014
opened dropdown disables scrolling
asliayk Oct 23, 2024
c9d276a
fix pin styling, updated tests
asliayk Oct 23, 2024
7792212
updated tests
asliayk Oct 23, 2024
21e97e1
fixed styling
asliayk Oct 23, 2024
67ce6f0
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 23, 2024
eec93d9
directive test added
asliayk Oct 24, 2024
9287c3a
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 24, 2024
d355ce0
minor fix
asliayk Oct 24, 2024
64bae5f
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 26, 2024
f81ba93
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 27, 2024
c34b89f
adjusted dropdown/reaction bar position, added tests
asliayk Oct 27, 2024
daa405a
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Oct 29, 2024
47c5b04
conflicts resolved & adjusted dropdown position
asliayk Oct 29, 2024
73da6d8
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Nov 3, 2024
3d6beb7
refactor @if, fix confirm icon bug/dropdown options visibility
asliayk Nov 3, 2024
95850f1
refactor output variables
asliayk Nov 3, 2024
ba071a1
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Nov 3, 2024
5bf7f97
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Nov 3, 2024
12937ee
moved undo event to reaction bar directive
asliayk Nov 3, 2024
fe6537f
fix tests
asliayk Nov 3, 2024
ae47652
fix pin message option visibility on dropdown menu
asliayk Nov 3, 2024
7dba8e8
fix visibility of confirm icon for different user roles
asliayk Nov 4, 2024
830a8ea
Merge branch 'develop' into feature/communication/consecutive-message…
asliayk Nov 4, 2024
5610443
fix codacy issue
asliayk Nov 4, 2024
fcb0525
Merge remote-tracking branch 'origin/feature/communication/consecutiv…
asliayk Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/webapp/app/entities/metis/answer-post.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Posting } from 'app/entities/metis/posting.model';
export class AnswerPost extends Posting {
public resolvesPost?: boolean;
public post?: Post;
public isConsecutive?: boolean = false;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Consider adding a comment for clarity.

The addition of the isConsecutive property aligns well with the PR objectives for enhancing message grouping. The implementation follows the coding guidelines, using camelCase for property naming.

Consider adding a brief comment explaining the purpose of the isConsecutive property for better code documentation. For example:

// Indicates whether this post is part of a consecutive message group
public isConsecutive?: boolean = false;


constructor() {
super();
Expand Down
1 change: 1 addition & 0 deletions src/main/webapp/app/entities/metis/post.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class Post extends Posting {
public conversation?: Conversation;
public displayPriority?: DisplayPriority;
public resolved?: boolean;
public isConsecutive?: boolean = false;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Consider making the property non-optional for type safety.

The addition of the isConsecutive property aligns well with the PR objectives for enhancing message grouping. The naming and default value are appropriate.

For improved type safety, consider making the property non-optional:

public isConsecutive: boolean = false;

This change would eliminate the need for null checks when using this property elsewhere in the codebase.


constructor() {
super();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,24 @@
>
<!-- list of all top level posts -->
<!-- answers are opened in the thread sidebar -->
@for (post of posts; track postsTrackByFn($index, post)) {
<div>
<jhi-posting-thread
#postingThread
[lastReadDate]="_activeConversation?.lastReadDate"
[hasChannelModerationRights]="!!getAsChannel(_activeConversation)?.hasChannelModerationRights"
[id]="'item-' + post.id"
[post]="post"
[showAnswers]="false"
[readOnlyMode]="!!getAsChannel(_activeConversation)?.isArchived"
[isCommunicationPage]="true"
(openThread)="setPostForThread($event)"
/>
@for (group of groupedPosts; track postsTrackByFn($index, group)) {
<div class="message-group">
@for (post of group.posts; track postsTrackByFn($index, post)) {
<div class="post-item">
<jhi-posting-thread
#postingThread
[lastReadDate]="_activeConversation?.lastReadDate"
[hasChannelModerationRights]="!!getAsChannel(_activeConversation)?.hasChannelModerationRights"
[id]="'item-' + post.id"
[post]="post"
[showAnswers]="false"
[readOnlyMode]="!!getAsChannel(_activeConversation)?.isArchived"
[isCommunicationPage]="true"
(openThread)="setPostForThread($event)"
[isConsecutive]="post.isConsecutive || false"
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider using the nullish coalescing operator for default values

Instead of using the logical OR || to assign a default value to [isConsecutive], consider using the nullish coalescing operator ?? for clarity and to handle falsy values correctly:

-[isConsecutive]="post.isConsecutive || false"
+[isConsecutive]="post.isConsecutive ?? false"

This ensures that if post.isConsecutive is explicitly false, it remains false, and only null or undefined values are replaced with false.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[isConsecutive]="post.isConsecutive || false"
[isConsecutive]="post.isConsecutive ?? false"

></jhi-posting-thread>
</div>
}
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,25 @@
padding-bottom: 100px;
}
}

.message-group {
display: flex;
flex-direction: column;
margin-bottom: 10px;
}

.grouped-posts {
margin-left: 30px;
padding-left: 10px;
}
Comment on lines +84 to +87
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM: Good indentation for grouped posts

The .grouped-posts class creates an effective indentation for grouped messages, which helps distinguish between the main message and subsequent grouped messages. This aligns well with the PR objective of grouping messages from the same user sent within a one-hour timeframe.

Consider using CSS variables for the margin and padding values to maintain consistency and ease future adjustments. For example:

:root {
  --grouped-posts-left-margin: 30px;
  --grouped-posts-left-padding: 10px;
}

.grouped-posts {
  margin-left: var(--grouped-posts-left-margin);
  padding-left: var(--grouped-posts-left-padding);
}


.grouped-posts,
.grouped-post {
margin-top: 0;
margin-bottom: 0;
padding: 0;
}

jhi-posting-thread {
margin-bottom: 5px;
}
Comment on lines +96 to +98
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM: Appropriate spacing for posting threads

The addition of a 5px bottom margin to the jhi-posting-thread element provides a subtle separation between posting threads, which enhances the overall visual hierarchy and readability of the conversation.

Consider using a class selector instead of an element selector to be more consistent with BEM naming conventions and to improve the modularity of your styles. For example:

.posting-thread {
  margin-bottom: 5px;
}

Then, apply this class to your jhi-posting-thread element in the HTML template.

Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ import { MetisConversationService } from 'app/shared/metis/metis-conversation.se
import { OneToOneChat, isOneToOneChatDTO } from 'app/entities/metis/conversation/one-to-one-chat.model';
import { canCreateNewMessageInConversation } from 'app/shared/metis/conversations/conversation-permissions.utils';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import dayjs from 'dayjs/esm';
import { User } from 'app/core/user/user.model';

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({ standalone: true, name: 'dayjsToDate' })
export class DayjsToDatePipe implements PipeTransform {
transform(value: dayjs.Dayjs | undefined): Date | undefined {
return value ? value.toDate() : undefined;
}
}

interface PostGroup {
author: User | undefined;
posts: Post[];
}

@Component({
selector: 'jhi-conversation-messages',
Expand Down Expand Up @@ -69,6 +85,7 @@ export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnD

newPost?: Post;
posts: Post[] = [];
groupedPosts: PostGroup[] = [];
totalNumberOfPosts = 0;
page = 1;
public isFetchingPosts = true;
Expand Down Expand Up @@ -159,11 +176,70 @@ export class ConversationMessagesComponent implements OnInit, AfterViewInit, OnD
};
}

toDate(dayjsDate: dayjs.Dayjs | undefined): Date | undefined {
return dayjsDate ? dayjsDate.toDate() : undefined;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Eliminate duplicate code by removing the toDate method

The toDate method duplicates the functionality of the DayjsToDatePipe. To adhere to the DRY (Don't Repeat Yourself) principle and promote code reuse, consider removing the toDate method and using the DayjsToDatePipe wherever date conversion is needed.


private groupPosts(): void {
if (!this.posts || this.posts.length === 0) {
this.groupedPosts = [];
return;
}

const sortedPosts = this.posts.sort((a, b) => {
const aDate = (a as any).creationDateAsDate;
const bDate = (b as any).creationDateAsDate;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace as any casts with proper typings

Using as any to access creationDateAsDate circumvents TypeScript's type checking. Define an extended Post interface that includes creationDateAsDate to maintain type safety and improve code clarity.

Also applies to: 205-206

return (aDate?.getTime() || 0) - (bDate?.getTime() || 0);
});

const groups: PostGroup[] = [];
let currentGroup: PostGroup = {
author: sortedPosts[0].author,
posts: [{ ...sortedPosts[0], isConsecutive: false }],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid adding isConsecutive property directly to Post objects

Adding isConsecutive directly to Post instances may cause unintended side effects if Post objects are used elsewhere. Consider defining an interface or class that extends Post to include isConsecutive, or use a separate data structure to store this information.

Also applies to: 214-214

};

for (let i = 1; i < sortedPosts.length; i++) {
const currentPost = sortedPosts[i];
const lastPostInGroup = currentGroup.posts[currentGroup.posts.length - 1];

const currentDate = (currentPost as any).creationDateAsDate;
const lastDate = (lastPostInGroup as any).creationDateAsDate;

let timeDiff = Number.MAX_SAFE_INTEGER;
if (currentDate && lastDate) {
timeDiff = Math.abs(currentDate.getTime() - lastDate.getTime()) / 60000;
}

if (currentPost.author?.id === currentGroup.author?.id && timeDiff <= 60) {
currentGroup.posts.push({ ...currentPost, isConsecutive: true }); // consecutive post
} else {
groups.push(currentGroup);
currentGroup = {
author: currentPost.author,
posts: [{ ...currentPost, isConsecutive: false }],
};
}
}

groups.push(currentGroup);
this.groupedPosts = groups;
this.cdr.detectChanges();
}

setPosts(posts: Post[]): void {
if (this.content) {
this.previousScrollDistanceFromTop = this.content.nativeElement.scrollHeight - this.content.nativeElement.scrollTop;
}
this.posts = posts.slice().reverse();

this.posts = posts
.slice()
.reverse()
.map((post) => {
(post as any).creationDateAsDate = post.creationDate ? dayjs(post.creationDate).toDate() : undefined;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid mutating Post objects by adding new properties

Adding creationDateAsDate directly to Post instances via type casting to any can introduce type safety issues and complicate maintenance. Consider creating a new interface or class that extends Post and includes the additional property, or use a mapping structure to avoid mutating the original objects.

return post;
});

this.groupPosts();
}

fetchNextPage() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
<div [id]="'item-' + posting.id" class="row" [ngClass]="isCommunicationPage ? 'module-bg mt-2 rounded-2' : 'answer-post m-1'">
<jhi-answer-post-header
[posting]="posting"
[isReadOnlyMode]="isReadOnlyMode"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
[isCommunicationPage]="isCommunicationPage"
[lastReadDate]="lastReadDate"
[hasChannelModerationRights]="hasChannelModerationRights"
/>
@if (!isConsecutive) {
<jhi-answer-post-header
[posting]="posting"
[isReadOnlyMode]="isReadOnlyMode"
[isCommunicationPage]="isCommunicationPage"
[lastReadDate]="lastReadDate"
[hasChannelModerationRights]="hasChannelModerationRights"
/>
}
@if (!createAnswerPostModal.isInputOpen) {
<div class="answer-post-content-margin">
<jhi-posting-content
[content]="posting.content"
[isEdited]="!!posting.updatedDate"
[author]="posting.author"
[posting]="posting"
[isReply]="true"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
<div class="answer-post-content-margin message-container">
<div class="message-content">
<jhi-posting-content
[content]="posting.content"
[isEdited]="!!posting.updatedDate"
[author]="posting.author"
[posting]="posting"
[isReply]="true"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
<div class="answer-post-content-margin hover-actions">
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
/>
</div>
</div>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM: New structure aligns with PR objectives

The new structure with the hover-actions div and the placement of jhi-answer-post-reactions-bar within it aligns well with the PR objective of displaying all message actions side by side on hover. The use of @if is correct and follows our coding guidelines.

Consider adding an aria-label to the hover-actions div to improve accessibility. For example:

- <div class="answer-post-content-margin hover-actions">
+ <div class="answer-post-content-margin hover-actions" aria-label="Message actions">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@if (!createAnswerPostModal.isInputOpen) {
<div class="answer-post-content-margin">
<jhi-posting-content
[content]="posting.content"
[isEdited]="!!posting.updatedDate"
[author]="posting.author"
[posting]="posting"
[isReply]="true"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
<div class="answer-post-content-margin message-container">
<div class="message-content">
<jhi-posting-content
[content]="posting.content"
[isEdited]="!!posting.updatedDate"
[author]="posting.author"
[posting]="posting"
[isReply]="true"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
<div class="answer-post-content-margin hover-actions">
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
/>
</div>
</div>
@if (!createAnswerPostModal.isInputOpen) {
<div class="answer-post-content-margin message-container">
<div class="message-content">
<jhi-posting-content
[content]="posting.content"
[isEdited]="!!posting.updatedDate"
[author]="posting.author"
[posting]="posting"
[isReply]="true"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
<div class="answer-post-content-margin hover-actions" aria-label="Message actions">
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
/>
</div>
</div>

</div>
}
<div class="answer-post-content-margin">
<ng-container #createEditAnswerPostContainer />
</div>
<div class="answer-post-content-margin">
<jhi-answer-post-footer
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openPostingCreateEditModal.emit()"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
[isEmojiCount]="true"
/>
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM: Standalone reactions bar for emoji counts

The addition of a standalone jhi-answer-post-reactions-bar with [isEmojiCount]="true" aligns with the PR objective of adding an emoji add button next to existing emoji reactions. This implementation allows for a clear separation between the hover actions and the persistent emoji count display.

For consistency, consider moving the [isEmojiCount]="true" property to be with the other input properties:

<jhi-answer-post-reactions-bar
    [isReadOnlyMode]="isReadOnlyMode"
    [posting]="posting"
    [isLastAnswer]="isLastAnswer"
    [isThreadSidebar]="isThreadSidebar"
+   [isEmojiCount]="true"
    (openPostingCreateEditModal)="createAnswerPostModal.open()"
    (reactionsUpdated)="onReactionsUpdated($event)"
-   [isEmojiCount]="true"
/>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openPostingCreateEditModal.emit()"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
[isEmojiCount]="true"
/>
<jhi-answer-post-reactions-bar
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
[isEmojiCount]="true"
(openPostingCreateEditModal)="createAnswerPostModal.open()"
(reactionsUpdated)="onReactionsUpdated($event)"
/>

</div>
</div>
<jhi-answer-post-create-edit-modal #createAnswerPostModal [posting]="posting" [createEditAnswerPostContainerRef]="containerRef" />
<jhi-answer-post-create-edit-modal #createAnswerPostModal [posting]="posting" (postingUpdated)="onPostingUpdated($event)" [createEditAnswerPostContainerRef]="containerRef" />
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,42 @@
.answer-post-content-margin {
padding-left: 3.2rem;
}

.message-container {
position: relative;
border-radius: 5px;
transition: background-color 0.3s ease;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Consider adding box-shadow for depth.

The .message-container class is well-structured and aligns with the PR objectives. The relative positioning and border-radius enhance the visual appeal, while the transition prepares for smooth hover effects.

To further improve the visual hierarchy, consider adding a subtle box-shadow:

 .message-container {
     position: relative;
     border-radius: 5px;
     transition: background-color 0.3s ease;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.message-container {
position: relative;
border-radius: 5px;
transition: background-color 0.3s ease;
}
.message-container {
position: relative;
border-radius: 5px;
transition: background-color 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}


.message-content {
padding-left: 0.3rem;
}

.message-content:hover {
background: var(--metis-selection-option-hover-background);
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Consider adding keyboard focus styles for accessibility.

The hover effect for .message-content is well-implemented and aligns with the PR objectives. To improve accessibility, consider adding styles for keyboard focus:

-.message-content:hover {
+.message-content:hover,
+.message-content:focus-within {
     background: var(--metis-selection-option-hover-background);
 }

This ensures that keyboard users can also access the hover state.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.message-content:hover {
background: var(--metis-selection-option-hover-background);
}
.message-content:hover,
.message-content:focus-within {
background: var(--metis-selection-option-hover-background);
}


.hover-actions {
position: absolute;
top: -1.8rem;
right: 1%;
display: flex;
gap: 10px;
visibility: hidden;
transition:
opacity 0.2s ease-in-out,
visibility 0.2s ease-in-out;
background: var(--metis-selection-option-background);
padding: 5px;
border-radius: 5px;
border: 0.01rem solid var(--metis-gray);
}

.message-container:hover .hover-actions {
opacity: 1;
visibility: visible;
}
Comment on lines +61 to +64
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

LGTM! Consider adding keyboard focus styles for accessibility.

The implementation for showing hover actions when the message container is hovered over is well done. To improve accessibility, consider adding styles for keyboard focus:

-.message-container:hover .hover-actions {
+.message-container:hover .hover-actions,
+.message-container:focus-within .hover-actions {
     opacity: 1;
     visibility: visible;
 }

This ensures that keyboard users can also access the hover actions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.message-container:hover .hover-actions {
opacity: 1;
visibility: visible;
}
.message-container:hover .hover-actions,
.message-container:focus-within .hover-actions {
opacity: 1;
visibility: visible;
}


.clickable {
cursor: pointer;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewCh
import { AnswerPost } from 'app/entities/metis/answer-post.model';
import { PostingDirective } from 'app/shared/metis/posting.directive';
import dayjs from 'dayjs/esm';
import { Posting } from 'app/entities/metis/posting.model';
import { Reaction } from 'app/entities/metis/reaction.model';

@Component({
selector: 'jhi-answer-post',
Expand All @@ -20,4 +22,13 @@ export class AnswerPostComponent extends PostingDirective<AnswerPost> {
isReadOnlyMode = false;
// ng-container to render answerPostCreateEditModalComponent
@ViewChild('createEditAnswerPostContainer', { read: ViewContainerRef }) containerRef: ViewContainerRef;
@Input() isConsecutive: boolean = false;
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove unnecessary type annotation

The type of isConsecutive is inferred from its initialization. You can omit the explicit type annotation : boolean.

Apply this diff to remove the redundant type annotation:

- @Input() isConsecutive: boolean = false;
+ @Input() isConsecutive = false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Input() isConsecutive: boolean = false;
@Input() isConsecutive = false;
🧰 Tools
🪛 Biome

[error] 25-25: This type annotation is trivially inferred from its initialization.

Safe fix: Remove the type annotation.

(lint/style/noInferrableTypes)


onPostingUpdated(updatedPosting: Posting) {
this.posting = updatedPosting;
}
Comment on lines +70 to +72
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add unit tests for onPostingUpdated method

To ensure the correctness and maintainability of the onPostingUpdated method, please add meaningful unit tests.

I can assist in creating unit tests or open a GitHub issue to track this task.


onReactionsUpdated(updatedReactions: Reaction[]) {
this.posting = { ...this.posting, reactions: updatedReactions };
}
Comment on lines +74 to +76
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add unit tests for onReactionsUpdated method

To ensure the correctness and maintainability of the onReactionsUpdated method, please add meaningful unit tests.

I can assist in creating unit tests or open a GitHub issue to track this task.

}
3 changes: 0 additions & 3 deletions src/main/webapp/app/shared/metis/metis.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { AnswerPostHeaderComponent } from 'app/shared/metis/posting-header/answe
import { PostHeaderComponent } from 'app/shared/metis/posting-header/post-header/post-header.component';
import { AnswerPostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/answer-post-create-edit-modal/answer-post-create-edit-modal.component';
import { PostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-create-edit-modal.component';
import { AnswerPostFooterComponent } from 'app/shared/metis/posting-footer/answer-post-footer/answer-post-footer.component';
import { PostFooterComponent } from 'app/shared/metis/posting-footer/post-footer/post-footer.component';
import { PostTagSelectorComponent } from 'app/shared/metis/posting-create-edit-modal/post-create-edit-modal/post-tag-selector/post-tag-selector.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
Expand Down Expand Up @@ -72,7 +71,6 @@ import { MetisConversationService } from 'app/shared/metis/metis-conversation.se
PostTagSelectorComponent,
PostFooterComponent,
AnswerPostCreateEditModalComponent,
AnswerPostFooterComponent,
PostingButtonComponent,
PostingMarkdownEditorComponent,
PostComponent,
Expand All @@ -99,7 +97,6 @@ import { MetisConversationService } from 'app/shared/metis/metis-conversation.se
PostTagSelectorComponent,
AnswerPostCreateEditModalComponent,
PostFooterComponent,
AnswerPostFooterComponent,
PostingButtonComponent,
PostingMarkdownEditorComponent,
PostComponent,
Expand Down
Loading
Loading