diff --git a/.env.example b/.env.example index 66237fd6b1e..1d95c56a067 100644 --- a/.env.example +++ b/.env.example @@ -21,6 +21,8 @@ NEXT_PUBLIC_TRACK_EVENTS=0 NEXT_PUBLIC_SLACK_CLIENT_ID="" # For Telemetry, set it to "app.plane.so" NEXT_PUBLIC_PLAUSIBLE_DOMAIN="" +# public boards deploy url +NEXT_PUBLIC_DEPLOY_URL="" # Backend # Debug value for api server use it as 0 for production use diff --git a/apps/app/components/project/publish-project/modal.tsx b/apps/app/components/project/publish-project/modal.tsx new file mode 100644 index 00000000000..d9171949726 --- /dev/null +++ b/apps/app/components/project/publish-project/modal.tsx @@ -0,0 +1,446 @@ +import React, { useEffect } from "react"; +// next imports +import { useRouter } from "next/router"; +// react-hook-form +import { useForm } from "react-hook-form"; +// headless ui +import { Dialog, Transition } from "@headlessui/react"; +// ui components +import { ToggleSwitch, PrimaryButton, SecondaryButton } from "components/ui"; +import { CustomPopover } from "./popover"; +// mobx react lite +import { observer } from "mobx-react-lite"; +// mobx store +import { useMobxStore } from "lib/mobx/store-provider"; +import { RootStore } from "store/root"; +import { IProjectPublishSettingsViews } from "store/project-publish"; + +type Props = { + // user: ICurrentUserResponse | undefined; +}; + +const defaultValues: Partial = { + id: null, + comments: false, + reactions: false, + votes: false, + inbox: null, + views: [], +}; + +const viewOptions = [ + { key: "list", value: "List" }, + { key: "kanban", value: "Kanban" }, + // { key: "calendar", value: "Calendar" }, + // { key: "gantt", value: "Gantt" }, + // { key: "spreadsheet", value: "Spreadsheet" }, +]; + +export const PublishProjectModal: React.FC = observer(() => { + const store: RootStore = useMobxStore(); + const { projectPublish } = store; + + const { NEXT_PUBLIC_DEPLOY_URL } = process.env; + const plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL + ? NEXT_PUBLIC_DEPLOY_URL + : "http://localhost:3001"; + + const router = useRouter(); + const { workspaceSlug } = router.query; + + const { + formState: { errors, isSubmitting }, + handleSubmit, + reset, + watch, + setValue, + } = useForm({ + defaultValues, + reValidateMode: "onChange", + }); + + const handleClose = () => { + projectPublish.handleProjectModal(null); + reset({ ...defaultValues }); + }; + + useEffect(() => { + if ( + projectPublish.projectPublishSettings && + projectPublish.projectPublishSettings != "not-initialized" + ) { + let userBoards: string[] = []; + if (projectPublish.projectPublishSettings?.views) { + const _views: IProjectPublishSettingsViews | null = + projectPublish.projectPublishSettings?.views || null; + if (_views != null) { + if (_views.list) userBoards.push("list"); + if (_views.kanban) userBoards.push("kanban"); + if (_views.calendar) userBoards.push("calendar"); + if (_views.gantt) userBoards.push("gantt"); + if (_views.spreadsheet) userBoards.push("spreadsheet"); + userBoards = userBoards && userBoards.length > 0 ? userBoards : ["list"]; + } + } + + const updatedData = { + id: projectPublish.projectPublishSettings?.id || null, + comments: projectPublish.projectPublishSettings?.comments || false, + reactions: projectPublish.projectPublishSettings?.reactions || false, + votes: projectPublish.projectPublishSettings?.votes || false, + inbox: projectPublish.projectPublishSettings?.inbox || null, + views: userBoards, + }; + reset({ ...updatedData }); + } + }, [reset, projectPublish.projectPublishSettings]); + + useEffect(() => { + if ( + projectPublish.projectPublishModal && + workspaceSlug && + projectPublish.project_id != null && + projectPublish?.projectPublishSettings === "not-initialized" + ) { + projectPublish.getProjectSettingsAsync( + workspaceSlug as string, + projectPublish.project_id as string, + null + ); + } + }, [workspaceSlug, projectPublish, projectPublish.projectPublishModal]); + + const onSettingsPublish = async (formData: any) => { + const payload = { + comments: formData.comments || false, + reactions: formData.reactions || false, + votes: formData.votes || false, + inbox: formData.inbox || null, + views: { + list: formData.views.includes("list") || false, + kanban: formData.views.includes("kanban") || false, + calendar: formData.views.includes("calendar") || false, + gantt: formData.views.includes("gantt") || false, + spreadsheet: formData.views.includes("spreadsheet") || false, + }, + }; + + return projectPublish + .createProjectSettingsAsync( + workspaceSlug as string, + projectPublish.project_id as string, + payload, + null + ) + .then((response) => response) + .catch((error) => { + console.error("error", error); + return error; + }); + }; + + const onSettingsUpdate = async (key: string, value: any) => { + const payload = { + comments: key === "comments" ? value : watch("comments"), + reactions: key === "reactions" ? value : watch("reactions"), + votes: key === "votes" ? value : watch("votes"), + inbox: key === "inbox" ? value : watch("inbox"), + views: + key === "views" + ? { + list: value.includes("list") ? true : false, + kanban: value.includes("kanban") ? true : false, + calendar: value.includes("calendar") ? true : false, + gantt: value.includes("gantt") ? true : false, + spreadsheet: value.includes("spreadsheet") ? true : false, + } + : { + list: watch("views").includes("list") ? true : false, + kanban: watch("views").includes("kanban") ? true : false, + calendar: watch("views").includes("calendar") ? true : false, + gantt: watch("views").includes("gantt") ? true : false, + spreadsheet: watch("views").includes("spreadsheet") ? true : false, + }, + }; + + return projectPublish + .updateProjectSettingsAsync( + workspaceSlug as string, + projectPublish.project_id as string, + watch("id"), + payload, + null + ) + .then((response) => response) + .catch((error) => { + console.log("error", error); + return error; + }); + }; + + const onSettingsUnPublish = async (formData: any) => + projectPublish + .deleteProjectSettingsAsync( + workspaceSlug as string, + projectPublish.project_id as string, + formData?.id, + null + ) + .then((response) => { + reset({ ...defaultValues }); + return response; + }) + .catch((error) => { + console.error("error", error); + return error; + }); + + const CopyLinkToClipboard = ({ copy_link }: { copy_link: string }) => { + const [status, setStatus] = React.useState(false); + + const copyText = () => { + navigator.clipboard.writeText(copy_link); + setStatus(true); + setTimeout(() => { + setStatus(false); + }, 1000); + }; + + return ( +
copyText()} + > + {status ? "Copied" : "Copy Link"} +
+ ); + }; + + return ( + + + +
+ + +
+
+ + + {/* heading */} +
+
Publish
+ {projectPublish.loader && ( +
Changes saved
+ )} +
+ close +
+
+ + {/* content */} +
+ {watch("id") && ( +
+
+ + radio_button_checked + +
+
This project is live on web
+
+ )} + +
+
+ {`${plane_deploy_url}/${workspaceSlug}/${projectPublish.project_id}`} +
+ +
+ +
+
+
Views
+
+ 0 + ? viewOptions + .filter( + (_view) => watch("views").includes(_view.key) && _view.value + ) + .map((_view) => _view.value) + .join(", ") + : `` + } + placeholder="Select views" + > + <> + {viewOptions && + viewOptions.length > 0 && + viewOptions.map((_view) => ( +
{ + const _views = + watch("views") && watch("views").length > 0 + ? watch("views").includes(_view?.key) + ? watch("views").filter((_o: string) => _o !== _view?.key) + : [...watch("views"), _view?.key] + : [_view?.key]; + setValue("views", _views); + if (watch("id") != null) onSettingsUpdate("views", _views); + }} + > +
{_view.value}
+
+ {watch("views") && + watch("views").length > 0 && + watch("views").includes(_view.key) && ( + + done + + )} +
+
+ ))} + +
+
+
+ + {/*
+
Allow comments
+
+ { + const _comments = !watch("comments"); + setValue("comments", _comments); + if (watch("id") != null) onSettingsUpdate("comments", _comments); + }} + size="sm" + /> +
+
*/} + + {/*
+
Allow reactions
+
+ { + const _reactions = !watch("reactions"); + setValue("reactions", _reactions); + if (watch("id") != null) onSettingsUpdate("reactions", _reactions); + }} + size="sm" + /> +
+
*/} + + {/*
+
Allow Voting
+
+ { + const _votes = !watch("votes"); + setValue("votes", _votes); + if (watch("id") != null) onSettingsUpdate("votes", _votes); + }} + size="sm" + /> +
+
*/} + + {/*
+
Allow issue proposals
+
+ { + setValue("inbox", !watch("inbox")); + }} + size="sm" + /> +
+
*/} +
+
+ + {/* modal handlers */} +
+
+
+ public +
+
Anyone with the link can access
+
+
+ Cancel + {watch("id") != null ? ( + + {isSubmitting ? "Unpublishing..." : "Unpublish"} + + ) : ( + + {isSubmitting ? "Publishing..." : "Publish"} + + )} +
+
+
+
+
+
+
+
+ ); +}); diff --git a/apps/app/components/project/publish-project/popover.tsx b/apps/app/components/project/publish-project/popover.tsx new file mode 100644 index 00000000000..623675b9f7a --- /dev/null +++ b/apps/app/components/project/publish-project/popover.tsx @@ -0,0 +1,54 @@ +import React, { Fragment } from "react"; +// headless ui +import { Popover, Transition } from "@headlessui/react"; + +export const CustomPopover = ({ + children, + label, + placeholder = "Select", +}: { + children: React.ReactNode; + label?: string; + placeholder?: string; +}) => ( +
+ + {({ open }) => ( + <> + +
+ {label ? label : placeholder ? placeholder : "Select"} +
+
+ {!open ? ( + expand_more + ) : ( + expand_less + )} +
+
+ + + +
+ {children} +
+
+
+ + )} +
+
+); diff --git a/apps/app/components/project/single-sidebar-project.tsx b/apps/app/components/project/single-sidebar-project.tsx index 464e137b4e7..7bfca0d2c4f 100644 --- a/apps/app/components/project/single-sidebar-project.tsx +++ b/apps/app/components/project/single-sidebar-project.tsx @@ -32,6 +32,11 @@ import { renderEmoji } from "helpers/emoji.helper"; import { IProject } from "types"; // fetch-keys import { PROJECTS_LIST } from "constants/fetch-keys"; +// mobx react lite +import { observer } from "mobx-react-lite"; +// mobx store +import { useMobxStore } from "lib/mobx/store-provider"; +import { RootStore } from "store/root"; type Props = { project: IProject; @@ -76,252 +81,277 @@ const navigation = (workspaceSlug: string, projectId: string) => [ }, ]; -export const SingleSidebarProject: React.FC = ({ - project, - sidebarCollapse, - provided, - snapshot, - handleDeleteProject, - handleCopyText, - shortContextMenu = false, -}) => { - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; +export const SingleSidebarProject: React.FC = observer( + ({ + project, + sidebarCollapse, + provided, + snapshot, + handleDeleteProject, + handleCopyText, + shortContextMenu = false, + }) => { + const store: RootStore = useMobxStore(); + const { projectPublish } = store; - const { setToastAlert } = useToast(); + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; - const isAdmin = project.member_role === 20; + const { setToastAlert } = useToast(); - const handleAddToFavorites = () => { - if (!workspaceSlug) return; + const isAdmin = project.member_role === 20; - mutate( - PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), - (prevData) => - (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: true } : p)), - false - ); + const handleAddToFavorites = () => { + if (!workspaceSlug) return; + + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: true } : p)), + false + ); - projectService - .addProjectToFavorites(workspaceSlug as string, { - project: project.id, - }) - .catch(() => + projectService + .addProjectToFavorites(workspaceSlug as string, { + project: project.id, + }) + .catch(() => + setToastAlert({ + type: "error", + title: "Error!", + message: "Couldn't remove the project from favorites. Please try again.", + }) + ); + }; + + const handleRemoveFromFavorites = () => { + if (!workspaceSlug) return; + + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: false } : p)), + false + ); + + projectService.removeProjectFromFavorites(workspaceSlug as string, project.id).catch(() => setToastAlert({ type: "error", title: "Error!", message: "Couldn't remove the project from favorites. Please try again.", }) ); - }; - - const handleRemoveFromFavorites = () => { - if (!workspaceSlug) return; - - mutate( - PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), - (prevData) => - (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: false } : p)), - false - ); - - projectService.removeProjectFromFavorites(workspaceSlug as string, project.id).catch(() => - setToastAlert({ - type: "error", - title: "Error!", - message: "Couldn't remove the project from favorites. Please try again.", - }) - ); - }; + }; - return ( - - {({ open }) => ( - <> -
- {provided && ( - - - - )} - + {({ open }) => ( + <> +
- + + + )} + -
- {project.emoji ? ( - - {renderEmoji(project.emoji)} - - ) : project.icon_prop ? ( -
- {renderEmoji(project.icon_prop)} -
- ) : ( - - {project?.name.charAt(0)} - - )} +
+ {project.emoji ? ( + + {renderEmoji(project.emoji)} + + ) : project.icon_prop ? ( +
+ {renderEmoji(project.icon_prop)} +
+ ) : ( + + {project?.name.charAt(0)} + + )} + {!sidebarCollapse && ( +

+ {project.name} +

+ )} +
{!sidebarCollapse && ( -

- {project.name} -

+ )} -
- {!sidebarCollapse && ( - - )} -
- + + - {!sidebarCollapse && ( - - {!shortContextMenu && isAdmin && ( - - - - Delete project - - - )} - {!project.is_favorite && ( - - - - Add to favorites - - - )} - {project.is_favorite && ( - + {!sidebarCollapse && ( + + {!shortContextMenu && isAdmin && ( + + + + Delete project + + + )} + {!project.is_favorite && ( + + + + Add to favorites + + + )} + {project.is_favorite && ( + + + + Remove from favorites + + + )} + - - Remove from favorites + + Copy project link - )} - - - - Copy project link - - - {project.archive_in > 0 && ( + + {/* publish project settings */} + {isAdmin && ( + projectPublish.handleProjectModal(project?.id)} + > +
+
+ ios_share +
+
Publish
+
+ {/* */} +
+ )} + + {project.archive_in > 0 && ( + + router.push(`/${workspaceSlug}/projects/${project?.id}/archived-issues/`) + } + > +
+ + Archived Issues +
+
+ )} - router.push(`/${workspaceSlug}/projects/${project?.id}/archived-issues/`) + router.push(`/${workspaceSlug}/projects/${project?.id}/settings`) } >
- - Archived Issues + + Settings
- )} - router.push(`/${workspaceSlug}/projects/${project?.id}/settings`)} - > -
- - Settings -
-
-
- )} -
+ + )} +
- - - {navigation(workspaceSlug as string, project?.id).map((item) => { - if ( - (item.name === "Cycles" && !project.cycle_view) || - (item.name === "Modules" && !project.module_view) || - (item.name === "Views" && !project.issue_views_view) || - (item.name === "Pages" && !project.page_view) - ) - return; + + + {navigation(workspaceSlug as string, project?.id).map((item) => { + if ( + (item.name === "Cycles" && !project.cycle_view) || + (item.name === "Modules" && !project.module_view) || + (item.name === "Views" && !project.issue_views_view) || + (item.name === "Pages" && !project.page_view) + ) + return; - return ( - - - - - - - - ); - })} - - - - )} -
- ); -}; +
+ + {!sidebarCollapse && item.name} +
+ + + + ); + })} + + + + )} + + ); + } +); diff --git a/apps/app/layouts/app-layout/app-sidebar.tsx b/apps/app/layouts/app-layout/app-sidebar.tsx index 04cc8393ac3..9290c00c62b 100644 --- a/apps/app/layouts/app-layout/app-sidebar.tsx +++ b/apps/app/layouts/app-layout/app-sidebar.tsx @@ -8,6 +8,7 @@ import { WorkspaceSidebarQuickAction, } from "components/workspace"; import { ProjectSidebarList } from "components/project"; +import { PublishProjectModal } from "components/project/publish-project/modal"; // mobx react lite import { observer } from "mobx-react-lite"; // mobx store @@ -37,6 +38,7 @@ const Sidebar: React.FC = observer(({ toggleSidebar, setToggleSide + ); }); diff --git a/apps/app/lib/mobx/store-provider.tsx b/apps/app/lib/mobx/store-provider.tsx index 24496802892..c6fde14ae02 100644 --- a/apps/app/lib/mobx/store-provider.tsx +++ b/apps/app/lib/mobx/store-provider.tsx @@ -1,24 +1,22 @@ +"use client"; + import { createContext, useContext } from "react"; // mobx store import { RootStore } from "store/root"; -let rootStore: any = null; +let rootStore: RootStore = new RootStore(); -export const MobxStoreContext = createContext(null); +export const MobxStoreContext = createContext(rootStore); const initializeStore = () => { - const _rootStore = rootStore ?? new RootStore(); - + const _rootStore: RootStore = rootStore ?? new RootStore(); if (typeof window === "undefined") return _rootStore; - if (!rootStore) rootStore = _rootStore; - return _rootStore; }; export const MobxStoreProvider = ({ children }: any) => { - const store = initializeStore(); - + const store: RootStore = initializeStore(); return {children}; }; diff --git a/apps/app/services/project-publish.service.ts b/apps/app/services/project-publish.service.ts new file mode 100644 index 00000000000..4ee01a94b2d --- /dev/null +++ b/apps/app/services/project-publish.service.ts @@ -0,0 +1,117 @@ +// services +import APIService from "services/api.service"; +import trackEventServices from "services/track-event.service"; +// types +import { ICurrentUserResponse } from "types"; +import { IProjectPublishSettings } from "store/project-publish"; + +const { NEXT_PUBLIC_API_BASE_URL } = process.env; + +const trackEvent = + process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1"; + +class ProjectServices extends APIService { + constructor() { + super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000"); + } + + async getProjectSettingsAsync( + workspace_slug: string, + project_slug: string, + user: ICurrentUserResponse | undefined + ): Promise { + return this.get( + `/api/workspaces/${workspace_slug}/projects/${project_slug}/project-deploy-boards/` + ) + .then((response) => { + if (trackEvent) { + // trackEventServices.trackProjectPublishSettingsEvent( + // response.data, + // "GET_PROJECT_PUBLISH_SETTINGS", + // user + // ); + } + return response?.data; + }) + .catch((error) => { + throw error?.response; + }); + } + + async createProjectSettingsAsync( + workspace_slug: string, + project_slug: string, + data: IProjectPublishSettings, + user: ICurrentUserResponse | undefined + ): Promise { + return this.post( + `/api/workspaces/${workspace_slug}/projects/${project_slug}/project-deploy-boards/`, + data + ) + .then((response) => { + if (trackEvent) { + // trackEventServices.trackProjectPublishSettingsEvent( + // response.data, + // "CREATE_PROJECT_PUBLISH_SETTINGS", + // user + // ); + } + return response?.data; + }) + .catch((error) => { + throw error?.response; + }); + } + + async updateProjectSettingsAsync( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + data: IProjectPublishSettings, + user: ICurrentUserResponse | undefined + ): Promise { + return this.patch( + `/api/workspaces/${workspace_slug}/projects/${project_slug}/project-deploy-boards/${project_publish_id}/`, + data + ) + .then((response) => { + if (trackEvent) { + // trackEventServices.trackProjectPublishSettingsEvent( + // response.data, + // "UPDATE_PROJECT_PUBLISH_SETTINGS", + // user + // ); + } + return response?.data; + }) + .catch((error) => { + throw error?.response; + }); + } + + async deleteProjectSettingsAsync( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + user: ICurrentUserResponse | undefined + ): Promise { + return this.delete( + `/api/workspaces/${workspace_slug}/projects/${project_slug}/project-deploy-boards/${project_publish_id}/` + ) + .then((response) => { + if (trackEvent) { + // trackEventServices.trackProjectPublishSettingsEvent( + // response.data, + // "DELETE_PROJECT_PUBLISH_SETTINGS", + // user + // ); + } + return response?.data; + }) + .catch((error) => { + throw error?.response; + }); + } +} + +export default ProjectServices; diff --git a/apps/app/services/track-event.service.ts b/apps/app/services/track-event.service.ts index a87a0ff07f8..f55a6f36696 100644 --- a/apps/app/services/track-event.service.ts +++ b/apps/app/services/track-event.service.ts @@ -856,6 +856,27 @@ class TrackEventServices extends APIService { }, }); } + + // project publish settings track events starts + async trackProjectPublishSettingsEvent( + data: any, + eventName: string, + user: ICurrentUserResponse | undefined + ): Promise { + const payload: any = data; + + return this.request({ + url: "/api/track-event", + method: "POST", + data: { + eventName, + extra: payload, + user: user, + }, + }); + } + + // project publish settings track events ends } const trackEventServices = new TrackEventServices(); diff --git a/apps/app/store/project-publish.tsx b/apps/app/store/project-publish.tsx new file mode 100644 index 00000000000..d1b4c58a7c3 --- /dev/null +++ b/apps/app/store/project-publish.tsx @@ -0,0 +1,279 @@ +import { observable, action, computed, makeObservable, runInAction } from "mobx"; +// types +import { RootStore } from "./root"; +// services +import ProjectServices from "services/project-publish.service"; + +export type IProjectPublishSettingsViewKeys = + | "list" + | "gantt" + | "kanban" + | "calendar" + | "spreadsheet" + | string; + +export interface IProjectPublishSettingsViews { + list: boolean; + gantt: boolean; + kanban: boolean; + calendar: boolean; + spreadsheet: boolean; +} + +export interface IProjectPublishSettings { + id?: string; + project?: string; + comments: boolean; + reactions: boolean; + votes: boolean; + views: IProjectPublishSettingsViews; + inbox: null; +} + +export interface IProjectPublishStore { + loader: boolean; + error: any | null; + + projectPublishModal: boolean; + project_id: string | null; + projectPublishSettings: IProjectPublishSettings | "not-initialized"; + + handleProjectModal: (project_id: string | null) => void; + + getProjectSettingsAsync: ( + workspace_slug: string, + project_slug: string, + user: any + ) => Promise; + createProjectSettingsAsync: ( + workspace_slug: string, + project_slug: string, + data: IProjectPublishSettings, + user: any + ) => Promise; + updateProjectSettingsAsync: ( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + data: IProjectPublishSettings, + user: any + ) => Promise; + deleteProjectSettingsAsync: ( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + user: any + ) => Promise; +} + +class ProjectPublishStore implements IProjectPublishStore { + loader: boolean = false; + error: any | null = null; + + projectPublishModal: boolean = false; + project_id: string | null = null; + projectPublishSettings: IProjectPublishSettings | "not-initialized" = "not-initialized"; + + // root store + rootStore; + // service + projectPublishService; + + constructor(_rootStore: RootStore) { + makeObservable(this, { + // observable + loader: observable, + error: observable, + + projectPublishModal: observable, + project_id: observable, + projectPublishSettings: observable.ref, + // action + handleProjectModal: action, + // computed + }); + + this.rootStore = _rootStore; + this.projectPublishService = new ProjectServices(); + } + + handleProjectModal = (project_id: string | null = null) => { + if (project_id) { + this.projectPublishModal = !this.projectPublishModal; + this.project_id = project_id; + } else { + this.projectPublishModal = !this.projectPublishModal; + this.project_id = null; + this.projectPublishSettings = "not-initialized"; + } + }; + + getProjectSettingsAsync = async (workspace_slug: string, project_slug: string, user: any) => { + try { + this.loader = true; + this.error = null; + + const response = await this.projectPublishService.getProjectSettingsAsync( + workspace_slug, + project_slug, + user + ); + + if (response && response.length > 0) { + const _projectPublishSettings: IProjectPublishSettings = { + id: response[0]?.id, + comments: response[0]?.comments, + reactions: response[0]?.reactions, + votes: response[0]?.votes, + views: { + list: response[0]?.views?.list || false, + kanban: response[0]?.views?.kanban || false, + calendar: response[0]?.views?.calendar || false, + gantt: response[0]?.views?.gantt || false, + spreadsheet: response[0]?.views?.spreadsheet || false, + }, + inbox: response[0]?.inbox || null, + project: response[0]?.project || null, + }; + + runInAction(() => { + this.projectPublishSettings = _projectPublishSettings; + this.loader = false; + this.error = null; + }); + } else { + this.projectPublishSettings = "not-initialized"; + this.loader = false; + this.error = null; + } + return response; + } catch (error) { + this.loader = false; + this.error = error; + return error; + } + }; + + createProjectSettingsAsync = async ( + workspace_slug: string, + project_slug: string, + data: IProjectPublishSettings, + user: any + ) => { + try { + this.loader = true; + this.error = null; + + const response = await this.projectPublishService.createProjectSettingsAsync( + workspace_slug, + project_slug, + data, + user + ); + + if (response) { + const _projectPublishSettings: IProjectPublishSettings = { + id: response?.id || null, + comments: response?.comments || false, + reactions: response?.reactions || false, + votes: response?.votes || false, + views: { ...response?.views }, + inbox: response?.inbox || null, + project: response?.project || null, + }; + + runInAction(() => { + this.projectPublishSettings = _projectPublishSettings; + this.loader = false; + this.error = null; + }); + + return response; + } + } catch (error) { + this.loader = false; + this.error = error; + return error; + } + }; + + updateProjectSettingsAsync = async ( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + data: IProjectPublishSettings, + user: any + ) => { + try { + this.loader = true; + this.error = null; + + const response = await this.projectPublishService.updateProjectSettingsAsync( + workspace_slug, + project_slug, + project_publish_id, + data, + user + ); + + if (response) { + const _projectPublishSettings: IProjectPublishSettings = { + id: response?.id || null, + comments: response?.comments || false, + reactions: response?.reactions || false, + votes: response?.votes || false, + views: { ...response?.views }, + inbox: response?.inbox || null, + project: response?.project || null, + }; + + runInAction(() => { + this.projectPublishSettings = _projectPublishSettings; + this.loader = false; + this.error = null; + }); + + return response; + } + } catch (error) { + this.loader = false; + this.error = error; + return error; + } + }; + + deleteProjectSettingsAsync = async ( + workspace_slug: string, + project_slug: string, + project_publish_id: string, + user: any + ) => { + try { + this.loader = true; + this.error = null; + + const response = await this.projectPublishService.deleteProjectSettingsAsync( + workspace_slug, + project_slug, + project_publish_id, + user + ); + + if (response) { + runInAction(() => { + this.projectPublishSettings = "not-initialized"; + this.loader = false; + this.error = null; + }); + + return response; + } + } catch (error) { + this.loader = false; + this.error = error; + return error; + } + }; +} + +export default ProjectPublishStore; diff --git a/apps/app/store/root.ts b/apps/app/store/root.ts index 43daa32e683..5895637a89f 100644 --- a/apps/app/store/root.ts +++ b/apps/app/store/root.ts @@ -3,15 +3,18 @@ import { enableStaticRendering } from "mobx-react-lite"; // store imports import UserStore from "./user"; import ThemeStore from "./theme"; +import ProjectPublishStore, { IProjectPublishStore } from "./project-publish"; enableStaticRendering(typeof window === "undefined"); export class RootStore { user; theme; + projectPublish: IProjectPublishStore; constructor() { this.user = new UserStore(this); this.theme = new ThemeStore(this); + this.projectPublish = new ProjectPublishStore(this); } } diff --git a/turbo.json b/turbo.json index a553347416c..69da3c552fd 100644 --- a/turbo.json +++ b/turbo.json @@ -4,6 +4,7 @@ "NEXT_PUBLIC_GITHUB_ID", "NEXT_PUBLIC_GOOGLE_CLIENTID", "NEXT_PUBLIC_API_BASE_URL", + "NEXT_PUBLIC_DEPLOY_URL", "API_BASE_URL", "NEXT_PUBLIC_SENTRY_DSN", "SENTRY_AUTH_TOKEN",