chore: new link endpoints

This commit is contained in:
Aaryan Khandelwal 2023-02-24 15:50:15 +05:30
parent 3c6752807d
commit df836d55d5
9 changed files with 134 additions and 44 deletions

View File

@ -16,7 +16,7 @@ import type { IIssueLink, ModuleLink } from "types";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
handleClose: () => void; handleClose: () => void;
onFormSubmit: (formData: IIssueLink | ModuleLink) => void; onFormSubmit: (formData: IIssueLink | ModuleLink) => Promise<void>;
}; };
const defaultValues: ModuleLink = { const defaultValues: ModuleLink = {

View File

@ -14,6 +14,7 @@ type Props = {
created_at: Date; created_at: Date;
created_by: string; created_by: string;
created_by_detail: IUserLite; created_by_detail: IUserLite;
metadata: any;
title: string; title: string;
url: string; url: string;
}[]; }[];

View File

@ -86,7 +86,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = ({
return () => { return () => {
window.removeEventListener("keydown", handleKeyDown); window.removeEventListener("keydown", handleKeyDown);
}; };
}, []); }, [handleClose]);
const addIssueToCycle = async (issueId: string, cycleId: string) => { const addIssueToCycle = async (issueId: string, cycleId: string) => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;

View File

@ -77,6 +77,17 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
console.log("isseu details: ", issueDetail);
// const { data: issueLinks } = 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: issues } = useSWR( const { data: issues } = useSWR(
workspaceSlug && projectId workspaceSlug && projectId
? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string) ? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string)
@ -149,16 +160,12 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
const handleCreateLink = async (formData: IIssueLink) => { const handleCreateLink = async (formData: IIssueLink) => {
if (!workspaceSlug || !projectId || !issueDetail) return; if (!workspaceSlug || !projectId || !issueDetail) return;
const previousLinks = issueDetail?.issue_link.map((l) => ({ title: l.title, url: l.url })); const payload = { metadata: {}, ...formData };
const payload: Partial<IIssue> = {
links_list: [...(previousLinks ?? []), formData],
};
await issuesService await issuesService
.patchIssue(workspaceSlug as string, projectId as string, issueDetail.id, payload) .createIssueLink(workspaceSlug as string, projectId as string, issueDetail.id, payload)
.then((res) => { .then((res) => {
mutate(ISSUE_DETAILS(issueDetail.id as string)); mutate(ISSUE_DETAILS(issueDetail.id));
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);
@ -171,17 +178,15 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
const updatedLinks = issueDetail.issue_link.filter((l) => l.id !== linkId); const updatedLinks = issueDetail.issue_link.filter((l) => l.id !== linkId);
mutate<IIssue>( mutate<IIssue>(
ISSUE_DETAILS(issueDetail.id as string), ISSUE_DETAILS(issueDetail.id),
(prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }),
false false
); );
await issuesService await issuesService
.patchIssue(workspaceSlug as string, projectId as string, issueDetail.id, { .deleteIssueLink(workspaceSlug as string, projectId as string, issueDetail.id, linkId)
links_list: updatedLinks,
})
.then((res) => { .then((res) => {
mutate(ISSUE_DETAILS(issueDetail.id as string)); mutate(ISSUE_DETAILS(issueDetail.id));
}) })
.catch((err) => { .catch((err) => {
console.log(err); console.log(err);

View File

@ -71,6 +71,8 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
const [startDateRange, setStartDateRange] = useState<Date | null>(new Date()); const [startDateRange, setStartDateRange] = useState<Date | null>(new Date());
const [endDateRange, setEndDateRange] = useState<Date | null>(null); const [endDateRange, setEndDateRange] = useState<Date | null>(null);
console.log("module details: ", module);
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query; const { workspaceSlug, projectId, moduleId } = router.query;
@ -115,14 +117,10 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
const handleCreateLink = async (formData: ModuleLink) => { const handleCreateLink = async (formData: ModuleLink) => {
if (!workspaceSlug || !projectId || !moduleId) return; if (!workspaceSlug || !projectId || !moduleId) return;
const previousLinks = module?.link_module.map((l) => ({ title: l.title, url: l.url })); const payload = { metadata: {}, ...formData };
const payload: Partial<IModule> = {
links_list: [...(previousLinks ?? []), formData],
};
await modulesService await modulesService
.patchModule(workspaceSlug as string, projectId as string, moduleId as string, payload) .createModuleLink(workspaceSlug as string, projectId as string, moduleId as string, payload)
.then((res) => { .then((res) => {
mutate(MODULE_DETAILS(moduleId as string)); mutate(MODULE_DETAILS(moduleId as string));
}) })
@ -135,11 +133,25 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
}); });
}; };
const handleDeleteLink = (linkId: string) => { const handleDeleteLink = async (linkId: string) => {
if (!module) return; if (!workspaceSlug || !projectId || !module) return;
const updatedLinks = module.link_module.filter((l) => l.id !== linkId); const updatedLinks = module.link_module.filter((l) => l.id !== linkId);
submitChanges({ links_list: updatedLinks });
mutate<IModule>(
MODULE_DETAILS(module.id),
(prevData) => ({ ...(prevData as IModule), link_module: updatedLinks }),
false
);
await modulesService
.deleteModuleLink(workspaceSlug as string, projectId as string, module.id, linkId)
.then((res) => {
mutate(MODULE_DETAILS(module.id));
})
.catch((err) => {
console.log(err);
});
}; };
useEffect(() => { useEffect(() => {
@ -350,7 +362,24 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
</div> </div>
</div> </div>
</div> </div>
<div className="py-1"> </div>
<div className="flex flex-col items-center justify-center w-full gap-2">
{isStartValid && isEndValid ? (
<ProgressChart
issues={issues}
start={module?.start_date ?? ""}
end={module?.target_date ?? ""}
/>
) : (
""
)}
{issues.length > 0 ? (
<SidebarProgressStats issues={issues} groupedIssues={groupedIssues} />
) : (
""
)}
</div>
<div className="py-1 text-xs">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center justify-between gap-2">
<h4>Links</h4> <h4>Links</h4>
<button <button
@ -371,23 +400,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
) : null} ) : null}
</div> </div>
</div> </div>
</div>
<div className="flex flex-col items-center justify-center w-full gap-2">
{isStartValid && isEndValid ? (
<ProgressChart
issues={issues}
start={module?.start_date ?? ""}
end={module?.target_date ?? ""}
/>
) : (
""
)}
{issues.length > 0 ? (
<SidebarProgressStats issues={issues} groupedIssues={groupedIssues} />
) : (
""
)}
</div>
</> </>
) : ( ) : (
<Loader> <Loader>

View File

@ -293,6 +293,41 @@ class ProjectIssuesServices extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
} }
async createIssueLink(
workspaceSlug: string,
projectId: string,
issueId: string,
data: {
metadata: any;
title: string;
url: string;
}
): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/`,
data
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssueLink(
workspaceSlug: string,
projectId: string,
issueId: string,
linkId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/${linkId}/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
} }
export default new ProjectIssuesServices(); export default new ProjectIssuesServices();

View File

@ -116,6 +116,41 @@ class ProjectIssuesServices extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
} }
async createModuleLink(
workspaceSlug: string,
projectId: string,
moduleId: string,
data: {
metadata: any;
title: string;
url: string;
}
): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/`,
data
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteModuleLink(
workspaceSlug: string,
projectId: string,
moduleId: string,
linkId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
} }
export default new ProjectIssuesServices(); export default new ProjectIssuesServices();

View File

@ -82,6 +82,7 @@ export interface IIssue {
created_by: string; created_by: string;
created_by_detail: IUserLite; created_by_detail: IUserLite;
id: string; id: string;
metadata: any;
title: string; title: string;
url: string; url: string;
}[]; }[];

View File

@ -14,6 +14,7 @@ export interface IModule {
created_by: string; created_by: string;
created_by_detail: IUserLite; created_by_detail: IUserLite;
id: string; id: string;
metadata: any;
title: string; title: string;
url: string; url: string;
}[]; }[];