diff --git a/apps/app/components/core/views/issues-view.tsx b/apps/app/components/core/views/issues-view.tsx index ffa3f8165..755b37aa1 100644 --- a/apps/app/components/core/views/issues-view.tsx +++ b/apps/app/components/core/views/issues-view.tsx @@ -548,7 +548,7 @@ export const IssuesView: React.FC = ({ }} handleOnDragEnd={handleOnDragEnd} handleIssueAction={handleIssueAction} - openIssuesListModal={openIssuesListModal ? openIssuesListModal : null} + openIssuesListModal={openIssuesListModal ?? null} removeIssue={cycleId ? removeIssueFromCycle : moduleId ? removeIssueFromModule : null} trashBox={trashBox} setTrashBox={setTrashBox} diff --git a/apps/app/components/core/views/spreadsheet-view/single-issue.tsx b/apps/app/components/core/views/spreadsheet-view/single-issue.tsx index 7e8fd0d26..11a8c42c5 100644 --- a/apps/app/components/core/views/spreadsheet-view/single-issue.tsx +++ b/apps/app/components/core/views/spreadsheet-view/single-issue.tsx @@ -1,12 +1,12 @@ import React, { useCallback, useState } from "react"; -import Link from "next/link"; import { useRouter } from "next/router"; import { mutate } from "swr"; // components import { + IssuePeekOverview, ViewAssigneeSelect, ViewDueDateSelect, ViewEstimateSelect, @@ -75,6 +75,10 @@ export const SingleSpreadsheetIssue: React.FC = ({ nestingLevel, }) => { const [isOpen, setIsOpen] = useState(false); + + // issue peek overview + const [issuePeekOverview, setIssuePeekOverview] = useState(false); + const router = useRouter(); const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; @@ -95,7 +99,7 @@ export const SingleSpreadsheetIssue: React.FC = ({ ? VIEW_ISSUES(viewId.toString(), params) : PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params); - if (issue.parent) { + if (issue.parent) mutate( SUB_ISSUES(issue.parent.toString()), (prevData) => { @@ -116,7 +120,7 @@ export const SingleSpreadsheetIssue: React.FC = ({ }, false ); - } else { + else mutate( fetchKey, (prevData) => @@ -131,7 +135,6 @@ export const SingleSpreadsheetIssue: React.FC = ({ }), false ); - } issuesService .patchIssue( @@ -179,190 +182,203 @@ export const SingleSpreadsheetIssue: React.FC = ({ const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( -
-
-
-
- {properties.key && ( - - {issue.project_detail?.identifier}-{issue.sequence_id} - - )} - {!isNotAllowed && !disableUserActions && ( -
- setIsOpen(nextOpenState)} - content={ -
- + - + - -
- } - placement="bottom-start" + +
+ } + placement="bottom-start" + > + + +
+ )} +
+ + {issue.sub_issues_count > 0 && ( +
+
)}
- {issue.sub_issues_count > 0 && ( -
- -
- )} -
- - - + + + {properties.state && ( +
+ +
+ )} + {properties.priority && ( +
+ +
+ )} + {properties.assignee && ( +
+ +
+ )} + {properties.labels && ( +
+ +
+ )} + + {properties.start_date && ( +
+ +
+ )} + + {properties.due_date && ( +
+ +
+ )} + {properties.estimate && ( +
+ +
+ )} + {properties.created_on && ( +
+ {renderLongDetailDateFormat(issue.created_at)} +
+ )} + {properties.updated_on && ( +
+ {renderLongDetailDateFormat(issue.updated_at)} +
+ )} - {properties.state && ( -
- -
- )} - {properties.priority && ( -
- -
- )} - {properties.assignee && ( -
- -
- )} - {properties.labels && ( -
- -
- )} - - {properties.start_date && ( -
- -
- )} - - {properties.due_date && ( -
- -
- )} - {properties.estimate && ( -
- -
- )} - {properties.created_on && ( -
- {renderLongDetailDateFormat(issue.created_at)} -
- )} - {properties.updated_on && ( -
- {renderLongDetailDateFormat(issue.updated_at)} -
- )} - + ); }; diff --git a/apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx b/apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx index a4f426a23..0b2e785d6 100644 --- a/apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx +++ b/apps/app/components/core/views/spreadsheet-view/spreadsheet-view.tsx @@ -5,7 +5,7 @@ import { useRouter } from "next/router"; // components import { SpreadsheetColumns, SpreadsheetIssues } from "components/core"; -import { CustomMenu, Icon, Spinner } from "components/ui"; +import { CustomMenu, Spinner } from "components/ui"; // hooks import useIssuesProperties from "hooks/use-issue-properties"; import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view"; diff --git a/apps/app/components/inbox/inbox-issue-activity.tsx b/apps/app/components/inbox/inbox-issue-activity.tsx new file mode 100644 index 000000000..efa237162 --- /dev/null +++ b/apps/app/components/inbox/inbox-issue-activity.tsx @@ -0,0 +1,106 @@ +import { useRouter } from "next/router"; + +import useSWR, { mutate } from "swr"; + +// components +import { AddComment, IssueActivitySection } from "components/issues"; +// services +import issuesService from "services/issues.service"; +// hooks +import useUser from "hooks/use-user"; +import useToast from "hooks/use-toast"; +// types +import { IIssue, IIssueComment } from "types"; +// fetch-keys +import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys"; + +type Props = { issueDetails: IIssue }; + +export const InboxIssueActivity: React.FC = ({ issueDetails }) => { + const router = useRouter(); + const { workspaceSlug, projectId, inboxIssueId } = router.query; + + const { setToastAlert } = useToast(); + + const { user } = useUser(); + + const { data: issueActivity, mutate: mutateIssueActivity } = useSWR( + workspaceSlug && projectId && inboxIssueId + ? PROJECT_ISSUES_ACTIVITY(inboxIssueId.toString()) + : null, + workspaceSlug && projectId && inboxIssueId + ? () => + issuesService.getIssueActivities( + workspaceSlug.toString(), + projectId.toString(), + inboxIssueId.toString() + ) + : null + ); + + const handleCommentUpdate = async (comment: IIssueComment) => { + if (!workspaceSlug || !projectId || !inboxIssueId) return; + + await issuesService + .patchIssueComment( + workspaceSlug as string, + projectId as string, + inboxIssueId as string, + comment.id, + comment, + user + ) + .then(() => mutateIssueActivity()); + }; + + const handleCommentDelete = async (commentId: string) => { + if (!workspaceSlug || !projectId || !inboxIssueId) return; + + mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false); + + await issuesService + .deleteIssueComment( + workspaceSlug as string, + projectId as string, + inboxIssueId as string, + commentId, + user + ) + .then(() => mutateIssueActivity()); + }; + + const handleAddComment = async (formData: IIssueComment) => { + if (!workspaceSlug || !issueDetails) return; + + await issuesService + .createIssueComment( + workspaceSlug.toString(), + issueDetails.project, + issueDetails.id, + formData, + user + ) + .then(() => { + mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id)); + }) + .catch(() => + setToastAlert({ + type: "error", + title: "Error!", + message: "Comment could not be posted. Please try again.", + }) + ); + }; + + return ( +
+

Comments/Activity

+ + +
+ ); +}; diff --git a/apps/app/components/inbox/inbox-main-content.tsx b/apps/app/components/inbox/inbox-main-content.tsx index bd4f0ab01..6d4a4337c 100644 --- a/apps/app/components/inbox/inbox-main-content.tsx +++ b/apps/app/components/inbox/inbox-main-content.tsx @@ -14,13 +14,8 @@ import inboxServices from "services/inbox.service"; import useInboxView from "hooks/use-inbox-view"; import useUserAuth from "hooks/use-user-auth"; // components -import { - AddComment, - IssueActivitySection, - IssueDescriptionForm, - IssueDetailsSidebar, - IssueReaction, -} from "components/issues"; +import { IssueDescriptionForm, IssueDetailsSidebar, IssueReaction } from "components/issues"; +import { InboxIssueActivity } from "components/inbox"; // ui import { Loader } from "components/ui"; // icons @@ -42,7 +37,6 @@ import { INBOX_ISSUES, INBOX_ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "cons const defaultValues = { name: "", - description: "", description_html: "", estimate_point: null, assignees_list: [], @@ -296,7 +290,6 @@ export const InboxMainContent: React.FC = () => { workspaceSlug={workspaceSlug as string} issue={{ name: issueDetails.name, - description: issueDetails.description, description_html: issueDetails.description_html, }} handleFormSubmit={submitChanges} @@ -312,11 +305,7 @@ export const InboxMainContent: React.FC = () => { issueId={issueDetails.id} /> -
-

Comments/Activity

- - -
+
diff --git a/apps/app/components/inbox/index.ts b/apps/app/components/inbox/index.ts index 38cea0348..8301d2570 100644 --- a/apps/app/components/inbox/index.ts +++ b/apps/app/components/inbox/index.ts @@ -4,6 +4,7 @@ export * from "./delete-issue-modal"; export * from "./filters-dropdown"; export * from "./filters-list"; export * from "./inbox-action-headers"; +export * from "./inbox-issue-activity"; export * from "./inbox-issue-card"; export * from "./inbox-main-content"; export * from "./issues-list-sidebar"; diff --git a/apps/app/components/issues/activity.tsx b/apps/app/components/issues/activity.tsx index 8dd948e08..5a82907f2 100644 --- a/apps/app/components/issues/activity.tsx +++ b/apps/app/components/issues/activity.tsx @@ -3,10 +3,6 @@ import React from "react"; import Link from "next/link"; import { useRouter } from "next/router"; -import useSWR from "swr"; - -// services -import issuesService from "services/issues.service"; // components import { ActivityIcon, ActivityMessage } from "components/core"; import { CommentCard } from "components/issues/comment"; @@ -15,62 +11,23 @@ import { Icon, Loader } from "components/ui"; // helpers import { timeAgo } from "helpers/date-time.helper"; // types -import { ICurrentUserResponse, IIssueComment } from "types"; -// fetch-keys -import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys"; +import { IIssueActivity, IIssueComment } from "types"; type Props = { - issueId: string; - user: ICurrentUserResponse | undefined; + activity: IIssueActivity[] | undefined; + handleCommentUpdate: (comment: IIssueComment) => Promise; + handleCommentDelete: (commentId: string) => Promise; }; -export const IssueActivitySection: React.FC = ({ issueId, user }) => { +export const IssueActivitySection: React.FC = ({ + activity, + handleCommentUpdate, + handleCommentDelete, +}) => { const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug } = router.query; - const { data: issueActivities, mutate: mutateIssueActivities } = useSWR( - workspaceSlug && projectId ? PROJECT_ISSUES_ACTIVITY(issueId) : null, - workspaceSlug && projectId - ? () => - issuesService.getIssueActivities(workspaceSlug as string, projectId as string, issueId) - : null - ); - - const handleCommentUpdate = async (comment: IIssueComment) => { - if (!workspaceSlug || !projectId || !issueId) return; - - await issuesService - .patchIssueComment( - workspaceSlug as string, - projectId as string, - issueId as string, - comment.id, - comment, - user - ) - .then((res) => mutateIssueActivities()); - }; - - const handleCommentDelete = async (commentId: string) => { - if (!workspaceSlug || !projectId || !issueId) return; - - mutateIssueActivities( - (prevData: any) => prevData?.filter((p: any) => p.id !== commentId), - false - ); - - await issuesService - .deleteIssueComment( - workspaceSlug as string, - projectId as string, - issueId as string, - commentId, - user - ) - .then(() => mutateIssueActivities()); - }; - - if (!issueActivities) { + if (!activity) return (
@@ -87,12 +44,11 @@ export const IssueActivitySection: React.FC = ({ issueId, user }) => {
); - } return (
    - {issueActivities.map((activityItem, index) => { + {activity.map((activityItem, index) => { // determines what type of action is performed const message = activityItem.field ? ( @@ -104,7 +60,7 @@ export const IssueActivitySection: React.FC = ({ issueId, user }) => { return (
  • - {issueActivities.length > 1 && index !== issueActivities.length - 1 ? ( + {activity.length > 1 && index !== activity.length - 1 ? (