diff --git a/web/components/issues/draft-issue-form.tsx b/web/components/issues/draft-issue-form.tsx index 8e0d8e604..6b1af9719 100644 --- a/web/components/issues/draft-issue-form.tsx +++ b/web/components/issues/draft-issue-form.tsx @@ -61,9 +61,8 @@ interface IssueFormProps { formData: Partial, action?: "createDraft" | "createNewIssue" | "updateDraft" | "convertToNewIssue" ) => Promise; - data?: Partial | null; + initialData?: Partial | null; isOpen: boolean; - prePopulatedData?: Partial | null; projectId: string; setActiveProject: React.Dispatch>; createMore: boolean; @@ -91,9 +90,8 @@ interface IssueFormProps { export const DraftIssueForm: FC = (props) => { const { handleFormSubmit, - data, + initialData, isOpen, - prePopulatedData, projectId, setActiveProject, createMore, @@ -124,7 +122,7 @@ export const DraftIssueForm: FC = (props) => { const editorSuggestions = useEditorSuggestions(workspaceSlug as string | undefined, projectId); const { - formState: { errors, isSubmitting }, + formState: { errors, isSubmitting, isDirty }, handleSubmit, reset, watch, @@ -132,30 +130,30 @@ export const DraftIssueForm: FC = (props) => { getValues, setValue, } = useForm({ - defaultValues: prePopulatedData ?? defaultValues, + defaultValues: initialData ?? defaultValues, reValidateMode: "onChange", }); const issueName = watch("name"); const payload: Partial = { - name: watch("name"), - description: watch("description"), - description_html: watch("description_html"), - state: watch("state"), - priority: watch("priority"), - assignees: watch("assignees"), - labels: watch("labels"), - start_date: watch("start_date"), - target_date: watch("target_date"), - project: watch("project"), - parent: watch("parent"), - cycle: watch("cycle"), - module: watch("module"), + name: getValues("name"), + description: getValues("description"), + description_html: getValues("description_html"), + state: getValues("state"), + priority: getValues("priority"), + assignees: getValues("assignees"), + labels: getValues("labels"), + start_date: getValues("start_date"), + target_date: getValues("target_date"), + project: getValues("project"), + parent: getValues("parent"), + cycle: getValues("cycle"), + module: getValues("module"), }; useEffect(() => { - if (!isOpen || data) return; + if (!isOpen) return; setLocalStorageValue( JSON.stringify({ @@ -163,7 +161,7 @@ export const DraftIssueForm: FC = (props) => { }) ); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [JSON.stringify(payload), isOpen, data]); + }, [JSON.stringify(payload), isOpen]); const handleCreateUpdateIssue = async ( formData: Partial, @@ -171,7 +169,7 @@ export const DraftIssueForm: FC = (props) => { ) => { await handleFormSubmit( { - ...(data ?? {}), + ...(initialData ?? {}), ...formData, }, action @@ -248,12 +246,14 @@ export const DraftIssueForm: FC = (props) => { }; useEffect(() => { + // if form is dirty, don't reset + if (isDirty) return; + reset({ ...defaultValues, - ...(prePopulatedData ?? {}), - ...(data ?? {}), + ...(initialData ?? {}), }); - }, [prePopulatedData, reset, data]); + }, [reset, initialData, isDirty]); // update projectId in form when projectId changes useEffect(() => { @@ -287,7 +287,7 @@ export const DraftIssueForm: FC = (props) => { )}
- handleCreateUpdateIssue(formData, data ? "convertToNewIssue" : "createDraft") + handleCreateUpdateIssue(formData, initialData?.id ? "convertToNewIssue" : "createDraft") )} >
@@ -583,7 +583,7 @@ export const DraftIssueForm: FC = (props) => { variant="neutral-primary" loading={isSubmitting} onClick={handleSubmit((formData) => - handleCreateUpdateIssue(formData, data?.id ? "updateDraft" : "createDraft") + handleCreateUpdateIssue(formData, initialData?.id ? "updateDraft" : "createDraft") )} > {isSubmitting ? "Saving..." : "Save Draft"} @@ -592,7 +592,7 @@ export const DraftIssueForm: FC = (props) => { loading={isSubmitting} variant="primary" onClick={handleSubmit((formData) => - handleCreateUpdateIssue(formData, data ? "convertToNewIssue" : "createNewIssue") + handleCreateUpdateIssue(formData, initialData?.id ? "convertToNewIssue" : "createNewIssue") )} > {isSubmitting ? "Saving..." : "Add Issue"} diff --git a/web/components/issues/draft-issue-modal.tsx b/web/components/issues/draft-issue-modal.tsx index 43b0ef74f..73c60f9d0 100644 --- a/web/components/issues/draft-issue-modal.tsx +++ b/web/components/issues/draft-issue-modal.tsx @@ -21,11 +21,10 @@ import type { IIssue } from "types"; import { SUB_ISSUES } from "constants/fetch-keys"; interface IssuesModalProps { - data?: IIssue | null; handleClose: () => void; isOpen: boolean; isUpdatingSingleIssue?: boolean; - prePopulateData?: Partial; + initialData?: Partial; fieldsToShow?: ( | "project" | "name" @@ -48,7 +47,7 @@ const issueService = new IssueService(); const moduleService = new ModuleService(); export const CreateUpdateDraftIssueModal: React.FC = observer((props) => { - const { data, handleClose, isOpen, prePopulateData: prePopulateDataProps, fieldsToShow = ["all"], onSubmit } = props; + const { handleClose, isOpen, initialData, fieldsToShow = ["all"], onSubmit } = props; // states const [createMore, setCreateMore] = useState(false); @@ -85,33 +84,30 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( }; useEffect(() => { - setPreloadedData(prePopulateDataProps ?? {}); + setPreloadedData(initialData ?? {}); - if (cycleId && !prePopulateDataProps?.cycle) { + if (cycleId && !initialData?.cycle) { setPreloadedData((prevData) => ({ ...(prevData ?? {}), - ...prePopulateDataProps, + ...initialData, cycle: cycleId.toString(), })); } - if (moduleId && !prePopulateDataProps?.module) { + if (moduleId && !initialData?.module) { setPreloadedData((prevData) => ({ ...(prevData ?? {}), - ...prePopulateDataProps, + ...initialData, module: moduleId.toString(), })); } - if ( - (router.asPath.includes("my-issues") || router.asPath.includes("assigned")) && - !prePopulateDataProps?.assignees - ) { + if ((router.asPath.includes("my-issues") || router.asPath.includes("assigned")) && !initialData?.assignees) { setPreloadedData((prevData) => ({ ...(prevData ?? {}), - ...prePopulateDataProps, - assignees: prePopulateDataProps?.assignees ?? [user?.id ?? ""], + ...initialData, + assignees: initialData?.assignees ?? [user?.id ?? ""], })); } - }, [prePopulateDataProps, cycleId, moduleId, router.asPath, user?.id]); + }, [initialData, cycleId, moduleId, router.asPath, user?.id]); useEffect(() => { // if modal is closed, reset active project to null @@ -123,7 +119,7 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( // if data is present, set active project to the project of the // issue. This has more priority than the project in the url. - if (data && data.project) return setActiveProject(data.project); + if (initialData && initialData.project) return setActiveProject(initialData.project); if (prePopulateData && prePopulateData.project && !activeProject) return setActiveProject(prePopulateData.project); @@ -133,7 +129,7 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( // in the url. This has the least priority. if (projects && projects.length > 0 && !activeProject) setActiveProject(projects?.find((p) => p.id === projectId)?.id ?? projects?.[0].id ?? null); - }, [activeProject, data, projectId, projects, isOpen, prePopulateData]); + }, [activeProject, initialData, projectId, projects, isOpen, prePopulateData]); const createDraftIssue = async (payload: Partial) => { if (!workspaceSlug || !activeProject || !user) return; @@ -328,15 +324,14 @@ export const CreateUpdateDraftIssueModal: React.FC = observer( diff --git a/web/components/issues/issue-layouts/list/roots/project-draft-issue-root.tsx b/web/components/issues/issue-layouts/list/roots/project-draft-issue-root.tsx index aa7f3466f..2335a4528 100644 --- a/web/components/issues/issue-layouts/list/roots/project-draft-issue-root.tsx +++ b/web/components/issues/issue-layouts/list/roots/project-draft-issue-root.tsx @@ -33,18 +33,13 @@ export const DraftIssueListLayout: FC = observer(() => { (group_by: string | null, issue: IIssue, action: "update" | "delete" | "convertToIssue") => { if (!workspaceSlug || !projectId) return; - const grouping = { - group_id: group_by, - sub_group_id: null, - }; - if (action === "update") { - draftIssuesStore.updateDraftIssue(workspaceSlug.toString(), projectId.toString(), grouping, issue); + draftIssuesStore.updateDraftIssue(workspaceSlug.toString(), projectId.toString(), issue); draftIssuesStore.updateIssueStructure(group_by, null, issue); } else if (action === "delete") { draftIssuesStore.deleteDraftIssue(workspaceSlug.toString(), projectId.toString(), issue.id); } else if (action === "convertToIssue") { - draftIssuesStore.convertDraftIssueToIssue(workspaceSlug.toString(), projectId.toString(), grouping, issue.id); + draftIssuesStore.convertDraftIssueToIssue(workspaceSlug.toString(), projectId.toString(), issue.id); } }, [workspaceSlug, projectId, draftIssuesStore] diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx index 4fc808398..47432363a 100644 --- a/web/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx +++ b/web/components/issues/issue-layouts/quick-action-dropdowns/draft-issue.tsx @@ -28,9 +28,7 @@ export const DraftIssueQuickActions: React.FC = (props) => { setCreateUpdateIssueModal(false); setIssueToEdit(null); }} - // pre-populate date only if not editing - prePopulateData={!issueToEdit && createUpdateIssueModal ? { ...issue } : {}} - data={issueToEdit} + initialData={issueToEdit ? { ...issueToEdit } : { ...issue, name: issue?.name, description: issue.description }} /> { setIsDraftIssueModalOpen(false)} - prePopulateData={storedValue ? JSON.parse(storedValue) : {}} + initialData={storedValue ? JSON.parse(storedValue) : {}} onSubmit={() => { localStorage.removeItem("draftedIssue"); clearValue();