From 66d07e340b6bb2a0c915434afa64c0dd2d7e748f Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Fri, 31 Mar 2023 02:17:35 +0530 Subject: [PATCH] fix: delete mutations for issues, cycles and modules (#634) --- .../core/list-view/single-issue.tsx | 19 ++-- .../components/cycles/delete-cycle-modal.tsx | 89 ++++++++++++++++--- .../components/issues/delete-issue-modal.tsx | 53 +++++------ .../modules/delete-module-modal.tsx | 43 ++++----- apps/app/hooks/use-issues-view.tsx | 2 +- 5 files changed, 131 insertions(+), 75 deletions(-) diff --git a/apps/app/components/core/list-view/single-issue.tsx b/apps/app/components/core/list-view/single-issue.tsx index 0dc66996c..4da844645 100644 --- a/apps/app/components/core/list-view/single-issue.tsx +++ b/apps/app/components/core/list-view/single-issue.tsx @@ -26,6 +26,7 @@ import { LinkIcon, PencilIcon, TrashIcon, + XMarkIcon, } from "@heroicons/react/24/outline"; // helpers import { copyTextToClipboard, truncateText } from "helpers/string.helper"; @@ -38,6 +39,7 @@ import { MODULE_ISSUES_WITH_PARAMS, PROJECT_ISSUES_LIST_WITH_PARAMS, } from "constants/fetch-keys"; +import { DIVIDER } from "@blueprintjs/core/lib/esm/common/classes"; type Props = { type?: string; @@ -258,27 +260,30 @@ export const SingleListIssue: React.FC = ({ {type && !isNotAllowed && ( - +
Edit issue - +
{type !== "issue" && removeIssue && ( - <>Remove from {type} +
+ + Remove from {type} +
)} handleDeleteIssue(issue)}> - +
Delete issue - +
- +
Copy issue link - +
)} diff --git a/apps/app/components/cycles/delete-cycle-modal.tsx b/apps/app/components/cycles/delete-cycle-modal.tsx index 4464c54d9..c43d34d68 100644 --- a/apps/app/components/cycles/delete-cycle-modal.tsx +++ b/apps/app/components/cycles/delete-cycle-modal.tsx @@ -14,14 +14,25 @@ import { DangerButton, SecondaryButton } from "components/ui"; // icons import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; // types -import type { ICycle } from "types"; +import type { + CompletedCyclesResponse, + CurrentAndUpcomingCyclesResponse, + DraftCyclesResponse, + ICycle, +} from "types"; type TConfirmCycleDeletionProps = { isOpen: boolean; setIsOpen: React.Dispatch>; data?: ICycle; }; // fetch-keys -import { CYCLE_LIST } from "constants/fetch-keys"; +import { + CYCLE_COMPLETE_LIST, + CYCLE_CURRENT_AND_UPCOMING_LIST, + CYCLE_DRAFT_LIST, + CYCLE_LIST, +} from "constants/fetch-keys"; +import { getDateRangeStatus } from "helpers/date-time.helper"; export const DeleteCycleModal: React.FC = ({ isOpen, @@ -31,7 +42,7 @@ export const DeleteCycleModal: React.FC = ({ const [isDeleteLoading, setIsDeleteLoading] = useState(false); const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, projectId } = router.query; const { setToastAlert } = useToast(); @@ -41,16 +52,68 @@ export const DeleteCycleModal: React.FC = ({ }; const handleDeletion = async () => { - setIsDeleteLoading(true); if (!data || !workspaceSlug) return; + + setIsDeleteLoading(true); + await cycleService .deleteCycle(workspaceSlug as string, data.project, data.id) .then(() => { - mutate( - CYCLE_LIST(data.project), - (prevData) => prevData?.filter((cycle) => cycle.id !== data?.id), - false - ); + switch (getDateRangeStatus(data.start_date, data.end_date)) { + case "completed": + mutate( + CYCLE_COMPLETE_LIST(projectId as string), + (prevData) => { + if (!prevData) return; + + return { + completed_cycles: prevData.completed_cycles?.filter( + (cycle) => cycle.id !== data?.id + ), + }; + }, + false + ); + break; + case "current": + mutate( + CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), + (prevData) => { + if (!prevData) return; + return { + current_cycle: prevData.current_cycle?.filter((c) => c.id !== data?.id), + upcoming_cycle: prevData.upcoming_cycle, + }; + }, + false + ); + break; + case "upcoming": + mutate( + CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string), + (prevData) => { + if (!prevData) return; + + return { + current_cycle: prevData.current_cycle, + upcoming_cycle: prevData.upcoming_cycle?.filter((c) => c.id !== data?.id), + }; + }, + false + ); + break; + default: + mutate( + CYCLE_DRAFT_LIST(projectId as string), + (prevData) => { + if (!prevData) return; + return { + draft_cycles: prevData.draft_cycles?.filter((cycle) => cycle.id !== data?.id), + }; + }, + false + ); + } handleClose(); setToastAlert({ @@ -59,8 +122,7 @@ export const DeleteCycleModal: React.FC = ({ message: "Cycle deleted successfully", }); }) - .catch((error) => { - console.log(error); + .catch(() => { setIsDeleteLoading(false); }); }; @@ -107,9 +169,8 @@ export const DeleteCycleModal: React.FC = ({

Are you sure you want to delete cycle-{" "} - {data?.name} - ? All of the data related to the cycle will be permanently removed. - This action cannot be undone. + {data?.name}? All of the data related + to the cycle will be permanently removed. This action cannot be undone.

diff --git a/apps/app/components/issues/delete-issue-modal.tsx b/apps/app/components/issues/delete-issue-modal.tsx index 0027e6d83..e161e52a1 100644 --- a/apps/app/components/issues/delete-issue-modal.tsx +++ b/apps/app/components/issues/delete-issue-modal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useState } from "react"; import { useRouter } from "next/router"; @@ -17,7 +17,15 @@ import { SecondaryButton, DangerButton } from "components/ui"; // types import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types"; // fetch-keys -import { CYCLE_ISSUES, PROJECT_ISSUES_LIST, MODULE_ISSUES, USER_ISSUE } from "constants/fetch-keys"; +import { + CYCLE_ISSUES, + CYCLE_ISSUES_WITH_PARAMS, + MODULE_ISSUES, + MODULE_ISSUES_WITH_PARAMS, + PROJECT_ISSUES_LIST_WITH_PARAMS, + USER_ISSUE, +} from "constants/fetch-keys"; +import useIssuesView from "hooks/use-issues-view"; type Props = { isOpen: boolean; @@ -29,7 +37,9 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data }) const [isDeleteLoading, setIsDeleteLoading] = useState(false); const router = useRouter(); - const { workspaceSlug, projectId: queryProjectId } = router.query; + const { workspaceSlug, projectId, cycleId, moduleId } = router.query; + + const { params } = useIssuesView(); const { setToastAlert } = useToast(); @@ -44,37 +54,14 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data }) const handleDeletion = async () => { setIsDeleteLoading(true); - if (!data || !workspaceSlug) return; + if (!workspaceSlug || !projectId || !data) return; - const projectId = data.project; await issueServices - .deleteIssue(workspaceSlug as string, projectId, data.id) + .deleteIssue(workspaceSlug as string, projectId as string, data.id) .then(() => { - const cycleId = data?.cycle; - const moduleId = data?.module; - - if (cycleId) { - mutate( - CYCLE_ISSUES(cycleId), - (prevData) => prevData?.filter((i) => i.issue !== data.id), - false - ); - } - - if (moduleId) { - mutate( - MODULE_ISSUES(moduleId), - (prevData) => prevData?.filter((i) => i.issue !== data.id), - false - ); - } - - if (!queryProjectId) - mutate( - USER_ISSUE(workspaceSlug as string), - (prevData) => prevData?.filter((i) => i.id !== data.id), - false - ); + if (cycleId) mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params)); + else if (moduleId) mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params)); + else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(projectId as string, params)); handleClose(); setToastAlert({ @@ -133,8 +120,8 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data }) Are you sure you want to delete issue{" "} {data?.project_detail.identifier}-{data?.sequence_id} - {""} - ? All of the data related to the issue will be permanently removed. This + + {""}? All of the data related to the issue will be permanently removed. This action cannot be undone.

diff --git a/apps/app/components/modules/delete-module-modal.tsx b/apps/app/components/modules/delete-module-modal.tsx index 97663b6b9..70fca1916 100644 --- a/apps/app/components/modules/delete-module-modal.tsx +++ b/apps/app/components/modules/delete-module-modal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useState } from "react"; import { useRouter } from "next/router"; @@ -29,7 +29,7 @@ export const DeleteModuleModal: React.FC = ({ isOpen, setIsOpen, data }) const [isDeleteLoading, setIsDeleteLoading] = useState(false); const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, projectId, moduleId } = router.query; const { setToastAlert } = useToast(); @@ -41,22 +41,26 @@ export const DeleteModuleModal: React.FC = ({ isOpen, setIsOpen, data }) const handleDeletion = async () => { setIsDeleteLoading(true); - if (!workspaceSlug || !data) return; - await modulesService - .deleteModule(workspaceSlug as string, data.project, data.id) - .then(() => { - mutate(MODULE_LIST(data.project)); - router.push(`/${workspaceSlug}/projects/${data.project}/modules`); - handleClose(); + if (!workspaceSlug || !projectId || !data) return; - setToastAlert({ - title: "Success", - type: "success", - message: "Module deleted successfully", - }); + mutate( + MODULE_LIST(projectId as string), + (prevData) => prevData?.filter((m) => m.id !== data.id), + false + ); + + await modulesService + .deleteModule(workspaceSlug as string, projectId as string, data.id) + .then(() => { + if (moduleId) router.push(`/${workspaceSlug}/projects/${data.project}/modules`); + handleClose(); }) - .catch((error) => { - console.log(error); + .catch(() => { + setToastAlert({ + type: "error", + title: "Error!", + message: "Module could not be deleted. Please try again.", + }); setIsDeleteLoading(false); }); }; @@ -102,10 +106,9 @@ export const DeleteModuleModal: React.FC = ({ isOpen, setIsOpen, data })

- Are you sure you want to delete module- {" "} - {data?.name} - ? All of the data related to the module will be permanently removed. - This action cannot be undone. + Are you sure you want to delete module-{" "} + {data?.name}? All of the data related + to the module will be permanently removed. This action cannot be undone.

diff --git a/apps/app/hooks/use-issues-view.tsx b/apps/app/hooks/use-issues-view.tsx index 789123c58..92e2d695c 100644 --- a/apps/app/hooks/use-issues-view.tsx +++ b/apps/app/hooks/use-issues-view.tsx @@ -36,7 +36,7 @@ const useIssuesView = () => { setFilters, resetFilterToDefault, setNewFilterDefaultView, - setIssueView + setIssueView, } = useContext(issueViewContext); const router = useRouter();