fix: issues resolved in sub issues (#2238)

This commit is contained in:
guru_sainath 2023-09-21 19:12:20 +05:30 committed by GitHub
parent 978909c021
commit 73afb8f4d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 264 additions and 189 deletions

View File

@ -43,7 +43,7 @@ export const IssueMainContent: React.FC<Props> = ({
uneditable = false, uneditable = false,
}) => { }) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, issueId, archivedIssueId } = router.query; const { workspaceSlug, projectId, issueId } = router.query;
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
@ -206,7 +206,7 @@ export const IssueMainContent: React.FC<Props> = ({
<IssueReaction workspaceSlug={workspaceSlug} issueId={issueId} projectId={projectId} /> <IssueReaction workspaceSlug={workspaceSlug} issueId={issueId} projectId={projectId} />
<div className="mt-2 space-y-2"> <div className="mt-2 space-y-2">
<SubIssuesRoot parentIssue={issueDetails} user={user} editable={uneditable} /> <SubIssuesRoot parentIssue={issueDetails} user={user} />
</div> </div>
</div> </div>
<div className="flex flex-col gap-3 py-3"> <div className="flex flex-col gap-3 py-3">

View File

@ -16,9 +16,9 @@ import { SubIssuesRootList } from "./issues-list";
import { IssueProperty } from "./properties"; import { IssueProperty } from "./properties";
// ui // ui
import { Tooltip, CustomMenu } from "components/ui"; import { Tooltip, CustomMenu } from "components/ui";
// types // types
import { ICurrentUserResponse, IIssue } from "types"; import { ICurrentUserResponse, IIssue } from "types";
import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root";
export interface ISubIssues { export interface ISubIssues {
workspaceSlug: string; workspaceSlug: string;
@ -29,8 +29,8 @@ export interface ISubIssues {
user: ICurrentUserResponse | undefined; user: ICurrentUserResponse | undefined;
editable: boolean; editable: boolean;
removeIssueFromSubIssues: (parentIssueId: string, issue: IIssue) => void; removeIssueFromSubIssues: (parentIssueId: string, issue: IIssue) => void;
issuesVisibility: string[]; issuesLoader: ISubIssuesRootLoaders;
handleIssuesVisibility: (issueId: string) => void; handleIssuesLoader: ({ key, issueId }: ISubIssuesRootLoadersHandler) => void;
copyText: (text: string) => void; copyText: (text: string) => void;
handleIssueCrudOperation: ( handleIssueCrudOperation: (
key: "create" | "existing" | "edit" | "delete", key: "create" | "existing" | "edit" | "delete",
@ -48,8 +48,8 @@ export const SubIssues: React.FC<ISubIssues> = ({
user, user,
editable, editable,
removeIssueFromSubIssues, removeIssueFromSubIssues,
issuesVisibility, issuesLoader,
handleIssuesVisibility, handleIssuesLoader,
copyText, copyText,
handleIssueCrudOperation, handleIssueCrudOperation,
}) => ( }) => (
@ -62,19 +62,21 @@ export const SubIssues: React.FC<ISubIssues> = ({
<div className="flex-shrink-0 w-[22px] h-[22px]"> <div className="flex-shrink-0 w-[22px] h-[22px]">
{issue?.sub_issues_count > 0 && ( {issue?.sub_issues_count > 0 && (
<> <>
{true ? ( {issuesLoader.sub_issues.includes(issue?.id) ? (
<div className="w-full h-full flex justify-center items-center rounded-sm bg-custom-background-80 transition-all cursor-not-allowed">
<Loader width={14} strokeWidth={2} className="animate-spin" />
</div>
) : (
<div <div
className="w-full h-full flex justify-center items-center rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer" className="w-full h-full flex justify-center items-center rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer"
onClick={() => handleIssuesVisibility(issue?.id)} onClick={() => handleIssuesLoader({ key: "visibility", issueId: issue?.id })}
> >
{issuesVisibility && issuesVisibility.includes(issue?.id) ? ( {issuesLoader && issuesLoader.visibility.includes(issue?.id) ? (
<ChevronDown width={14} strokeWidth={2} /> <ChevronDown width={14} strokeWidth={2} />
) : ( ) : (
<ChevronRight width={14} strokeWidth={2} /> <ChevronRight width={14} strokeWidth={2} />
)} )}
</div> </div>
) : (
<Loader width={14} strokeWidth={2} className="animate-spin" />
)} )}
</> </>
)} )}
@ -92,7 +94,7 @@ export const SubIssues: React.FC<ISubIssues> = ({
{issue.project_detail.identifier}-{issue?.sequence_id} {issue.project_detail.identifier}-{issue?.sequence_id}
</div> </div>
<Tooltip tooltipHeading="Title" tooltipContent={`${issue?.name}`}> <Tooltip tooltipHeading="Title" tooltipContent={`${issue?.name}`}>
<div className="line-clamp-1 text-xs text-custom-text-100">{issue?.name}</div> <div className="line-clamp-1 text-xs text-custom-text-100 pr-2">{issue?.name}</div>
</Tooltip> </Tooltip>
</a> </a>
</Link> </Link>
@ -132,7 +134,11 @@ export const SubIssues: React.FC<ISubIssues> = ({
</CustomMenu.MenuItem> </CustomMenu.MenuItem>
)} )}
<CustomMenu.MenuItem onClick={copyText}> <CustomMenu.MenuItem
onClick={() =>
copyText(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`)
}
>
<div className="flex items-center justify-start gap-2"> <div className="flex items-center justify-start gap-2">
<LinkIcon width={14} strokeWidth={2} /> <LinkIcon width={14} strokeWidth={2} />
<span>Copy issue link</span> <span>Copy issue link</span>
@ -142,17 +148,28 @@ export const SubIssues: React.FC<ISubIssues> = ({
</div> </div>
{editable && ( {editable && (
<div <>
className="flex-shrink-0 invisible group-hover:visible w-[22px] h-[22px] flex justify-center items-center rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer overflow-hidden" {issuesLoader.delete.includes(issue?.id) ? (
onClick={() => removeIssueFromSubIssues(parentIssue?.id, issue)} <div className="flex-shrink-0 w-[22px] h-[22px] rounded-sm bg-red-200/10 text-red-500 transition-all cursor-not-allowed overflow-hidden flex justify-center items-center">
> <Loader width={14} strokeWidth={2} className="animate-spin" />
<X width={14} strokeWidth={2} /> </div>
</div> ) : (
<div
className="flex-shrink-0 invisible group-hover:visible w-[22px] h-[22px] rounded-sm hover:bg-custom-background-80 transition-all cursor-pointer overflow-hidden flex justify-center items-center"
onClick={() => {
handleIssuesLoader({ key: "delete", issueId: issue?.id });
removeIssueFromSubIssues(parentIssue?.id, issue);
}}
>
<X width={14} strokeWidth={2} />
</div>
)}
</>
)} )}
</div> </div>
)} )}
{issuesVisibility.includes(issue?.id) && issue?.sub_issues_count > 0 && ( {issuesLoader.visibility.includes(issue?.id) && issue?.sub_issues_count > 0 && (
<SubIssuesRootList <SubIssuesRootList
workspaceSlug={workspaceSlug} workspaceSlug={workspaceSlug}
projectId={projectId} projectId={projectId}
@ -161,8 +178,8 @@ export const SubIssues: React.FC<ISubIssues> = ({
user={user} user={user}
editable={editable} editable={editable}
removeIssueFromSubIssues={removeIssueFromSubIssues} removeIssueFromSubIssues={removeIssueFromSubIssues}
issuesVisibility={issuesVisibility} issuesLoader={issuesLoader}
handleIssuesVisibility={handleIssuesVisibility} handleIssuesLoader={handleIssuesLoader}
copyText={copyText} copyText={copyText}
handleIssueCrudOperation={handleIssueCrudOperation} handleIssueCrudOperation={handleIssueCrudOperation}
/> />

View File

@ -5,6 +5,7 @@ import useSWR from "swr";
import { SubIssues } from "./issue"; import { SubIssues } from "./issue";
// types // types
import { ICurrentUserResponse, IIssue } from "types"; import { ICurrentUserResponse, IIssue } from "types";
import { ISubIssuesRootLoaders, ISubIssuesRootLoadersHandler } from "./root";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// fetch keys // fetch keys
@ -18,8 +19,8 @@ export interface ISubIssuesRootList {
user: ICurrentUserResponse | undefined; user: ICurrentUserResponse | undefined;
editable: boolean; editable: boolean;
removeIssueFromSubIssues: (parentIssueId: string, issue: IIssue) => void; removeIssueFromSubIssues: (parentIssueId: string, issue: IIssue) => void;
issuesVisibility: string[]; issuesLoader: ISubIssuesRootLoaders;
handleIssuesVisibility: (issueId: string) => void; handleIssuesLoader: ({ key, issueId }: ISubIssuesRootLoadersHandler) => void;
copyText: (text: string) => void; copyText: (text: string) => void;
handleIssueCrudOperation: ( handleIssueCrudOperation: (
key: "create" | "existing" | "edit" | "delete", key: "create" | "existing" | "edit" | "delete",
@ -36,8 +37,8 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
user, user,
editable, editable,
removeIssueFromSubIssues, removeIssueFromSubIssues,
issuesVisibility, issuesLoader,
handleIssuesVisibility, handleIssuesLoader,
copyText, copyText,
handleIssueCrudOperation, handleIssueCrudOperation,
}) => { }) => {
@ -50,6 +51,16 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
: null : null
); );
React.useEffect(() => {
if (isLoading) {
handleIssuesLoader({ key: "sub_issues", issueId: parentIssue?.id });
} else {
if (issuesLoader.sub_issues.includes(parentIssue?.id)) {
handleIssuesLoader({ key: "sub_issues", issueId: parentIssue?.id });
}
}
}, [isLoading]);
return ( return (
<div className="relative"> <div className="relative">
{issues && {issues &&
@ -66,8 +77,8 @@ export const SubIssuesRootList: React.FC<ISubIssuesRootList> = ({
user={user} user={user}
editable={editable} editable={editable}
removeIssueFromSubIssues={removeIssueFromSubIssues} removeIssueFromSubIssues={removeIssueFromSubIssues}
issuesVisibility={issuesVisibility} issuesLoader={issuesLoader}
handleIssuesVisibility={handleIssuesVisibility} handleIssuesLoader={handleIssuesLoader}
copyText={copyText} copyText={copyText}
handleIssueCrudOperation={handleIssueCrudOperation} handleIssueCrudOperation={handleIssueCrudOperation}
/> />

View File

@ -14,7 +14,7 @@ export const ProgressBar = ({ total = 0, done = 0 }: IProgressBar) => {
<div className="w-full"> <div className="w-full">
<div className="w-full rounded-full bg-custom-background-80 overflow-hidden shadow"> <div className="w-full rounded-full bg-custom-background-80 overflow-hidden shadow">
<div <div
className="bg-green-500 h-[6px] rounded-full" className="bg-green-500 h-[6px] rounded-full transition-all"
style={{ width: `${calPercentage(done, total)}%` }} style={{ width: `${calPercentage(done, total)}%` }}
/> />
</div> </div>

View File

@ -86,12 +86,14 @@ export const IssueProperty: React.FC<IIssueProperty> = ({
}; };
const handleAssigneeChange = (data: any) => { const handleAssigneeChange = (data: any) => {
const newData = issue.assignees ?? []; let newData = issue.assignees ?? [];
if (newData.includes(data)) newData.splice(newData.indexOf(data), 1); if (newData && newData.length > 0) {
else newData.push(data); if (newData.includes(data)) newData = newData.splice(newData.indexOf(data), 1);
else newData = [...newData, data];
} else newData = [...newData, data];
partialUpdateIssue({ assignees_list: data }); partialUpdateIssue({ assignees_list: data, assignees: data });
trackEventServices.trackIssuePartialPropertyUpdateEvent( trackEventServices.trackIssuePartialPropertyUpdateEvent(
{ {

View File

@ -14,6 +14,7 @@ import { ProgressBar } from "./progressbar";
import { CustomMenu } from "components/ui"; import { CustomMenu } from "components/ui";
// hooks // hooks
import { useProjectMyMembership } from "contexts/project-member.context"; import { useProjectMyMembership } from "contexts/project-member.context";
import useToast from "hooks/use-toast";
// helpers // helpers
import { copyTextToClipboard } from "helpers/string.helper"; import { copyTextToClipboard } from "helpers/string.helper";
// types // types
@ -25,18 +26,27 @@ import { SUB_ISSUES } from "constants/fetch-keys";
export interface ISubIssuesRoot { export interface ISubIssuesRoot {
parentIssue: IIssue; parentIssue: IIssue;
user: ICurrentUserResponse | undefined; user: ICurrentUserResponse | undefined;
editable: boolean;
} }
export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, editable }) => { export interface ISubIssuesRootLoaders {
visibility: string[];
delete: string[];
sub_issues: string[];
}
export interface ISubIssuesRootLoadersHandler {
key: "visibility" | "delete" | "sub_issues";
issueId: string;
}
export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user }) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string }; const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const { memberRole } = useProjectMyMembership(); const { memberRole } = useProjectMyMembership();
const { setToastAlert } = useToast();
const { data: issues } = useSWR( const { data: issues, isLoading } = useSWR(
workspaceSlug && projectId && parentIssue && parentIssue?.id workspaceSlug && projectId && parentIssue && parentIssue?.id
? SUB_ISSUES(parentIssue?.id) ? SUB_ISSUES(parentIssue?.id)
: null, : null,
@ -45,13 +55,18 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, edi
: null : null
); );
const [issuesVisibility, setIssuesVisibility] = React.useState<string[]>([parentIssue?.id]); const [issuesLoader, setIssuesLoader] = React.useState<ISubIssuesRootLoaders>({
const handleIssuesVisibility = (issueId: string) => { visibility: [parentIssue?.id],
if (issuesVisibility.includes(issueId)) { delete: [],
setIssuesVisibility(issuesVisibility.filter((i: string) => i !== issueId)); sub_issues: [],
} else { });
setIssuesVisibility([...issuesVisibility, issueId]); const handleIssuesLoader = ({ key, issueId }: ISubIssuesRootLoadersHandler) => {
} setIssuesLoader((previousData: ISubIssuesRootLoaders) => ({
...previousData,
[key]: previousData[key].includes(issueId)
? previousData[key].filter((i: string) => i !== issueId)
: [...previousData[key], issueId],
}));
}; };
const [issueCrudOperation, setIssueCrudOperation] = React.useState<{ const [issueCrudOperation, setIssueCrudOperation] = React.useState<{
@ -100,7 +115,6 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, edi
const payload = { const payload = {
sub_issue_ids: data.map((i) => i.id), sub_issue_ids: data.map((i) => i.id),
}; };
await issuesService.addSubIssues(workspaceSlug, projectId, issueId, payload).finally(() => { await issuesService.addSubIssues(workspaceSlug, projectId, issueId, payload).finally(() => {
if (issueId) mutate(SUB_ISSUES(issueId)); if (issueId) mutate(SUB_ISSUES(issueId));
}); });
@ -110,8 +124,22 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, edi
if (!workspaceSlug || !parentIssue || !issue?.id) return; if (!workspaceSlug || !parentIssue || !issue?.id) return;
issuesService issuesService
.patchIssue(workspaceSlug, projectId, issue.id, { parent: null }, user) .patchIssue(workspaceSlug, projectId, issue.id, { parent: null }, user)
.finally(() => { .then(async () => {
if (parentIssueId) mutate(SUB_ISSUES(parentIssueId)); if (parentIssueId) await mutate(SUB_ISSUES(parentIssueId));
handleIssuesLoader({ key: "delete", issueId: issue?.id });
setToastAlert({
type: "success",
title: `Issue removed!`,
message: `Issue removed successfully.`,
});
})
.catch(() => {
handleIssuesLoader({ key: "delete", issueId: issue?.id });
setToastAlert({
type: "warning",
title: `Error!`,
message: `Error, Please try again later.`,
});
}); });
}; };
@ -119,11 +147,11 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, edi
const originURL = const originURL =
typeof window !== "undefined" && window.location.origin ? window.location.origin : ""; typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
copyTextToClipboard(`${originURL}/${text}`).then(() => { copyTextToClipboard(`${originURL}/${text}`).then(() => {
// setToastAlert({ setToastAlert({
// type: "success", type: "success",
// title: "Link Copied!", title: "Link Copied!",
// message: "Issue link copied to clipboard.", message: "Issue link copied to clipboard.",
// }); });
}); });
}; };
@ -135,148 +163,165 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = ({ parentIssue, user, edi
return ( return (
<div className="w-full h-full space-y-2"> <div className="w-full h-full space-y-2">
{parentIssue && parentIssue?.sub_issues_count > 0 ? ( {!issues && isLoading ? (
<div className="py-3 text-center text-sm text-custom-text-300 font-medium">Loading...</div>
) : (
<> <>
{/* header */} {issues && issues?.sub_issues && issues?.sub_issues?.length > 0 ? (
<div className="relative flex items-center gap-4 text-xs"> <>
<div {/* header */}
className="rounded border border-custom-border-100 shadow p-1.5 px-2 flex items-center gap-1 hover:bg-custom-background-80 transition-all cursor-pointer select-none" <div className="relative flex items-center gap-4 text-xs">
onClick={() => handleIssuesVisibility(parentIssue?.id)} <div
> className="rounded border border-custom-border-100 shadow p-1.5 px-2 flex items-center gap-1 hover:bg-custom-background-80 transition-all cursor-pointer select-none"
<div className="flex-shrink-0 w-[16px] h-[16px] flex justify-center items-center"> onClick={() =>
{issuesVisibility.includes(parentIssue?.id) ? ( handleIssuesLoader({ key: "visibility", issueId: parentIssue?.id })
<ChevronDown width={16} strokeWidth={2} /> }
) : ( >
<ChevronRight width={14} strokeWidth={2} /> <div className="flex-shrink-0 w-[16px] h-[16px] flex justify-center items-center">
{issuesLoader.visibility.includes(parentIssue?.id) ? (
<ChevronDown width={16} strokeWidth={2} />
) : (
<ChevronRight width={14} strokeWidth={2} />
)}
</div>
<div>Sub-issues</div>
<div>({issues?.sub_issues?.length || 0})</div>
</div>
<div className="w-full max-w-[250px] select-none">
<ProgressBar
total={issues?.sub_issues?.length || 0}
done={
(issues?.state_distribution?.cancelled || 0) +
(issues?.state_distribution?.completed || 0)
}
/>
</div>
{isEditable && issuesLoader.visibility.includes(parentIssue?.id) && (
<div className="ml-auto flex-shrink-0 flex items-center gap-2 select-none">
<div
className="hover:bg-custom-background-80 transition-all cursor-pointer p-1.5 px-2 rounded border border-custom-border-100 shadow"
onClick={() => handleIssueCrudOperation("create", parentIssue?.id)}
>
Add sub-issue
</div>
<div
className="hover:bg-custom-background-80 transition-all cursor-pointer p-1.5 px-2 rounded border border-custom-border-100 shadow"
onClick={() => handleIssueCrudOperation("existing", parentIssue?.id)}
>
Add an existing issue
</div>
</div>
)} )}
</div> </div>
<div>Sub-issues</div>
<div>({parentIssue?.sub_issues_count})</div>
</div>
<div className="w-full max-w-[250px] select-none"> {/* issues */}
<ProgressBar {issuesLoader.visibility.includes(parentIssue?.id) && (
total={parentIssue?.sub_issues_count} <div className="border border-b-0 border-custom-border-100">
done={ <SubIssuesRootList
(issues?.state_distribution?.cancelled || 0) + workspaceSlug={workspaceSlug}
(issues?.state_distribution?.completed || 0) projectId={projectId}
} parentIssue={parentIssue}
/> user={undefined}
</div> editable={isEditable}
removeIssueFromSubIssues={removeIssueFromSubIssues}
{isEditable && issuesVisibility.includes(parentIssue?.id) && ( issuesLoader={issuesLoader}
<div className="ml-auto flex-shrink-0 flex items-center gap-2 select-none"> handleIssuesLoader={handleIssuesLoader}
<div copyText={copyText}
className="hover:bg-custom-background-80 transition-all cursor-pointer p-1.5 px-2 rounded border border-custom-border-100 shadow" handleIssueCrudOperation={handleIssueCrudOperation}
onClick={() => handleIssueCrudOperation("create", parentIssue?.id)} />
>
Add sub-issue
</div> </div>
<div )}
className="hover:bg-custom-background-80 transition-all cursor-pointer p-1.5 px-2 rounded border border-custom-border-100 shadow"
onClick={() => handleIssueCrudOperation("existing", parentIssue?.id)}
>
Add an existing issue
</div>
</div>
)}
</div>
{/* issues */}
{issuesVisibility.includes(parentIssue?.id) && (
<div className="border border-b-0 border-custom-border-100">
<SubIssuesRootList
workspaceSlug={workspaceSlug}
projectId={projectId}
parentIssue={parentIssue}
user={undefined}
editable={isEditable}
removeIssueFromSubIssues={removeIssueFromSubIssues}
issuesVisibility={issuesVisibility}
handleIssuesVisibility={handleIssuesVisibility}
copyText={copyText}
handleIssueCrudOperation={handleIssueCrudOperation}
/>
</div>
)}
</>
) : (
isEditable && (
<div className="text-xs py-2 text-custom-text-300 font-medium">
<div className="py-3 text-center">No sub issues are available</div>
<>
<CustomMenu
label={
<>
<Plus className="h-3 w-3" />
Add sub-issue
</>
}
buttonClassName="whitespace-nowrap"
position="left"
noBorder
noChevron
>
<CustomMenu.MenuItem
onClick={() => handleIssueCrudOperation("create", parentIssue?.id)}
>
Create new
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
onClick={() => handleIssueCrudOperation("existing", parentIssue?.id)}
>
Add an existing issue
</CustomMenu.MenuItem>
</CustomMenu>
</> </>
</div> ) : (
) isEditable && (
)} <div className="text-xs py-2 text-custom-text-300 font-medium">
<div className="py-3 text-center">No sub issues are available</div>
{isEditable && issueCrudOperation?.create?.toggle && ( <>
<CreateUpdateIssueModal <CustomMenu
isOpen={issueCrudOperation?.create?.toggle} label={
prePopulateData={{ <>
parent: issueCrudOperation?.create?.issueId, <Plus className="h-3 w-3" />
}} Add sub-issue
handleClose={() => handleIssueCrudOperation("create", null)} </>
/> }
)} buttonClassName="whitespace-nowrap"
position="left"
{isEditable && noBorder
issueCrudOperation?.existing?.toggle && noChevron
issueCrudOperation?.existing?.issueId && ( >
<ExistingIssuesListModal <CustomMenu.MenuItem
isOpen={issueCrudOperation?.existing?.toggle} onClick={() => {
handleClose={() => handleIssueCrudOperation("existing", null)} mutateSubIssues(parentIssue?.id);
searchParams={{ sub_issue: true, issue_id: issueCrudOperation?.existing?.issueId }} handleIssueCrudOperation("create", parentIssue?.id);
handleOnSubmit={addAsSubIssueFromExistingIssues} }}
workspaceLevelToggle >
/> Create new
)} </CustomMenu.MenuItem>
<CustomMenu.MenuItem
{isEditable && issueCrudOperation?.edit?.toggle && issueCrudOperation?.edit?.issueId && ( onClick={() => {
<CreateUpdateIssueModal mutateSubIssues(parentIssue?.id);
isOpen={issueCrudOperation?.edit?.toggle} handleIssueCrudOperation("existing", parentIssue?.id);
handleClose={() => { }}
mutateSubIssues(issueCrudOperation?.edit?.issueId); >
handleIssueCrudOperation("edit", null, null); Add an existing issue
}} </CustomMenu.MenuItem>
data={issueCrudOperation?.edit?.issue} </CustomMenu>
/> </>
)} </div>
)
{isEditable && issueCrudOperation?.delete?.toggle && issueCrudOperation?.delete?.issueId && ( )}
<DeleteIssueModal {isEditable && issueCrudOperation?.create?.toggle && (
isOpen={issueCrudOperation?.delete?.toggle} <CreateUpdateIssueModal
handleClose={() => { isOpen={issueCrudOperation?.create?.toggle}
mutateSubIssues(issueCrudOperation?.delete?.issueId); prePopulateData={{
handleIssueCrudOperation("delete", null, null); parent: issueCrudOperation?.create?.issueId,
}} }}
data={issueCrudOperation?.delete?.issue} handleClose={() => {
user={user} mutateSubIssues(issueCrudOperation?.create?.issueId);
redirection={false} handleIssueCrudOperation("create", null);
/> }}
/>
)}
{isEditable &&
issueCrudOperation?.existing?.toggle &&
issueCrudOperation?.existing?.issueId && (
<ExistingIssuesListModal
isOpen={issueCrudOperation?.existing?.toggle}
handleClose={() => handleIssueCrudOperation("existing", null)}
searchParams={{ sub_issue: true, issue_id: issueCrudOperation?.existing?.issueId }}
handleOnSubmit={addAsSubIssueFromExistingIssues}
workspaceLevelToggle
/>
)}
{isEditable && issueCrudOperation?.edit?.toggle && issueCrudOperation?.edit?.issueId && (
<>
<CreateUpdateIssueModal
isOpen={issueCrudOperation?.edit?.toggle}
handleClose={() => {
mutateSubIssues(issueCrudOperation?.edit?.issueId);
handleIssueCrudOperation("edit", null, null);
}}
data={issueCrudOperation?.edit?.issue}
/>
</>
)}
{isEditable &&
issueCrudOperation?.delete?.toggle &&
issueCrudOperation?.delete?.issueId && (
<DeleteIssueModal
isOpen={issueCrudOperation?.delete?.toggle}
handleClose={() => {
mutateSubIssues(issueCrudOperation?.delete?.issueId);
handleIssueCrudOperation("delete", null, null);
}}
data={issueCrudOperation?.delete?.issue}
user={user}
redirection={false}
/>
)}
</>
)} )}
</div> </div>
); );