fix: new project issues response (#303)

This commit is contained in:
Aaryan Khandelwal 2023-02-18 21:19:04 +05:30 committed by GitHub
parent 393638c700
commit 77c319c748
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 105 additions and 141 deletions

View File

@ -43,10 +43,13 @@ export const BoardHeader: React.FC<Props> = ({
let assignees: any; let assignees: any;
if (selectedGroup === "assignees") { if (selectedGroup === "assignees") {
assignees = groupTitle.split(","); assignees = groupTitle && groupTitle !== "" ? groupTitle.split(",") : [];
assignees = assignees assignees =
.map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name) assignees.length > 0
.join(", "); ? assignees
.map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name)
.join(", ")
: "No assignee";
} }
return ( return (

View File

@ -12,10 +12,10 @@ import {
DraggingStyle, DraggingStyle,
NotDraggingStyle, NotDraggingStyle,
} from "react-beautiful-dnd"; } from "react-beautiful-dnd";
// constants
import { TrashIcon } from "@heroicons/react/24/outline";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// hooks
import useToast from "hooks/use-toast";
// components // components
import { import {
ViewAssigneeSelect, ViewAssigneeSelect,
@ -25,11 +25,12 @@ import {
} from "components/issues/view-select"; } from "components/issues/view-select";
// ui // ui
import { CustomMenu } from "components/ui"; import { CustomMenu } from "components/ui";
// helpers
import { copyTextToClipboard } from "helpers/string.helper";
// types // types
import { import {
CycleIssueResponse, CycleIssueResponse,
IIssue, IIssue,
IssueResponse,
ModuleIssueResponse, ModuleIssueResponse,
NestedKeyOf, NestedKeyOf,
Properties, Properties,
@ -37,8 +38,6 @@ import {
} from "types"; } from "types";
// fetch-keys // fetch-keys
import { CYCLE_ISSUES, MODULE_ISSUES, PROJECT_ISSUES_LIST } from "constants/fetch-keys"; import { CYCLE_ISSUES, MODULE_ISSUES, PROJECT_ISSUES_LIST } from "constants/fetch-keys";
import { copyTextToClipboard } from "helpers/string.helper";
import useToast from "hooks/use-toast";
type Props = { type Props = {
type?: string; type?: string;
@ -71,7 +70,9 @@ export const SingleBoardIssue: React.FC<Props> = ({
}) => { }) => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query; const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const partialUpdateIssue = useCallback( const partialUpdateIssue = useCallback(
(formData: Partial<IIssue>) => { (formData: Partial<IIssue>) => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
@ -118,15 +119,15 @@ export const SingleBoardIssue: React.FC<Props> = ({
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((p) => {
results: (prevData?.results ?? []).map((p) => {
if (p.id === issue.id) return { ...p, ...formData }; if (p.id === issue.id) return { ...p, ...formData };
return p; return p;
}), }),
}),
false false
); );

View File

@ -18,7 +18,7 @@ import { Button } from "components/ui";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline"; import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { LayerDiagonalIcon } from "components/icons"; import { LayerDiagonalIcon } from "components/icons";
// types // types
import { IIssue, IssueResponse } from "types"; import { IIssue } from "types";
// fetch keys // fetch keys
import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; import { PROJECT_ISSUES_LIST } from "constants/fetch-keys";
@ -62,8 +62,8 @@ export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) =>
const filteredIssues: IIssue[] = const filteredIssues: IIssue[] =
query === "" query === ""
? issues?.results ?? [] ? issues ?? []
: issues?.results.filter( : issues?.filter(
(issue) => (issue) =>
issue.name.toLowerCase().includes(query.toLowerCase()) || issue.name.toLowerCase().includes(query.toLowerCase()) ||
`${issue.project_detail.identifier}-${issue.sequence_id}` `${issue.project_detail.identifier}-${issue.sequence_id}`
@ -101,17 +101,9 @@ export const BulkDeleteIssuesModal: React.FC<Props> = ({ isOpen, setIsOpen }) =>
message: res.message, message: res.message,
}); });
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => ({ (prevData) => (prevData ?? []).filter((p) => !data.delete_issue_ids.includes(p.id)),
...(prevData as IssueResponse),
count: (prevData?.results ?? []).filter(
(p) => !data.delete_issue_ids.some((id) => p.id === id)
).length,
results: (prevData?.results ?? []).filter(
(p) => !data.delete_issue_ids.some((id) => p.id === id)
),
}),
false false
); );
handleClose(); handleClose();

View File

@ -103,7 +103,7 @@ export const ExistingIssuesListModal: React.FC<Props> = ({
leaveFrom="opacity-100 scale-100" leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95" leaveTo="opacity-0 scale-95"
> >
<Dialog.Panel className="relative mx-auto max-w-2xl transform divide-y divide-gray-500 divide-opacity-10 rounded-xl bg-white bg-opacity-80 shadow-2xl ring-1 ring-black ring-opacity-5 backdrop-blur backdrop-filter transition-all"> <Dialog.Panel className="relative mx-auto max-w-2xl transform divide-y divide-gray-500 divide-opacity-10 rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 transition-all">
<form> <form>
<Controller <Controller
control={control} control={control}

View File

@ -22,7 +22,7 @@ import { TrashIcon } from "@heroicons/react/24/outline";
// helpers // helpers
import { getStatesList } from "helpers/state.helper"; import { getStatesList } from "helpers/state.helper";
// types // types
import { CycleIssueResponse, IIssue, IssueResponse, ModuleIssueResponse, UserAuth } from "types"; import { CycleIssueResponse, IIssue, ModuleIssueResponse, UserAuth } from "types";
// fetch-keys // fetch-keys
import { import {
CYCLE_ISSUES, CYCLE_ISSUES,
@ -159,12 +159,12 @@ export const IssuesView: React.FC<Props> = ({
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => { (prevData) => {
if (!prevData) return prevData; if (!prevData) return prevData;
const updatedIssues = prevData.results.map((issue) => { const updatedIssues = prevData.map((issue) => {
if (issue.id === draggedItem.id) if (issue.id === draggedItem.id)
return { return {
...draggedItem, ...draggedItem,
@ -174,10 +174,7 @@ export const IssuesView: React.FC<Props> = ({
return issue; return issue;
}); });
return { return updatedIssues;
...prevData,
results: updatedIssues,
};
}, },
false false
); );
@ -248,12 +245,12 @@ export const IssuesView: React.FC<Props> = ({
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => { (prevData) => {
if (!prevData) return prevData; if (!prevData) return prevData;
const updatedIssues = prevData.results.map((issue) => { const updatedIssues = prevData.map((issue) => {
if (issue.id === draggedItem.id) if (issue.id === draggedItem.id)
return { return {
...draggedItem, ...draggedItem,
@ -264,10 +261,7 @@ export const IssuesView: React.FC<Props> = ({
return issue; return issue;
}); });
return { return updatedIssues;
...prevData,
results: updatedIssues,
};
}, },
false false
); );

View File

@ -7,6 +7,8 @@ import { mutate } from "swr";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
// hooks
import useToast from "hooks/use-toast";
// components // components
import { import {
ViewAssigneeSelect, ViewAssigneeSelect,
@ -16,19 +18,12 @@ import {
} from "components/issues/view-select"; } from "components/issues/view-select";
// ui // ui
import { CustomMenu } from "components/ui"; import { CustomMenu } from "components/ui";
// types // helpers
import {
CycleIssueResponse,
IIssue,
IssueResponse,
ModuleIssueResponse,
Properties,
UserAuth,
} from "types";
// fetch-keys
import { CYCLE_ISSUES, MODULE_ISSUES, PROJECT_ISSUES_LIST, STATE_LIST } from "constants/fetch-keys";
import { copyTextToClipboard } from "helpers/string.helper"; import { copyTextToClipboard } from "helpers/string.helper";
import useToast from "hooks/use-toast"; // types
import { CycleIssueResponse, IIssue, ModuleIssueResponse, Properties, UserAuth } from "types";
// fetch-keys
import { CYCLE_ISSUES, MODULE_ISSUES, PROJECT_ISSUES_LIST } from "constants/fetch-keys";
type Props = { type Props = {
type?: string; type?: string;
@ -98,15 +93,15 @@ export const SingleListIssue: React.FC<Props> = ({
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((p) => {
results: (prevData?.results ?? []).map((p) => {
if (p.id === issue.id) return { ...p, ...formData }; if (p.id === issue.id) return { ...p, ...formData };
return p; return p;
}), }),
}),
false false
); );

View File

@ -55,10 +55,13 @@ export const SingleList: React.FC<Props> = ({
let assignees: any; let assignees: any;
if (selectedGroup === "assignees") { if (selectedGroup === "assignees") {
assignees = groupTitle.split(","); assignees = groupTitle && groupTitle !== "" ? groupTitle.split(",") : [];
assignees = assignees assignees =
.map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name) assignees.length > 0
.join(", "); ? assignees
.map((a: string) => members?.find((m) => m.member.id === a)?.member.first_name)
.join(", ")
: "No assignee";
} }
return ( return (

View File

@ -15,7 +15,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// ui // ui
import { Button } from "components/ui"; import { Button } from "components/ui";
// types // types
import type { CycleIssueResponse, IIssue, IssueResponse, ModuleIssueResponse } from "types"; import type { CycleIssueResponse, IIssue, ModuleIssueResponse } from "types";
// fetch-keys // fetch-keys
import { CYCLE_ISSUES, PROJECT_ISSUES_LIST, MODULE_ISSUES, USER_ISSUE } from "constants/fetch-keys"; import { CYCLE_ISSUES, PROJECT_ISSUES_LIST, MODULE_ISSUES, USER_ISSUE } from "constants/fetch-keys";
@ -77,13 +77,9 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data })
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId),
(prevData) => ({ (prevData) => (prevData ?? []).filter((i) => i.id !== data.id),
...(prevData as IssueResponse),
results: prevData?.results.filter((i) => i.id !== data.id) ?? [],
count: (prevData?.count as number) - 1,
}),
false false
); );

View File

@ -16,7 +16,7 @@ import useToast from "hooks/use-toast";
// components // components
import { IssueForm } from "components/issues"; import { IssueForm } from "components/issues";
// types // types
import type { IIssue, IssueResponse } from "types"; import type { IIssue } from "types";
// fetch keys // fetch keys
import { import {
PROJECT_ISSUES_DETAILS, PROJECT_ISSUES_DETAILS,
@ -91,15 +91,13 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
false false
); );
} else } else
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""), PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((i) => {
results: (prevData?.results ?? []).map((issue) => { if (i.id === res.id) return { ...i, sprints: cycleId };
if (issue.id === res.id) return { ...issue, sprints: cycleId }; return i;
return issue;
}), }),
}),
false false
); );
}) })
@ -126,7 +124,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
await issuesService await issuesService
.createIssues(workspaceSlug as string, activeProject ?? "", payload) .createIssues(workspaceSlug as string, activeProject ?? "", payload)
.then((res) => { .then((res) => {
mutate<IssueResponse>(PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? "")); mutate(PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""));
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle); if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module); if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
@ -159,15 +157,13 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
if (isUpdatingSingleIssue) { if (isUpdatingSingleIssue) {
mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false); mutate<IIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
} else { } else {
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""), PROJECT_ISSUES_LIST(workspaceSlug as string, activeProject ?? ""),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((i) => {
results: (prevData?.results ?? []).map((issue) => { if (i.id === res.id) return { ...i, ...res };
if (issue.id === res.id) return { ...issue, ...res }; return i;
return issue; })
}),
})
); );
} }
@ -232,7 +228,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
> >
<Dialog.Panel className="relative transform rounded-lg bg-white p-5 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl"> <Dialog.Panel className="relative transform rounded-lg bg-white p-5 text-left shadow-xl transition-all sm:w-full sm:max-w-2xl">
<IssueForm <IssueForm
issues={issues?.results ?? []} issues={issues ?? []}
handleFormSubmit={handleFormSubmit} handleFormSubmit={handleFormSubmit}
initialData={prePopulateData} initialData={prePopulateData}
createMore={createMore} createMore={createMore}

View File

@ -127,14 +127,14 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
> >
<Link <Link
href={`/${workspaceSlug}/projects/${projectId}/issues/${ href={`/${workspaceSlug}/projects/${projectId}/issues/${
issues?.results.find((i) => i.id === issue)?.id issues?.find((i) => i.id === issue)?.id
}`} }`}
> >
<a className="flex items-center gap-1"> <a className="flex items-center gap-1">
<BlockedIcon height={10} width={10} /> <BlockedIcon height={10} width={10} />
{`${ {`${issues?.find((i) => i.id === issue)?.project_detail?.identifier}-${
issues?.results.find((i) => i.id === issue)?.project_detail?.identifier issues?.find((i) => i.id === issue)?.sequence_id
}-${issues?.results.find((i) => i.id === issue)?.sequence_id}`} }`}
</a> </a>
</Link> </Link>
<span className="opacity-0 duration-300 group-hover:opacity-100"> <span className="opacity-0 duration-300 group-hover:opacity-100">
@ -243,8 +243,8 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
/> />
<span className="flex-shrink-0 text-xs text-gray-500"> <span className="flex-shrink-0 text-xs text-gray-500">
{ {
issues?.results.find((i) => i.id === issue.id) issues?.find((i) => i.id === issue.id)?.project_detail
?.project_detail?.identifier ?.identifier
} }
-{issue.sequence_id} -{issue.sequence_id}
</span> </span>

View File

@ -119,14 +119,14 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
> >
<Link <Link
href={`/${workspaceSlug}/projects/${projectId}/issues/${ href={`/${workspaceSlug}/projects/${projectId}/issues/${
issues?.results.find((i) => i.id === issue)?.id issues?.find((i) => i.id === issue)?.id
}`} }`}
> >
<a className="flex items-center gap-1"> <a className="flex items-center gap-1">
<BlockerIcon height={10} width={10} /> <BlockerIcon height={10} width={10} />
{`${ {`${issues?.find((i) => i.id === issue)?.project_detail?.identifier}-${
issues?.results.find((i) => i.id === issue)?.project_detail?.identifier issues?.find((i) => i.id === issue)?.sequence_id
}-${issues?.results.find((i) => i.id === issue)?.sequence_id}`} }`}
</a> </a>
</Link> </Link>
<span <span
@ -244,8 +244,8 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
/> />
<span className="flex-shrink-0 text-xs text-gray-500"> <span className="flex-shrink-0 text-xs text-gray-500">
{ {
issues?.results.find((i) => i.id === issue.id) issues?.find((i) => i.id === issue.id)?.project_detail
?.project_detail?.identifier ?.identifier
} }
-{issue.sequence_id} -{issue.sequence_id}
</span> </span>

View File

@ -84,9 +84,9 @@ export const SidebarParentSelect: React.FC<Props> = ({
disabled={isNotAllowed} disabled={isNotAllowed}
> >
{watch("parent") && watch("parent") !== "" {watch("parent") && watch("parent") !== ""
? `${ ? `${issues?.find((i) => i.id === watch("parent"))?.project_detail?.identifier}-${
issues?.results.find((i) => i.id === watch("parent"))?.project_detail?.identifier issues?.find((i) => i.id === watch("parent"))?.sequence_id
}-${issues?.results.find((i) => i.id === watch("parent"))?.sequence_id}` }`
: "Select issue"} : "Select issue"}
</button> </button>
</div> </div>

View File

@ -222,7 +222,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
control={control} control={control}
submitChanges={submitChanges} submitChanges={submitChanges}
issuesList={ issuesList={
issues?.results.filter( issues?.filter(
(i) => (i) =>
i.id !== issueDetail?.id && i.id !== issueDetail?.id &&
i.id !== issueDetail?.parent && i.id !== issueDetail?.parent &&
@ -250,13 +250,13 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
/> />
<SidebarBlockerSelect <SidebarBlockerSelect
submitChanges={submitChanges} submitChanges={submitChanges}
issuesList={issues?.results.filter((i) => i.id !== issueDetail?.id) ?? []} issuesList={issues?.filter((i) => i.id !== issueDetail?.id) ?? []}
watch={watchIssue} watch={watchIssue}
userAuth={userAuth} userAuth={userAuth}
/> />
<SidebarBlockedSelect <SidebarBlockedSelect
submitChanges={submitChanges} submitChanges={submitChanges}
issuesList={issues?.results.filter((i) => i.id !== issueDetail?.id) ?? []} issuesList={issues?.filter((i) => i.id !== issueDetail?.id) ?? []}
watch={watchIssue} watch={watchIssue}
userAuth={userAuth} userAuth={userAuth}
/> />

View File

@ -19,7 +19,7 @@ import { ChevronRightIcon, PlusIcon, XMarkIcon } from "@heroicons/react/24/outli
// helpers // helpers
import { orderArrayBy } from "helpers/array.helper"; import { orderArrayBy } from "helpers/array.helper";
// types // types
import { IIssue, IssueResponse, UserAuth } from "types"; import { IIssue, UserAuth } from "types";
// fetch-keys // fetch-keys
import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys"; import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys";
@ -68,7 +68,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
let newSubIssues = [...(prevData as IIssue[])]; let newSubIssues = [...(prevData as IIssue[])];
data.issues.forEach((issueId: string) => { data.issues.forEach((issueId: string) => {
const issue = issues?.results.find((i) => i.id === issueId); const issue = issues?.find((i) => i.id === issueId);
if (issue) newSubIssues.push(issue); if (issue) newSubIssues.push(issue);
}); });
@ -80,11 +80,10 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
false false
); );
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((p) => {
results: (prevData?.results ?? []).map((p) => {
if (data.issues.includes(p.id)) if (data.issues.includes(p.id))
return { return {
...p, ...p,
@ -93,7 +92,6 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
return p; return p;
}), }),
}),
false false
); );
@ -118,11 +116,10 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
.then((res) => { .then((res) => {
mutate(SUB_ISSUES(parentIssue.id ?? "")); mutate(SUB_ISSUES(parentIssue.id ?? ""));
mutate<IssueResponse>( mutate<IIssue[]>(
PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string),
(prevData) => ({ (prevData) =>
...(prevData as IssueResponse), (prevData ?? []).map((p) => {
results: (prevData?.results ?? []).map((p) => {
if (p.id === res.id) if (p.id === res.id)
return { return {
...p, ...p,
@ -131,7 +128,6 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
return p; return p;
}), }),
}),
false false
); );
}) })
@ -160,7 +156,7 @@ export const SubIssuesList: FC<Props> = ({ parentIssue, userAuth }) => {
isOpen={subIssuesListModal} isOpen={subIssuesListModal}
handleClose={() => setSubIssuesListModal(false)} handleClose={() => setSubIssuesListModal(false)}
issues={ issues={
issues?.results.filter( issues?.filter(
(i) => (i) =>
(i.parent === "" || i.parent === null) && (i.parent === "" || i.parent === null) &&
i.id !== parentIssue?.id && i.id !== parentIssue?.id &&

View File

@ -8,6 +8,8 @@ import { useRouter } from "next/router";
import useSWR from "swr"; import useSWR from "swr";
// services // services
import cyclesService from "services/cycles.service"; import cyclesService from "services/cycles.service";
// hooks
import useToast from "hooks/use-toast";
// ui // ui
import { Button, CustomMenu } from "components/ui"; import { Button, CustomMenu } from "components/ui";
// icons // icons
@ -17,12 +19,11 @@ import { CyclesIcon } from "components/icons";
// helpers // helpers
import { renderShortNumericDateFormat } from "helpers/date-time.helper"; import { renderShortNumericDateFormat } from "helpers/date-time.helper";
import { groupBy } from "helpers/array.helper"; import { groupBy } from "helpers/array.helper";
import { copyTextToClipboard } from "helpers/string.helper";
// types // types
import { CycleIssueResponse, ICycle } from "types"; import { CycleIssueResponse, ICycle } from "types";
// fetch-keys // fetch-keys
import { CYCLE_ISSUES } from "constants/fetch-keys"; import { CYCLE_ISSUES } from "constants/fetch-keys";
import { copyTextToClipboard } from "helpers/string.helper";
import useToast from "hooks/use-toast";
type TSingleStatProps = { type TSingleStatProps = {
cycle: ICycle; cycle: ICycle;

View File

@ -74,7 +74,7 @@ export const DeleteStateModal: React.FC<Props> = ({ isOpen, onClose, data }) =>
}); });
}; };
const groupedIssues = groupBy(issues?.results ?? [], "state"); const groupedIssues = groupBy(issues ?? [], "state");
useEffect(() => { useEffect(() => {
if (data) setIssuesWithThisStateExist(!!groupedIssues[data.id]); if (data) setIssuesWithThisStateExist(!!groupedIssues[data.id]);

View File

@ -118,7 +118,7 @@ const SingleCycle: React.FC<UserAuth> = (props) => {
<ExistingIssuesListModal <ExistingIssuesListModal
isOpen={cycleIssuesListModal} isOpen={cycleIssuesListModal}
handleClose={() => setCycleIssuesListModal(false)} handleClose={() => setCycleIssuesListModal(false)}
issues={issues?.results.filter((i) => !i.issue_cycle) ?? []} issues={issues?.filter((i) => !i.issue_cycle) ?? []}
handleOnSubmit={handleAddIssuesToCycle} handleOnSubmit={handleAddIssuesToCycle}
/> />
<AppLayout <AppLayout

View File

@ -55,9 +55,7 @@ const ProjectIssues: NextPage<UserAuth> = (props) => {
} }
right={ right={
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<IssuesFilterView <IssuesFilterView issues={projectIssues?.filter((p) => p.parent === null) ?? []} />
issues={projectIssues?.results.filter((p) => p.parent === null) ?? []}
/>
<HeaderButton <HeaderButton
Icon={PlusIcon} Icon={PlusIcon}
label="Add Issue" label="Add Issue"
@ -72,9 +70,9 @@ const ProjectIssues: NextPage<UserAuth> = (props) => {
} }
> >
{projectIssues ? ( {projectIssues ? (
projectIssues.count > 0 ? ( projectIssues.length > 0 ? (
<IssuesView <IssuesView
issues={projectIssues?.results.filter((p) => p.parent === null) ?? []} issues={projectIssues?.filter((p) => p.parent === null) ?? []}
userAuth={props} userAuth={props}
/> />
) : ( ) : (

View File

@ -113,7 +113,7 @@ const SingleModule: React.FC<UserAuth> = (props) => {
<ExistingIssuesListModal <ExistingIssuesListModal
isOpen={moduleIssuesListModal} isOpen={moduleIssuesListModal}
handleClose={() => setModuleIssuesListModal(false)} handleClose={() => setModuleIssuesListModal(false)}
issues={issues?.results.filter((i) => !i.issue_module) ?? []} issues={issues?.filter((i) => !i.issue_module) ?? []}
handleOnSubmit={handleAddIssuesToModule} handleOnSubmit={handleAddIssuesToModule}
/> />
<AppLayout <AppLayout

View File

@ -1,7 +1,7 @@
// services // services
import APIService from "services/api.service"; import APIService from "services/api.service";
// type // type
import type { IIssue, IIssueActivity, IIssueComment, IssueResponse } from "types"; import type { IIssue, IIssueActivity, IIssueComment } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env; const { NEXT_PUBLIC_API_BASE_URL } = process.env;
@ -18,7 +18,7 @@ class ProjectIssuesServices extends APIService {
}); });
} }
async getIssues(workspaceSlug: string, projectId: string): Promise<IssueResponse> { async getIssues(workspaceSlug: string, projectId: string): Promise<IIssue[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`)
.then((response) => response?.data) .then((response) => response?.data)
.catch((error) => { .catch((error) => {

View File

@ -1,16 +1,5 @@
import type { IState, IUser, IProject, ICycle, IModule, IUserLite } from "./"; import type { IState, IUser, IProject, ICycle, IModule, IUserLite } from "./";
export interface IssueResponse {
next_cursor: string;
prev_cursor: string;
next_page_results: boolean;
prev_page_results: boolean;
count: number;
total_pages: number;
extra_stats: null;
results: IIssue[];
}
export interface IIssueCycle { export interface IIssueCycle {
id: string; id: string;
cycle_detail: ICycle; cycle_detail: ICycle;