From bf66ebf5dca7705a9d7c782372cf8addd44b25c3 Mon Sep 17 00:00:00 2001 From: LAKHAN BAHETI Date: Thu, 14 Dec 2023 19:43:26 +0530 Subject: [PATCH 1/2] fix: peek-overview delete issue --- .../calendar/base-calendar-root.tsx | 4 +-- .../issue-layouts/gantt/base-gantt-root.tsx | 26 ++++++++++++---- .../issues/issue-layouts/gantt/cycle-root.tsx | 30 ++++++++++++++++++- .../issue-layouts/gantt/module-root.tsx | 30 ++++++++++++++++++- .../issue-layouts/gantt/project-root.tsx | 26 +++++++++++++++- .../issue-layouts/gantt/project-view-root.tsx | 26 +++++++++++++++- .../issue-layouts/kanban/base-kanban-root.tsx | 4 +-- .../issue-layouts/list/base-list-root.tsx | 4 ++- .../spreadsheet/spreadsheet-view.tsx | 2 +- web/components/issues/peek-overview/root.tsx | 7 +++-- web/components/issues/sub-issues/issue.tsx | 12 +++++++- .../issues/sub-issues/issues-list.tsx | 3 ++ web/components/issues/sub-issues/root.tsx | 11 +++++++ 13 files changed, 166 insertions(+), 19 deletions(-) diff --git a/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx b/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx index 1d70e22894..b080bc838a 100644 --- a/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx +++ b/web/components/issues/issue-layouts/calendar/base-calendar-root.tsx @@ -120,8 +120,8 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => { workspaceSlug={workspaceSlug.toString()} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate) => - await handleIssues(issueToUpdate.target_date ?? "", issueToUpdate as IIssue, EIssueActions.UPDATE) + handleIssue={async (issueToUpdate, action: EIssueActions) => + await handleIssues(issueToUpdate.target_date ?? "", issueToUpdate as IIssue, action) } /> )} diff --git a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx index 62df8fc797..7ed42bf22a 100644 --- a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx +++ b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback } from "react"; import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // mobx store @@ -25,6 +25,8 @@ import { IViewIssuesStore, } from "store/issues"; import { TUnGroupedIssues } from "store/issues/types"; +import { EIssueActions } from "../types"; +// constants import { EUserWorkspaceRoles } from "constants/workspace"; interface IBaseGanttRoot { @@ -35,13 +37,18 @@ interface IBaseGanttRoot { | IViewIssuesFilterStore; issueStore: IProjectIssuesStore | IModuleIssuesStore | ICycleIssuesStore | IViewIssuesStore; viewId?: string; + issueActions: { + [EIssueActions.DELETE]: (issue: IIssue) => Promise; + [EIssueActions.UPDATE]?: (issue: IIssue) => Promise; + [EIssueActions.REMOVE]?: (issue: IIssue) => Promise; + }; } export const BaseGanttRoot: React.FC = observer((props: IBaseGanttRoot) => { - const { issueFiltersStore, issueStore, viewId } = props; + const { issueFiltersStore, issueStore, viewId, issueActions } = props; const router = useRouter(); - const { workspaceSlug, peekIssueId, peekProjectId } = router.query; + const { workspaceSlug, projectId, peekIssueId, peekProjectId } = router.query; const { user: { currentProjectRole }, @@ -64,6 +71,15 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan await issueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, payload, viewId); }; + const handleIssues = useCallback( + async (issue: IIssue, action: EIssueActions) => { + if (issueActions[action]) { + await issueActions[action]!(issue); + } + }, + [issueActions] + ); + const updateIssue = async (projectId: string, issueId: string, payload: Partial) => { if (!workspaceSlug) return; @@ -102,8 +118,8 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan workspaceSlug={workspaceSlug.toString()} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate) => { - await updateIssue(peekProjectId.toString(), peekIssueId.toString(), issueToUpdate); + handleIssue={async (issueToUpdate, action) => { + await handleIssues(issueToUpdate as IIssue, action); }} /> )} diff --git a/web/components/issues/issue-layouts/gantt/cycle-root.tsx b/web/components/issues/issue-layouts/gantt/cycle-root.tsx index 5366506947..e09092fec9 100644 --- a/web/components/issues/issue-layouts/gantt/cycle-root.tsx +++ b/web/components/issues/issue-layouts/gantt/cycle-root.tsx @@ -4,15 +4,43 @@ import { useMobxStore } from "lib/mobx/store-provider"; // components import { BaseGanttRoot } from "./base-gantt-root"; import { useRouter } from "next/router"; +// types +import { EIssueActions } from "../types"; +import { IIssue } from "types"; export const CycleGanttLayout: React.FC = observer(() => { const router = useRouter(); - const { cycleId } = router.query; + const { cycleId, workspaceSlug } = router.query; const { cycleIssues: cycleIssueStore, cycleIssuesFilter: cycleIssueFilterStore } = useMobxStore(); + const issueActions = { + [EIssueActions.UPDATE]: async (issue: IIssue) => { + if (!workspaceSlug || !cycleId) return; + + await cycleIssueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue, cycleId.toString()); + }, + [EIssueActions.DELETE]: async (issue: IIssue) => { + if (!workspaceSlug || !cycleId) return; + + await cycleIssueStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id, cycleId.toString()); + }, + [EIssueActions.REMOVE]: async (issue: IIssue) => { + if (!workspaceSlug || !cycleId || !issue.bridge_id) return; + + await cycleIssueStore.removeIssueFromCycle( + workspaceSlug.toString(), + issue.project, + cycleId.toString(), + issue.id, + issue.bridge_id + ); + }, + }; + return ( { const router = useRouter(); - const { moduleId } = router.query; + const { moduleId, workspaceSlug } = router.query; const { moduleIssues: moduleIssueStore, moduleIssuesFilter: moduleIssueFilterStore } = useMobxStore(); + const issueActions = { + [EIssueActions.UPDATE]: async (issue: IIssue) => { + if (!workspaceSlug || !moduleId) return; + + await moduleIssueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue, moduleId.toString()); + }, + [EIssueActions.DELETE]: async (issue: IIssue) => { + if (!workspaceSlug || !moduleId) return; + + await moduleIssueStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id, moduleId.toString()); + }, + [EIssueActions.REMOVE]: async (issue: IIssue) => { + if (!workspaceSlug || !moduleId || !issue.bridge_id) return; + + await moduleIssueStore.removeIssueFromModule( + workspaceSlug.toString(), + issue.project, + moduleId.toString(), + issue.id, + issue.bridge_id + ); + }, + }; + return ( { const { projectIssues: projectIssuesStore, projectIssuesFilter: projectIssueFiltersStore } = useMobxStore(); + const router = useRouter(); + const { workspaceSlug } = router.query; - return ; + const issueActions = { + [EIssueActions.UPDATE]: async (issue: IIssue) => { + if (!workspaceSlug) return; + + await projectIssuesStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue); + }, + [EIssueActions.DELETE]: async (issue: IIssue) => { + if (!workspaceSlug) return; + + await projectIssuesStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id); + }, + }; + return ( + + ); }); diff --git a/web/components/issues/issue-layouts/gantt/project-view-root.tsx b/web/components/issues/issue-layouts/gantt/project-view-root.tsx index 3155aae6f7..767603bd74 100644 --- a/web/components/issues/issue-layouts/gantt/project-view-root.tsx +++ b/web/components/issues/issue-layouts/gantt/project-view-root.tsx @@ -1,11 +1,35 @@ import { observer } from "mobx-react-lite"; +import { useRouter } from "next/router"; // mobx store import { useMobxStore } from "lib/mobx/store-provider"; // components import { BaseGanttRoot } from "./base-gantt-root"; +// types +import { EIssueActions } from "../types"; +import { IIssue } from "types"; export const ProjectViewGanttLayout: React.FC = observer(() => { const { viewIssues: projectIssueViewStore, viewIssuesFilter: projectIssueViewFiltersStore } = useMobxStore(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; - return ; + const issueActions = { + [EIssueActions.UPDATE]: async (issue: IIssue) => { + if (!workspaceSlug) return; + + await projectIssueViewStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, issue); + }, + [EIssueActions.DELETE]: async (issue: IIssue) => { + if (!workspaceSlug) return; + + await projectIssueViewStore.removeIssue(workspaceSlug.toString(), issue.project, issue.id); + }, + }; + return ( + + ); }); diff --git a/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx b/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx index 057ba0b87b..b536b1fa87 100644 --- a/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx +++ b/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx @@ -346,8 +346,8 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas workspaceSlug={workspaceSlug.toString()} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate) => - await handleIssues(sub_group_by, group_by, issueToUpdate as IIssue, EIssueActions.UPDATE) + handleIssue={async (issueToUpdate, action: EIssueActions) => + await handleIssues(sub_group_by, group_by, issueToUpdate as IIssue, action) } /> )} diff --git a/web/components/issues/issue-layouts/list/base-list-root.tsx b/web/components/issues/issue-layouts/list/base-list-root.tsx index 92956509e1..55b2fce55b 100644 --- a/web/components/issues/issue-layouts/list/base-list-root.tsx +++ b/web/components/issues/issue-layouts/list/base-list-root.tsx @@ -168,7 +168,9 @@ export const BaseListRoot = observer((props: IBaseListRoot) => { workspaceSlug={workspaceSlug.toString()} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate) => await handleIssues(issueToUpdate as IIssue, EIssueActions.UPDATE)} + handleIssue={async (issueToUpdate, action: EIssueActions) => + await handleIssues(issueToUpdate as IIssue, action) + } /> )} diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx index 370bbfa0f9..4b7ffe6dae 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx @@ -194,7 +194,7 @@ export const SpreadsheetView: React.FC = observer((props) => { workspaceSlug={workspaceSlug.toString()} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate: any) => await handleIssues(issueToUpdate, EIssueActions.UPDATE)} + handleIssue={async (issueToUpdate: any, action: EIssueActions) => await handleIssues(issueToUpdate, action)} /> )} diff --git a/web/components/issues/peek-overview/root.tsx b/web/components/issues/peek-overview/root.tsx index 783958f5dd..51c13d7cc7 100644 --- a/web/components/issues/peek-overview/root.tsx +++ b/web/components/issues/peek-overview/root.tsx @@ -11,6 +11,7 @@ import { IssueView } from "components/issues"; import { copyUrlToClipboard } from "helpers/string.helper"; // types import { IIssue, IIssueLink } from "types"; +import { EIssueActions } from "../issue-layouts/types"; // constants import { EUserWorkspaceRoles } from "constants/workspace"; @@ -18,7 +19,7 @@ interface IIssuePeekOverview { workspaceSlug: string; projectId: string; issueId: string; - handleIssue: (issue: Partial) => void; + handleIssue: (issue: Partial, action: EIssueActions) => Promise; isArchived?: boolean; children?: ReactNode; } @@ -98,7 +99,7 @@ export const IssuePeekOverview: FC = observer((props) => { const issueUpdate = async (_data: Partial) => { if (handleIssue) { - await handleIssue(_data); + await handleIssue(_data, EIssueActions.UPDATE); fetchIssueActivity(workspaceSlug, projectId, issueId); } }; @@ -133,7 +134,7 @@ export const IssuePeekOverview: FC = observer((props) => { const handleDeleteIssue = async () => { if (isArchived) await deleteArchivedIssue(workspaceSlug, projectId, issue!); - else removeIssueFromStructure(workspaceSlug, projectId, issue!); + else await handleIssue(issue!, EIssueActions.DELETE); const { query } = router; if (query.peekIssueId) { setPeekId(null); diff --git a/web/components/issues/sub-issues/issue.tsx b/web/components/issues/sub-issues/issue.tsx index 02ab4a1430..c7d36ac34f 100644 --- a/web/components/issues/sub-issues/issue.tsx +++ b/web/components/issues/sub-issues/issue.tsx @@ -10,6 +10,7 @@ import { CustomMenu, Tooltip } from "@plane/ui"; // types import { IUser, IIssue } from "types"; import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root"; +import { EIssueActions } from "../issue-layouts/types"; export interface ISubIssues { workspaceSlug: string; @@ -29,6 +30,7 @@ export interface ISubIssues { issue?: IIssue | null ) => void; handleUpdateIssue: (issue: IIssue, data: Partial) => void; + handleDeleteIssue: (issue: IIssue) => Promise; } export const SubIssues: React.FC = ({ @@ -45,6 +47,7 @@ export const SubIssues: React.FC = ({ copyText, handleIssueCrudOperation, handleUpdateIssue, + handleDeleteIssue, }) => { const router = useRouter(); const { peekProjectId, peekIssueId } = router.query; @@ -65,7 +68,13 @@ export const SubIssues: React.FC = ({ workspaceSlug={workspaceSlug} projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} - handleIssue={async (issueToUpdate) => await handleUpdateIssue(issue, { ...issue, ...issueToUpdate })} + handleIssue={async (issueToUpdate, action) => { + if (action === EIssueActions.UPDATE) { + await handleUpdateIssue(issue, { ...issue, ...issueToUpdate }); + } else if (action === EIssueActions.DELETE) { + await handleDeleteIssue(issue); + } + }} /> )}
@@ -176,6 +185,7 @@ export const SubIssues: React.FC = ({ {issuesLoader.visibility.includes(issue?.id) && issue?.sub_issues_count > 0 && ( void; handleUpdateIssue: (issue: IIssue, data: Partial) => void; + handleDeleteIssue: (issue: IIssue) => Promise } const issueService = new IssueService(); @@ -44,6 +45,7 @@ export const SubIssuesRootList: React.FC = ({ copyText, handleIssueCrudOperation, handleUpdateIssue, + handleDeleteIssue }) => { const { data: issues, isLoading } = useSWR( workspaceSlug && projectId && parentIssue && parentIssue?.id ? SUB_ISSUES(parentIssue?.id) : null, @@ -70,6 +72,7 @@ export const SubIssuesRootList: React.FC = ({ issues.sub_issues.length > 0 && issues.sub_issues.map((issue: IIssue) => ( = observer((props) => { [updateIssueStructure, projectId, updateIssue, user, workspaceSlug] ); + const handleDeleteIssue = useCallback( + async (issue: IIssue) => { + if (!workspaceSlug || !projectId || !user) return; + + await removeIssue(workspaceSlug.toString(), projectId.toString(), issue.id); + await mutate(SUB_ISSUES(parentIssue?.id)); + }, + [removeIssue, projectId, user, workspaceSlug] + ); + const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const mutateSubIssues = (parentIssueId: string | null) => { @@ -236,6 +246,7 @@ export const SubIssuesRoot: React.FC = observer((props) => { {issuesLoader.visibility.includes(parentIssue?.id) && workspaceSlug && projectId && (
Date: Thu, 14 Dec 2023 19:56:04 +0530 Subject: [PATCH 2/2] refactor: removed unused variables --- .../issue-layouts/gantt/base-gantt-root.tsx | 8 +------- .../issue-layouts/gantt/project-view-root.tsx | 2 +- web/components/issues/peek-overview/root.tsx | 1 - web/components/issues/sub-issues/root.tsx | 2 +- .../projects/[projectId]/pages/[pageId].tsx | 19 ++++++++----------- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx index 7ed42bf22a..15b8516614 100644 --- a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx +++ b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx @@ -48,7 +48,7 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan const { issueFiltersStore, issueStore, viewId, issueActions } = props; const router = useRouter(); - const { workspaceSlug, projectId, peekIssueId, peekProjectId } = router.query; + const { workspaceSlug, peekIssueId, peekProjectId } = router.query; const { user: { currentProjectRole }, @@ -80,12 +80,6 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan [issueActions] ); - const updateIssue = async (projectId: string, issueId: string, payload: Partial) => { - if (!workspaceSlug) return; - - await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId); - }; - const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; return ( diff --git a/web/components/issues/issue-layouts/gantt/project-view-root.tsx b/web/components/issues/issue-layouts/gantt/project-view-root.tsx index 767603bd74..c39c32fe8e 100644 --- a/web/components/issues/issue-layouts/gantt/project-view-root.tsx +++ b/web/components/issues/issue-layouts/gantt/project-view-root.tsx @@ -11,7 +11,7 @@ import { IIssue } from "types"; export const ProjectViewGanttLayout: React.FC = observer(() => { const { viewIssues: projectIssueViewStore, viewIssuesFilter: projectIssueViewFiltersStore } = useMobxStore(); const router = useRouter(); - const { workspaceSlug, projectId } = router.query; + const { workspaceSlug } = router.query; const issueActions = { [EIssueActions.UPDATE]: async (issue: IIssue) => { diff --git a/web/components/issues/peek-overview/root.tsx b/web/components/issues/peek-overview/root.tsx index 51c13d7cc7..c00074af95 100644 --- a/web/components/issues/peek-overview/root.tsx +++ b/web/components/issues/peek-overview/root.tsx @@ -32,7 +32,6 @@ export const IssuePeekOverview: FC = observer((props) => { const { user: { currentProjectRole }, - issue: { removeIssueFromStructure }, issueDetail: { createIssueComment, updateIssueComment, diff --git a/web/components/issues/sub-issues/root.tsx b/web/components/issues/sub-issues/root.tsx index ad17148ea4..c19e809f51 100644 --- a/web/components/issues/sub-issues/root.tsx +++ b/web/components/issues/sub-issues/root.tsx @@ -183,7 +183,7 @@ export const SubIssuesRoot: React.FC = observer((props) => { await removeIssue(workspaceSlug.toString(), projectId.toString(), issue.id); await mutate(SUB_ISSUES(parentIssue?.id)); }, - [removeIssue, projectId, user, workspaceSlug] + [removeIssue, projectId, user, workspaceSlug, parentIssue?.id] ); const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx index 69d6db1d30..a781cfd780 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/pages/[pageId].tsx @@ -82,7 +82,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { description_html: newDescription, }) .then(() => { - mutatePageDetails((prevData) => ({ ...prevData, description_html: newDescription }) as IPage, false); + mutatePageDetails((prevData) => ({ ...prevData, description_html: newDescription } as IPage), false); }); }; @@ -162,15 +162,12 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { }, [pageDetails?.description_html]); // TODO: Verify the exhaustive-deps warning function createObjectFromArray(keys: string[], options: any): any { - return keys.reduce( - (obj, key) => { - if (options[key] !== undefined) { - obj[key] = options[key]; - } - return obj; - }, - {} as { [key: string]: any } - ); + return keys.reduce((obj, key) => { + if (options[key] !== undefined) { + obj[key] = options[key]; + } + return obj; + }, {} as { [key: string]: any }); } const mutatePageDetailsHelper = ( @@ -499,7 +496,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => { projectId={projectId as string} issueId={peekIssueId ? (peekIssueId as string) : ""} isArchived={false} - handleIssue={(issueToUpdate) => { + handleIssue={async (issueToUpdate, action) => { if (peekIssueId && typeof peekIssueId === "string") { handleUpdateIssue(peekIssueId, issueToUpdate); }