From 90843a4037b8abf7c3ba82b597f990773ed1b689 Mon Sep 17 00:00:00 2001 From: Palanikannan M Date: Tue, 8 Jul 2025 12:24:54 +0530 Subject: [PATCH 1/2] feat: enhance issue description input with unsaved changes tracking --- .../components/issues/description-input.tsx | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/web/core/components/issues/description-input.tsx b/apps/web/core/components/issues/description-input.tsx index 10d0dfac8ba..1d89f194a4d 100644 --- a/apps/web/core/components/issues/description-input.tsx +++ b/apps/web/core/components/issues/description-input.tsx @@ -1,6 +1,6 @@ "use client"; -import { FC, useCallback, useEffect, useState } from "react"; +import { FC, useCallback, useEffect, useRef, useState } from "react"; import debounce from "lodash/debounce"; import { observer } from "mobx-react"; import { Controller, useForm } from "react-hook-form"; @@ -53,6 +53,8 @@ export const IssueDescriptionInput: FC = observer((p id: issueId, description_html: initialValue, }); + // ref to track if there are unsaved changes + const hasUnsavedChanges = useRef(false); // store hooks const { uploadEditorAsset } = useEditorAsset(); const { getWorkspaceBySlug } = useWorkspace(); @@ -87,6 +89,8 @@ export const IssueDescriptionInput: FC = observer((p id: issueId, description_html: initialValue === "" ? "

" : initialValue, }); + // Reset unsaved changes flag when form is reset + hasUnsavedChanges.current = false; }, [initialValue, issueId, reset]); // ADDING handleDescriptionFormSubmit TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS @@ -94,11 +98,31 @@ export const IssueDescriptionInput: FC = observer((p // eslint-disable-next-line react-hooks/exhaustive-deps const debouncedFormSave = useCallback( debounce(async () => { - handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); + handleSubmit(handleDescriptionFormSubmit)().finally(() => { + setIsSubmitting("submitted"); + hasUnsavedChanges.current = false; + }); }, 1500), [handleSubmit, issueId] ); + // Save on unmount if there are unsaved changes + useEffect( + () => () => { + debouncedFormSave.cancel(); + + if (hasUnsavedChanges.current) { + handleSubmit(handleDescriptionFormSubmit)().finally(() => { + setIsSubmitting("submitted"); + hasUnsavedChanges.current = false; + }); + } + }, + // since we don't want to save on unmount if there are no unsaved changes, no deps are needed + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ); + if (!workspaceId) return null; return ( @@ -120,6 +144,7 @@ export const IssueDescriptionInput: FC = observer((p onChange={(_description: object, description_html: string) => { setIsSubmitting("submitting"); onChange(description_html); + hasUnsavedChanges.current = true; debouncedFormSave(); }} placeholder={ From e7c09ebd332c5bfa347f269e267f23f70e2acd48 Mon Sep 17 00:00:00 2001 From: Palanikannan M Date: Tue, 8 Jul 2025 12:52:31 +0530 Subject: [PATCH 2/2] description saved with error handling --- .../web/core/components/issues/description-input.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/web/core/components/issues/description-input.tsx b/apps/web/core/components/issues/description-input.tsx index 1d89f194a4d..1e99de3aa82 100644 --- a/apps/web/core/components/issues/description-input.tsx +++ b/apps/web/core/components/issues/description-input.tsx @@ -112,10 +112,14 @@ export const IssueDescriptionInput: FC = observer((p debouncedFormSave.cancel(); if (hasUnsavedChanges.current) { - handleSubmit(handleDescriptionFormSubmit)().finally(() => { - setIsSubmitting("submitted"); - hasUnsavedChanges.current = false; - }); + handleSubmit(handleDescriptionFormSubmit)() + .catch((error) => { + console.error("Failed to save description on unmount:", error); + }) + .finally(() => { + setIsSubmitting("submitted"); + hasUnsavedChanges.current = false; + }); } }, // since we don't want to save on unmount if there are no unsaved changes, no deps are needed