plane/apps/app/services/issues.service.ts
Anmol Singh Bhatia 14dd498d08
feat: issue attachments feature (#717)
* chore: issue attachment services added

* feat: attachment icons added

* chore: fetch-key and icons export

* feat: issue attachment upload section added

* feat: issue attachment list section added

* feat: date helper function added

* style: responsiveness added

* feat: attachment info added

* style: attachment overflow fix

* style: cursor pointer added

* chore: issue attachment interface

* style: uploading state added

* feat: delete issue attachment modal

* style: style improvement and refactor

* style: consistent icon added , chore: refactor the code

* fix: js icon import fix

* fix: build fix

* chore: refactor code
2023-04-06 15:07:11 +05:30

491 lines
14 KiB
TypeScript

// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// type
import type { IIssue, IIssueActivity, IIssueComment, IIssueLabels, IIssueViewOptions } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectIssuesServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async createIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_CREATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssues(workspaceSlug: string, projectId: string): Promise<IIssue[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssuesWithParams(
workspaceSlug: string,
projectId: string,
queries?: any
): Promise<IIssue[] | { [key: string]: IIssue[] }> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, {
params: queries,
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async retrieve(workspaceSlug: string, projectId: string, issueId: string): Promise<any> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueActivities(
workspaceSlug: string,
projectId: string,
issueId: string
): Promise<IIssueActivity[]> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/history/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueComments(workspaceSlug: string, projectId: string, issueId: string): Promise<any> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueProperties(workspaceSlug: string, projectId: string): Promise<any> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async addIssueToCycle(
workspaceSlug: string,
projectId: string,
cycleId: string,
data: {
issues: string[];
}
) {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`,
data
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueMovedToCycleOrModuleEvent(
{
workspaceSlug,
workspaceName: response?.data?.[0]?.issue_detail?.workspace_detail?.name,
projectId,
projectIdentifier: response?.data?.[0]?.issue_detail?.project_detail?.identifier,
projectName: response?.data?.[0]?.issue_detail?.project_detail?.name,
issueId: response?.data?.[0]?.issue_detail?.id,
cycleId,
},
response.data.length > 1 ? "ISSUE_MOVED_TO_CYCLE_IN_BULK" : "ISSUE_MOVED_TO_CYCLE"
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async removeIssueFromCycle(
workspaceSlug: string,
projectId: string,
cycleId: string,
bridgeId: string
) {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/${bridgeId}/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueProperties(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/`,
data
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssueProperties(
workspaceSlug: string,
projectId: string,
issuePropertyId: string,
data: any
): Promise<any> {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-properties/` +
`${issuePropertyId}/`,
data
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueComment(
workspaceSlug: string,
projectId: string,
issueId: string,
data: any
): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`,
data
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_CREATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssueComment(
workspaceSlug: string,
projectId: string,
issueId: string,
commentId: string,
data: IIssueComment
): Promise<any> {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`,
data
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssueComment(
workspaceSlug: string,
projectId: string,
issueId: string,
commentId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueCommentEvent(
{
issueId,
commentId,
},
"ISSUE_COMMENT_DELETE"
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueLabels(workspaceSlug: string, projectId: string): Promise<IIssueLabels[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueLabel(
workspaceSlug: string,
projectId: string,
data: any
): Promise<IIssueLabels> {
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
.then((response: { data: IIssueLabels; [key: string]: any }) => {
if (trackEvent)
trackEventServices.trackIssueLabelEvent(
{
workSpaceId: response?.data?.workspace_detail?.id,
workSpaceName: response?.data?.workspace_detail?.name,
workspaceSlug,
projectId,
projectIdentifier: response?.data?.project_detail?.identifier,
projectName: response?.data?.project_detail?.name,
labelId: response?.data?.id,
color: response?.data?.color,
},
"ISSUE_LABEL_CREATE"
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssueLabel(
workspaceSlug: string,
projectId: string,
labelId: string,
data: any
): Promise<any> {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`,
data
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueLabelEvent(
{
workSpaceId: response?.data?.workspace_detail?.id,
workSpaceName: response?.data?.workspace_detail?.name,
workspaceSlug,
projectId,
projectIdentifier: response?.data?.project_detail?.identifier,
projectName: response?.data?.project_detail?.name,
labelId: response?.data?.id,
color: response?.data?.color,
},
"ISSUE_LABEL_UPDATE"
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssueLabel(workspaceSlug: string, projectId: string, labelId: string): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`
)
.then((response) => {
if (trackEvent)
trackEventServices.trackIssueLabelEvent(
{
workspaceSlug,
projectId,
},
"ISSUE_LABEL_DELETE"
);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateIssue(
workspaceSlug: string,
projectId: string,
issueId: string,
data: any
): Promise<any> {
return this.put(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssue(
workspaceSlug: string,
projectId: string,
issueId: string,
data: Partial<IIssue>
): Promise<any> {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`,
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueEvent(response.data, "ISSUE_UPDATE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueEvent({ issuesId }, "ISSUE_DELETE");
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async bulkDeleteIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`,
data
)
.then((response) => {
if (trackEvent) trackEventServices.trackIssueBulkDeleteEvent(data);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async subIssues(workspaceSlug: string, projectId: string, issueId: string) {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/sub-issues/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async addSubIssues(
workspaceSlug: string,
projectId: string,
issueId: string,
data: { sub_issue_ids: string[] }
): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/sub-issues/`,
data
)
.then((response) => response?.data)
.catch((error) => {
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;
});
}
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;
});
}
async uploadIssueAttachment(
workspaceSlug: string,
projectId: string,
issueId: string,
file: FormData
): Promise<any> {
return this.mediaUpload(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-attachments/`,
file
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueAttachment(
workspaceSlug: string,
projectId: string,
issueId: string
): Promise<any> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-attachments/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssueAttachment(
workspaceSlug: string,
projectId: string,
issueId: string,
assetId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-attachments/${assetId}/`
)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new ProjectIssuesServices();