mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: mobx changes
This commit is contained in:
parent
6246a740d5
commit
240acc6cd0
6
apps/space/components/accounts/index.ts
Normal file
6
apps/space/components/accounts/index.ts
Normal file
@ -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";
|
@ -1,6 +1,5 @@
|
|||||||
"use client";
|
import { FC } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
// mobx react lite
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// components
|
// components
|
||||||
import { IssueBlockPriority } from "components/issues/board-views/block-priority";
|
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";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// interfaces
|
// interfaces
|
||||||
import { IIssue } from "types/issue";
|
import { IIssue } from "types/issue";
|
||||||
|
// store
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
|
|
||||||
export const IssueListBlock = observer(({ issue }: { issue: IIssue }) => {
|
export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
|
||||||
const { issue: issueStore, project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore();
|
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 (
|
return (
|
||||||
<div className="flex items-center px-9 py-3.5 relative gap-10 border-b border-custom-border-200 bg-custom-background-100 last:border-b-0">
|
<div className="flex items-center px-9 py-3.5 relative gap-10 border-b border-custom-border-200 bg-custom-background-100 last:border-b-0">
|
||||||
@ -25,12 +46,7 @@ export const IssueListBlock = observer(({ issue }: { issue: IIssue }) => {
|
|||||||
</div>
|
</div>
|
||||||
{/* name */}
|
{/* name */}
|
||||||
<div className="h-full line-clamp-1 w-full overflow-ellipsis cursor-pointer">
|
<div className="h-full line-clamp-1 w-full overflow-ellipsis cursor-pointer">
|
||||||
<p
|
<p onClick={handleBlockClick} className="text-[0.825rem] font-medium text-sm truncate text-custom-text-100">
|
||||||
onClick={() => {
|
|
||||||
issueDetailStore.setPeekId(issue.id);
|
|
||||||
}}
|
|
||||||
className="text-[0.825rem] font-medium text-sm truncate text-custom-text-100"
|
|
||||||
>
|
|
||||||
{issue.name}
|
{issue.name}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
"use client";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
// mobx react lite
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// components
|
// components
|
||||||
import { IssueListHeader } from "components/issues/board-views/list/header";
|
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";
|
import { IIssueState, IIssue } from "types/issue";
|
||||||
// mobx hook
|
// mobx hook
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
// store
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
export const IssueListView = observer(() => {
|
export const IssueListView = observer(() => {
|
||||||
const { issue: issueStore }: RootStore = useMobxStore();
|
const { issue: issueStore }: RootStore = useMobxStore();
|
||||||
console.log("issueStore", issueStore.states);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{issueStore?.states &&
|
{issueStore?.states &&
|
||||||
|
@ -11,13 +11,7 @@ import { SecondaryButton } from "components/ui";
|
|||||||
// types
|
// types
|
||||||
import { Comment } from "types";
|
import { Comment } from "types";
|
||||||
// components
|
// components
|
||||||
import Tiptap, { ITiptapRichTextEditor } from "components/tiptap";
|
import { TipTapEditor } from "components/tiptap";
|
||||||
|
|
||||||
const TiptapEditor = React.forwardRef<ITiptapRichTextEditor, ITiptapRichTextEditor>((props, ref) => (
|
|
||||||
<Tiptap {...props} forwardedRef={ref} />
|
|
||||||
));
|
|
||||||
|
|
||||||
TiptapEditor.displayName = "TiptapEditor";
|
|
||||||
|
|
||||||
const defaultValues: Partial<Comment> = {
|
const defaultValues: Partial<Comment> = {
|
||||||
comment_json: "",
|
comment_json: "",
|
||||||
@ -25,12 +19,11 @@ const defaultValues: Partial<Comment> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
issueId: string | null;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AddComment: React.FC<Props> = observer((props) => {
|
export const AddComment: React.FC<Props> = observer((props) => {
|
||||||
const { issueId, disabled = false } = props;
|
const { disabled = false } = props;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@ -44,7 +37,9 @@ export const AddComment: React.FC<Props> = observer((props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
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<any>(null);
|
const editorRef = useRef<any>(null);
|
||||||
|
|
||||||
@ -61,8 +56,8 @@ export const AddComment: React.FC<Props> = observer((props) => {
|
|||||||
)
|
)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await issueStore
|
await issueDetailStore
|
||||||
.createIssueCommentAsync(workspace_slug, project_slug, issueId, formData)
|
.addIssueComment(workspace_slug, project_slug, issueId, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
reset(defaultValues);
|
reset(defaultValues);
|
||||||
editorRef.current?.clearEditor();
|
editorRef.current?.clearEditor();
|
||||||
@ -83,7 +78,7 @@ export const AddComment: React.FC<Props> = observer((props) => {
|
|||||||
name="comment_html"
|
name="comment_html"
|
||||||
control={control}
|
control={control}
|
||||||
render={({ field: { value, onChange } }) => (
|
render={({ field: { value, onChange } }) => (
|
||||||
<TiptapEditor
|
<TipTapEditor
|
||||||
workspaceSlug={workspace_slug as string}
|
workspaceSlug={workspace_slug as string}
|
||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
value={
|
value={
|
||||||
|
@ -17,13 +17,7 @@ import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon, EllipsisVerticalIcon
|
|||||||
import { timeAgo } from "helpers/date-time.helper";
|
import { timeAgo } from "helpers/date-time.helper";
|
||||||
// types
|
// types
|
||||||
import { Comment } from "types";
|
import { Comment } from "types";
|
||||||
import Tiptap, { ITiptapRichTextEditor } from "components/tiptap";
|
import { TipTapEditor } from "components/tiptap";
|
||||||
|
|
||||||
const TiptapEditor = React.forwardRef<ITiptapRichTextEditor, ITiptapRichTextEditor>((props, ref) => (
|
|
||||||
<Tiptap {...props} forwardedRef={ref} />
|
|
||||||
));
|
|
||||||
|
|
||||||
TiptapEditor.displayName = "TiptapEditor";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
@ -124,7 +118,7 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
|||||||
className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}
|
className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<TiptapEditor
|
<TipTapEditor
|
||||||
workspaceSlug={workspaceSlug as string}
|
workspaceSlug={workspaceSlug as string}
|
||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
value={watch("comment_html")}
|
value={watch("comment_html")}
|
||||||
@ -154,7 +148,7 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div className={`${isEditing ? "hidden" : ""}`}>
|
<div className={`${isEditing ? "hidden" : ""}`}>
|
||||||
<TiptapEditor
|
<TipTapEditor
|
||||||
workspaceSlug={workspaceSlug as string}
|
workspaceSlug={workspaceSlug as string}
|
||||||
ref={showEditorRef}
|
ref={showEditorRef}
|
||||||
value={comment.comment_html}
|
value={comment.comment_html}
|
||||||
|
@ -14,25 +14,24 @@ type Props = {
|
|||||||
|
|
||||||
export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
|
export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspace_slug } = router.query;
|
||||||
|
|
||||||
const { issueDetails: issueDetailStore, user: userStore } = useMobxStore();
|
const { issueDetails: issueDetailStore, user: userStore } = useMobxStore();
|
||||||
|
|
||||||
const issueId = issueDetailStore?.peekId;
|
const comments = issueDetailStore.details[issueDetailStore.peekId || ""]?.comments || [];
|
||||||
const comments = issueDetailStore?.details[issueId ?? ""]?.comments ?? [];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-medium">Activity</h4>
|
<h4 className="font-medium">Activity</h4>
|
||||||
{workspaceSlug && (
|
{workspace_slug && (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{comments.map((comment: any) => (
|
{comments.map((comment: any) => (
|
||||||
<CommentCard comment={comment} workspaceSlug={workspaceSlug?.toString()} />
|
<CommentCard comment={comment} workspaceSlug={workspace_slug?.toString()} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<AddComment disabled={!userStore.currentUser} issueId={issueId} />
|
<AddComment disabled={!userStore.currentUser} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// components
|
|
||||||
import { IssueReactions } from "components/issues/peek-overview";
|
import { IssueReactions } from "components/issues/peek-overview";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
|
@ -9,22 +9,21 @@ import { groupReactions, renderEmoji } from "helpers/emoji.helper";
|
|||||||
import { ReactionSelector } from "components/ui";
|
import { ReactionSelector } from "components/ui";
|
||||||
|
|
||||||
export const IssueEmojiReactions: React.FC = observer(() => {
|
export const IssueEmojiReactions: React.FC = observer(() => {
|
||||||
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||||
|
// store
|
||||||
const { user: userStore, issue: issueStore } = useMobxStore();
|
const { user: userStore, issue: issueStore, issueDetails: issueDetailsStore } = useMobxStore();
|
||||||
|
|
||||||
const user = userStore?.currentUser;
|
const user = userStore?.currentUser;
|
||||||
const issueId = issueStore.activePeekOverviewIssueId;
|
const issueId = issueDetailsStore.peekId;
|
||||||
|
const reactions = issueId ? issueDetailsStore.details[issueId]?.reactions || [] : [];
|
||||||
const reactions = issueId ? issueStore.issue_detail[issueId]?.reactions || [] : [];
|
|
||||||
const groupedReactions = groupReactions(reactions, "reaction");
|
const groupedReactions = groupReactions(reactions, "reaction");
|
||||||
|
|
||||||
const handleReactionClick = (reactionHexa: string) => {
|
const handleReactionClick = (reactionHexa: string) => {
|
||||||
if (!workspace_slug || !project_slug || !issueId) return;
|
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)
|
if (userReaction)
|
||||||
issueStore.deleteIssueReactionAsync(workspace_slug, userReaction.project, userReaction.issue, reactionHexa);
|
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<ReactionSelector
|
<ReactionSelector
|
||||||
@ -63,7 +56,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
|
|||||||
}}
|
}}
|
||||||
key={reaction}
|
key={reaction}
|
||||||
className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md border ${
|
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-primary-100/10 border-custom-primary-100"
|
||||||
: "bg-custom-background-80 border-transparent"
|
: "bg-custom-background-80 border-transparent"
|
||||||
}`}
|
}`}
|
||||||
@ -71,7 +64,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
|
|||||||
<span>{renderEmoji(reaction)}</span>
|
<span>{renderEmoji(reaction)}</span>
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
reactions?.some((r) => r.actor === user?.id && r.reaction === reaction)
|
reactions?.some((r: any) => r.actor === user?.id && r.reaction === reaction)
|
||||||
? "text-custom-primary-100"
|
? "text-custom-primary-100"
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
// ui
|
|
||||||
import { IssueEmojiReactions, IssueVotes } from "components/issues/peek-overview";
|
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 = () => {
|
||||||
<div className="flex gap-3 items-center mt-4">
|
const { project: projectStore } = useMobxStore();
|
||||||
<div className="flex gap-2 items-center">
|
return (
|
||||||
<IssueVotes />
|
<div className="flex gap-3 items-center mt-4">
|
||||||
|
{projectStore?.deploySettings?.votes && (
|
||||||
|
<>
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<IssueVotes />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-0.5 h-8 bg-custom-background-200" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{projectStore?.deploySettings?.reactions && (
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<IssueEmojiReactions />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
<div className="w-0.5 h-8 bg-custom-background-200" />
|
};
|
||||||
|
|
||||||
<div className="flex gap-2 items-center">
|
|
||||||
<IssueEmojiReactions />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useMemo } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
@ -18,20 +18,19 @@ export const IssuePeekOverview: React.FC<Props> = observer((props) => {
|
|||||||
const { isOpen, onClose } = props;
|
const { isOpen, onClose } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspace_slug, project_slug } = router.query;
|
const { workspace_slug, project_slug, peekId } = router.query;
|
||||||
// store
|
// store
|
||||||
const { issueDetails: issueDetailStore } = useMobxStore();
|
const { issueDetails: issueDetailStore, issue: issueStore } = useMobxStore();
|
||||||
|
|
||||||
const issueDetails = issueDetailStore.peekId ? issueDetailStore.details[issueDetailStore.peekId] : null;
|
const issueDetails = issueDetailStore.peekId && peekId ? issueDetailStore.details[peekId.toString()] : null;
|
||||||
console.log("issueDetails", issueDetails);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace_slug && project_slug && issueDetailStore.peekId) {
|
if (workspace_slug && project_slug && peekId && issueStore.issues && issueStore.issues.length > 0) {
|
||||||
if (!issueDetails) {
|
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 = () => {
|
const handleClose = () => {
|
||||||
onClose();
|
onClose();
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
} from "components/issues/peek-overview";
|
} from "components/issues/peek-overview";
|
||||||
// types
|
// types
|
||||||
import { IIssue } from "types/issue";
|
import { IIssue } from "types/issue";
|
||||||
|
import { RootStore } from "store/root";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
@ -20,6 +21,8 @@ type Props = {
|
|||||||
export const SidePeekView: React.FC<Props> = observer((props) => {
|
export const SidePeekView: React.FC<Props> = observer((props) => {
|
||||||
const { handleClose, issueDetails } = props;
|
const { handleClose, issueDetails } = props;
|
||||||
|
|
||||||
|
const { project: projectStore } = useMobxStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full flex flex-col overflow-hidden">
|
<div className="h-full w-full flex flex-col overflow-hidden">
|
||||||
<div className="w-full p-5">
|
<div className="w-full p-5">
|
||||||
@ -38,9 +41,11 @@ export const SidePeekView: React.FC<Props> = observer((props) => {
|
|||||||
{/* divider */}
|
{/* divider */}
|
||||||
<div className="h-[1] w-full border-t border-custom-border-200 my-5" />
|
<div className="h-[1] w-full border-t border-custom-border-200 my-5" />
|
||||||
{/* issue activity/comments */}
|
{/* issue activity/comments */}
|
||||||
<div className="w-full pb-5">
|
{projectStore?.deploySettings?.comments && (
|
||||||
<PeekOverviewIssueActivity issueDetails={issueDetails} />
|
<div className="w-full pb-5">
|
||||||
</div>
|
<PeekOverviewIssueActivity issueDetails={issueDetails} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,10 +3,10 @@ import { useDebouncedCallback } from "use-debounce";
|
|||||||
import { EditorBubbleMenu } from "./bubble-menu";
|
import { EditorBubbleMenu } from "./bubble-menu";
|
||||||
import { TiptapExtensions } from "./extensions";
|
import { TiptapExtensions } from "./extensions";
|
||||||
import { TiptapEditorProps } from "./props";
|
import { TiptapEditorProps } from "./props";
|
||||||
import { useImperativeHandle, useRef } from "react";
|
import { useImperativeHandle, useRef, forwardRef } from "react";
|
||||||
import { ImageResizer } from "./extensions/image-resize";
|
import { ImageResizer } from "./extensions/image-resize";
|
||||||
|
|
||||||
export interface ITiptapRichTextEditor {
|
export interface ITipTapRichTextEditor {
|
||||||
value: string;
|
value: string;
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
borderOnFocus?: boolean;
|
borderOnFocus?: boolean;
|
||||||
@ -21,7 +21,7 @@ export interface ITiptapRichTextEditor {
|
|||||||
debouncedUpdatesEnabled?: boolean;
|
debouncedUpdatesEnabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tiptap = (props: ITiptapRichTextEditor) => {
|
const Tiptap = (props: ITipTapRichTextEditor) => {
|
||||||
const {
|
const {
|
||||||
onChange,
|
onChange,
|
||||||
debouncedUpdatesEnabled,
|
debouncedUpdatesEnabled,
|
||||||
@ -73,9 +73,10 @@ const Tiptap = (props: ITiptapRichTextEditor) => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
const editorClassNames = `relative w-full max-w-screen-lg sm:rounded-lg mt-2 p-3 relative focus:outline-none rounded-md
|
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"
|
${noBorder ? "" : "border border-custom-border-200"} ${
|
||||||
} ${customClassName}`;
|
borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0"
|
||||||
|
} ${customClassName}`;
|
||||||
|
|
||||||
if (!editor) return null;
|
if (!editor) return null;
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
@ -97,4 +98,10 @@ const Tiptap = (props: ITiptapRichTextEditor) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Tiptap;
|
const TipTapEditor = forwardRef<ITipTapRichTextEditor, ITipTapRichTextEditor>((props, ref) => (
|
||||||
|
<Tiptap {...props} forwardedRef={ref} />
|
||||||
|
));
|
||||||
|
|
||||||
|
TipTapEditor.displayName = "TipTapEditor";
|
||||||
|
|
||||||
|
export { TipTapEditor };
|
||||||
|
@ -14,12 +14,23 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
|
|
||||||
export const ProjectDetailsView = observer(() => {
|
export const ProjectDetailsView = observer(() => {
|
||||||
const router = useRouter();
|
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;
|
const activeIssueId = issueDetailStore.peekId;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!userStore.currentUser) {
|
||||||
|
userStore.fetchCurrentUser();
|
||||||
|
}
|
||||||
|
}, [userStore]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workspace_slug && project_slug) {
|
if (workspace_slug && project_slug) {
|
||||||
const params = {
|
const params = {
|
||||||
@ -31,11 +42,29 @@ export const ProjectDetailsView = observer(() => {
|
|||||||
}
|
}
|
||||||
}, [workspace_slug, project_slug, issueStore, states, labels, priorities]);
|
}, [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 (
|
return (
|
||||||
<div className="relative w-full h-full overflow-hidden">
|
<div className="relative w-full h-full overflow-hidden">
|
||||||
{workspace_slug && (
|
{workspace_slug && <IssuePeekOverview isOpen={Boolean(activeIssueId)} onClose={handlePeekClose} />}
|
||||||
<IssuePeekOverview isOpen={Boolean(activeIssueId)} onClose={() => issueDetailStore.setPeekId(null)} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{issueStore?.loader && !issueStore.issues ? (
|
{issueStore?.loader && !issueStore.issues ? (
|
||||||
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
||||||
|
@ -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 = () => (
|
const HomePage = () => {
|
||||||
<div className="relative w-screen h-screen flex justify-center items-center text-5xl">Plane Deploy</div>
|
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 (
|
||||||
|
<div className="h-screen w-full overflow-hidden">
|
||||||
|
<div className="hidden sm:block sm:fixed border-r-[0.5px] border-custom-border-200 h-screen w-[0.5px] top-0 left-20 lg:left-32" />
|
||||||
|
<div className="fixed grid place-items-center bg-custom-background-100 sm:py-5 top-11 sm:top-12 left-7 sm:left-16 lg:left-28">
|
||||||
|
<div className="grid place-items-center bg-custom-background-100">
|
||||||
|
<div className="h-[30px] w-[30px]">
|
||||||
|
<Image src={BluePlaneLogoWithoutText} alt="Plane Logo" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid place-items-center h-full overflow-y-auto py-5 px-7">
|
||||||
|
<div>
|
||||||
|
{parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? (
|
||||||
|
<>
|
||||||
|
<h1 className="text-center text-2xl sm:text-2.5xl font-semibold text-custom-text-100">
|
||||||
|
Sign in to Plane
|
||||||
|
</h1>
|
||||||
|
<div className="flex flex-col divide-y divide-custom-border-200">
|
||||||
|
<div className="pb-7">
|
||||||
|
<EmailCodeForm handleSignIn={handleEmailCodeSignIn} />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col items-center justify-center gap-4 pt-7 sm:w-[360px] mx-auto overflow-hidden">
|
||||||
|
<GoogleLoginButton handleSignIn={handleGoogleSignIn} />
|
||||||
|
<GithubLoginButton handleSignIn={handleGitHubSignIn} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<EmailPasswordForm onSubmit={handlePasswordSignIn} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? (
|
||||||
|
<p className="pt-16 text-custom-text-200 text-sm text-center">
|
||||||
|
By signing up, you agree to the{" "}
|
||||||
|
<a
|
||||||
|
href="https://plane.so/terms-and-conditions"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="font-medium underline"
|
||||||
|
>
|
||||||
|
Terms & Conditions
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default HomePage;
|
export default HomePage;
|
||||||
|
@ -13,10 +13,20 @@ export interface IIssueDetailStore {
|
|||||||
peekId: string | null;
|
peekId: string | null;
|
||||||
peekMode: IPeekMode;
|
peekMode: IPeekMode;
|
||||||
details: any;
|
details: any;
|
||||||
// actions
|
// peek actions
|
||||||
setPeekId: (issueId: string | null) => void;
|
setPeekId: (issueId: string | null) => void;
|
||||||
setPeekMode: (mode: IPeekMode) => void;
|
setPeekMode: (mode: IPeekMode) => void;
|
||||||
|
// issue details
|
||||||
fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void;
|
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 {
|
class IssueDetailStore implements IssueDetailStore {
|
||||||
@ -59,9 +69,7 @@ class IssueDetailStore implements IssueDetailStore {
|
|||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
|
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 commentsResponse = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
|
||||||
const votesResponse = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (issueDetails) {
|
if (issueDetails) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
@ -70,8 +78,6 @@ class IssueDetailStore implements IssueDetailStore {
|
|||||||
[issueId]: {
|
[issueId]: {
|
||||||
...issueDetails,
|
...issueDetails,
|
||||||
comments: commentsResponse,
|
comments: commentsResponse,
|
||||||
reactions: reactionsResponse,
|
|
||||||
votes: votesResponse,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -79,20 +85,148 @@ class IssueDetailStore implements IssueDetailStore {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
this.error = error;
|
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 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(() => {
|
updateIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
|
||||||
this.details = {
|
try {
|
||||||
...this.details,
|
const issueVoteResponse = await this.issueService.updateIssueComment(workspaceSlug, projectId, issueId, data);
|
||||||
[issueId]: {
|
if (issueVoteResponse) {
|
||||||
...issueDetails,
|
runInAction(() => {
|
||||||
comments: [],
|
this.details = {
|
||||||
reactions: [],
|
...this.details,
|
||||||
votes: [],
|
[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");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ export interface IProjectStore {
|
|||||||
error: any | null;
|
error: any | null;
|
||||||
workspace: IWorkspace | null;
|
workspace: IWorkspace | null;
|
||||||
project: IProject | null;
|
project: IProject | null;
|
||||||
projectDeploySettings: IProjectSettings | null;
|
deploySettings: IProjectSettings | null;
|
||||||
viewOptions: any;
|
viewOptions: any;
|
||||||
activeBoard: string | null;
|
activeBoard: string | null;
|
||||||
fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise<void>;
|
fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise<void>;
|
||||||
@ -23,7 +23,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
// data
|
// data
|
||||||
workspace: IWorkspace | null = null;
|
workspace: IWorkspace | null = null;
|
||||||
project: IProject | null = null;
|
project: IProject | null = null;
|
||||||
projectDeploySettings: IProjectSettings | null = null;
|
deploySettings: IProjectSettings | null = null;
|
||||||
viewOptions: any = null;
|
viewOptions: any = null;
|
||||||
activeBoard: string | null = null;
|
activeBoard: string | null = null;
|
||||||
// root store
|
// root store
|
||||||
@ -39,7 +39,7 @@ class ProjectStore implements IProjectStore {
|
|||||||
// observable
|
// observable
|
||||||
workspace: observable.ref,
|
workspace: observable.ref,
|
||||||
project: observable.ref,
|
project: observable.ref,
|
||||||
projectDeploySettings: observable.ref,
|
deploySettings: observable.ref,
|
||||||
viewOptions: observable.ref,
|
viewOptions: observable.ref,
|
||||||
activeBoard: observable.ref,
|
activeBoard: observable.ref,
|
||||||
// actions
|
// actions
|
||||||
@ -63,10 +63,12 @@ class ProjectStore implements IProjectStore {
|
|||||||
const _project: IProject = { ...response?.project_details };
|
const _project: IProject = { ...response?.project_details };
|
||||||
const _workspace: IWorkspace = { ...response?.workspace_detail };
|
const _workspace: IWorkspace = { ...response?.workspace_detail };
|
||||||
const _viewOptions = { ...response?.views };
|
const _viewOptions = { ...response?.views };
|
||||||
|
const _deploySettings = { ...response };
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.project = _project;
|
this.project = _project;
|
||||||
this.workspace = _workspace;
|
this.workspace = _workspace;
|
||||||
this.viewOptions = _viewOptions;
|
this.viewOptions = _viewOptions;
|
||||||
|
this.deploySettings = _deploySettings;
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||||
// service
|
// service
|
||||||
import UserService from "services/user.service";
|
import UserService from "services/user.service";
|
||||||
// types
|
|
||||||
import { IUserStore } from "../types";
|
export interface IUserStore {
|
||||||
|
currentUser: any | null;
|
||||||
|
fetchCurrentUser: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
class UserStore implements IUserStore {
|
class UserStore implements IUserStore {
|
||||||
currentUser: any | null = null;
|
currentUser: any | null = null;
|
||||||
@ -42,7 +45,7 @@ class UserStore implements IUserStore {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getUserAsync()
|
this.fetchCurrentUser()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!this.currentUser) {
|
if (!this.currentUser) {
|
||||||
const currentPath = window.location.pathname;
|
const currentPath = window.location.pathname;
|
||||||
@ -55,7 +58,7 @@ class UserStore implements IUserStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getUserAsync = async () => {
|
fetchCurrentUser = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await this.userService.currentUser();
|
const response = await this.userService.currentUser();
|
||||||
if (response) {
|
if (response) {
|
||||||
@ -64,10 +67,7 @@ class UserStore implements IUserStore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("error", error);
|
console.error("Failed to fetch current user", error);
|
||||||
runInAction(() => {
|
|
||||||
// render error actions
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export interface IUserStore {
|
|
||||||
currentUser: any | null;
|
|
||||||
getUserAsync: () => void;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user