build: create frontend and backend dockerfiles docker compose and scripts

This commit is contained in:
pablohashescobar 2022-12-01 19:18:10 +05:30
parent 26ec1e8c15
commit 949b62d13f
151 changed files with 186 additions and 1 deletions

3
apps/plane/lib/cookie.ts Normal file
View file

@ -0,0 +1,3 @@
export const setCookie = () => {
// add set cookie logic here
};

View file

@ -0,0 +1,32 @@
import React from "react";
// next
import type { NextPage } from "next";
// redirect
import redirect from "lib/redirect";
const withAuth = (WrappedComponent: NextPage) => {
const Wrapper: NextPage<any> = (props) => {
return <WrappedComponent {...props} />;
};
Wrapper.getInitialProps = async (ctx) => {
const isServer = typeof window === "undefined";
const cookies = isServer ? ctx?.req?.headers.cookie : document.cookie;
const token = cookies?.split("accessToken=")?.[1]?.split(";")?.[0];
if (!token) {
redirect(ctx, "/signin");
}
const pageProps =
WrappedComponent.getInitialProps && (await WrappedComponent.getInitialProps(ctx));
return { ...pageProps };
};
return Wrapper;
};
export default withAuth;

View file

@ -0,0 +1,21 @@
import { useEffect } from "react";
// Updates the height of a <textarea> when the value changes.
const useAutosizeTextArea = (
textAreaRef: HTMLTextAreaElement | null,
value: any
) => {
useEffect(() => {
if (textAreaRef) {
// We need to reset the height momentarily to get the correct scrollHeight for the textarea
textAreaRef.style.height = "0px";
const scrollHeight = textAreaRef.scrollHeight;
// We then set the height directly, outside of the render loop
// Trying to set this with state or a ref will product an incorrect value.
textAreaRef.style.height = scrollHeight + "px";
}
}, [textAreaRef, value]);
};
export default useAutosizeTextArea;

View file

@ -0,0 +1,86 @@
import { useState, useContext, useEffect, useCallback } from "react";
// swr
import useSWR from "swr";
// api routes
import { ISSUE_PROPERTIES_ENDPOINT } from "constants/api-routes";
// services
import issueServices from "lib/services/issues.services";
// hooks
import useUser from "./useUser";
// types
import { IssuePriorities, Properties } from "types";
const initialValues: Properties = {
name: true,
key: true,
parent: false,
project: false,
state: true,
assignee: true,
description: false,
priority: false,
start_date: false,
target_date: false,
sequence_id: false,
attachments: false,
children: false,
cycle: false,
};
const useIssuesProperties = (workspaceSlug?: string, projectId?: string) => {
const [properties, setProperties] = useState<Properties>(initialValues);
const { user } = useUser();
const { data: issueProperties } = useSWR<IssuePriorities>(
workspaceSlug && projectId ? ISSUE_PROPERTIES_ENDPOINT(workspaceSlug, projectId) : null,
workspaceSlug && projectId
? () => issueServices.getIssueProperties(workspaceSlug, projectId)
: null,
{
shouldRetryOnError: false,
}
);
useEffect(() => {
if (!issueProperties || !workspaceSlug || !projectId || !user) return;
setProperties({ ...initialValues, ...issueProperties.properties });
if (Object.keys(issueProperties).length === 0)
issueServices.createIssueProperties(workspaceSlug, projectId, {
properties: { ...initialValues },
user: user.id,
});
else if (Object.keys(issueProperties?.properties).length === 0)
issueServices.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, {
properties: { ...initialValues },
user: user.id,
});
}, [issueProperties, workspaceSlug, projectId, user]);
const updateIssueProperties = useCallback(
(key: keyof Properties) => {
if (!workspaceSlug || !projectId || !issueProperties || !user) return;
setProperties((prev) => ({ ...prev, [key]: !prev[key] }));
if (Object.keys(issueProperties).length > 0) {
issueServices.patchIssueProperties(workspaceSlug, projectId, issueProperties.id, {
properties: {
...issueProperties.properties,
[key]: !issueProperties.properties[key],
},
user: user.id,
});
} else {
issueServices.createIssueProperties(workspaceSlug, projectId, {
properties: { ...initialValues },
user: user.id,
});
}
},
[workspaceSlug, projectId, issueProperties, user]
);
return [properties, updateIssueProperties] as const;
};
export default useIssuesProperties;

View file

@ -0,0 +1,38 @@
import { useState, useEffect, useCallback } from "react";
const useLocalStorage = <T,>(
key: string,
initialValue?: T extends Function ? never : T | (() => T)
) => {
const [value, setValue] = useState<T | string>("");
useEffect(() => {
const data = window.localStorage.getItem(key);
if (data !== null && data !== "undefined") setValue(JSON.parse(data));
else setValue(typeof initialValue === "function" ? initialValue() : initialValue);
}, [key, initialValue]);
const updateState = useCallback(
(value: T) => {
if (!value) window.localStorage.removeItem(key);
else window.localStorage.setItem(key, JSON.stringify(value));
setValue(value);
window.dispatchEvent(new Event(`local-storage-change-${key}`));
},
[key]
);
const reHydrateState = useCallback(() => {
const data = window.localStorage.getItem(key);
if (data !== null) setValue(JSON.parse(data));
}, [key]);
useEffect(() => {
window.addEventListener(`local-storage-change-${key}`, reHydrateState);
return () => window.removeEventListener(`local-storage-change-${key}`, reHydrateState);
}, [reHydrateState, key]);
return [value, updateState];
};
export default useLocalStorage;

View file

@ -0,0 +1,11 @@
import { useContext } from "react";
import { themeContext } from "contexts/theme.context";
const useTheme = () => {
const themeContextData = useContext(themeContext);
return themeContextData;
};
export default useTheme;

View file

@ -0,0 +1,11 @@
import { useContext } from "react";
import { toastContext } from "contexts/toast.context";
const useToast = () => {
const toastContextData = useContext(toastContext);
return toastContextData;
};
export default useToast;

View file

@ -0,0 +1,42 @@
import { useContext, useEffect } from "react";
import { useRouter } from "next/router";
// context
import { UserContext } from "contexts/user.context";
interface useUserOptions {
redirectTo?: string;
}
const useUser = (options: useUserOptions = {}) => {
// props
const { redirectTo = null } = options;
// context
const contextData = useContext(UserContext);
// router
const router = useRouter();
/**
* Checks for redirect url and user details from the API.
* if the user is not authenticated, user will be redirected
* to the provided redirectTo route.
*/
useEffect(() => {
if (!contextData?.user || !redirectTo) return;
if (!contextData?.user) {
if (redirectTo) {
router?.pathname !== redirectTo && router.push(redirectTo);
}
router?.pathname !== "/signin" && router.push("/signin");
}
if (contextData?.user) {
if (redirectTo) {
router?.pathname !== redirectTo && router.push(redirectTo);
}
}
}, [contextData?.user, redirectTo, router]);
return contextData;
};
export default useUser;

View file

@ -0,0 +1,17 @@
// next imports
import type { NextPageContext } from "next";
import Router from "next/router";
const redirect = (context: NextPageContext, target: any) => {
if (context.res) {
// server
// 303: "See other"
context.res.writeHead(301, { Location: target });
context.res.end();
} else {
// In the browser, we just pretend like this never even happened ;)
Router.push(target);
}
};
export default redirect;

View file

@ -0,0 +1,107 @@
import axios from "axios";
import Cookies from "js-cookie";
abstract class APIService {
protected baseURL: string;
protected headers: any = {};
constructor(baseURL: string) {
this.baseURL = baseURL;
}
setRefreshToken(token: string) {
Cookies.set("refreshToken", token);
}
getRefreshToken() {
return Cookies.get("refreshToken");
}
purgeRefreshToken() {
Cookies.remove("refreshToken", { path: "/" });
}
setAccessToken(token: string) {
Cookies.set("accessToken", token);
}
getAccessToken() {
return Cookies.get("accessToken");
}
purgeAccessToken() {
Cookies.remove("accessToken", { path: "/" });
}
getHeaders() {
return {
Authorization: `Bearer ${this.getAccessToken()}`,
};
}
get(url: string, config = {}): Promise<any> {
return axios({
method: "get",
url: this.baseURL + url,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
});
}
post(url: string, data = {}, config = {}): Promise<any> {
return axios({
method: "post",
url: this.baseURL + url,
data,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
});
}
put(url: string, data = {}, config = {}): Promise<any> {
return axios({
method: "put",
url: this.baseURL + url,
data,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
});
}
patch(url: string, data = {}, config = {}): Promise<any> {
return axios({
method: "patch",
url: this.baseURL + url,
data,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
});
}
delete(url: string, config = {}): Promise<any> {
return axios({
method: "delete",
url: this.baseURL + url,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
});
}
mediaUpload(url: string, data = {}, config = {}): Promise<any> {
return axios({
method: "post",
url: this.baseURL + url,
data,
headers: this.getAccessToken()
? { ...this.getHeaders(), "Content-Type": "multipart/form-data" }
: {},
...config,
});
}
request(config = {}) {
return axios(config);
}
}
export default APIService;

View file

@ -0,0 +1,71 @@
// api routes
import { SIGN_IN_ENDPOINT, SOCIAL_AUTH_ENDPOINT, MAGIC_LINK_GENERATE, MAGIC_LINK_SIGNIN } from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class AuthService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async emailLogin(data: any) {
return this.post(SIGN_IN_ENDPOINT, data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async socialAuth(data: any) {
return this.post(SOCIAL_AUTH_ENDPOINT, data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async emailCode(data: any) {
return this.post(MAGIC_LINK_GENERATE, data, { headers: {} })
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async magicSignIn(data: any) {
const response = await this.post(MAGIC_LINK_SIGNIN, data, { headers: {} });
if (response?.status === 200) {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
}
throw response.response.data;
}
async signOut(data = {}) {
return this.post("/api/sign-out/", data)
.then((response) => {
this.purgeAccessToken();
this.purgeRefreshToken();
return response?.data;
})
.catch((error) => {
this.purgeAccessToken();
this.purgeRefreshToken();
throw error?.response?.data;
});
}
}
export default new AuthService();

View file

@ -0,0 +1,84 @@
// api routes
import { CYCLES_ENDPOINT, CYCLE_DETAIL } from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class ProjectCycleServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async createCycle(workspace_slug: string, projectId: string, data: any): Promise<any> {
return this.post(CYCLES_ENDPOINT(workspace_slug, projectId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getCycles(workspace_slug: string, projectId: string): Promise<any> {
return this.get(CYCLES_ENDPOINT(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getCycleIssues(workspace_slug: string, projectId: string, cycleId: string): Promise<any> {
return this.get(CYCLE_DETAIL(workspace_slug, projectId, cycleId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getCycle(workspace_slug: string, projectId: string, cycleId: string): Promise<any> {
return this.get(CYCLE_DETAIL(workspace_slug, projectId, cycleId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateCycle(
workspace_slug: string,
projectId: string,
cycleId: string,
data: any
): Promise<any> {
return this.put(
CYCLE_DETAIL(workspace_slug, projectId, cycleId).replace("cycle-issues/", ""),
data
)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteCycle(workspace_slug: string, projectId: string, cycleId: string): Promise<any> {
return this.delete(
CYCLE_DETAIL(workspace_slug, projectId, cycleId).replace("cycle-issues/", "")
)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new ProjectCycleServices();

View file

@ -0,0 +1,24 @@
// api routes
import { S3_URL } from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class FileServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async uploadFile(file: FormData): Promise<any> {
return this.mediaUpload(S3_URL, file)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new FileServices();

View file

@ -0,0 +1,242 @@
// api routes
import {
ISSUES_ENDPOINT,
ISSUE_DETAIL,
ISSUE_ACTIVITIES,
ISSUE_COMMENTS,
ISSUE_COMMENT_DETAIL,
ISSUE_PROPERTIES_ENDPOINT,
CYCLE_DETAIL,
ISSUE_LABELS,
} from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
import { IIssue, IIssueComment } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class ProjectIssuesServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async createIssues(workspace_slug: string, projectId: string, data: any): Promise<any> {
return this.post(ISSUES_ENDPOINT(workspace_slug, projectId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssues(workspace_slug: string, projectId: string): Promise<any> {
return this.get(ISSUES_ENDPOINT(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssue(workspace_slug: string, projectId: string, issueId: string): Promise<any> {
return this.get(ISSUE_DETAIL(workspace_slug, projectId, issueId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueActivities(
workspace_slug: string,
projectId: string,
issueId: string
): Promise<any> {
return this.get(ISSUE_ACTIVITIES(workspace_slug, projectId, issueId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueComments(workspace_slug: string, projectId: string, issueId: string): Promise<any> {
return this.get(ISSUE_COMMENTS(workspace_slug, projectId, issueId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueProperties(workspace_slug: string, projectId: string): Promise<any> {
return this.get(ISSUE_PROPERTIES_ENDPOINT(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async addIssueToSprint(
workspace_slug: string,
projectId: string,
cycleId: string,
data: {
issue: string;
}
) {
console.log(data);
return this.post(CYCLE_DETAIL(workspace_slug, projectId, cycleId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueProperties(workspace_slug: string, projectId: string, data: any): Promise<any> {
return this.post(ISSUE_PROPERTIES_ENDPOINT(workspace_slug, projectId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssueProperties(
workspace_slug: string,
projectId: string,
issuePropertyId: string,
data: any
): Promise<any> {
return this.patch(
ISSUE_PROPERTIES_ENDPOINT(workspace_slug, projectId) + `${issuePropertyId}/`,
data
)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueComment(
workspace_slug: string,
projectId: string,
issueId: string,
data: any
): Promise<any> {
return this.post(ISSUE_COMMENTS(workspace_slug, projectId, issueId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssueComment(
workspace_slug: string,
projectId: string,
issueId: string,
commentId: string,
data: IIssueComment
): Promise<any> {
return this.patch(ISSUE_COMMENT_DETAIL(workspace_slug, projectId, issueId, commentId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssueComment(
workspace_slug: string,
projectId: string,
issueId: string,
commentId: string
): Promise<any> {
return this.delete(ISSUE_COMMENT_DETAIL(workspace_slug, projectId, issueId, commentId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueLabels(workspace_slug: string, projectId: string): Promise<any> {
return this.get(ISSUE_LABELS(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async createIssueLabel(workspace_slug: string, projectId: string, data: any): Promise<any> {
return this.post(ISSUE_LABELS(workspace_slug, projectId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateIssue(
workspace_slug: string,
projectId: string,
issueId: string,
data: any
): Promise<any> {
return this.put(ISSUE_DETAIL(workspace_slug, projectId, issueId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchIssue(
workspace_slug: string,
projectId: string,
issueId: string,
data: Partial<IIssue>
): Promise<any> {
return this.patch(ISSUE_DETAIL(workspace_slug, projectId, issueId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteIssue(workspace_slug: string, projectId: string, issuesId: string): Promise<any> {
return this.delete(ISSUE_DETAIL(workspace_slug, projectId, issuesId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new ProjectIssuesServices();

View file

@ -0,0 +1,192 @@
// api routes
import {
CHECK_PROJECT_IDENTIFIER,
INVITE_PROJECT,
JOIN_PROJECT,
PROJECTS_ENDPOINT,
PROJECT_DETAIL,
PROJECT_INVITATIONS,
PROJECT_INVITATION_DETAIL,
PROJECT_MEMBERS,
PROJECT_MEMBER_DETAIL,
USER_PROJECT_INVITATIONS,
} from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class ProjectServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async createProject(workspace_slug: string, data: any): Promise<any> {
return this.post(PROJECTS_ENDPOINT(workspace_slug), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async checkProjectIdentifierAvailability(workspaceSlug: string, data: string): Promise<any> {
return this.get(CHECK_PROJECT_IDENTIFIER(workspaceSlug), {
params: {
name: data,
},
})
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getProjects(workspace_slug: string): Promise<any> {
return this.get(PROJECTS_ENDPOINT(workspace_slug))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getProject(workspace_slug: string, project_id: string): Promise<any> {
return this.get(PROJECT_DETAIL(workspace_slug, project_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateProject(workspace_slug: string, project_id: string, data: any): Promise<any> {
return this.patch(PROJECT_DETAIL(workspace_slug, project_id), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProject(workspace_slug: string, project_id: string): Promise<any> {
return this.delete(PROJECT_DETAIL(workspace_slug, project_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async inviteProject(workspace_slug: string, project_id: string, data: any): Promise<any> {
return this.post(INVITE_PROJECT(workspace_slug, project_id), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async joinProject(workspace_slug: string, data: any): Promise<any> {
return this.post(JOIN_PROJECT(workspace_slug), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async joinProjects(data: any): Promise<any> {
return this.post(USER_PROJECT_INVITATIONS, data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async projectMembers(workspace_slug: string, project_id: string): Promise<any> {
return this.get(PROJECT_MEMBERS(workspace_slug, project_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectMember(
workspace_slug: string,
project_id: string,
memberId: string
): Promise<any> {
return this.put(PROJECT_MEMBER_DETAIL(workspace_slug, project_id, memberId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectMember(
workspace_slug: string,
project_id: string,
memberId: string
): Promise<any> {
return this.delete(PROJECT_MEMBER_DETAIL(workspace_slug, project_id, memberId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async projectInvitations(workspace_slug: string, project_id: string): Promise<any> {
return this.get(PROJECT_INVITATIONS(workspace_slug, project_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateProjectInvitation(
workspace_slug: string,
project_id: string,
invitation_id: string
): Promise<any> {
return this.put(PROJECT_INVITATION_DETAIL(workspace_slug, project_id, invitation_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectInvitation(
workspace_slug: string,
project_id: string,
invitation_id: string
): Promise<any> {
return this.delete(PROJECT_INVITATION_DETAIL(workspace_slug, project_id, invitation_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new ProjectServices();

View file

@ -0,0 +1,98 @@
// api routes
import { STATES_ENDPOINT, STATE_DETAIL, ISSUES_BY_STATE } from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
// types
import type { IState } from "types";
class ProjectStateServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async createState(workspace_slug: string, projectId: string, data: any): Promise<any> {
return this.post(STATES_ENDPOINT(workspace_slug, projectId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getStates(workspace_slug: string, projectId: string): Promise<any> {
return this.get(STATES_ENDPOINT(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getIssuesByState(workspace_slug: string, projectId: string): Promise<any> {
return this.get(ISSUES_BY_STATE(workspace_slug, projectId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getState(workspace_slug: string, projectId: string, stateId: string): Promise<any> {
return this.get(STATE_DETAIL(workspace_slug, projectId, stateId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateState(
workspace_slug: string,
projectId: string,
stateId: string,
data: IState
): Promise<any> {
return this.put(STATE_DETAIL(workspace_slug, projectId, stateId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async patchState(
workspace_slug: string,
projectId: string,
stateId: string,
data: Partial<IState>
): Promise<any> {
return this.patch(STATE_DETAIL(workspace_slug, projectId, stateId), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteState(workspace_slug: string, projectId: string, stateId: string): Promise<any> {
return this.delete(STATE_DETAIL(workspace_slug, projectId, stateId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new ProjectStateServices();

View file

@ -0,0 +1,62 @@
// services
import { USER_ENDPOINT, USER_ISSUES_ENDPOINT, USER_ONBOARD_ENDPOINT } from "constants/api-routes";
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class UserService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
currentUserConfig() {
return {
url: `${this.baseURL}/api/users/me/`,
headers: this.getHeaders(),
};
}
async userIssues(): Promise<any> {
return this.get(USER_ISSUES_ENDPOINT)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async currentUser(): Promise<any> {
if (!this.getAccessToken()) return null;
return this.get(USER_ENDPOINT)
.then((response) => {
return response?.data;
})
.catch((error) => {
this.purgeAccessToken();
throw error?.response?.data;
});
}
async updateUser(data = {}): Promise<any> {
return this.patch(USER_ENDPOINT, data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateUserOnBoard(): Promise<any> {
return this.patch(USER_ONBOARD_ENDPOINT, { is_onboarded: true })
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new UserService();

View file

@ -0,0 +1,173 @@
// api routes
import {
USER_WORKSPACES,
WORKSPACES_ENDPOINT,
INVITE_WORKSPACE,
WORKSPACE_DETAIL,
JOIN_WORKSPACE,
WORKSPACE_MEMBERS,
WORKSPACE_MEMBER_DETAIL,
WORKSPACE_INVITATIONS,
WORKSPACE_INVITATION_DETAIL,
USER_WORKSPACE_INVITATION,
USER_WORKSPACE_INVITATIONS,
} from "constants/api-routes";
// services
import APIService from "lib/services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
class WorkspaceService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
}
async userWorkspaces(): Promise<any> {
return this.get(USER_WORKSPACES)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async createWorkspace(data: any): Promise<any> {
return this.post(WORKSPACES_ENDPOINT, data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateWorkspace(workspace_slug: string, data: any): Promise<any> {
return this.patch(WORKSPACE_DETAIL(workspace_slug), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteWorkspace(workspace_slug: string): Promise<any> {
return this.delete(WORKSPACE_DETAIL(workspace_slug))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async inviteWorkspace(workspace_slug: string, data: any): Promise<any> {
return this.post(INVITE_WORKSPACE(workspace_slug), data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async joinWorkspace(workspace_slug: string, InvitationId: string, data: any): Promise<any> {
return this.post(JOIN_WORKSPACE(workspace_slug, InvitationId), data, {
headers: {},
})
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async joinWorkspaces(data: any): Promise<any> {
return this.post(USER_WORKSPACE_INVITATIONS, data)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async userWorkspaceInvitations(): Promise<any> {
return this.get(USER_WORKSPACE_INVITATIONS)
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async workspaceMembers(workspace_slug: string): Promise<any> {
return this.get(WORKSPACE_MEMBERS(workspace_slug))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateWorkspaceMember(workspace_slug: string, memberId: string): Promise<any> {
return this.put(WORKSPACE_MEMBER_DETAIL(workspace_slug, memberId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteWorkspaceMember(workspace_slug: string, memberId: string): Promise<any> {
return this.delete(WORKSPACE_MEMBER_DETAIL(workspace_slug, memberId))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async workspaceInvitations(workspace_slug: string): Promise<any> {
return this.get(WORKSPACE_INVITATIONS(workspace_slug))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async getWorkspaceInvitation(invitation_id: string): Promise<any> {
return this.get(USER_WORKSPACE_INVITATION(invitation_id), { headers: {} })
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async updateWorkspaceInvitation(workspace_slug: string, invitation_id: string): Promise<any> {
return this.put(WORKSPACE_INVITATION_DETAIL(workspace_slug, invitation_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async deleteWorkspaceInvitations(workspace_slug: string, invitation_id: string): Promise<any> {
return this.delete(WORKSPACE_INVITATION_DETAIL(workspace_slug, invitation_id))
.then((response) => {
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
}
export default new WorkspaceService();