feat: search endpoint (#1317)

* feat: search endpoint for parent issue selection

* feat: blocker and blocked by search endpoint

* refactor: blocker and blocked by components and types

* refactor: blocker and blocked by components, feeat: cycle and module new search endpoints

* chore: sub-issues param change

* style: show selected issues list
This commit is contained in:
Aaryan Khandelwal 2023-06-23 13:18:38 +05:30 committed by GitHub
parent 62392be5a3
commit 41b7544cfc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 584 additions and 880 deletions

View file

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
import useSWR from "swr";
// icons
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
import { CyclesIcon } from "components/icons";
@ -16,7 +16,6 @@ import { CycleDetailsSidebar } from "components/cycles";
// services
import issuesService from "services/issues.service";
import cycleServices from "services/cycles.service";
import projectService from "services/project.service";
// hooks
import useToast from "hooks/use-toast";
import useUserAuth from "hooks/use-user-auth";
@ -28,14 +27,10 @@ import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// helpers
import { truncateText } from "helpers/string.helper";
import { getDateRangeStatus } from "helpers/date-time.helper";
// types
import { ISearchIssueResponse } from "types";
// fetch-keys
import {
CYCLE_ISSUES,
CYCLES_LIST,
PROJECT_DETAILS,
CYCLE_DETAILS,
PROJECT_ISSUES_LIST,
} from "constants/fetch-keys";
import { CYCLES_LIST, CYCLE_DETAILS } from "constants/fetch-keys";
const SingleCycle: React.FC = () => {
const [cycleIssuesListModal, setCycleIssuesListModal] = useState(false);
@ -49,13 +44,6 @@ const SingleCycle: React.FC = () => {
const { setToastAlert } = useToast();
const { data: activeProject } = useSWR(
workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null,
workspaceSlug && projectId
? () => projectService.getProject(workspaceSlug as string, projectId as string)
: null
);
const { data: cycles } = useSWR(
workspaceSlug && projectId ? CYCLES_LIST(projectId as string) : null,
workspaceSlug && projectId
@ -75,15 +63,6 @@ const SingleCycle: React.FC = () => {
: null
);
const { data: issues } = useSWR(
workspaceSlug && projectId
? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)
: null,
workspaceSlug && projectId
? () => issuesService.getIssues(workspaceSlug as string, projectId as string)
: null
);
const cycleStatus =
cycleDetails?.start_date && cycleDetails?.end_date
? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date)
@ -93,14 +72,21 @@ const SingleCycle: React.FC = () => {
setCycleIssuesListModal(true);
};
const handleAddIssuesToCycle = async (data: { issues: string[] }) => {
const handleAddIssuesToCycle = async (data: ISearchIssueResponse[]) => {
if (!workspaceSlug || !projectId) return;
const payload = {
issues: data.map((i) => i.id),
};
await issuesService
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, data, user)
.then(() => {
mutate(CYCLE_ISSUES(cycleId as string));
})
.addIssueToCycle(
workspaceSlug as string,
projectId as string,
cycleId as string,
payload,
user
)
.catch(() => {
setToastAlert({
type: "error",
@ -115,15 +101,15 @@ const SingleCycle: React.FC = () => {
<ExistingIssuesListModal
isOpen={cycleIssuesListModal}
handleClose={() => setCycleIssuesListModal(false)}
issues={issues?.filter((i) => !i.cycle_id) ?? []}
searchParams={{ cycle: true }}
handleOnSubmit={handleAddIssuesToCycle}
/>
<ProjectAuthorizationWrapper
breadcrumbs={
<Breadcrumbs>
<BreadcrumbItem
title={`${activeProject?.name ?? "Project"} Cycles`}
link={`/${workspaceSlug}/projects/${activeProject?.id}/cycles`}
title={`${cycleDetails?.project_detail.name ?? "Project"} Cycles`}
link={`/${workspaceSlug}/projects/${projectId}/cycles`}
/>
</Breadcrumbs>
}
@ -142,7 +128,7 @@ const SingleCycle: React.FC = () => {
<CustomMenu.MenuItem
key={cycle.id}
renderAs="a"
href={`/${workspaceSlug}/projects/${activeProject?.id}/cycles/${cycle.id}`}
href={`/${workspaceSlug}/projects/${projectId}/cycles/${cycle.id}`}
>
{truncateText(cycle.name, 40)}
</CustomMenu.MenuItem>

View file

@ -31,8 +31,6 @@ const defaultValues = {
state: "",
assignees_list: [],
priority: "low",
blockers_list: [],
blocked_list: [],
target_date: new Date().toString(),
issue_cycle: null,
issue_module: null,
@ -65,6 +63,7 @@ const IssueDetailsPage: NextPage = () => {
ISSUE_DETAILS(issueId as string),
(prevData) => {
if (!prevData) return prevData;
return {
...prevData,
...formData,
@ -73,10 +72,13 @@ const IssueDetailsPage: NextPage = () => {
false
);
const payload = { ...formData };
const payload: Partial<IIssue> = {
...formData,
};
await issuesService
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
.then((res) => {
.then(() => {
mutateIssueDetails();
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
})
@ -93,12 +95,6 @@ const IssueDetailsPage: NextPage = () => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
reset({
...issueDetails,
blockers_list:
issueDetails.blockers_list ??
issueDetails.blocker_issues?.map((issue) => issue.blocker_issue_detail?.id),
blocked_list:
issueDetails.blocks_list ??
issueDetails.blocked_issues?.map((issue) => issue.blocked_issue_detail?.id),
assignees_list:
issueDetails.assignees_list ?? issueDetails.assignee_details?.map((user) => user.id),
labels_list: issueDetails.labels_list ?? issueDetails.labels,

View file

@ -2,13 +2,12 @@ import React, { useState } from "react";
import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
import useSWR from "swr";
// icons
import { ArrowLeftIcon, RectangleGroupIcon } from "@heroicons/react/24/outline";
// services
import modulesService from "services/modules.service";
import issuesService from "services/issues.service";
// hooks
import useToast from "hooks/use-toast";
import useUserAuth from "hooks/use-user-auth";
@ -21,20 +20,14 @@ import { ExistingIssuesListModal, IssuesFilterView, IssuesView } from "component
import { ModuleDetailsSidebar } from "components/modules";
import { AnalyticsProjectModal } from "components/analytics";
// ui
import { CustomMenu, EmptySpace, EmptySpaceItem, SecondaryButton, Spinner } from "components/ui";
import { CustomMenu, SecondaryButton } from "components/ui";
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
// helpers
import { truncateText } from "helpers/string.helper";
// types
import { IModule } from "types";
import { ISearchIssueResponse } from "types";
// fetch-keys
import {
MODULE_DETAILS,
MODULE_ISSUES,
MODULE_LIST,
PROJECT_ISSUES_LIST,
} from "constants/fetch-keys";
import { MODULE_DETAILS, MODULE_ISSUES, MODULE_LIST } from "constants/fetch-keys";
const SingleModule: React.FC = () => {
const [moduleIssuesListModal, setModuleIssuesListModal] = useState(false);
@ -48,15 +41,6 @@ const SingleModule: React.FC = () => {
const { setToastAlert } = useToast();
const { data: issues } = useSWR(
workspaceSlug && projectId
? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)
: null,
workspaceSlug && projectId
? () => issuesService.getIssues(workspaceSlug as string, projectId as string)
: null
);
const { data: modules } = useSWR(
workspaceSlug && projectId ? MODULE_LIST(projectId as string) : null,
workspaceSlug && projectId
@ -76,7 +60,7 @@ const SingleModule: React.FC = () => {
: null
);
const { data: moduleDetails } = useSWR<IModule>(
const { data: moduleDetails } = useSWR(
moduleId ? MODULE_DETAILS(moduleId as string) : null,
workspaceSlug && projectId
? () =>
@ -88,18 +72,21 @@ const SingleModule: React.FC = () => {
: null
);
const handleAddIssuesToModule = async (data: { issues: string[] }) => {
const handleAddIssuesToModule = async (data: ISearchIssueResponse[]) => {
if (!workspaceSlug || !projectId) return;
const payload = {
issues: data.map((i) => i.id),
};
await modulesService
.addIssuesToModule(
workspaceSlug as string,
projectId as string,
moduleId as string,
data,
payload,
user
)
.then(() => mutate(MODULE_ISSUES(moduleId as string)))
.catch(() =>
setToastAlert({
type: "error",
@ -118,7 +105,7 @@ const SingleModule: React.FC = () => {
<ExistingIssuesListModal
isOpen={moduleIssuesListModal}
handleClose={() => setModuleIssuesListModal(false)}
issues={issues?.filter((i) => !i.module_id) ?? []}
searchParams={{ module: true }}
handleOnSubmit={handleAddIssuesToModule}
/>
<ProjectAuthorizationWrapper