Merge pull request #339 from makeplane/chore/new_link_endpoint

chore: new link endpoints
This commit is contained in:
Aaryan Khandelwal 2023-02-27 15:20:00 +05:30 committed by GitHub
commit 3af3bb0fb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 46 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;
}[]; }[];
@ -56,8 +57,8 @@ export const LinksList: React.FC<Props> = ({ links, handleDeleteLink, userAuth }
<h5 className="w-4/5">{link.title}</h5> <h5 className="w-4/5">{link.title}</h5>
<p className="mt-0.5 text-gray-500"> <p className="mt-0.5 text-gray-500">
Added {timeAgo(link.created_at)} Added {timeAgo(link.created_at)}
{/* <br /> <br />
by {link.created_by_detail.email} */} by {link.created_by_detail.email}
</p> </p>
</div> </div>
</a> </a>

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,27 +362,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
</div> </div>
</div> </div>
</div> </div>
<div className="py-1">
<div className="flex items-center justify-between gap-2">
<h4>Links</h4>
<button
type="button"
className="grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-gray-100"
onClick={() => setModuleLinkModal(true)}
>
<PlusIcon className="h-4 w-4" />
</button>
</div>
<div className="mt-2 space-y-2">
{module.link_module && module.link_module.length > 0 ? (
<LinksList
links={module.link_module}
handleDeleteLink={handleDeleteLink}
userAuth={userAuth}
/>
) : null}
</div>
</div>
</div> </div>
<div className="flex flex-col items-center justify-center w-full gap-2"> <div className="flex flex-col items-center justify-center w-full gap-2">
{isStartValid && isEndValid ? ( {isStartValid && isEndValid ? (
@ -388,6 +379,27 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
"" ""
)} )}
</div> </div>
<div className="py-1 text-xs">
<div className="flex items-center justify-between gap-2">
<h4>Links</h4>
<button
type="button"
className="grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-gray-100"
onClick={() => setModuleLinkModal(true)}
>
<PlusIcon className="h-4 w-4" />
</button>
</div>
<div className="mt-2 space-y-2">
{module.link_module && module.link_module.length > 0 ? (
<LinksList
links={module.link_module}
handleDeleteLink={handleDeleteLink}
userAuth={userAuth}
/>
) : null}
</div>
</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;
}[]; }[];