From fffa8648bb46f6e0547797eeea9d27dce563b8de Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:32:24 +0530 Subject: [PATCH] Space app Kanban block reactions (#5272) --- .../issue-layouts/kanban/block-reactions.tsx | 45 +++++++++ .../issues/issue-layouts/kanban/block.tsx | 22 +++-- .../components/issues/peek-overview/index.ts | 2 - .../issues/peek-overview/issue-reaction.tsx | 2 +- .../core/components/issues/reactions/index.ts | 2 + .../issue-emoji-reactions.tsx | 91 ++++++++++--------- .../issue-vote-reactions.tsx | 13 ++- 7 files changed, 117 insertions(+), 60 deletions(-) create mode 100644 space/core/components/issues/issue-layouts/kanban/block-reactions.tsx create mode 100644 space/core/components/issues/reactions/index.ts rename space/core/components/issues/{peek-overview => reactions}/issue-emoji-reactions.tsx (57%) rename space/core/components/issues/{peek-overview => reactions}/issue-vote-reactions.tsx (90%) diff --git a/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx b/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx new file mode 100644 index 0000000000..241a087e78 --- /dev/null +++ b/space/core/components/issues/issue-layouts/kanban/block-reactions.tsx @@ -0,0 +1,45 @@ +import { observer } from "mobx-react"; +import { useParams } from "next/navigation"; +//plane +import { cn } from "@plane/editor"; +// components +import { IssueEmojiReactions, IssueVotes } from "@/components/issues/reactions"; +// hooks +import { usePublish } from "@/hooks/store"; + +type Props = { + issueId: string; +}; +export const BlockReactions = observer((props: Props) => { + const { issueId } = props; + const { anchor } = useParams(); + const { canVote, canReact } = usePublish(anchor.toString()); + + // if the user cannot vote or react then return empty + if (!canVote && !canReact) return <>; + + return ( +
+
+ {canVote && ( +
+ +
+ )} + {canReact && ( +
+ +
+ )} +
+
+ ); +}); diff --git a/space/core/components/issues/issue-layouts/kanban/block.tsx b/space/core/components/issues/issue-layouts/kanban/block.tsx index b1d0f93aa0..7c246cc339 100644 --- a/space/core/components/issues/issue-layouts/kanban/block.tsx +++ b/space/core/components/issues/issue-layouts/kanban/block.tsx @@ -14,10 +14,11 @@ import { WithDisplayPropertiesHOC } from "@/components/issues/issue-layouts/with import { queryParamGenerator } from "@/helpers/query-param-generator"; // hooks import { useIssueDetails, usePublish } from "@/hooks/store"; - +// import { IIssue } from "@/types/issue"; import { IssueProperties } from "../properties/all-properties"; import { getIssueBlockId } from "../utils"; +import { BlockReactions } from "./block-reactions"; interface IssueBlockProps { issueId: string; @@ -83,17 +84,22 @@ export const KanbanIssueBlock: React.FC = observer((props) => { return (
- - - + + + + +
); }); diff --git a/space/core/components/issues/peek-overview/index.ts b/space/core/components/issues/peek-overview/index.ts index f42253e5e7..e0142b0240 100644 --- a/space/core/components/issues/peek-overview/index.ts +++ b/space/core/components/issues/peek-overview/index.ts @@ -7,5 +7,3 @@ export * from "./issue-properties"; export * from "./layout"; export * from "./side-peek-view"; export * from "./issue-reaction"; -export * from "./issue-vote-reactions"; -export * from "./issue-emoji-reactions"; diff --git a/space/core/components/issues/peek-overview/issue-reaction.tsx b/space/core/components/issues/peek-overview/issue-reaction.tsx index 953852d05a..1345531413 100644 --- a/space/core/components/issues/peek-overview/issue-reaction.tsx +++ b/space/core/components/issues/peek-overview/issue-reaction.tsx @@ -1,5 +1,5 @@ import { observer } from "mobx-react"; -import { IssueEmojiReactions, IssueVotes } from "@/components/issues/peek-overview"; +import { IssueEmojiReactions, IssueVotes } from "@/components/issues/reactions"; // hooks import { usePublish } from "@/hooks/store"; import useIsInIframe from "@/hooks/use-is-in-iframe"; diff --git a/space/core/components/issues/reactions/index.ts b/space/core/components/issues/reactions/index.ts new file mode 100644 index 0000000000..914579fa45 --- /dev/null +++ b/space/core/components/issues/reactions/index.ts @@ -0,0 +1,2 @@ +export * from "./issue-emoji-reactions"; +export * from "./issue-vote-reactions"; diff --git a/space/core/components/issues/peek-overview/issue-emoji-reactions.tsx b/space/core/components/issues/reactions/issue-emoji-reactions.tsx similarity index 57% rename from space/core/components/issues/peek-overview/issue-emoji-reactions.tsx rename to space/core/components/issues/reactions/issue-emoji-reactions.tsx index 7a9851244a..fd78a558e1 100644 --- a/space/core/components/issues/peek-overview/issue-emoji-reactions.tsx +++ b/space/core/components/issues/reactions/issue-emoji-reactions.tsx @@ -13,10 +13,12 @@ import { useIssueDetails, useUser } from "@/hooks/store"; type IssueEmojiReactionsProps = { anchor: string; + issueIdFromProps?: string; + size?: "md" | "sm"; }; export const IssueEmojiReactions: React.FC = observer((props) => { - const { anchor } = props; + const { anchor, issueIdFromProps, size = "md" } = props; // router const router = useRouter(); const pathName = usePathname(); @@ -31,7 +33,7 @@ export const IssueEmojiReactions: React.FC = observer( const issueDetailsStore = useIssueDetails(); const { data: user } = useUser(); - const issueId = issueDetailsStore.peekId; + const issueId = issueIdFromProps ?? issueDetailsStore.peekId; const reactions = issueDetailsStore.details[issueId ?? ""]?.reaction_items ?? []; const groupedReactions = groupReactions(reactions, "reaction"); @@ -55,6 +57,7 @@ export const IssueEmojiReactions: React.FC = observer( // derived values const { queryParam } = queryParamGenerator({ peekId, board, state, priority, labels }); + const reactionDimensions = size === "sm" ? "h-6 px-2 py-1" : "h-full px-2 py-1"; return ( <> @@ -64,54 +67,52 @@ export const IssueEmojiReactions: React.FC = observer( else router.push(`/?next_path=${pathName}?${queryParam}`); }} selected={userReactions?.map((r) => r.reaction)} - size="md" + size={size} /> -
- {Object.keys(groupedReactions || {}).map((reaction) => { - const reactions = groupedReactions?.[reaction] ?? []; - const REACTIONS_LIMIT = 1000; + {Object.keys(groupedReactions || {}).map((reaction) => { + const reactions = groupedReactions?.[reaction] ?? []; + const REACTIONS_LIMIT = 1000; - if (reactions.length > 0) - return ( - - {reactions - ?.map((r) => r?.actor_details?.display_name) - ?.splice(0, REACTIONS_LIMIT) - ?.join(", ")} - {reactions.length > REACTIONS_LIMIT && " and " + (reactions.length - REACTIONS_LIMIT) + " more"} -
- } + if (reactions.length > 0) + return ( + + {reactions + ?.map((r) => r?.actor_details?.display_name) + ?.splice(0, REACTIONS_LIMIT) + ?.join(", ")} + {reactions.length > REACTIONS_LIMIT && " and " + (reactions.length - REACTIONS_LIMIT) + " more"} + + } + > + - - ); - })} - + {groupedReactions?.[reaction].length}{" "} + + + + ); + })} ); }); diff --git a/space/core/components/issues/peek-overview/issue-vote-reactions.tsx b/space/core/components/issues/reactions/issue-vote-reactions.tsx similarity index 90% rename from space/core/components/issues/peek-overview/issue-vote-reactions.tsx rename to space/core/components/issues/reactions/issue-vote-reactions.tsx index ccfe4967a2..7134c05cf9 100644 --- a/space/core/components/issues/peek-overview/issue-vote-reactions.tsx +++ b/space/core/components/issues/reactions/issue-vote-reactions.tsx @@ -13,10 +13,12 @@ import useIsInIframe from "@/hooks/use-is-in-iframe"; type TIssueVotes = { anchor: string; + issueIdFromProps?: string; + size?: "md" | "sm"; }; export const IssueVotes: React.FC = observer((props) => { - const { anchor } = props; + const { anchor, issueIdFromProps, size = "md" } = props; // states const [isSubmitting, setIsSubmitting] = useState(false); // router @@ -35,7 +37,7 @@ export const IssueVotes: React.FC = observer((props) => { const isInIframe = useIsInIframe(); - const issueId = issueDetailsStore.peekId; + const issueId = issueIdFromProps ?? issueDetailsStore.peekId; const votes = issueDetailsStore.details[issueId ?? ""]?.vote_items ?? []; @@ -66,6 +68,7 @@ export const IssueVotes: React.FC = observer((props) => { // derived values const { queryParam } = queryParamGenerator({ peekId, board, state, priority, labels }); + const votingDimensions = size === "sm" ? "px-1 h-6 min-w-9" : "px-2 h-7"; return (
@@ -96,7 +99,8 @@ export const IssueVotes: React.FC = observer((props) => { else router.push(`/?next_path=${pathName}?${queryParam}`); }} className={cn( - "flex items-center justify-center gap-x-1 overflow-hidden rounded border px-2 h-7 focus:outline-none", + "flex items-center justify-center gap-x-1 overflow-hidden rounded border focus:outline-none bg-custom-background-100", + votingDimensions, { "border-custom-primary-200 text-custom-primary-200": isUpVotedByUser, "border-custom-border-300": !isUpVotedByUser, @@ -136,7 +140,8 @@ export const IssueVotes: React.FC = observer((props) => { else router.push(`/?next_path=${pathName}?${queryParam}`); }} className={cn( - "flex items-center justify-center gap-x-1 h-7 overflow-hidden rounded border px-2 focus:outline-none", + "flex items-center justify-center gap-x-1 overflow-hidden rounded border focus:outline-none bg-custom-background-100", + votingDimensions, { "border-red-600 text-red-600": isDownVotedByUser, "border-custom-border-300": !isDownVotedByUser,