From c4fff45429524c8bf4799bfa73b95c0224685a4f Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Thu, 2 Feb 2023 13:29:17 +0530 Subject: [PATCH 01/40] feat: manual ordering for issues in kanban --- apiserver/plane/api/serializers/issue.py | 12 +----------- apiserver/plane/db/models/issue.py | 6 ++---- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/apiserver/plane/api/serializers/issue.py b/apiserver/plane/api/serializers/issue.py index a148cbfb5..3add8f965 100644 --- a/apiserver/plane/api/serializers/issue.py +++ b/apiserver/plane/api/serializers/issue.py @@ -40,12 +40,12 @@ class IssueFlatSerializer(BaseSerializer): "start_date", "target_date", "sequence_id", + "sort_order", ] # Issue Serializer with state details class IssueStateSerializer(BaseSerializer): - state_detail = StateSerializer(read_only=True, source="state") project_detail = ProjectSerializer(read_only=True, source="project") @@ -57,7 +57,6 @@ class IssueStateSerializer(BaseSerializer): ##TODO: Find a better way to write this serializer ## Find a better approach to save manytomany? class IssueCreateSerializer(BaseSerializer): - state_detail = StateSerializer(read_only=True, source="state") created_by_detail = UserLiteSerializer(read_only=True, source="created_by") project_detail = ProjectSerializer(read_only=True, source="project") @@ -176,7 +175,6 @@ class IssueCreateSerializer(BaseSerializer): return issue def update(self, instance, validated_data): - blockers = validated_data.pop("blockers_list", None) assignees = validated_data.pop("assignees_list", None) labels = validated_data.pop("labels_list", None) @@ -254,7 +252,6 @@ class IssueCreateSerializer(BaseSerializer): class IssueActivitySerializer(BaseSerializer): - actor_detail = UserLiteSerializer(read_only=True, source="actor") class Meta: @@ -263,7 +260,6 @@ class IssueActivitySerializer(BaseSerializer): class IssueCommentSerializer(BaseSerializer): - actor_detail = UserLiteSerializer(read_only=True, source="actor") issue_detail = IssueFlatSerializer(read_only=True, source="issue") project_detail = ProjectSerializer(read_only=True, source="project") @@ -319,7 +315,6 @@ class LabelSerializer(BaseSerializer): class IssueLabelSerializer(BaseSerializer): - # label_details = LabelSerializer(read_only=True, source="label") class Meta: @@ -332,7 +327,6 @@ class IssueLabelSerializer(BaseSerializer): class BlockedIssueSerializer(BaseSerializer): - blocked_issue_detail = IssueFlatSerializer(source="block", read_only=True) class Meta: @@ -341,7 +335,6 @@ class BlockedIssueSerializer(BaseSerializer): class BlockerIssueSerializer(BaseSerializer): - blocker_issue_detail = IssueFlatSerializer(source="blocked_by", read_only=True) class Meta: @@ -350,7 +343,6 @@ class BlockerIssueSerializer(BaseSerializer): class IssueAssigneeSerializer(BaseSerializer): - assignee_details = UserLiteSerializer(read_only=True, source="assignee") class Meta: @@ -373,7 +365,6 @@ class CycleBaseSerializer(BaseSerializer): class IssueCycleDetailSerializer(BaseSerializer): - cycle_detail = CycleBaseSerializer(read_only=True, source="cycle") class Meta: @@ -404,7 +395,6 @@ class ModuleBaseSerializer(BaseSerializer): class IssueModuleDetailSerializer(BaseSerializer): - module_detail = ModuleBaseSerializer(read_only=True, source="module") class Meta: diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index c3984b3d2..be9612acf 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -9,6 +9,7 @@ from django.dispatch import receiver from . import ProjectBaseModel from plane.utils.html_processor import strip_tags + # TODO: Handle identifiers for Bulk Inserts - nk class Issue(ProjectBaseModel): PRIORITY_CHOICES = ( @@ -56,6 +57,7 @@ class Issue(ProjectBaseModel): labels = models.ManyToManyField( "db.Label", blank=True, related_name="labels", through="IssueLabel" ) + sort_order = models.FloatField(default=65535) class Meta: verbose_name = "Issue" @@ -246,7 +248,6 @@ class IssueProperty(ProjectBaseModel): class Label(ProjectBaseModel): - parent = models.ForeignKey( "self", on_delete=models.CASCADE, @@ -269,7 +270,6 @@ class Label(ProjectBaseModel): class IssueLabel(ProjectBaseModel): - issue = models.ForeignKey( "db.Issue", on_delete=models.CASCADE, related_name="label_issue" ) @@ -288,7 +288,6 @@ class IssueLabel(ProjectBaseModel): class IssueSequence(ProjectBaseModel): - issue = models.ForeignKey( Issue, on_delete=models.SET_NULL, related_name="issue_sequence", null=True ) @@ -305,7 +304,6 @@ class IssueSequence(ProjectBaseModel): # TODO: Find a better method to save the model @receiver(post_save, sender=Issue) def create_issue_sequence(sender, instance, created, **kwargs): - if created: IssueSequence.objects.create( issue=instance, sequence=instance.sequence_id, project=instance.project From 8b1bf53831b58c7b880ee87b2275d27b2aca248a Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Thu, 2 Feb 2023 15:00:35 +0530 Subject: [PATCH 02/40] refactor: issues folder structure --- .../common/list-view/single-issue.tsx | 10 +- .../index.tsx => issues/activity.tsx} | 9 +- .../BoardView => issues/board-view}/index.tsx | 7 +- .../board-view}/single-board.tsx | 0 .../comment/add-comment.tsx} | 5 +- .../comment/comment-card.tsx} | 4 +- apps/app/components/issues/comment/index.ts | 2 + .../delete-issue-modal.tsx} | 6 +- apps/app/components/issues/form.tsx | 2 +- apps/app/components/issues/index.ts | 12 ++- .../index.tsx => issues/list-view.tsx} | 4 +- apps/app/components/issues/modal.tsx | 2 +- ...{list-item.tsx => my-issues-list-item.tsx} | 5 +- .../parent-issues-list-modal.tsx} | 4 +- apps/app/components/issues/select/index.ts | 2 +- .../select/{parent-issue.tsx => parent.tsx} | 4 +- .../sidebar-select/assignee.tsx} | 4 +- .../sidebar-select/blocked.tsx} | 11 +- .../sidebar-select/blocker.tsx} | 9 +- .../sidebar-select/cycle.tsx} | 8 +- .../components/issues/sidebar-select/index.ts | 8 ++ .../sidebar-select/module.tsx} | 4 +- .../sidebar-select/parent.tsx} | 8 +- .../sidebar-select/priority.tsx} | 4 +- .../sidebar-select/state.tsx} | 4 +- .../index.tsx => issues/sidebar.tsx} | 53 +++++---- .../sub-issues-list-modal.tsx} | 10 +- ...sub-issue-list.tsx => sub-issues-list.tsx} | 19 ++-- .../cycles/cycle-detail-sidebar/index.tsx | 20 ++-- .../my-issues/change-state-dropdown.tsx | 101 ------------------ .../modules/module-detail-sidebar/index.tsx | 54 +++++----- .../project/modules/module-link-modal.tsx | 27 ++--- .../create-update-state-inline.tsx | 0 .../create-update-state-modal.tsx | 27 +++-- .../delete-state-modal.tsx} | 4 +- apps/app/components/states/index.ts | 3 + apps/app/constants/fetch-keys.ts | 4 +- .../pages/[workspaceSlug]/me/my-issues.tsx | 8 +- .../projects/[projectId]/cycles/[cycleId].tsx | 22 +++- .../projects/[projectId]/issues/[issueId].tsx | 32 +++--- .../projects/[projectId]/issues/index.tsx | 10 +- .../[projectId]/modules/[moduleId].tsx | 21 ++-- .../projects/[projectId]/settings/states.tsx | 8 +- apps/app/services/cycles.service.ts | 12 +++ 44 files changed, 249 insertions(+), 324 deletions(-) rename apps/app/components/{project/issues/issue-detail/activity/index.tsx => issues/activity.tsx} (97%) rename apps/app/components/{project/issues/BoardView => issues/board-view}/index.tsx (97%) rename apps/app/components/{project/issues/BoardView => issues/board-view}/single-board.tsx (100%) rename apps/app/components/{project/issues/issue-detail/comment/issue-comment-section.tsx => issues/comment/add-comment.tsx} (97%) rename apps/app/components/{project/issues/issue-detail/comment/issue-comment-card.tsx => issues/comment/comment-card.tsx} (97%) create mode 100644 apps/app/components/issues/comment/index.ts rename apps/app/components/{project/issues/confirm-issue-deletion.tsx => issues/delete-issue-modal.tsx} (97%) rename apps/app/components/{project/issues/list-view/index.tsx => issues/list-view.tsx} (98%) rename apps/app/components/issues/{list-item.tsx => my-issues-list-item.tsx} (96%) rename apps/app/components/{project/issues/issues-list-modal.tsx => issues/parent-issues-list-modal.tsx} (99%) rename apps/app/components/issues/select/{parent-issue.tsx => parent.tsx} (86%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-assignee.tsx => issues/sidebar-select/assignee.tsx} (98%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-blocked.tsx => issues/sidebar-select/blocked.tsx} (98%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx => issues/sidebar-select/blocker.tsx} (98%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx => issues/sidebar-select/cycle.tsx} (96%) create mode 100644 apps/app/components/issues/sidebar-select/index.ts rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-module.tsx => issues/sidebar-select/module.tsx} (95%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx => issues/sidebar-select/parent.tsx} (94%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-priority.tsx => issues/sidebar-select/priority.tsx} (94%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/select-state.tsx => issues/sidebar-select/state.tsx} (96%) rename apps/app/components/{project/issues/issue-detail/issue-detail-sidebar/index.tsx => issues/sidebar.tsx} (92%) rename apps/app/components/{project/issues/issue-detail/add-as-sub-issue.tsx => issues/sub-issues-list-modal.tsx} (96%) rename apps/app/components/issues/{sub-issue-list.tsx => sub-issues-list.tsx} (90%) delete mode 100644 apps/app/components/project/issues/my-issues/change-state-dropdown.tsx rename apps/app/components/{project/issues/BoardView/state => states}/create-update-state-inline.tsx (100%) rename apps/app/components/{project/issues/BoardView/state => states}/create-update-state-modal.tsx (97%) rename apps/app/components/{project/issues/BoardView/state/confirm-state-delete.tsx => states/delete-state-modal.tsx} (98%) create mode 100644 apps/app/components/states/index.ts diff --git a/apps/app/components/common/list-view/single-issue.tsx b/apps/app/components/common/list-view/single-issue.tsx index 262f332b5..68c71ca1a 100644 --- a/apps/app/components/common/list-view/single-issue.tsx +++ b/apps/app/components/common/list-view/single-issue.tsx @@ -5,16 +5,16 @@ import { useRouter } from "next/router"; import useSWR, { mutate } from "swr"; +// headless ui +import { Listbox, Transition } from "@headlessui/react"; // services import issuesService from "services/issues.service"; import workspaceService from "services/workspace.service"; import stateService from "services/state.service"; -// headless ui -import { Listbox, Transition } from "@headlessui/react"; +// components +import { DeleteIssueModal } from "components/issues"; // ui import { CustomMenu, CustomSelect, AssigneesList, Avatar, CustomDatePicker } from "components/ui"; -// components -import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion"; // helpers import { renderShortNumericDateFormat, findHowManyDaysLeft } from "helpers/date-time.helper"; import { addSpaceIfCamelCase } from "helpers/string.helper"; @@ -152,7 +152,7 @@ const SingleListIssue: React.FC = ({ return ( <> - setDeleteIssue(undefined)} isOpen={!!deleteIssue} data={deleteIssue} diff --git a/apps/app/components/project/issues/issue-detail/activity/index.tsx b/apps/app/components/issues/activity.tsx similarity index 97% rename from apps/app/components/project/issues/issue-detail/activity/index.tsx rename to apps/app/components/issues/activity.tsx index 3594bf7a8..351aff485 100644 --- a/apps/app/components/project/issues/issue-detail/activity/index.tsx +++ b/apps/app/components/issues/activity.tsx @@ -14,7 +14,7 @@ import { // services import issuesServices from "services/issues.service"; // components -import CommentCard from "components/project/issues/issue-detail/comment/issue-comment-card"; +import { CommentCard } from "components/issues/comment"; // ui import { Loader } from "components/ui"; // icons @@ -76,7 +76,7 @@ const activityDetails: { }, }; -const IssueActivitySection: React.FC<{ +export const IssueActivitySection: React.FC<{ issueActivities: IIssueActivity[]; mutate: KeyedMutator; }> = ({ issueActivities, mutate }) => { @@ -216,7 +216,7 @@ const IssueActivitySection: React.FC<{ ); - } else if ("comment_json" in activity) { + } else if ("comment_json" in activity) return ( ); - } })} ) : ( @@ -247,5 +246,3 @@ const IssueActivitySection: React.FC<{ ); }; - -export default IssueActivitySection; diff --git a/apps/app/components/project/issues/BoardView/index.tsx b/apps/app/components/issues/board-view/index.tsx similarity index 97% rename from apps/app/components/project/issues/BoardView/index.tsx rename to apps/app/components/issues/board-view/index.tsx index 6243e88dd..4487ec1c8 100644 --- a/apps/app/components/project/issues/BoardView/index.tsx +++ b/apps/app/components/issues/board-view/index.tsx @@ -14,10 +14,9 @@ import stateServices from "services/state.service"; import issuesServices from "services/issues.service"; import projectService from "services/project.service"; // components -import SingleBoard from "components/project/issues/BoardView/single-board"; +import SingleBoard from "components/issues/board-view/single-board"; import StrictModeDroppable from "components/dnd/StrictModeDroppable"; -import { CreateUpdateIssueModal } from "components/issues/modal"; -import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion"; +import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; // ui import { Spinner } from "components/ui"; // types @@ -185,7 +184,7 @@ const BoardView: React.FC = ({ issues, handleDeleteIssue, userAuth }) => return ( <> - setIsIssueDeletionOpen(false)} data={issueDeletionData} diff --git a/apps/app/components/project/issues/BoardView/single-board.tsx b/apps/app/components/issues/board-view/single-board.tsx similarity index 100% rename from apps/app/components/project/issues/BoardView/single-board.tsx rename to apps/app/components/issues/board-view/single-board.tsx diff --git a/apps/app/components/project/issues/issue-detail/comment/issue-comment-section.tsx b/apps/app/components/issues/comment/add-comment.tsx similarity index 97% rename from apps/app/components/project/issues/issue-detail/comment/issue-comment-section.tsx rename to apps/app/components/issues/comment/add-comment.tsx index 5ac7e061a..a904a6c4a 100644 --- a/apps/app/components/project/issues/issue-detail/comment/issue-comment-section.tsx +++ b/apps/app/components/issues/comment/add-comment.tsx @@ -28,7 +28,8 @@ const defaultValues: Partial = { comment_html: "", comment_json: "", }; -const AddIssueComment: React.FC<{ + +export const AddComment: React.FC<{ mutate: KeyedMutator; }> = ({ mutate }) => { const { @@ -111,5 +112,3 @@ const AddIssueComment: React.FC<{ ); }; - -export default AddIssueComment; diff --git a/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx b/apps/app/components/issues/comment/comment-card.tsx similarity index 97% rename from apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx rename to apps/app/components/issues/comment/comment-card.tsx index ec270ff25..79582df3f 100644 --- a/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx +++ b/apps/app/components/issues/comment/comment-card.tsx @@ -24,7 +24,7 @@ type Props = { handleCommentDeletion: (comment: string) => void; }; -const CommentCard: React.FC = ({ comment, onSubmit, handleCommentDeletion }) => { +export const CommentCard: React.FC = ({ comment, onSubmit, handleCommentDeletion }) => { const { user } = useUser(); const [isEditing, setIsEditing] = useState(false); @@ -130,5 +130,3 @@ const CommentCard: React.FC = ({ comment, onSubmit, handleCommentDeletion ); }; - -export default CommentCard; diff --git a/apps/app/components/issues/comment/index.ts b/apps/app/components/issues/comment/index.ts new file mode 100644 index 000000000..cf13ca91e --- /dev/null +++ b/apps/app/components/issues/comment/index.ts @@ -0,0 +1,2 @@ +export * from "./add-comment"; +export * from "./comment-card"; diff --git a/apps/app/components/project/issues/confirm-issue-deletion.tsx b/apps/app/components/issues/delete-issue-modal.tsx similarity index 97% rename from apps/app/components/project/issues/confirm-issue-deletion.tsx rename to apps/app/components/issues/delete-issue-modal.tsx index 12b8c63e9..c64e4965b 100644 --- a/apps/app/components/project/issues/confirm-issue-deletion.tsx +++ b/apps/app/components/issues/delete-issue-modal.tsx @@ -25,7 +25,7 @@ type Props = { data?: IIssue; }; -const ConfirmIssueDeletion: React.FC = ({ isOpen, handleClose, data }) => { +export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data }) => { const cancelButtonRef = useRef(null); const [isDeleteLoading, setIsDeleteLoading] = useState(false); @@ -43,8 +43,6 @@ const ConfirmIssueDeletion: React.FC = ({ isOpen, handleClose, data }) => handleClose(); }; - console.log(data); - const handleDeletion = async () => { setIsDeleteLoading(true); if (!data || !workspaceSlug) return; @@ -173,5 +171,3 @@ const ConfirmIssueDeletion: React.FC = ({ isOpen, handleClose, data }) => ); }; - -export default ConfirmIssueDeletion; diff --git a/apps/app/components/issues/form.tsx b/apps/app/components/issues/form.tsx index a2233fc52..5e034822a 100644 --- a/apps/app/components/issues/form.tsx +++ b/apps/app/components/issues/form.tsx @@ -16,7 +16,7 @@ import { IssueStateSelect, } from "components/issues/select"; import { CycleSelect as IssueCycleSelect } from "components/cycles/select"; -import CreateUpdateStateModal from "components/project/issues/BoardView/state/create-update-state-modal"; +import { CreateUpdateStateModal } from "components/states"; import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal"; // ui import { Button, CustomDatePicker, CustomMenu, Input, Loader } from "components/ui"; diff --git a/apps/app/components/issues/index.ts b/apps/app/components/issues/index.ts index 5608866d4..ba8b85301 100644 --- a/apps/app/components/issues/index.ts +++ b/apps/app/components/issues/index.ts @@ -1,5 +1,13 @@ -export * from "./list-item"; +export * from "./board-view"; +export * from "./comment"; +export * from "./activity"; +export * from "./delete-issue-modal"; export * from "./description-form"; -export * from "./sub-issue-list"; export * from "./form"; +export * from "./list-view"; export * from "./modal"; +export * from "./my-issues-list-item"; +export * from "./parent-issues-list-modal"; +export * from "./sidebar"; +export * from "./sub-issues-list"; +export * from "./sub-issues-list-modal"; diff --git a/apps/app/components/project/issues/list-view/index.tsx b/apps/app/components/issues/list-view.tsx similarity index 98% rename from apps/app/components/project/issues/list-view/index.tsx rename to apps/app/components/issues/list-view.tsx index 102295f84..eb5c00527 100644 --- a/apps/app/components/project/issues/list-view/index.tsx +++ b/apps/app/components/issues/list-view.tsx @@ -31,7 +31,7 @@ type Props = { userAuth: UserAuth; }; -const ListView: React.FC = ({ issues, handleEditIssue, userAuth }) => { +export const IssuesListView: React.FC = ({ issues, handleEditIssue, userAuth }) => { const [isCreateIssuesModalOpen, setIsCreateIssuesModalOpen] = useState(false); const [preloadedData, setPreloadedData] = useState< (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined @@ -180,5 +180,3 @@ const ListView: React.FC = ({ issues, handleEditIssue, userAuth }) => { ); }; - -export default ListView; diff --git a/apps/app/components/issues/modal.tsx b/apps/app/components/issues/modal.tsx index 3f7555435..2bb588460 100644 --- a/apps/app/components/issues/modal.tsx +++ b/apps/app/components/issues/modal.tsx @@ -16,7 +16,7 @@ import issuesService from "services/issues.service"; import useUser from "hooks/use-user"; import useToast from "hooks/use-toast"; // components -import CreateUpdateStateModal from "components/project/issues/BoardView/state/create-update-state-modal"; +import { CreateUpdateStateModal } from "components/states"; import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal"; import { IssueForm } from "components/issues"; // common diff --git a/apps/app/components/issues/list-item.tsx b/apps/app/components/issues/my-issues-list-item.tsx similarity index 96% rename from apps/app/components/issues/list-item.tsx rename to apps/app/components/issues/my-issues-list-item.tsx index 603d8d299..2075c5161 100644 --- a/apps/app/components/issues/list-item.tsx +++ b/apps/app/components/issues/my-issues-list-item.tsx @@ -24,10 +24,7 @@ type Props = { removeIssue?: () => void; }; -export const IssueListItem: React.FC = (props) => { - // const { type, issue, properties, editIssue, handleDeleteIssue, removeIssue } = props; - const { issue, properties } = props; - // router +export const MyIssuesListItem: React.FC = ({ issue, properties }) => { const router = useRouter(); const { workspaceSlug } = router.query; diff --git a/apps/app/components/project/issues/issues-list-modal.tsx b/apps/app/components/issues/parent-issues-list-modal.tsx similarity index 99% rename from apps/app/components/project/issues/issues-list-modal.tsx rename to apps/app/components/issues/parent-issues-list-modal.tsx index 9c56d6406..b805e7b14 100644 --- a/apps/app/components/project/issues/issues-list-modal.tsx +++ b/apps/app/components/issues/parent-issues-list-modal.tsx @@ -21,7 +21,7 @@ type Props = { customDisplay?: JSX.Element; }; -const IssuesListModal: React.FC = ({ +export const ParentIssuesListModal: React.FC = ({ isOpen, handleClose: onClose, value, @@ -227,5 +227,3 @@ const IssuesListModal: React.FC = ({ ); }; - -export default IssuesListModal; diff --git a/apps/app/components/issues/select/index.ts b/apps/app/components/issues/select/index.ts index de43d9b0e..4338b3162 100644 --- a/apps/app/components/issues/select/index.ts +++ b/apps/app/components/issues/select/index.ts @@ -1,6 +1,6 @@ export * from "./assignee"; export * from "./label"; -export * from "./parent-issue"; +export * from "./parent"; export * from "./priority"; export * from "./project"; export * from "./state"; diff --git a/apps/app/components/issues/select/parent-issue.tsx b/apps/app/components/issues/select/parent.tsx similarity index 86% rename from apps/app/components/issues/select/parent-issue.tsx rename to apps/app/components/issues/select/parent.tsx index d08020d20..c04e89b92 100644 --- a/apps/app/components/issues/select/parent-issue.tsx +++ b/apps/app/components/issues/select/parent.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Controller, Control } from "react-hook-form"; // components -import IssuesListModal from "components/project/issues/issues-list-modal"; +import { ParentIssuesListModal } from "components/issues"; // types import type { IIssue } from "types"; @@ -17,7 +17,7 @@ export const IssueParentSelect: React.FC = ({ control, isOpen, setIsOpen, control={control} name="parent" render={({ field: { onChange } }) => ( - setIsOpen(false)} onChange={onChange} diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-assignee.tsx b/apps/app/components/issues/sidebar-select/assignee.tsx similarity index 98% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-assignee.tsx rename to apps/app/components/issues/sidebar-select/assignee.tsx index ceefa5e7a..369d03368 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-assignee.tsx +++ b/apps/app/components/issues/sidebar-select/assignee.tsx @@ -27,7 +27,7 @@ type Props = { userAuth: UserAuth; }; -const SelectAssignee: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarAssigneeSelect: React.FC = ({ control, submitChanges, userAuth }) => { const router = useRouter(); const { workspaceSlug } = router.query; @@ -143,5 +143,3 @@ const SelectAssignee: React.FC = ({ control, submitChanges, userAuth }) = ); }; - -export default SelectAssignee; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocked.tsx b/apps/app/components/issues/sidebar-select/blocked.tsx similarity index 98% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocked.tsx rename to apps/app/components/issues/sidebar-select/blocked.tsx index 0e8ec0881..a6024a1a4 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocked.tsx +++ b/apps/app/components/issues/sidebar-select/blocked.tsx @@ -16,7 +16,7 @@ import issuesService from "services/issues.service"; // ui import { Button } from "components/ui"; // icons -import { FolderIcon, MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; +import { MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { BlockedIcon, LayerDiagonalIcon } from "components/icons"; // types import { IIssue, UserAuth } from "types"; @@ -34,7 +34,12 @@ type Props = { userAuth: UserAuth; }; -const SelectBlocked: React.FC = ({ submitChanges, issuesList, watch, userAuth }) => { +export const SidebarBlockedSelect: React.FC = ({ + submitChanges, + issuesList, + watch, + userAuth, +}) => { const [query, setQuery] = useState(""); const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false); @@ -301,5 +306,3 @@ const SelectBlocked: React.FC = ({ submitChanges, issuesList, watch, user ); }; - -export default SelectBlocked; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx b/apps/app/components/issues/sidebar-select/blocker.tsx similarity index 98% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx rename to apps/app/components/issues/sidebar-select/blocker.tsx index 433f5c9fe..789c11d1c 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx +++ b/apps/app/components/issues/sidebar-select/blocker.tsx @@ -34,7 +34,12 @@ type Props = { userAuth: UserAuth; }; -const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch, userAuth }) => { +export const SidebarBlockerSelect: React.FC = ({ + submitChanges, + issuesList, + watch, + userAuth, +}) => { const [query, setQuery] = useState(""); const [isBlockerModalOpen, setIsBlockerModalOpen] = useState(false); @@ -299,5 +304,3 @@ const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch, user ); }; - -export default SelectBlocker; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx b/apps/app/components/issues/sidebar-select/cycle.tsx similarity index 96% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx rename to apps/app/components/issues/sidebar-select/cycle.tsx index 159f96c68..0c92a575f 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx +++ b/apps/app/components/issues/sidebar-select/cycle.tsx @@ -22,7 +22,11 @@ type Props = { userAuth: UserAuth; }; -const SelectCycle: React.FC = ({ issueDetail, handleCycleChange, userAuth }) => { +export const SidebarCycleSelect: React.FC = ({ + issueDetail, + handleCycleChange, + userAuth, +}) => { const router = useRouter(); const { workspaceSlug, projectId, issueId } = router.query; @@ -98,5 +102,3 @@ const SelectCycle: React.FC = ({ issueDetail, handleCycleChange, userAuth ); }; - -export default SelectCycle; diff --git a/apps/app/components/issues/sidebar-select/index.ts b/apps/app/components/issues/sidebar-select/index.ts new file mode 100644 index 000000000..9070d2d2e --- /dev/null +++ b/apps/app/components/issues/sidebar-select/index.ts @@ -0,0 +1,8 @@ +export * from "./assignee"; +export * from "./blocked"; +export * from "./blocker"; +export * from "./cycle"; +export * from "./module"; +export * from "./parent"; +export * from "./priority"; +export * from "./state"; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-module.tsx b/apps/app/components/issues/sidebar-select/module.tsx similarity index 95% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-module.tsx rename to apps/app/components/issues/sidebar-select/module.tsx index 1deac86e4..df0a3d050 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-module.tsx +++ b/apps/app/components/issues/sidebar-select/module.tsx @@ -21,7 +21,7 @@ type Props = { handleModuleChange: (module: IModule) => void; }; -const SelectModule: React.FC = ({ control, handleModuleChange }) => { +export const SidebarModuleSelect: React.FC = ({ control, handleModuleChange }) => { const router = useRouter(); const { workspaceSlug, projectId } = router.query; @@ -76,5 +76,3 @@ const SelectModule: React.FC = ({ control, handleModuleChange }) => { ); }; - -export default SelectModule; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx b/apps/app/components/issues/sidebar-select/parent.tsx similarity index 94% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx rename to apps/app/components/issues/sidebar-select/parent.tsx index 7cb298324..1af86c359 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx +++ b/apps/app/components/issues/sidebar-select/parent.tsx @@ -10,7 +10,7 @@ import { UserIcon } from "@heroicons/react/24/outline"; // services import issuesServices from "services/issues.service"; // components -import IssuesListModal from "components/project/issues/issues-list-modal"; +import { ParentIssuesListModal } from "components/issues"; // icons // types import { IIssue, UserAuth } from "types"; @@ -26,7 +26,7 @@ type Props = { userAuth: UserAuth; }; -const SelectParent: React.FC = ({ +export const SidebarParentSelect: React.FC = ({ control, submitChanges, issuesList, @@ -61,7 +61,7 @@ const SelectParent: React.FC = ({ control={control} name="parent" render={({ field: { value, onChange } }) => ( - setIsParentModalOpen(false)} onChange={(val) => { @@ -93,5 +93,3 @@ const SelectParent: React.FC = ({ ); }; - -export default SelectParent; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-priority.tsx b/apps/app/components/issues/sidebar-select/priority.tsx similarity index 94% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-priority.tsx rename to apps/app/components/issues/sidebar-select/priority.tsx index 8057b14ec..252400669 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-priority.tsx +++ b/apps/app/components/issues/sidebar-select/priority.tsx @@ -19,7 +19,7 @@ type Props = { userAuth: UserAuth; }; -const SelectPriority: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarPrioritySelect: React.FC = ({ control, submitChanges, userAuth }) => { const isNotAllowed = userAuth.isGuest || userAuth.isViewer; return ( @@ -65,5 +65,3 @@ const SelectPriority: React.FC = ({ control, submitChanges, userAuth }) = ); }; - -export default SelectPriority; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-state.tsx b/apps/app/components/issues/sidebar-select/state.tsx similarity index 96% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-state.tsx rename to apps/app/components/issues/sidebar-select/state.tsx index 8906de605..bbe57cc7a 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-state.tsx +++ b/apps/app/components/issues/sidebar-select/state.tsx @@ -22,7 +22,7 @@ type Props = { userAuth: UserAuth; }; -const SelectState: React.FC = ({ control, submitChanges, userAuth }) => { +export const SidebarStateSelect: React.FC = ({ control, submitChanges, userAuth }) => { const router = useRouter(); const { workspaceSlug, projectId } = router.query; @@ -100,5 +100,3 @@ const SelectState: React.FC = ({ control, submitChanges, userAuth }) => { ); }; - -export default SelectState; diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx b/apps/app/components/issues/sidebar.tsx similarity index 92% rename from apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx rename to apps/app/components/issues/sidebar.tsx index fb18d4ebd..0c358f9a4 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx +++ b/apps/app/components/issues/sidebar.tsx @@ -15,17 +15,18 @@ import useToast from "hooks/use-toast"; // services import issuesServices from "services/issues.service"; // components -import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion"; -import SelectState from "components/project/issues/issue-detail/issue-detail-sidebar/select-state"; -import SelectPriority from "components/project/issues/issue-detail/issue-detail-sidebar/select-priority"; -import SelectParent from "components/project/issues/issue-detail/issue-detail-sidebar/select-parent"; -import SelectCycle from "components/project/issues/issue-detail/issue-detail-sidebar/select-cycle"; -import SelectAssignee from "components/project/issues/issue-detail/issue-detail-sidebar/select-assignee"; -import SelectBlocker from "components/project/issues/issue-detail/issue-detail-sidebar/select-blocker"; -import SelectBlocked from "components/project/issues/issue-detail/issue-detail-sidebar/select-blocked"; +import { + SidebarAssigneeSelect, + SidebarBlockedSelect, + SidebarBlockerSelect, + SidebarCycleSelect, + SidebarParentSelect, + SidebarPrioritySelect, + SidebarStateSelect, +} from "components/issues/sidebar-select"; +import { DeleteIssueModal } from "components/issues"; // ui import { Input, Button, Spinner, CustomDatePicker } from "components/ui"; -import DatePicker from "react-datepicker"; // icons import { TagIcon, @@ -43,8 +44,6 @@ import type { ICycle, IIssue, IIssueLabels, UserAuth } from "types"; // fetch-keys import { PROJECT_ISSUE_LABELS, PROJECT_ISSUES_LIST, ISSUE_DETAILS } from "constants/fetch-keys"; -import "react-datepicker/dist/react-datepicker.css"; - type Props = { control: Control; submitChanges: (formData: Partial) => void; @@ -58,7 +57,7 @@ const defaultValues: Partial = { colour: "#ff0000", }; -const IssueDetailSidebar: React.FC = ({ +export const IssueDetailsSidebar: React.FC = ({ control, submitChanges, issueDetail, @@ -128,7 +127,7 @@ const IssueDetailSidebar: React.FC = ({ return ( <> - setDeleteIssueModal(false)} isOpen={deleteIssueModal} data={issueDetail} @@ -175,12 +174,24 @@ const IssueDetailSidebar: React.FC = ({
- - - + + +
- = ({ watch={watchIssue} userAuth={userAuth} /> - i.id !== issueDetail?.id) ?? []} watch={watchIssue} userAuth={userAuth} /> - i.id !== issueDetail?.id) ?? []} watch={watchIssue} @@ -247,7 +258,7 @@ const IssueDetailSidebar: React.FC = ({
- = ({ ); }; - -export default IssueDetailSidebar; diff --git a/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx b/apps/app/components/issues/sub-issues-list-modal.tsx similarity index 96% rename from apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx rename to apps/app/components/issues/sub-issues-list-modal.tsx index 95eae4555..ddf98e195 100644 --- a/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx +++ b/apps/app/components/issues/sub-issues-list-modal.tsx @@ -17,11 +17,11 @@ import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys"; type Props = { isOpen: boolean; - setIsOpen: React.Dispatch>; + handleClose: () => void; parent: IIssue | undefined; }; -const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parent }) => { +export const SubIssuesListModal: React.FC = ({ isOpen, handleClose, parent }) => { const [query, setQuery] = useState(""); const router = useRouter(); @@ -43,7 +43,7 @@ const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parent }) => { []; const handleCommandPaletteClose = () => { - setIsOpen(false); + handleClose(); setQuery(""); }; @@ -147,7 +147,7 @@ const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parent }) => { } onClick={() => { addAsSubIssue(issue.id); - setIsOpen(false); + handleClose(); }} > = ({ isOpen, setIsOpen, parent }) => { ); }; - -export default AddAsSubIssue; diff --git a/apps/app/components/issues/sub-issue-list.tsx b/apps/app/components/issues/sub-issues-list.tsx similarity index 90% rename from apps/app/components/issues/sub-issue-list.tsx rename to apps/app/components/issues/sub-issues-list.tsx index f8944f379..de85f1535 100644 --- a/apps/app/components/issues/sub-issue-list.tsx +++ b/apps/app/components/issues/sub-issues-list.tsx @@ -4,8 +4,7 @@ import { Disclosure, Transition } from "@headlessui/react"; import { ChevronRightIcon, PlusIcon } from "@heroicons/react/24/outline"; // components import { CustomMenu } from "components/ui"; -import { CreateUpdateIssueModal } from "components/issues"; -import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-issue"; +import { CreateUpdateIssueModal, SubIssuesListModal } from "components/issues"; // types import { IIssue, UserAuth } from "types"; @@ -18,7 +17,7 @@ export interface SubIssueListProps { userAuth: UserAuth; } -export const SubIssueList: FC = ({ +export const SubIssuesList: FC = ({ issues = [], handleSubIssueRemove, parentIssue, @@ -28,7 +27,7 @@ export const SubIssueList: FC = ({ }) => { // states const [isIssueModalActive, setIssueModalActive] = useState(false); - const [isSubIssueModalActive, setSubIssueModalActive] = useState(false); + const [subIssuesListModal, setSubIssuesListModal] = useState(false); const [preloadedData, setPreloadedData] = useState | null>(null); const openIssueModal = () => { @@ -40,11 +39,11 @@ export const SubIssueList: FC = ({ }; const openSubIssueModal = () => { - setSubIssueModalActive(true); + setSubIssuesListModal(true); }; const closeSubIssueModal = () => { - setSubIssueModalActive(false); + setSubIssuesListModal(false); }; const isNotAllowed = userAuth.isGuest || userAuth.isViewer; @@ -56,9 +55,9 @@ export const SubIssueList: FC = ({ prePopulateData={{ ...preloadedData }} handleClose={closeIssueModal} /> - setSubIssuesListModal(false)} parent={parentIssue} /> @@ -88,7 +87,7 @@ export const SubIssueList: FC = ({ { - setSubIssueModalActive(true); + setSubIssuesListModal(true); }} > Add an existing issue diff --git a/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx b/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx index 323b4f5f8..a98a2b433 100644 --- a/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx +++ b/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx @@ -15,7 +15,7 @@ import cyclesService from "services/cycles.service"; import useToast from "hooks/use-toast"; // ui import { Loader, CustomDatePicker } from "components/ui"; -//progress-bar +// progress-bar import { CircularProgressbar } from "react-circular-progressbar"; import "react-circular-progressbar/dist/styles.css"; // helpers @@ -24,7 +24,7 @@ import { groupBy } from "helpers/array.helper"; // types import { CycleIssueResponse, ICycle } from "types"; // fetch-keys -import { CYCLE_LIST } from "constants/fetch-keys"; +import { CYCLE_DETAILS } from "constants/fetch-keys"; type Props = { cycle: ICycle | undefined; @@ -57,23 +57,19 @@ const CycleDetailSidebar: React.FC = ({ cycle, isOpen, cycleIssues }) => }; const submitChanges = (data: Partial) => { - if (!workspaceSlug || !projectId || !module) return; + if (!workspaceSlug || !projectId || !cycleId) return; - mutate( - projectId && CYCLE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((tempCycle) => { - if (tempCycle.id === cycleId) return { ...tempCycle, ...data }; - return tempCycle; - }), + mutate( + CYCLE_DETAILS(cycleId as string), + (prevData) => ({ ...(prevData as ICycle), ...data }), false ); cyclesService - .patchCycle(workspaceSlug as string, projectId as string, cycle?.id ?? "", data) + .patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data) .then((res) => { console.log(res); - mutate(CYCLE_LIST(projectId as string)); + mutate(CYCLE_DETAILS(cycleId as string)); }) .catch((e) => { console.log(e); diff --git a/apps/app/components/project/issues/my-issues/change-state-dropdown.tsx b/apps/app/components/project/issues/my-issues/change-state-dropdown.tsx deleted file mode 100644 index 375632148..000000000 --- a/apps/app/components/project/issues/my-issues/change-state-dropdown.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import React from "react"; - -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// headless ui -import { Listbox, Transition } from "@headlessui/react"; -// services -import stateServices from "services/state.service"; -// helpers -import { addSpaceIfCamelCase } from "helpers/string.helper"; -// types -import { IIssue, IState } from "types"; -// fetch-keys -import { STATE_LIST } from "constants/fetch-keys"; - -type Props = { - issue: IIssue; - updateIssues: ( - workspaceSlug: string, - projectId: string, - issueId: string, - issue: Partial - ) => void; -}; - -const ChangeStateDropdown: React.FC = ({ issue, updateIssues }) => { - const router = useRouter(); - const { workspaceSlug } = router.query; - - const { data: states } = useSWR( - workspaceSlug ? STATE_LIST(issue.project) : null, - workspaceSlug ? () => stateServices.getStates(workspaceSlug as string, issue.project) : null - ); - - return ( - <> - { - if (!workspaceSlug) return; - updateIssues(workspaceSlug as string, issue.project, issue.id, { - state: data, - state_detail: states?.find((state) => state.id === data), - }); - }} - className="flex-shrink-0" - > - {({ open }) => ( - <> -
- - - {addSpaceIfCamelCase(issue.state_detail.name)} - - - - - - {states?.map((state) => ( - - `cursor-pointer select-none px-3 py-2 ${ - active ? "bg-indigo-50" : "bg-white" - }` - } - value={state.id} - > - {addSpaceIfCamelCase(state.name)} - - ))} - - -
- - )} -
- - ); -}; - -export default ChangeStateDropdown; diff --git a/apps/app/components/project/modules/module-detail-sidebar/index.tsx b/apps/app/components/project/modules/module-detail-sidebar/index.tsx index 74e7beb93..fa78f9a57 100644 --- a/apps/app/components/project/modules/module-detail-sidebar/index.tsx +++ b/apps/app/components/project/modules/module-detail-sidebar/index.tsx @@ -8,13 +8,6 @@ import { mutate } from "swr"; // react-hook-form import { Controller, useForm } from "react-hook-form"; // services -import { - CalendarDaysIcon, - ChartPieIcon, - LinkIcon, - PlusIcon, - TrashIcon, -} from "@heroicons/react/24/outline"; import modulesService from "services/modules.service"; // hooks import useToast from "hooks/use-toast"; @@ -23,12 +16,19 @@ import SelectLead from "components/project/modules/module-detail-sidebar/select- import SelectMembers from "components/project/modules/module-detail-sidebar/select-members"; import SelectStatus from "components/project/modules/module-detail-sidebar/select-status"; import ModuleLinkModal from "components/project/modules/module-link-modal"; -//progress-bar +// progress-bar import { CircularProgressbar } from "react-circular-progressbar"; import "react-circular-progressbar/dist/styles.css"; // ui import { CustomDatePicker, Loader } from "components/ui"; // icons +import { + CalendarDaysIcon, + ChartPieIcon, + LinkIcon, + PlusIcon, + TrashIcon, +} from "@heroicons/react/24/outline"; // helpers import { timeAgo } from "helpers/date-time.helper"; import { copyTextToClipboard } from "helpers/string.helper"; @@ -36,9 +36,10 @@ import { groupBy } from "helpers/array.helper"; // types import { IModule, ModuleIssueResponse } from "types"; // fetch-keys -import { MODULE_LIST } from "constants/fetch-keys"; +import { MODULE_DETAILS } from "constants/fetch-keys"; const defaultValues: Partial = { + lead: "", members_list: [], start_date: null, target_date: null, @@ -69,14 +70,6 @@ const ModuleDetailSidebar: React.FC = ({ defaultValues, }); - useEffect(() => { - if (module) - reset({ - ...module, - members_list: module.members_list ?? module.members_detail?.map((m) => m.id), - }); - }, [module, reset]); - const groupedIssues = { backlog: [], unstarted: [], @@ -87,29 +80,36 @@ const ModuleDetailSidebar: React.FC = ({ }; const submitChanges = (data: Partial) => { - if (!workspaceSlug || !projectId || !module) return; + if (!workspaceSlug || !projectId || !moduleId) return; - mutate( - projectId && MODULE_LIST(projectId as string), - (prevData) => - (prevData ?? []).map((module) => { - if (module.id === moduleId) return { ...module, ...data }; - return module; - }), + mutate( + MODULE_DETAILS(moduleId as string), + (prevData) => ({ + ...(prevData as IModule), + ...data, + }), false ); modulesService - .patchModule(workspaceSlug as string, projectId as string, module.id, data) + .patchModule(workspaceSlug as string, projectId as string, moduleId as string, data) .then((res) => { console.log(res); - mutate(MODULE_LIST(projectId as string)); + mutate(MODULE_DETAILS(moduleId as string)); }) .catch((e) => { console.log(e); }); }; + useEffect(() => { + if (module) + reset({ + ...module, + members_list: module.members_list ?? module.members_detail?.map((m) => m.id), + }); + }, [module, reset]); + return ( <> = ({ isOpen, module, handleClose }) => { }); const onSubmit = async (formData: ModuleLink) => { - if (!workspaceSlug || !projectId || !module) return; + if (!workspaceSlug || !projectId || !moduleId) return; - const previousLinks = module.link_module.map((l) => ({ title: l.title, url: l.url })); + const previousLinks = module?.link_module.map((l) => ({ title: l.title, url: l.url })); const payload: Partial = { - links_list: [...previousLinks, formData], + links_list: [...(previousLinks ?? []), formData], }; await modulesService - .patchModule(workspaceSlug as string, projectId as string, module.id, payload) - .then(() => { - mutate(projectId && MODULE_LIST(projectId as string), (prevData) => - (prevData ?? []).map((module) => { - if (module.id === moduleId) return { ...module, ...payload }; - return module; - }) - ); + .patchModule(workspaceSlug as string, projectId as string, moduleId as string, payload) + .then((res) => { + mutate(MODULE_DETAILS(moduleId as string)); onClose(); }) .catch((err) => { diff --git a/apps/app/components/project/issues/BoardView/state/create-update-state-inline.tsx b/apps/app/components/states/create-update-state-inline.tsx similarity index 100% rename from apps/app/components/project/issues/BoardView/state/create-update-state-inline.tsx rename to apps/app/components/states/create-update-state-inline.tsx diff --git a/apps/app/components/project/issues/BoardView/state/create-update-state-modal.tsx b/apps/app/components/states/create-update-state-modal.tsx similarity index 97% rename from apps/app/components/project/issues/BoardView/state/create-update-state-modal.tsx rename to apps/app/components/states/create-update-state-modal.tsx index f621a2ad9..16484d343 100644 --- a/apps/app/components/project/issues/BoardView/state/create-update-state-modal.tsx +++ b/apps/app/components/states/create-update-state-modal.tsx @@ -4,22 +4,24 @@ import { useRouter } from "next/router"; import { mutate } from "swr"; +// react-hook-form import { Controller, useForm } from "react-hook-form"; - +// react-color import { TwitterPicker } from "react-color"; - +// headless ui import { Dialog, Popover, Transition } from "@headlessui/react"; // services -import { ChevronDownIcon } from "@heroicons/react/24/outline"; -import type { IState } from "types"; import stateService from "services/state.service"; +// ui +import { Button, Input, Select, TextArea } from "components/ui"; +// icons +import { ChevronDownIcon } from "@heroicons/react/24/outline"; +// types +import type { IState } from "types"; // fetch keys import { STATE_LIST } from "constants/fetch-keys"; // constants import { GROUP_CHOICES } from "constants/"; -// ui -import { Button, Input, Select, TextArea } from "components/ui"; -// icons // types type Props = { @@ -36,7 +38,12 @@ const defaultValues: Partial = { group: "backlog", }; -const CreateUpdateStateModal: React.FC = ({ isOpen, data, projectId, handleClose }) => { +export const CreateUpdateStateModal: React.FC = ({ + isOpen, + data, + projectId, + handleClose, +}) => { const router = useRouter(); const { workspaceSlug } = router.query; @@ -194,7 +201,7 @@ const CreateUpdateStateModal: React.FC = ({ isOpen, data, projectId, hand style={{ backgroundColor: watch("color") ?? "green", }} - /> + /> )} = ({ isOpen, data, projectId, hand ); }; - -export default CreateUpdateStateModal; diff --git a/apps/app/components/project/issues/BoardView/state/confirm-state-delete.tsx b/apps/app/components/states/delete-state-modal.tsx similarity index 98% rename from apps/app/components/project/issues/BoardView/state/confirm-state-delete.tsx rename to apps/app/components/states/delete-state-modal.tsx index ecf3e7874..b517ddbf9 100644 --- a/apps/app/components/project/issues/BoardView/state/confirm-state-delete.tsx +++ b/apps/app/components/states/delete-state-modal.tsx @@ -28,7 +28,7 @@ type Props = { data: IState | null; }; -const ConfirmStateDeletion: React.FC = ({ isOpen, onClose, data }) => { +export const DeleteStateModal: React.FC = ({ isOpen, onClose, data }) => { const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [issuesWithThisStateExist, setIssuesWithThisStateExist] = useState(true); @@ -175,5 +175,3 @@ const ConfirmStateDeletion: React.FC = ({ isOpen, onClose, data }) => { ); }; - -export default ConfirmStateDeletion; diff --git a/apps/app/components/states/index.ts b/apps/app/components/states/index.ts new file mode 100644 index 000000000..63bb55a9c --- /dev/null +++ b/apps/app/components/states/index.ts @@ -0,0 +1,3 @@ +export * from "./create-update-state-inline"; +export * from "./create-update-state-modal"; +export * from "./delete-state-modal"; diff --git a/apps/app/constants/fetch-keys.ts b/apps/app/constants/fetch-keys.ts index 37466673e..77df1bc97 100644 --- a/apps/app/constants/fetch-keys.ts +++ b/apps/app/constants/fetch-keys.ts @@ -29,7 +29,7 @@ export const PROJECT_ISSUE_LABELS = (projectId: string) => `PROJECT_ISSUE_LABELS export const CYCLE_LIST = (projectId: string) => `CYCLE_LIST_${projectId}`; export const CYCLE_ISSUES = (cycleId: string) => `CYCLE_ISSUES_${cycleId}`; -export const CYCLE_DETAIL = "CYCLE_DETAIL"; +export const CYCLE_DETAILS = (cycleId: string) => `CYCLE_DETAIL_${cycleId}`; export const STATE_LIST = (projectId: string) => `STATE_LIST_${projectId}`; export const STATE_DETAIL = "STATE_DETAIL"; @@ -39,7 +39,7 @@ export const USER_PROJECT_VIEW = (projectId: string) => `USER_PROJECT_VIEW_${pro export const MODULE_LIST = (projectId: string) => `MODULE_LIST_${projectId}`; export const MODULE_ISSUES = (moduleId: string) => `MODULE_ISSUES_${moduleId}`; -export const MODULE_DETAIL = "MODULE_DETAIL"; +export const MODULE_DETAILS = (moduleId: string) => `MODULE_DETAIL_${moduleId}`; // Issues export const ISSUE_DETAILS = (issueId: string) => `ISSUE_DETAILS_${issueId}`; diff --git a/apps/app/pages/[workspaceSlug]/me/my-issues.tsx b/apps/app/pages/[workspaceSlug]/me/my-issues.tsx index ce6deebe6..943f4028f 100644 --- a/apps/app/pages/[workspaceSlug]/me/my-issues.tsx +++ b/apps/app/pages/[workspaceSlug]/me/my-issues.tsx @@ -17,7 +17,7 @@ import useIssuesProperties from "hooks/use-issue-properties"; // types import { IIssue, Properties } from "types"; // components -import { IssueListItem } from "components/issues"; +import { MyIssuesListItem } from "components/issues"; // helpers import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; // types @@ -142,7 +142,11 @@ const MyIssuesPage: NextPage = () => {
{myIssues.map((issue: IIssue) => ( - + ))}
diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx index d8851371f..f55f71b38 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx @@ -13,8 +13,7 @@ import { IssueViewContextProvider } from "contexts/issue-view.context"; // components import CyclesListView from "components/project/cycles/list-view"; import CyclesBoardView from "components/project/cycles/board-view"; -import { CreateUpdateIssueModal } from "components/issues"; -import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion"; +import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; import ExistingIssuesListModal from "components/common/existing-issues-list-modal"; import CycleDetailSidebar from "components/project/cycles/cycle-detail-sidebar"; import View from "components/core/view"; @@ -38,6 +37,7 @@ import { PROJECT_ISSUES_LIST, PROJECT_MEMBERS, PROJECT_DETAILS, + CYCLE_DETAILS, } from "constants/fetch-keys"; const SingleCycle: React.FC = (props) => { @@ -77,6 +77,18 @@ const SingleCycle: React.FC = (props) => { : null ); + const { data: cycleDetails } = useSWR( + cycleId ? CYCLE_DETAILS(cycleId as string) : null, + workspaceSlug && projectId && cycleId + ? () => + cycleServices.getCycleDetails( + workspaceSlug as string, + projectId as string, + cycleId as string + ) + : null + ); + const { data: cycleIssues } = useSWR( workspaceSlug && projectId && cycleId ? CYCLE_ISSUES(cycleId as string) : null, workspaceSlug && projectId && cycleId @@ -181,7 +193,7 @@ const SingleCycle: React.FC = (props) => { issues={issues?.results.filter((i) => !i.issue_cycle) ?? []} handleOnSubmit={handleAddIssuesToCycle} /> - setDeleteIssue(undefined)} isOpen={!!deleteIssue} data={issues?.results.find((issue) => issue.id === deleteIssue)} @@ -200,7 +212,7 @@ const SingleCycle: React.FC = (props) => { label={ <> - {cycles?.find((c) => c.id === cycleId)?.name} + {cycleDetails?.name} } className="ml-1.5" @@ -287,7 +299,7 @@ const SingleCycle: React.FC = (props) => {
)} c.id === (cycleId as string))} + cycle={cycleDetails} isOpen={cycleSidebar} cycleIssues={cycleIssues ?? []} /> diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx index b74aa14d0..12e3e4c93 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx @@ -14,11 +14,15 @@ import { requiredAdmin, requiredAuth } from "lib/auth"; // layouts import AppLayout from "layouts/app-layout"; // components -import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-issue"; -import IssueDetailSidebar from "components/project/issues/issue-detail/issue-detail-sidebar"; -import AddIssueComment from "components/project/issues/issue-detail/comment/issue-comment-section"; -import IssueActivitySection from "components/project/issues/issue-detail/activity"; -import { IssueDescriptionForm, SubIssueList, CreateUpdateIssueModal } from "components/issues"; +import { + IssueDescriptionForm, + SubIssuesList, + CreateUpdateIssueModal, + IssueDetailsSidebar, + IssueActivitySection, + AddComment, + SubIssuesListModal, +} from "components/issues"; // ui import { Loader, CustomMenu } from "components/ui"; import { Breadcrumbs } from "components/breadcrumbs"; @@ -52,7 +56,7 @@ const defaultValues = { const IssueDetailsPage: NextPage = (props) => { // states const [isOpen, setIsOpen] = useState(false); - const [isAddAsSubIssueOpen, setIsAddAsSubIssueOpen] = useState(false); + const [subIssuesListModal, setSubIssuesListModal] = useState(false); const [preloadedData, setPreloadedData] = useState< (Partial & { actionType: "createIssue" | "edit" | "delete" }) | undefined >(undefined); @@ -211,10 +215,10 @@ const IssueDetailsPage: NextPage = (props) => { }} /> )} - {isAddAsSubIssueOpen && ( - setSubIssuesListModal(false)} parent={issueDetails} /> )} @@ -276,7 +280,7 @@ const IssueDetailsPage: NextPage = (props) => { />
{issueId && workspaceSlug && projectId && subIssues?.length > 0 ? ( - = (props) => { { - setIsAddAsSubIssueOpen(true); + setSubIssuesListModal(true); setPreloadedData({ parent: issueDetails.id, actionType: "createIssue", @@ -329,11 +333,11 @@ const IssueDetailsPage: NextPage = (props) => { issueActivities={issueActivities || []} mutate={mutateIssueActivities} /> - +
- = (props) => { handleClose={() => setIsOpen(false)} data={selectedIssue} /> - setDeleteIssue(undefined)} isOpen={!!deleteIssue} data={projectIssues?.results.find((issue) => issue.id === deleteIssue)} @@ -110,7 +108,7 @@ const ProjectIssues: NextPage = (props) => {
) : projectIssues.count > 0 ? ( <> - p.parent === null) ?? []} handleEditIssue={handleEditIssue} userAuth={props} diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx index 0a679f58d..e6a2139ba 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/modules/[moduleId].tsx @@ -18,10 +18,9 @@ import { IssueViewContextProvider } from "contexts/issue-view.context"; import ExistingIssuesListModal from "components/common/existing-issues-list-modal"; import ModulesBoardView from "components/project/modules/board-view"; import ModulesListView from "components/project/modules/list-view"; -import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deletion"; import ModuleDetailSidebar from "components/project/modules/module-detail-sidebar"; import ConfirmModuleDeletion from "components/project/modules/confirm-module-deletion"; -import { CreateUpdateIssueModal } from "components/issues"; +import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues"; import View from "components/core/view"; // ui import { CustomMenu, EmptySpace, EmptySpaceItem, Spinner } from "components/ui"; @@ -46,7 +45,7 @@ import { import { NextPageContext } from "next"; // fetch-keys import { - MODULE_DETAIL, + MODULE_DETAILS, MODULE_ISSUES, MODULE_LIST, PROJECT_ISSUES_LIST, @@ -96,8 +95,8 @@ const SingleModule: React.FC = (props) => { : null ); - const { data: moduleDetail } = useSWR( - MODULE_DETAIL, + const { data: moduleDetails } = useSWR( + moduleId ? MODULE_DETAILS(moduleId as string) : null, workspaceSlug && projectId ? () => modulesService.getModuleDetails( @@ -181,9 +180,9 @@ const SingleModule: React.FC = (props) => { }; const handleDeleteModule = () => { - if (!moduleDetail) return; + if (!moduleDetails) return; - setSelectedModuleForDelete({ ...moduleDetail, actionType: "delete" }); + setSelectedModuleForDelete({ ...moduleDetails, actionType: "delete" }); setModuleDeleteModal(true); }; @@ -208,7 +207,7 @@ const SingleModule: React.FC = (props) => { issues={issues?.results.filter((i) => !i.issue_module) ?? []} handleOnSubmit={handleAddIssuesToModule} /> - setDeleteIssue(undefined)} isOpen={!!deleteIssue} data={moduleIssuesArray?.find((issue) => issue.id === deleteIssue)} @@ -226,7 +225,7 @@ const SingleModule: React.FC = (props) => { breadcrumbs={ @@ -236,7 +235,7 @@ const SingleModule: React.FC = (props) => { label={ <> - {modules?.find((c) => c.id === moduleId)?.name} + {moduleDetails?.name} } className="ml-1.5" @@ -323,7 +322,7 @@ const SingleModule: React.FC = (props) => { )} m.id === moduleId)} + module={moduleDetails} isOpen={moduleSidebar} moduleIssues={moduleIssues} handleDeleteModule={handleDeleteModule} diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx index 1234b7063..34549b0d5 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/states.tsx @@ -13,11 +13,7 @@ import { requiredAdmin } from "lib/auth"; // layouts import SettingsLayout from "layouts/settings-layout"; // components -import ConfirmStateDeletion from "components/project/issues/BoardView/state/confirm-state-delete"; -import { - CreateUpdateStateInline, - StateGroup, -} from "components/project/issues/BoardView/state/create-update-state-inline"; +import { CreateUpdateStateInline, DeleteStateModal, StateGroup } from "components/states"; // ui import { Loader } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; @@ -67,7 +63,7 @@ const StatesSettings: NextPage = (props) => { return ( <> - state.id === selectDeleteState) ?? null} onClose={() => setSelectDeleteState(null)} diff --git a/apps/app/services/cycles.service.ts b/apps/app/services/cycles.service.ts index 07f39d3a5..109b62108 100644 --- a/apps/app/services/cycles.service.ts +++ b/apps/app/services/cycles.service.ts @@ -26,6 +26,18 @@ class ProjectCycleServices extends APIService { }); } + async getCycleDetails( + workspaceSlug: string, + projectId: string, + cycleId: string + ): Promise { + return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`) + .then((res) => res?.data) + .catch((err) => { + throw err?.response?.data; + }); + } + async getCycleIssues(workspaceSlug: string, projectId: string, cycleId: string): Promise { return this.get( `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/` From b2eab805e98ef4ab2139be6933135a1c00702504 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Thu, 2 Feb 2023 18:04:13 +0530 Subject: [PATCH 03/40] refactor: modules and states folder structure --- apps/app/components/command-palette/index.tsx | 5 +- apps/app/components/issues/index.ts | 1 + apps/app/components/issues/modal.tsx | 18 +- apps/app/components/issues/sidebar.tsx | 4 +- .../modules/board-view/index.tsx | 2 +- .../modules/board-view/single-board.tsx | 0 .../delete-module-modal.tsx} | 4 +- apps/app/components/modules/form.tsx | 128 ++++++++ apps/app/components/modules/index.ts | 10 + .../index.tsx => modules/list-view.tsx} | 4 +- apps/app/components/modules/modal.tsx | 170 +++++++++++ .../modules/module-link-modal.tsx | 4 +- apps/app/components/modules/select/index.ts | 3 + .../select}/select-lead.tsx | 12 +- .../select}/select-members.tsx | 12 +- .../select}/select-status.tsx | 3 +- .../modules/sidebar-select/index.ts | 3 + .../sidebar-select}/select-lead.tsx | 4 +- .../sidebar-select}/select-members.tsx | 4 +- .../sidebar-select}/select-status.tsx | 4 +- .../index.tsx => modules/sidebar.tsx} | 24 +- .../modules/single-module-card.tsx | 13 +- .../create-update-module-modal/index.tsx | 273 ------------------ .../[projectId]/modules/[moduleId].tsx | 10 +- .../projects/[projectId]/modules/index.tsx | 2 +- 25 files changed, 371 insertions(+), 346 deletions(-) rename apps/app/components/{project => }/modules/board-view/index.tsx (98%) rename apps/app/components/{project => }/modules/board-view/single-board.tsx (100%) rename apps/app/components/{project/modules/confirm-module-deletion.tsx => modules/delete-module-modal.tsx} (97%) create mode 100644 apps/app/components/modules/form.tsx create mode 100644 apps/app/components/modules/index.ts rename apps/app/components/{project/modules/list-view/index.tsx => modules/list-view.tsx} (98%) create mode 100644 apps/app/components/modules/modal.tsx rename apps/app/components/{project => }/modules/module-link-modal.tsx (97%) create mode 100644 apps/app/components/modules/select/index.ts rename apps/app/components/{project/modules/create-update-module-modal => modules/select}/select-lead.tsx (91%) rename apps/app/components/{project/modules/create-update-module-modal => modules/select}/select-members.tsx (90%) rename apps/app/components/{project/modules/create-update-module-modal => modules/select}/select-status.tsx (93%) create mode 100644 apps/app/components/modules/sidebar-select/index.ts rename apps/app/components/{project/modules/module-detail-sidebar => modules/sidebar-select}/select-lead.tsx (98%) rename apps/app/components/{project/modules/module-detail-sidebar => modules/sidebar-select}/select-members.tsx (98%) rename apps/app/components/{project/modules/module-detail-sidebar => modules/sidebar-select}/select-status.tsx (94%) rename apps/app/components/{project/modules/module-detail-sidebar/index.tsx => modules/sidebar.tsx} (94%) rename apps/app/components/{project => }/modules/single-module-card.tsx (97%) delete mode 100644 apps/app/components/project/modules/create-update-module-modal/index.tsx diff --git a/apps/app/components/command-palette/index.tsx b/apps/app/components/command-palette/index.tsx index 441fb31fa..26dc252b2 100644 --- a/apps/app/components/command-palette/index.tsx +++ b/apps/app/components/command-palette/index.tsx @@ -20,9 +20,9 @@ import userService from "services/user.service"; // components import ShortcutsModal from "components/command-palette/shortcuts"; import { CreateProjectModal } from "components/project"; -import { CreateUpdateIssueModal } from "components/issues/modal"; +import { CreateUpdateIssueModal } from "components/issues"; +import { CreateUpdateModuleModal } from "components/modules"; import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal"; -import CreateUpdateModuleModal from "components/project/modules/create-update-module-modal"; import BulkDeleteIssuesModal from "components/common/bulk-delete-issues-modal"; // headless ui // helpers @@ -179,7 +179,6 @@ const CommandPalette: React.FC = () => { )} diff --git a/apps/app/components/issues/index.ts b/apps/app/components/issues/index.ts index ba8b85301..de602c2e1 100644 --- a/apps/app/components/issues/index.ts +++ b/apps/app/components/issues/index.ts @@ -1,5 +1,6 @@ export * from "./board-view"; export * from "./comment"; +export * from "./sidebar-select"; export * from "./activity"; export * from "./delete-issue-modal"; export * from "./description-form"; diff --git a/apps/app/components/issues/modal.tsx b/apps/app/components/issues/modal.tsx index 2bb588460..09ad6446b 100644 --- a/apps/app/components/issues/modal.tsx +++ b/apps/app/components/issues/modal.tsx @@ -16,8 +16,6 @@ import issuesService from "services/issues.service"; import useUser from "hooks/use-user"; import useToast from "hooks/use-toast"; // components -import { CreateUpdateStateModal } from "components/states"; -import CreateUpdateCycleModal from "components/project/cycles/create-update-cycle-modal"; import { IssueForm } from "components/issues"; // common import { renderDateFormat } from "helpers/date-time.helper"; @@ -206,15 +204,15 @@ export const CreateUpdateIssueModal: React.FC = ({ }; const handleFormSubmit = async (formData: Partial) => { - if (workspaceSlug && activeProject) { - const payload: Partial = { - ...formData, - target_date: formData.target_date ? renderDateFormat(formData.target_date ?? "") : null, - }; + if (!workspaceSlug || !activeProject) return; - if (!data) await createIssue(payload); - else await updateIssue(payload); - } + const payload: Partial = { + ...formData, + target_date: formData.target_date ? renderDateFormat(formData.target_date ?? "") : null, + }; + + if (!data) await createIssue(payload); + else await updateIssue(payload); }; return ( diff --git a/apps/app/components/issues/sidebar.tsx b/apps/app/components/issues/sidebar.tsx index 0c358f9a4..5868e884b 100644 --- a/apps/app/components/issues/sidebar.tsx +++ b/apps/app/components/issues/sidebar.tsx @@ -16,6 +16,7 @@ import useToast from "hooks/use-toast"; import issuesServices from "services/issues.service"; // components import { + DeleteIssueModal, SidebarAssigneeSelect, SidebarBlockedSelect, SidebarBlockerSelect, @@ -23,8 +24,7 @@ import { SidebarParentSelect, SidebarPrioritySelect, SidebarStateSelect, -} from "components/issues/sidebar-select"; -import { DeleteIssueModal } from "components/issues"; +} from "components/issues"; // ui import { Input, Button, Spinner, CustomDatePicker } from "components/ui"; // icons diff --git a/apps/app/components/project/modules/board-view/index.tsx b/apps/app/components/modules/board-view/index.tsx similarity index 98% rename from apps/app/components/project/modules/board-view/index.tsx rename to apps/app/components/modules/board-view/index.tsx index 4951f80af..95efa123a 100644 --- a/apps/app/components/project/modules/board-view/index.tsx +++ b/apps/app/components/modules/board-view/index.tsx @@ -13,7 +13,7 @@ import issuesService from "services/issues.service"; import useIssuesProperties from "hooks/use-issue-properties"; import useIssueView from "hooks/use-issue-view"; // components -import SingleBoard from "components/project/modules/board-view/single-board"; +import SingleBoard from "components/modules/board-view/single-board"; // ui import { Spinner } from "components/ui"; // types diff --git a/apps/app/components/project/modules/board-view/single-board.tsx b/apps/app/components/modules/board-view/single-board.tsx similarity index 100% rename from apps/app/components/project/modules/board-view/single-board.tsx rename to apps/app/components/modules/board-view/single-board.tsx diff --git a/apps/app/components/project/modules/confirm-module-deletion.tsx b/apps/app/components/modules/delete-module-modal.tsx similarity index 97% rename from apps/app/components/project/modules/confirm-module-deletion.tsx rename to apps/app/components/modules/delete-module-modal.tsx index df3f32fea..317f49a68 100644 --- a/apps/app/components/project/modules/confirm-module-deletion.tsx +++ b/apps/app/components/modules/delete-module-modal.tsx @@ -25,7 +25,7 @@ type Props = { data?: IModule; }; -const ConfirmModuleDeletion: React.FC = ({ isOpen, setIsOpen, data }) => { +export const DeleteModuleModal: React.FC = ({ isOpen, setIsOpen, data }) => { const [isDeleteLoading, setIsDeleteLoading] = useState(false); const router = useRouter(); @@ -152,5 +152,3 @@ const ConfirmModuleDeletion: React.FC = ({ isOpen, setIsOpen, data }) => ); }; - -export default ConfirmModuleDeletion; diff --git a/apps/app/components/modules/form.tsx b/apps/app/components/modules/form.tsx new file mode 100644 index 000000000..60fd93059 --- /dev/null +++ b/apps/app/components/modules/form.tsx @@ -0,0 +1,128 @@ +// react-hook-form +import { Controller, useForm } from "react-hook-form"; +// components +import { ModuleLeadSelect, ModuleMembersSelect, ModuleStatusSelect } from "components/modules"; +// ui +import { Button, CustomDatePicker, Input, TextArea } from "components/ui"; +// types +import { IModule } from "types"; + +type Props = { + handleFormSubmit: (values: Partial) => void; + handleClose: () => void; + status: boolean; +}; + +const defaultValues: Partial = { + name: "", + description: "", + status: null, + lead: null, + members_list: [], +}; + +export const ModuleForm: React.FC = ({ handleFormSubmit, handleClose, status }) => { + const { + register, + formState: { errors, isSubmitting }, + handleSubmit, + control, + reset, + } = useForm({ + defaultValues, + }); + + const handleCreateUpdateModule = async (formData: Partial) => { + await handleFormSubmit(formData); + + reset({ + ...defaultValues, + }); + }; + + return ( +
+
+

+ {status ? "Update" : "Create"} Module +

+
+
+ +
+
+