diff --git a/web/components/issues/activity.tsx b/web/components/issues/activity.tsx deleted file mode 100644 index 6dae8486f..000000000 --- a/web/components/issues/activity.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import React from "react"; - -import Link from "next/link"; -import { useRouter } from "next/router"; - -// components -import { ActivityIcon, ActivityMessage } from "components/core"; -import { CommentCard } from "components/issues/comment"; -// ui -import { Loader, Tooltip } from "@plane/ui"; -// helpers -import { renderFormattedTime, renderFormattedDate, calculateTimeAgo } from "helpers/date-time.helper"; -// types -import { IIssueActivity } from "@plane/types"; -import { History } from "lucide-react"; - -type Props = { - activity: IIssueActivity[] | undefined; - handleCommentUpdate: (commentId: string, data: Partial) => Promise; - handleCommentDelete: (commentId: string) => Promise; - showAccessSpecifier?: boolean; -}; - -export const IssueActivitySection: React.FC = ({ - activity, - handleCommentUpdate, - handleCommentDelete, - showAccessSpecifier = false, -}) => { - const router = useRouter(); - const { workspaceSlug } = router.query; - - if (!activity) - return ( - -
- - -
-
- - -
-
- - -
-
- ); - - return ( -
-
    - {activity.map((activityItem, index) => { - // determines what type of action is performed - const message = activityItem.field ? : "created the issue."; - - if ("field" in activityItem && activityItem.field !== "updated_by") { - return ( -
  • -
    - {activity.length > 1 && index !== activity.length - 1 ? ( -
    -
  • - ); - } else if ("comment_json" in activityItem) - return ( -
    - -
    - ); - })} -
-
- ); -}; diff --git a/web/components/issues/comment/add-comment.tsx b/web/components/issues/comment/add-comment.tsx deleted file mode 100644 index e9396eccc..000000000 --- a/web/components/issues/comment/add-comment.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import React from "react"; -import { useRouter } from "next/router"; -import { useForm, Controller } from "react-hook-form"; -// hooks -import { useMention, useWorkspace } from "hooks/store"; -// services -import { FileService } from "services/file.service"; -// components -import { LiteTextEditorWithRef } from "@plane/lite-text-editor"; -// ui -import { Button } from "@plane/ui"; -import { Globe2, Lock } from "lucide-react"; -// types -import type { IIssueActivity } from "@plane/types"; - -const defaultValues: Partial = { - access: "INTERNAL", - comment_html: "", -}; - -type Props = { - disabled?: boolean; - onSubmit: (data: IIssueActivity) => Promise; - showAccessSpecifier?: boolean; -}; - -type commentAccessType = { - icon: any; - key: string; - label: "Private" | "Public"; -}; -const commentAccess: commentAccessType[] = [ - { - icon: Lock, - key: "INTERNAL", - label: "Private", - }, - { - icon: Globe2, - key: "EXTERNAL", - label: "Public", - }, -]; - -// services -const fileService = new FileService(); - -export const AddComment: React.FC = ({ disabled = false, onSubmit, showAccessSpecifier = false }) => { - // refs - const editorRef = React.useRef(null); - // router - const router = useRouter(); - const { workspaceSlug } = router.query; - const workspaceStore = useWorkspace(); - const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string; - - // store hooks - const { mentionHighlights, mentionSuggestions } = useMention(); - // form info - const { - control, - formState: { isSubmitting }, - handleSubmit, - reset, - } = useForm({ defaultValues }); - - const handleAddComment = async (formData: IIssueActivity) => { - if (!formData.comment_html || isSubmitting) return; - - await onSubmit(formData).then(() => { - reset(defaultValues); - editorRef.current?.clearEditor(); - }); - }; - - return ( -
-
-
- ( - ( -

" : commentValue} - customClassName="p-2 h-full" - editorContentCustomClassNames="min-h-[35px]" - debouncedUpdatesEnabled={false} - onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)} - commentAccessSpecifier={ - showAccessSpecifier - ? { accessValue: accessValue ?? "INTERNAL", onAccessChange, showAccessSpecifier, commentAccess } - : undefined - } - mentionSuggestions={mentionSuggestions} - mentionHighlights={mentionHighlights} - submitButton={ - - } - /> - )} - /> - )} - /> -
-
-
- ); -}; diff --git a/web/components/issues/comment/comment-card.tsx b/web/components/issues/comment/comment-card.tsx deleted file mode 100644 index 1ee90f99f..000000000 --- a/web/components/issues/comment/comment-card.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { useForm } from "react-hook-form"; -import { observer } from "mobx-react-lite"; -// hooks -import { useMention, useUser, useWorkspace } from "hooks/store"; -// services -import { FileService } from "services/file.service"; -// icons -import { Check, Globe2, Lock, MessageSquare, Pencil, Trash2, X } from "lucide-react"; -// ui -import { CustomMenu } from "@plane/ui"; -import { CommentReaction } from "components/issues"; -import { LiteTextEditorWithRef, LiteReadOnlyEditorWithRef } from "@plane/lite-text-editor"; -// helpers -import { calculateTimeAgo } from "helpers/date-time.helper"; -// types -import type { IIssueActivity } from "@plane/types"; - -// services -const fileService = new FileService(); - -type Props = { - comment: IIssueActivity; - handleCommentDeletion: (comment: string) => void; - onSubmit: (commentId: string, data: Partial) => void; - showAccessSpecifier?: boolean; - workspaceSlug: string; -}; - -export const CommentCard: React.FC = observer((props) => { - const { comment, handleCommentDeletion, onSubmit, showAccessSpecifier = false, workspaceSlug } = props; - const workspaceStore = useWorkspace(); - const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug)?.id as string; - - // states - const [isEditing, setIsEditing] = useState(false); - // refs - const editorRef = React.useRef(null); - const showEditorRef = React.useRef(null); - // store hooks - const { currentUser } = useUser(); - const { mentionHighlights, mentionSuggestions } = useMention(); - // form info - const { - formState: { isSubmitting }, - handleSubmit, - setFocus, - watch, - setValue, - } = useForm({ - defaultValues: comment, - }); - - const onEnter = (formData: Partial) => { - if (isSubmitting) return; - setIsEditing(false); - - onSubmit(comment.id, formData); - - editorRef.current?.setEditorValue(formData.comment_html); - showEditorRef.current?.setEditorValue(formData.comment_html); - }; - - useEffect(() => { - isEditing && setFocus("comment"); - }, [isEditing, setFocus]); - - return ( -
-
- {comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? ( - { - ) : ( -
- {comment.actor_detail.is_bot - ? comment.actor_detail.first_name.charAt(0) - : comment.actor_detail.display_name.charAt(0)} -
- )} - - - -
- -
-
-
- {comment.actor_detail.is_bot ? comment.actor_detail.first_name + " Bot" : comment.actor_detail.display_name} -
-

commented {calculateTimeAgo(comment.created_at)}

-
-
-
-
- setValue("comment_html", comment_html)} - mentionSuggestions={mentionSuggestions} - mentionHighlights={mentionHighlights} - /> -
-
- - -
-
-
- {showAccessSpecifier && ( -
- {comment.access === "INTERNAL" ? : } -
- )} - - -
-
-
- - {currentUser?.id === comment.actor && ( - - setIsEditing(true)} className="flex items-center gap-1"> - - Edit comment - - {showAccessSpecifier && ( - <> - {comment.access === "INTERNAL" ? ( - onSubmit(comment.id, { access: "EXTERNAL" })} - className="flex items-center gap-1" - > - - Switch to public comment - - ) : ( - onSubmit(comment.id, { access: "INTERNAL" })} - className="flex items-center gap-1" - > - - Switch to private comment - - )} - - )} - { - handleCommentDeletion(comment.id); - }} - className="flex items-center gap-1" - > - - Delete comment - - - )} -
- ); -}); diff --git a/web/components/issues/comment/comment-reaction.tsx b/web/components/issues/comment/comment-reaction.tsx deleted file mode 100644 index a59337575..000000000 --- a/web/components/issues/comment/comment-reaction.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import { FC } from "react"; -import { useRouter } from "next/router"; -import { observer } from "mobx-react-lite"; -// hooks -import { useUser } from "hooks/store"; -import useCommentReaction from "hooks/use-comment-reaction"; -// ui -// import { ReactionSelector } from "components/core"; -// helper -import { renderEmoji } from "helpers/emoji.helper"; -// types -import { IssueCommentReaction } from "@plane/types"; - -type Props = { - projectId?: string | string[]; - commentId: string; - readonly?: boolean; -}; - -export const CommentReaction: FC = observer((props) => { - const { projectId, commentId, readonly = false } = props; - // router - const router = useRouter(); - const { workspaceSlug } = router.query; - // store hooks - const { currentUser } = useUser(); - - const { commentReactions, groupedReactions, handleReactionCreate, handleReactionDelete } = useCommentReaction( - workspaceSlug, - projectId, - commentId - ); - - const handleReactionClick = (reaction: string) => { - if (!workspaceSlug || !projectId || !commentId) return; - - const isSelected = commentReactions?.some( - (r: IssueCommentReaction) => r.actor === currentUser?.id && r.reaction === reaction - ); - - if (isSelected) { - handleReactionDelete(reaction); - } else { - handleReactionCreate(reaction); - } - }; - - return ( -
- {/* FIXME: have to replace this once the issue details page is ready --issue-detail-- */} - {/* {!readonly && ( - reaction.actor === currentUser?.id) - .map((r: IssueCommentReaction) => r.reaction) || [] - } - onSelect={handleReactionClick} - /> - )} */} - - {Object.keys(groupedReactions || {}).map( - (reaction) => - groupedReactions?.[reaction]?.length && - groupedReactions[reaction].length > 0 && ( - - ) - )} -
- ); -}); diff --git a/web/components/issues/comment/index.ts b/web/components/issues/comment/index.ts deleted file mode 100644 index 61ac899ad..000000000 --- a/web/components/issues/comment/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./add-comment"; -export * from "./comment-card"; -export * from "./comment-reaction"; diff --git a/web/components/issues/index.ts b/web/components/issues/index.ts index f1c6636cd..3cf88cb7c 100644 --- a/web/components/issues/index.ts +++ b/web/components/issues/index.ts @@ -1,8 +1,6 @@ export * from "./attachment"; -export * from "./comment"; export * from "./issue-modal"; export * from "./view-select"; -export * from "./activity"; export * from "./delete-issue-modal"; export * from "./description-form"; export * from "./issue-layouts"; diff --git a/web/components/issues/issue-detail/sidebar.tsx b/web/components/issues/issue-detail/sidebar.tsx index 46b9e6c6c..f811078f8 100644 --- a/web/components/issues/issue-detail/sidebar.tsx +++ b/web/components/issues/issue-detail/sidebar.tsx @@ -50,38 +50,10 @@ type Props = { issueOperations: TIssueOperations; is_archived: boolean; is_editable: boolean; - fieldsToShow?: ( - | "state" - | "assignee" - | "priority" - | "estimate" - | "parent" - | "blocker" - | "blocked" - | "startDate" - | "dueDate" - | "cycle" - | "module" - | "label" - | "link" - | "delete" - | "all" - | "subscribe" - | "duplicate" - | "relates_to" - )[]; }; export const IssueDetailsSidebar: React.FC = observer((props) => { - const { - workspaceSlug, - projectId, - issueId, - issueOperations, - is_archived, - is_editable, - fieldsToShow = ["all"], - } = props; + const { workspaceSlug, projectId, issueId, issueOperations, is_archived, is_editable } = props; // router const router = useRouter(); const { inboxIssueId } = router.query; @@ -153,21 +125,19 @@ export const IssueDetailsSidebar: React.FC = observer((props) => {
- {currentUser && !is_archived && (fieldsToShow.includes("all") || fieldsToShow.includes("subscribe")) && ( + {currentUser && !is_archived && ( )} - {(fieldsToShow.includes("all") || fieldsToShow.includes("link")) && ( - - )} + - {is_editable && (fieldsToShow.includes("all") || fieldsToShow.includes("delete")) && ( + {is_editable && ( - - -
- - -
- {showAccessSpecifier && ( -
- {comment.access === "INTERNAL" ? : } -
- )} - - -
- -
-
- - - {user?.id === comment.actor && ( - - setIsEditing(true)} className="flex items-center gap-1"> - - Edit comment - - {showAccessSpecifier && ( - <> - {comment.access === "INTERNAL" ? ( - onSubmit({ id: comment.id, access: "EXTERNAL" })} - className="flex items-center gap-1" - > - - Switch to public comment - - ) : ( - onSubmit({ id: comment.id, access: "INTERNAL" })} - className="flex items-center gap-1" - > - - Switch to private comment - - )} - - )} - { - handleCommentDeletion(comment.id); - }} - className="flex items-center gap-1" - > - - Delete comment - - - )} - - ); -}; diff --git a/web/components/issues/peek-overview/activity/comment-editor.tsx b/web/components/issues/peek-overview/activity/comment-editor.tsx deleted file mode 100644 index 45119e932..000000000 --- a/web/components/issues/peek-overview/activity/comment-editor.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import React from "react"; -import { useRouter } from "next/router"; -import { useForm, Controller } from "react-hook-form"; -import { Globe2, Lock } from "lucide-react"; -// hooks -import { useMention, useWorkspace } from "hooks/store"; -// services -import { FileService } from "services/file.service"; -// components -import { LiteTextEditorWithRef } from "@plane/lite-text-editor"; -// ui -import { Button } from "@plane/ui"; -// types -import type { IIssueActivity } from "@plane/types"; - -const defaultValues: Partial = { - access: "INTERNAL", - comment_html: "", -}; - -type IIssueCommentEditor = { - disabled?: boolean; - onSubmit: (data: IIssueActivity) => Promise; - showAccessSpecifier?: boolean; -}; - -type commentAccessType = { - icon: any; - key: string; - label: "Private" | "Public"; -}; -const commentAccess: commentAccessType[] = [ - { - icon: Lock, - key: "INTERNAL", - label: "Private", - }, - { - icon: Globe2, - key: "EXTERNAL", - label: "Public", - }, -]; - -// services -const fileService = new FileService(); - -export const IssueCommentEditor: React.FC = (props) => { - const { disabled = false, onSubmit, showAccessSpecifier = false } = props; - // refs - const editorRef = React.useRef(null); - // router - const router = useRouter(); - const { workspaceSlug } = router.query; - const workspaceStore = useWorkspace(); - const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string; - - // store hooks - const { mentionHighlights, mentionSuggestions } = useMention(); - // form info - const { - control, - formState: { isSubmitting }, - handleSubmit, - reset, - } = useForm({ defaultValues }); - - const handleAddComment = async (formData: IIssueActivity) => { - if (!formData.comment_html || isSubmitting) return; - - await onSubmit(formData).then(() => { - reset(defaultValues); - editorRef.current?.clearEditor(); - }); - }; - - return ( -
-
-
- ( - ( -

" : commentValue} - customClassName="p-2 h-full" - editorContentCustomClassNames="min-h-[35px]" - debouncedUpdatesEnabled={false} - mentionSuggestions={mentionSuggestions} - mentionHighlights={mentionHighlights} - onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)} - commentAccessSpecifier={ - showAccessSpecifier - ? { accessValue: accessValue ?? "INTERNAL", onAccessChange, showAccessSpecifier, commentAccess } - : undefined - } - submitButton={ - - } - /> - )} - /> - )} - /> -
-
-
- ); -}; diff --git a/web/components/issues/peek-overview/activity/comment-reaction.tsx b/web/components/issues/peek-overview/activity/comment-reaction.tsx deleted file mode 100644 index 81ce7b4d5..000000000 --- a/web/components/issues/peek-overview/activity/comment-reaction.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { FC } from "react"; -import useSWR from "swr"; -import { observer } from "mobx-react-lite"; -// components -import { IssuePeekOverviewReactions } from "components/issues"; -import { useIssueDetail } from "hooks/store"; - -interface IIssueCommentReaction { - workspaceSlug: string; - projectId: string; - issueId: string; - user: any; - - comment: any; - issueCommentReactionCreate: (commentId: string, reaction: string) => void; - issueCommentReactionRemove: (commentId: string, reaction: string) => void; -} - -export const IssueCommentReaction: FC = observer((props) => { - const { workspaceSlug, projectId, issueId, user, comment, issueCommentReactionCreate, issueCommentReactionRemove } = - props; - - const issueDetail = useIssueDetail(); - - const handleCommentReactionCreate = (reaction: string) => { - if (issueCommentReactionCreate && comment?.id) issueCommentReactionCreate(comment?.id, reaction); - }; - - const handleCommentReactionRemove = (reaction: string) => { - if (issueCommentReactionRemove && comment?.id) issueCommentReactionRemove(comment?.id, reaction); - }; - - useSWR( - workspaceSlug && projectId && issueId && comment && comment?.id - ? `ISSUE+PEEK_OVERVIEW_COMMENT_${comment?.id}` - : null, - () => { - if (workspaceSlug && projectId && issueId && comment && comment.id) { - issueDetail.fetchCommentReactions(workspaceSlug, projectId, comment?.id); - } - } - ); - - const issueReactions = issueDetail?.commentReaction.getCommentReactionsByCommentId(comment.id) || null; - - return ( -
- -
- ); -}); diff --git a/web/components/issues/peek-overview/activity/index.ts b/web/components/issues/peek-overview/activity/index.ts deleted file mode 100644 index 705c5a336..000000000 --- a/web/components/issues/peek-overview/activity/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./card"; -export * from "./comment-card"; -export * from "./comment-editor"; -export * from "./comment-reaction"; -export * from "./view"; diff --git a/web/components/issues/peek-overview/activity/view.tsx b/web/components/issues/peek-overview/activity/view.tsx deleted file mode 100644 index 4a13abb1e..000000000 --- a/web/components/issues/peek-overview/activity/view.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { FC } from "react"; -// components -import { IssueActivityCard, IssueCommentEditor } from "components/issues"; -// types -import { IUser } from "@plane/types"; - -type Props = { - workspaceSlug: string; - projectId: string; - issueId: string; - user: IUser | null; - issueActivity: string[] | undefined; - issueCommentCreate: (comment: any) => void; - issueCommentUpdate: (comment: any) => void; - issueCommentRemove: (commentId: string) => void; - issueCommentReactionCreate: (commentId: string, reaction: string) => void; - issueCommentReactionRemove: (commentId: string, reaction: string) => void; - showCommentAccessSpecifier: boolean; -}; - -export const IssueActivity: FC = (props) => { - const { - workspaceSlug, - projectId, - issueId, - user, - issueActivity, - issueCommentCreate, - issueCommentUpdate, - issueCommentRemove, - issueCommentReactionCreate, - issueCommentReactionRemove, - showCommentAccessSpecifier, - } = props; - - const handleAddComment = async (formData: any) => { - if (!formData.comment_html) return; - await issueCommentCreate(formData); - }; - - return ( -
-
Activity
- -
- - -
-
- ); -}; diff --git a/web/components/issues/peek-overview/index.ts b/web/components/issues/peek-overview/index.ts index 38581dada..6d602e45b 100644 --- a/web/components/issues/peek-overview/index.ts +++ b/web/components/issues/peek-overview/index.ts @@ -1,5 +1,3 @@ -export * from "./activity"; -export * from "./reactions"; export * from "./issue-detail"; export * from "./properties"; export * from "./root"; diff --git a/web/components/issues/peek-overview/reactions/index.ts b/web/components/issues/peek-overview/reactions/index.ts deleted file mode 100644 index 579646533..000000000 --- a/web/components/issues/peek-overview/reactions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./preview"; -export * from "./root"; -export * from "./selector"; diff --git a/web/components/issues/peek-overview/reactions/preview.tsx b/web/components/issues/peek-overview/reactions/preview.tsx deleted file mode 100644 index 7dc1f78ec..000000000 --- a/web/components/issues/peek-overview/reactions/preview.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { FC } from "react"; -// helpers -import { renderEmoji } from "helpers/emoji.helper"; - -interface IIssueReactionPreview { - issueReactions: any; - user: any; - handleReaction: (reaction: string) => void; -} - -export const IssueReactionPreview: FC = (props) => { - const { issueReactions, user, handleReaction } = props; - - const isUserReacted = (reactions: any) => { - const userReaction = reactions?.find((reaction: any) => reaction.actor === user?.id); - if (userReaction) return true; - return false; - }; - - return ( -
- {Object.keys(issueReactions || {}).map( - (reaction) => - issueReactions[reaction]?.length > 0 && ( - - ) - )} -
- ); -}; diff --git a/web/components/issues/peek-overview/reactions/root.tsx b/web/components/issues/peek-overview/reactions/root.tsx deleted file mode 100644 index d8aa47721..000000000 --- a/web/components/issues/peek-overview/reactions/root.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { FC } from "react"; -// components -import { IssueReactionPreview, IssueReactionSelector } from "components/issues"; -// types -import { IUser } from "@plane/types"; - -interface IIssueReaction { - issueReactions: any; - user: IUser | null; - issueReactionCreate: (reaction: string) => void; - issueReactionRemove: (reaction: string) => void; - position?: "top" | "bottom"; -} - -export const IssuePeekOverviewReactions: FC = (props) => { - const { issueReactions, user, issueReactionCreate, issueReactionRemove, position = "bottom" } = props; - - const handleReaction = (reaction: string) => { - const isReactionAvailable = - issueReactions?.[reaction].find((_reaction: any) => _reaction.actor === user?.id) ?? false; - - if (isReactionAvailable) issueReactionRemove(reaction); - else issueReactionCreate(reaction); - }; - - return ( -
- - -
- ); -}; diff --git a/web/components/issues/peek-overview/reactions/selector.tsx b/web/components/issues/peek-overview/reactions/selector.tsx deleted file mode 100644 index 5292cedf3..000000000 --- a/web/components/issues/peek-overview/reactions/selector.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { FC, Fragment } from "react"; -import { Popover, Transition } from "@headlessui/react"; -// helper -import { renderEmoji } from "helpers/emoji.helper"; -// icons -import { SmilePlus } from "lucide-react"; -// constants -import { issueReactionEmojis } from "constants/issue"; - -interface IIssueReactionSelector { - size?: "sm" | "md" | "lg"; - position?: "top" | "bottom"; - onSelect: (reaction: any) => void; -} - -export const IssueReactionSelector: FC = (props) => { - const { size = "md", position = "top", onSelect } = props; - - return ( - <> - - {({ open, close: closePopover }) => ( - <> - - - - - - - -
- {issueReactionEmojis.map((emoji) => ( - - ))} -
-
-
- - )} -
- - ); -};