forked from github/plane
fix: cycle modal redendent component fix (#2528)
This commit is contained in:
parent
08f7ac6da7
commit
07d548ea43
@ -8,7 +8,7 @@ import useUser from "hooks/use-user";
|
||||
// components
|
||||
import { CommandModal, ShortcutsModal } from "components/command-palette";
|
||||
import { BulkDeleteIssuesModal } from "components/core";
|
||||
import { CreateUpdateCycleModal } from "components/cycles";
|
||||
import { CycleCreateUpdateModal } from "components/cycles";
|
||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
|
||||
import { CreateUpdateModuleModal } from "components/modules";
|
||||
import { CreateProjectModal } from "components/project";
|
||||
@ -180,7 +180,7 @@ export const CommandPalette: FC = observer(() => {
|
||||
)}
|
||||
{workspaceSlug && projectId && (
|
||||
<>
|
||||
<CreateUpdateCycleModal
|
||||
<CycleCreateUpdateModal
|
||||
isOpen={isCreateCycleModalOpen}
|
||||
handleClose={() => toggleCreateCycleModal(false)}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
|
@ -1,163 +0,0 @@
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
import { CycleForm } from "./form";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// types
|
||||
import { CycleDateCheckData, ICycle } from "types";
|
||||
|
||||
interface ICycleCreateEdit {
|
||||
cycle?: ICycle | null;
|
||||
modal: boolean;
|
||||
modalClose: () => void;
|
||||
onSubmit?: () => void;
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export const CycleCreateEditModal: React.FC<ICycleCreateEdit> = observer((props) => {
|
||||
const { modal, modalClose, cycle = null, onSubmit, workspaceSlug, projectId } = props;
|
||||
const [activeProject, setActiveProject] = useState<string | null>(null);
|
||||
|
||||
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const validateCycleDate = async (payload: CycleDateCheckData) => {
|
||||
let status = false;
|
||||
await cycleStore.validateDate(workspaceSlug as string, projectId as string, payload).then((res) => {
|
||||
status = res.status;
|
||||
});
|
||||
return status;
|
||||
};
|
||||
|
||||
const formSubmit = async (data: Partial<ICycle>) => {
|
||||
let isDateValid: boolean = true;
|
||||
|
||||
if (data?.start_date && data?.end_date) {
|
||||
if (cycle?.id && cycle?.start_date && cycle?.end_date)
|
||||
isDateValid = await validateCycleDate({
|
||||
start_date: data.start_date,
|
||||
end_date: data.end_date,
|
||||
cycle_id: cycle.id,
|
||||
});
|
||||
else
|
||||
isDateValid = await validateCycleDate({
|
||||
start_date: data.start_date,
|
||||
end_date: data.end_date,
|
||||
});
|
||||
}
|
||||
|
||||
if (isDateValid)
|
||||
if (cycle) {
|
||||
try {
|
||||
await cycleStore.updateCycle(workspaceSlug, projectId, cycle.id, data);
|
||||
if (modalClose) modalClose();
|
||||
if (onSubmit) onSubmit();
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Cycle updated successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Warning!",
|
||||
message: "Something went wrong please try again later.",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
await cycleStore.createCycle(workspaceSlug, projectId, data);
|
||||
if (modalClose) modalClose();
|
||||
if (onSubmit) onSubmit();
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
message: "Cycle created successfully.",
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Warning!",
|
||||
message: "Something went wrong please try again later.",
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
title: "Error!",
|
||||
message: "You already have a cycle on the given dates, if you want to create a draft cycle, remove the dates.",
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// if modal is closed, reset active project to null
|
||||
// and return to avoid activeProject being set to some other project
|
||||
if (!modal) {
|
||||
setActiveProject(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// if data is present, set active project to the project of the
|
||||
// issue. This has more priority than the project in the url.
|
||||
if (cycle && cycle.project) {
|
||||
setActiveProject(cycle.project);
|
||||
return;
|
||||
}
|
||||
|
||||
// if data is not present, set active project to the project
|
||||
// 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, cycle, projectId, projects, modal]);
|
||||
|
||||
return (
|
||||
<Transition.Root show={modal} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={modalClose}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<Dialog.Panel className="relative transform rounded-lg border border-custom-border-200 bg-custom-background-100 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-2xl p-5">
|
||||
<CycleForm
|
||||
handleFormSubmit={formSubmit}
|
||||
handleClose={modalClose}
|
||||
projectId={activeProject ?? ""}
|
||||
setActiveProject={setActiveProject}
|
||||
data={cycle}
|
||||
/>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
);
|
||||
});
|
@ -7,8 +7,7 @@ import { Disclosure, Transition } from "@headlessui/react";
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { SingleProgressStats } from "components/core";
|
||||
import { CycleCreateEditModal } from "./cycle-create-edit-modal";
|
||||
import { CycleDeleteModal } from "./cycle-delete-modal";
|
||||
import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles";
|
||||
// ui
|
||||
import { AssigneesList } from "components/ui/avatar";
|
||||
import { CustomMenu, Tooltip, LinearProgressIndicator, ContrastIcon, RunningIcon } from "@plane/ui";
|
||||
@ -69,19 +68,14 @@ export interface ICyclesBoardCard {
|
||||
|
||||
export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
||||
const { cycle, workspaceSlug, projectId } = props;
|
||||
|
||||
const [updateModal, setUpdateModal] = useState(false);
|
||||
const updateModalCallback = () => {};
|
||||
|
||||
const [deleteModal, setDeleteModal] = useState(false);
|
||||
const deleteModalCallback = () => {};
|
||||
|
||||
// store
|
||||
const { cycle: cycleStore } = useMobxStore();
|
||||
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// states
|
||||
const [updateModal, setUpdateModal] = useState(false);
|
||||
const [deleteModal, setDeleteModal] = useState(false);
|
||||
// computed
|
||||
const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date);
|
||||
const isCompleted = cycleStatus === "completed";
|
||||
const endDate = new Date(cycle.end_date ?? "");
|
||||
@ -142,20 +136,18 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CycleCreateEditModal
|
||||
cycle={cycle}
|
||||
modal={updateModal}
|
||||
modalClose={() => setUpdateModal(false)}
|
||||
onSubmit={updateModalCallback}
|
||||
<CycleCreateUpdateModal
|
||||
data={cycle}
|
||||
isOpen={updateModal}
|
||||
handleClose={() => setUpdateModal(false)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
/>
|
||||
|
||||
<CycleDeleteModal
|
||||
cycle={cycle}
|
||||
modal={deleteModal}
|
||||
modalClose={() => setDeleteModal(false)}
|
||||
onSubmit={deleteModalCallback}
|
||||
isOpen={deleteModal}
|
||||
handleClose={() => setDeleteModal(false)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
/>
|
||||
|
@ -3,8 +3,7 @@ import Link from "next/link";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { CycleCreateEditModal } from "./cycle-create-edit-modal";
|
||||
import { CycleDeleteModal } from "./cycle-delete-modal";
|
||||
import { CycleCreateUpdateModal, CycleDeleteModal } from "components/cycles";
|
||||
// ui
|
||||
import { CustomMenu, RadialProgressBar, Tooltip, LinearProgressIndicator, ContrastIcon, RunningIcon } from "@plane/ui";
|
||||
// icons
|
||||
@ -66,19 +65,14 @@ const stateGroups = [
|
||||
|
||||
export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
||||
const { cycle, workspaceSlug, projectId } = props;
|
||||
|
||||
const [updateModal, setUpdateModal] = useState(false);
|
||||
const updateModalCallback = () => {};
|
||||
|
||||
const [deleteModal, setDeleteModal] = useState(false);
|
||||
const deleteModalCallback = () => {};
|
||||
|
||||
// store
|
||||
const { cycle: cycleStore } = useMobxStore();
|
||||
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// states
|
||||
const [updateModal, setUpdateModal] = useState(false);
|
||||
const [deleteModal, setDeleteModal] = useState(false);
|
||||
// computed
|
||||
const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date);
|
||||
const isCompleted = cycleStatus === "completed";
|
||||
const endDate = new Date(cycle.end_date ?? "");
|
||||
@ -347,20 +341,18 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CycleCreateEditModal
|
||||
cycle={cycle}
|
||||
modal={updateModal}
|
||||
modalClose={() => setUpdateModal(false)}
|
||||
onSubmit={updateModalCallback}
|
||||
<CycleCreateUpdateModal
|
||||
data={cycle}
|
||||
isOpen={updateModal}
|
||||
handleClose={() => setUpdateModal(false)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
/>
|
||||
|
||||
<CycleDeleteModal
|
||||
cycle={cycle}
|
||||
modal={deleteModal}
|
||||
modalClose={() => setDeleteModal(false)}
|
||||
onSubmit={deleteModalCallback}
|
||||
isOpen={deleteModal}
|
||||
handleClose={() => setDeleteModal(false)}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
/>
|
||||
|
@ -13,24 +13,23 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
interface ICycleDelete {
|
||||
cycle: ICycle;
|
||||
modal: boolean;
|
||||
modalClose: () => void;
|
||||
onSubmit?: () => void;
|
||||
isOpen: boolean;
|
||||
handleClose: () => void;
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
const { modal, modalClose, cycle, onSubmit, workspaceSlug, projectId } = props;
|
||||
|
||||
const { isOpen, handleClose, cycle, workspaceSlug, projectId } = props;
|
||||
// store
|
||||
const { cycle: cycleStore } = useMobxStore();
|
||||
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// states
|
||||
const [loader, setLoader] = useState(false);
|
||||
|
||||
const formSubmit = async () => {
|
||||
setLoader(true);
|
||||
|
||||
if (cycle?.id)
|
||||
try {
|
||||
await cycleStore.removeCycle(workspaceSlug, projectId, cycle?.id);
|
||||
@ -39,8 +38,7 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
title: "Success!",
|
||||
message: "Cycle deleted successfully.",
|
||||
});
|
||||
if (modalClose) modalClose();
|
||||
if (onSubmit) onSubmit();
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
@ -61,8 +59,8 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<Transition.Root show={modal} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={modalClose}>
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<Transition.Child
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
@ -103,7 +101,7 @@ export const CycleDeleteModal: React.FC<ICycleDelete> = observer((props) => {
|
||||
</p>
|
||||
</span>
|
||||
<div className="flex justify-end gap-2">
|
||||
<SecondaryButton onClick={modalClose}>Cancel</SecondaryButton>
|
||||
<SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
|
||||
<DangerButton onClick={formSubmit} loading={loader}>
|
||||
{loader ? "Deleting..." : "Delete Cycle"}
|
||||
</DangerButton>
|
@ -10,7 +10,7 @@ type Props = {
|
||||
handleFormSubmit: (values: Partial<ICycle>) => Promise<void>;
|
||||
handleClose: () => void;
|
||||
projectId: string;
|
||||
setActiveProject: React.Dispatch<React.SetStateAction<string | null>>;
|
||||
setActiveProject: (projectId: string) => void;
|
||||
data?: ICycle | null;
|
||||
};
|
||||
|
||||
|
@ -16,3 +16,4 @@ export * from "./cycles-list-item";
|
||||
export * from "./cycles-board";
|
||||
export * from "./cycles-board-card";
|
||||
export * from "./cycles-gantt";
|
||||
export * from "./delete-modal";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { mutate } from "swr";
|
||||
import React, { useState } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
import { CycleService } from "services/cycle.service";
|
||||
@ -8,20 +7,8 @@ import useToast from "hooks/use-toast";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { CycleForm } from "components/cycles";
|
||||
// helper
|
||||
import { getDateRangeStatus } from "helpers/date-time.helper";
|
||||
// types
|
||||
import type { CycleDateCheckData, ICycle, IProject, IUser } from "types";
|
||||
// fetch keys
|
||||
import {
|
||||
COMPLETED_CYCLES_LIST,
|
||||
CURRENT_CYCLE_LIST,
|
||||
CYCLES_LIST,
|
||||
DRAFT_CYCLES_LIST,
|
||||
INCOMPLETE_CYCLES_LIST,
|
||||
PROJECT_DETAILS,
|
||||
UPCOMING_CYCLES_LIST,
|
||||
} from "constants/fetch-keys";
|
||||
import type { CycleDateCheckData, ICycle } from "types";
|
||||
|
||||
type CycleModalProps = {
|
||||
isOpen: boolean;
|
||||
@ -34,49 +21,19 @@ type CycleModalProps = {
|
||||
// services
|
||||
const cycleService = new CycleService();
|
||||
|
||||
export const CreateUpdateCycleModal: React.FC<CycleModalProps> = (props) => {
|
||||
export const CycleCreateUpdateModal: React.FC<CycleModalProps> = (props) => {
|
||||
const { isOpen, handleClose, data, workspaceSlug, projectId } = props;
|
||||
const [activeProject, setActiveProject] = useState<string | null>(null);
|
||||
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : undefined;
|
||||
|
||||
// store
|
||||
const { cycle: cycleStore } = useMobxStore();
|
||||
// states
|
||||
const [activeProject, setActiveProject] = useState<string>(projectId);
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const createCycle = async (payload: Partial<ICycle>) => {
|
||||
await cycleService
|
||||
.createCycle(workspaceSlug.toString(), projectId.toString(), payload, {} as IUser)
|
||||
.then((res) => {
|
||||
switch (getDateRangeStatus(res.start_date, res.end_date)) {
|
||||
case "completed":
|
||||
mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
case "current":
|
||||
mutate(CURRENT_CYCLE_LIST(projectId.toString()));
|
||||
break;
|
||||
case "upcoming":
|
||||
mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
default:
|
||||
mutate(DRAFT_CYCLES_LIST(projectId.toString()));
|
||||
}
|
||||
mutate(INCOMPLETE_CYCLES_LIST(projectId.toString()));
|
||||
mutate(CYCLES_LIST(projectId.toString()));
|
||||
|
||||
// update total cycles count in the project details
|
||||
mutate<IProject>(
|
||||
PROJECT_DETAILS(projectId.toString()),
|
||||
(prevData) => {
|
||||
if (!prevData) return prevData;
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
total_cycles: prevData.total_cycles + 1,
|
||||
};
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
const createCycle = async (payload: Partial<ICycle>) =>
|
||||
cycleStore
|
||||
.createCycle(workspaceSlug, projectId, payload)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
@ -90,42 +47,11 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = (props) => {
|
||||
message: "Error in creating cycle. Please try again.",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const updateCycle = async (cycleId: string, payload: Partial<ICycle>) => {
|
||||
await cycleService
|
||||
.updateCycle(workspaceSlug.toString(), projectId.toString(), cycleId, payload, {} as IUser)
|
||||
.then((res) => {
|
||||
switch (getDateRangeStatus(data?.start_date, data?.end_date)) {
|
||||
case "completed":
|
||||
mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
case "current":
|
||||
mutate(CURRENT_CYCLE_LIST(projectId.toString()));
|
||||
break;
|
||||
case "upcoming":
|
||||
mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
default:
|
||||
mutate(DRAFT_CYCLES_LIST(projectId.toString()));
|
||||
}
|
||||
mutate(CYCLES_LIST(projectId.toString()));
|
||||
if (getDateRangeStatus(data?.start_date, data?.end_date) != getDateRangeStatus(res.start_date, res.end_date)) {
|
||||
switch (getDateRangeStatus(res.start_date, res.end_date)) {
|
||||
case "completed":
|
||||
mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
case "current":
|
||||
mutate(CURRENT_CYCLE_LIST(projectId.toString()));
|
||||
break;
|
||||
case "upcoming":
|
||||
mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
|
||||
break;
|
||||
default:
|
||||
mutate(DRAFT_CYCLES_LIST(projectId.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
const updateCycle = async (cycleId: string, payload: Partial<ICycle>) =>
|
||||
cycleStore
|
||||
.updateCycle(workspaceSlug, projectId, cycleId, payload)
|
||||
.then(() => {
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
@ -139,7 +65,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = (props) => {
|
||||
message: "Error in updating cycle. Please try again.",
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const dateChecker = async (payload: CycleDateCheckData) => {
|
||||
let status = false;
|
||||
@ -186,27 +111,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// if modal is closed, reset active project to null
|
||||
// and return to avoid activeProject being set to some other project
|
||||
if (!isOpen) {
|
||||
setActiveProject(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
setActiveProject(data.project);
|
||||
return;
|
||||
}
|
||||
|
||||
// if data is not present, set active project to the project
|
||||
// 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]);
|
||||
|
||||
return (
|
||||
<Transition.Root show={isOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
@ -237,7 +141,7 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = (props) => {
|
||||
<CycleForm
|
||||
handleFormSubmit={handleFormSubmit}
|
||||
handleClose={handleClose}
|
||||
projectId={activeProject ?? ""}
|
||||
projectId={activeProject}
|
||||
setActiveProject={setActiveProject}
|
||||
data={data}
|
||||
/>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
import { ContrastIcon } from "@plane/ui";
|
||||
@ -9,7 +8,7 @@ import { Plus } from "lucide-react";
|
||||
// services
|
||||
import { CycleService } from "services/cycle.service";
|
||||
// components
|
||||
import { CreateUpdateCycleModal } from "components/cycles";
|
||||
import { CycleCreateUpdateModal } from "components/cycles";
|
||||
// fetch-keys
|
||||
import { CYCLES_LIST } from "constants/fetch-keys";
|
||||
|
||||
@ -29,8 +28,6 @@ export const CycleSelect: React.FC<IssueCycleSelectProps> = ({ projectId, value,
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { data: cycles } = useSWR(
|
||||
workspaceSlug && projectId ? CYCLES_LIST(projectId) : null,
|
||||
workspaceSlug && projectId
|
||||
@ -51,7 +48,7 @@ export const CycleSelect: React.FC<IssueCycleSelectProps> = ({ projectId, value,
|
||||
return (
|
||||
<>
|
||||
{workspaceSlug && projectId && (
|
||||
<CreateUpdateCycleModal
|
||||
<CycleCreateUpdateModal
|
||||
isOpen={isCycleModalActive}
|
||||
handleClose={closeCycleModal}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
|
@ -13,7 +13,7 @@ import useToast from "hooks/use-toast";
|
||||
// components
|
||||
import { SidebarProgressStats } from "components/core";
|
||||
import ProgressChart from "components/core/sidebar/progress-chart";
|
||||
import { CycleDeleteModal } from "components/cycles/cycle-delete-modal";
|
||||
import { CycleDeleteModal } from "components/cycles/delete-modal";
|
||||
// ui
|
||||
import { CustomRangeDatePicker } from "components/ui";
|
||||
import { CustomMenu, Loader, ProgressBar } from "@plane/ui";
|
||||
@ -285,9 +285,8 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
||||
{cycleDetails && workspaceSlug && projectId && (
|
||||
<CycleDeleteModal
|
||||
cycle={cycleDetails}
|
||||
modal={cycleDeleteModal}
|
||||
modalClose={() => setCycleDeleteModal(false)}
|
||||
onSubmit={() => {}}
|
||||
isOpen={cycleDeleteModal}
|
||||
handleClose={() => setCycleDeleteModal(false)}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={projectId.toString()}
|
||||
/>
|
||||
|
@ -10,8 +10,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { AppLayout } from "layouts/app-layout";
|
||||
// components
|
||||
import { CyclesHeader } from "components/headers";
|
||||
import { CyclesView, ActiveCycleDetails } from "components/cycles";
|
||||
import { CycleCreateEditModal } from "components/cycles/cycle-create-edit-modal";
|
||||
import { CyclesView, ActiveCycleDetails, CycleCreateUpdateModal } from "components/cycles";
|
||||
// ui
|
||||
import { EmptyState } from "components/common";
|
||||
// images
|
||||
@ -26,15 +25,12 @@ import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
||||
|
||||
const ProjectCyclesPage: NextPage = observer(() => {
|
||||
const [createModal, setCreateModal] = useState(false);
|
||||
const createOnSubmit = () => {};
|
||||
|
||||
// store
|
||||
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
||||
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||
|
||||
// fetching project details
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_DETAILS_${projectId}` : null,
|
||||
workspaceSlug && projectId ? () => projectStore.fetchProjectDetails(workspaceSlug, projectId) : null
|
||||
@ -84,14 +80,12 @@ const ProjectCyclesPage: NextPage = observer(() => {
|
||||
|
||||
return (
|
||||
<AppLayout header={<CyclesHeader name={projectDetails?.name} />} withProjectWrapper>
|
||||
<CycleCreateEditModal
|
||||
<CycleCreateUpdateModal
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
modal={createModal}
|
||||
modalClose={() => setCreateModal(false)}
|
||||
onSubmit={createOnSubmit}
|
||||
isOpen={createModal}
|
||||
handleClose={() => setCreateModal(false)}
|
||||
/>
|
||||
|
||||
{projectDetails?.total_cycles === 0 ? (
|
||||
<div className="h-full grid place-items-center">
|
||||
<EmptyState
|
||||
|
@ -211,12 +211,14 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
createCycle = async (workspaceSlug: string, projectId: string, data: any) => {
|
||||
try {
|
||||
console.log("Cycle Creating");
|
||||
const response = await this.cycleService.createCycle(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
data,
|
||||
this.rootStore.user.currentUser
|
||||
);
|
||||
console.log("Cycle created");
|
||||
|
||||
runInAction(() => {
|
||||
this.cycle_details = {
|
||||
|
Loading…
Reference in New Issue
Block a user