diff --git a/apps/app/components/issues/description-form.tsx b/apps/app/components/issues/description-form.tsx index 2a82ec4da..7cbb99981 100644 --- a/apps/app/components/issues/description-form.tsx +++ b/apps/app/components/issues/description-form.tsx @@ -1,11 +1,9 @@ -import { FC, useCallback, useEffect, useMemo, useState } from "react"; +import { FC, useCallback, useEffect, useState } from "react"; import dynamic from "next/dynamic"; // react-hook-form import { useForm } from "react-hook-form"; -// lodash -import debounce from "lodash.debounce"; // components import { Loader, TextArea } from "components/ui"; const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), { @@ -27,7 +25,7 @@ export interface IssueDescriptionFormValues { export interface IssueDetailsProps { issue: IIssue; - handleFormSubmit: (value: IssueDescriptionFormValues) => void; + handleFormSubmit: (value: IssueDescriptionFormValues) => Promise; userAuth: UserAuth; } @@ -36,6 +34,7 @@ export const IssueDescriptionForm: FC = ({ handleFormSubmit, userAuth, }) => { + const [isSubmitting, setIsSubmitting] = useState(false); const [characterLimit, setCharacterLimit] = useState(false); const { @@ -53,10 +52,10 @@ export const IssueDescriptionForm: FC = ({ }); const handleDescriptionFormSubmit = useCallback( - (formData: Partial) => { + async (formData: Partial) => { if (!formData.name || formData.name.length === 0 || formData.name.length > 255) return; - handleFormSubmit({ + await handleFormSubmit({ name: formData.name ?? "", description: formData.description ?? "", description_html: formData.description_html ?? "

", @@ -65,17 +64,19 @@ export const IssueDescriptionForm: FC = ({ [handleFormSubmit] ); - const debounceHandler = useMemo( - () => debounce(handleSubmit(handleDescriptionFormSubmit), 2000), - [handleSubmit, handleDescriptionFormSubmit] - ); + useEffect(() => { + const alertUser = (e: BeforeUnloadEvent) => { + console.log("beforeunload"); + e.preventDefault(); + e.returnValue = ""; + return "Are you sure you want to leave?"; + }; - useEffect( - () => () => { - debounceHandler.cancel(); - }, - [debounceHandler] - ); + window.addEventListener("beforeunload", alertUser); + return () => { + window.removeEventListener("beforeunload", alertUser); + }; + }, [isSubmitting]); // reset form values useEffect(() => { @@ -95,19 +96,29 @@ export const IssueDescriptionForm: FC = ({ placeholder="Enter issue name" value={watch("name")} onFocus={() => setCharacterLimit(true)} - onBlur={() => setCharacterLimit(false)} + onBlur={() => { + setCharacterLimit(false); + + setIsSubmitting(true); + handleSubmit(handleDescriptionFormSubmit)() + .then(() => { + setIsSubmitting(false); + }) + .catch(() => { + setIsSubmitting(false); + }); + }} onChange={(e) => { setValue("name", e.target.value); - debounceHandler(); }} required={true} - className="block px-3 py-2 text-xl - w-full overflow-hidden resize-none min-h-10 - rounded border-none bg-transparent ring-0 focus:ring-1 focus:ring-theme outline-none" + className="min-h-10 block w-full resize-none + overflow-hidden rounded border-none bg-transparent + px-3 py-2 text-xl outline-none ring-0 focus:ring-1 focus:ring-theme" role="textbox" /> {characterLimit && ( -
+
255 ? "text-red-500" : "" @@ -123,13 +134,21 @@ export const IssueDescriptionForm: FC = ({ { - setValue("description", json); - debounceHandler(); + onBlur={() => { + setIsSubmitting(true); + handleSubmit(handleDescriptionFormSubmit)() + .then(() => { + setIsSubmitting(false); + }) + .catch(() => { + setIsSubmitting(false); + }); }} + onJSONChange={(json) => setValue("description", json)} onHTMLChange={(html) => setValue("description_html", html)} editable={!isNotAllowed} /> +
{isSubmitting && "Saving..."}
); }; diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx index e9b5ba271..8471a68f5 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx @@ -74,7 +74,7 @@ const IssueDetailsPage: NextPage = (props) => { }); const submitChanges = useCallback( - (formData: Partial) => { + async (formData: Partial) => { if (!workspaceSlug || !projectId || !issueId) return; mutate( @@ -87,7 +87,7 @@ const IssueDetailsPage: NextPage = (props) => { ); const payload = { ...formData }; - issuesService + await issuesService .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload) .then((res) => { mutateIssueDetails();