Skip to content

Commit cdfff12

Browse files
authored
fix: fields not getting selected in the create issue form (#2212)
* fix: hydration error and draft issue workflow * fix: build error * fix: properties getting de-selected after create, module & cycle not getting auto-select on the form * fix: display layout, props being updated directly
1 parent e01a0d2 commit cdfff12

File tree

7 files changed

+284
-110
lines changed

7 files changed

+284
-110
lines changed

web/components/core/views/issues-view.tsx

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useState } from "react";
1+
import { useCallback, useEffect, useState } from "react";
22

33
import { useRouter } from "next/router";
44

@@ -87,8 +87,16 @@ export const IssuesView: React.FC<Props> = ({
8787

8888
const { setToastAlert } = useToast();
8989

90-
const { groupedByIssues, mutateIssues, displayFilters, filters, isEmpty, setFilters, params } =
91-
useIssuesView();
90+
const {
91+
groupedByIssues,
92+
mutateIssues,
93+
displayFilters,
94+
filters,
95+
isEmpty,
96+
setFilters,
97+
params,
98+
setDisplayFilters,
99+
} = useIssuesView();
92100
const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string);
93101

94102
const { data: stateGroups } = useSWR(
@@ -108,6 +116,17 @@ export const IssuesView: React.FC<Props> = ({
108116

109117
const { members } = useProjectMembers(workspaceSlug?.toString(), projectId?.toString());
110118

119+
useEffect(() => {
120+
if (!isDraftIssues) return;
121+
122+
if (
123+
displayFilters.layout === "calendar" ||
124+
displayFilters.layout === "gantt_chart" ||
125+
displayFilters.layout === "spreadsheet"
126+
)
127+
setDisplayFilters({ layout: "list" });
128+
}, [isDraftIssues, displayFilters, setDisplayFilters]);
129+
111130
const handleDeleteIssue = useCallback(
112131
(issue: IIssue) => {
113132
setDeleteIssueModal(true);

web/components/issues/confirm-issue-discard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const ConfirmIssueDiscard: React.FC<Props> = (props) => {
5757
<Dialog.Panel className="relative transform overflow-hidden rounded-lg border border-custom-border-200 bg-custom-background-100 text-left shadow-xl transition-all sm:my-8 sm:w-[40rem]">
5858
<div className="px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
5959
<div className="sm:flex sm:items-start">
60-
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
60+
<div className="mt-3 text-center sm:mt-0 sm:text-left">
6161
<Dialog.Title
6262
as="h3"
6363
className="text-lg font-medium leading-6 text-custom-text-100"

web/components/issues/draft-issue-form.tsx

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ const defaultValues: Partial<IIssue> = {
5555
};
5656

5757
interface IssueFormProps {
58-
handleFormSubmit: (formData: Partial<IIssue>) => Promise<void>;
58+
handleFormSubmit: (
59+
formData: Partial<IIssue>,
60+
action?: "createDraft" | "createNewIssue" | "updateDraft" | "convertToNewIssue"
61+
) => Promise<void>;
5962
data?: Partial<IIssue> | null;
6063
prePopulatedData?: Partial<IIssue> | null;
6164
projectId: string;
@@ -134,12 +137,16 @@ export const DraftIssueForm: FC<IssueFormProps> = (props) => {
134137

135138
const handleCreateUpdateIssue = async (
136139
formData: Partial<IIssue>,
137-
action: "saveDraft" | "createToNewIssue" = "saveDraft"
140+
action: "createDraft" | "createNewIssue" | "updateDraft" | "convertToNewIssue" = "createDraft"
138141
) => {
139-
await handleFormSubmit({
140-
...formData,
141-
is_draft: action === "saveDraft",
142-
});
142+
await handleFormSubmit(
143+
{
144+
...(data ?? {}),
145+
...formData,
146+
is_draft: action === "createDraft" || action === "updateDraft",
147+
},
148+
action
149+
);
143150

144151
setGptAssistantModal(false);
145152

@@ -263,7 +270,9 @@ export const DraftIssueForm: FC<IssueFormProps> = (props) => {
263270
</>
264271
)}
265272
<form
266-
onSubmit={handleSubmit((formData) => handleCreateUpdateIssue(formData, "createToNewIssue"))}
273+
onSubmit={handleSubmit((formData) =>
274+
handleCreateUpdateIssue(formData, "convertToNewIssue")
275+
)}
267276
>
268277
<div className="space-y-5">
269278
<div className="flex items-center gap-x-2">
@@ -563,15 +572,20 @@ export const DraftIssueForm: FC<IssueFormProps> = (props) => {
563572
<SecondaryButton onClick={onClose}>Discard</SecondaryButton>
564573
<SecondaryButton
565574
loading={isSubmitting}
566-
onClick={handleSubmit((formData) => handleCreateUpdateIssue(formData, "saveDraft"))}
575+
onClick={handleSubmit((formData) =>
576+
handleCreateUpdateIssue(formData, data?.id ? "updateDraft" : "createDraft")
577+
)}
567578
>
568579
{isSubmitting ? "Saving..." : "Save Draft"}
569580
</SecondaryButton>
570-
{data && (
571-
<PrimaryButton type="submit" loading={isSubmitting}>
572-
{isSubmitting ? "Saving..." : "Add Issue"}
573-
</PrimaryButton>
574-
)}
581+
<PrimaryButton
582+
loading={isSubmitting}
583+
onClick={handleSubmit((formData) =>
584+
handleCreateUpdateIssue(formData, data ? "convertToNewIssue" : "createNewIssue")
585+
)}
586+
>
587+
{isSubmitting ? "Saving..." : "Add Issue"}
588+
</PrimaryButton>
575589
</div>
576590
</div>
577591
</form>

web/components/issues/draft-issue-modal.tsx

Lines changed: 146 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ import {
3131
MODULE_ISSUES_WITH_PARAMS,
3232
VIEW_ISSUES,
3333
PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS,
34+
CYCLE_DETAILS,
35+
MODULE_DETAILS,
3436
} from "constants/fetch-keys";
37+
import modulesService from "services/modules.service";
3538

3639
interface IssuesModalProps {
3740
data?: IIssue | null;
@@ -56,18 +59,21 @@ interface IssuesModalProps {
5659
onSubmit?: (data: Partial<IIssue>) => Promise<void> | void;
5760
}
5861

59-
export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
60-
data,
61-
handleClose,
62-
isOpen,
63-
isUpdatingSingleIssue = false,
64-
prePopulateData,
65-
fieldsToShow = ["all"],
66-
onSubmit,
67-
}) => {
62+
export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = (props) => {
63+
const {
64+
data,
65+
handleClose,
66+
isOpen,
67+
isUpdatingSingleIssue = false,
68+
prePopulateData: prePopulateDataProps,
69+
fieldsToShow = ["all"],
70+
onSubmit,
71+
} = props;
72+
6873
// states
6974
const [createMore, setCreateMore] = useState(false);
7075
const [activeProject, setActiveProject] = useState<string | null>(null);
76+
const [prePopulateData, setPreloadedData] = useState<Partial<IIssue> | undefined>(undefined);
7177

7278
const router = useRouter();
7379
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
@@ -86,19 +92,40 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
8692

8793
const { setToastAlert } = useToast();
8894

89-
if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string };
90-
if (moduleId) prePopulateData = { ...prePopulateData, module: moduleId as string };
91-
if (router.asPath.includes("my-issues") || router.asPath.includes("assigned"))
92-
prePopulateData = {
93-
...prePopulateData,
94-
assignees: [...(prePopulateData?.assignees ?? []), user?.id ?? ""],
95-
};
96-
9795
const onClose = () => {
9896
handleClose();
9997
setActiveProject(null);
10098
};
10199

100+
useEffect(() => {
101+
setPreloadedData(prePopulateDataProps ?? {});
102+
103+
if (cycleId && !prePopulateDataProps?.cycle) {
104+
setPreloadedData((prevData) => ({
105+
...(prevData ?? {}),
106+
...prePopulateDataProps,
107+
cycle: cycleId.toString(),
108+
}));
109+
}
110+
if (moduleId && !prePopulateDataProps?.module) {
111+
setPreloadedData((prevData) => ({
112+
...(prevData ?? {}),
113+
...prePopulateDataProps,
114+
module: moduleId.toString(),
115+
}));
116+
}
117+
if (
118+
(router.asPath.includes("my-issues") || router.asPath.includes("assigned")) &&
119+
!prePopulateDataProps?.assignees
120+
) {
121+
setPreloadedData((prevData) => ({
122+
...(prevData ?? {}),
123+
...prePopulateDataProps,
124+
assignees: prePopulateDataProps?.assignees ?? [user?.id ?? ""],
125+
}));
126+
}
127+
}, [prePopulateDataProps, cycleId, moduleId, router.asPath, user?.id]);
128+
102129
useEffect(() => {
103130
// if modal is closed, reset active project to null
104131
// and return to avoid activeProject being set to some other project
@@ -109,10 +136,10 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
109136

110137
// if data is present, set active project to the project of the
111138
// issue. This has more priority than the project in the url.
112-
if (data && data.project) {
113-
setActiveProject(data.project);
114-
return;
115-
}
139+
if (data && data.project) return setActiveProject(data.project);
140+
141+
if (prePopulateData && prePopulateData.project && !activeProject)
142+
return setActiveProject(prePopulateData.project);
116143

117144
if (prePopulateData && prePopulateData.project)
118145
return setActiveProject(prePopulateData.project);
@@ -147,7 +174,7 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
147174
? VIEW_ISSUES(viewId.toString(), viewGanttParams)
148175
: PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject?.toString() ?? "");
149176

150-
const createIssue = async (payload: Partial<IIssue>) => {
177+
const createDraftIssue = async (payload: Partial<IIssue>) => {
151178
if (!workspaceSlug || !activeProject || !user) return;
152179

153180
await issuesService
@@ -187,7 +214,7 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
187214
if (!createMore) onClose();
188215
};
189216

190-
const updateIssue = async (payload: Partial<IIssue>) => {
217+
const updateDraftIssue = async (payload: Partial<IIssue>) => {
191218
if (!user) return;
192219

193220
await issuesService
@@ -203,6 +230,11 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
203230
mutate(PROJECT_DRAFT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
204231
}
205232

233+
if (!payload.is_draft) {
234+
if (payload.cycle && payload.cycle !== "") addIssueToCycle(res.id, payload.cycle);
235+
if (payload.module && payload.module !== "") addIssueToModule(res.id, payload.module);
236+
}
237+
206238
if (!createMore) onClose();
207239

208240
setToastAlert({
@@ -220,7 +252,93 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
220252
});
221253
};
222254

223-
const handleFormSubmit = async (formData: Partial<IIssue>) => {
255+
const addIssueToCycle = async (issueId: string, cycleId: string) => {
256+
if (!workspaceSlug || !activeProject) return;
257+
258+
await issuesService
259+
.addIssueToCycle(
260+
workspaceSlug as string,
261+
activeProject ?? "",
262+
cycleId,
263+
{
264+
issues: [issueId],
265+
},
266+
user
267+
)
268+
.then(() => {
269+
if (cycleId) {
270+
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId, params));
271+
mutate(CYCLE_DETAILS(cycleId as string));
272+
}
273+
});
274+
};
275+
276+
const addIssueToModule = async (issueId: string, moduleId: string) => {
277+
if (!workspaceSlug || !activeProject) return;
278+
279+
await modulesService
280+
.addIssuesToModule(
281+
workspaceSlug as string,
282+
activeProject ?? "",
283+
moduleId as string,
284+
{
285+
issues: [issueId],
286+
},
287+
user
288+
)
289+
.then(() => {
290+
if (moduleId) {
291+
mutate(MODULE_ISSUES_WITH_PARAMS(moduleId as string, params));
292+
mutate(MODULE_DETAILS(moduleId as string));
293+
}
294+
});
295+
};
296+
297+
const createIssue = async (payload: Partial<IIssue>) => {
298+
if (!workspaceSlug || !activeProject) return;
299+
300+
await issuesService
301+
.createIssues(workspaceSlug as string, activeProject ?? "", payload, user)
302+
.then(async (res) => {
303+
mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(activeProject ?? "", params));
304+
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
305+
if (payload.module && payload.module !== "") await addIssueToModule(res.id, payload.module);
306+
307+
if (displayFilters.layout === "calendar") mutate(calendarFetchKey);
308+
if (displayFilters.layout === "gantt_chart")
309+
mutate(ganttFetchKey, {
310+
start_target_date: true,
311+
order_by: "sort_order",
312+
});
313+
if (displayFilters.layout === "spreadsheet") mutate(spreadsheetFetchKey);
314+
if (groupedIssues) mutateMyIssues();
315+
316+
setToastAlert({
317+
type: "success",
318+
title: "Success!",
319+
message: "Issue created successfully.",
320+
});
321+
322+
if (!createMore) onClose();
323+
324+
if (payload.assignees_list?.some((assignee) => assignee === user?.id))
325+
mutate(USER_ISSUE(workspaceSlug as string));
326+
327+
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
328+
})
329+
.catch(() => {
330+
setToastAlert({
331+
type: "error",
332+
title: "Error!",
333+
message: "Issue could not be created. Please try again.",
334+
});
335+
});
336+
};
337+
338+
const handleFormSubmit = async (
339+
formData: Partial<IIssue>,
340+
action: "createDraft" | "createNewIssue" | "updateDraft" | "convertToNewIssue" = "createDraft"
341+
) => {
224342
if (!workspaceSlug || !activeProject) return;
225343

226344
const payload: Partial<IIssue> = {
@@ -231,8 +349,10 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = ({
231349
description_html: formData.description_html ?? "<p></p>",
232350
};
233351

234-
if (!data) await createIssue(payload);
235-
else await updateIssue(payload);
352+
if (action === "createDraft") await createDraftIssue(payload);
353+
else if (action === "updateDraft" || action === "convertToNewIssue")
354+
await updateDraftIssue(payload);
355+
else if (action === "createNewIssue") await createIssue(payload);
236356

237357
clearDraftIssueLocalStorage();
238358

web/components/issues/form.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ export const IssueForm: FC<IssueFormProps> = (props) => {
139139
target_date: getValues("target_date"),
140140
project: getValues("project"),
141141
parent: getValues("parent"),
142+
cycle: getValues("cycle"),
143+
module: getValues("module"),
142144
};
143145

144146
useEffect(() => {

0 commit comments

Comments
 (0)