diff --git a/apps/space/components/accounts/index.ts b/apps/space/components/accounts/index.ts new file mode 100644 index 0000000000..093e8538c4 --- /dev/null +++ b/apps/space/components/accounts/index.ts @@ -0,0 +1,6 @@ +export * from "./email-code-form"; +export * from "./email-password-form"; +export * from "./email-reset-password-form"; +export * from "./github-login-button"; +export * from "./google-login"; +export * from "./onboarding-form"; diff --git a/apps/space/components/issues/board-views/list/block.tsx b/apps/space/components/issues/board-views/list/block.tsx index fcb123c217..bbac97741c 100644 --- a/apps/space/components/issues/board-views/list/block.tsx +++ b/apps/space/components/issues/board-views/list/block.tsx @@ -1,6 +1,5 @@ -"use client"; - -// mobx react lite +import { FC } from "react"; +import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // components import { IssueBlockPriority } from "components/issues/board-views/block-priority"; @@ -11,10 +10,32 @@ import { IssueBlockDueDate } from "components/issues/board-views/block-due-date" import { useMobxStore } from "lib/mobx/store-provider"; // interfaces import { IIssue } from "types/issue"; +// store import { RootStore } from "store/root"; -export const IssueListBlock = observer(({ issue }: { issue: IIssue }) => { - const { issue: issueStore, project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore(); +export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => { + const { issue } = props; + // store + const { project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore(); + // router + const router = useRouter(); + const { workspace_slug, project_slug, board } = router.query; + + const handleBlockClick = () => { + issueDetailStore.setPeekId(issue.id); + router.replace( + { + pathname: `/${workspace_slug?.toString()}/${project_slug}`, + query: { + board: board?.toString(), + peekId: issue.id, + }, + }, + undefined, + { shallow: true } + ); + // router.push(`/${workspace_slug?.toString()}/${project_slug}?board=${board?.toString()}&peekId=${issue.id}`); + }; return (
@@ -25,12 +46,7 @@ export const IssueListBlock = observer(({ issue }: { issue: IIssue }) => {
{/* name */}
-

{ - issueDetailStore.setPeekId(issue.id); - }} - className="text-[0.825rem] font-medium text-sm truncate text-custom-text-100" - > +

{issue.name}

diff --git a/apps/space/components/issues/board-views/list/index.tsx b/apps/space/components/issues/board-views/list/index.tsx index 268c27fc18..8d31199b03 100644 --- a/apps/space/components/issues/board-views/list/index.tsx +++ b/apps/space/components/issues/board-views/list/index.tsx @@ -1,6 +1,4 @@ -"use client"; - -// mobx react lite +import { useEffect } from "react"; import { observer } from "mobx-react-lite"; // components import { IssueListHeader } from "components/issues/board-views/list/header"; @@ -9,11 +7,13 @@ import { IssueListBlock } from "components/issues/board-views/list/block"; import { IIssueState, IIssue } from "types/issue"; // mobx hook import { useMobxStore } from "lib/mobx/store-provider"; +// store import { RootStore } from "store/root"; +import { useRouter } from "next/router"; export const IssueListView = observer(() => { const { issue: issueStore }: RootStore = useMobxStore(); - console.log("issueStore", issueStore.states); + return ( <> {issueStore?.states && diff --git a/apps/space/components/issues/peek-overview/add-comment.tsx b/apps/space/components/issues/peek-overview/add-comment.tsx index 618552aaf9..52c3b997f9 100644 --- a/apps/space/components/issues/peek-overview/add-comment.tsx +++ b/apps/space/components/issues/peek-overview/add-comment.tsx @@ -11,13 +11,7 @@ import { SecondaryButton } from "components/ui"; // types import { Comment } from "types"; // components -import Tiptap, { ITiptapRichTextEditor } from "components/tiptap"; - -const TiptapEditor = React.forwardRef((props, ref) => ( - -)); - -TiptapEditor.displayName = "TiptapEditor"; +import { TipTapEditor } from "components/tiptap"; const defaultValues: Partial = { comment_json: "", @@ -25,12 +19,11 @@ const defaultValues: Partial = { }; type Props = { - issueId: string | null; disabled?: boolean; }; export const AddComment: React.FC = observer((props) => { - const { issueId, disabled = false } = props; + const { disabled = false } = props; const { handleSubmit, @@ -44,7 +37,9 @@ export const AddComment: React.FC = observer((props) => { const router = useRouter(); const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string }; - const { issue: issueStore, user: userStore } = useMobxStore(); + const { issue: issueStore, user: userStore, issueDetails: issueDetailStore } = useMobxStore(); + + const issueId = issueDetailStore.peekId; const editorRef = useRef(null); @@ -61,8 +56,8 @@ export const AddComment: React.FC = observer((props) => { ) return; - await issueStore - .createIssueCommentAsync(workspace_slug, project_slug, issueId, formData) + await issueDetailStore + .addIssueComment(workspace_slug, project_slug, issueId, formData) .then(() => { reset(defaultValues); editorRef.current?.clearEditor(); @@ -83,7 +78,7 @@ export const AddComment: React.FC = observer((props) => { name="comment_html" control={control} render={({ field: { value, onChange } }) => ( - ((props, ref) => ( - -)); - -TiptapEditor.displayName = "TiptapEditor"; +import { TipTapEditor } from "components/tiptap"; type Props = { workspaceSlug: string; @@ -124,7 +118,7 @@ export const CommentCard: React.FC = observer((props) => { className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`} >
- = observer((props) => {
- = observer((props) => { const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspace_slug } = router.query; const { issueDetails: issueDetailStore, user: userStore } = useMobxStore(); - const issueId = issueDetailStore?.peekId; - const comments = issueDetailStore?.details[issueId ?? ""]?.comments ?? []; + const comments = issueDetailStore.details[issueDetailStore.peekId || ""]?.comments || []; return (

Activity

- {workspaceSlug && ( + {workspace_slug && (
{comments.map((comment: any) => ( - + ))}
- +
)} diff --git a/apps/space/components/issues/peek-overview/issue-details.tsx b/apps/space/components/issues/peek-overview/issue-details.tsx index bbe982a69c..ff725182d0 100644 --- a/apps/space/components/issues/peek-overview/issue-details.tsx +++ b/apps/space/components/issues/peek-overview/issue-details.tsx @@ -1,4 +1,3 @@ -// components import { IssueReactions } from "components/issues/peek-overview"; // types import { IIssue } from "types"; diff --git a/apps/space/components/issues/peek-overview/issue-emoji-reactions.tsx b/apps/space/components/issues/peek-overview/issue-emoji-reactions.tsx index 2f51b59550..04bd9f63b5 100644 --- a/apps/space/components/issues/peek-overview/issue-emoji-reactions.tsx +++ b/apps/space/components/issues/peek-overview/issue-emoji-reactions.tsx @@ -9,22 +9,21 @@ import { groupReactions, renderEmoji } from "helpers/emoji.helper"; import { ReactionSelector } from "components/ui"; export const IssueEmojiReactions: React.FC = observer(() => { + // router const router = useRouter(); - const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string }; - - const { user: userStore, issue: issueStore } = useMobxStore(); + // store + const { user: userStore, issue: issueStore, issueDetails: issueDetailsStore } = useMobxStore(); const user = userStore?.currentUser; - const issueId = issueStore.activePeekOverviewIssueId; - - const reactions = issueId ? issueStore.issue_detail[issueId]?.reactions || [] : []; + const issueId = issueDetailsStore.peekId; + const reactions = issueId ? issueDetailsStore.details[issueId]?.reactions || [] : []; const groupedReactions = groupReactions(reactions, "reaction"); const handleReactionClick = (reactionHexa: string) => { if (!workspace_slug || !project_slug || !issueId) return; - const userReaction = reactions?.find((r) => r.created_by === user?.id && r.reaction === reactionHexa); + const userReaction = reactions?.find((r: any) => r.created_by === user?.id && r.reaction === reactionHexa); if (userReaction) issueStore.deleteIssueReactionAsync(workspace_slug, userReaction.project, userReaction.issue, reactionHexa); @@ -34,12 +33,6 @@ export const IssueEmojiReactions: React.FC = observer(() => { }); }; - useEffect(() => { - if (user) return; - - userStore.getUserAsync(); - }, [user, userStore]); - return ( <> { }} key={reaction} className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md border ${ - reactions?.some((r) => r.actor === user?.id && r.reaction === reaction) + reactions?.some((r: any) => r.actor === user?.id && r.reaction === reaction) ? "bg-custom-primary-100/10 border-custom-primary-100" : "bg-custom-background-80 border-transparent" }`} @@ -71,7 +64,7 @@ export const IssueEmojiReactions: React.FC = observer(() => { {renderEmoji(reaction)} r.actor === user?.id && r.reaction === reaction) + reactions?.some((r: any) => r.actor === user?.id && r.reaction === reaction) ? "text-custom-primary-100" : "" } diff --git a/apps/space/components/issues/peek-overview/issue-reaction.tsx b/apps/space/components/issues/peek-overview/issue-reaction.tsx index 9dc1fac403..fc1b15e513 100644 --- a/apps/space/components/issues/peek-overview/issue-reaction.tsx +++ b/apps/space/components/issues/peek-overview/issue-reaction.tsx @@ -1,18 +1,25 @@ -"use client"; - -// ui import { IssueEmojiReactions, IssueVotes } from "components/issues/peek-overview"; +import { useMobxStore } from "lib/mobx/store-provider"; -export const IssueReactions: React.FC = () => ( -
-
- +export const IssueReactions: React.FC = () => { + const { project: projectStore } = useMobxStore(); + return ( +
+ {projectStore?.deploySettings?.votes && ( + <> +
+ +
+ +
+ + )} + + {projectStore?.deploySettings?.reactions && ( +
+ +
+ )}
- -
- -
- -
-
-); + ); +}; diff --git a/apps/space/components/issues/peek-overview/layout.tsx b/apps/space/components/issues/peek-overview/layout.tsx index ee763d1480..c50bd70663 100644 --- a/apps/space/components/issues/peek-overview/layout.tsx +++ b/apps/space/components/issues/peek-overview/layout.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo } from "react"; import { useRouter } from "next/router"; import { Dialog, Transition } from "@headlessui/react"; import { observer } from "mobx-react-lite"; @@ -18,20 +18,19 @@ export const IssuePeekOverview: React.FC = observer((props) => { const { isOpen, onClose } = props; // router const router = useRouter(); - const { workspace_slug, project_slug } = router.query; + const { workspace_slug, project_slug, peekId } = router.query; // store - const { issueDetails: issueDetailStore } = useMobxStore(); + const { issueDetails: issueDetailStore, issue: issueStore } = useMobxStore(); - const issueDetails = issueDetailStore.peekId ? issueDetailStore.details[issueDetailStore.peekId] : null; - console.log("issueDetails", issueDetails); + const issueDetails = issueDetailStore.peekId && peekId ? issueDetailStore.details[peekId.toString()] : null; useEffect(() => { - if (workspace_slug && project_slug && issueDetailStore.peekId) { + if (workspace_slug && project_slug && peekId && issueStore.issues && issueStore.issues.length > 0) { if (!issueDetails) { - issueDetailStore.fetchIssueDetails(workspace_slug.toString(), project_slug.toString(), issueDetailStore.peekId); + issueDetailStore.fetchIssueDetails(workspace_slug.toString(), project_slug.toString(), peekId.toString()); } } - }, [workspace_slug, project_slug, issueDetailStore, issueDetails]); + }, [workspace_slug, project_slug, issueDetailStore, issueDetails, peekId, issueStore.issues]); const handleClose = () => { onClose(); diff --git a/apps/space/components/issues/peek-overview/side-peek-view.tsx b/apps/space/components/issues/peek-overview/side-peek-view.tsx index 094565c933..967c2ae692 100644 --- a/apps/space/components/issues/peek-overview/side-peek-view.tsx +++ b/apps/space/components/issues/peek-overview/side-peek-view.tsx @@ -11,6 +11,7 @@ import { } from "components/issues/peek-overview"; // types import { IIssue } from "types/issue"; +import { RootStore } from "store/root"; type Props = { handleClose: () => void; @@ -20,6 +21,8 @@ type Props = { export const SidePeekView: React.FC = observer((props) => { const { handleClose, issueDetails } = props; + const { project: projectStore } = useMobxStore(); + return (
@@ -38,9 +41,11 @@ export const SidePeekView: React.FC = observer((props) => { {/* divider */}
{/* issue activity/comments */} -
- -
+ {projectStore?.deploySettings?.comments && ( +
+ +
+ )}
)}
diff --git a/apps/space/components/tiptap/index.tsx b/apps/space/components/tiptap/index.tsx index 418449c089..f0315cad4a 100644 --- a/apps/space/components/tiptap/index.tsx +++ b/apps/space/components/tiptap/index.tsx @@ -3,10 +3,10 @@ import { useDebouncedCallback } from "use-debounce"; import { EditorBubbleMenu } from "./bubble-menu"; import { TiptapExtensions } from "./extensions"; import { TiptapEditorProps } from "./props"; -import { useImperativeHandle, useRef } from "react"; +import { useImperativeHandle, useRef, forwardRef } from "react"; import { ImageResizer } from "./extensions/image-resize"; -export interface ITiptapRichTextEditor { +export interface ITipTapRichTextEditor { value: string; noBorder?: boolean; borderOnFocus?: boolean; @@ -21,7 +21,7 @@ export interface ITiptapRichTextEditor { debouncedUpdatesEnabled?: boolean; } -const Tiptap = (props: ITiptapRichTextEditor) => { +const Tiptap = (props: ITipTapRichTextEditor) => { const { onChange, debouncedUpdatesEnabled, @@ -73,9 +73,10 @@ const Tiptap = (props: ITiptapRichTextEditor) => { }, 500); }, 1000); - const editorClassNames = `relative w-full max-w-screen-lg sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md - ${noBorder ? "" : "border border-custom-border-200"} ${borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0" - } ${customClassName}`; + const editorClassNames = `relative w-full max-w-full sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md + ${noBorder ? "" : "border border-custom-border-200"} ${ + borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0" + } ${customClassName}`; if (!editor) return null; editorRef.current = editor; @@ -97,4 +98,10 @@ const Tiptap = (props: ITiptapRichTextEditor) => { ); }; -export default Tiptap; +const TipTapEditor = forwardRef((props, ref) => ( + +)); + +TipTapEditor.displayName = "TipTapEditor"; + +export { TipTapEditor }; diff --git a/apps/space/components/views/project-details.tsx b/apps/space/components/views/project-details.tsx index 1ef870dc4a..8f46af79c1 100644 --- a/apps/space/components/views/project-details.tsx +++ b/apps/space/components/views/project-details.tsx @@ -14,12 +14,23 @@ import { useMobxStore } from "lib/mobx/store-provider"; export const ProjectDetailsView = observer(() => { const router = useRouter(); - const { workspace_slug, project_slug, states, labels, priorities } = router.query; + const { workspace_slug, project_slug, states, labels, priorities, board, peekId } = router.query; - const { issue: issueStore, project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore(); + const { + issue: issueStore, + project: projectStore, + issueDetails: issueDetailStore, + user: userStore, + }: RootStore = useMobxStore(); const activeIssueId = issueDetailStore.peekId; + useEffect(() => { + if (!userStore.currentUser) { + userStore.fetchCurrentUser(); + } + }, [userStore]); + useEffect(() => { if (workspace_slug && project_slug) { const params = { @@ -31,11 +42,29 @@ export const ProjectDetailsView = observer(() => { } }, [workspace_slug, project_slug, issueStore, states, labels, priorities]); + useEffect(() => { + if (peekId && workspace_slug && project_slug) { + issueDetailStore.setPeekId(peekId.toString()); + } + }, [peekId, issueDetailStore, project_slug, workspace_slug]); + + const handlePeekClose = () => { + issueDetailStore.setPeekId(null); + router.replace( + { + pathname: `/${workspace_slug?.toString()}/${project_slug}`, + query: { + ...(board && { board: board.toString() }), + }, + }, + undefined, + { shallow: true } + ); + }; + return (
- {workspace_slug && ( - issueDetailStore.setPeekId(null)} /> - )} + {workspace_slug && } {issueStore?.loader && !issueStore.issues ? (
Loading...
diff --git a/apps/space/pages/index.tsx b/apps/space/pages/index.tsx index ae93b1ba30..3a8838b1de 100644 --- a/apps/space/pages/index.tsx +++ b/apps/space/pages/index.tsx @@ -1,7 +1,157 @@ -import React from "react"; +import React, { useEffect } from "react"; +import Image from "next/image"; +import { useRouter } from "next/router"; +// assets +import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png"; +// mobx +import { observer } from "mobx-react-lite"; +import { useMobxStore } from "lib/mobx/store-provider"; +// services +import authenticationService from "services/authentication.service"; +// hooks +import useToast from "hooks/use-toast"; +// components +import { EmailPasswordForm, GithubLoginButton, GoogleLoginButton, EmailCodeForm } from "components/accounts"; -const HomePage = () => ( -
Plane Deploy
-); +const HomePage = () => { + const { user: userStore } = useMobxStore(); + + const router = useRouter(); + const { next_path = "/" } = router.query; + + const { setToastAlert } = useToast(); + + const onSignInError = (error: any) => { + setToastAlert({ + title: "Error signing in!", + type: "error", + message: error?.error || "Something went wrong. Please try again later or contact the support team.", + }); + }; + + const onSignInSuccess = (response: any) => { + const isOnboarded = response?.user?.onboarding_step?.profile_complete || false; + + userStore.setCurrentUser(response?.user); + + if (!isOnboarded) { + router.push(`/onboarding?next_path=${next_path}`); + return; + } + console.log("hello"); + router.push(next_path.toString()); + }; + + const handleGoogleSignIn = async ({ clientId, credential }: any) => { + try { + if (clientId && credential) { + const socialAuthPayload = { + medium: "google", + credential, + clientId, + }; + const response = await authenticationService.socialAuth(socialAuthPayload); + + onSignInSuccess(response); + } else { + throw Error("Cant find credentials"); + } + } catch (err: any) { + onSignInError(err); + } + }; + + const handleGitHubSignIn = async (credential: string) => { + try { + if (process.env.NEXT_PUBLIC_GITHUB_ID && credential) { + const socialAuthPayload = { + medium: "github", + credential, + clientId: process.env.NEXT_PUBLIC_GITHUB_ID, + }; + const response = await authenticationService.socialAuth(socialAuthPayload); + onSignInSuccess(response); + } else { + throw Error("Cant find credentials"); + } + } catch (err: any) { + onSignInError(err); + } + }; + + const handlePasswordSignIn = async (formData: any) => { + await authenticationService + .emailLogin(formData) + .then((response) => { + try { + if (response) { + onSignInSuccess(response); + } + } catch (err: any) { + onSignInError(err); + } + }) + .catch((err) => onSignInError(err)); + }; + + const handleEmailCodeSignIn = async (response: any) => { + try { + if (response) { + onSignInSuccess(response); + } + } catch (err: any) { + onSignInError(err); + } + }; + + return ( +
+
+
+
+
+ Plane Logo +
+
+
+
+
+ {parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? ( + <> +

+ Sign in to Plane +

+
+
+ +
+
+ + +
+
+ + ) : ( + + )} + + {parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? ( +

+ By signing up, you agree to the{" "} + + Terms & Conditions + +

+ ) : null} +
+
+
+ ); +}; export default HomePage; diff --git a/apps/space/store/issue_details.ts b/apps/space/store/issue_details.ts index 4da937bff2..89b2c2c8fd 100644 --- a/apps/space/store/issue_details.ts +++ b/apps/space/store/issue_details.ts @@ -13,10 +13,20 @@ export interface IIssueDetailStore { peekId: string | null; peekMode: IPeekMode; details: any; - // actions + // peek actions setPeekId: (issueId: string | null) => void; setPeekMode: (mode: IPeekMode) => void; + // issue details fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void; + // issue comments + addIssueComment: (workspaceId: string, projectId: string, issueId: string, data: any) => void; + deleteIssueComment: (workspaceId: string, projectId: string, issueId: string) => void; + // issue reactions + addIssueReaction: (workspaceId: string, projectId: string, issueId: string) => void; + removeIssueReaction: (workspaceId: string, projectId: string, issueId: string) => void; + // issue votes + addIssueVote: (workspaceId: string, projectId: string, issueId: string) => void; + removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => void; } class IssueDetailStore implements IssueDetailStore { @@ -59,9 +69,7 @@ class IssueDetailStore implements IssueDetailStore { this.error = null; const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId); - const reactionsResponse = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId); const commentsResponse = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId); - const votesResponse = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId); if (issueDetails) { runInAction(() => { @@ -70,8 +78,6 @@ class IssueDetailStore implements IssueDetailStore { [issueId]: { ...issueDetails, comments: commentsResponse, - reactions: reactionsResponse, - votes: votesResponse, }, }; }); @@ -79,20 +85,148 @@ class IssueDetailStore implements IssueDetailStore { } catch (error) { this.loader = false; this.error = error; + } + }; + addIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => { + try { const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId); + const issueCommentResponse = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data); + console.log("issueCommentResponse", issueCommentResponse); + if (issueDetails) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + comments: [...this.details[issueId].comments, issueCommentResponse], + }, + }; + }); + } + return issueCommentResponse; + } catch (error) { + console.log("Failed to add issue comment"); + throw error; + } + }; - runInAction(() => { - this.details = { - ...this.details, - [issueId]: { - ...issueDetails, - comments: [], - reactions: [], - votes: [], - }, - }; - }); + updateIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => { + try { + const issueVoteResponse = await this.issueService.updateIssueComment(workspaceSlug, projectId, issueId, data); + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + comments: commentsResponse, + }, + }; + }); + } + } catch (error) { + console.log("Failed to add issue comment"); + } + }; + + deleteIssueComment = async () => { + try { + const issueVoteResponse = await this.issueService.deleteIssueComment(workspaceSlug, projectId, issueId, data); + // const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); + + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + }, + }; + }); + } + } catch (error) { + console.log("Failed to add issue vote"); + } + }; + + addIssueReaction = async () => { + try { + const issueVoteResponse = await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, data); + // const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); + + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + }, + }; + }); + } + } catch (error) { + console.log("Failed to add issue vote"); + } + }; + + removeIssueReaction = async () => { + try { + const issueVoteResponse = await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, data); + // const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); + + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + }, + }; + }); + } + } catch (error) { + console.log("Failed to add issue vote"); + } + }; + + addIssueVote = async (workspaceSlug: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => { + try { + const issueVoteResponse = await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data); + // const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); + + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + }, + }; + }); + } + } catch (error) { + console.log("Failed to add issue vote"); + } + }; + + removeIssueVote = async (workspaceSlug: string, projectId: string, issueId: string) => { + try { + const issueVoteResponse = await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId, data); + // const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); + + if (issueVoteResponse) { + runInAction(() => { + this.details = { + ...this.details, + [issueId]: { + ...issueDetails, + }, + }; + }); + } + } catch (error) { + console.log("Failed to remove issue vote"); } }; } diff --git a/apps/space/store/project.ts b/apps/space/store/project.ts index a22a58a0c7..45ce06f725 100644 --- a/apps/space/store/project.ts +++ b/apps/space/store/project.ts @@ -10,7 +10,7 @@ export interface IProjectStore { error: any | null; workspace: IWorkspace | null; project: IProject | null; - projectDeploySettings: IProjectSettings | null; + deploySettings: IProjectSettings | null; viewOptions: any; activeBoard: string | null; fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise; @@ -23,7 +23,7 @@ class ProjectStore implements IProjectStore { // data workspace: IWorkspace | null = null; project: IProject | null = null; - projectDeploySettings: IProjectSettings | null = null; + deploySettings: IProjectSettings | null = null; viewOptions: any = null; activeBoard: string | null = null; // root store @@ -39,7 +39,7 @@ class ProjectStore implements IProjectStore { // observable workspace: observable.ref, project: observable.ref, - projectDeploySettings: observable.ref, + deploySettings: observable.ref, viewOptions: observable.ref, activeBoard: observable.ref, // actions @@ -63,10 +63,12 @@ class ProjectStore implements IProjectStore { const _project: IProject = { ...response?.project_details }; const _workspace: IWorkspace = { ...response?.workspace_detail }; const _viewOptions = { ...response?.views }; + const _deploySettings = { ...response }; runInAction(() => { this.project = _project; this.workspace = _workspace; this.viewOptions = _viewOptions; + this.deploySettings = _deploySettings; this.loader = false; }); } diff --git a/apps/space/store/user.ts b/apps/space/store/user.ts index d2f68360ff..9cd25bf8cb 100644 --- a/apps/space/store/user.ts +++ b/apps/space/store/user.ts @@ -2,8 +2,11 @@ import { observable, action, computed, makeObservable, runInAction } from "mobx"; // service import UserService from "services/user.service"; -// types -import { IUserStore } from "../types"; + +export interface IUserStore { + currentUser: any | null; + fetchCurrentUser: () => void; +} class UserStore implements IUserStore { currentUser: any | null = null; @@ -42,7 +45,7 @@ class UserStore implements IUserStore { return; } - this.getUserAsync() + this.fetchCurrentUser() .then(() => { if (!this.currentUser) { const currentPath = window.location.pathname; @@ -55,7 +58,7 @@ class UserStore implements IUserStore { }); }; - getUserAsync = async () => { + fetchCurrentUser = async () => { try { const response = await this.userService.currentUser(); if (response) { @@ -64,10 +67,7 @@ class UserStore implements IUserStore { }); } } catch (error) { - console.error("error", error); - runInAction(() => { - // render error actions - }); + console.error("Failed to fetch current user", error); } }; } diff --git a/apps/space/types/user.ts b/apps/space/types/user.ts index 0293c53816..e69de29bb2 100644 --- a/apps/space/types/user.ts +++ b/apps/space/types/user.ts @@ -1,4 +0,0 @@ -export interface IUserStore { - currentUser: any | null; - getUserAsync: () => void; -}