[842] chore: disable comments and reactions in archived issues. (#4101)

This commit is contained in:
Prateek Shourya 2024-04-03 18:02:07 +05:30 committed by GitHub
parent fed5916907
commit 68ebcfd04e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 77 additions and 36 deletions

View File

@ -13,10 +13,11 @@ type TIssueActivityCommentRoot = {
issueId: string; issueId: string;
activityOperations: TActivityOperations; activityOperations: TActivityOperations;
showAccessSpecifier?: boolean; showAccessSpecifier?: boolean;
disabled?: boolean;
}; };
export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer((props) => { export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer((props) => {
const { workspaceSlug, issueId, activityOperations, showAccessSpecifier } = props; const { workspaceSlug, issueId, activityOperations, showAccessSpecifier, disabled } = props;
// hooks // hooks
const { const {
activity: { getActivityCommentByIssueId }, activity: { getActivityCommentByIssueId },
@ -37,6 +38,7 @@ export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer(
activityOperations={activityOperations} activityOperations={activityOperations}
ends={index === 0 ? "top" : index === activityComments.length - 1 ? "bottom" : undefined} ends={index === 0 ? "top" : index === activityComments.length - 1 ? "bottom" : undefined}
showAccessSpecifier={showAccessSpecifier} showAccessSpecifier={showAccessSpecifier}
disabled={disabled}
/> />
) : activityComment.activity_type === "ACTIVITY" ? ( ) : activityComment.activity_type === "ACTIVITY" ? (
<IssueActivityList <IssueActivityList

View File

@ -25,10 +25,11 @@ type TIssueCommentCard = {
activityOperations: TActivityOperations; activityOperations: TActivityOperations;
ends: "top" | "bottom" | undefined; ends: "top" | "bottom" | undefined;
showAccessSpecifier?: boolean; showAccessSpecifier?: boolean;
disabled?: boolean;
}; };
export const IssueCommentCard: FC<TIssueCommentCard> = (props) => { export const IssueCommentCard: FC<TIssueCommentCard> = (props) => {
const { workspaceSlug, commentId, activityOperations, ends, showAccessSpecifier = false } = props; const { workspaceSlug, commentId, activityOperations, ends, showAccessSpecifier = false, disabled = false } = props;
// hooks // hooks
const { const {
comment: { getCommentById }, comment: { getCommentById },
@ -81,7 +82,7 @@ export const IssueCommentCard: FC<TIssueCommentCard> = (props) => {
commentId={commentId} commentId={commentId}
quickActions={ quickActions={
<> <>
{currentUser?.id === comment.actor && ( {!disabled && currentUser?.id === comment.actor && (
<CustomMenu ellipsis> <CustomMenu ellipsis>
<CustomMenu.MenuItem onClick={() => setIsEditing(true)} className="flex items-center gap-1"> <CustomMenu.MenuItem onClick={() => setIsEditing(true)} className="flex items-center gap-1">
<Pencil className="h-3 w-3" /> <Pencil className="h-3 w-3" />
@ -184,6 +185,7 @@ export const IssueCommentCard: FC<TIssueCommentCard> = (props) => {
projectId={comment?.project_detail?.id} projectId={comment?.project_detail?.id}
commentId={comment.id} commentId={comment.id}
currentUser={currentUser} currentUser={currentUser}
disabled={disabled}
/> />
</div> </div>
</> </>

View File

@ -12,10 +12,11 @@ type TIssueCommentRoot = {
issueId: string; issueId: string;
activityOperations: TActivityOperations; activityOperations: TActivityOperations;
showAccessSpecifier?: boolean; showAccessSpecifier?: boolean;
disabled?: boolean;
}; };
export const IssueCommentRoot: FC<TIssueCommentRoot> = observer((props) => { export const IssueCommentRoot: FC<TIssueCommentRoot> = observer((props) => {
const { workspaceSlug, issueId, activityOperations, showAccessSpecifier } = props; const { workspaceSlug, issueId, activityOperations, showAccessSpecifier, disabled } = props;
// hooks // hooks
const { const {
comment: { getCommentsByIssueId }, comment: { getCommentsByIssueId },
@ -34,6 +35,7 @@ export const IssueCommentRoot: FC<TIssueCommentRoot> = observer((props) => {
ends={index === 0 ? "top" : index === commentIds.length - 1 ? "bottom" : undefined} ends={index === 0 ? "top" : index === commentIds.length - 1 ? "bottom" : undefined}
activityOperations={activityOperations} activityOperations={activityOperations}
showAccessSpecifier={showAccessSpecifier} showAccessSpecifier={showAccessSpecifier}
disabled={disabled}
/> />
))} ))}
</div> </div>

View File

@ -14,6 +14,7 @@ type TIssueActivity = {
workspaceSlug: string; workspaceSlug: string;
projectId: string; projectId: string;
issueId: string; issueId: string;
disabled?: boolean;
}; };
type TActivityTabs = "all" | "activity" | "comments"; type TActivityTabs = "all" | "activity" | "comments";
@ -43,7 +44,7 @@ export type TActivityOperations = {
}; };
export const IssueActivity: FC<TIssueActivity> = observer((props) => { export const IssueActivity: FC<TIssueActivity> = observer((props) => {
const { workspaceSlug, projectId, issueId } = props; const { workspaceSlug, projectId, issueId, disabled = false } = props;
// hooks // hooks
const { createComment, updateComment, removeComment } = useIssueDetail(); const { createComment, updateComment, removeComment } = useIssueDetail();
const { getProjectById } = useProject(); const { getProjectById } = useProject();
@ -145,12 +146,15 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
issueId={issueId} issueId={issueId}
activityOperations={activityOperations} activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed} showAccessSpecifier={project.is_deployed}
disabled={disabled}
/> />
<IssueCommentCreate {!disabled && (
workspaceSlug={workspaceSlug} <IssueCommentCreate
activityOperations={activityOperations} workspaceSlug={workspaceSlug}
showAccessSpecifier={project.is_deployed} activityOperations={activityOperations}
/> showAccessSpecifier={project.is_deployed}
/>
)}
</div> </div>
) : activityTab === "activity" ? ( ) : activityTab === "activity" ? (
<IssueActivityRoot issueId={issueId} /> <IssueActivityRoot issueId={issueId} />
@ -161,12 +165,15 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
issueId={issueId} issueId={issueId}
activityOperations={activityOperations} activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed} showAccessSpecifier={project.is_deployed}
disabled={disabled}
/> />
<IssueCommentCreate {!disabled && (
workspaceSlug={workspaceSlug} <IssueCommentCreate
activityOperations={activityOperations} workspaceSlug={workspaceSlug}
showAccessSpecifier={project.is_deployed} activityOperations={activityOperations}
/> showAccessSpecifier={project.is_deployed}
/>
)}
</div> </div>
)} )}
</div> </div>

View File

@ -132,7 +132,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
disabled={!is_editable} disabled={!is_editable}
/> />
<IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} /> <IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} disabled={!is_editable} />
</> </>
); );
}); });

View File

@ -3,10 +3,12 @@ import { observer } from "mobx-react-lite";
import { IUser } from "@plane/types"; import { IUser } from "@plane/types";
// components // components
import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
// helper
import { cn } from "@/helpers/common.helper";
import { renderEmoji } from "@/helpers/emoji.helper"; import { renderEmoji } from "@/helpers/emoji.helper";
import { formatTextList } from "@/helpers/issue.helper"; import { formatTextList } from "@/helpers/issue.helper";
// hooks
import { useIssueDetail, useMember } from "@/hooks/store"; import { useIssueDetail, useMember } from "@/hooks/store";
// helper
// types // types
import { ReactionSelector } from "./reaction-selector"; import { ReactionSelector } from "./reaction-selector";
@ -15,10 +17,11 @@ export type TIssueCommentReaction = {
projectId: string; projectId: string;
commentId: string; commentId: string;
currentUser: IUser; currentUser: IUser;
disabled?: boolean;
}; };
export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props) => { export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props) => {
const { workspaceSlug, projectId, commentId, currentUser } = props; const { workspaceSlug, projectId, commentId, currentUser, disabled = false } = props;
// hooks // hooks
const { const {
@ -88,12 +91,14 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
return ( return (
<div className="mt-4 relative flex items-center gap-1.5"> <div className="mt-4 relative flex items-center gap-1.5">
<ReactionSelector {!disabled && (
size="md" <ReactionSelector
position="top" size="md"
value={userReactions} position="top"
onSelect={issueCommentReactionOperations.react} value={userReactions}
/> onSelect={issueCommentReactionOperations.react}
/>
)}
{reactionIds && {reactionIds &&
Object.keys(reactionIds || {}).map( Object.keys(reactionIds || {}).map(
@ -103,11 +108,15 @@ export const IssueCommentReaction: FC<TIssueCommentReaction> = observer((props)
<Tooltip tooltipContent={getReactionUsers(reaction)}> <Tooltip tooltipContent={getReactionUsers(reaction)}>
<button <button
type="button" type="button"
onClick={() => issueCommentReactionOperations.react(reaction)} onClick={() => !disabled && issueCommentReactionOperations.react(reaction)}
key={reaction} key={reaction}
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${ className={cn(
userReactions.includes(reaction) ? "bg-custom-primary-100/10" : "bg-custom-background-80" "flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100",
}`} userReactions.includes(reaction) ? "bg-custom-primary-100/10" : "bg-custom-background-80",
{
"cursor-not-allowed": disabled,
}
)}
> >
<span>{renderEmoji(reaction)}</span> <span>{renderEmoji(reaction)}</span>
<span className={userReactions.includes(reaction) ? "text-custom-primary-100" : ""}> <span className={userReactions.includes(reaction) ? "text-custom-primary-100" : ""}>

View File

@ -5,6 +5,7 @@ import { IUser } from "@plane/types";
// ui // ui
import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui"; import { TOAST_TYPE, Tooltip, setToast } from "@plane/ui";
// helpers // helpers
import { cn } from "@/helpers/common.helper";
import { renderEmoji } from "@/helpers/emoji.helper"; import { renderEmoji } from "@/helpers/emoji.helper";
import { formatTextList } from "@/helpers/issue.helper"; import { formatTextList } from "@/helpers/issue.helper";
import { useIssueDetail, useMember } from "@/hooks/store"; import { useIssueDetail, useMember } from "@/hooks/store";
@ -16,10 +17,11 @@ export type TIssueReaction = {
projectId: string; projectId: string;
issueId: string; issueId: string;
currentUser: IUser; currentUser: IUser;
disabled?: boolean;
}; };
export const IssueReaction: FC<TIssueReaction> = observer((props) => { export const IssueReaction: FC<TIssueReaction> = observer((props) => {
const { workspaceSlug, projectId, issueId, currentUser } = props; const { workspaceSlug, projectId, issueId, currentUser, disabled = false } = props;
// hooks // hooks
const { const {
reaction: { getReactionsByIssueId, reactionsByUser, getReactionById }, reaction: { getReactionsByIssueId, reactionsByUser, getReactionById },
@ -89,7 +91,9 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
return ( return (
<div className="mt-4 relative flex items-center gap-1.5"> <div className="mt-4 relative flex items-center gap-1.5">
<ReactionSelector size="md" position="top" value={userReactions} onSelect={issueReactionOperations.react} /> {!disabled && (
<ReactionSelector size="md" position="top" value={userReactions} onSelect={issueReactionOperations.react} />
)}
{reactionIds && {reactionIds &&
Object.keys(reactionIds || {}).map( Object.keys(reactionIds || {}).map(
@ -99,11 +103,15 @@ export const IssueReaction: FC<TIssueReaction> = observer((props) => {
<Tooltip tooltipContent={getReactionUsers(reaction)}> <Tooltip tooltipContent={getReactionUsers(reaction)}>
<button <button
type="button" type="button"
onClick={() => issueReactionOperations.react(reaction)} onClick={() => !disabled && issueReactionOperations.react(reaction)}
key={reaction} key={reaction}
className={`flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100 ${ className={cn(
userReactions.includes(reaction) ? "bg-custom-primary-100/10" : "bg-custom-background-80" "flex h-full items-center gap-1 rounded-md px-2 py-1 text-sm text-custom-text-100",
}`} userReactions.includes(reaction) ? "bg-custom-primary-100/10" : "bg-custom-background-80",
{
"cursor-not-allowed": disabled,
}
)}
> >
<span>{renderEmoji(reaction)}</span> <span>{renderEmoji(reaction)}</span>
<span className={userReactions.includes(reaction) ? "text-custom-primary-100" : ""}> <span className={userReactions.includes(reaction) ? "text-custom-primary-100" : ""}>

View File

@ -87,6 +87,7 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = observer(
projectId={issue.project_id} projectId={issue.project_id}
issueId={issueId} issueId={issueId}
currentUser={currentUser} currentUser={currentUser}
disabled={disabled}
/> />
)} )}
</div> </div>

View File

@ -177,7 +177,12 @@ export const IssueView: FC<IIssueView> = observer((props) => {
disabled={disabled || is_archived} disabled={disabled || is_archived}
/> />
<IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} /> <IssueActivity
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
disabled={disabled || is_archived}
/>
</div> </div>
) : ( ) : (
<div className="vertical-scrollbar flex h-full w-full overflow-auto"> <div className="vertical-scrollbar flex h-full w-full overflow-auto">
@ -210,7 +215,12 @@ export const IssueView: FC<IIssueView> = observer((props) => {
workspaceSlug={workspaceSlug} workspaceSlug={workspaceSlug}
/> />
<IssueActivity workspaceSlug={workspaceSlug} projectId={projectId} issueId={issueId} /> <IssueActivity
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
disabled={disabled || is_archived}
/>
</div> </div>
</div> </div>
<div <div