feat: init
This commit is contained in:
44
apps/web/core/services/ai.service.ts
Normal file
44
apps/web/core/services/ai.service.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
// helpers
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
// plane web constants
|
||||
import type { AI_EDITOR_TASKS } from "@/plane-web/constants/ai";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// FIXME:
|
||||
// import { IGptResponse } from "@plane/types";
|
||||
// helpers
|
||||
|
||||
export type TTaskPayload = {
|
||||
casual_score?: number;
|
||||
formal_score?: number;
|
||||
task: AI_EDITOR_TASKS;
|
||||
text_input: string;
|
||||
};
|
||||
|
||||
export class AIService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async createGptTask(workspaceSlug: string, data: { prompt: string; task: string }): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/ai-assistant/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async performEditorTask(
|
||||
workspaceSlug: string,
|
||||
data: TTaskPayload
|
||||
): Promise<{
|
||||
response: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/rephrase-grammar/`, data)
|
||||
.then((res) => res?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
106
apps/web/core/services/analytics.service.ts
Normal file
106
apps/web/core/services/analytics.service.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
// plane imports
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
IAnalyticsResponse,
|
||||
TAnalyticsTabsBase,
|
||||
TAnalyticsGraphsBase,
|
||||
TAnalyticsFilterParams,
|
||||
} from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "./api.service";
|
||||
|
||||
export class AnalyticsService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getAdvanceAnalytics<T extends IAnalyticsResponse>(
|
||||
workspaceSlug: string,
|
||||
tab: TAnalyticsTabsBase,
|
||||
params?: TAnalyticsFilterParams,
|
||||
isPeekView?: boolean
|
||||
): Promise<T> {
|
||||
return this.get(this.processUrl<TAnalyticsTabsBase>("advance-analytics", workspaceSlug, tab, params, isPeekView), {
|
||||
params: {
|
||||
tab,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getAdvanceAnalyticsStats<T>(
|
||||
workspaceSlug: string,
|
||||
tab: Exclude<TAnalyticsTabsBase, "overview">,
|
||||
params?: TAnalyticsFilterParams,
|
||||
isPeekView?: boolean
|
||||
): Promise<T> {
|
||||
const processedUrl = this.processUrl<Exclude<TAnalyticsTabsBase, "overview">>(
|
||||
"advance-analytics-stats",
|
||||
workspaceSlug,
|
||||
tab,
|
||||
params,
|
||||
isPeekView
|
||||
);
|
||||
return this.get(processedUrl, {
|
||||
params: {
|
||||
type: tab,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getAdvanceAnalyticsCharts<T>(
|
||||
workspaceSlug: string,
|
||||
tab: TAnalyticsGraphsBase,
|
||||
params?: TAnalyticsFilterParams,
|
||||
isPeekView?: boolean
|
||||
): Promise<T> {
|
||||
const processedUrl = this.processUrl<TAnalyticsGraphsBase>(
|
||||
"advance-analytics-charts",
|
||||
workspaceSlug,
|
||||
tab,
|
||||
params,
|
||||
isPeekView
|
||||
);
|
||||
return this.get(processedUrl, {
|
||||
params: {
|
||||
type: tab,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
processUrl<T extends string>(
|
||||
endpoint: string,
|
||||
workspaceSlug: string,
|
||||
tab: TAnalyticsGraphsBase | TAnalyticsTabsBase,
|
||||
params?: TAnalyticsFilterParams,
|
||||
isPeekView?: boolean
|
||||
) {
|
||||
let processedUrl = `/api/workspaces/${workspaceSlug}`;
|
||||
if (isPeekView && (tab === "work-items" || tab === "custom-work-items")) {
|
||||
const projectIds = params?.project_ids;
|
||||
if (typeof projectIds !== "string" || !projectIds.trim()) {
|
||||
throw new Error("project_ids parameter is required for peek view of work items");
|
||||
}
|
||||
const projectId = projectIds.split(",")[0];
|
||||
if (!projectId) {
|
||||
throw new Error("Invalid project_ids format - no project ID found");
|
||||
}
|
||||
processedUrl += `/projects/${projectId}`;
|
||||
}
|
||||
return `${processedUrl}/${endpoint}`;
|
||||
}
|
||||
}
|
||||
58
apps/web/core/services/api.service.ts
Normal file
58
apps/web/core/services/api.service.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import type { AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import axios from "axios";
|
||||
|
||||
export abstract class APIService {
|
||||
protected baseURL: string;
|
||||
private axiosInstance: AxiosInstance;
|
||||
|
||||
constructor(baseURL: string) {
|
||||
this.baseURL = baseURL;
|
||||
this.axiosInstance = axios.create({
|
||||
baseURL,
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
this.setupInterceptors();
|
||||
}
|
||||
|
||||
private setupInterceptors() {
|
||||
this.axiosInstance.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.replace(`/${currentPath ? `?next_path=${currentPath}` : ``}`);
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
get(url: string, params = {}, config: AxiosRequestConfig = {}) {
|
||||
return this.axiosInstance.get(url, {
|
||||
...params,
|
||||
...config,
|
||||
});
|
||||
}
|
||||
|
||||
post(url: string, data = {}, config: AxiosRequestConfig = {}) {
|
||||
return this.axiosInstance.post(url, data, config);
|
||||
}
|
||||
|
||||
put(url: string, data = {}, config: AxiosRequestConfig = {}) {
|
||||
return this.axiosInstance.put(url, data, config);
|
||||
}
|
||||
|
||||
patch(url: string, data = {}, config: AxiosRequestConfig = {}) {
|
||||
return this.axiosInstance.patch(url, data, config);
|
||||
}
|
||||
|
||||
delete(url: string, data?: any, config: AxiosRequestConfig = {}) {
|
||||
return this.axiosInstance.delete(url, { data, ...config });
|
||||
}
|
||||
|
||||
request(config = {}) {
|
||||
return this.axiosInstance(config);
|
||||
}
|
||||
}
|
||||
23
apps/web/core/services/app_config.service.ts
Normal file
23
apps/web/core/services/app_config.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helper
|
||||
// types
|
||||
// FIXME:
|
||||
// import { TAppConfig } from "@plane/types";
|
||||
|
||||
export class AppConfigService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async envConfig(): Promise<any> {
|
||||
return this.get("/api/configs/", {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
})
|
||||
.then((response) => response.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
63
apps/web/core/services/app_installation.service.ts
Normal file
63
apps/web/core/services/app_installation.service.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
|
||||
export class AppInstallationService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async addInstallationApp(workspaceSlug: string, provider: string, data: any): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/workspace-integrations/${provider}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async addSlackChannel(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
integrationId: string | null | undefined,
|
||||
data: any
|
||||
): Promise<any> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getSlackChannelDetail(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
integrationId: string | null | undefined
|
||||
): Promise<any> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async removeSlackChannel(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
integrationId: string | null | undefined,
|
||||
slackSyncId: string | undefined
|
||||
): Promise<any> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/project-slack-sync/${slackSyncId}`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
}
|
||||
78
apps/web/core/services/auth.service.ts
Normal file
78
apps/web/core/services/auth.service.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { ICsrfTokenData, IEmailCheckData, IEmailCheckResponse } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class AuthService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async requestCSRFToken(): Promise<ICsrfTokenData> {
|
||||
return this.get("/auth/get-csrf-token/")
|
||||
.then((response) => response.data)
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
emailCheck = async (data: IEmailCheckData): Promise<IEmailCheckResponse> =>
|
||||
this.post("/auth/email-check/", data, { headers: {} })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
|
||||
async sendResetPasswordLink(data: { email: string }): Promise<any> {
|
||||
return this.post(`/auth/forgot-password/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async setPassword(token: string, data: { password: string }): Promise<any> {
|
||||
return this.post(`/auth/set-password/`, data, {
|
||||
headers: {
|
||||
"X-CSRFTOKEN": token,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async generateUniqueCode(data: { email: string }): Promise<any> {
|
||||
return this.post("/auth/magic-generate/", data, { headers: {} })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async signOut(baseUrl: string): Promise<any> {
|
||||
await this.requestCSRFToken().then((data) => {
|
||||
const csrfToken = data?.csrf_token;
|
||||
|
||||
if (!csrfToken) throw Error("CSRF token not found");
|
||||
|
||||
const form = document.createElement("form");
|
||||
const element1 = document.createElement("input");
|
||||
|
||||
form.method = "POST";
|
||||
form.action = `${baseUrl}/auth/sign-out/`;
|
||||
|
||||
element1.value = csrfToken;
|
||||
element1.name = "csrfmiddlewaretoken";
|
||||
element1.type = "hidden";
|
||||
form.appendChild(element1);
|
||||
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.submit();
|
||||
});
|
||||
}
|
||||
}
|
||||
191
apps/web/core/services/cycle.service.ts
Normal file
191
apps/web/core/services/cycle.service.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
CycleDateCheckData,
|
||||
ICycle,
|
||||
TIssuesResponse,
|
||||
IWorkspaceActiveCyclesResponse,
|
||||
TCycleDistribution,
|
||||
TProgressSnapshot,
|
||||
TCycleEstimateDistribution,
|
||||
} from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class CycleService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async workspaceActiveCyclesAnalytics(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
analytic_type: string = "points"
|
||||
): Promise<TCycleDistribution | TCycleEstimateDistribution> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/analytics?type=${analytic_type}`
|
||||
)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceActiveCyclesProgress(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string
|
||||
): Promise<TProgressSnapshot> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/progress/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceActiveCyclesProgressPro(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string
|
||||
): Promise<TProgressSnapshot> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-progress/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceActiveCycles(
|
||||
workspaceSlug: string,
|
||||
cursor: string,
|
||||
per_page: number
|
||||
): Promise<IWorkspaceActiveCyclesResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/active-cycles/`, {
|
||||
params: {
|
||||
per_page,
|
||||
cursor,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceCycles(workspaceSlug: string): Promise<ICycle[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/cycles/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createCycle(workspaceSlug: string, projectId: string, data: any): Promise<ICycle> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getCyclesWithParams(workspaceSlug: string, projectId: string, cycleType?: "current"): Promise<ICycle[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, {
|
||||
params: {
|
||||
cycle_view: cycleType,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getCycleDetails(workspaceSlug: string, projectId: string, cycleId: string): Promise<ICycle> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getCycleIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
queries?: any,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`,
|
||||
{
|
||||
params: queries,
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async patchCycle(workspaceSlug: string, projectId: string, cycleId: string, data: Partial<ICycle>): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async cycleDateCheck(workspaceSlug: string, projectId: string, data: CycleDateCheckData): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/date-check/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addCycleToFavorites(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
cycle: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-cycles/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async transferIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
data: {
|
||||
new_cycle_id: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/transfer-issues/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeCycleFromFavorites(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-cycles/${cycleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
50
apps/web/core/services/cycle_archive.service.ts
Normal file
50
apps/web/core/services/cycle_archive.service.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// type
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { ICycle } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class CycleArchiveService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getArchivedCycles(workspaceSlug: string, projectId: string): Promise<ICycle[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-cycles/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getArchivedCycleDetails(workspaceSlug: string, projectId: string, cycleId: string): Promise<ICycle> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-cycles/${cycleId}/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async archiveCycle(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
53
apps/web/core/services/dashboard.service.ts
Normal file
53
apps/web/core/services/dashboard.service.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { THomeDashboardResponse, TWidget, TWidgetStatsResponse, TWidgetStatsRequestParams } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
// types
|
||||
|
||||
export class DashboardService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getHomeDashboardWidgets(workspaceSlug: string): Promise<THomeDashboardResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/dashboard/`, {
|
||||
params: {
|
||||
dashboard_type: "home",
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWidgetStats(
|
||||
workspaceSlug: string,
|
||||
dashboardId: string,
|
||||
params: TWidgetStatsRequestParams
|
||||
): Promise<TWidgetStatsResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/dashboard/${dashboardId}/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getDashboardDetails(dashboardId: string): Promise<TWidgetStatsResponse> {
|
||||
return this.get(`/api/dashboard/${dashboardId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateDashboardWidget(dashboardId: string, widgetId: string, data: Partial<TWidget>): Promise<TWidget> {
|
||||
return this.patch(`/api/dashboard/${dashboardId}/widgets/${widgetId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
56
apps/web/core/services/favorite/favorite.service.ts
Normal file
56
apps/web/core/services/favorite/favorite.service.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IFavorite } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
|
||||
export class FavoriteService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async addFavorite(workspaceSlug: string, data: Partial<IFavorite>): Promise<IFavorite> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateFavorite(workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>): Promise<IFavorite> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteFavorite(workspaceSlug: string, favoriteId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getFavorites(workspaceSlug: string): Promise<IFavorite[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/`, {
|
||||
params: {
|
||||
all: true,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getGroupedFavorites(workspaceSlug: string, favoriteId: string): Promise<IFavorite[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/group/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
1
apps/web/core/services/favorite/index.ts
Normal file
1
apps/web/core/services/favorite/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./favorite.service";
|
||||
40
apps/web/core/services/file-upload.service.ts
Normal file
40
apps/web/core/services/file-upload.service.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { AxiosRequestConfig } from "axios";
|
||||
import axios from "axios";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class FileUploadService extends APIService {
|
||||
private cancelSource: any;
|
||||
|
||||
constructor() {
|
||||
super("");
|
||||
}
|
||||
|
||||
async uploadFile(
|
||||
url: string,
|
||||
data: FormData,
|
||||
uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"]
|
||||
): Promise<void> {
|
||||
this.cancelSource = axios.CancelToken.source();
|
||||
return this.post(url, data, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
cancelToken: this.cancelSource.token,
|
||||
withCredentials: false,
|
||||
onUploadProgress: uploadProgressHandler,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
if (axios.isCancel(error)) {
|
||||
console.log(error.message);
|
||||
} else {
|
||||
throw error?.response?.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cancelUpload() {
|
||||
this.cancelSource.cancel("Upload canceled");
|
||||
}
|
||||
}
|
||||
284
apps/web/core/services/file.service.ts
Normal file
284
apps/web/core/services/file.service.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import type { AxiosRequestConfig } from "axios";
|
||||
// plane types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { getFileMetaDataForUpload, generateFileUploadPayload } from "@plane/services";
|
||||
import type { TFileEntityInfo, TFileSignedURLResponse } from "@plane/types";
|
||||
import { getAssetIdFromUrl } from "@plane/utils";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
import { FileUploadService } from "@/services/file-upload.service";
|
||||
|
||||
export interface UnSplashImage {
|
||||
id: string;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
promoted_at: Date;
|
||||
width: number;
|
||||
height: number;
|
||||
color: string;
|
||||
blur_hash: string;
|
||||
description: null;
|
||||
alt_description: string;
|
||||
urls: UnSplashImageUrls;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface UnSplashImageUrls {
|
||||
raw: string;
|
||||
full: string;
|
||||
regular: string;
|
||||
small: string;
|
||||
thumb: string;
|
||||
small_s3: string;
|
||||
}
|
||||
|
||||
export enum TFileAssetType {
|
||||
COMMENT_DESCRIPTION = "COMMENT_DESCRIPTION",
|
||||
ISSUE_ATTACHMENT = "ISSUE_ATTACHMENT",
|
||||
ISSUE_DESCRIPTION = "ISSUE_DESCRIPTION",
|
||||
PAGE_DESCRIPTION = "PAGE_DESCRIPTION",
|
||||
PROJECT_COVER = "PROJECT_COVER",
|
||||
USER_AVATAR = "USER_AVATAR",
|
||||
USER_COVER = "USER_COVER",
|
||||
WORKSPACE_LOGO = "WORKSPACE_LOGO",
|
||||
}
|
||||
|
||||
export class FileService extends APIService {
|
||||
private cancelSource: any;
|
||||
private fileUploadService: FileUploadService;
|
||||
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
this.cancelUpload = this.cancelUpload.bind(this);
|
||||
// upload service
|
||||
this.fileUploadService = new FileUploadService();
|
||||
}
|
||||
|
||||
private async updateWorkspaceAssetUploadStatus(workspaceSlug: string, assetId: string): Promise<void> {
|
||||
return this.patch(`/api/assets/v2/workspaces/${workspaceSlug}/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async uploadWorkspaceAsset(
|
||||
workspaceSlug: string,
|
||||
data: TFileEntityInfo,
|
||||
file: File,
|
||||
uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"]
|
||||
): Promise<TFileSignedURLResponse> {
|
||||
const fileMetaData = await getFileMetaDataForUpload(file);
|
||||
return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/`, {
|
||||
...data,
|
||||
...fileMetaData,
|
||||
})
|
||||
.then(async (response) => {
|
||||
const signedURLResponse: TFileSignedURLResponse = response?.data;
|
||||
const fileUploadPayload = generateFileUploadPayload(signedURLResponse, file);
|
||||
await this.fileUploadService.uploadFile(
|
||||
signedURLResponse.upload_data.url,
|
||||
fileUploadPayload,
|
||||
uploadProgressHandler
|
||||
);
|
||||
await this.updateWorkspaceAssetUploadStatus(workspaceSlug.toString(), signedURLResponse.asset_id);
|
||||
return signedURLResponse;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceAsset(workspaceSlug: string, assetId: string): Promise<void> {
|
||||
return this.delete(`/api/assets/v2/workspaces/${workspaceSlug}/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
private async updateProjectAssetUploadStatus(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
assetId: string
|
||||
): Promise<void> {
|
||||
return this.patch(`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateBulkWorkspaceAssetsUploadStatus(
|
||||
workspaceSlug: string,
|
||||
entityId: string,
|
||||
data: {
|
||||
asset_ids: string[];
|
||||
}
|
||||
): Promise<void> {
|
||||
return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/${entityId}/bulk/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateBulkProjectAssetsUploadStatus(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
entityId: string,
|
||||
data: {
|
||||
asset_ids: string[];
|
||||
}
|
||||
): Promise<void> {
|
||||
return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${entityId}/bulk/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async uploadProjectAsset(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: TFileEntityInfo,
|
||||
file: File,
|
||||
uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"]
|
||||
): Promise<TFileSignedURLResponse> {
|
||||
const fileMetaData = await getFileMetaDataForUpload(file);
|
||||
return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/`, {
|
||||
...data,
|
||||
...fileMetaData,
|
||||
})
|
||||
.then(async (response) => {
|
||||
const signedURLResponse: TFileSignedURLResponse = response?.data;
|
||||
const fileUploadPayload = generateFileUploadPayload(signedURLResponse, file);
|
||||
await this.fileUploadService.uploadFile(
|
||||
signedURLResponse.upload_data.url,
|
||||
fileUploadPayload,
|
||||
uploadProgressHandler
|
||||
);
|
||||
await this.updateProjectAssetUploadStatus(workspaceSlug, projectId, signedURLResponse.asset_id);
|
||||
return signedURLResponse;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
private async updateUserAssetUploadStatus(assetId: string): Promise<void> {
|
||||
return this.patch(`/api/assets/v2/user-assets/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async uploadUserAsset(data: TFileEntityInfo, file: File): Promise<TFileSignedURLResponse> {
|
||||
const fileMetaData = await getFileMetaDataForUpload(file);
|
||||
return this.post(`/api/assets/v2/user-assets/`, {
|
||||
...data,
|
||||
...fileMetaData,
|
||||
})
|
||||
.then(async (response) => {
|
||||
const signedURLResponse: TFileSignedURLResponse = response?.data;
|
||||
const fileUploadPayload = generateFileUploadPayload(signedURLResponse, file);
|
||||
await this.fileUploadService.uploadFile(signedURLResponse.upload_data.url, fileUploadPayload);
|
||||
await this.updateUserAssetUploadStatus(signedURLResponse.asset_id);
|
||||
return signedURLResponse;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteUserAsset(assetId: string): Promise<void> {
|
||||
return this.delete(`/api/assets/v2/user-assets/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteNewAsset(assetPath: string): Promise<void> {
|
||||
return this.delete(assetPath)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteOldWorkspaceAsset(workspaceId: string, src: string): Promise<any> {
|
||||
const assetKey = getAssetIdFromUrl(src);
|
||||
return this.delete(`/api/workspaces/file-assets/${workspaceId}/${assetKey}/`)
|
||||
.then((response) => response?.status)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteOldUserAsset(src: string): Promise<any> {
|
||||
const assetKey = getAssetIdFromUrl(src);
|
||||
return this.delete(`/api/users/file-assets/${assetKey}/`)
|
||||
.then((response) => response?.status)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreNewAsset(workspaceSlug: string, src: string): Promise<void> {
|
||||
// remove the last slash and get the asset id
|
||||
const assetId = getAssetIdFromUrl(src);
|
||||
return this.post(`/api/assets/v2/workspaces/${workspaceSlug}/restore/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async checkIfAssetExists(
|
||||
workspaceSlug: string,
|
||||
assetId: string
|
||||
): Promise<{
|
||||
exists: boolean;
|
||||
}> {
|
||||
return this.get(`/api/assets/v2/workspaces/${workspaceSlug}/check/${assetId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreOldEditorAsset(workspaceId: string, src: string): Promise<void> {
|
||||
const assetKey = getAssetIdFromUrl(src);
|
||||
return this.post(`/api/workspaces/file-assets/${workspaceId}/${assetKey}/restore/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
cancelUpload() {
|
||||
this.cancelSource.cancel("Upload canceled");
|
||||
}
|
||||
|
||||
async getUnsplashImages(query?: string): Promise<UnSplashImage[]> {
|
||||
return this.get(`/api/unsplash/`, {
|
||||
params: {
|
||||
query,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data?.results ?? res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
async getProjectCoverImages(): Promise<string[]> {
|
||||
return this.get(`/api/project-covers/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
80
apps/web/core/services/inbox/inbox-issue.service.ts
Normal file
80
apps/web/core/services/inbox/inbox-issue.service.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// plane imports
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TInboxIssue, TIssue, TInboxIssueWithPagination } from "@plane/types";
|
||||
import { EInboxIssueSource } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class InboxIssueService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async list(workspaceSlug: string, projectId: string, params = {}): Promise<TInboxIssueWithPagination> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieve(workspaceSlug: string, projectId: string, inboxIssueId: string): Promise<TInboxIssue> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/${inboxIssueId}/?expand=issue_inbox`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async create(workspaceSlug: string, projectId: string, data: Partial<TIssue>): Promise<TInboxIssue> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/`, {
|
||||
source: EInboxIssueSource.IN_APP,
|
||||
issue: data,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async update(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxIssueId: string,
|
||||
data: Partial<TInboxIssue>
|
||||
): Promise<TInboxIssue> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/${inboxIssueId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateIssue(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxIssueId: string,
|
||||
data: Partial<TIssue>
|
||||
): Promise<TInboxIssue> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/${inboxIssueId}/`, {
|
||||
issue: data,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async destroy(workspaceSlug: string, projectId: string, inboxIssueId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inbox-issues/${inboxIssueId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
2
apps/web/core/services/inbox/index.ts
Normal file
2
apps/web/core/services/inbox/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./inbox-issue.service";
|
||||
export * from "./intake-work_item_version.service";
|
||||
@@ -0,0 +1,41 @@
|
||||
// plane imports
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TDescriptionVersionsListResponse, TDescriptionVersionDetails } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class IntakeWorkItemVersionService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async listDescriptionVersions(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
intakeWorkItemId: string
|
||||
): Promise<TDescriptionVersionsListResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/intake-work-items/${intakeWorkItemId}/description-versions/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveDescriptionVersion(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
intakeWorkItemId: string,
|
||||
versionId: string
|
||||
): Promise<TDescriptionVersionDetails> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/intake-work-items/${intakeWorkItemId}/description-versions/${versionId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
28
apps/web/core/services/instance.service.ts
Normal file
28
apps/web/core/services/instance.service.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IInstanceInfo, TPage } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class InstanceService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async requestCSRFToken(): Promise<{ csrf_token: string }> {
|
||||
return this.get("/auth/get-csrf-token/")
|
||||
.then((response) => response.data)
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
async getInstanceInfo(): Promise<IInstanceInfo> {
|
||||
return this.get("/api/instances/")
|
||||
.then((response) => response.data)
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
39
apps/web/core/services/integrations/github.service.ts
Normal file
39
apps/web/core/services/integrations/github.service.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IGithubRepoInfo, IGithubServiceImportFormData } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
// types
|
||||
|
||||
const integrationServiceType: string = "github";
|
||||
|
||||
export class GithubIntegrationService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async listAllRepositories(workspaceSlug: string, integrationSlug: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/workspace-integrations/${integrationSlug}/github-repositories`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getGithubRepoInfo(workspaceSlug: string, params: { owner: string; repo: string }): Promise<IGithubRepoInfo> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/importers/${integrationServiceType}/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createGithubServiceImport(workspaceSlug: string, data: IGithubServiceImportFormData): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
3
apps/web/core/services/integrations/index.ts
Normal file
3
apps/web/core/services/integrations/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./github.service";
|
||||
export * from "./integration.service";
|
||||
export * from "./jira.service";
|
||||
67
apps/web/core/services/integrations/integration.service.ts
Normal file
67
apps/web/core/services/integrations/integration.service.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IAppIntegration, IImporterService, IWorkspaceIntegration, IExportServiceResponse } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// helper
|
||||
|
||||
export class IntegrationService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getAppIntegrationsList(): Promise<IAppIntegration[]> {
|
||||
return this.get(`/api/integrations/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceIntegrationsList(workspaceSlug: string): Promise<IWorkspaceIntegration[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/workspace-integrations/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceIntegration(workspaceSlug: string, integrationId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/workspace-integrations/${integrationId}/provider/`)
|
||||
.then((res) => res?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getImporterServicesList(workspaceSlug: string): Promise<IImporterService[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/importers/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async getExportsServicesList(
|
||||
workspaceSlug: string,
|
||||
cursor: string,
|
||||
per_page: number
|
||||
): Promise<IExportServiceResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/export-issues`, {
|
||||
params: {
|
||||
per_page,
|
||||
cursor,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteImporterService(workspaceSlug: string, service: string, importerId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/importers/${service}/${importerId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
28
apps/web/core/services/integrations/jira.service.ts
Normal file
28
apps/web/core/services/integrations/jira.service.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IJiraMetadata, IJiraResponse, IJiraImporterForm } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
|
||||
export class JiraImporterService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getJiraProjectInfo(workspaceSlug: string, params: IJiraMetadata): Promise<IJiraResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/importers/jira`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createJiraImporter(workspaceSlug: string, data: IJiraImporterForm): Promise<IJiraResponse> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/jira/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
10
apps/web/core/services/issue/index.ts
Normal file
10
apps/web/core/services/issue/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export * from "./issue_archive.service";
|
||||
export * from "./issue.service";
|
||||
export * from "./issue_reaction.service";
|
||||
export * from "./issue_label.service";
|
||||
export * from "./issue_attachment.service";
|
||||
export * from "./issue_activity.service";
|
||||
export * from "./issue_comment.service";
|
||||
export * from "./issue_relation.service";
|
||||
export * from "./work_item_version.service";
|
||||
export * from "./workspace_draft.service";
|
||||
497
apps/web/core/services/issue/issue.service.ts
Normal file
497
apps/web/core/services/issue/issue.service.ts
Normal file
@@ -0,0 +1,497 @@
|
||||
// plane imports
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import type {
|
||||
TIssueParams,
|
||||
IIssueDisplayProperties,
|
||||
TBulkOperationsPayload,
|
||||
TIssue,
|
||||
TIssueActivity,
|
||||
TIssueLink,
|
||||
TIssueServiceType,
|
||||
TIssuesResponse,
|
||||
TIssueSubIssues,
|
||||
} from "@plane/types";
|
||||
import { getIssuesShouldFallbackToServer } from "@plane/utils";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class IssueService extends APIService {
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async createIssue(workspaceSlug: string, projectId: string, data: Partial<TIssue>): Promise<TIssue> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssuesFromServer(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
queries?: any,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
const path =
|
||||
(queries.expand as string)?.includes("issue_relation") && !queries.group_by
|
||||
? `/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}-detail/`
|
||||
: `/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/`;
|
||||
return this.get(
|
||||
path,
|
||||
{
|
||||
params: queries,
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssuesForSync(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
queries?: any,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/v2/${this.serviceType}/`,
|
||||
{ params: queries },
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
queries?: Partial<Record<TIssueParams, string | boolean>>,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
if (getIssuesShouldFallbackToServer(queries) || this.serviceType !== EIssueServiceType.ISSUES) {
|
||||
return await this.getIssuesFromServer(workspaceSlug, projectId, queries, config);
|
||||
}
|
||||
const { persistence } = await import("@/local-db/storage.sqlite");
|
||||
const response = await persistence.getIssues(workspaceSlug, projectId, queries, config);
|
||||
return response as TIssuesResponse;
|
||||
}
|
||||
|
||||
async getDeletedIssues(workspaceSlug: string, projectId: string, queries?: any): Promise<TIssuesResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/deleted-issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssuesWithParams(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
queries?: any
|
||||
): Promise<TIssue[] | { [key: string]: TIssue[] }> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieve(workspaceSlug: string, projectId: string, issueId: string, queries?: any): Promise<TIssue> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then(async (response) => {
|
||||
// skip issue update when the service type is epic
|
||||
if (response.data && this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { updateIssue } = await import("@/local-db/utils/load-issues");
|
||||
updateIssue({ ...response.data, is_local_update: 1 });
|
||||
}
|
||||
// add is_epic flag when the service type is epic
|
||||
if (response.data && this.serviceType === EIssueServiceType.EPICS) {
|
||||
response.data.is_epic = true;
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveIssues(workspaceSlug: string, projectId: string, issueIds: string[]): Promise<TIssue[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/list/`, {
|
||||
params: { issues: issueIds.join(",") },
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (response?.data && Array.isArray(response?.data) && this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { addIssuesBulk } = await import("@/local-db/utils/load-issues");
|
||||
addIssuesBulk(response.data);
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssueActivities(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueActivity[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/history/`)
|
||||
.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) => 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 createIssueRelation(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: {
|
||||
related_list: Array<{
|
||||
relation_type: "duplicate" | "relates_to" | "blocked_by";
|
||||
related_issue: string;
|
||||
}>;
|
||||
relation?: "blocking" | null;
|
||||
}
|
||||
) {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/issue-relation/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueRelation(workspaceSlug: string, projectId: string, issueId: string, relationId: string) {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/issue-relation/${relationId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssueDisplayProperties(workspaceSlug: string, projectId: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-display-properties/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateIssueDisplayProperties(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: IIssueDisplayProperties
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-display-properties/`, {
|
||||
properties: data,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async patchIssue(workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
|
||||
if (this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { deleteIssueFromLocal } = await import("@/local-db/utils/load-issues");
|
||||
deleteIssueFromLocal(issuesId);
|
||||
}
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issuesId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateIssueDates(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
updates: { id: string; start_date?: string; target_date?: string }[]
|
||||
): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-dates/`, { updates })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async subIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
queries?: Partial<Record<TIssueParams, string | boolean>>
|
||||
): Promise<TIssueSubIssues> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "issues" : "sub-issues"}/`,
|
||||
{ params: queries }
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addSubIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: { sub_issue_ids: string[] }
|
||||
): Promise<TIssueSubIssues> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "issues" : "sub-issues"}/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchIssueLinks(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueLink[]> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "links" : "issue-links"}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async createIssueLink(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssueLink>
|
||||
): Promise<TIssueLink> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "links" : "issue-links"}/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateIssueLink(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
linkId: string,
|
||||
data: Partial<TIssueLink>
|
||||
): Promise<TIssueLink> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "links" : "issue-links"}/${linkId}/`,
|
||||
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}/${this.serviceType}/${issueId}/${this.serviceType === EIssueServiceType.EPICS ? "links" : "issue-links"}/${linkId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async bulkOperations(workspaceSlug: string, projectId: string, data: TBulkOperationsPayload): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-operation-issues/`, data)
|
||||
.then(async (response) => {
|
||||
if (this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { persistence } = await import("@/local-db/storage.sqlite");
|
||||
persistence.syncIssues(projectId);
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async bulkDeleteIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
issue_ids: string[];
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`, data)
|
||||
.then(async (response) => {
|
||||
if (this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { persistence } = await import("@/local-db/storage.sqlite");
|
||||
persistence.syncIssues(projectId);
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async bulkArchiveIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
issue_ids: string[];
|
||||
}
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-archive-issues/`, data)
|
||||
.then(async (response) => {
|
||||
if (this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { persistence } = await import("@/local-db/storage.sqlite");
|
||||
persistence.syncIssues(projectId);
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// issue subscriptions
|
||||
async getIssueNotificationSubscriptionStatus(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string
|
||||
): Promise<{
|
||||
subscribed: boolean;
|
||||
}> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/subscribe/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async unsubscribeFromIssueNotifications(workspaceSlug: string, projectId: string, issueId: string): Promise<any> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/subscribe/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async subscribeToIssueNotifications(workspaceSlug: string, projectId: string, issueId: string): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/subscribe/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async bulkSubscribeIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
issue_ids: string[];
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-subscribe-issues/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssueMetaFromURL(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string
|
||||
): Promise<{
|
||||
project_identifier: string;
|
||||
sequence_id: string;
|
||||
}> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/meta/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveWithIdentifier(
|
||||
workspaceSlug: string,
|
||||
project_identifier: string,
|
||||
issue_sequence: string,
|
||||
queries?: any
|
||||
): Promise<TIssue> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/work-items/${project_identifier}-${issue_sequence}/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then(async (response) => {
|
||||
// skip issue update when the service type is epic
|
||||
if (response.data && this.serviceType === EIssueServiceType.ISSUES) {
|
||||
const { updateIssue } = await import("@/local-db/utils/load-issues");
|
||||
updateIssue({ ...response.data, is_local_update: 1 });
|
||||
}
|
||||
// add is_epic flag when the service type is epic
|
||||
if (response.data && this.serviceType === EIssueServiceType.EPICS) {
|
||||
response.data.is_epic = true;
|
||||
}
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
37
apps/web/core/services/issue/issue_activity.service.ts
Normal file
37
apps/web/core/services/issue/issue_activity.service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TIssueActivity, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// helper
|
||||
|
||||
export class IssueActivityService extends APIService {
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async getIssueActivities(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
params:
|
||||
| {
|
||||
created_at__gt: string;
|
||||
}
|
||||
| object = {}
|
||||
): Promise<TIssueActivity[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/history/`, {
|
||||
params: {
|
||||
activity_type: `${this.serviceType === EIssueServiceType.EPICS ? "epic-property" : "issue-property"}`,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
66
apps/web/core/services/issue/issue_archive.service.ts
Normal file
66
apps/web/core/services/issue/issue_archive.service.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TIssue, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// constants
|
||||
|
||||
export class IssueArchiveService extends APIService {
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async getArchivedIssues(workspaceSlug: string, projectId: string, queries?: any, config = {}): Promise<any> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-issues/`,
|
||||
{
|
||||
params: { ...queries },
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async archiveIssue(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreIssue(workspaceSlug: string, projectId: string, issueId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveArchivedIssue(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
queries?: any
|
||||
): Promise<TIssue> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/archive/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
89
apps/web/core/services/issue/issue_attachment.service.ts
Normal file
89
apps/web/core/services/issue/issue_attachment.service.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import type { AxiosRequestConfig } from "axios";
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
// plane types
|
||||
import { getFileMetaDataForUpload, generateFileUploadPayload } from "@plane/services";
|
||||
import type { TIssueAttachment, TIssueAttachmentUploadResponse, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
import { FileUploadService } from "@/services/file-upload.service";
|
||||
|
||||
export class IssueAttachmentService extends APIService {
|
||||
private fileUploadService: FileUploadService;
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
// upload service
|
||||
this.fileUploadService = new FileUploadService();
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
private async updateIssueAttachmentUploadStatus(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
attachmentId: string
|
||||
): Promise<void> {
|
||||
return this.patch(
|
||||
`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/attachments/${attachmentId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async uploadIssueAttachment(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
file: File,
|
||||
uploadProgressHandler?: AxiosRequestConfig["onUploadProgress"]
|
||||
): Promise<TIssueAttachment> {
|
||||
const fileMetaData = await getFileMetaDataForUpload(file);
|
||||
return this.post(
|
||||
`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/attachments/`,
|
||||
fileMetaData
|
||||
)
|
||||
.then(async (response) => {
|
||||
const signedURLResponse: TIssueAttachmentUploadResponse = response?.data;
|
||||
const fileUploadPayload = generateFileUploadPayload(signedURLResponse, file);
|
||||
await this.fileUploadService.uploadFile(
|
||||
signedURLResponse.upload_data.url,
|
||||
fileUploadPayload,
|
||||
uploadProgressHandler
|
||||
);
|
||||
await this.updateIssueAttachmentUploadStatus(workspaceSlug, projectId, issueId, signedURLResponse.asset_id);
|
||||
return signedURLResponse.attachment;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssueAttachments(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueAttachment[]> {
|
||||
return this.get(
|
||||
`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/attachments/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueAttachment(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
assetId: string
|
||||
): Promise<TIssueAttachment> {
|
||||
return this.delete(
|
||||
`/api/assets/v2/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/attachments/${assetId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
89
apps/web/core/services/issue/issue_comment.service.ts
Normal file
89
apps/web/core/services/issue/issue_comment.service.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
// plane types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TIssueComment, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
import { FileUploadService } from "@/services/file-upload.service";
|
||||
|
||||
export class IssueCommentService extends APIService {
|
||||
private fileUploadService: FileUploadService;
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
// upload service
|
||||
this.fileUploadService = new FileUploadService();
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async getIssueComments(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
params:
|
||||
| {
|
||||
created_at__gt: string;
|
||||
}
|
||||
| object = {}
|
||||
): Promise<TIssueComment[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/history/`, {
|
||||
params: {
|
||||
activity_type: `${this.serviceType === EIssueServiceType.EPICS ? "epic-comment" : "issue-comment"}`,
|
||||
...params,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createIssueComment(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssueComment>
|
||||
): Promise<TIssueComment> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/comments/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async patchIssueComment(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
commentId: string,
|
||||
data: Partial<TIssueComment>
|
||||
): Promise<TIssueComment> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/comments/${commentId}/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueComment(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
commentId: string
|
||||
): Promise<void> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/comments/${commentId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
51
apps/web/core/services/issue/issue_label.service.ts
Normal file
51
apps/web/core/services/issue/issue_label.service.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IIssueLabel } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
|
||||
export class IssueLabelService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getWorkspaceIssueLabels(workspaceSlug: string): Promise<IIssueLabel[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/labels/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectLabels(workspaceSlug: string, projectId: string): Promise<IIssueLabel[]> {
|
||||
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<IIssueLabel> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
|
||||
.then((response) => 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) => 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) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
89
apps/web/core/services/issue/issue_reaction.service.ts
Normal file
89
apps/web/core/services/issue/issue_reaction.service.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import type { TIssueCommentReaction, TIssueReaction, TIssueServiceType } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
|
||||
export class IssueReactionService extends APIService {
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
super(API_BASE_URL);
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async createIssueReaction(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssueReaction>
|
||||
): Promise<any> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/reactions/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async listIssueReactions(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueReaction[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/reactions/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueReaction(workspaceSlug: string, projectId: string, issueId: string, reaction: string): Promise<any> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${issueId}/reactions/${reaction}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createIssueCommentReaction(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
commentId: string,
|
||||
data: Partial<TIssueCommentReaction>
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async listIssueCommentReactions(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
commentId: string
|
||||
): Promise<TIssueCommentReaction[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueCommentReaction(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
commentId: string,
|
||||
reaction: string
|
||||
): Promise<any> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/${reaction}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
47
apps/web/core/services/issue/issue_relation.service.ts
Normal file
47
apps/web/core/services/issue/issue_relation.service.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TIssueRelation, TIssue } from "@plane/types";
|
||||
// helpers
|
||||
// Plane-web
|
||||
import type { TIssueRelationTypes } from "@/plane-web/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class IssueRelationService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async listIssueRelations(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueRelation> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createIssueRelations(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: { relation_type: TIssueRelationTypes; issues: string[] }
|
||||
): Promise<TIssue[]> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssueRelation(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: { relation_type: TIssueRelationTypes; related_issue: string }
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/remove-relation/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
45
apps/web/core/services/issue/work_item_version.service.ts
Normal file
45
apps/web/core/services/issue/work_item_version.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// plane imports
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
import type { TDescriptionVersionsListResponse, TDescriptionVersionDetails, TIssueServiceType } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class WorkItemVersionService extends APIService {
|
||||
private serviceType: TIssueServiceType;
|
||||
|
||||
constructor(serviceType: TIssueServiceType = EIssueServiceType.WORK_ITEMS) {
|
||||
super(API_BASE_URL);
|
||||
this.serviceType = serviceType;
|
||||
}
|
||||
|
||||
async listDescriptionVersions(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
workItemId: string
|
||||
): Promise<TDescriptionVersionsListResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${workItemId}/description-versions/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveDescriptionVersion(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
workItemId: string,
|
||||
versionId: string
|
||||
): Promise<TDescriptionVersionDetails> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/${this.serviceType}/${workItemId}/description-versions/${versionId}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
73
apps/web/core/services/issue/workspace_draft.service.ts
Normal file
73
apps/web/core/services/issue/workspace_draft.service.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TIssue, TWorkspaceDraftIssue, TWorkspaceDraftPaginationInfo } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class WorkspaceDraftService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getIssues(
|
||||
workspaceSlug: string,
|
||||
query: object = {}
|
||||
): Promise<TWorkspaceDraftPaginationInfo<TWorkspaceDraftIssue> | undefined> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/draft-issues/`, { params: { ...query } })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssueById(workspaceSlug: string, issueId: string): Promise<TWorkspaceDraftIssue | undefined> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/draft-issues/${issueId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async createIssue(
|
||||
workspaceSlug: string,
|
||||
payload: Partial<TWorkspaceDraftIssue | TIssue>
|
||||
): Promise<TWorkspaceDraftIssue | undefined> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/draft-issues/`, payload)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateIssue(
|
||||
workspaceSlug: string,
|
||||
issueId: string,
|
||||
payload: Partial<TWorkspaceDraftIssue | TIssue>
|
||||
): Promise<TWorkspaceDraftIssue | undefined> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/draft-issues/${issueId}/`, payload)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteIssue(workspaceSlug: string, issueId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/draft-issues/${issueId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async moveIssue(workspaceSlug: string, issueId: string, payload: Partial<TWorkspaceDraftIssue>): Promise<TIssue> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/draft-to-issue/${issueId}/`, payload)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const workspaceDraftService = new WorkspaceDraftService();
|
||||
|
||||
export default workspaceDraftService;
|
||||
123
apps/web/core/services/issue_filter.service.ts
Normal file
123
apps/web/core/services/issue_filter.service.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IIssueFiltersResponse } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
|
||||
export class IssueFiltersService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
// // workspace issue filters
|
||||
// async fetchWorkspaceFilters(workspaceSlug: string): Promise<IIssueFiltersResponse> {
|
||||
// return this.get(`/api/workspaces/${workspaceSlug}/user-properties/`)
|
||||
// .then((response) => response?.data)
|
||||
// .catch((error) => {
|
||||
// throw error?.response?.data;
|
||||
// });
|
||||
// }
|
||||
// async patchWorkspaceFilters(
|
||||
// workspaceSlug: string,
|
||||
// data: Partial<IIssueFiltersResponse>
|
||||
// ): Promise<IIssueFiltersResponse> {
|
||||
// return this.patch(`/api/workspaces/${workspaceSlug}/user-properties/`, data)
|
||||
// .then((response) => response?.data)
|
||||
// .catch((error) => {
|
||||
// throw error?.response?.data;
|
||||
// });
|
||||
// }
|
||||
|
||||
// project issue filters
|
||||
async fetchProjectIssueFilters(workspaceSlug: string, projectId: string): Promise<IIssueFiltersResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-properties/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async patchProjectIssueFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: Partial<IIssueFiltersResponse>
|
||||
): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-properties/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// epic issue filters
|
||||
async fetchProjectEpicFilters(workspaceSlug: string, projectId: string): Promise<IIssueFiltersResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/epics-user-properties/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async patchProjectEpicFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: Partial<IIssueFiltersResponse>
|
||||
): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/epics-user-properties/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// cycle issue filters
|
||||
async fetchCycleIssueFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string
|
||||
): Promise<IIssueFiltersResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/user-properties/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async patchCycleIssueFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
data: Partial<IIssueFiltersResponse>
|
||||
): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/user-properties/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// module issue filters
|
||||
async fetchModuleIssueFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string
|
||||
): Promise<IIssueFiltersResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/user-properties/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async patchModuleIssueFilters(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
data: Partial<IIssueFiltersResponse>
|
||||
): Promise<any> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/user-properties/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
218
apps/web/core/services/module.service.ts
Normal file
218
apps/web/core/services/module.service.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IModule, ILinkDetails, ModuleLink, TIssuesResponse } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ModuleService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getWorkspaceModules(workspaceSlug: string): Promise<IModule[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/modules/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getModules(workspaceSlug: string, projectId: string): Promise<IModule[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createModule(workspaceSlug: string, projectId: string, data: any): Promise<IModule> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateModule(workspaceSlug: string, projectId: string, moduleId: string, data: any): Promise<any> {
|
||||
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getModuleDetails(workspaceSlug: string, projectId: string, moduleId: string): Promise<IModule> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async patchModule(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
data: Partial<IModule>
|
||||
): Promise<IModule> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteModule(workspaceSlug: string, projectId: string, moduleId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getModuleIssues(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
queries?: any,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/`,
|
||||
{
|
||||
params: queries,
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addIssuesToModule(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
data: { issues: string[] }
|
||||
): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addModulesToIssue(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: { modules: string[]; removed_modules?: string[] }
|
||||
): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/modules/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeIssuesFromModuleBulk(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
issueIds: string[]
|
||||
): Promise<void> {
|
||||
const promiseDataUrls: any = [];
|
||||
issueIds.forEach((issueId) => {
|
||||
promiseDataUrls.push(
|
||||
this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/${issueId}/`)
|
||||
);
|
||||
});
|
||||
await Promise.all(promiseDataUrls)
|
||||
.then((response) => response)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeModulesFromIssueBulk(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
moduleIds: string[]
|
||||
): Promise<void> {
|
||||
const promiseDataUrls: any = [];
|
||||
moduleIds.forEach((moduleId) => {
|
||||
promiseDataUrls.push(
|
||||
this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/${issueId}/`)
|
||||
);
|
||||
});
|
||||
await Promise.all(promiseDataUrls)
|
||||
.then((response) => response)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createModuleLink(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
data: Partial<ModuleLink>
|
||||
): Promise<ILinkDetails> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateModuleLink(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
linkId: string,
|
||||
data: Partial<ModuleLink>
|
||||
): Promise<ILinkDetails> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
async addModuleToFavorites(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
module: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-modules/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeModuleFromFavorites(workspaceSlug: string, projectId: string, moduleId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-modules/${moduleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
50
apps/web/core/services/module_archive.service.ts
Normal file
50
apps/web/core/services/module_archive.service.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
// type
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IModule } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ModuleArchiveService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async getArchivedModules(workspaceSlug: string, projectId: string): Promise<IModule[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-modules/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getArchivedModuleDetails(workspaceSlug: string, projectId: string, moduleId: string): Promise<IModule> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-modules/${moduleId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async archiveModule(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreModule(workspaceSlug: string, projectId: string, moduleId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
2
apps/web/core/services/page/index.ts
Normal file
2
apps/web/core/services/page/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./project-page-version.service";
|
||||
export * from "./project-page.service";
|
||||
43
apps/web/core/services/page/project-page-version.service.ts
Normal file
43
apps/web/core/services/page/project-page-version.service.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
// plane types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TPageVersion } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ProjectPageVersionService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchAllVersions(workspaceSlug: string, projectId: string, pageId: string): Promise<TPageVersion[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/versions/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchVersionById(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
pageId: string,
|
||||
versionId: string
|
||||
): Promise<TPageVersion> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/versions/${versionId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreVersion(workspaceSlug: string, projectId: string, pageId: string, versionId: string): Promise<void> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/versions/${versionId}/restore/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
188
apps/web/core/services/page/project-page.service.ts
Normal file
188
apps/web/core/services/page/project-page.service.ts
Normal file
@@ -0,0 +1,188 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TDocumentPayload, TPage } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
import { FileUploadService } from "@/services/file-upload.service";
|
||||
|
||||
export class ProjectPageService extends APIService {
|
||||
private fileUploadService: FileUploadService;
|
||||
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
// upload service
|
||||
this.fileUploadService = new FileUploadService();
|
||||
}
|
||||
|
||||
async fetchAll(workspaceSlug: string, projectId: string): Promise<TPage[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchById(workspaceSlug: string, projectId: string, pageId: string, trackVisit: boolean): Promise<TPage> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`, {
|
||||
params: {
|
||||
track_visit: trackVisit,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async create(workspaceSlug: string, projectId: string, data: Partial<TPage>): Promise<TPage> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async update(workspaceSlug: string, projectId: string, pageId: string, data: Partial<TPage>): Promise<TPage> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateAccess(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
pageId: string,
|
||||
data: Pick<TPage, "access">
|
||||
): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/access/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async remove(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchFavorites(workspaceSlug: string, projectId: string): Promise<TPage[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/favorite-pages/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addToFavorites(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/favorite-pages/${pageId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeFromFavorites(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/favorite-pages/${pageId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchArchived(workspaceSlug: string, projectId: string): Promise<TPage[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-pages/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async archive(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
pageId: string
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restore(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async lock(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/lock/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async unlock(workspaceSlug: string, projectId: string, pageId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/lock/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchDescriptionBinary(workspaceSlug: string, projectId: string, pageId: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/description/`, {
|
||||
headers: {
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
responseType: "arraybuffer",
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateDescription(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
pageId: string,
|
||||
data: TDocumentPayload
|
||||
): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/description/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
async duplicate(workspaceSlug: string, projectId: string, pageId: string): Promise<TPage> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/duplicate/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async move(workspaceSlug: string, projectId: string, pageId: string, newProjectId: string): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/move/`, {
|
||||
new_project_id: newProjectId,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
6
apps/web/core/services/project/index.ts
Normal file
6
apps/web/core/services/project/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from "./project.service";
|
||||
export * from "./project-export.service";
|
||||
export * from "./project-member.service";
|
||||
export * from "./project-state.service";
|
||||
export * from "./project-publish.service";
|
||||
export * from "./project-archive.service";
|
||||
31
apps/web/core/services/project/project-archive.service.ts
Normal file
31
apps/web/core/services/project/project-archive.service.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
// helpers
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ProjectArchiveService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async archiveProject(
|
||||
workspaceSlug: string,
|
||||
projectId: string
|
||||
): Promise<{
|
||||
archived_at: string;
|
||||
}> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async restoreProject(workspaceSlug: string, projectId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archive/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
23
apps/web/core/services/project/project-export.service.ts
Normal file
23
apps/web/core/services/project/project-export.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
|
||||
export class ProjectExportService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async csvExport(
|
||||
workspaceSlug: string,
|
||||
data: {
|
||||
provider: string;
|
||||
project: string[];
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/export-issues/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
72
apps/web/core/services/project/project-member.service.ts
Normal file
72
apps/web/core/services/project/project-member.service.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IProjectBulkAddFormData, TProjectMembership } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ProjectMemberService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchProjectMembers(workspaceSlug: string, projectId: string): Promise<TProjectMembership[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async bulkAddMembersToProject(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: IProjectBulkAddFormData
|
||||
): Promise<TProjectMembership[]> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async projectMemberMe(workspaceSlug: string, projectId: string): Promise<TProjectMembership> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<TProjectMembership> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateProjectMember(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
memberId: string,
|
||||
data: Partial<TProjectMembership>
|
||||
): Promise<TProjectMembership> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const projectMemberService = new ProjectMemberService();
|
||||
|
||||
export default projectMemberService;
|
||||
58
apps/web/core/services/project/project-publish.service.ts
Normal file
58
apps/web/core/services/project/project-publish.service.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// types
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TProjectPublishSettings } from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ProjectPublishService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchPublishSettings(workspaceSlug: string, projectID: string): Promise<TProjectPublishSettings> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectID}/project-deploy-boards/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async publishProject(
|
||||
workspaceSlug: string,
|
||||
projectID: string,
|
||||
data: Partial<TProjectPublishSettings>
|
||||
): Promise<TProjectPublishSettings> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectID}/project-deploy-boards/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updatePublishSettings(
|
||||
workspaceSlug: string,
|
||||
projectID: string,
|
||||
project_publish_id: string,
|
||||
data: Partial<TProjectPublishSettings>
|
||||
): Promise<TProjectPublishSettings> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectID}/project-deploy-boards/${project_publish_id}/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async unpublishProject(workspaceSlug: string, projectID: string, project_publish_id: string): Promise<any> {
|
||||
return this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectID}/project-deploy-boards/${project_publish_id}/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
}
|
||||
76
apps/web/core/services/project/project-state.service.ts
Normal file
76
apps/web/core/services/project/project-state.service.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IState } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
// types
|
||||
|
||||
export class ProjectStateService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async createState(workspaceSlug: string, projectId: string, data: any): Promise<IState> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async markDefault(workspaceSlug: string, projectId: string, stateId: string): Promise<void> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/mark-default/`, {})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getStates(workspaceSlug: string, projectId: string): Promise<IState[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateState(workspaceSlug: string, projectId: string, stateId: string, data: IState): Promise<any> {
|
||||
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async patchState(workspaceSlug: string, projectId: string, stateId: string, data: Partial<IState>): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceStates(workspaceSlug: string): Promise<IState[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/states/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
186
apps/web/core/services/project/project.service.ts
Normal file
186
apps/web/core/services/project/project.service.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
GithubRepositoriesResponse,
|
||||
ISearchIssueResponse,
|
||||
TProjectAnalyticsCount,
|
||||
TProjectAnalyticsCountParams,
|
||||
TProjectIssuesSearchParams,
|
||||
} from "@plane/types";
|
||||
// helpers
|
||||
// plane web types
|
||||
import type { TProject, TPartialProject } from "@/plane-web/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class ProjectService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async createProject(workspaceSlug: string, data: Partial<TProject>): Promise<TProject> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async checkProjectIdentifierAvailability(workspaceSlug: string, data: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/project-identifiers`, {
|
||||
params: {
|
||||
name: data,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectsLite(workspaceSlug: string): Promise<TPartialProject[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjects(workspaceSlug: string): Promise<TProject[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/details/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProject(workspaceSlug: string, projectId: string): Promise<TProject> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectAnalyticsCount(
|
||||
workspaceSlug: string,
|
||||
params?: TProjectAnalyticsCountParams
|
||||
): Promise<TProjectAnalyticsCount[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/project-stats/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateProject(workspaceSlug: string, projectId: string, data: Partial<TProject>): Promise<TProject> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteProject(workspaceSlug: string, projectId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async setProjectView(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
sort_order?: number;
|
||||
}
|
||||
): Promise<any> {
|
||||
await this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/project-views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getGithubRepositories(url: string): Promise<GithubRepositoriesResponse> {
|
||||
return this.request({
|
||||
method: "get",
|
||||
url,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async syncGithubRepository(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
workspaceIntegrationId: string,
|
||||
data: {
|
||||
name: string;
|
||||
owner: string;
|
||||
repository_id: string;
|
||||
url: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${workspaceIntegrationId}/github-repository-sync/`,
|
||||
data
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectGithubRepository(workspaceSlug: string, projectId: string, integrationId: string): Promise<any> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/github-repository-sync/`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProjectFavorites(workspaceSlug: string): Promise<any[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-favorite-projects/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addProjectToFavorites(workspaceSlug: string, project: string): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/user-favorite-projects/`, { project })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeProjectFromFavorites(workspaceSlug: string, projectId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/user-favorite-projects/${projectId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async projectIssuesSearch(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
params: TProjectIssuesSearchParams
|
||||
): Promise<ISearchIssueResponse[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/search-issues/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
62
apps/web/core/services/sticky.service.ts
Normal file
62
apps/web/core/services/sticky.service.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
// helpers
|
||||
import { STICKIES_PER_PAGE, API_BASE_URL } from "@plane/constants";
|
||||
import type { TSticky } from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class StickyService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async createSticky(workspaceSlug: string, payload: Partial<TSticky>) {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/stickies/`, payload)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getStickies(
|
||||
workspaceSlug: string,
|
||||
cursor: string,
|
||||
query?: string,
|
||||
per_page?: number
|
||||
): Promise<{ results: TSticky[]; total_pages: number }> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/stickies/`, {
|
||||
params: {
|
||||
cursor,
|
||||
per_page: per_page || STICKIES_PER_PAGE,
|
||||
query,
|
||||
},
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getSticky(workspaceSlug: string, id: string) {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/stickies/${id}`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateSticky(workspaceSlug: string, id: string, data: Partial<TSticky>) {
|
||||
return await this.patch(`/api/workspaces/${workspaceSlug}/stickies/${id}/`, data)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteSticky(workspaceSlug: string, id: string) {
|
||||
return await this.delete(`/api/workspaces/${workspaceSlug}/stickies/${id}`)
|
||||
.then((res) => res?.data)
|
||||
.catch((err) => {
|
||||
throw err?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
23
apps/web/core/services/timezone.service.ts
Normal file
23
apps/web/core/services/timezone.service.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { TTimezones } from "@plane/types";
|
||||
// helpers
|
||||
// api services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class TimezoneService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetch(): Promise<TTimezones> {
|
||||
return this.get(`/api/timezones/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const timezoneService = new TimezoneService();
|
||||
|
||||
export default timezoneService;
|
||||
265
apps/web/core/services/user.service.ts
Normal file
265
apps/web/core/services/user.service.ts
Normal file
@@ -0,0 +1,265 @@
|
||||
// services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
TIssue,
|
||||
IUser,
|
||||
IUserActivityResponse,
|
||||
IInstanceAdminStatus,
|
||||
IUserProfileData,
|
||||
IUserProfileProjectSegregation,
|
||||
IUserSettings,
|
||||
IUserEmailNotificationSettings,
|
||||
TIssuesResponse,
|
||||
TUserProfile,
|
||||
} from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// helpers
|
||||
|
||||
export class UserService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
currentUserConfig() {
|
||||
return {
|
||||
url: `${this.baseURL}/api/users/me/`,
|
||||
};
|
||||
}
|
||||
|
||||
async userIssues(
|
||||
workspaceSlug: string,
|
||||
params: any
|
||||
): Promise<
|
||||
| {
|
||||
[key: string]: TIssue[];
|
||||
}
|
||||
| TIssue[]
|
||||
> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/my-issues/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async currentUser(): Promise<IUser> {
|
||||
// Using validateStatus: null to bypass interceptors for unauthorized errors.
|
||||
return this.get("/api/users/me/", { validateStatus: null })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getCurrentUserProfile(): Promise<TUserProfile> {
|
||||
return this.get("/api/users/me/profile/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
async updateCurrentUserProfile(data: any): Promise<any> {
|
||||
return this.patch("/api/users/me/profile/", data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async getCurrentUserAccounts(): Promise<any> {
|
||||
return this.get("/api/users/me/accounts/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async currentUserInstanceAdminStatus(): Promise<IInstanceAdminStatus> {
|
||||
return this.get("/api/users/me/instance-admin/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async currentUserSettings(bustCache: boolean = false): Promise<IUserSettings> {
|
||||
const url = bustCache ? `/api/users/me/settings/?t=${Date.now()}` : "/api/users/me/settings/";
|
||||
return this.get(url)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async currentUserEmailNotificationSettings(): Promise<IUserEmailNotificationSettings> {
|
||||
return this.get("/api/users/me/notification-preferences/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateUser(data: Partial<IUser>): Promise<any> {
|
||||
return this.patch("/api/users/me/", data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateUserOnBoard(): Promise<any> {
|
||||
return this.patch("/api/users/me/onboard/", {
|
||||
is_onboarded: true,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateUserTourCompleted(): Promise<any> {
|
||||
return this.patch("/api/users/me/tour-completed/", {
|
||||
is_tour_completed: true,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateCurrentUserEmailNotificationSettings(data: Partial<IUserEmailNotificationSettings>): Promise<any> {
|
||||
return this.patch("/api/users/me/notification-preferences/", data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserActivity(params: { per_page: number; cursor?: string }): Promise<IUserActivityResponse> {
|
||||
return this.get("/api/users/me/activities/", { params })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async changePassword(token: string, data: { old_password?: string; new_password: string }): Promise<any> {
|
||||
return this.post(`/auth/change-password/`, data, {
|
||||
headers: {
|
||||
"X-CSRFTOKEN": token,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfileData(workspaceSlug: string, userId: string): Promise<IUserProfileData> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-stats/${userId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfileProjectsSegregation(
|
||||
workspaceSlug: string,
|
||||
userId: string
|
||||
): Promise<IUserProfileProjectSegregation> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-profile/${userId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfileActivity(
|
||||
workspaceSlug: string,
|
||||
userId: string,
|
||||
params: {
|
||||
per_page: number;
|
||||
cursor?: string;
|
||||
}
|
||||
): Promise<IUserActivityResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/user-activity/${userId}/`, {
|
||||
params,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async downloadProfileActivity(
|
||||
workspaceSlug: string,
|
||||
userId: string,
|
||||
data: {
|
||||
date: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/user-activity/${userId}/export/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getUserProfileIssues(
|
||||
workspaceSlug: string,
|
||||
userId: string,
|
||||
params: any,
|
||||
config = {}
|
||||
): Promise<TIssuesResponse> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/user-issues/${userId}/`,
|
||||
{
|
||||
params,
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deactivateAccount() {
|
||||
return this.delete(`/api/users/me/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async leaveWorkspace(workspaceSlug: string) {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/members/leave/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async joinProject(workspaceSlug: string, project_ids: string[]): Promise<any> {
|
||||
return this.post(`/api/users/me/workspaces/${workspaceSlug}/projects/invitations/`, { project_ids })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async leaveProject(workspaceSlug: string, projectId: string) {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/leave/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const userService = new UserService();
|
||||
|
||||
export default userService;
|
||||
81
apps/web/core/services/view.service.ts
Normal file
81
apps/web/core/services/view.service.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IProjectView } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// types
|
||||
// helpers
|
||||
|
||||
export class ViewService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async patchView(workspaceSlug: string, projectId: string, viewId: string, data: Partial<IProjectView>): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteView(workspaceSlug: string, projectId: string, viewId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getViews(workspaceSlug: string, projectId: string): Promise<IProjectView[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getViewDetails(workspaceSlug: string, projectId: string, viewId: string): Promise<IProjectView> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getViewIssues(workspaceSlug: string, projectId: string, viewId: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/issues/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async addViewToFavorites(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: {
|
||||
view: string;
|
||||
}
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async removeViewFromFavorites(workspaceSlug: string, projectId: string, viewId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
60
apps/web/core/services/webhook.service.ts
Normal file
60
apps/web/core/services/webhook.service.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
// api services
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type { IWebhook } from "@plane/types";
|
||||
import { APIService } from "@/services/api.service";
|
||||
// helpers
|
||||
// types
|
||||
|
||||
export class WebhookService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchWebhooksList(workspaceSlug: string): Promise<IWebhook[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/webhooks/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchWebhookDetails(workspaceSlug: string, webhookId: string): Promise<IWebhook> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/webhooks/${webhookId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createWebhook(workspaceSlug: string, data = {}): Promise<IWebhook> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/webhooks/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWebhook(workspaceSlug: string, webhookId: string, data = {}): Promise<IWebhook> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/webhooks/${webhookId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWebhook(workspaceSlug: string, webhookId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/webhooks/${webhookId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async regenerateSecretKey(workspaceSlug: string, webhookId: string): Promise<IWebhook> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/webhooks/${webhookId}/regenerate/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
118
apps/web/core/services/workspace-notification.service.ts
Normal file
118
apps/web/core/services/workspace-notification.service.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
/* eslint-disable no-useless-catch */
|
||||
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
TNotificationPaginatedInfo,
|
||||
TNotificationPaginatedInfoQueryParams,
|
||||
TNotification,
|
||||
TUnreadNotificationsCount,
|
||||
} from "@plane/types";
|
||||
// helpers
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class WorkspaceNotificationService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async fetchUnreadNotificationsCount(workspaceSlug: string): Promise<TUnreadNotificationsCount | undefined> {
|
||||
try {
|
||||
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/users/notifications/unread/`);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchNotifications(
|
||||
workspaceSlug: string,
|
||||
params: TNotificationPaginatedInfoQueryParams
|
||||
): Promise<TNotificationPaginatedInfo | undefined> {
|
||||
try {
|
||||
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/users/notifications`, {
|
||||
params,
|
||||
});
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateNotificationById(
|
||||
workspaceSlug: string,
|
||||
notificationId: string,
|
||||
payload: Partial<TNotification>
|
||||
): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/`,
|
||||
payload
|
||||
);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async markNotificationAsRead(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.post(`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/read/`);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async markNotificationAsUnread(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/read/`
|
||||
);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async markNotificationAsArchived(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.post(
|
||||
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/archive/`
|
||||
);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async markNotificationAsUnArchived(
|
||||
workspaceSlug: string,
|
||||
notificationId: string
|
||||
): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.delete(
|
||||
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/archive/`
|
||||
);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async markAllNotificationsAsRead(
|
||||
workspaceSlug: string,
|
||||
payload: TNotificationPaginatedInfoQueryParams
|
||||
): Promise<TNotification | undefined> {
|
||||
try {
|
||||
const { data } = await this.post(`/api/workspaces/${workspaceSlug}/users/notifications/mark-all-read/`, payload);
|
||||
return data || undefined;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workspaceNotificationService = new WorkspaceNotificationService();
|
||||
|
||||
export default workspaceNotificationService;
|
||||
389
apps/web/core/services/workspace.service.ts
Normal file
389
apps/web/core/services/workspace.service.ts
Normal file
@@ -0,0 +1,389 @@
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
IWorkspace,
|
||||
IWorkspaceMemberMe,
|
||||
IWorkspaceMember,
|
||||
IWorkspaceMemberInvitation,
|
||||
ILastActiveWorkspaceDetails,
|
||||
IWorkspaceSearchResults,
|
||||
IProductUpdateResponse,
|
||||
IWorkspaceBulkInviteFormData,
|
||||
IWorkspaceViewProps,
|
||||
IUserProjectsRole,
|
||||
IWorkspaceView,
|
||||
TIssuesResponse,
|
||||
TLink,
|
||||
TSearchResponse,
|
||||
TSearchEntityRequestPayload,
|
||||
TWidgetEntityData,
|
||||
TActivityEntityData,
|
||||
IWorkspaceSidebarNavigationItem,
|
||||
IWorkspaceSidebarNavigation,
|
||||
} from "@plane/types";
|
||||
// services
|
||||
import { APIService } from "@/services/api.service";
|
||||
|
||||
export class WorkspaceService extends APIService {
|
||||
constructor() {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async userWorkspaces(): Promise<IWorkspace[]> {
|
||||
return this.get("/api/users/me/workspaces/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspace(workspaceSlug: string): Promise<IWorkspace> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||
return this.post("/api/workspaces/", data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspace(workspaceSlug: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async inviteWorkspace(workspaceSlug: string, data: IWorkspaceBulkInviteFormData): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/invitations/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async joinWorkspace(workspaceSlug: string, invitationId: string, data: any): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/join/`, data, {
|
||||
headers: {},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async joinWorkspaces(data: any): Promise<any> {
|
||||
return this.post("/api/users/me/workspaces/invitations/", data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getLastActiveWorkspaceAndProjects(): Promise<ILastActiveWorkspaceDetails> {
|
||||
return this.get("/api/users/last-visited-workspace/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async userWorkspaceInvitations(): Promise<IWorkspaceMemberInvitation[]> {
|
||||
return this.get("/api/users/me/workspaces/invitations/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceMemberMe(workspaceSlug: string): Promise<IWorkspaceMemberMe> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/workspace-members/me/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceView(workspaceSlug: string, data: { view_props: IWorkspaceViewProps }): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/workspace-views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchWorkspaceMembers(workspaceSlug: string): Promise<IWorkspaceMember[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/members/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceMember(
|
||||
workspaceSlug: string,
|
||||
memberId: string,
|
||||
data: Partial<IWorkspaceMember>
|
||||
): Promise<IWorkspaceMember> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/members/${memberId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceMember(workspaceSlug: string, memberId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/members/${memberId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceInvitations(workspaceSlug: string): Promise<IWorkspaceMemberInvitation[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/invitations/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceInvitation(workspaceSlug: string, invitationId: string): Promise<IWorkspaceMemberInvitation> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/join/`, { headers: {} })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceInvitation(
|
||||
workspaceSlug: string,
|
||||
invitationId: string,
|
||||
data: Partial<IWorkspaceMember>
|
||||
): Promise<any> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceInvitations(workspaceSlug: string, invitationId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async workspaceSlugCheck(slug: string): Promise<any> {
|
||||
return this.get(`/api/workspace-slug-check/?slug=${slug}`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async searchWorkspace(
|
||||
workspaceSlug: string,
|
||||
params: {
|
||||
project_id?: string;
|
||||
search: string;
|
||||
workspace_search: boolean;
|
||||
}
|
||||
): Promise<IWorkspaceSearchResults> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/search/`, {
|
||||
params,
|
||||
})
|
||||
.then((res) => res?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
async getProductUpdates(): Promise<IProductUpdateResponse[]> {
|
||||
return this.get("/api/release-notes/")
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async createView(workspaceSlug: string, data: Partial<IWorkspaceView>): Promise<IWorkspaceView> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/views/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateView(workspaceSlug: string, viewId: string, data: Partial<IWorkspaceView>): Promise<IWorkspaceView> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/views/${viewId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteView(workspaceSlug: string, viewId: string): Promise<any> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getAllViews(workspaceSlug: string): Promise<IWorkspaceView[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/views/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getViewDetails(workspaceSlug: string, viewId: string): Promise<IWorkspaceView> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/views/${viewId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getViewIssues(workspaceSlug: string, params: any, config = {}): Promise<TIssuesResponse> {
|
||||
const path = params.expand?.includes("issue_relation")
|
||||
? `/api/workspaces/${workspaceSlug}/issues-detail/`
|
||||
: `/api/workspaces/${workspaceSlug}/issues/`;
|
||||
return this.get(
|
||||
path,
|
||||
{
|
||||
params,
|
||||
},
|
||||
config
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getWorkspaceUserProjectsRole(workspaceSlug: string): Promise<IUserProjectsRole> {
|
||||
return this.get(`/api/users/me/workspaces/${workspaceSlug}/project-roles/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// quicklinks
|
||||
async fetchWorkspaceLinks(workspaceSlug: string): Promise<TLink[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/quick-links/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async createWorkspaceLink(workspaceSlug: string, data: Partial<TLink>): Promise<TLink> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/quick-links/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceLink(workspaceSlug: string, linkId: string, data: Partial<TLink>): Promise<TLink> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/quick-links/${linkId}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkspaceLink(workspaceSlug: string, linkId: string): Promise<void> {
|
||||
return this.delete(`/api/workspaces/${workspaceSlug}/quick-links/${linkId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async searchEntity(workspaceSlug: string, params: TSearchEntityRequestPayload): Promise<TSearchResponse> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/entity-search/`, {
|
||||
params: {
|
||||
...params,
|
||||
query_type: params.query_type.join(","),
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// recents
|
||||
async fetchWorkspaceRecents(workspaceSlug: string, entity_name?: string): Promise<TActivityEntityData[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/recent-visits/`, {
|
||||
params: {
|
||||
entity_name,
|
||||
},
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
// widgets
|
||||
async fetchWorkspaceWidgets(workspaceSlug: string): Promise<TWidgetEntityData[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/home-preferences/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkspaceWidget(
|
||||
workspaceSlug: string,
|
||||
widgetKey: string,
|
||||
data: Partial<TWidgetEntityData>
|
||||
): Promise<TWidgetEntityData> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/home-preferences/${widgetKey}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async fetchSidebarNavigationPreferences(workspaceSlug: string): Promise<IWorkspaceSidebarNavigation> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/sidebar-preferences/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
|
||||
async updateSidebarPreference(
|
||||
workspaceSlug: string,
|
||||
key: string,
|
||||
data: Partial<IWorkspaceSidebarNavigationItem>
|
||||
): Promise<IWorkspaceSidebarNavigationItem> {
|
||||
return this.patch(`/api/workspaces/${workspaceSlug}/sidebar-preferences/${key}/`, data)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user