From 0ffa075110f1a5f2fc60d28873c3126365cd7262 Mon Sep 17 00:00:00 2001 From: rahulramesha <71900764+rahulramesha@users.noreply.github.com> Date: Wed, 29 Nov 2023 19:58:27 +0530 Subject: [PATCH] fix: v3 issues for the layouts (#2941) * fix drag n drop exception error * fix peek overlay close buttons * fix project empty state view * fix cycle and module empty state view * add ai options to inbox issue creation * fix inbox filters for viewers * fix inbox filters for viewers for project * disable editing permission for members and viewers * define accurate types for drag and drop --- .../inbox/modals/create-issue-modal.tsx | 144 +++++++++++-- .../issue-layouts/kanban/base-kanban-root.tsx | 18 +- .../issues/issue-layouts/kanban/block.tsx | 6 +- .../issue-layouts/kanban/roots/cycle-root.tsx | 5 +- .../kanban/roots/module-root.tsx | 27 +-- .../kanban/roots/profile-issues-root.tsx | 2 +- .../kanban/roots/project-root.tsx | 5 +- .../kanban/roots/project-view-root.tsx | 5 +- .../issue-layouts/list/base-list-root.tsx | 6 +- .../list/roots/profile-issues-root.tsx | 2 +- .../issue-layouts/roots/cycle-layout-root.tsx | 2 +- .../roots/module-layout-root.tsx | 2 +- .../roots/project-layout-root.tsx | 2 +- .../spreadsheet/base-spreadsheet-root.tsx | 5 +- web/store/inbox/inbox_filters.store.ts | 5 +- .../issues/base-issue-kanban-helper.store.ts | 194 ++++++++++-------- web/store/issues/profile/issue.store.ts | 7 +- 17 files changed, 290 insertions(+), 147 deletions(-) diff --git a/web/components/inbox/modals/create-issue-modal.tsx b/web/components/inbox/modals/create-issue-modal.tsx index 3a0746da6..0ab6b3d85 100644 --- a/web/components/inbox/modals/create-issue-modal.tsx +++ b/web/components/inbox/modals/create-issue-modal.tsx @@ -16,6 +16,10 @@ import { Button, Input, ToggleSwitch } from "@plane/ui"; // types import { IIssue } from "types"; import useEditorSuggestions from "hooks/use-editor-suggestions"; +import { GptAssistantModal } from "components/core"; +import { Sparkle } from "lucide-react"; +import useToast from "hooks/use-toast"; +import { AIService } from "services/ai.service"; type Props = { isOpen: boolean; @@ -31,6 +35,7 @@ const defaultValues: Partial = { }; // services +const aiService = new AIService(); const fileService = new FileService(); export const CreateInboxIssueModal: React.FC = observer((props) => { @@ -38,21 +43,35 @@ export const CreateInboxIssueModal: React.FC = observer((props) => { // states const [createMore, setCreateMore] = useState(false); + const [gptAssistantModal, setGptAssistantModal] = useState(false); + const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false); const editorRef = useRef(null); + const { setToastAlert } = useToast(); const editorSuggestion = useEditorSuggestions(); const router = useRouter(); - const { workspaceSlug, projectId, inboxId } = router.query; + const { workspaceSlug, projectId, inboxId } = router.query as { + workspaceSlug: string; + projectId: string; + inboxId: string; + }; - const { inboxIssueDetails: inboxIssueDetailsStore, trackEvent: { postHogEventTracker } } = useMobxStore(); + const { + inboxIssueDetails: inboxIssueDetailsStore, + trackEvent: { postHogEventTracker }, + appConfig: { envConfig }, + } = useMobxStore(); const { control, formState: { errors, isSubmitting }, handleSubmit, reset, + watch, + getValues, + setValue, } = useForm({ defaultValues }); const handleClose = () => { @@ -60,6 +79,8 @@ export const CreateInboxIssueModal: React.FC = observer((props) => { reset(defaultValues); }; + const issueName = watch("name"); + const handleFormSubmit = async (formData: Partial) => { if (!workspaceSlug || !projectId || !inboxId) return; @@ -70,24 +91,66 @@ export const CreateInboxIssueModal: React.FC = observer((props) => { router.push(`/${workspaceSlug}/projects/${projectId}/inbox/${inboxId}?inboxIssueId=${res.issue_inbox[0].id}`); handleClose(); } else reset(defaultValues); - postHogEventTracker( - "ISSUE_CREATE", - { - ...res, - state: "SUCCESS" - } - ); - }).catch((error) => { + postHogEventTracker("ISSUE_CREATE", { + ...res, + state: "SUCCESS", + }); + }) + .catch((error) => { console.log(error); - postHogEventTracker( - "ISSUE_CREATE", - { - state: "FAILED" - } - ); + postHogEventTracker("ISSUE_CREATE", { + state: "FAILED", + }); }); }; + const handleAiAssistance = async (response: string) => { + if (!workspaceSlug || !projectId) return; + + setValue("description", {}); + setValue("description_html", `${watch("description_html")}

${response}

`); + editorRef.current?.setEditorValue(`${watch("description_html")}`); + }; + + const handleAutoGenerateDescription = async () => { + if (!workspaceSlug || !projectId || !issueName) return; + + setIAmFeelingLucky(true); + + aiService + .createGptTask(workspaceSlug as string, projectId as string, { + prompt: issueName, + task: "Generate a proper description for this issue.", + }) + .then((res) => { + if (res.response === "") + setToastAlert({ + type: "error", + title: "Error!", + message: + "Issue title isn't informative enough to generate the description. Please try with a different title.", + }); + else handleAiAssistance(res.response_html); + }) + .catch((err) => { + const error = err?.data?.error; + + if (err.status === 429) + setToastAlert({ + type: "error", + title: "Error!", + message: error || "You have reached the maximum number of requests of 50 requests per month per user.", + }); + else + setToastAlert({ + type: "error", + title: "Error!", + message: error || "Some error occurred. Please try again.", + }); + }) + .finally(() => setIAmFeelingLucky(false)); + }; + return ( @@ -146,7 +209,35 @@ export const CreateInboxIssueModal: React.FC = observer((props) => { )} /> -
+
+
+ {issueName && issueName !== "" && ( + + )} + +
= observer((props) => { /> )} /> + {envConfig?.has_openai_configured && ( + { + setGptAssistantModal(false); + // this is done so that the title do not reset after gpt popover closed + reset(getValues()); + }} + inset="top-2 left-0" + content="" + htmlContent={watch("description_html")} + onResponse={(response) => { + handleAiAssistance(response); + }} + projectId={projectId} + /> + )}
@@ -188,7 +296,7 @@ export const CreateInboxIssueModal: React.FC = observer((props) => { onClick={() => setCreateMore((prevData) => !prevData)} > Create more - { }} size="md" /> + {}} size="md" />