diff --git a/web/components/issues/issue-detail/reactions/issue-comment.tsx b/web/components/issues/issue-detail/reactions/issue-comment.tsx index 97c63a017..e26befe1b 100644 --- a/web/components/issues/issue-detail/reactions/issue-comment.tsx +++ b/web/components/issues/issue-detail/reactions/issue-comment.tsx @@ -1,10 +1,11 @@ import { FC, useMemo } from "react"; import { observer } from "mobx-react-lite"; // components -import { TOAST_TYPE, setToast } from "@plane/ui"; +import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { renderEmoji } from "helpers/emoji.helper"; -import { useIssueDetail } from "hooks/store"; -// ui +import { useIssueDetail, useMember } from "hooks/store"; +// helper +import { formatTextList } from "helpers/issue.helper"; // types import { IUser } from "@plane/types"; import { ReactionSelector } from "./reaction-selector"; @@ -21,10 +22,11 @@ export const IssueCommentReaction: FC = observer((props) // hooks const { - commentReaction: { getCommentReactionsByCommentId, commentReactionsByUser }, + commentReaction: { getCommentReactionsByCommentId, commentReactionsByUser, getCommentReactionById }, createCommentReaction, removeCommentReaction, } = useIssueDetail(); + const { getUserDetails } = useMember(); const reactionIds = getCommentReactionsByCommentId(commentId); const userReactions = commentReactionsByUser(commentId, currentUser.id).map((r) => r.reaction); @@ -73,6 +75,17 @@ export const IssueCommentReaction: FC = observer((props) [workspaceSlug, projectId, commentId, currentUser, createCommentReaction, removeCommentReaction, userReactions] ); + const getReactionUsers = (reaction: string): string => { + const reactionUsers = (reactionIds?.[reaction] || []) + .map((reactionId) => { + const reactionDetails = getCommentReactionById(reactionId); + return reactionDetails ? getUserDetails(reactionDetails.actor)?.display_name : null; + }) + .filter((displayName): displayName is string => !!displayName); + const formattedUsers = formatTextList(reactionUsers); + return formattedUsers; + }; + return (
= observer((props) (reaction) => reactionIds[reaction]?.length > 0 && ( <> - + + + ) )} diff --git a/web/components/issues/issue-detail/reactions/issue.tsx b/web/components/issues/issue-detail/reactions/issue.tsx index 6f5610634..c21f92139 100644 --- a/web/components/issues/issue-detail/reactions/issue.tsx +++ b/web/components/issues/issue-detail/reactions/issue.tsx @@ -1,10 +1,12 @@ import { FC, useMemo } from "react"; import { observer } from "mobx-react-lite"; -// components -import { TOAST_TYPE, setToast } from "@plane/ui"; -import { renderEmoji } from "helpers/emoji.helper"; -import { useIssueDetail } from "hooks/store"; +// hooks +import { useIssueDetail, useMember } from "hooks/store"; // ui +import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; +// helpers +import { renderEmoji } from "helpers/emoji.helper"; +import { formatTextList } from "helpers/issue.helper"; // types import { IUser } from "@plane/types"; import { ReactionSelector } from "./reaction-selector"; @@ -20,10 +22,11 @@ export const IssueReaction: FC = observer((props) => { const { workspaceSlug, projectId, issueId, currentUser } = props; // hooks const { - reaction: { getReactionsByIssueId, reactionsByUser }, + reaction: { getReactionsByIssueId, reactionsByUser, getReactionById }, createReaction, removeReaction, } = useIssueDetail(); + const { getUserDetails } = useMember(); const reactionIds = getReactionsByIssueId(issueId); const userReactions = reactionsByUser(issueId, currentUser.id).map((r) => r.reaction); @@ -72,6 +75,18 @@ export const IssueReaction: FC = observer((props) => { [workspaceSlug, projectId, issueId, currentUser, createReaction, removeReaction, userReactions] ); + const getReactionUsers = (reaction: string): string => { + const reactionUsers = (reactionIds?.[reaction] || []) + .map((reactionId) => { + const reactionDetails = getReactionById(reactionId); + return reactionDetails ? getUserDetails(reactionDetails.actor_id)?.display_name : null; + }) + .filter((displayName): displayName is string => !!displayName); + + const formattedUsers = formatTextList(reactionUsers); + return formattedUsers; + }; + return (
@@ -81,19 +96,21 @@ export const IssueReaction: FC = observer((props) => { (reaction) => reactionIds[reaction]?.length > 0 && ( <> - + + + ) )} diff --git a/web/helpers/issue.helper.ts b/web/helpers/issue.helper.ts index 3e6689151..cba9ced8d 100644 --- a/web/helpers/issue.helper.ts +++ b/web/helpers/issue.helper.ts @@ -184,3 +184,21 @@ export function getChangedIssuefields(formData: Partial, dirtyFields: { return changedFields; } + +export const formatTextList = (TextArray: string[]): string => { + const count = TextArray.length; + switch (count) { + case 0: + return ""; + case 1: + return TextArray[0]; + case 2: + return `${TextArray[0]} and ${TextArray[1]}`; + case 3: + return `${TextArray.slice(0, 2).join(", ")}, and ${TextArray[2]}`; + case 4: + return `${TextArray.slice(0, 3).join(", ")}, and ${TextArray[3]}`; + default: + return `${TextArray.slice(0, 3).join(", ")}, and +${count - 3} more`; + } +};